[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] More emulator fixes:
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1168510216 0 # Node ID 558960865583da8aaafdc65f400acbefc6c240c9 # Parent dc0638bb4628653d794dbbcdb3e7d8df7b365f92 [XEN] More emulator fixes: 1. Emulate LAHF/SAHF instructions 2. #GP if instruction is longer than 15 bytes 3. Accept any number of prefix bytes (up to 15-byte total instruction length) 4. Repeated addr/data-size overrides are sticky rather than toggling. 2,3,4 are based on a patch from Jan Beulich. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/x86/x86_emulate.c | 36 ++++++++++++++++++++++-------------- 1 files changed, 22 insertions(+), 14 deletions(-) diff -r dc0638bb4628 -r 558960865583 xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Thu Jan 11 10:08:14 2007 +0000 +++ b/xen/arch/x86/x86_emulate.c Thu Jan 11 10:10:16 2007 +0000 @@ -107,7 +107,7 @@ static uint8_t opcode_table[256] = { ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, /* 0x98 - 0x9F */ - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, ImplicitOps, ImplicitOps, /* 0xA0 - 0xA7 */ ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, @@ -230,7 +230,8 @@ struct operand { #define EFLG_CF (1<<0) /* Exception definitions. */ -#define EXC_DE 0 +#define EXC_DE 0 +#define EXC_GP 13 /* * Instruction emulation: @@ -394,11 +395,13 @@ do{ __asm__ __volatile__ ( /* Fetch next part of the instruction being emulated. */ #define insn_fetch_bytes(_size) \ -({ unsigned long _x, _eip = _truncate_ea(_regs.eip, def_ad_bytes); \ +({ unsigned long _x, _eip = _regs.eip; \ if ( !mode_64bit() ) _eip = (uint32_t)_eip; /* ignore upper dword */ \ + _regs.eip += (_size); /* real hardware doesn't truncate */ \ + generate_exception_if((uint8_t)(_regs.eip - ctxt->regs->eip) > 15, \ + EXC_GP); \ rc = ops->insn_fetch(x86_seg_cs, _eip, &_x, (_size), ctxt); \ if ( rc ) goto done; \ - _regs.eip += (_size); /* real hardware doesn't truncate */ \ _x; \ }) #define insn_fetch_type(_type) ((_type)insn_fetch_bytes(sizeof(_type))) @@ -540,8 +543,8 @@ x86_emulate( uint8_t b, d, sib, sib_index, sib_base, twobyte = 0, rex_prefix = 0; uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; - unsigned int op_bytes, ad_bytes, def_ad_bytes; - unsigned int lock_prefix = 0, rep_prefix = 0, i; + unsigned int op_bytes, def_op_bytes, ad_bytes, def_ad_bytes; + unsigned int lock_prefix = 0, rep_prefix = 0; int rc = 0; struct operand src, dst; @@ -553,28 +556,25 @@ x86_emulate( ea.mem.seg = x86_seg_ds; ea.mem.off = 0; - op_bytes = ad_bytes = def_ad_bytes = ctxt->address_bytes; + op_bytes = def_op_bytes = ad_bytes = def_ad_bytes = ctxt->address_bytes; if ( op_bytes == 8 ) { - op_bytes = 4; + op_bytes = def_op_bytes = 4; #ifndef __x86_64__ return -1; #endif } /* Prefix bytes. */ - for ( i = 0; i < 8; i++ ) + for ( ; ; ) { switch ( b = insn_fetch_type(uint8_t) ) { case 0x66: /* operand-size override */ - op_bytes ^= 6; /* switch between 2/4 bytes */ + op_bytes = def_op_bytes ^ 6; break; case 0x67: /* address-size override */ - if ( mode_64bit() ) - ad_bytes ^= 12; /* switch between 4/8 bytes */ - else - ad_bytes ^= 6; /* switch between 2/4 bytes */ + ad_bytes = def_ad_bytes ^ (mode_64bit() ? 12 : 6); break; case 0x2e: /* CS override */ ea.mem.seg = x86_seg_cs; @@ -1288,6 +1288,14 @@ x86_emulate( dst.val = dst.orig_val = *dst.reg; goto xchg; + case 0x9e: /* sahf */ + *(uint8_t *)_regs.eflags = (((uint8_t *)&_regs.eax)[1] & 0xd7) | 0x02; + break; + + case 0x9f: /* lahf */ + ((uint8_t *)&_regs.eax)[1] = (_regs.eflags & 0xd7) | 0x02; + break; + case 0xa0 ... 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */ /* Source EA is not encoded via ModRM. */ dst.type = OP_REG; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |