[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86_emulate: Fix the segment-load function



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1213611857 -3600
# Node ID 049a42108c65d9e56d18539454d49bc83f66eca2
# Parent  ac745ad5f018356b4cf4b1ba127e6c2cc42c4723
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/arch/x86/x86_emulate/x86_emulate.c |   30 +++++++++++++++++++-----------
 1 files changed, 19 insertions(+), 11 deletions(-)

diff -r ac745ad5f018 -r 049a42108c65 xen/arch/x86/x86_emulate/x86_emulate.c
--- a/xen/arch/x86/x86_emulate/x86_emulate.c    Fri Jun 13 16:10:50 2008 +0100
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c    Mon Jun 16 11:24:17 2008 +0100
@@ -878,6 +878,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,
@@ -903,7 +911,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;
@@ -923,7 +931,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;
@@ -955,7 +963,7 @@ protmode_load_seg(
 
         dpl = (desc.b >> 13) & 3;
         rpl = sel & 3;
-        cpl = cs.sel & 3;
+        cpl = ss.attr.fields.dpl;
 
         switch ( seg )
         {
@@ -964,7 +972,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:
@@ -984,7 +992,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;
         }
@@ -1034,10 +1042,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 *
@@ -1596,7 +1604,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, -1);
+            generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1);
         }
         break;
 
@@ -3212,7 +3220,7 @@ x86_emulate(
 
         if ( modrm == 0xdf ) /* invlpga */
         {
-            generate_exception_if(in_realmode(ctxt, ops), EXC_UD, -1);
+            generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1);
             generate_exception_if(!mode_ring0(), EXC_GP, 0);
             fail_if(ops->invlpg == NULL);
             if ( (rc = ops->invlpg(x86_seg_none, truncate_ea(_regs.eax),

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.