[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] emulator: Start filling in gaps for privileged instructions.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1169738706 0 # Node ID 21b9416d2215bb6241ccb20957a2428eb1bbaa07 # Parent 0843e4261753c3d2d99d7e5163491ccee1dc33a3 emulator: Start filling in gaps for privileged instructions. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/x86/x86_emulate.c | 124 +++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 114 insertions(+), 10 deletions(-) diff -r 0843e4261753 -r 21b9416d2215 xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Thu Jan 25 14:52:36 2007 +0000 +++ b/xen/arch/x86/x86_emulate.c Thu Jan 25 15:25:06 2007 +0000 @@ -162,22 +162,29 @@ static uint8_t opcode_table[256] = { 0, 0, 0, 0, 0, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM, /* 0xF8 - 0xFF */ - ImplicitOps, ImplicitOps, 0, 0, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM }; static uint8_t twobyte_table[256] = { - /* 0x00 - 0x0F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, + /* 0x00 - 0x07 */ + 0, 0, 0, 0, 0, ImplicitOps, 0, 0, + /* 0x08 - 0x0F */ + ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps|ModRM, 0, 0, /* 0x10 - 0x17 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x18 - 0x1F */ ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, - /* 0x20 - 0x2F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x30 - 0x3F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x20 - 0x27 */ + ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, + 0, 0, 0, 0, + /* 0x28 - 0x2F */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x30 - 0x37 */ + ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0, 0, + /* 0x38 - 0x3F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x47 */ DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, @@ -255,6 +262,7 @@ struct operand { /* EFLAGS bit definitions. */ #define EFLG_OF (1<<11) #define EFLG_DF (1<<10) +#define EFLG_IF (1<<9) #define EFLG_SF (1<<7) #define EFLG_ZF (1<<6) #define EFLG_AF (1<<4) @@ -463,6 +471,10 @@ do { /* In future we will be able to generate arbitrary exceptions. */ #define generate_exception_if(p, e) fail_if(p) +/* To be done... */ +#define mode_ring0() (0) +#define mode_iopl() (0) + /* Given byte has even parity (even number of 1s)? */ static int even_parity(uint8_t v) { @@ -1554,10 +1566,13 @@ x86_emulate( dst.type = OP_NONE; /* - * The only implicit-operands instruction allowed a LOCK prefix is - * CMPXCHG{8,16}B. + * The only implicit-operands instructions allowed a LOCK prefix are + * CMPXCHG{8,16}B, MOV CRn, MOV DRn. */ - generate_exception_if(lock_prefix && (b != 0xc7), EXC_GP); + generate_exception_if(lock_prefix && + ((b < 0x20) || (b > 0x23)) && /* MOV CRn/DRn */ + (b != 0xc7), /* CMPXCHG{8,16}B */ + EXC_GP); if ( twobyte ) goto twobyte_special_insn; @@ -1933,6 +1948,20 @@ x86_emulate( _regs.eflags |= EFLG_CF; break; + case 0xfa: /* cli */ + generate_exception_if(!mode_iopl(), EXC_GP); + fail_if(ops->write_rflags == NULL); + if ( (rc = ops->write_rflags(_regs.eflags & ~EFLG_IF, ctxt)) != 0 ) + goto done; + break; + + case 0xfb: /* sti */ + generate_exception_if(!mode_iopl(), EXC_GP); + fail_if(ops->write_rflags == NULL); + if ( (rc = ops->write_rflags(_regs.eflags | EFLG_IF, ctxt)) != 0 ) + goto done; + break; + case 0xfc: /* cld */ _regs.eflags &= ~EFLG_DF; break; @@ -2089,10 +2118,85 @@ x86_emulate( twobyte_special_insn: switch ( b ) { + case 0x06: /* clts */ + generate_exception_if(!mode_ring0(), EXC_GP); + fail_if((ops->read_cr == NULL) || (ops->write_cr == NULL)); + if ( (rc = ops->read_cr(0, &dst.val, ctxt)) || + (rc = ops->write_cr(0, dst.val|8, ctxt)) ) + goto done; + break; + + case 0x08: /* invd */ + case 0x09: /* wbinvd */ + generate_exception_if(!mode_ring0(), EXC_GP); + fail_if(ops->wbinvd == NULL); + if ( (rc = ops->wbinvd(ctxt)) != 0 ) + goto done; + break; + case 0x0d: /* GrpP (prefetch) */ case 0x18: /* Grp16 (prefetch/nop) */ case 0x19 ... 0x1f: /* nop (amd-defined) */ break; + + case 0x20: /* mov cr,reg */ + case 0x21: /* mov dr,reg */ + case 0x22: /* mov reg,cr */ + case 0x23: /* mov reg,dr */ + generate_exception_if(!mode_ring0(), EXC_GP); + modrm_rm |= (rex_prefix & 1) << 3; + modrm_reg |= lock_prefix << 3; + if ( b & 2 ) + { + /* Write to CR/DR. */ + src.val = *(unsigned long *)decode_register(modrm_rm, &_regs, 0); + if ( !mode_64bit() ) + src.val = (uint32_t)src.val; + rc = ((b & 1) + ? (ops->write_dr + ? ops->write_dr(modrm_reg, src.val, ctxt) + : X86EMUL_UNHANDLEABLE) + : (ops->write_cr + ? ops->write_dr(modrm_reg, src.val, ctxt) + : X86EMUL_UNHANDLEABLE)); + } + else + { + /* Read from CR/DR. */ + dst.type = OP_REG; + dst.bytes = mode_64bit() ? 8 : 4; + dst.reg = decode_register(modrm_rm, &_regs, 0); + rc = ((b & 1) + ? (ops->read_dr + ? ops->read_dr(modrm_reg, &dst.val, ctxt) + : X86EMUL_UNHANDLEABLE) + : (ops->read_cr + ? ops->read_dr(modrm_reg, &dst.val, ctxt) + : X86EMUL_UNHANDLEABLE)); + } + if ( rc != 0 ) + goto done; + break; + + case 0x30: /* wrmsr */ { + uint64_t val = ((uint64_t)_regs.edx << 32) | (uint32_t)_regs.eax; + generate_exception_if(!mode_ring0(), EXC_GP); + fail_if(ops->write_msr == NULL); + if ( (rc = ops->write_msr((uint32_t)_regs.ecx, val, ctxt)) != 0 ) + goto done; + break; + } + + case 0x32: /* rdmsr */ { + uint64_t val; + generate_exception_if(!mode_ring0(), EXC_GP); + fail_if(ops->read_msr == NULL); + if ( (rc = ops->read_msr((uint32_t)_regs.ecx, &val, ctxt)) != 0 ) + goto done; + _regs.edx = (uint32_t)(val >> 32); + _regs.eax = (uint32_t)(val >> 0); + break; + } case 0x80 ... 0x8f: /* jcc (near) */ { int rel = (((op_bytes == 2) && !mode_64bit()) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |