# 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
|