Commit c7e75a3d authored by Avi Kivity's avatar Avi Kivity

KVM: x86 emulator: don't depend on cr2 for mov abs emulation

The 'mov abs' instruction family (opcodes 0xa0 - 0xa3) still depends on cr2
provided by the page fault handler.  This is wrong for several reasons:

- if an instruction accessed misaligned data that crosses a page boundary,
  and if the fault happened on the second page, cr2 will point at the
  second page, not the data itself.

- if we're emulating in real mode, or due to a FlexPriority exit, there
  is no cr2 generated.

So, this change adds decoding for this instruction form and drops reliance
on cr2.
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent fe7935d4
...@@ -63,8 +63,9 @@ ...@@ -63,8 +63,9 @@
/* Destination is only written; never read. */ /* Destination is only written; never read. */
#define Mov (1<<7) #define Mov (1<<7)
#define BitOp (1<<8) #define BitOp (1<<8)
#define MemAbs (1<<9) /* Memory operand is absolute displacement */
static u8 opcode_table[256] = { static u16 opcode_table[256] = {
/* 0x00 - 0x07 */ /* 0x00 - 0x07 */
ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
...@@ -134,8 +135,8 @@ static u8 opcode_table[256] = { ...@@ -134,8 +135,8 @@ static u8 opcode_table[256] = {
/* 0x90 - 0x9F */ /* 0x90 - 0x9F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps, ImplicitOps, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps, ImplicitOps, 0, 0,
/* 0xA0 - 0xA7 */ /* 0xA0 - 0xA7 */
ByteOp | DstReg | SrcMem | Mov, DstReg | SrcMem | Mov, ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs,
ByteOp | DstMem | SrcReg | Mov, DstMem | SrcReg | Mov, ByteOp | DstMem | SrcReg | Mov | MemAbs, DstMem | SrcReg | Mov | MemAbs,
ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,
ByteOp | ImplicitOps, ImplicitOps, ByteOp | ImplicitOps, ImplicitOps,
/* 0xA8 - 0xAF */ /* 0xA8 - 0xAF */
...@@ -755,16 +756,6 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) ...@@ -755,16 +756,6 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
break; break;
} }
} }
if (!c->override_base)
c->override_base = &ctxt->ds_base;
if (mode == X86EMUL_MODE_PROT64 &&
c->override_base != &ctxt->fs_base &&
c->override_base != &ctxt->gs_base)
c->override_base = NULL;
if (c->override_base)
c->modrm_ea += *c->override_base;
if (rip_relative) { if (rip_relative) {
c->modrm_ea += c->eip; c->modrm_ea += c->eip;
switch (c->d & SrcMask) { switch (c->d & SrcMask) {
...@@ -781,12 +772,35 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) ...@@ -781,12 +772,35 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
c->modrm_ea += c->op_bytes; c->modrm_ea += c->op_bytes;
} }
} }
if (c->ad_bytes != 8)
c->modrm_ea = (u32)c->modrm_ea;
modrm_done: modrm_done:
; ;
} else if (c->d & MemAbs) {
switch (c->ad_bytes) {
case 2:
c->modrm_ea = insn_fetch(u16, 2, c->eip);
break;
case 4:
c->modrm_ea = insn_fetch(u32, 4, c->eip);
break;
case 8:
c->modrm_ea = insn_fetch(u64, 8, c->eip);
break;
}
} }
if (!c->override_base)
c->override_base = &ctxt->ds_base;
if (mode == X86EMUL_MODE_PROT64 &&
c->override_base != &ctxt->fs_base &&
c->override_base != &ctxt->gs_base)
c->override_base = NULL;
if (c->override_base)
c->modrm_ea += *c->override_base;
if (c->ad_bytes != 8)
c->modrm_ea = (u32)c->modrm_ea;
/* /*
* Decode and fetch the source operand: register, memory * Decode and fetch the source operand: register, memory
* or immediate. * or immediate.
...@@ -1171,7 +1185,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) ...@@ -1171,7 +1185,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
memcpy(c->regs, ctxt->vcpu->regs, sizeof c->regs); memcpy(c->regs, ctxt->vcpu->regs, sizeof c->regs);
saved_eip = c->eip; saved_eip = c->eip;
if ((c->d & ModRM) && (c->modrm_mod != 3)) if (((c->d & ModRM) && (c->modrm_mod != 3)) || (c->d & MemAbs))
cr2 = c->modrm_ea; cr2 = c->modrm_ea;
if (c->src.type == OP_MEM) { if (c->src.type == OP_MEM) {
...@@ -1326,13 +1340,9 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) ...@@ -1326,13 +1340,9 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
case 0xa0 ... 0xa1: /* mov */ case 0xa0 ... 0xa1: /* mov */
c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX]; c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
c->dst.val = c->src.val; c->dst.val = c->src.val;
/* skip src displacement */
c->eip += c->ad_bytes;
break; break;
case 0xa2 ... 0xa3: /* mov */ case 0xa2 ... 0xa3: /* mov */
c->dst.val = (unsigned long)c->regs[VCPU_REGS_RAX]; c->dst.val = (unsigned long)c->regs[VCPU_REGS_RAX];
/* skip c->dst displacement */
c->eip += c->ad_bytes;
break; break;
case 0xc0 ... 0xc1: case 0xc0 ... 0xc1:
emulate_grp2(ctxt); emulate_grp2(ctxt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment