Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: arm64: Refine PMU defines for number of counters

There are 2 defines for the number of PMU counters:
ARMV8_PMU_MAX_COUNTERS and ARMPMU_MAX_HWEVENTS. Both are the same
currently, but Armv9.4/8.9 increases the number of possible counters
from 32 to 33. With this change, the maximum number of counters will
differ for KVM's PMU emulation which is PMUv3.4. Give KVM PMU emulation
its own define to decouple it from the rest of the kernel's number PMU
counters.

The VHE PMU code needs to match the PMU driver, so switch it to use
ARMPMU_MAX_HWEVENTS instead.

Acked-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
Tested-by: James Clark <james.clark@linaro.org>
Link: https://lore.kernel.org/r/20240731-arm-pmu-3-9-icntr-v3-6-280a8d7ff465@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>

authored by

Rob Herring (Arm) and committed by
Will Deacon
2f62701f 126d7d7c

+9 -9
+4 -4
arch/arm64/kvm/pmu-emul.c
··· 233 233 int i; 234 234 struct kvm_pmu *pmu = &vcpu->arch.pmu; 235 235 236 - for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) 236 + for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++) 237 237 pmu->pmc[i].idx = i; 238 238 } 239 239 ··· 260 260 { 261 261 int i; 262 262 263 - for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) 263 + for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++) 264 264 kvm_pmu_release_perf_event(kvm_vcpu_idx_to_pmc(vcpu, i)); 265 265 irq_work_sync(&vcpu->arch.pmu.overflow_work); 266 266 } ··· 291 291 if (!(kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E) || !val) 292 292 return; 293 293 294 - for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) { 294 + for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++) { 295 295 struct kvm_pmc *pmc; 296 296 297 297 if (!(val & BIT(i))) ··· 323 323 if (!kvm_vcpu_has_pmu(vcpu) || !val) 324 324 return; 325 325 326 - for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) { 326 + for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++) { 327 327 struct kvm_pmc *pmc; 328 328 329 329 if (!(val & BIT(i)))
+3 -2
arch/arm64/kvm/pmu.c
··· 5 5 */ 6 6 #include <linux/kvm_host.h> 7 7 #include <linux/perf_event.h> 8 + #include <linux/perf/arm_pmu.h> 8 9 #include <linux/perf/arm_pmuv3.h> 9 10 10 11 static DEFINE_PER_CPU(struct kvm_pmu_events, kvm_pmu_events); ··· 96 95 u64 typer; 97 96 u32 counter; 98 97 99 - for_each_set_bit(counter, &events, 32) { 98 + for_each_set_bit(counter, &events, ARMPMU_MAX_HWEVENTS) { 100 99 typer = kvm_vcpu_pmu_read_evtype_direct(counter); 101 100 typer &= ~ARMV8_PMU_EXCLUDE_EL0; 102 101 kvm_vcpu_pmu_write_evtype_direct(counter, typer); ··· 111 110 u64 typer; 112 111 u32 counter; 113 112 114 - for_each_set_bit(counter, &events, 32) { 113 + for_each_set_bit(counter, &events, ARMPMU_MAX_HWEVENTS) { 115 114 typer = kvm_vcpu_pmu_read_evtype_direct(counter); 116 115 typer |= ARMV8_PMU_EXCLUDE_EL0; 117 116 kvm_vcpu_pmu_write_evtype_direct(counter, typer);
+2 -1
include/kvm/arm_pmu.h
··· 10 10 #include <linux/perf_event.h> 11 11 #include <linux/perf/arm_pmuv3.h> 12 12 13 + #define KVM_ARMV8_PMU_MAX_COUNTERS 32 13 14 14 15 #if IS_ENABLED(CONFIG_HW_PERF_EVENTS) && IS_ENABLED(CONFIG_KVM) 15 16 struct kvm_pmc { ··· 26 25 struct kvm_pmu { 27 26 struct irq_work overflow_work; 28 27 struct kvm_pmu_events events; 29 - struct kvm_pmc pmc[ARMV8_PMU_MAX_COUNTERS]; 28 + struct kvm_pmc pmc[KVM_ARMV8_PMU_MAX_COUNTERS]; 30 29 int irq_num; 31 30 bool created; 32 31 bool irq_level;
-2
include/linux/perf/arm_pmuv3.h
··· 7 7 #define __PERF_ARM_PMUV3_H 8 8 9 9 #define ARMV8_PMU_MAX_GENERAL_COUNTERS 31 10 - #define ARMV8_PMU_MAX_COUNTERS 32 11 - 12 10 #define ARMV8_PMU_CYCLE_IDX 31 13 11 14 12