Commit c49aa983 authored by Sean Christopherson's avatar Sean Christopherson
Browse files

KVM: x86/pmu: Restrict GLOBAL_{CTRL,STATUS}, fixed PMCs, and PEBS to PMU v2+



Restrict support for GLOBAL_CTRL, GLOBAL_STATUS, fixed PMCs, and PEBS to
v2 or later vPMUs.  The SDM explicitly states that GLOBAL_{CTRL,STATUS} and
fixed counters were introduced with PMU v2, and PEBS has hard dependencies
on fixed counters and the bitmap MSR layouts established by PMU v2.

Reported-by: default avatarDapeng Mi <dapeng1.mi@linux.intel.com>
Tested-by: default avatarXudong Hao <xudong.hao@intel.com>
Link: https://lore.kernel.org/r/20250806195706.1650976-32-seanjc@google.com


Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
parent 9bae7a08
Loading
Loading
Loading
Loading
+25 −26
Original line number Diff line number Diff line
@@ -541,15 +541,32 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
				      kvm_pmu_cap.events_mask_len);
	pmu->available_event_types = ~entry->ebx & (BIT_ULL(eax.split.mask_length) - 1);

	if (pmu->version == 1) {
		pmu->nr_arch_fixed_counters = 0;
	} else {
	entry = kvm_find_cpuid_entry_index(vcpu, 7, 0);
	if (entry &&
	    (boot_cpu_has(X86_FEATURE_HLE) || boot_cpu_has(X86_FEATURE_RTM)) &&
	    (entry->ebx & (X86_FEATURE_HLE|X86_FEATURE_RTM))) {
		pmu->reserved_bits ^= HSW_IN_TX;
		pmu->raw_event_mask |= (HSW_IN_TX|HSW_IN_TX_CHECKPOINTED);
	}

	perf_capabilities = vcpu_get_perf_capabilities(vcpu);
	if (intel_pmu_lbr_is_compatible(vcpu) &&
	    (perf_capabilities & PERF_CAP_LBR_FMT))
		memcpy(&lbr_desc->records, &vmx_lbr_caps, sizeof(vmx_lbr_caps));
	else
		lbr_desc->records.nr = 0;

	if (lbr_desc->records.nr)
		bitmap_set(pmu->all_valid_pmc_idx, INTEL_PMC_IDX_FIXED_VLBR, 1);

	if (pmu->version == 1)
		return;

	pmu->nr_arch_fixed_counters = min_t(int, edx.split.num_counters_fixed,
					    kvm_pmu_cap.num_counters_fixed);
	edx.split.bit_width_fixed = min_t(int, edx.split.bit_width_fixed,
					  kvm_pmu_cap.bit_width_fixed);
	pmu->counter_bitmask[KVM_PMC_FIXED] = BIT_ULL(edx.split.bit_width_fixed) - 1;
	}

	intel_pmu_enable_fixed_counter_bits(pmu, INTEL_FIXED_0_KERNEL |
						 INTEL_FIXED_0_USER |
@@ -571,24 +588,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
		pmu->global_status_rsvd &=
				~MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI;

	entry = kvm_find_cpuid_entry_index(vcpu, 7, 0);
	if (entry &&
	    (boot_cpu_has(X86_FEATURE_HLE) || boot_cpu_has(X86_FEATURE_RTM)) &&
	    (entry->ebx & (X86_FEATURE_HLE|X86_FEATURE_RTM))) {
		pmu->reserved_bits ^= HSW_IN_TX;
		pmu->raw_event_mask |= (HSW_IN_TX|HSW_IN_TX_CHECKPOINTED);
	}

	perf_capabilities = vcpu_get_perf_capabilities(vcpu);
	if (intel_pmu_lbr_is_compatible(vcpu) &&
	    (perf_capabilities & PERF_CAP_LBR_FMT))
		memcpy(&lbr_desc->records, &vmx_lbr_caps, sizeof(vmx_lbr_caps));
	else
		lbr_desc->records.nr = 0;

	if (lbr_desc->records.nr)
		bitmap_set(pmu->all_valid_pmc_idx, INTEL_PMC_IDX_FIXED_VLBR, 1);

	if (perf_capabilities & PERF_CAP_PEBS_FORMAT) {
		if (perf_capabilities & PERF_CAP_PEBS_BASELINE) {
			pmu->pebs_enable_rsvd = counter_rsvd;