Skip to content

Commit

Permalink
KVM: SVM: Add intercept checks for remaining group7 instructions
Browse files Browse the repository at this point in the history
This patch implements the emulator intercept checks for the
RDTSCP, MONITOR, and MWAIT 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 01de8b0 commit d7eb820
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
25 changes: 23 additions & 2 deletions arch/x86/kvm/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -2604,6 +2604,16 @@ static int check_svme_pa(struct x86_emulate_ctxt *ctxt)
return check_svme(ctxt);
}

static int check_rdtsc(struct x86_emulate_ctxt *ctxt)
{
u64 cr4 = ctxt->ops->get_cr(4, ctxt->vcpu);

if (cr4 & X86_CR4_TSD && ctxt->ops->cpl(ctxt->vcpu))
return emulate_ud(ctxt);

return X86EMUL_CONTINUE;
}

#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, \
Expand All @@ -2627,6 +2637,12 @@ static int check_svme_pa(struct x86_emulate_ctxt *ctxt)
D2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock), \
D2bv(((_f) & ~Lock) | DstAcc | SrcImm)

static struct opcode group7_rm1[] = {
DI(SrcNone | ModRM | Priv, monitor),
DI(SrcNone | ModRM | Priv, mwait),
N, N, N, N, N, N,
};

static struct opcode group7_rm3[] = {
DIP(SrcNone | ModRM | Prot | Priv, vmrun, check_svme_pa),
DIP(SrcNone | ModRM | Prot , vmmcall, check_svme),
Expand All @@ -2638,6 +2654,11 @@ static struct opcode group7_rm3[] = {
DIP(SrcNone | ModRM | Prot | Priv, invlpga, check_svme),
};

static struct opcode group7_rm7[] = {
N,
DIP(SrcNone | ModRM, rdtscp, check_rdtsc),
N, N, N, N, N, N,
};
static struct opcode group1[] = {
X7(D(Lock)), N
};
Expand Down Expand Up @@ -2681,10 +2702,10 @@ static struct group_dual group7 = { {
DI(SrcMem16 | ModRM | Mov | Priv, lmsw),
DI(SrcMem | ModRM | ByteOp | Priv | NoAccess, invlpg),
}, {
D(SrcNone | ModRM | Priv | VendorSpecific), N,
D(SrcNone | ModRM | Priv | VendorSpecific), EXT(0, group7_rm1),
N, EXT(0, group7_rm3),
DI(SrcNone | ModRM | DstMem | Mov, smsw), N,
DI(SrcMem16 | ModRM | Mov | Priv, lmsw), N,
DI(SrcMem16 | ModRM | Mov | Priv, lmsw), EXT(0, group7_rm7),
} };

static struct opcode group8[] = {
Expand Down
7 changes: 7 additions & 0 deletions arch/x86/kvm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3871,6 +3871,9 @@ static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
#define POST_EX(exit) { .exit_code = (exit), \
.stage = X86_ICPT_POST_EXCEPT, \
.valid = true }
#define POST_MEM(exit) { .exit_code = (exit), \
.stage = X86_ICPT_POST_MEMACCESS, \
.valid = true }

static struct __x86_intercept {
u32 exit_code;
Expand Down Expand Up @@ -3900,9 +3903,13 @@ static struct __x86_intercept {
[x86_intercept_clgi] = POST_EX(SVM_EXIT_CLGI),
[x86_intercept_skinit] = POST_EX(SVM_EXIT_SKINIT),
[x86_intercept_invlpga] = POST_EX(SVM_EXIT_INVLPGA),
[x86_intercept_rdtscp] = POST_EX(SVM_EXIT_RDTSCP),
[x86_intercept_monitor] = POST_MEM(SVM_EXIT_MONITOR),
[x86_intercept_mwait] = POST_EX(SVM_EXIT_MWAIT),
};

#undef POST_EX
#undef POST_MEM

static int svm_check_intercept(struct kvm_vcpu *vcpu,
struct x86_instruction_info *info,
Expand Down

0 comments on commit d7eb820

Please sign in to comment.