aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/x86_emulate
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-08-06 09:54:22 +0100
committerKeir Fraser <keir.fraser@citrix.com>2009-08-06 09:54:22 +0100
commit0297087090b22377d72318917a3ef947606a66d7 (patch)
tree00f1533fc6835ce1070cfafe7fb599b22ddfa44b /xen/arch/x86/x86_emulate
parent94df1707a3b54ff2f94923046c8f8cb166a6c4e4 (diff)
downloadxen-0297087090b22377d72318917a3ef947606a66d7.tar.gz
xen-0297087090b22377d72318917a3ef947606a66d7.tar.bz2
xen-0297087090b22377d72318917a3ef947606a66d7.zip
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 <keir.fraser@citrix.com>
Diffstat (limited to 'xen/arch/x86/x86_emulate')
-rw-r--r--xen/arch/x86/x86_emulate/x86_emulate.c132
1 files changed, 64 insertions, 68 deletions
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c
index d221f0076c..de14199b1f 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -1021,79 +1021,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;
+ 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;
- }
-
- /* 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. */