diff options
author | Avi Kivity <avi@qumranet.com> | 2007-11-22 14:16:12 +0200 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 17:53:14 +0200 |
commit | f21b8bf4cc4091b23669987124fd13f758abf6d6 (patch) | |
tree | a15405e027bc520727c9aa86e607a629b98924ac | |
parent | 90e0a28f6b7241c7793f2ebd540c349580170446 (diff) |
KVM: x86 emulator: address size and operand size overrides are sticky
Current implementation is to toggle, which is incorrect. Patch ported from
corresponding Xen code.
Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r-- | drivers/kvm/x86_emulate.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index 9f8d59a4931..3be506ac01a 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c @@ -758,6 +758,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) struct decode_cache *c = &ctxt->decode; int rc = 0; int mode = ctxt->mode; + int def_op_bytes, def_ad_bytes; /* Shadow copy of register state. Committed on successful emulation. */ @@ -768,34 +769,38 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) switch (mode) { case X86EMUL_MODE_REAL: case X86EMUL_MODE_PROT16: - c->op_bytes = c->ad_bytes = 2; + def_op_bytes = def_ad_bytes = 2; break; case X86EMUL_MODE_PROT32: - c->op_bytes = c->ad_bytes = 4; + def_op_bytes = def_ad_bytes = 4; break; #ifdef CONFIG_X86_64 case X86EMUL_MODE_PROT64: - c->op_bytes = 4; - c->ad_bytes = 8; + def_op_bytes = 4; + def_ad_bytes = 8; break; #endif default: return -1; } + c->op_bytes = def_op_bytes; + c->ad_bytes = def_ad_bytes; + /* Legacy prefixes. */ for (;;) { switch (c->b = insn_fetch(u8, 1, c->eip)) { case 0x66: /* operand-size override */ - c->op_bytes ^= 6; /* switch between 2/4 bytes */ + /* switch between 2/4 bytes */ + c->op_bytes = def_op_bytes ^ 6; break; case 0x67: /* address-size override */ if (mode == X86EMUL_MODE_PROT64) /* switch between 4/8 bytes */ - c->ad_bytes ^= 12; + c->ad_bytes = def_ad_bytes ^ 12; else /* switch between 2/4 bytes */ - c->ad_bytes ^= 6; + c->ad_bytes = def_ad_bytes ^ 6; break; case 0x2e: /* CS override */ c->override_base = &ctxt->cs_base; |