# HG changeset patch # User Keir Fraser # Date 1250693923 -3600 # Node ID 44d852862374dff2e734070ac60399f6875f6cd5 # Parent bea861fb0f20671d41e467557bfdffb67b42f5e7 x86_emulate: Remove cmpxchg retry loop from protmode_load_seg(). It is safer to retry in a loop via the caller. Signed-off-by: Keir Fraser xen-unstable changeset: 20031:34bdb5a29963 xen-unstable date: Thu Aug 06 09:54:22 2009 +0100 Index: xen-3.4.1-testing/xen/arch/x86/x86_emulate/x86_emulate.c =================================================================== --- xen-3.4.1-testing.orig/xen/arch/x86/x86_emulate/x86_emulate.c +++ xen-3.4.1-testing/xen/arch/x86/x86_emulate/x86_emulate.c @@ -996,79 +996,75 @@ protmode_load_seg( if ( ((sel & 0xfff8) + 7) > desctab.limit ) goto raise_exn; - do { - if ( (rc = read_ulong(x86_seg_none, desctab.base + (sel & 0xfff8), - &val, 4, ctxt, ops)) ) - return rc; - desc.a = val; - if ( (rc = read_ulong(x86_seg_none, desctab.base + (sel & 0xfff8) + 4, - &val, 4, ctxt, ops)) ) - return rc; - desc.b = val; + if ( (rc = read_ulong(x86_seg_none, desctab.base + (sel & 0xfff8), + &val, 4, ctxt, ops)) ) + return rc; + desc.a = val; + if ( (rc = read_ulong(x86_seg_none, desctab.base + (sel & 0xfff8) + 4, + &val, 4, ctxt, ops)) ) + return rc; + desc.b = val; - /* Segment present in memory? */ - if ( !(desc.b & (1u<<15)) ) - { - fault_type = EXC_NP; - goto raise_exn; - } + /* Segment present in memory? */ + if ( !(desc.b & (1u<<15)) ) + { + fault_type = EXC_NP; + goto raise_exn; + } - /* System segments must have the system flag (S) set. */ - if ( (desc.b & (1u<<12)) == (!is_x86_user_segment(seg) << 12) ) - goto raise_exn; + /* System segments must have the system flag (S) set. */ + if ( (desc.b & (1u<<12)) == (!is_x86_user_segment(seg) << 12) ) + goto raise_exn; - dpl = (desc.b >> 13) & 3; - rpl = sel & 3; - cpl = ss.attr.fields.dpl; - - switch ( seg ) - { - case x86_seg_cs: - /* Code segment? */ - if ( !(desc.b & (1u<<11)) ) - goto raise_exn; - /* Non-conforming segment: check DPL against RPL. */ - if ( ((desc.b & (6u<<9)) != (6u<<9)) && (dpl != rpl) ) - goto raise_exn; - break; - case x86_seg_ss: - /* Writable data segment? */ - if ( (desc.b & (5u<<9)) != (1u<<9) ) - goto raise_exn; - if ( (dpl != cpl) || (dpl != rpl) ) - goto raise_exn; - break; - case x86_seg_ldtr: - /* LDT system segment? */ - if ( (desc.b & (15u<<8)) != (2u<<8) ) - goto raise_exn; - goto skip_accessed_flag; - case x86_seg_tr: - /* Available TSS system segment? */ - if ( (desc.b & (15u<<8)) != (9u<<8) ) - goto raise_exn; - a_flag = 0x200; /* busy flag */ - break; - default: - /* Readable code or data segment? */ - if ( (desc.b & (5u<<9)) == (4u<<9) ) - goto raise_exn; - /* Non-conforming segment: check DPL against RPL and CPL. */ - if ( ((desc.b & (6u<<9)) != (6u<<9)) && - ((dpl < cpl) || (dpl < rpl)) ) - goto raise_exn; - break; - } + dpl = (desc.b >> 13) & 3; + rpl = sel & 3; + cpl = ss.attr.fields.dpl; - /* Ensure Accessed flag is set. */ - new_desc_b = desc.b | a_flag; - rc = ((desc.b & a_flag) ? X86EMUL_OKAY : - ops->cmpxchg( - x86_seg_none, desctab.base + (sel & 0xfff8) + 4, - &desc.b, &new_desc_b, 4, ctxt)); - } while ( rc == X86EMUL_CMPXCHG_FAILED ); + switch ( seg ) + { + case x86_seg_cs: + /* Code segment? */ + if ( !(desc.b & (1u<<11)) ) + goto raise_exn; + /* Non-conforming segment: check DPL against RPL. */ + if ( ((desc.b & (6u<<9)) != (6u<<9)) && (dpl != rpl) ) + goto raise_exn; + break; + case x86_seg_ss: + /* Writable data segment? */ + if ( (desc.b & (5u<<9)) != (1u<<9) ) + goto raise_exn; + if ( (dpl != cpl) || (dpl != rpl) ) + goto raise_exn; + break; + case x86_seg_ldtr: + /* LDT system segment? */ + if ( (desc.b & (15u<<8)) != (2u<<8) ) + goto raise_exn; + goto skip_accessed_flag; + case x86_seg_tr: + /* Available TSS system segment? */ + if ( (desc.b & (15u<<8)) != (9u<<8) ) + goto raise_exn; + a_flag = 0x200; /* busy flag */ + break; + default: + /* Readable code or data segment? */ + if ( (desc.b & (5u<<9)) == (4u<<9) ) + goto raise_exn; + /* Non-conforming segment: check DPL against RPL and CPL. */ + if ( ((desc.b & (6u<<9)) != (6u<<9)) && + ((dpl < cpl) || (dpl < rpl)) ) + goto raise_exn; + break; + } - if ( rc ) + /* Ensure Accessed flag is set. */ + new_desc_b = desc.b | a_flag; + if ( !(desc.b & a_flag) && + ((rc = ops->cmpxchg( + x86_seg_none, desctab.base + (sel & 0xfff8) + 4, + &desc.b, &new_desc_b, 4, ctxt)) != 0) ) return rc; /* Force the Accessed flag in our local copy. */