Skip to content

Commit

Permalink
KVM: SVM: Add intercept checks for SVM instructions
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Joerg Roedel authored and Avi Kivity committed May 11, 2011
1 parent dee6bb7 commit 01de8b0
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 1 deletion.
44 changes: 43 additions & 1 deletion arch/x86/kvm/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
#define GroupDual (1<<15) /* Alternate decoding of mod == 3 */
#define Prefix (1<<16) /* Instruction varies with 66/f2/f3 prefix */
#define Sse (1<<17) /* SSE Vector instruction */
#define RMExt (1<<18) /* Opcode extension in ModRM r/m if mod == 3 */
/* Misc flags */
#define Prot (1<<21) /* instruction generates #UD if not in prot-mode */
#define VendorSpecific (1<<22) /* Vendor specific instruction */
Expand Down Expand Up @@ -2580,11 +2581,35 @@ static int check_dr_write(struct x86_emulate_ctxt *ctxt)
return check_dr_read(ctxt);
}

static int check_svme(struct x86_emulate_ctxt *ctxt)
{
u64 efer;

ctxt->ops->get_msr(ctxt->vcpu, MSR_EFER, &efer);

if (!(efer & EFER_SVME))
return emulate_ud(ctxt);

return X86EMUL_CONTINUE;
}

static int check_svme_pa(struct x86_emulate_ctxt *ctxt)
{
u64 rax = kvm_register_read(ctxt->vcpu, VCPU_REGS_RAX);

/* Valid physical address? */
if (rax & 0xffff000000000000)
return emulate_gp(ctxt, 0);

return check_svme(ctxt);
}

#define D(_y) { .flags = (_y) }
#define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i }
#define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \
.check_perm = (_p) }
#define N D(0)
#define EXT(_f, _e) { .flags = ((_f) | RMExt), .u.group = (_e) }
#define G(_f, _g) { .flags = ((_f) | Group), .u.group = (_g) }
#define GD(_f, _g) { .flags = ((_f) | Group | GroupDual), .u.gdual = (_g) }
#define I(_f, _e) { .flags = (_f), .u.execute = (_e) }
Expand All @@ -2602,6 +2627,16 @@ static int check_dr_write(struct x86_emulate_ctxt *ctxt)
D2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock), \
D2bv(((_f) & ~Lock) | DstAcc | SrcImm)

static struct opcode group7_rm3[] = {
DIP(SrcNone | ModRM | Prot | Priv, vmrun, check_svme_pa),
DIP(SrcNone | ModRM | Prot , vmmcall, check_svme),
DIP(SrcNone | ModRM | Prot | Priv, vmload, check_svme_pa),
DIP(SrcNone | ModRM | Prot | Priv, vmsave, check_svme_pa),
DIP(SrcNone | ModRM | Prot | Priv, stgi, check_svme),
DIP(SrcNone | ModRM | Prot | Priv, clgi, check_svme),
DIP(SrcNone | ModRM | Prot | Priv, skinit, check_svme),
DIP(SrcNone | ModRM | Prot | Priv, invlpga, check_svme),
};

static struct opcode group1[] = {
X7(D(Lock)), N
Expand Down Expand Up @@ -2647,7 +2682,7 @@ static struct group_dual group7 = { {
DI(SrcMem | ModRM | ByteOp | Priv | NoAccess, invlpg),
}, {
D(SrcNone | ModRM | Priv | VendorSpecific), N,
N, D(SrcNone | ModRM | Priv | VendorSpecific),
N, EXT(0, group7_rm3),
DI(SrcNone | ModRM | DstMem | Mov, smsw), N,
DI(SrcMem16 | ModRM | Mov | Priv, lmsw), N,
} };
Expand Down Expand Up @@ -2853,6 +2888,7 @@ static struct opcode twobyte_table[256] = {
#undef GD
#undef I
#undef GP
#undef EXT

#undef D2bv
#undef I2bv
Expand Down Expand Up @@ -3030,6 +3066,12 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
opcode = g_mod3[goffset];
else
opcode = g_mod012[goffset];

if (opcode.flags & RMExt) {
goffset = c->modrm & 7;
opcode = opcode.u.group[goffset];
}

c->d |= opcode.flags;
}

Expand Down
8 changes: 8 additions & 0 deletions arch/x86/kvm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3892,6 +3892,14 @@ static struct __x86_intercept {
[x86_intercept_sidt] = POST_EX(SVM_EXIT_IDTR_READ),
[x86_intercept_lgdt] = POST_EX(SVM_EXIT_GDTR_WRITE),
[x86_intercept_lidt] = POST_EX(SVM_EXIT_IDTR_WRITE),
[x86_intercept_vmrun] = POST_EX(SVM_EXIT_VMRUN),
[x86_intercept_vmmcall] = POST_EX(SVM_EXIT_VMMCALL),
[x86_intercept_vmload] = POST_EX(SVM_EXIT_VMLOAD),
[x86_intercept_vmsave] = POST_EX(SVM_EXIT_VMSAVE),
[x86_intercept_stgi] = POST_EX(SVM_EXIT_STGI),
[x86_intercept_clgi] = POST_EX(SVM_EXIT_CLGI),
[x86_intercept_skinit] = POST_EX(SVM_EXIT_SKINIT),
[x86_intercept_invlpga] = POST_EX(SVM_EXIT_INVLPGA),
};

#undef POST_EX
Expand Down

0 comments on commit 01de8b0

Please sign in to comment.