diff options
author | Avi Kivity <avi@qumranet.com> | 2007-10-28 10:34:25 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:52:57 -0500 |
commit | c7e75a3db4ecd952e7a5562cea1b27007bf0c01c (patch) | |
tree | a83547a4a40ff4c05a62ab5eb112d4417462d235 /drivers/kvm/x86_emulate.c | |
parent | fe7935d49fbe33308c1b5f0e35137989da851010 (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.c | 50 |
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 | ||
67 | static u8 opcode_table[256] = { | 68 | static 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; | ||
786 | modrm_done: | 775 | modrm_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); |