From: Marc Zyngier <maz@kernel.org>
To: linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org
Cc: Thomas Gleixner <tglx@linutronix.de>,
Mark Rutland <mark.rutland@arm.com>,
Will Deacon <will@kernel.org>,
"Rafael J. Wysocki" <rafael@kernel.org>,
Rob Herring <robh@kernel.org>,
Saravana Kannan <saravanak@google.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Sven Peter <sven@kernel.org>, Janne Grunau <j@jannau.net>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
James Clark <james.clark@linaro.org>
Subject: [PATCH 10/25] perf: arm_pmu: Add PMU/CPU affinity tracking
Date: Mon, 8 Sep 2025 17:31:12 +0100 [thread overview]
Message-ID: <20250908163127.2462948-11-maz@kernel.org> (raw)
In-Reply-To: <20250908163127.2462948-1-maz@kernel.org>
The ARM PMU code is built around the assumption that different CPU
affinities (either a single CPU in the case of an SPI, or a group
of CPUs for a PPI) must result in different IRQ numbers.
This scheme is about to be removed, so the driver must be able to match
the new behaviour.
For this purpose, add a new per-CPU variable that tracks the PMU
affinities on a per-CPU basis, so that the driver can, from any CPU,
find out which other CPUs it is sharing an interrupt number with.
It is likely that some simplifications could result from this scheme,
but this is good enough to get started.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
drivers/perf/arm_pmu.c | 37 +++++++++++++++++++++++++--------
drivers/perf/arm_pmu_acpi.c | 5 +++++
drivers/perf/arm_pmu_platform.c | 4 ++++
include/linux/perf/arm_pmu.h | 1 +
4 files changed, 38 insertions(+), 9 deletions(-)
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 5c310e803dd78..6e3c72e9b41cd 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -26,7 +26,7 @@
#include <asm/irq_regs.h>
-static int armpmu_count_irq_users(const int irq);
+static int armpmu_count_irq_users(const int this_cpu, const int irq);
struct pmu_irq_ops {
void (*enable_pmuirq)(unsigned int irq);
@@ -64,7 +64,7 @@ static void armpmu_enable_percpu_pmuirq(unsigned int irq)
static void armpmu_free_percpu_pmuirq(unsigned int irq, int cpu,
void __percpu *devid)
{
- if (armpmu_count_irq_users(irq) == 1)
+ if (armpmu_count_irq_users(cpu, irq) == 1)
free_percpu_irq(irq, devid);
}
@@ -89,7 +89,7 @@ static void armpmu_disable_percpu_pmunmi(unsigned int irq)
static void armpmu_free_percpu_pmunmi(unsigned int irq, int cpu,
void __percpu *devid)
{
- if (armpmu_count_irq_users(irq) == 1)
+ if (armpmu_count_irq_users(cpu, irq) == 1)
free_percpu_nmi(irq, devid);
}
@@ -100,11 +100,20 @@ static const struct pmu_irq_ops percpu_pmunmi_ops = {
};
DEFINE_PER_CPU(struct arm_pmu *, cpu_armpmu);
+static DEFINE_PER_CPU(const struct cpumask *, pmu_affinity);
static DEFINE_PER_CPU(int, cpu_irq);
static DEFINE_PER_CPU(const struct pmu_irq_ops *, cpu_irq_ops);
static bool has_nmi;
+void armpmu_register_affinity_group(const struct cpumask *aff_grp)
+{
+ int cpu;
+
+ for_each_cpu(cpu, aff_grp)
+ per_cpu(pmu_affinity, cpu) = aff_grp;
+}
+
static inline u64 arm_pmu_event_max_period(struct perf_event *event)
{
if (event->hw.flags & ARMPMU_EVT_64BIT)
@@ -580,11 +589,16 @@ static const struct attribute_group armpmu_common_attr_group = {
.attrs = armpmu_common_attrs,
};
-static int armpmu_count_irq_users(const int irq)
+static int armpmu_count_irq_users(const int this_cpu, const int irq)
{
+ const struct cpumask *affinity;
int cpu, count = 0;
- for_each_possible_cpu(cpu) {
+ affinity = per_cpu(pmu_affinity, this_cpu);
+ if (WARN_ON(!affinity))
+ return 0;
+
+ for_each_cpu(cpu, affinity) {
if (per_cpu(cpu_irq, cpu) == irq)
count++;
}
@@ -592,12 +606,17 @@ static int armpmu_count_irq_users(const int irq)
return count;
}
-static const struct pmu_irq_ops *armpmu_find_irq_ops(int irq)
+static const struct pmu_irq_ops *armpmu_find_irq_ops(int this_cpu, int irq)
{
const struct pmu_irq_ops *ops = NULL;
+ const struct cpumask *affinity;
int cpu;
- for_each_possible_cpu(cpu) {
+ affinity = per_cpu(pmu_affinity, this_cpu);
+ if (!affinity)
+ return NULL;
+
+ for_each_cpu(cpu, affinity) {
if (per_cpu(cpu_irq, cpu) != irq)
continue;
@@ -658,7 +677,7 @@ int armpmu_request_irq(int irq, int cpu)
has_nmi = true;
irq_ops = &pmunmi_ops;
}
- } else if (armpmu_count_irq_users(irq) == 0) {
+ } else if (armpmu_count_irq_users(cpu, irq) == 0) {
err = request_percpu_nmi(irq, handler, "arm-pmu", &cpu_armpmu);
/* If cannot get an NMI, get a normal interrupt */
@@ -672,7 +691,7 @@ int armpmu_request_irq(int irq, int cpu)
}
} else {
/* Per cpudevid irq was already requested by another CPU */
- irq_ops = armpmu_find_irq_ops(irq);
+ irq_ops = armpmu_find_irq_ops(cpu, irq);
if (WARN_ON(!irq_ops))
err = -EINVAL;
diff --git a/drivers/perf/arm_pmu_acpi.c b/drivers/perf/arm_pmu_acpi.c
index 05dda19c5359a..a5956fa728070 100644
--- a/drivers/perf/arm_pmu_acpi.c
+++ b/drivers/perf/arm_pmu_acpi.c
@@ -212,6 +212,11 @@ static int arm_pmu_acpi_parse_irqs(void)
pr_warn("No ACPI PMU IRQ for CPU%d\n", cpu);
}
+ if (irq_is_percpu_devid(irq))
+ armpmu_register_affinity_group(cpu_possible_mask);
+ else
+ armpmu_register_affinity_group(cpumask_of(cpu));
+
/*
* Log and request the IRQ so the core arm_pmu code can manage
* it. We'll have to sanity-check IRQs later when we associate
diff --git a/drivers/perf/arm_pmu_platform.c b/drivers/perf/arm_pmu_platform.c
index 9c0494d8a867a..0c7d5065e9074 100644
--- a/drivers/perf/arm_pmu_platform.c
+++ b/drivers/perf/arm_pmu_platform.c
@@ -53,6 +53,8 @@ static int pmu_parse_percpu_irq(struct arm_pmu *pmu, int irq,
for_each_cpu(cpu, &pmu->supported_cpus)
per_cpu(hw_events->irq, cpu) = irq;
+ armpmu_register_affinity_group(&pmu->supported_cpus);
+
return 0;
}
@@ -152,6 +154,8 @@ static int pmu_parse_irqs(struct arm_pmu *pmu)
cpumask_set_cpu(cpu, &pmu->supported_cpus);
}
+ armpmu_register_affinity_group(&pmu->supported_cpus);
+
return 0;
}
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
index 93c9a26492fcf..7bf548678b288 100644
--- a/include/linux/perf/arm_pmu.h
+++ b/include/linux/perf/arm_pmu.h
@@ -171,6 +171,7 @@ struct pmu_probe_info {
int arm_pmu_device_probe(struct platform_device *pdev,
const struct of_device_id *of_table,
const struct pmu_probe_info *probe_table);
+void armpmu_register_affinity_group(const struct cpumask *);
#ifdef CONFIG_ACPI
int arm_pmu_acpi_probe(armpmu_init_fn init_fn);
--
2.39.2
next prev parent reply other threads:[~2025-09-09 6:46 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-08 16:31 [PATCH 00/25] genirq: Add support for percpu_devid IRQ affinity Marc Zyngier
2025-09-08 16:31 ` [PATCH 01/25] irqdomain: Add firmware info reporting interface Marc Zyngier
2025-09-09 9:18 ` Thomas Gleixner
2025-09-09 9:24 ` Thomas Gleixner
2025-09-11 14:13 ` Marc Zyngier
2025-09-11 15:49 ` Thomas Gleixner
2025-09-08 16:31 ` [PATCH 02/25] ACPI: irq: Add IRQ affinity " Marc Zyngier
2025-09-08 17:20 ` Rafael J. Wysocki
2025-09-08 16:31 ` [PATCH 03/25] of/irq: " Marc Zyngier
2025-09-08 16:31 ` [PATCH 04/25] platform: Add firmware-agnostic irq and affinity retrieval interface Marc Zyngier
2025-09-08 16:31 ` [PATCH 05/25] irqchip/gic-v3: Add FW info retrieval support Marc Zyngier
2025-09-09 9:37 ` Thomas Gleixner
2025-09-08 16:31 ` [PATCH 06/25] irqchip/apple-aic: " Marc Zyngier
2025-09-08 16:31 ` [PATCH 07/25] coresight: trbe: Convert to new IRQ affinity retrieval API Marc Zyngier
2025-09-08 16:31 ` [PATCH 08/25] perf: arm_pmu: " Marc Zyngier
2025-09-08 16:31 ` [PATCH 09/25] perf: arm_spe_pmu: " Marc Zyngier
2025-09-08 16:31 ` Marc Zyngier [this message]
2025-09-08 16:31 ` [PATCH 11/25] genirq: Merge irqaction::{dev_id,percpu_dev_id} Marc Zyngier
2025-09-08 16:31 ` [PATCH 12/25] genirq: Factor-in percpu irqaction creation Marc Zyngier
2025-09-09 9:41 ` Thomas Gleixner
2025-09-08 16:31 ` [PATCH 13/25] genirq: Add affinity to percpu_devid interrupt requests Marc Zyngier
2025-09-08 16:31 ` [PATCH 14/25] genirq: Update request_percpu_nmi() to take an affinity Marc Zyngier
2025-09-09 9:45 ` Thomas Gleixner
2025-09-09 11:21 ` Marc Zyngier
2025-09-08 16:31 ` [PATCH 15/25] genirq: Allow per-cpu interrupt sharing for non-overlapping affinities Marc Zyngier
2025-09-10 8:28 ` Marc Zyngier
2025-09-10 14:47 ` Thomas Gleixner
2025-09-10 15:44 ` Marc Zyngier
2025-09-08 16:31 ` [PATCH 16/25] genirq: Add request_percpu_irq_affinity() helper Marc Zyngier
2025-09-08 16:31 ` [PATCH 17/25] perf: arm_pmu: Use a backend-specific pointer for percpu interrupt request Marc Zyngier
2025-09-08 16:31 ` [PATCH 18/25] perf: arm_pmu: Request specific affinities for percpu NMI/IRQ Marc Zyngier
2025-09-08 16:31 ` [PATCH 19/25] perf: arm_spe_pmu: Request specific affinities for percpu IRQ Marc Zyngier
2025-09-08 16:31 ` [PATCH 20/25] coresight: trbe: " Marc Zyngier
2025-09-08 16:31 ` [PATCH 21/25] irqchip/gic-v3: Drop support for custom PPI partitions Marc Zyngier
2025-09-08 16:31 ` [PATCH 22/25] irqchip/apple-aic: Drop support for custom PMU irq partitions Marc Zyngier
2025-09-08 16:31 ` [PATCH 23/25] irqchip: Kill irq-partition-percpu Marc Zyngier
2025-09-08 16:31 ` [PATCH 24/25] genirq: Kill irq_{g,s}et_percpu_devid_partition() Marc Zyngier
2025-09-08 16:31 ` [PATCH 25/25] perf: arm_pmu: Kill last use of per-CPU cpu_armpmu pointer Marc Zyngier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250908163127.2462948-11-maz@kernel.org \
--to=maz@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=j@jannau.net \
--cc=james.clark@linaro.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=rafael@kernel.org \
--cc=robh@kernel.org \
--cc=saravanak@google.com \
--cc=suzuki.poulose@arm.com \
--cc=sven@kernel.org \
--cc=tglx@linutronix.de \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).