Re: [PATCH v9 11/16] KVM: arm64: PMU: Protect the list of PMUs with RCU

Fuad Tabba <[email protected]>
Newsgroups dev.linux.lists.kvmarm,org.infradead.lists.linux-arm-kernel,org.kernel.vger.kvm,org.kernel.vger.linux-doc,org.kernel.vger.linux-hardening,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest
Message-ID <CA+EHjTyY3PnJLHBVWCx1Mjy09a+AztByawZxcSSVtBUfzObC_A@mail.gmail.com>
On Mon, 20 Jul 2026 at 06:39, Akihiko Odaki
<[email protected]> wrote:
>
> 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]>

Reviewed-by: Fuad Tabba <[email protected]>

Cheers,
/fuad


> ---
>  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 9ac5f307ea31..c5c505b6fc61 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>
> @@ -20,6 +20,10 @@
>  #define MDCR_EL2_PMU_RECREATE_MASK     (MDCR_EL2_HPMN | MDCR_EL2_HPMD | \
>                                          MDCR_EL2_HLP)
>
> +/*
> + * 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);
>
> @@ -29,7 +33,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);
>  }
>
> @@ -807,7 +810,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)
> @@ -816,7 +819,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
> @@ -836,7 +839,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))
> @@ -1088,9 +1091,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) ||
> @@ -1106,7 +1109,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
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.