ia64/xen-unstable

changeset 17867:049a42108c65

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@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Jun 16 11:24:17 2008 +0100 (2008-06-16)
parents ac745ad5f018
children 42323a447cbe
files xen/arch/x86/x86_emulate/x86_emulate.c
line diff
     1.1 --- a/xen/arch/x86/x86_emulate/x86_emulate.c	Fri Jun 13 16:10:50 2008 +0100
     1.2 +++ b/xen/arch/x86/x86_emulate/x86_emulate.c	Mon Jun 16 11:24:17 2008 +0100
     1.3 @@ -878,6 +878,14 @@ in_realmode(
     1.4  }
     1.5  
     1.6  static int
     1.7 +in_protmode(
     1.8 +    struct x86_emulate_ctxt *ctxt,
     1.9 +    struct x86_emulate_ops  *ops)
    1.10 +{
    1.11 +    return !(in_realmode(ctxt, ops) || (ctxt->regs->eflags & EFLG_VM));
    1.12 +}
    1.13 +
    1.14 +static int
    1.15  realmode_load_seg(
    1.16      enum x86_segment seg,
    1.17      uint16_t sel,
    1.18 @@ -903,7 +911,7 @@ protmode_load_seg(
    1.19      struct x86_emulate_ctxt *ctxt,
    1.20      struct x86_emulate_ops *ops)
    1.21  {
    1.22 -    struct segment_register desctab, cs, segr;
    1.23 +    struct segment_register desctab, ss, segr;
    1.24      struct { uint32_t a, b; } desc;
    1.25      unsigned long val;
    1.26      uint8_t dpl, rpl, cpl;
    1.27 @@ -923,7 +931,7 @@ protmode_load_seg(
    1.28      if ( (seg == x86_seg_ldtr) && (sel & 4) )
    1.29          goto raise_exn;
    1.30  
    1.31 -    if ( (rc = ops->read_segment(x86_seg_cs, &cs, ctxt)) ||
    1.32 +    if ( (rc = ops->read_segment(x86_seg_ss, &ss, ctxt)) ||
    1.33           (rc = ops->read_segment((sel & 4) ? x86_seg_ldtr : x86_seg_gdtr,
    1.34                                   &desctab, ctxt)) )
    1.35          return rc;
    1.36 @@ -955,7 +963,7 @@ protmode_load_seg(
    1.37  
    1.38          dpl = (desc.b >> 13) & 3;
    1.39          rpl = sel & 3;
    1.40 -        cpl = cs.sel & 3;
    1.41 +        cpl = ss.attr.fields.dpl;
    1.42  
    1.43          switch ( seg )
    1.44          {
    1.45 @@ -964,7 +972,7 @@ protmode_load_seg(
    1.46              if ( !(desc.b & (1u<<11)) )
    1.47                  goto raise_exn;
    1.48              /* Non-conforming segment: check DPL against RPL. */
    1.49 -            if ( ((desc.b & (6u<<9)) != 6) && (dpl != rpl) )
    1.50 +            if ( ((desc.b & (6u<<9)) != (6u<<9)) && (dpl != rpl) )
    1.51                  goto raise_exn;
    1.52              break;
    1.53          case x86_seg_ss:
    1.54 @@ -984,7 +992,7 @@ protmode_load_seg(
    1.55              if ( (desc.b & (5u<<9)) == (4u<<9) )
    1.56                  goto raise_exn;
    1.57              /* Non-conforming segment: check DPL against RPL and CPL. */
    1.58 -            if ( ((desc.b & (6u<<9)) != 6) && ((dpl < cpl) || (dpl < rpl)) )
    1.59 +            if ( ((desc.b & (6u<<9)) != (6u<<9)) && ((dpl < cpl) || (dpl < rpl)) )
    1.60                  goto raise_exn;
    1.61              break;
    1.62          }
    1.63 @@ -1034,10 +1042,10 @@ load_seg(
    1.64           (ops->write_segment == NULL) )
    1.65          return X86EMUL_UNHANDLEABLE;
    1.66  
    1.67 -    if ( in_realmode(ctxt, ops) )
    1.68 -        return realmode_load_seg(seg, sel, ctxt, ops);
    1.69 +    if ( in_protmode(ctxt, ops) )
    1.70 +        return protmode_load_seg(seg, sel, ctxt, ops);
    1.71  
    1.72 -    return protmode_load_seg(seg, sel, ctxt, ops);
    1.73 +    return realmode_load_seg(seg, sel, ctxt, ops);
    1.74  }
    1.75  
    1.76  void *
    1.77 @@ -1596,7 +1604,7 @@ x86_emulate(
    1.78                  dst.val  = (dst.val & ~3) | (src_val & 3);
    1.79              else
    1.80                  dst.type = OP_NONE;
    1.81 -            generate_exception_if(in_realmode(ctxt, ops), EXC_UD, -1);
    1.82 +            generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1);
    1.83          }
    1.84          break;
    1.85  
    1.86 @@ -3212,7 +3220,7 @@ x86_emulate(
    1.87  
    1.88          if ( modrm == 0xdf ) /* invlpga */
    1.89          {
    1.90 -            generate_exception_if(in_realmode(ctxt, ops), EXC_UD, -1);
    1.91 +            generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1);
    1.92              generate_exception_if(!mode_ring0(), EXC_GP, 0);
    1.93              fail_if(ops->invlpg == NULL);
    1.94              if ( (rc = ops->invlpg(x86_seg_none, truncate_ea(_regs.eax),