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 <[email protected]>
---
 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 185ea3631eee..e70628653e4b 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -690,6 +690,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
@@ -819,42 +836,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];
@@ -1089,7 +1070,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


Reply via email to