Commit fb6d4d34 authored by Paolo Bonzini's avatar Paolo Bonzini

KVM: x86: emulate RDPID

This is encoded as F3 0F C7 /7 with a register argument.  The register
argument is the second array in the group9 GroupDual, while F3 is the
fourth element of a Prefix.
Reviewed-by: default avatarWanpeng Li <wanpeng.li@hotmail.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 0367f205
...@@ -293,13 +293,18 @@ static int __do_cpuid_ent_emulated(struct kvm_cpuid_entry2 *entry, ...@@ -293,13 +293,18 @@ static int __do_cpuid_ent_emulated(struct kvm_cpuid_entry2 *entry,
{ {
switch (func) { switch (func) {
case 0: case 0:
entry->eax = 1; /* only one leaf currently */ entry->eax = 7;
++*nent; ++*nent;
break; break;
case 1: case 1:
entry->ecx = F(MOVBE); entry->ecx = F(MOVBE);
++*nent; ++*nent;
break; break;
case 7:
entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
if (index == 0)
entry->ecx = F(RDPID);
++*nent;
default: default:
break; break;
} }
......
...@@ -3514,6 +3514,16 @@ static int em_cwd(struct x86_emulate_ctxt *ctxt) ...@@ -3514,6 +3514,16 @@ static int em_cwd(struct x86_emulate_ctxt *ctxt)
return X86EMUL_CONTINUE; return X86EMUL_CONTINUE;
} }
static int em_rdpid(struct x86_emulate_ctxt *ctxt)
{
u64 tsc_aux = 0;
if (ctxt->ops->get_msr(ctxt, MSR_TSC_AUX, &tsc_aux))
return emulate_gp(ctxt, 0);
ctxt->dst.val = tsc_aux;
return X86EMUL_CONTINUE;
}
static int em_rdtsc(struct x86_emulate_ctxt *ctxt) static int em_rdtsc(struct x86_emulate_ctxt *ctxt)
{ {
u64 tsc = 0; u64 tsc = 0;
...@@ -4424,10 +4434,20 @@ static const struct opcode group8[] = { ...@@ -4424,10 +4434,20 @@ static const struct opcode group8[] = {
F(DstMem | SrcImmByte | Lock | PageTable, em_btc), F(DstMem | SrcImmByte | Lock | PageTable, em_btc),
}; };
/*
* The "memory" destination is actually always a register, since we come
* from the register case of group9.
*/
static const struct gprefix pfx_0f_c7_7 = {
N, N, N, II(DstMem | ModRM | Op3264 | EmulateOnUD, em_rdpid, rdtscp),
};
static const struct group_dual group9 = { { static const struct group_dual group9 = { {
N, I(DstMem64 | Lock | PageTable, em_cmpxchg8b), N, N, N, N, N, N, N, I(DstMem64 | Lock | PageTable, em_cmpxchg8b), N, N, N, N, N, N,
}, { }, {
N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
GP(0, &pfx_0f_c7_7),
} }; } };
static const struct opcode group11[] = { static const struct opcode group11[] = {
......
...@@ -11687,6 +11687,21 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu, ...@@ -11687,6 +11687,21 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
struct x86_instruction_info *info, struct x86_instruction_info *info,
enum x86_intercept_stage stage) enum x86_intercept_stage stage)
{ {
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
/*
* RDPID causes #UD if disabled through secondary execution controls.
* Because it is marked as EmulateOnUD, we need to intercept it here.
*/
if (info->intercept == x86_intercept_rdtscp &&
!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
ctxt->exception.vector = UD_VECTOR;
ctxt->exception.error_code_valid = false;
return X86EMUL_PROPAGATE_FAULT;
}
/* TODO: check more intercepts... */
return X86EMUL_CONTINUE; return X86EMUL_CONTINUE;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment