ia64/xen-unstable

changeset 16464:7c6944d861b2

x86_emulate: Emulate IRET.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Sun Nov 25 18:06:30 2007 +0000 (2007-11-25)
parents 502f5b9469c3
children 6d129d093394
files xen/arch/x86/x86_emulate.c
line diff
     1.1 --- a/xen/arch/x86/x86_emulate.c	Sun Nov 25 18:05:56 2007 +0000
     1.2 +++ b/xen/arch/x86/x86_emulate.c	Sun Nov 25 18:06:30 2007 +0000
     1.3 @@ -149,7 +149,7 @@ static uint8_t opcode_table[256] = {
     1.4      ImplicitOps, ImplicitOps,
     1.5      0, 0, ByteOp|DstMem|SrcImm|ModRM|Mov, DstMem|SrcImm|ModRM|Mov,
     1.6      /* 0xC8 - 0xCF */
     1.7 -    0, 0, 0, 0, ImplicitOps, ImplicitOps, ImplicitOps, 0,
     1.8 +    0, 0, 0, 0, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     1.9      /* 0xD0 - 0xD7 */
    1.10      ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 
    1.11      ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 
    1.12 @@ -2214,6 +2214,33 @@ x86_emulate(
    1.13          src.val = EXC_OF;
    1.14          goto swint;
    1.15  
    1.16 +    case 0xcf: /* iret */ {
    1.17 +        unsigned long cs, eip, eflags;
    1.18 +        uint32_t mask = EFLG_VIP | EFLG_VIF | EFLG_VM;
    1.19 +        if ( !mode_iopl() )
    1.20 +            mask |= EFLG_IOPL;
    1.21 +        fail_if(!in_realmode(ctxt, ops));
    1.22 +        fail_if(ops->write_rflags == NULL);
    1.23 +        if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes),
    1.24 +                             &eip, op_bytes, ctxt)) ||
    1.25 +             (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes),
    1.26 +                             &cs, op_bytes, ctxt)) ||
    1.27 +             (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes),
    1.28 +                             &eflags, op_bytes, ctxt)) )
    1.29 +            goto done;
    1.30 +        if ( op_bytes == 2 )
    1.31 +            eflags = (uint16_t)eflags | (_regs.eflags & 0xffff0000u);
    1.32 +        eflags &= 0x257fd5;
    1.33 +        _regs.eflags &= mask;
    1.34 +        _regs.eflags |= (uint32_t)(eflags & ~mask) | 0x02;
    1.35 +        if ( (rc = ops->write_rflags(_regs.eflags, ctxt)) != 0 )
    1.36 +            goto done;
    1.37 +        _regs.eip = eip;
    1.38 +        if ( (rc = load_seg(x86_seg_cs, (uint16_t)cs, ctxt, ops)) != 0 )
    1.39 +            goto done;
    1.40 +        break;
    1.41 +    }
    1.42 +
    1.43      case 0xd4: /* aam */ {
    1.44          unsigned int base = insn_fetch_type(uint8_t);
    1.45          uint8_t al = _regs.eax;