aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2011-04-04 06:39:31 -0400
committerAvi Kivity <avi@redhat.com>2011-05-11 07:57:02 -0400
commit01de8b09e6068936f7f5e386cb85637cf926468c (patch)
tree4a192866e9dbf557fe91bed1a24a351a7292bd40 /arch/x86/kvm/emulate.c
parentdee6bb70e4ac0588c98cc4e661664f0653117f89 (diff)
KVM: SVM: Add intercept checks for SVM instructions
This patch adds the necessary code changes in the instruction emulator and the extensions to svm.c to implement intercept checks for the svm instructions. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 3ac830a135fd..a3aba9552b39 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -77,6 +77,7 @@
77#define GroupDual (1<<15) /* Alternate decoding of mod == 3 */ 77#define GroupDual (1<<15) /* Alternate decoding of mod == 3 */
78#define Prefix (1<<16) /* Instruction varies with 66/f2/f3 prefix */ 78#define Prefix (1<<16) /* Instruction varies with 66/f2/f3 prefix */
79#define Sse (1<<17) /* SSE Vector instruction */ 79#define Sse (1<<17) /* SSE Vector instruction */
80#define RMExt (1<<18) /* Opcode extension in ModRM r/m if mod == 3 */
80/* Misc flags */ 81/* Misc flags */
81#define Prot (1<<21) /* instruction generates #UD if not in prot-mode */ 82#define Prot (1<<21) /* instruction generates #UD if not in prot-mode */
82#define VendorSpecific (1<<22) /* Vendor specific instruction */ 83#define VendorSpecific (1<<22) /* Vendor specific instruction */
@@ -2580,11 +2581,35 @@ static int check_dr_write(struct x86_emulate_ctxt *ctxt)
2580 return check_dr_read(ctxt); 2581 return check_dr_read(ctxt);
2581} 2582}
2582 2583
2584static int check_svme(struct x86_emulate_ctxt *ctxt)
2585{
2586 u64 efer;
2587
2588 ctxt->ops->get_msr(ctxt->vcpu, MSR_EFER, &efer);
2589
2590 if (!(efer & EFER_SVME))
2591 return emulate_ud(ctxt);
2592
2593 return X86EMUL_CONTINUE;
2594}
2595
2596static int check_svme_pa(struct x86_emulate_ctxt *ctxt)
2597{
2598 u64 rax = kvm_register_read(ctxt->vcpu, VCPU_REGS_RAX);
2599
2600 /* Valid physical address? */
2601 if (rax & 0xffff000000000000)
2602 return emulate_gp(ctxt, 0);
2603
2604 return check_svme(ctxt);
2605}
2606
2583#define D(_y) { .flags = (_y) } 2607#define D(_y) { .flags = (_y) }
2584#define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i } 2608#define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i }
2585#define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \ 2609#define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \
2586 .check_perm = (_p) } 2610 .check_perm = (_p) }
2587#define N D(0) 2611#define N D(0)
2612#define EXT(_f, _e) { .flags = ((_f) | RMExt), .u.group = (_e) }
2588#define G(_f, _g) { .flags = ((_f) | Group), .u.group = (_g) } 2613#define G(_f, _g) { .flags = ((_f) | Group), .u.group = (_g) }
2589#define GD(_f, _g) { .flags = ((_f) | Group | GroupDual), .u.gdual = (_g) } 2614#define GD(_f, _g) { .flags = ((_f) | Group | GroupDual), .u.gdual = (_g) }
2590#define I(_f, _e) { .flags = (_f), .u.execute = (_e) } 2615#define I(_f, _e) { .flags = (_f), .u.execute = (_e) }
@@ -2602,6 +2627,16 @@ static int check_dr_write(struct x86_emulate_ctxt *ctxt)
2602 D2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock), \ 2627 D2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock), \
2603 D2bv(((_f) & ~Lock) | DstAcc | SrcImm) 2628 D2bv(((_f) & ~Lock) | DstAcc | SrcImm)
2604 2629
2630static struct opcode group7_rm3[] = {
2631 DIP(SrcNone | ModRM | Prot | Priv, vmrun, check_svme_pa),
2632 DIP(SrcNone | ModRM | Prot , vmmcall, check_svme),
2633 DIP(SrcNone | ModRM | Prot | Priv, vmload, check_svme_pa),
2634 DIP(SrcNone | ModRM | Prot | Priv, vmsave, check_svme_pa),
2635 DIP(SrcNone | ModRM | Prot | Priv, stgi, check_svme),
2636 DIP(SrcNone | ModRM | Prot | Priv, clgi, check_svme),
2637 DIP(SrcNone | ModRM | Prot | Priv, skinit, check_svme),
2638 DIP(SrcNone | ModRM | Prot | Priv, invlpga, check_svme),
2639};
2605 2640
2606static struct opcode group1[] = { 2641static struct opcode group1[] = {
2607 X7(D(Lock)), N 2642 X7(D(Lock)), N
@@ -2647,7 +2682,7 @@ static struct group_dual group7 = { {
2647 DI(SrcMem | ModRM | ByteOp | Priv | NoAccess, invlpg), 2682 DI(SrcMem | ModRM | ByteOp | Priv | NoAccess, invlpg),
2648}, { 2683}, {
2649 D(SrcNone | ModRM | Priv | VendorSpecific), N, 2684 D(SrcNone | ModRM | Priv | VendorSpecific), N,
2650 N, D(SrcNone | ModRM | Priv | VendorSpecific), 2685 N, EXT(0, group7_rm3),
2651 DI(SrcNone | ModRM | DstMem | Mov, smsw), N, 2686 DI(SrcNone | ModRM | DstMem | Mov, smsw), N,
2652 DI(SrcMem16 | ModRM | Mov | Priv, lmsw), N, 2687 DI(SrcMem16 | ModRM | Mov | Priv, lmsw), N,
2653} }; 2688} };
@@ -2853,6 +2888,7 @@ static struct opcode twobyte_table[256] = {
2853#undef GD 2888#undef GD
2854#undef I 2889#undef I
2855#undef GP 2890#undef GP
2891#undef EXT
2856 2892
2857#undef D2bv 2893#undef D2bv
2858#undef I2bv 2894#undef I2bv
@@ -3030,6 +3066,12 @@ done_prefixes:
3030 opcode = g_mod3[goffset]; 3066 opcode = g_mod3[goffset];
3031 else 3067 else
3032 opcode = g_mod012[goffset]; 3068 opcode = g_mod012[goffset];
3069
3070 if (opcode.flags & RMExt) {
3071 goffset = c->modrm & 7;
3072 opcode = opcode.u.group[goffset];
3073 }
3074
3033 c->d |= opcode.flags; 3075 c->d |= opcode.flags;
3034 } 3076 }
3035 3077