aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/x86_emulate.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-10-28 10:34:25 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:52:57 -0500
commitc7e75a3db4ecd952e7a5562cea1b27007bf0c01c (patch)
treea83547a4a40ff4c05a62ab5eb112d4417462d235 /drivers/kvm/x86_emulate.c
parentfe7935d49fbe33308c1b5f0e35137989da851010 (diff)
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: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r--drivers/kvm/x86_emulate.c50
1 files changed, 30 insertions, 20 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 73e3580c88e4..087a8208f873 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -63,8 +63,9 @@
63/* Destination is only written; never read. */ 63/* Destination is only written; never read. */
64#define Mov (1<<7) 64#define Mov (1<<7)
65#define BitOp (1<<8) 65#define BitOp (1<<8)
66#define MemAbs (1<<9) /* Memory operand is absolute displacement */
66 67
67static u8 opcode_table[256] = { 68static u16 opcode_table[256] = {
68 /* 0x00 - 0x07 */ 69 /* 0x00 - 0x07 */
69 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 70 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
70 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, 71 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
@@ -134,8 +135,8 @@ static u8 opcode_table[256] = {
134 /* 0x90 - 0x9F */ 135 /* 0x90 - 0x9F */
135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps, ImplicitOps, 0, 0, 136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps, ImplicitOps, 0, 0,
136 /* 0xA0 - 0xA7 */ 137 /* 0xA0 - 0xA7 */
137 ByteOp | DstReg | SrcMem | Mov, DstReg | SrcMem | Mov, 138 ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs,
138 ByteOp | DstMem | SrcReg | Mov, DstMem | SrcReg | Mov, 139 ByteOp | DstMem | SrcReg | Mov | MemAbs, DstMem | SrcReg | Mov | MemAbs,
139 ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, 140 ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,
140 ByteOp | ImplicitOps, ImplicitOps, 141 ByteOp | ImplicitOps, ImplicitOps,
141 /* 0xA8 - 0xAF */ 142 /* 0xA8 - 0xAF */
@@ -755,16 +756,6 @@ done_prefixes:
755 break; 756 break;
756 } 757 }
757 } 758 }
758 if (!c->override_base)
759 c->override_base = &ctxt->ds_base;
760 if (mode == X86EMUL_MODE_PROT64 &&
761 c->override_base != &ctxt->fs_base &&
762 c->override_base != &ctxt->gs_base)
763 c->override_base = NULL;
764
765 if (c->override_base)
766 c->modrm_ea += *c->override_base;
767
768 if (rip_relative) { 759 if (rip_relative) {
769 c->modrm_ea += c->eip; 760 c->modrm_ea += c->eip;
770 switch (c->d & SrcMask) { 761 switch (c->d & SrcMask) {
@@ -781,12 +772,35 @@ done_prefixes:
781 c->modrm_ea += c->op_bytes; 772 c->modrm_ea += c->op_bytes;
782 } 773 }
783 } 774 }
784 if (c->ad_bytes != 8)
785 c->modrm_ea = (u32)c->modrm_ea;
786modrm_done: 775modrm_done:
787 ; 776 ;
777 } else if (c->d & MemAbs) {
778 switch (c->ad_bytes) {
779 case 2:
780 c->modrm_ea = insn_fetch(u16, 2, c->eip);
781 break;
782 case 4:
783 c->modrm_ea = insn_fetch(u32, 4, c->eip);
784 break;
785 case 8:
786 c->modrm_ea = insn_fetch(u64, 8, c->eip);
787 break;
788 }
789
788 } 790 }
789 791
792 if (!c->override_base)
793 c->override_base = &ctxt->ds_base;
794 if (mode == X86EMUL_MODE_PROT64 &&
795 c->override_base != &ctxt->fs_base &&
796 c->override_base != &ctxt->gs_base)
797 c->override_base = NULL;
798
799 if (c->override_base)
800 c->modrm_ea += *c->override_base;
801
802 if (c->ad_bytes != 8)
803 c->modrm_ea = (u32)c->modrm_ea;
790 /* 804 /*
791 * Decode and fetch the source operand: register, memory 805 * Decode and fetch the source operand: register, memory
792 * or immediate. 806 * or immediate.
@@ -1171,7 +1185,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
1171 memcpy(c->regs, ctxt->vcpu->regs, sizeof c->regs); 1185 memcpy(c->regs, ctxt->vcpu->regs, sizeof c->regs);
1172 saved_eip = c->eip; 1186 saved_eip = c->eip;
1173 1187
1174 if ((c->d & ModRM) && (c->modrm_mod != 3)) 1188 if (((c->d & ModRM) && (c->modrm_mod != 3)) || (c->d & MemAbs))
1175 cr2 = c->modrm_ea; 1189 cr2 = c->modrm_ea;
1176 1190
1177 if (c->src.type == OP_MEM) { 1191 if (c->src.type == OP_MEM) {
@@ -1326,13 +1340,9 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
1326 case 0xa0 ... 0xa1: /* mov */ 1340 case 0xa0 ... 0xa1: /* mov */
1327 c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX]; 1341 c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
1328 c->dst.val = c->src.val; 1342 c->dst.val = c->src.val;
1329 /* skip src displacement */
1330 c->eip += c->ad_bytes;
1331 break; 1343 break;
1332 case 0xa2 ... 0xa3: /* mov */ 1344 case 0xa2 ... 0xa3: /* mov */
1333 c->dst.val = (unsigned long)c->regs[VCPU_REGS_RAX]; 1345 c->dst.val = (unsigned long)c->regs[VCPU_REGS_RAX];
1334 /* skip c->dst displacement */
1335 c->eip += c->ad_bytes;
1336 break; 1346 break;
1337 case 0xc0 ... 0xc1: 1347 case 0xc0 ... 0xc1:
1338 emulate_grp2(ctxt); 1348 emulate_grp2(ctxt);