ia64/xen-unstable

changeset 17268:f45aa9a14db4

x86_emulate: Return X86EMUL_UNHANDLEABLE if mode_iopl() or
mode_ring0() checks cannot be carried out.
Also fix handling of EFLAGS.IF in iret and popf.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Mar 19 14:06:18 2008 +0000 (2008-03-19)
parents d1e91aba2758
children ba3356c82317
files xen/arch/x86/x86_emulate.c
line diff
     1.1 --- a/xen/arch/x86/x86_emulate.c	Wed Mar 19 12:41:48 2008 +0000
     1.2 +++ b/xen/arch/x86/x86_emulate.c	Wed Mar 19 14:06:18 2008 +0000
     1.3 @@ -785,11 +785,21 @@ static int
     1.4      struct x86_emulate_ops  *ops)
     1.5  {
     1.6      int cpl = get_cpl(ctxt, ops);
     1.7 +    if ( cpl == -1 )
     1.8 +        return -1;
     1.9      return ((cpl >= 0) && (cpl <= ((ctxt->regs->eflags >> 12) & 3)));
    1.10  }
    1.11  
    1.12 -#define mode_ring0() (get_cpl(ctxt, ops) == 0)
    1.13 -#define mode_iopl()  _mode_iopl(ctxt, ops)
    1.14 +#define mode_ring0() ({                         \
    1.15 +    int _cpl = get_cpl(ctxt, ops);              \
    1.16 +    fail_if(_cpl < 0);                          \
    1.17 +    (_cpl == 0);                                \
    1.18 +})
    1.19 +#define mode_iopl() ({                          \
    1.20 +    int _iopl = _mode_iopl(ctxt, ops);          \
    1.21 +    fail_if(_iopl < 0);                         \
    1.22 +    _iopl;                                      \
    1.23 +})
    1.24  
    1.25  static int
    1.26  in_realmode(
    1.27 @@ -2394,8 +2404,10 @@ x86_emulate(
    1.28  
    1.29      case 0x9d: /* popf */ {
    1.30          uint32_t mask = EFLG_VIP | EFLG_VIF | EFLG_VM;
    1.31 +        if ( !mode_ring0() )
    1.32 +            mask |= EFLG_IOPL;
    1.33          if ( !mode_iopl() )
    1.34 -            mask |= EFLG_IOPL;
    1.35 +            mask |= EFLG_IF;
    1.36          /* 64-bit mode: POP defaults to a 64-bit operand. */
    1.37          if ( mode_64bit() && (op_bytes == 4) )
    1.38              op_bytes = 8;
    1.39 @@ -2640,8 +2652,10 @@ x86_emulate(
    1.40      case 0xcf: /* iret */ {
    1.41          unsigned long cs, eip, eflags;
    1.42          uint32_t mask = EFLG_VIP | EFLG_VIF | EFLG_VM;
    1.43 +        if ( !mode_ring0() )
    1.44 +            mask |= EFLG_IOPL;
    1.45          if ( !mode_iopl() )
    1.46 -            mask |= EFLG_IOPL;
    1.47 +            mask |= EFLG_IF;
    1.48          fail_if(!in_realmode(ctxt, ops));
    1.49          if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes),
    1.50                               &eip, op_bytes, ctxt)) ||