Kernel KVM virtualization development
 help / color / mirror / Atom feed
From: "Mi, Dapeng" <dapeng1.mi@linux.intel.com>
To: Zide Chen <zide.chen@intel.com>,
	Sean Christopherson <seanjc@google.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Peter Zijlstra <peterz@infradead.org>
Cc: kvm@vger.kernel.org, Andi Kleen <ak@linux.intel.com>,
	Jim Mattson <jmattson@google.com>,
	Stephane Eranian <eranian@google.com>,
	linux-kernel@vger.kernel.org, Mingwei Zhang <mizhang@google.com>,
	Das Sandipan <Sandipan.Das@amd.com>,
	Shukla Manali <Manali.Shukla@amd.com>,
	Xudong Hao <xudong.hao@intel.com>
Subject: Re: [PATCH v2 06/16] KVM: x86/pmu: Drop nr_arch_{gp,fixed}_counters from kvm_pmu
Date: Tue, 1 Sep 2026 11:07:27 +0800	[thread overview]
Message-ID: <2bb5aa22-42f0-4d65-a1f9-572084ba2eec@linux.intel.com> (raw)
In-Reply-To: <20260827223755.143247-7-zide.chen@intel.com>

Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>

On 8/28/2026 6:37 AM, Zide Chen wrote:
> From: Dapeng Mi <dapeng1.mi@linux.intel.com>
>
> This is a preparatory step toward fully bitmap-based PMU capability
> handling. Later patches switch KVM's view of host PMU capabilities from
> counter counts to counter bitmaps.
>
> Populate and use pmc_exists directly when walking guest-visible PMCs,
> instead of relying on pmu->nr_arch_{gp,fixed}_counters as intermediate
> state.
>
> Iterate counters via the newly added pmc_exists based helpers, and
> remove the now-redundant nr_arch_{gp,fixed}_counters fields from struct
> kvm_pmu.
>
> Note: {vmx,svm}_recalc_pmu_msr_intercepts() may leave stale intercepts
> on GP MSRs after CPUID narrowing. This corner case is resolved by the
> following patch: "KVM: x86/pmu: Switch to bitmask-based KVM PMU
> capabilities".
>
> Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
> Co-developed-by: Zide Chen <zide.chen@intel.com>
> Signed-off-by: Zide Chen <zide.chen@intel.com>
> ---
> v2:
> - Fix AMD legacy PMU MSR intercept handling for guest PMU
>   narrowing reconfiguration by adding for_each_clear_bit_from().
> - Re-word the stale interception changelog part.
> ---
>  arch/x86/include/asm/kvm_host.h |  2 --
>  arch/x86/kvm/pmu.c              | 26 +++++++++----------
>  arch/x86/kvm/svm/pmu.c          | 25 ++++++++----------
>  arch/x86/kvm/svm/svm.c          |  8 ++++--
>  arch/x86/kvm/vmx/nested.c       |  6 +++--
>  arch/x86/kvm/vmx/pmu_intel.c    | 46 ++++++++++++++++++++++-----------
>  arch/x86/kvm/vmx/vmx.c          |  6 +++--
>  7 files changed, 68 insertions(+), 51 deletions(-)
>
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 49a8a2e9cee0..717ba98c08c9 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -569,8 +569,6 @@ struct kvm_pmc {
>  
>  struct kvm_pmu {
>  	u8 version;
> -	unsigned nr_arch_gp_counters;
> -	unsigned nr_arch_fixed_counters;
>  	unsigned available_event_types;
>  	u64 fixed_ctr_ctrl;
>  	u64 fixed_ctr_ctrl_hw;
> diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
> index 964e74bdaaa7..b0fcd0a538d2 100644
> --- a/arch/x86/kvm/pmu.c
> +++ b/arch/x86/kvm/pmu.c
> @@ -785,8 +785,8 @@ static bool kvm_need_any_pmc_intercept(struct kvm_vcpu *vcpu)
>  	 * KVM's capabilities are constrained based on KVM support, i.e. KVM's
>  	 * capabilities themselves may be a subset of hardware capabilities.
>  	 */
> -	return pmu->nr_arch_gp_counters != kvm_host_pmu.num_counters_gp ||
> -	       pmu->nr_arch_fixed_counters != kvm_host_pmu.num_counters_fixed;
> +	return kvm_gp_pmc_mask(pmu) != BIT_ULL(kvm_host_pmu.num_counters_gp) - 1 ||
> +	       kvm_fixed_pmc_mask(pmu) != BIT_ULL(kvm_host_pmu.num_counters_fixed) - 1;
>  }
>  
>  bool kvm_need_perf_global_ctrl_intercept(struct kvm_vcpu *vcpu)
> @@ -985,8 +985,6 @@ void kvm_pmu_refresh(struct kvm_vcpu *vcpu)
>  	kvm_pmu_reset(vcpu);
>  
>  	pmu->version = 0;
> -	pmu->nr_arch_gp_counters = 0;
> -	pmu->nr_arch_fixed_counters = 0;
>  	pmu->counter_bitmask[KVM_PMC_GP] = 0;
>  	pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
>  	/*
> @@ -1014,16 +1012,12 @@ void kvm_pmu_refresh(struct kvm_vcpu *vcpu)
>  	 * in the global controls).  Emulate that behavior when refreshing the
>  	 * PMU so that userspace doesn't need to manually set PERF_GLOBAL_CTRL.
>  	 */
> -	if (pmu->nr_arch_gp_counters &&
> +	if (kvm_gp_pmc_mask(pmu) &&
>  	    (kvm_pmu_has_perf_global_ctrl(pmu) || kvm_vcpu_has_mediated_pmu(vcpu)))
> -		pmu->global_ctrl = GENMASK_ULL(pmu->nr_arch_gp_counters - 1, 0);
> +		pmu->global_ctrl = kvm_gp_pmc_mask(pmu);
>  
>  	if (kvm_vcpu_has_mediated_pmu(vcpu))
>  		kvm_pmu_call(write_global_ctrl)(pmu->global_ctrl);
> -
> -	bitmap_set(pmu->pmc_exists, 0, pmu->nr_arch_gp_counters);
> -	bitmap_set(pmu->pmc_exists, KVM_FIXED_PMC_BASE_IDX,
> -		   pmu->nr_arch_fixed_counters);
>  }
>  
>  void kvm_pmu_init(struct kvm_vcpu *vcpu)
> @@ -1332,6 +1326,8 @@ static __always_inline u32 gp_eventsel_msr(u32 idx)
>  static void kvm_pmu_load_guest_pmcs(struct kvm_vcpu *vcpu)
>  {
>  	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
> +	unsigned long fixed_mask = kvm_fixed_pmc_mask(pmu);
> +	unsigned long gp_mask = kvm_gp_pmc_mask(pmu);
>  	struct kvm_pmc *pmc;
>  	u32 i;
>  
> @@ -1340,14 +1336,14 @@ static void kvm_pmu_load_guest_pmcs(struct kvm_vcpu *vcpu)
>  	 * is intercepted if hardware has counters that aren't visible to the
>  	 * guest (KVM will inject #GP as appropriate).
>  	 */
> -	for (i = 0; i < pmu->nr_arch_gp_counters; i++) {
> +	kvm_for_each_gp_counter(i, gp_mask) {
>  		pmc = &pmu->gp_counters[i];
>  
>  		if (pmc->counter != rdpmc(i))
>  			wrmsrq(gp_counter_msr(i), pmc->counter);
>  		wrmsrq(gp_eventsel_msr(i), pmc->eventsel_hw);
>  	}
> -	for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
> +	kvm_for_each_fixed_counter(i, fixed_mask) {
>  		pmc = &pmu->fixed_counters[i];
>  
>  		if (pmc->counter != rdpmc(INTEL_PMC_FIXED_RDPMC_BASE | i))
> @@ -1390,6 +1386,8 @@ void kvm_mediated_pmu_load(struct kvm_vcpu *vcpu)
>  static void kvm_pmu_put_guest_pmcs(struct kvm_vcpu *vcpu)
>  {
>  	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
> +	unsigned long fixed_mask = kvm_fixed_pmc_mask(pmu);
> +	unsigned long gp_mask = kvm_gp_pmc_mask(pmu);
>  	struct kvm_pmc *pmc;
>  	u32 i;
>  
> @@ -1397,7 +1395,7 @@ static void kvm_pmu_put_guest_pmcs(struct kvm_vcpu *vcpu)
>  	 * Clear selectors and counters to ensure hardware doesn't count using
>  	 * guest controls when the host (perf) restores its state.
>  	 */
> -	for (i = 0; i < pmu->nr_arch_gp_counters; i++) {
> +	kvm_for_each_gp_counter(i, gp_mask) {
>  		pmc = &pmu->gp_counters[i];
>  
>  		pmc->counter = rdpmc(i);
> @@ -1407,7 +1405,7 @@ static void kvm_pmu_put_guest_pmcs(struct kvm_vcpu *vcpu)
>  			wrmsrq(gp_eventsel_msr(i), 0);
>  	}
>  
> -	for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
> +	kvm_for_each_fixed_counter(i, fixed_mask) {
>  		pmc = &pmu->fixed_counters[i];
>  
>  		pmc->counter = rdpmc(INTEL_PMC_FIXED_RDPMC_BASE | i);
> diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c
> index 52224872e0d4..0943ccc1d6b8 100644
> --- a/arch/x86/kvm/svm/pmu.c
> +++ b/arch/x86/kvm/svm/pmu.c
> @@ -27,12 +27,11 @@ enum pmu_type {
>  
>  static struct kvm_pmc *amd_pmu_get_pmc(struct kvm_pmu *pmu, int pmc_idx)
>  {
> -	unsigned int num_counters = pmu->nr_arch_gp_counters;
> -
> -	if (pmc_idx >= num_counters)
> +	if (!kvm_is_gp_pmc_supported(pmu, pmc_idx))
>  		return NULL;
>  
> -	return &pmu->gp_counters[array_index_nospec(pmc_idx, num_counters)];
> +	pmc_idx = array_index_nospec(pmc_idx, KVM_MAX_NR_AMD_GP_COUNTERS);
> +	return &pmu->gp_counters[pmc_idx];
>  }
>  
>  static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr,
> @@ -77,7 +76,7 @@ static int amd_check_rdpmc_early(struct kvm_vcpu *vcpu, unsigned int idx)
>  {
>  	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
>  
> -	if (idx >= pmu->nr_arch_gp_counters)
> +	if (!kvm_is_gp_pmc_supported(pmu, idx))
>  		return -EINVAL;
>  
>  	return 0;
> @@ -117,7 +116,7 @@ static bool amd_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
>  		return pmu->version > 1;
>  	default:
>  		if (msr > MSR_F15H_PERF_CTR5 &&
> -		    msr < MSR_F15H_PERF_CTL0 + 2 * pmu->nr_arch_gp_counters)
> +		    msr < MSR_F15H_PERF_CTL0 + 2 * hweight_long(kvm_gp_pmc_mask(pmu)))
>  			return pmu->version > 1;
>  		break;
>  	}
> @@ -184,6 +183,7 @@ static int amd_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>  
>  static void amd_pmu_refresh(struct kvm_vcpu *vcpu)
>  {
> +	unsigned int nr_gp_counters = AMD64_NUM_COUNTERS;
>  	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
>  	union cpuid_0x80000022_ebx ebx;
>  
> @@ -197,18 +197,16 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu)
>  		BUILD_BUG_ON(x86_feature_cpuid(X86_FEATURE_PERFMON_V2).function != 0x80000022 ||
>  			     x86_feature_cpuid(X86_FEATURE_PERFMON_V2).index);
>  		ebx.full = kvm_find_cpuid_entry_index(vcpu, 0x80000022, 0)->ebx;
> -		pmu->nr_arch_gp_counters = ebx.split.num_core_pmc;
> +		nr_gp_counters = ebx.split.num_core_pmc;
>  	} else if (guest_cpu_cap_has(vcpu, X86_FEATURE_PERFCTR_CORE)) {
> -		pmu->nr_arch_gp_counters = AMD64_NUM_COUNTERS_CORE;
> -	} else {
> -		pmu->nr_arch_gp_counters = AMD64_NUM_COUNTERS;
> +		nr_gp_counters = AMD64_NUM_COUNTERS_CORE;
>  	}
>  
> -	pmu->nr_arch_gp_counters = min_t(unsigned int, pmu->nr_arch_gp_counters,
> -					 kvm_pmu_cap.num_counters_gp);
> +	pmu->pmc_exists64 = (BIT_ULL(nr_gp_counters) - 1) &
> +			    (BIT_ULL(kvm_pmu_cap.num_counters_gp) - 1);
>  
>  	if (pmu->version > 1) {
> -		pmu->global_ctrl_rsvd = ~(BIT_ULL(pmu->nr_arch_gp_counters) - 1);
> +		pmu->global_ctrl_rsvd = ~pmu->pmc_exists64;
>  		pmu->global_status_rsvd = pmu->global_ctrl_rsvd;
>  	}
>  
> @@ -227,7 +225,6 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu)
>  	pmu->raw_event_mask = AMD64_RAW_EVENT_MASK;
>  	/* not applicable to AMD; but clean them to prevent any fall out */
>  	pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
> -	pmu->nr_arch_fixed_counters = 0;
>  }
>  
>  static void amd_pmu_init(struct kvm_vcpu *vcpu)
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 9d607b98bd06..fb8442a08b63 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -753,18 +753,22 @@ static void svm_recalc_pmu_msr_intercepts(struct kvm_vcpu *vcpu)
>  {
>  	bool intercept = !kvm_vcpu_has_mediated_pmu(vcpu);
>  	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
> +	unsigned long gp_mask = kvm_gp_pmc_mask(pmu);
>  	int i;
>  
>  	if (!enable_mediated_pmu)
>  		return;
>  
>  	/* Legacy counters are always available for AMD CPUs with a PMU. */
> -	for (i = 0; i < min(pmu->nr_arch_gp_counters, AMD64_NUM_COUNTERS); i++)
> +	for_each_set_bit(i, &gp_mask, AMD64_NUM_COUNTERS)
>  		svm_set_intercept_for_msr(vcpu, MSR_K7_PERFCTR0 + i,
>  					  MSR_TYPE_RW, intercept);
> +	for_each_clear_bit(i, &gp_mask, AMD64_NUM_COUNTERS)
> +		svm_enable_intercept_for_msr(vcpu, MSR_K7_PERFCTR0 + i,
> +					     MSR_TYPE_RW);
>  
>  	intercept |= !guest_cpu_cap_has(vcpu, X86_FEATURE_PERFCTR_CORE);
> -	for (i = 0; i < pmu->nr_arch_gp_counters; i++)
> +	kvm_for_each_gp_counter(i, gp_mask)
>  		svm_set_intercept_for_msr(vcpu, MSR_F15H_PERF_CTR + 2 * i,
>  					  MSR_TYPE_RW, intercept);
>  
> diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
> index 7ed79894d11d..0cff369982ae 100644
> --- a/arch/x86/kvm/vmx/nested.c
> +++ b/arch/x86/kvm/vmx/nested.c
> @@ -697,6 +697,8 @@ static void nested_vmx_merge_pmu_msr_bitmaps(struct kvm_vcpu *vcpu,
>  {
>  	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
>  	struct vcpu_vmx *vmx = to_vmx(vcpu);
> +	unsigned long gp_mask = kvm_gp_pmc_mask(pmu);
> +	unsigned long fixed_mask = kvm_fixed_pmc_mask(pmu);
>  	int i;
>  
>  	/*
> @@ -706,12 +708,12 @@ static void nested_vmx_merge_pmu_msr_bitmaps(struct kvm_vcpu *vcpu,
>  	if (!kvm_vcpu_has_mediated_pmu(vcpu))
>  		return;
>  
> -	for (i = 0; i < pmu->nr_arch_gp_counters; i++) {
> +	kvm_for_each_gp_counter(i, gp_mask) {
>  		nested_vmx_merge_msr_bitmaps_rw(MSR_IA32_PERFCTR0 + i);
>  		nested_vmx_merge_msr_bitmaps_rw(MSR_IA32_PMC0 + i);
>  	}
>  
> -	for (i = 0; i < pmu->nr_arch_fixed_counters; i++)
> +	kvm_for_each_fixed_counter(i, fixed_mask)
>  		nested_vmx_merge_msr_bitmaps_rw(MSR_CORE_PERF_FIXED_CTR0 + i);
>  
>  	nested_vmx_merge_msr_bitmaps_rw(MSR_CORE_PERF_GLOBAL_CTRL);
> diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
> index 9fdae437e569..926d1c57f8bf 100644
> --- a/arch/x86/kvm/vmx/pmu_intel.c
> +++ b/arch/x86/kvm/vmx/pmu_intel.c
> @@ -66,12 +66,13 @@ static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
>  	 * hardware, e.g. to ensure the event filter is enforced.
>  	 */
>  	u64 old_fixed_ctr_ctrl = pmu->fixed_ctr_ctrl_hw;
> +	unsigned long fixed_mask = kvm_fixed_pmc_mask(pmu);
>  	struct kvm_pmc *pmc;
>  	int i;
>  
>  	pmu->fixed_ctr_ctrl = data;
>  	pmu->fixed_ctr_ctrl_hw = data;
> -	for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
> +	kvm_for_each_fixed_counter(i, fixed_mask) {
>  		u8 new_ctrl = fixed_ctrl_field(data, i);
>  		u8 old_ctrl = fixed_ctrl_field(old_fixed_ctr_ctrl, i);
>  
> @@ -107,6 +108,8 @@ static struct kvm_pmc *intel_rdpmc_ecx_to_pmc(struct kvm_vcpu *vcpu,
>  	if (WARN_ON_ONCE(!pmu->version))
>  		return NULL;
>  
> +	idx &= INTEL_RDPMC_INDEX_MASK;
> +
>  	/*
>  	 * General Purpose (GP) PMCs are supported on all PMUs, and fixed PMCs
>  	 * are supported on all architectural PMUs, i.e. on all virtual PMUs
> @@ -117,23 +120,25 @@ static struct kvm_pmc *intel_rdpmc_ecx_to_pmc(struct kvm_vcpu *vcpu,
>  	 */
>  	switch (type) {
>  	case INTEL_RDPMC_FIXED:
> +		if (!kvm_is_fixed_pmc_supported(pmu, idx))
> +			return NULL;
> +
>  		counters = pmu->fixed_counters;
> -		num_counters = pmu->nr_arch_fixed_counters;
> +		num_counters = KVM_MAX_NR_INTEL_FIXED_COUNTERS;
>  		bitmask = pmu->counter_bitmask[KVM_PMC_FIXED];
>  		break;
>  	case INTEL_RDPMC_GP:
> +		if (!kvm_is_gp_pmc_supported(pmu, idx))
> +			return NULL;
> +
>  		counters = pmu->gp_counters;
> -		num_counters = pmu->nr_arch_gp_counters;
> +		num_counters = KVM_MAX_NR_INTEL_GP_COUNTERS;
>  		bitmask = pmu->counter_bitmask[KVM_PMC_GP];
>  		break;
>  	default:
>  		return NULL;
>  	}
>  
> -	idx &= INTEL_RDPMC_INDEX_MASK;
> -	if (idx >= num_counters)
> -		return NULL;
> -
>  	*mask &= bitmask;
>  	return &counters[array_index_nospec(idx, num_counters)];
>  }
> @@ -492,9 +497,10 @@ static __always_inline u64 intel_get_fixed_pmc_eventsel(unsigned int index)
>  
>  static void intel_pmu_enable_fixed_counter_bits(struct kvm_pmu *pmu, u64 bits)
>  {
> +	unsigned long fixed_mask = kvm_fixed_pmc_mask(pmu);
>  	int i;
>  
> -	for (i = 0; i < pmu->nr_arch_fixed_counters; i++)
> +	kvm_for_each_fixed_counter(i, fixed_mask)
>  		pmu->fixed_ctr_ctrl_rsvd &= ~intel_fixed_bits_by_idx(i, bits);
>  }
>  
> @@ -506,6 +512,8 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
>  	union cpuid10_eax eax;
>  	union cpuid10_edx edx;
>  	u64 perf_capabilities;
> +	u64 fixed_cntr_mask;
> +	int nr_gp_counters;
>  	u64 counter_rsvd;
>  
>  	if (!lbr_desc)
> @@ -532,8 +540,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
>  	if (!pmu->version)
>  		return;
>  
> -	pmu->nr_arch_gp_counters = min_t(int, eax.split.num_counters,
> -					 kvm_pmu_cap.num_counters_gp);
>  	eax.split.bit_width = min_t(int, eax.split.bit_width,
>  				    kvm_pmu_cap.bit_width_gp);
>  	pmu->counter_bitmask[KVM_PMC_GP] = BIT_ULL(eax.split.bit_width) - 1;
> @@ -541,6 +547,17 @@ 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_cntr_mask = BIT_ULL(edx.split.num_counters_fixed) - 1;
> +	fixed_cntr_mask &= BIT_ULL(kvm_pmu_cap.num_counters_fixed) - 1;
> +
> +	/*
> +	 * The number of counters comes from guest CPUID data. Clamp the value
> +	 * to avoid a shift-by-64 in BIT_ULL().
> +	 */
> +	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);
> +
>  	entry = kvm_find_cpuid_entry_index(vcpu, 7, 0);
>  	if (entry &&
>  	    (boot_cpu_has(X86_FEATURE_HLE) || boot_cpu_has(X86_FEATURE_RTM)) &&
> @@ -562,8 +579,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
>  	if (pmu->version == 1)
>  		return;
>  
> -	pmu->nr_arch_fixed_counters = min_t(int, edx.split.num_counters_fixed,
> -					    kvm_pmu_cap.num_counters_fixed);
> +	pmu->pmc_exists64 |= fixed_cntr_mask << INTEL_PMC_IDX_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;
> @@ -572,8 +588,8 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
>  						 INTEL_FIXED_0_USER |
>  						 INTEL_FIXED_0_ENABLE_PMI);
>  
> -	counter_rsvd = ~((BIT_ULL(pmu->nr_arch_gp_counters) - 1) |
> -			 ((BIT_ULL(pmu->nr_arch_fixed_counters) - 1) << KVM_FIXED_PMC_BASE_IDX));
> +	counter_rsvd = ~(kvm_gp_pmc_mask(pmu) |
> +			((u64)kvm_fixed_pmc_mask(pmu) << KVM_FIXED_PMC_BASE_IDX));
>  	pmu->global_ctrl_rsvd = counter_rsvd;
>  
>  	/*
> @@ -596,7 +612,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
>  			pmu->pebs_data_cfg_rsvd = ~0xff00000full;
>  			intel_pmu_enable_fixed_counter_bits(pmu, ICL_FIXED_0_ADAPTIVE);
>  		} else {
> -			pmu->pebs_enable_rsvd = ~(BIT_ULL(pmu->nr_arch_gp_counters) - 1);
> +			pmu->pebs_enable_rsvd = ~kvm_gp_pmc_mask(pmu);
>  		}
>  	}
>  }
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index d3789b2ee18e..be994adbd954 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -4230,6 +4230,8 @@ static void vmx_recalc_pmu_msr_intercepts(struct kvm_vcpu *vcpu)
>  	bool has_mediated_pmu = kvm_vcpu_has_mediated_pmu(vcpu);
>  	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
>  	struct vcpu_vmx *vmx = to_vmx(vcpu);
> +	unsigned long fixed_mask = kvm_fixed_pmc_mask(pmu);
> +	unsigned long gp_mask = kvm_gp_pmc_mask(pmu);
>  	bool intercept = !has_mediated_pmu;
>  	int i;
>  
> @@ -4250,7 +4252,7 @@ static void vmx_recalc_pmu_msr_intercepts(struct kvm_vcpu *vcpu)
>  
>  	vm_exit_controls_changebit(vmx, vm_exit_controls_bits, has_mediated_pmu);
>  
> -	for (i = 0; i < pmu->nr_arch_gp_counters; i++) {
> +	kvm_for_each_gp_counter(i, gp_mask) {
>  		vmx_set_intercept_for_msr(vcpu, MSR_IA32_PERFCTR0 + i,
>  					  MSR_TYPE_RW, intercept);
>  		vmx_set_intercept_for_msr(vcpu, MSR_IA32_PMC0 + i, MSR_TYPE_RW,
> @@ -4263,7 +4265,7 @@ static void vmx_recalc_pmu_msr_intercepts(struct kvm_vcpu *vcpu)
>  					  MSR_TYPE_RW, true);
>  	}
>  
> -	for (i = 0; i < pmu->nr_arch_fixed_counters; i++)
> +	kvm_for_each_fixed_counter(i, fixed_mask)
>  		vmx_set_intercept_for_msr(vcpu, MSR_CORE_PERF_FIXED_CTR0 + i,
>  					  MSR_TYPE_RW, intercept);
>  	for ( ; i < kvm_pmu_cap.num_counters_fixed; i++)

  reply	other threads:[~2026-09-01  3:07 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-27 22:37 [PATCH] KVM: x86/pmu: Add mediated vPMU PerfMon v5 support Zide Chen
2026-08-27 22:37 ` [PATCH v2 01/16] KVM: x86/pmu: Remove redundant Perf Global Status MSR bit definitions Zide Chen
2026-08-27 22:57   ` sashiko-bot
2026-08-28 13:51     ` Chen, Zide
2026-09-01  2:07   ` Mi, Dapeng
2026-08-27 22:37 ` [PATCH v2 02/16] KVM: x86/pmu: Rename all_valid_pmc_idx to pmc_exists Zide Chen
2026-09-01  2:09   ` Mi, Dapeng
2026-08-27 22:37 ` [PATCH v2 03/16] KVM: x86/pmu: Rename reserved_bits to eventsel_rsvd in kvm_pmu Zide Chen
2026-09-01  2:17   ` Mi, Dapeng
2026-08-27 22:37 ` [PATCH v2 04/16] KVM: x86/pmu: Gate BUFFER_OVF reserved bit on guest DS Zide Chen
2026-09-01  2:30   ` Mi, Dapeng
2026-08-27 22:37 ` [PATCH v2 05/16] KVM: x86/pmu: Add PMC bitmap accessor helpers Zide Chen
2026-09-01  2:43   ` Mi, Dapeng
2026-08-27 22:37 ` [PATCH v2 06/16] KVM: x86/pmu: Drop nr_arch_{gp,fixed}_counters from kvm_pmu Zide Chen
2026-09-01  3:07   ` Mi, Dapeng [this message]
2026-08-27 22:37 ` [PATCH v2 07/16] KVM: x86/pmu: Expose kvm_host_pmu to vendor modules Zide Chen
2026-09-01  3:08   ` Mi, Dapeng
2026-08-27 22:37 ` [PATCH v2 08/16] perf/x86: Plumb counter bitmap from x86_pmu to x86_pmu_cap Zide Chen
2026-08-27 22:37 ` [PATCH v2 09/16] KVM: x86/pmu: Switch to bitmask-based KVM PMU capabilities Zide Chen
2026-09-01  3:32   ` Mi, Dapeng
2026-08-27 22:37 ` [PATCH v2 10/16] perf/x86: Remove num_counters_{gp,fixed} from x86_pmu_capability Zide Chen
2026-08-27 22:37 ` [PATCH v2 11/16] KVM: x86/pmu: Emulate the GLOBAL_STATUS_SET and GLOBAL_INUSE MSRs Zide Chen
2026-08-27 23:05   ` sashiko-bot
2026-08-28 20:22     ` Chen, Zide
2026-09-01  6:45   ` Mi, Dapeng
2026-09-01 14:20     ` Chen, Zide
2026-09-02  0:44       ` Mi, Dapeng
2026-08-27 22:37 ` [PATCH v2 12/16] KVM: x86/pmu: Populate CPUID.0AH:ECX fixed-counter bitmap Zide Chen
2026-09-01  6:50   ` Mi, Dapeng
2026-08-27 22:37 ` [PATCH v2 13/16] KVM: x86/pmu: Factor out fixed counter control bit calculation Zide Chen
2026-09-01  6:57   ` Mi, Dapeng
2026-08-27 22:37 ` [PATCH v2 14/16] KVM: x86/pmu: Ignore AnyThread bit if CPUID.0AH:EDX[15] is set Zide Chen
2026-09-01  8:01   ` Mi, Dapeng
2026-08-27 22:37 ` [PATCH v2 15/16] KVM: x86/pmu: Advertise PerfMon version 5 on Intel hosts Zide Chen
2026-08-27 22:37 ` [PATCH v2 16/16] KVM: selftests: Support fixed counters bitmap in pmu_counters_test Zide Chen
2026-08-29  9:30 ` [PATCH] KVM: x86/pmu: Add mediated vPMU PerfMon v5 support Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2bb5aa22-42f0-4d65-a1f9-572084ba2eec@linux.intel.com \
    --to=dapeng1.mi@linux.intel.com \
    --cc=Manali.Shukla@amd.com \
    --cc=Sandipan.Das@amd.com \
    --cc=ak@linux.intel.com \
    --cc=eranian@google.com \
    --cc=jmattson@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mizhang@google.com \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=seanjc@google.com \
    --cc=xudong.hao@intel.com \
    --cc=zide.chen@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox