Re: [PATCH v9 13/16] KVM: arm64: PMU: Pass the target CPU to kvm_pmu_probe_armpmu()

From: Fuad Tabba

Date: Wed Jul 29 2026 - 14:01:27 EST


On Mon, 20 Jul 2026 at 06:39, Akihiko Odaki
<odaki@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
> kvm_pmu_probe_armpmu() currently samples the current CPU internally,
> which ties the helper to default PMU selection.
>
> Move that policy to kvm_arm_set_default_pmu() by passing
> raw_smp_processor_id() from the caller, and make the helper search for
> the pPMU covering an explicit CPU. Move the helper above
> kvm_pmu_create_perf_event() so later code can reuse it when creating
> PMU events for a VCPU's current pCPU.
>
> This preserves the existing default PMU selection behavior while
> preparing fixed-counters-only mode to select a pPMU at runtime.
>
> Signed-off-by: Akihiko Odaki <odaki@xxxxxxxxxxxxxxxxxxxxxx>

Reviewed-by: Fuad Tabba <fuad.tabba@xxxxxxxxx>

Cheers,
/fuad


> ---
> arch/arm64/kvm/pmu-emul.c | 72 +++++++++++++++++++++++------------------------
> 1 file changed, 35 insertions(+), 37 deletions(-)
>
> diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
> index 27db8877f96e..78611eaecca2 100644
> --- a/arch/arm64/kvm/pmu-emul.c
> +++ b/arch/arm64/kvm/pmu-emul.c
> @@ -682,6 +682,23 @@ static int kvm_map_pmu_event(struct arm_pmu *pmu, unsigned int eventsel)
> return eventsel;
> }
>
> +static struct arm_pmu *kvm_pmu_probe_armpmu(int cpu)
> +{
> + struct arm_pmu_entry *entry;
> + struct arm_pmu *pmu;
> +
> + guard(rcu)();
> +
> + list_for_each_entry_rcu(entry, &arm_pmus, entry) {
> + pmu = entry->arm_pmu;
> +
> + if (cpumask_test_cpu(cpu, &pmu->supported_cpus))
> + return pmu;
> + }
> +
> + return NULL;
> +}
> +
> /**
> * kvm_pmu_create_perf_event - create a perf event for a counter
> * @pmc: Counter context
> @@ -811,42 +828,6 @@ void kvm_host_pmu_init(struct arm_pmu *pmu)
> list_add_tail_rcu(&entry->entry, &arm_pmus);
> }
>
> -static struct arm_pmu *kvm_pmu_probe_armpmu(void)
> -{
> - struct arm_pmu_entry *entry;
> - struct arm_pmu *pmu;
> - int cpu;
> -
> - guard(rcu)();
> -
> - /*
> - * It is safe to use a stale cpu to iterate the list of PMUs so long as
> - * the same value is used for the entirety of the loop. Given this, and
> - * the fact that no percpu data is used for the lookup there is no need
> - * to disable preemption.
> - *
> - * It is still necessary to get a valid cpu, though, to probe for the
> - * default PMU instance as userspace is not required to specify a PMU
> - * type. In order to uphold the preexisting behavior KVM selects the
> - * PMU instance for the core during vcpu init. A dependent use
> - * case would be a user with disdain of all things big.LITTLE that
> - * affines the VMM to a particular cluster of cores.
> - *
> - * In any case, userspace should just do the sane thing and use the UAPI
> - * to select a PMU type directly. But, be wary of the baggage being
> - * carried here.
> - */
> - cpu = raw_smp_processor_id();
> - list_for_each_entry_rcu(entry, &arm_pmus, entry) {
> - pmu = entry->arm_pmu;
> -
> - if (cpumask_test_cpu(cpu, &pmu->supported_cpus))
> - return pmu;
> - }
> -
> - return NULL;
> -}
> -
> static u64 __compute_pmceid(struct arm_pmu *pmu, bool pmceid1)
> {
> u32 hi[2], lo[2];
> @@ -1072,7 +1053,24 @@ static void kvm_arm_set_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu)
> */
> int kvm_arm_set_default_pmu(struct kvm *kvm)
> {
> - struct arm_pmu *arm_pmu = kvm_pmu_probe_armpmu();
> + /*
> + * It is safe to use a stale cpu to iterate the list of PMUs so long as
> + * the same value is used for the entirety of the loop. Given this, and
> + * the fact that no percpu data is used for the lookup there is no need
> + * to disable preemption.
> + *
> + * It is still necessary to get a valid cpu, though, to probe for the
> + * default PMU instance as userspace is not required to specify a PMU
> + * type. In order to uphold the preexisting behavior KVM selects the
> + * PMU instance for the core during vcpu init. A dependent use
> + * case would be a user with disdain of all things big.LITTLE that
> + * affines the VMM to a particular cluster of cores.
> + *
> + * In any case, userspace should just do the sane thing and use the UAPI
> + * to select a PMU type directly. But, be wary of the baggage being
> + * carried here.
> + */
> + struct arm_pmu *arm_pmu = kvm_pmu_probe_armpmu(raw_smp_processor_id());
>
> if (!arm_pmu)
> return -ENODEV;
>
> --
> 2.55.0
>
>