ia64/xen-unstable

changeset 13623:21b9416d2215

emulator: Start filling in gaps for privileged instructions.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu Jan 25 15:25:06 2007 +0000 (2007-01-25)
parents 0843e4261753
children fec1a6975588
files xen/arch/x86/x86_emulate.c
line diff
     1.1 --- a/xen/arch/x86/x86_emulate.c	Thu Jan 25 14:52:36 2007 +0000
     1.2 +++ b/xen/arch/x86/x86_emulate.c	Thu Jan 25 15:25:06 2007 +0000
     1.3 @@ -162,22 +162,29 @@ static uint8_t opcode_table[256] = {
     1.4      0, 0, 0, 0,
     1.5      0, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM,
     1.6      /* 0xF8 - 0xFF */
     1.7 -    ImplicitOps, ImplicitOps, 0, 0,
     1.8 +    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     1.9      ImplicitOps, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM
    1.10  };
    1.11  
    1.12  static uint8_t twobyte_table[256] = {
    1.13 -    /* 0x00 - 0x0F */
    1.14 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0,
    1.15 +    /* 0x00 - 0x07 */
    1.16 +    0, 0, 0, 0, 0, ImplicitOps, 0, 0,
    1.17 +    /* 0x08 - 0x0F */
    1.18 +    ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps|ModRM, 0, 0,
    1.19      /* 0x10 - 0x17 */
    1.20      0, 0, 0, 0, 0, 0, 0, 0,
    1.21      /* 0x18 - 0x1F */
    1.22      ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM,
    1.23      ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM,
    1.24 -    /* 0x20 - 0x2F */
    1.25 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    1.26 -    /* 0x30 - 0x3F */
    1.27 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    1.28 +    /* 0x20 - 0x27 */
    1.29 +    ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM,
    1.30 +    0, 0, 0, 0,
    1.31 +    /* 0x28 - 0x2F */
    1.32 +    0, 0, 0, 0, 0, 0, 0, 0,
    1.33 +    /* 0x30 - 0x37 */
    1.34 +    ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0, 0,
    1.35 +    /* 0x38 - 0x3F */
    1.36 +    0, 0, 0, 0, 0, 0, 0, 0,
    1.37      /* 0x40 - 0x47 */
    1.38      DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
    1.39      DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
    1.40 @@ -255,6 +262,7 @@ struct operand {
    1.41  /* EFLAGS bit definitions. */
    1.42  #define EFLG_OF (1<<11)
    1.43  #define EFLG_DF (1<<10)
    1.44 +#define EFLG_IF (1<<9)
    1.45  #define EFLG_SF (1<<7)
    1.46  #define EFLG_ZF (1<<6)
    1.47  #define EFLG_AF (1<<4)
    1.48 @@ -463,6 +471,10 @@ do {                                    
    1.49  /* In future we will be able to generate arbitrary exceptions. */
    1.50  #define generate_exception_if(p, e) fail_if(p)
    1.51  
    1.52 +/* To be done... */
    1.53 +#define mode_ring0() (0)
    1.54 +#define mode_iopl()  (0)
    1.55 +
    1.56  /* Given byte has even parity (even number of 1s)? */
    1.57  static int even_parity(uint8_t v)
    1.58  {
    1.59 @@ -1554,10 +1566,13 @@ x86_emulate(
    1.60      dst.type = OP_NONE;
    1.61  
    1.62      /*
    1.63 -     * The only implicit-operands instruction allowed a LOCK prefix is
    1.64 -     * CMPXCHG{8,16}B.
    1.65 +     * The only implicit-operands instructions allowed a LOCK prefix are
    1.66 +     * CMPXCHG{8,16}B, MOV CRn, MOV DRn.
    1.67       */
    1.68 -    generate_exception_if(lock_prefix && (b != 0xc7), EXC_GP);
    1.69 +    generate_exception_if(lock_prefix &&
    1.70 +                          ((b < 0x20) || (b > 0x23)) && /* MOV CRn/DRn */
    1.71 +                          (b != 0xc7),                  /* CMPXCHG{8,16}B */
    1.72 +                          EXC_GP);
    1.73  
    1.74      if ( twobyte )
    1.75          goto twobyte_special_insn;
    1.76 @@ -1933,6 +1948,20 @@ x86_emulate(
    1.77          _regs.eflags |= EFLG_CF;
    1.78          break;
    1.79  
    1.80 +    case 0xfa: /* cli */
    1.81 +        generate_exception_if(!mode_iopl(), EXC_GP);
    1.82 +        fail_if(ops->write_rflags == NULL);
    1.83 +        if ( (rc = ops->write_rflags(_regs.eflags & ~EFLG_IF, ctxt)) != 0 )
    1.84 +            goto done;
    1.85 +        break;
    1.86 +
    1.87 +    case 0xfb: /* sti */
    1.88 +        generate_exception_if(!mode_iopl(), EXC_GP);
    1.89 +        fail_if(ops->write_rflags == NULL);
    1.90 +        if ( (rc = ops->write_rflags(_regs.eflags | EFLG_IF, ctxt)) != 0 )
    1.91 +            goto done;
    1.92 +        break;
    1.93 +
    1.94      case 0xfc: /* cld */
    1.95          _regs.eflags &= ~EFLG_DF;
    1.96          break;
    1.97 @@ -2089,11 +2118,86 @@ x86_emulate(
    1.98   twobyte_special_insn:
    1.99      switch ( b )
   1.100      {
   1.101 +    case 0x06: /* clts */
   1.102 +        generate_exception_if(!mode_ring0(), EXC_GP);
   1.103 +        fail_if((ops->read_cr == NULL) || (ops->write_cr == NULL));
   1.104 +        if ( (rc = ops->read_cr(0, &dst.val, ctxt)) ||
   1.105 +             (rc = ops->write_cr(0, dst.val|8, ctxt)) )
   1.106 +            goto done;
   1.107 +        break;
   1.108 +
   1.109 +    case 0x08: /* invd */
   1.110 +    case 0x09: /* wbinvd */
   1.111 +        generate_exception_if(!mode_ring0(), EXC_GP);
   1.112 +        fail_if(ops->wbinvd == NULL);
   1.113 +        if ( (rc = ops->wbinvd(ctxt)) != 0 )
   1.114 +            goto done;
   1.115 +        break;
   1.116 +
   1.117      case 0x0d: /* GrpP (prefetch) */
   1.118      case 0x18: /* Grp16 (prefetch/nop) */
   1.119      case 0x19 ... 0x1f: /* nop (amd-defined) */
   1.120          break;
   1.121  
   1.122 +    case 0x20: /* mov cr,reg */
   1.123 +    case 0x21: /* mov dr,reg */
   1.124 +    case 0x22: /* mov reg,cr */
   1.125 +    case 0x23: /* mov reg,dr */
   1.126 +        generate_exception_if(!mode_ring0(), EXC_GP);
   1.127 +        modrm_rm  |= (rex_prefix & 1) << 3;
   1.128 +        modrm_reg |= lock_prefix << 3;
   1.129 +        if ( b & 2 )
   1.130 +        {
   1.131 +            /* Write to CR/DR. */
   1.132 +            src.val = *(unsigned long *)decode_register(modrm_rm, &_regs, 0);
   1.133 +            if ( !mode_64bit() )
   1.134 +                src.val = (uint32_t)src.val;
   1.135 +            rc = ((b & 1)
   1.136 +                  ? (ops->write_dr
   1.137 +                     ? ops->write_dr(modrm_reg, src.val, ctxt)
   1.138 +                     : X86EMUL_UNHANDLEABLE)
   1.139 +                  : (ops->write_cr
   1.140 +                     ? ops->write_dr(modrm_reg, src.val, ctxt)
   1.141 +                     : X86EMUL_UNHANDLEABLE));
   1.142 +        }
   1.143 +        else
   1.144 +        {
   1.145 +            /* Read from CR/DR. */
   1.146 +            dst.type  = OP_REG;
   1.147 +            dst.bytes = mode_64bit() ? 8 : 4;
   1.148 +            dst.reg   = decode_register(modrm_rm, &_regs, 0);
   1.149 +            rc = ((b & 1)
   1.150 +                  ? (ops->read_dr
   1.151 +                     ? ops->read_dr(modrm_reg, &dst.val, ctxt)
   1.152 +                     : X86EMUL_UNHANDLEABLE)
   1.153 +                  : (ops->read_cr
   1.154 +                     ? ops->read_dr(modrm_reg, &dst.val, ctxt)
   1.155 +                     : X86EMUL_UNHANDLEABLE));
   1.156 +        }
   1.157 +        if ( rc != 0 )
   1.158 +            goto done;
   1.159 +        break;
   1.160 +
   1.161 +    case 0x30: /* wrmsr */ {
   1.162 +        uint64_t val = ((uint64_t)_regs.edx << 32) | (uint32_t)_regs.eax;
   1.163 +        generate_exception_if(!mode_ring0(), EXC_GP);
   1.164 +        fail_if(ops->write_msr == NULL);
   1.165 +        if ( (rc = ops->write_msr((uint32_t)_regs.ecx, val, ctxt)) != 0 )
   1.166 +            goto done;
   1.167 +        break;
   1.168 +    }
   1.169 +
   1.170 +    case 0x32: /* rdmsr */ {
   1.171 +        uint64_t val;
   1.172 +        generate_exception_if(!mode_ring0(), EXC_GP);
   1.173 +        fail_if(ops->read_msr == NULL);
   1.174 +        if ( (rc = ops->read_msr((uint32_t)_regs.ecx, &val, ctxt)) != 0 )
   1.175 +            goto done;
   1.176 +        _regs.edx = (uint32_t)(val >> 32);
   1.177 +        _regs.eax = (uint32_t)(val >>  0);
   1.178 +        break;
   1.179 +    }
   1.180 +
   1.181      case 0x80 ... 0x8f: /* jcc (near) */ {
   1.182          int rel = (((op_bytes == 2) && !mode_64bit())
   1.183                     ? (int32_t)insn_fetch_type(int16_t)