Re: [PATCH v3 08/18] KVM: x86/pmu: Switch to bitmask-based KVM PMU capabilities

From: Chen, Zide

Date: Mon Nov 09 2026 - 16:22:35 EST




On 11/6/2026 2:05 PM, Yosry Ahmed wrote:

>> @@ -1903,7 +1911,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
>>
>> cpuid_entry_override(entry, CPUID_8000_0022_EAX);
>>
>> - ebx.split.num_core_pmc = kvm_pmu_cap.num_counters_gp;
>> + ebx.split.num_core_pmc = hweight64(kvm_pmu_cap.cntr_mask64);
>
> Should this be the number of contiguous counters?

Yes, to match the Intel code, and to be defensive, I may update it to this:

--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -1903,7 +1911,10 @@ static inline int __do_cpuid_func(struct
kvm_cpuid_array *array, u32 function)

cpuid_entry_override(entry, CPUID_8000_0022_EAX);

- ebx.split.num_core_pmc = hweight64(kvm_pmu_cap.cntr_mask64);
+ /* Contiguous GP counters only. */
+ ebx.split.num_core_pmc =
+ find_first_zero_bit(kvm_pmu_cap.cntr_mask,
+ KVM_MAX_NR_GP_COUNTERS);

And replace other places of hweight64(kvm_pmu_cap.cntr_mask64) to
find_first_zero_bit() in AMD code.

>
>> entry->ebx = ebx.full;
>> break;
>> }
> [..]
>> @@ -516,7 +517,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
>> union cpuid10_edx edx;
>> u64 perf_capabilities;
>> u64 fixed_mask;
>> - int nr_gp_counters;
>> + int nr_gp_counters, nr_fixed_counters;
>> u64 counter_rsvd;
>>
>> if (!lbr_desc)
>> @@ -550,16 +551,25 @@ 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);
>>
>> - fixed_mask = BIT_ULL(edx.split.num_counters_fixed) - 1;
>> - fixed_mask &= BIT_ULL(kvm_pmu_cap.num_counters_fixed) - 1;
>> + /*
>> + * CPUID.0AH:EDX[4:0] can only enumerate contiguous counters. Clamp the
>> + * value to the number of contiguous fixed counters supported by KVM.
>> + */
>> + nr_fixed_counters = min_t(int, edx.split.num_counters_fixed,
>> + find_first_zero_bit(kvm_pmu_cap.fixed_cntr_mask,
>> + KVM_MAX_NR_FIXED_COUNTERS));
>> +
>> + fixed_mask = BIT_ULL(nr_fixed_counters) - 1;
>> + fixed_mask &= kvm_pmu_cap.fixed_cntr_mask64;
>
> Isn't nr_fixed_counters already clamped to the number of contiguous bits
> in fixed_cntr_mask?

Yes, you are right.
I will drop this redundant '&=' statement from this patch:

>
>>
>> /*
>> - * The number of counters comes from guest CPUID data. Clamp the value
>> - * to avoid a shift-by-64 in BIT_ULL().
>> + * CPUID.0AH:EAX[15:8] can only enumerate contiguous counters. Clamp the
>> + * value to the number of contiguous GP counters supported by KVM.
>> */
>> - nr_gp_counters = min_t(int, eax.split.num_counters, X86_PMC_IDX_MAX - 1);
>> - pmu->pmc_exists64 = (BIT_ULL(nr_gp_counters) - 1) &
>> - (BIT_ULL(kvm_pmu_cap.num_counters_gp) - 1);
>> + nr_gp_counters = min_t(int, eax.split.num_counters,
>> + find_first_zero_bit(kvm_pmu_cap.cntr_mask,
>> + KVM_MAX_NR_GP_COUNTERS));
>> + pmu->pmc_exists64 = BIT_ULL(nr_gp_counters) - 1;
>>
>> entry = kvm_find_cpuid_entry_index(vcpu, 7, 0);