162 lines
5.6 KiB
Diff
162 lines
5.6 KiB
Diff
|
# HG changeset patch
|
||
|
# User Keir Fraser <keir.fraser@citrix.com>
|
||
|
# 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 <keir.fraser@citrix.com>
|
||
|
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. */
|