Commit c6462363 authored by Like Xu's avatar Like Xu Committed by Paolo Bonzini
Browse files

KVM: vmx/pmu: Add PMU_CAP_LBR_FMT check when guest LBR is enabled



Usespace could set the bits [0, 5] of the IA32_PERF_CAPABILITIES
MSR which tells about the record format stored in the LBR records.

The LBR will be enabled on the guest if host perf supports LBR
(checked via x86_perf_get_lbr()) and the vcpu model is compatible
with the host one.

Signed-off-by: default avatarLike Xu <like.xu@linux.intel.com>
Message-Id: <20210201051039.255478-4-like.xu@linux.intel.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 9c9520ce
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -387,7 +387,12 @@ static inline u64 vmx_get_perf_capabilities(void)

static inline u64 vmx_supported_debugctl(void)
{
	return 0;
	u64 debugctl = 0;

	if (vmx_get_perf_capabilities() & PMU_CAP_LBR_FMT)
		debugctl |= DEBUGCTLMSR_LBR;

	return debugctl;
}

#endif /* __KVM_X86_VMX_CAPS_H */
+7 −0
Original line number Diff line number Diff line
@@ -183,6 +183,13 @@ bool intel_pmu_lbr_is_compatible(struct kvm_vcpu *vcpu)
	return boot_cpu_data.x86_model == guest_cpuid_model(vcpu);
}

bool intel_pmu_lbr_is_enabled(struct kvm_vcpu *vcpu)
{
	struct x86_pmu_lbr *lbr = vcpu_to_lbr_records(vcpu);

	return lbr->nr && (vcpu_get_perf_capabilities(vcpu) & PMU_CAP_LBR_FMT);
}

static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
{
	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
+11 −1
Original line number Diff line number Diff line
@@ -1950,6 +1950,16 @@ static u64 nested_vmx_truncate_sysenter_addr(struct kvm_vcpu *vcpu,
	return (unsigned long)data;
}

static u64 vcpu_supported_debugctl(struct kvm_vcpu *vcpu)
{
	u64 debugctl = vmx_supported_debugctl();

	if (!intel_pmu_lbr_is_enabled(vcpu))
		debugctl &= ~DEBUGCTLMSR_LBR;

	return debugctl;
}

/*
 * Writes msr value into the appropriate "register".
 * Returns 0 on success, non-0 otherwise.
@@ -2001,7 +2011,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
		vmcs_writel(GUEST_SYSENTER_ESP, data);
		break;
	case MSR_IA32_DEBUGCTLMSR: {
		u64 invalid = data & ~vmx_supported_debugctl();
		u64 invalid = data & ~vcpu_supported_debugctl(vcpu);
		if (invalid & (DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR)) {
			if (report_ignored_msrs)
				vcpu_unimpl(vcpu, "%s: BTF|LBR in IA32_DEBUGCTLMSR 0x%llx, nop\n",
+1 −0
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ union vmx_exit_reason {
#define vcpu_to_lbr_records(vcpu) (&to_vmx(vcpu)->lbr_desc.records)

bool intel_pmu_lbr_is_compatible(struct kvm_vcpu *vcpu);
bool intel_pmu_lbr_is_enabled(struct kvm_vcpu *vcpu);

struct lbr_desc {
	/* Basic info about guest LBR records. */