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>
This commit is contained in:
Родитель
90e0a28f6b
Коммит
f21b8bf4cc
|
@ -758,6 +758,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
|
||||||
struct decode_cache *c = &ctxt->decode;
|
struct decode_cache *c = &ctxt->decode;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int mode = ctxt->mode;
|
int mode = ctxt->mode;
|
||||||
|
int def_op_bytes, def_ad_bytes;
|
||||||
|
|
||||||
/* Shadow copy of register state. Committed on successful emulation. */
|
/* 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) {
|
switch (mode) {
|
||||||
case X86EMUL_MODE_REAL:
|
case X86EMUL_MODE_REAL:
|
||||||
case X86EMUL_MODE_PROT16:
|
case X86EMUL_MODE_PROT16:
|
||||||
c->op_bytes = c->ad_bytes = 2;
|
def_op_bytes = def_ad_bytes = 2;
|
||||||
break;
|
break;
|
||||||
case X86EMUL_MODE_PROT32:
|
case X86EMUL_MODE_PROT32:
|
||||||
c->op_bytes = c->ad_bytes = 4;
|
def_op_bytes = def_ad_bytes = 4;
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
case X86EMUL_MODE_PROT64:
|
case X86EMUL_MODE_PROT64:
|
||||||
c->op_bytes = 4;
|
def_op_bytes = 4;
|
||||||
c->ad_bytes = 8;
|
def_ad_bytes = 8;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c->op_bytes = def_op_bytes;
|
||||||
|
c->ad_bytes = def_ad_bytes;
|
||||||
|
|
||||||
/* Legacy prefixes. */
|
/* Legacy prefixes. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
switch (c->b = insn_fetch(u8, 1, c->eip)) {
|
switch (c->b = insn_fetch(u8, 1, c->eip)) {
|
||||||
case 0x66: /* operand-size override */
|
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;
|
break;
|
||||||
case 0x67: /* address-size override */
|
case 0x67: /* address-size override */
|
||||||
if (mode == X86EMUL_MODE_PROT64)
|
if (mode == X86EMUL_MODE_PROT64)
|
||||||
/* switch between 4/8 bytes */
|
/* switch between 4/8 bytes */
|
||||||
c->ad_bytes ^= 12;
|
c->ad_bytes = def_ad_bytes ^ 12;
|
||||||
else
|
else
|
||||||
/* switch between 2/4 bytes */
|
/* switch between 2/4 bytes */
|
||||||
c->ad_bytes ^= 6;
|
c->ad_bytes = def_ad_bytes ^ 6;
|
||||||
break;
|
break;
|
||||||
case 0x2e: /* CS override */
|
case 0x2e: /* CS override */
|
||||||
c->override_base = &ctxt->cs_base;
|
c->override_base = &ctxt->cs_base;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче