# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1213613667 -3600
# Node ID d1d066a0fc01c52c2fa5baaf4328ee4f72100348
# Parent b39b6ab402ee28b71d0b78e92f897f38e1583e89
x86_emulate: Fix the segment-load function
Fix the non-conforming type check and uses the consistent method to
fetch the cpl value as function get_cpl().
Also make sure vm86 mode is properly handled when determining whether
in real mode or protected mode -- in various respects vm86 mode can
act like both.
Signed-off-by: Dongxiao Xu <dongxiao.xu@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset: 17861:049a42108c65d9e56d18539454d49bc83f66eca2
xen-unstable date: Mon Jun 16 11:24:17 2008 +0100
---
xen/arch/x86/x86_emulate.c | 28 ++++++++++++++++++----------
1 files changed, 18 insertions(+), 10 deletions(-)
diff -r b39b6ab402ee -r d1d066a0fc01 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c Fri Jun 13 13:59:22 2008 +0100
+++ b/xen/arch/x86/x86_emulate.c Mon Jun 16 11:54:27 2008 +0100
@@ -817,6 +817,14 @@ in_realmode(
}
static int
+in_protmode(
+ struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops *ops)
+{
+ return !(in_realmode(ctxt, ops) || (ctxt->regs->eflags & EFLG_VM));
+}
+
+static int
realmode_load_seg(
enum x86_segment seg,
uint16_t sel,
@@ -842,7 +850,7 @@ protmode_load_seg(
struct x86_emulate_ctxt *ctxt,
struct x86_emulate_ops *ops)
{
- struct segment_register desctab, cs, segr;
+ struct segment_register desctab, ss, segr;
struct { uint32_t a, b; } desc;
unsigned long val;
uint8_t dpl, rpl, cpl;
@@ -861,7 +869,7 @@ protmode_load_seg(
if ( (seg == x86_seg_ldtr) && (sel & 4) )
goto raise_exn;
- if ( (rc = ops->read_segment(x86_seg_cs, &cs, ctxt)) ||
+ if ( (rc = ops->read_segment(x86_seg_ss, &ss, ctxt)) ||
(rc = ops->read_segment((sel & 4) ? x86_seg_ldtr : x86_seg_gdtr,
&desctab, ctxt)) )
return rc;
@@ -893,7 +901,7 @@ protmode_load_seg(
dpl = (desc.b >> 13) & 3;
rpl = sel & 3;
- cpl = cs.sel & 3;
+ cpl = ss.attr.fields.dpl;
switch ( seg )
{
@@ -902,7 +910,7 @@ protmode_load_seg(
if ( !(desc.b & (1u<<11)) )
goto raise_exn;
/* Non-conforming segment: check DPL against RPL. */
- if ( ((desc.b & (6u<<9)) != 6) && (dpl != rpl) )
+ if ( ((desc.b & (6u<<9)) != (6u<<9)) && (dpl != rpl) )
goto raise_exn;
break;
case x86_seg_ss:
@@ -922,7 +930,7 @@ protmode_load_seg(
if ( (desc.b & (5u<<9)) == (4u<<9) )
goto raise_exn;
/* Non-conforming segment: check DPL against RPL and CPL. */
- if ( ((desc.b & (6u<<9)) != 6) && ((dpl < cpl) || (dpl < rpl)) )
+ if ( ((desc.b & (6u<<9)) != (6u<<9)) && ((dpl < cpl) || (dpl <
rpl)) )
goto raise_exn;
break;
}
@@ -971,10 +979,10 @@ load_seg(
(ops->write_segment == NULL) )
return X86EMUL_UNHANDLEABLE;
- if ( in_realmode(ctxt, ops) )
- return realmode_load_seg(seg, sel, ctxt, ops);
-
- return protmode_load_seg(seg, sel, ctxt, ops);
+ if ( in_protmode(ctxt, ops) )
+ return protmode_load_seg(seg, sel, ctxt, ops);
+
+ return realmode_load_seg(seg, sel, ctxt, ops);
}
void *
@@ -1530,7 +1538,7 @@ x86_emulate(
dst.val = (dst.val & ~3) | (src_val & 3);
else
dst.type = OP_NONE;
- generate_exception_if(in_realmode(ctxt, ops), EXC_UD);
+ generate_exception_if(!in_protmode(ctxt, ops), EXC_UD);
}
break;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|