Convert the list of PMUs to a RCU-protected list that has primitives to avoid read-side contention.
Assisted-by: Codex:gpt-5.5 Signed-off-by: Akihiko Odaki <[email protected]> --- arch/arm64/kvm/pmu-emul.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c index c816db5d6761..68fce960ba69 100644 --- a/arch/arm64/kvm/pmu-emul.c +++ b/arch/arm64/kvm/pmu-emul.c @@ -7,9 +7,9 @@ #include <linux/cpu.h> #include <linux/kvm.h> #include <linux/kvm_host.h> -#include <linux/list.h> #include <linux/perf_event.h> #include <linux/perf/arm_pmu.h> +#include <linux/rculist.h> #include <linux/uaccess.h> #include <asm/kvm_emulate.h> #include <kvm/arm_pmu.h> @@ -17,6 +17,10 @@ #define PERF_ATTR_CFG1_COUNTER_64BIT BIT(0) +/* + * arm_pmus is append-only. kvm_supports_guest_pmuv3() feeds persistent + * VM state, so a true result must remain valid after the check. + */ static LIST_HEAD(arm_pmus); static DEFINE_MUTEX(arm_pmus_lock); @@ -26,7 +30,6 @@ static bool kvm_pmu_counter_is_enabled(struct kvm_pmc *pmc); bool kvm_supports_guest_pmuv3(void) { - guard(mutex)(&arm_pmus_lock); return !list_empty(&arm_pmus); } @@ -802,7 +805,7 @@ void kvm_host_pmu_init(struct arm_pmu *pmu) return; entry->arm_pmu = pmu; - list_add_tail(&entry->entry, &arm_pmus); + list_add_tail_rcu(&entry->entry, &arm_pmus); } static struct arm_pmu *kvm_pmu_probe_armpmu(void) @@ -811,7 +814,7 @@ static struct arm_pmu *kvm_pmu_probe_armpmu(void) struct arm_pmu *pmu; int cpu; - guard(mutex)(&arm_pmus_lock); + guard(rcu)(); /* * It is safe to use a stale cpu to iterate the list of PMUs so long as @@ -831,7 +834,7 @@ static struct arm_pmu *kvm_pmu_probe_armpmu(void) * carried here. */ cpu = raw_smp_processor_id(); - list_for_each_entry(entry, &arm_pmus, entry) { + list_for_each_entry_rcu(entry, &arm_pmus, entry) { pmu = entry->arm_pmu; if (cpumask_test_cpu(cpu, &pmu->supported_cpus)) @@ -1092,9 +1095,9 @@ static int kvm_arm_pmu_v3_set_pmu(struct kvm_vcpu *vcpu, int pmu_id) int ret = -ENXIO; lockdep_assert_held(&kvm->arch.config_lock); - mutex_lock(&arm_pmus_lock); + guard(rcu)(); - list_for_each_entry(entry, &arm_pmus, entry) { + list_for_each_entry_rcu(entry, &arm_pmus, entry) { arm_pmu = entry->arm_pmu; if (arm_pmu->pmu.type == pmu_id) { if (kvm_vm_has_ran_once(kvm) || @@ -1110,7 +1113,6 @@ static int kvm_arm_pmu_v3_set_pmu(struct kvm_vcpu *vcpu, int pmu_id) } } - mutex_unlock(&arm_pmus_lock); return ret; } -- 2.55.0

