aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2010-02-10 07:21:36 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2010-03-01 10:36:11 -0500
commitd380a5e4022a5c63a6c5ac631e48c752ba7f1e4f (patch)
tree06346e56054146b10e6669ea358c07d85333d544 /arch
parente92805ac1228626c59c865f2f4e9059b9fb8c97b (diff)
KVM: x86 emulator: Add LOCK prefix validity checking
Instructions which are not allowed to have LOCK prefix should generate #UD if one is used. [avi: fold opcode 82 fix from another patch] Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/emulate.c97
1 files changed, 56 insertions, 41 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index d63211169ac1..c2de9f03da84 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -76,6 +76,7 @@
76#define GroupDual (1<<15) /* Alternate decoding of mod == 3 */ 76#define GroupDual (1<<15) /* Alternate decoding of mod == 3 */
77#define GroupMask 0xff /* Group number stored in bits 0:7 */ 77#define GroupMask 0xff /* Group number stored in bits 0:7 */
78/* Misc flags */ 78/* Misc flags */
79#define Lock (1<<26) /* lock prefix is allowed for the instruction */
79#define Priv (1<<27) /* instruction generates #GP if current CPL != 0 */ 80#define Priv (1<<27) /* instruction generates #GP if current CPL != 0 */
80#define No64 (1<<28) 81#define No64 (1<<28)
81/* Source 2 operand type */ 82/* Source 2 operand type */
@@ -94,35 +95,35 @@ enum {
94 95
95static u32 opcode_table[256] = { 96static u32 opcode_table[256] = {
96 /* 0x00 - 0x07 */ 97 /* 0x00 - 0x07 */
97 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 98 ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
98 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, 99 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
99 ByteOp | DstAcc | SrcImm, DstAcc | SrcImm, 100 ByteOp | DstAcc | SrcImm, DstAcc | SrcImm,
100 ImplicitOps | Stack | No64, ImplicitOps | Stack | No64, 101 ImplicitOps | Stack | No64, ImplicitOps | Stack | No64,
101 /* 0x08 - 0x0F */ 102 /* 0x08 - 0x0F */
102 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 103 ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
103 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, 104 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
104 ByteOp | DstAcc | SrcImm, DstAcc | SrcImm, 105 ByteOp | DstAcc | SrcImm, DstAcc | SrcImm,
105 ImplicitOps | Stack | No64, 0, 106 ImplicitOps | Stack | No64, 0,
106 /* 0x10 - 0x17 */ 107 /* 0x10 - 0x17 */
107 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 108 ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
108 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, 109 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
109 ByteOp | DstAcc | SrcImm, DstAcc | SrcImm, 110 ByteOp | DstAcc | SrcImm, DstAcc | SrcImm,
110 ImplicitOps | Stack | No64, ImplicitOps | Stack | No64, 111 ImplicitOps | Stack | No64, ImplicitOps | Stack | No64,
111 /* 0x18 - 0x1F */ 112 /* 0x18 - 0x1F */
112 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 113 ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
113 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, 114 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
114 ByteOp | DstAcc | SrcImm, DstAcc | SrcImm, 115 ByteOp | DstAcc | SrcImm, DstAcc | SrcImm,
115 ImplicitOps | Stack | No64, ImplicitOps | Stack | No64, 116 ImplicitOps | Stack | No64, ImplicitOps | Stack | No64,
116 /* 0x20 - 0x27 */ 117 /* 0x20 - 0x27 */
117 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 118 ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
118 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, 119 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
119 DstAcc | SrcImmByte, DstAcc | SrcImm, 0, 0, 120 DstAcc | SrcImmByte, DstAcc | SrcImm, 0, 0,
120 /* 0x28 - 0x2F */ 121 /* 0x28 - 0x2F */
121 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 122 ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
122 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, 123 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
123 0, 0, 0, 0, 124 0, 0, 0, 0,
124 /* 0x30 - 0x37 */ 125 /* 0x30 - 0x37 */
125 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 126 ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
126 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, 127 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
127 0, 0, 0, 0, 128 0, 0, 0, 0,
128 /* 0x38 - 0x3F */ 129 /* 0x38 - 0x3F */
@@ -158,7 +159,7 @@ static u32 opcode_table[256] = {
158 Group | Group1_80, Group | Group1_81, 159 Group | Group1_80, Group | Group1_81,
159 Group | Group1_82, Group | Group1_83, 160 Group | Group1_82, Group | Group1_83,
160 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 161 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
161 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 162 ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
162 /* 0x88 - 0x8F */ 163 /* 0x88 - 0x8F */
163 ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov, 164 ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov,
164 ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, 165 ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
@@ -263,17 +264,18 @@ static u32 twobyte_table[256] = {
263 DstMem | SrcReg | Src2CL | ModRM, 0, 0, 264 DstMem | SrcReg | Src2CL | ModRM, 0, 0,
264 /* 0xA8 - 0xAF */ 265 /* 0xA8 - 0xAF */
265 ImplicitOps | Stack, ImplicitOps | Stack, 266 ImplicitOps | Stack, ImplicitOps | Stack,
266 0, DstMem | SrcReg | ModRM | BitOp, 267 0, DstMem | SrcReg | ModRM | BitOp | Lock,
267 DstMem | SrcReg | Src2ImmByte | ModRM, 268 DstMem | SrcReg | Src2ImmByte | ModRM,
268 DstMem | SrcReg | Src2CL | ModRM, 269 DstMem | SrcReg | Src2CL | ModRM,
269 ModRM, 0, 270 ModRM, 0,
270 /* 0xB0 - 0xB7 */ 271 /* 0xB0 - 0xB7 */
271 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0, 272 ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
272 DstMem | SrcReg | ModRM | BitOp, 273 0, DstMem | SrcReg | ModRM | BitOp | Lock,
273 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, 274 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
274 DstReg | SrcMem16 | ModRM | Mov, 275 DstReg | SrcMem16 | ModRM | Mov,
275 /* 0xB8 - 0xBF */ 276 /* 0xB8 - 0xBF */
276 0, 0, Group | Group8, DstMem | SrcReg | ModRM | BitOp, 277 0, 0,
278 Group | Group8, DstMem | SrcReg | ModRM | BitOp | Lock,
277 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, 279 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
278 DstReg | SrcMem16 | ModRM | Mov, 280 DstReg | SrcMem16 | ModRM | Mov,
279 /* 0xC0 - 0xCF */ 281 /* 0xC0 - 0xCF */
@@ -290,25 +292,41 @@ static u32 twobyte_table[256] = {
290 292
291static u32 group_table[] = { 293static u32 group_table[] = {
292 [Group1_80*8] = 294 [Group1_80*8] =
293 ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM, 295 ByteOp | DstMem | SrcImm | ModRM | Lock,
294 ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM, 296 ByteOp | DstMem | SrcImm | ModRM | Lock,
295 ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM, 297 ByteOp | DstMem | SrcImm | ModRM | Lock,
296 ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM, 298 ByteOp | DstMem | SrcImm | ModRM | Lock,
299 ByteOp | DstMem | SrcImm | ModRM | Lock,
300 ByteOp | DstMem | SrcImm | ModRM | Lock,
301 ByteOp | DstMem | SrcImm | ModRM | Lock,
302 ByteOp | DstMem | SrcImm | ModRM,
297 [Group1_81*8] = 303 [Group1_81*8] =
298 DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM, 304 DstMem | SrcImm | ModRM | Lock,
299 DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM, 305 DstMem | SrcImm | ModRM | Lock,
300 DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM, 306 DstMem | SrcImm | ModRM | Lock,
301 DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM, 307 DstMem | SrcImm | ModRM | Lock,
308 DstMem | SrcImm | ModRM | Lock,
309 DstMem | SrcImm | ModRM | Lock,
310 DstMem | SrcImm | ModRM | Lock,
311 DstMem | SrcImm | ModRM,
302 [Group1_82*8] = 312 [Group1_82*8] =
303 ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM, 313 ByteOp | DstMem | SrcImm | ModRM | Lock,
304 ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM, 314 ByteOp | DstMem | SrcImm | ModRM | Lock,
305 ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM, 315 ByteOp | DstMem | SrcImm | ModRM | Lock,
306 ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM, 316 ByteOp | DstMem | SrcImm | ModRM | Lock,
317 ByteOp | DstMem | SrcImm | ModRM | Lock,
318 ByteOp | DstMem | SrcImm | ModRM | Lock,
319 ByteOp | DstMem | SrcImm | ModRM | Lock,
320 ByteOp | DstMem | SrcImm | ModRM,
307 [Group1_83*8] = 321 [Group1_83*8] =
308 DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM, 322 DstMem | SrcImmByte | ModRM | Lock,
309 DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM, 323 DstMem | SrcImmByte | ModRM | Lock,
310 DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM, 324 DstMem | SrcImmByte | ModRM | Lock,
311 DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM, 325 DstMem | SrcImmByte | ModRM | Lock,
326 DstMem | SrcImmByte | ModRM | Lock,
327 DstMem | SrcImmByte | ModRM | Lock,
328 DstMem | SrcImmByte | ModRM | Lock,
329 DstMem | SrcImmByte | ModRM,
312 [Group1A*8] = 330 [Group1A*8] =
313 DstMem | SrcNone | ModRM | Mov | Stack, 0, 0, 0, 0, 0, 0, 0, 331 DstMem | SrcNone | ModRM | Mov | Stack, 0, 0, 0, 0, 0, 0, 0,
314 [Group3_Byte*8] = 332 [Group3_Byte*8] =
@@ -332,10 +350,10 @@ static u32 group_table[] = {
332 SrcMem16 | ModRM | Mov | Priv, SrcMem | ModRM | ByteOp | Priv, 350 SrcMem16 | ModRM | Mov | Priv, SrcMem | ModRM | ByteOp | Priv,
333 [Group8*8] = 351 [Group8*8] =
334 0, 0, 0, 0, 352 0, 0, 0, 0,
335 DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM, 353 DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM | Lock,
336 DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM, 354 DstMem | SrcImmByte | ModRM | Lock, DstMem | SrcImmByte | ModRM | Lock,
337 [Group9*8] = 355 [Group9*8] =
338 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 356 0, ImplicitOps | ModRM | Lock, 0, 0, 0, 0, 0, 0,
339}; 357};
340 358
341static u32 group2_table[] = { 359static u32 group2_table[] = {
@@ -1580,8 +1598,7 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt)
1580 u64 msr_data; 1598 u64 msr_data;
1581 1599
1582 /* syscall is not available in real mode */ 1600 /* syscall is not available in real mode */
1583 if (c->lock_prefix || ctxt->mode == X86EMUL_MODE_REAL 1601 if (ctxt->mode == X86EMUL_MODE_REAL || ctxt->mode == X86EMUL_MODE_VM86)
1584 || ctxt->mode == X86EMUL_MODE_VM86)
1585 return -1; 1602 return -1;
1586 1603
1587 setup_syscalls_segments(ctxt, &cs, &ss); 1604 setup_syscalls_segments(ctxt, &cs, &ss);
@@ -1629,10 +1646,6 @@ emulate_sysenter(struct x86_emulate_ctxt *ctxt)
1629 struct kvm_segment cs, ss; 1646 struct kvm_segment cs, ss;
1630 u64 msr_data; 1647 u64 msr_data;
1631 1648
1632 /* inject #UD if LOCK prefix is used */
1633 if (c->lock_prefix)
1634 return -1;
1635
1636 /* inject #GP if in real mode */ 1649 /* inject #GP if in real mode */
1637 if (ctxt->mode == X86EMUL_MODE_REAL) { 1650 if (ctxt->mode == X86EMUL_MODE_REAL) {
1638 kvm_inject_gp(ctxt->vcpu, 0); 1651 kvm_inject_gp(ctxt->vcpu, 0);
@@ -1694,10 +1707,6 @@ emulate_sysexit(struct x86_emulate_ctxt *ctxt)
1694 u64 msr_data; 1707 u64 msr_data;
1695 int usermode; 1708 int usermode;
1696 1709
1697 /* inject #UD if LOCK prefix is used */
1698 if (c->lock_prefix)
1699 return -1;
1700
1701 /* inject #GP if in real mode or Virtual 8086 mode */ 1710 /* inject #GP if in real mode or Virtual 8086 mode */
1702 if (ctxt->mode == X86EMUL_MODE_REAL || 1711 if (ctxt->mode == X86EMUL_MODE_REAL ||
1703 ctxt->mode == X86EMUL_MODE_VM86) { 1712 ctxt->mode == X86EMUL_MODE_VM86) {
@@ -1819,6 +1828,12 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
1819 memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs); 1828 memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
1820 saved_eip = c->eip; 1829 saved_eip = c->eip;
1821 1830
1831 /* LOCK prefix is allowed only with some instructions */
1832 if (c->lock_prefix && !(c->d & Lock)) {
1833 kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
1834 goto done;
1835 }
1836
1822 /* Privileged instruction can be executed only in CPL=0 */ 1837 /* Privileged instruction can be executed only in CPL=0 */
1823 if ((c->d & Priv) && kvm_x86_ops->get_cpl(ctxt->vcpu)) { 1838 if ((c->d & Priv) && kvm_x86_ops->get_cpl(ctxt->vcpu)) {
1824 kvm_inject_gp(ctxt->vcpu, 0); 1839 kvm_inject_gp(ctxt->vcpu, 0);