aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorNadav Amit <namit@cs.technion.ac.il>2014-11-26 08:47:18 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2014-12-04 09:29:04 -0500
commit39f062ff51b2a3bf9919bc74e575296f7e8cce1f (patch)
tree79005a4f1775c033f1bd4c500b6381578f8e6ae5 /arch/x86/kvm/emulate.c
parentbe06b6bece19be5b167d863fd6c5271e4ec8f1fa (diff)
KVM: x86: Generate #UD when memory operand is required
Certain x86 instructions that use modrm operands only allow memory operand (i.e., mod012), and cause a #UD exception otherwise. KVM ignores this fact. Currently, the instructions that are such and are emulated by KVM are MOVBE, MOVNTPS, MOVNTPD and MOVNTI. MOVBE is the most blunt example, since it may be emulated by the host regardless of MMIO. The fix introduces a new group for handling such instructions, marking mod3 as illegal instruction. Signed-off-by: Nadav Amit <namit@cs.technion.ac.il> Reviewed-by: Radim Krčmář <rkrcmar@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 6a57157675ad..38173343153f 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -123,6 +123,7 @@
123#define Prefix (3<<15) /* Instruction varies with 66/f2/f3 prefix */ 123#define Prefix (3<<15) /* Instruction varies with 66/f2/f3 prefix */
124#define RMExt (4<<15) /* Opcode extension in ModRM r/m if mod == 3 */ 124#define RMExt (4<<15) /* Opcode extension in ModRM r/m if mod == 3 */
125#define Escape (5<<15) /* Escape to coprocessor instruction */ 125#define Escape (5<<15) /* Escape to coprocessor instruction */
126#define InstrDual (6<<15) /* Alternate instruction decoding of mod == 3 */
126#define Sse (1<<18) /* SSE Vector instruction */ 127#define Sse (1<<18) /* SSE Vector instruction */
127/* Generic ModRM decode. */ 128/* Generic ModRM decode. */
128#define ModRM (1<<19) 129#define ModRM (1<<19)
@@ -211,6 +212,7 @@ struct opcode {
211 const struct group_dual *gdual; 212 const struct group_dual *gdual;
212 const struct gprefix *gprefix; 213 const struct gprefix *gprefix;
213 const struct escape *esc; 214 const struct escape *esc;
215 const struct instr_dual *idual;
214 void (*fastop)(struct fastop *fake); 216 void (*fastop)(struct fastop *fake);
215 } u; 217 } u;
216 int (*check_perm)(struct x86_emulate_ctxt *ctxt); 218 int (*check_perm)(struct x86_emulate_ctxt *ctxt);
@@ -233,6 +235,11 @@ struct escape {
233 struct opcode high[64]; 235 struct opcode high[64];
234}; 236};
235 237
238struct instr_dual {
239 struct opcode mod012;
240 struct opcode mod3;
241};
242
236/* EFLAGS bit definitions. */ 243/* EFLAGS bit definitions. */
237#define EFLG_ID (1<<21) 244#define EFLG_ID (1<<21)
238#define EFLG_VIP (1<<20) 245#define EFLG_VIP (1<<20)
@@ -3679,6 +3686,7 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
3679#define EXT(_f, _e) { .flags = ((_f) | RMExt), .u.group = (_e) } 3686#define EXT(_f, _e) { .flags = ((_f) | RMExt), .u.group = (_e) }
3680#define G(_f, _g) { .flags = ((_f) | Group | ModRM), .u.group = (_g) } 3687#define G(_f, _g) { .flags = ((_f) | Group | ModRM), .u.group = (_g) }
3681#define GD(_f, _g) { .flags = ((_f) | GroupDual | ModRM), .u.gdual = (_g) } 3688#define GD(_f, _g) { .flags = ((_f) | GroupDual | ModRM), .u.gdual = (_g) }
3689#define ID(_f, _i) { .flags = ((_f) | InstrDual | ModRM), .u.idual = (_i) }
3682#define E(_f, _e) { .flags = ((_f) | Escape | ModRM), .u.esc = (_e) } 3690#define E(_f, _e) { .flags = ((_f) | Escape | ModRM), .u.esc = (_e) }
3683#define I(_f, _e) { .flags = (_f), .u.execute = (_e) } 3691#define I(_f, _e) { .flags = (_f), .u.execute = (_e) }
3684#define F(_f, _e) { .flags = (_f) | Fastop, .u.fastop = (_e) } 3692#define F(_f, _e) { .flags = (_f) | Fastop, .u.fastop = (_e) }
@@ -3840,8 +3848,12 @@ static const struct gprefix pfx_0f_6f_0f_7f = {
3840 I(Mmx, em_mov), I(Sse | Aligned, em_mov), N, I(Sse | Unaligned, em_mov), 3848 I(Mmx, em_mov), I(Sse | Aligned, em_mov), N, I(Sse | Unaligned, em_mov),
3841}; 3849};
3842 3850
3851static const struct instr_dual instr_dual_0f_2b = {
3852 I(0, em_mov), N
3853};
3854
3843static const struct gprefix pfx_0f_2b = { 3855static const struct gprefix pfx_0f_2b = {
3844 I(0, em_mov), I(0, em_mov), N, N, 3856 ID(0, &instr_dual_0f_2b), ID(0, &instr_dual_0f_2b), N, N,
3845}; 3857};
3846 3858
3847static const struct gprefix pfx_0f_28_0f_29 = { 3859static const struct gprefix pfx_0f_28_0f_29 = {
@@ -3915,6 +3927,10 @@ static const struct escape escape_dd = { {
3915 N, N, N, N, N, N, N, N, 3927 N, N, N, N, N, N, N, N,
3916} }; 3928} };
3917 3929
3930static const struct instr_dual instr_dual_0f_c3 = {
3931 I(DstMem | SrcReg | ModRM | No16 | Mov, em_mov), N
3932};
3933
3918static const struct opcode opcode_table[256] = { 3934static const struct opcode opcode_table[256] = {
3919 /* 0x00 - 0x07 */ 3935 /* 0x00 - 0x07 */
3920 F6ALU(Lock, em_add), 3936 F6ALU(Lock, em_add),
@@ -4117,7 +4133,7 @@ static const struct opcode twobyte_table[256] = {
4117 D(DstReg | SrcMem8 | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov), 4133 D(DstReg | SrcMem8 | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
4118 /* 0xC0 - 0xC7 */ 4134 /* 0xC0 - 0xC7 */
4119 F2bv(DstMem | SrcReg | ModRM | SrcWrite | Lock, em_xadd), 4135 F2bv(DstMem | SrcReg | ModRM | SrcWrite | Lock, em_xadd),
4120 N, I(DstMem | SrcReg | ModRM | No16 | Mov, em_mov), 4136 N, ID(0, &instr_dual_0f_c3),
4121 N, N, N, GD(0, &group9), 4137 N, N, N, GD(0, &group9),
4122 /* 0xC8 - 0xCF */ 4138 /* 0xC8 - 0xCF */
4123 X8(I(DstReg, em_bswap)), 4139 X8(I(DstReg, em_bswap)),
@@ -4130,12 +4146,20 @@ static const struct opcode twobyte_table[256] = {
4130 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N 4146 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N
4131}; 4147};
4132 4148
4149static const struct instr_dual instr_dual_0f_38_f0 = {
4150 I(DstReg | SrcMem | Mov, em_movbe), N
4151};
4152
4153static const struct instr_dual instr_dual_0f_38_f1 = {
4154 I(DstMem | SrcReg | Mov, em_movbe), N
4155};
4156
4133static const struct gprefix three_byte_0f_38_f0 = { 4157static const struct gprefix three_byte_0f_38_f0 = {
4134 I(DstReg | SrcMem | Mov, em_movbe), N, N, N 4158 ID(0, &instr_dual_0f_38_f0), N, N, N
4135}; 4159};
4136 4160
4137static const struct gprefix three_byte_0f_38_f1 = { 4161static const struct gprefix three_byte_0f_38_f1 = {
4138 I(DstMem | SrcReg | Mov, em_movbe), N, N, N 4162 ID(0, &instr_dual_0f_38_f1), N, N, N
4139}; 4163};
4140 4164
4141/* 4165/*
@@ -4536,6 +4560,12 @@ done_prefixes:
4536 else 4560 else
4537 opcode = opcode.u.esc->op[(ctxt->modrm >> 3) & 7]; 4561 opcode = opcode.u.esc->op[(ctxt->modrm >> 3) & 7];
4538 break; 4562 break;
4563 case InstrDual:
4564 if ((ctxt->modrm >> 6) == 3)
4565 opcode = opcode.u.idual->mod3;
4566 else
4567 opcode = opcode.u.idual->mod012;
4568 break;
4539 default: 4569 default:
4540 return EMULATION_FAILED; 4570 return EMULATION_FAILED;
4541 } 4571 }