This series creates a new PMU scheme on ARM, a partitioned PMU that allows reserving a subset of counters for more direct guest access, significantly reducing overhead. More details, including performance benchmarks, can be read in the v1 cover letter linked below.
v2:
* Rebased on top of kvm/queue to pick up Sean's patch [1] that reorganizes some of the same headers and would otherwise conflict.
* Changed the semantics of the command line parameters and the ioctl. It was pointed out in the comments last time that it doesn't work to repartition at runtime because the perf subsystem assumes the number of counters it gets will not change after the PMU is probed. Now the PMUv3 command line parameters are the sole thing that divides up guest and host counters and the ioctl just toggles a flag for whether a vcpu should use the partitioned PMU. I've also moved from one to two parameters: partition_pmu=[y/n] and reserved_guest_counters=[0-N]. This makes it possible to unambiguously express configurations like a partitioned PMU with 0 general purpose counters exposed to the guest (which still exposes the cycle counter.
* Moved the partitioning code into the PMUv3 driver itself so KVM code isn't modifying fields that are otherwise internal to the driver.
* Define PMI{CNTR,FILTR} as undef_access since KVM isn't ready to support that counter. It is, however, still handled in the partitioning because the driver recognizes it.
* Take out the dependency on FEAT_FGT since it is not widely available on hardware yet. Instead, define a fast path in switch.h for handling accesses to the registers that would otherwise be untrapped.
* During MDCR_EL2 setup for guests, ensure the computed HPMN value is always below the number of guest counters allocated by the driver at boot and always below the number of counters on the current CPU. This accounts for the possibiliy of heterogeneous hardware where I guest might be able to use the partitioned PMU on one CPU but not another.
* The KVM PMU event filter API says that counters must not count while the event is filtered. To ensure this, enforce the filter on every vcpu_load into the guest.
* Settable PMCR_EL0.N with a partitioned PMU now works and the vcpu_counter_access selftest changes reflect that.
v1: https://lore.kernel.org/kvm/20250602192702.2125115-1-coltonlewis@google.com/
Colton Lewis (22): arm64: cpufeature: Add cpucap for HPMN0 arm64: Generate sign macro for sysreg Enums arm64: cpufeature: Add cpucap for PMICNTR arm64: Define PMI{CNTR,FILTR}_EL0 as undef_access KVM: arm64: Reorganize PMU functions perf: arm_pmuv3: Introduce method to partition the PMU perf: arm_pmuv3: Generalize counter bitmasks perf: arm_pmuv3: Keep out of guest counter partition KVM: arm64: Correct kvm_arm_pmu_get_max_counters() KVM: arm64: Set up FGT for Partitioned PMU KVM: arm64: Writethrough trapped PMEVTYPER register KVM: arm64: Use physical PMSELR for PMXEVTYPER if partitioned KVM: arm64: Writethrough trapped PMOVS register KVM: arm64: Write fast path PMU register handlers KVM: arm64: Setup MDCR_EL2 to handle a partitioned PMU KVM: arm64: Account for partitioning in PMCR_EL0 access KVM: arm64: Context swap Partitioned PMU guest registers KVM: arm64: Enforce PMU event filter at vcpu_load() perf: arm_pmuv3: Handle IRQs for Partitioned PMU guest counters KVM: arm64: Inject recorded guest interrupts KVM: arm64: Add ioctl to partition the PMU when supported KVM: arm64: selftests: Add test case for partitioned PMU
Marc Zyngier (1): KVM: arm64: Cleanup PMU includes
Documentation/virt/kvm/api.rst | 21 + arch/arm/include/asm/arm_pmuv3.h | 34 + arch/arm64/include/asm/arm_pmuv3.h | 61 +- arch/arm64/include/asm/kvm_host.h | 20 +- arch/arm64/include/asm/kvm_pmu.h | 61 ++ arch/arm64/kernel/cpufeature.c | 15 + arch/arm64/kvm/Makefile | 2 +- arch/arm64/kvm/arm.c | 22 + arch/arm64/kvm/debug.c | 24 +- arch/arm64/kvm/hyp/include/hyp/switch.h | 233 ++++++ arch/arm64/kvm/pmu-emul.c | 676 +---------------- arch/arm64/kvm/pmu-part.c | 359 +++++++++ arch/arm64/kvm/pmu.c | 687 ++++++++++++++++++ arch/arm64/kvm/sys_regs.c | 66 +- arch/arm64/tools/cpucaps | 2 + arch/arm64/tools/gen-sysreg.awk | 1 + arch/arm64/tools/sysreg | 6 +- drivers/perf/arm_pmuv3.c | 150 +++- include/linux/perf/arm_pmu.h | 15 +- include/linux/perf/arm_pmuv3.h | 14 +- include/uapi/linux/kvm.h | 4 + tools/include/uapi/linux/kvm.h | 2 + .../selftests/kvm/arm64/vpmu_counter_access.c | 63 +- virt/kvm/kvm_main.c | 1 + 24 files changed, 1791 insertions(+), 748 deletions(-) create mode 100644 arch/arm64/kvm/pmu-part.c
base-commit: 79150772457f4d45e38b842d786240c36bb1f97f -- 2.50.0.714.g196bf9f422-goog