Commit fb6d4d34 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

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
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -293,13 +293,18 @@ static int __do_cpuid_ent_emulated(struct kvm_cpuid_entry2 *entry,
{
	switch (func) {
	case 0:
		entry->eax = 1;		/* only one leaf currently */
		entry->eax = 7;
		++*nent;
		break;
	case 1:
		entry->ecx = F(MOVBE);
		++*nent;
		break;
	case 7:
		entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
		if (index == 0)
			entry->ecx = F(RDPID);
		++*nent;
	default:
		break;
	}
+21 −1
Original line number Diff line number Diff line
@@ -3514,6 +3514,16 @@ static int em_cwd(struct x86_emulate_ctxt *ctxt)
	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)
{
	u64 tsc = 0;
@@ -4424,10 +4434,20 @@ static const struct opcode group8[] = {
	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 = { {
	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[] = {
+15 −0
Original line number Diff line number Diff line
@@ -11687,6 +11687,21 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
			       struct x86_instruction_info *info,
			       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;
}