From: Lorenzo Pieralisi <lpieralisi@kernel.org>
To: Marc Zyngier <maz@kernel.org>,
Thomas Gleixner <tglx@linutronix.de>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>,
Sascha Bischoff <sascha.bischoff@arm.com>,
Jonathan Cameron <Jonathan.Cameron@huawei.com>,
Timothy Hayes <timothy.hayes@arm.com>,
Bjorn Helgaas <bhelgaas@google.com>,
"Liam R. Howlett" <Liam.Howlett@oracle.com>,
Peter Maydell <peter.maydell@linaro.org>,
Mark Rutland <mark.rutland@arm.com>,
Jiri Slaby <jirislaby@kernel.org>,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
linux-pci@vger.kernel.org,
Lorenzo Pieralisi <lpieralisi@kernel.org>
Subject: [PATCH v7 18/31] arm64: smp: Support non-SGIs for IPIs
Date: Thu, 03 Jul 2025 12:25:08 +0200 [thread overview]
Message-ID: <20250703-gicv5-host-v7-18-12e71f1b3528@kernel.org> (raw)
In-Reply-To: <20250703-gicv5-host-v7-0-12e71f1b3528@kernel.org>
From: Marc Zyngier <maz@kernel.org>
The arm64 arch has relied so far on GIC architectural software
generated interrupt (SGIs) to handle IPIs. Those are per-cpu
software generated interrupts.
arm64 architecture code that allocates the IPIs virtual IRQs and
IRQ descriptors was written accordingly.
On GICv5 systems, IPIs are implemented using LPIs that are not
per-cpu interrupts - they are just normal routable IRQs.
Add arch code to set-up IPIs on systems where they are handled
using normal routable IRQs.
For those systems, force the IRQ affinity (and make it immutable)
to the cpu a given IRQ was assigned to.
Signed-off-by: Marc Zyngier <maz@kernel.org>
[timothy.hayes@arm.com: fixed ipi/irq conversion, irq flags]
Signed-off-by: Timothy Hayes <timothy.hayes@arm.com>
[lpieralisi: changed affinity set-up, log]
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Will Deacon <will@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/smp.h | 7 ++-
arch/arm64/kernel/smp.c | 127 +++++++++++++++++++++++++++++++------------
2 files changed, 99 insertions(+), 35 deletions(-)
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 2510eec026f7..d6fd6efb66a6 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -53,7 +53,12 @@ extern void smp_init_cpus(void);
/*
* Register IPI interrupts with the arch SMP code
*/
-extern void set_smp_ipi_range(int ipi_base, int nr_ipi);
+extern void set_smp_ipi_range_percpu(int ipi_base, int nr_ipi, int ncpus);
+
+static inline void set_smp_ipi_range(int ipi_base, int n)
+{
+ set_smp_ipi_range_percpu(ipi_base, n, 0);
+}
/*
* Called from the secondary holding pen, this is the secondary CPU entry point.
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 3b3f6b56e733..2c501e917d38 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -83,7 +83,16 @@ enum ipi_msg_type {
static int ipi_irq_base __ro_after_init;
static int nr_ipi __ro_after_init = NR_IPI;
-static struct irq_desc *ipi_desc[MAX_IPI] __ro_after_init;
+
+struct ipi_descs {
+ struct irq_desc *descs[MAX_IPI];
+};
+
+static DEFINE_PER_CPU_READ_MOSTLY(struct ipi_descs, pcpu_ipi_desc);
+
+#define get_ipi_desc(__cpu, __ipi) (per_cpu_ptr(&pcpu_ipi_desc, __cpu)->descs[__ipi])
+
+static bool percpu_ipi_descs __ro_after_init;
static bool crash_stop;
@@ -844,7 +853,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i,
prec >= 4 ? " " : "");
for_each_online_cpu(cpu)
- seq_printf(p, "%10u ", irq_desc_kstat_cpu(ipi_desc[i], cpu));
+ seq_printf(p, "%10u ", irq_desc_kstat_cpu(get_ipi_desc(cpu, i), cpu));
seq_printf(p, " %s\n", ipi_types[i]);
}
@@ -917,9 +926,20 @@ static void __noreturn ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs
#endif
}
+static void arm64_send_ipi(const cpumask_t *mask, unsigned int nr)
+{
+ unsigned int cpu;
+
+ if (!percpu_ipi_descs)
+ __ipi_send_mask(get_ipi_desc(0, nr), mask);
+ else
+ for_each_cpu(cpu, mask)
+ __ipi_send_single(get_ipi_desc(cpu, nr), cpu);
+}
+
static void arm64_backtrace_ipi(cpumask_t *mask)
{
- __ipi_send_mask(ipi_desc[IPI_CPU_BACKTRACE], mask);
+ arm64_send_ipi(mask, IPI_CPU_BACKTRACE);
}
void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu)
@@ -944,7 +964,7 @@ void kgdb_roundup_cpus(void)
if (cpu == this_cpu)
continue;
- __ipi_send_single(ipi_desc[IPI_KGDB_ROUNDUP], cpu);
+ __ipi_send_single(get_ipi_desc(cpu, IPI_KGDB_ROUNDUP), cpu);
}
}
#endif
@@ -1013,14 +1033,16 @@ static void do_handle_IPI(int ipinr)
static irqreturn_t ipi_handler(int irq, void *data)
{
- do_handle_IPI(irq - ipi_irq_base);
+ unsigned int ipi = (irq - ipi_irq_base) % nr_ipi;
+
+ do_handle_IPI(ipi);
return IRQ_HANDLED;
}
static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
{
trace_ipi_raise(target, ipi_types[ipinr]);
- __ipi_send_mask(ipi_desc[ipinr], target);
+ arm64_send_ipi(target, ipinr);
}
static bool ipi_should_be_nmi(enum ipi_msg_type ipi)
@@ -1046,11 +1068,15 @@ static void ipi_setup(int cpu)
return;
for (i = 0; i < nr_ipi; i++) {
- if (ipi_should_be_nmi(i)) {
- prepare_percpu_nmi(ipi_irq_base + i);
- enable_percpu_nmi(ipi_irq_base + i, 0);
+ if (!percpu_ipi_descs) {
+ if (ipi_should_be_nmi(i)) {
+ prepare_percpu_nmi(ipi_irq_base + i);
+ enable_percpu_nmi(ipi_irq_base + i, 0);
+ } else {
+ enable_percpu_irq(ipi_irq_base + i, 0);
+ }
} else {
- enable_percpu_irq(ipi_irq_base + i, 0);
+ enable_irq(irq_desc_get_irq(get_ipi_desc(cpu, i)));
}
}
}
@@ -1064,44 +1090,77 @@ static void ipi_teardown(int cpu)
return;
for (i = 0; i < nr_ipi; i++) {
- if (ipi_should_be_nmi(i)) {
- disable_percpu_nmi(ipi_irq_base + i);
- teardown_percpu_nmi(ipi_irq_base + i);
+ if (!percpu_ipi_descs) {
+ if (ipi_should_be_nmi(i)) {
+ disable_percpu_nmi(ipi_irq_base + i);
+ teardown_percpu_nmi(ipi_irq_base + i);
+ } else {
+ disable_percpu_irq(ipi_irq_base + i);
+ }
} else {
- disable_percpu_irq(ipi_irq_base + i);
+ disable_irq(irq_desc_get_irq(get_ipi_desc(cpu, i)));
}
}
}
#endif
-void __init set_smp_ipi_range(int ipi_base, int n)
+static void ipi_setup_sgi(int ipi)
+{
+ int err, irq, cpu;
+
+ irq = ipi_irq_base + ipi;
+
+ if (ipi_should_be_nmi(irq)) {
+ err = request_percpu_nmi(irq, ipi_handler, "IPI", &irq_stat);
+ WARN(err, "Could not request IRQ %d as NMI, err=%d\n", irq, err);
+ } else {
+ err = request_percpu_irq(irq, ipi_handler, "IPI", &irq_stat);
+ WARN(err, "Could not request IRQ %d as IRQ, err=%d\n", irq, err);
+ }
+
+ for_each_possible_cpu(cpu)
+ get_ipi_desc(cpu, ipi) = irq_to_desc(irq);
+
+ irq_set_status_flags(irq, IRQ_HIDDEN);
+}
+
+static void ipi_setup_lpi(int ipi, int ncpus)
+{
+ for (int cpu = 0; cpu < ncpus; cpu++) {
+ int err, irq;
+
+ irq = ipi_irq_base + (cpu * nr_ipi) + ipi;
+
+ err = irq_force_affinity(irq, cpumask_of(cpu));
+ WARN(err, "Could not force affinity IRQ %d, err=%d\n", irq, err);
+
+ err = request_irq(irq, ipi_handler, IRQF_NO_AUTOEN, "IPI",
+ NULL);
+ WARN(err, "Could not request IRQ %d, err=%d\n", irq, err);
+
+ irq_set_status_flags(irq, (IRQ_HIDDEN | IRQ_NO_BALANCING_MASK));
+
+ get_ipi_desc(cpu, ipi) = irq_to_desc(irq);
+ }
+}
+
+void __init set_smp_ipi_range_percpu(int ipi_base, int n, int ncpus)
{
int i;
WARN_ON(n < MAX_IPI);
nr_ipi = min(n, MAX_IPI);
- for (i = 0; i < nr_ipi; i++) {
- int err;
-
- if (ipi_should_be_nmi(i)) {
- err = request_percpu_nmi(ipi_base + i, ipi_handler,
- "IPI", &irq_stat);
- WARN(err, "Could not request IPI %d as NMI, err=%d\n",
- i, err);
- } else {
- err = request_percpu_irq(ipi_base + i, ipi_handler,
- "IPI", &irq_stat);
- WARN(err, "Could not request IPI %d as IRQ, err=%d\n",
- i, err);
- }
-
- ipi_desc[i] = irq_to_desc(ipi_base + i);
- irq_set_status_flags(ipi_base + i, IRQ_HIDDEN);
- }
-
+ percpu_ipi_descs = !!ncpus;
ipi_irq_base = ipi_base;
+ for (i = 0; i < nr_ipi; i++) {
+ if (!percpu_ipi_descs)
+ ipi_setup_sgi(i);
+ else
+ ipi_setup_lpi(i, ncpus);
+ }
+
/* Setup the boot CPU immediately */
ipi_setup(smp_processor_id());
}
--
2.48.0
next prev parent reply other threads:[~2025-07-03 10:26 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-03 10:24 [PATCH v7 00/31] Arm GICv5: Host driver implementation Lorenzo Pieralisi
2025-07-03 10:24 ` [PATCH v7 01/31] dt-bindings: interrupt-controller: Add Arm GICv5 Lorenzo Pieralisi
2025-07-03 10:24 ` [PATCH v7 02/31] arm64/sysreg: Add GCIE field to ID_AA64PFR2_EL1 Lorenzo Pieralisi
2025-07-03 15:57 ` Catalin Marinas
2025-07-03 10:24 ` [PATCH v7 03/31] arm64/sysreg: Add ICC_PPI_PRIORITY<n>_EL1 Lorenzo Pieralisi
2025-07-03 15:58 ` Catalin Marinas
2025-07-03 10:24 ` [PATCH v7 04/31] arm64/sysreg: Add ICC_ICSR_EL1 Lorenzo Pieralisi
2025-07-03 15:58 ` Catalin Marinas
2025-07-03 10:24 ` [PATCH v7 05/31] arm64/sysreg: Add ICC_PPI_HMR<n>_EL1 Lorenzo Pieralisi
2025-07-03 15:58 ` Catalin Marinas
2025-07-03 10:24 ` [PATCH v7 06/31] arm64/sysreg: Add ICC_PPI_ENABLER<n>_EL1 Lorenzo Pieralisi
2025-07-03 15:58 ` Catalin Marinas
2025-07-03 10:24 ` [PATCH v7 07/31] arm64/sysreg: Add ICC_PPI_{C/S}ACTIVER<n>_EL1 Lorenzo Pieralisi
2025-07-03 15:59 ` Catalin Marinas
2025-07-03 10:24 ` [PATCH v7 08/31] arm64/sysreg: Add ICC_PPI_{C/S}PENDR<n>_EL1 Lorenzo Pieralisi
2025-07-03 15:59 ` Catalin Marinas
2025-07-03 10:24 ` [PATCH v7 09/31] arm64/sysreg: Add ICC_CR0_EL1 Lorenzo Pieralisi
2025-07-03 15:59 ` Catalin Marinas
2025-07-03 10:25 ` [PATCH v7 10/31] arm64/sysreg: Add ICC_PCR_EL1 Lorenzo Pieralisi
2025-07-03 16:00 ` Catalin Marinas
2025-07-03 10:25 ` [PATCH v7 11/31] arm64/sysreg: Add ICC_IDR0_EL1 Lorenzo Pieralisi
2025-07-03 16:01 ` Catalin Marinas
2025-07-03 10:25 ` [PATCH v7 12/31] arm64/sysreg: Add ICH_HFGRTR_EL2 Lorenzo Pieralisi
2025-07-03 16:02 ` Catalin Marinas
2025-07-03 10:25 ` [PATCH v7 13/31] arm64/sysreg: Add ICH_HFGWTR_EL2 Lorenzo Pieralisi
2025-07-03 16:02 ` Catalin Marinas
2025-07-03 10:25 ` [PATCH v7 14/31] arm64/sysreg: Add ICH_HFGITR_EL2 Lorenzo Pieralisi
2025-07-03 16:02 ` Catalin Marinas
2025-07-03 10:25 ` [PATCH v7 15/31] arm64: Disable GICv5 read/write/instruction traps Lorenzo Pieralisi
2025-07-03 16:03 ` Catalin Marinas
2025-07-03 10:25 ` [PATCH v7 16/31] arm64: cpucaps: Rename GICv3 CPU interface capability Lorenzo Pieralisi
2025-07-03 16:03 ` Catalin Marinas
2025-07-03 10:25 ` [PATCH v7 17/31] arm64: cpucaps: Add GICv5 CPU interface (GCIE) capability Lorenzo Pieralisi
2025-07-03 16:04 ` Catalin Marinas
2025-07-03 10:25 ` Lorenzo Pieralisi [this message]
2025-07-03 16:04 ` [PATCH v7 18/31] arm64: smp: Support non-SGIs for IPIs Catalin Marinas
2025-07-15 14:10 ` Breno Leitao
2025-07-15 14:34 ` Lorenzo Pieralisi
2025-07-15 16:07 ` Lorenzo Pieralisi
2025-07-15 16:14 ` Breno Leitao
2025-07-03 10:25 ` [PATCH v7 19/31] arm64: Add support for GICv5 GSB barriers Lorenzo Pieralisi
2025-07-03 16:04 ` Catalin Marinas
2025-07-03 10:25 ` [PATCH v7 20/31] irqchip/gic-v5: Add GICv5 PPI support Lorenzo Pieralisi
2025-07-03 16:05 ` Catalin Marinas
2025-07-03 10:25 ` [PATCH v7 21/31] irqchip/gic-v5: Add GICv5 IRS/SPI support Lorenzo Pieralisi
2025-07-03 16:07 ` Catalin Marinas
2025-07-03 10:25 ` [PATCH v7 22/31] irqchip/gic-v5: Add GICv5 LPI/IPI support Lorenzo Pieralisi
2025-07-03 16:07 ` Catalin Marinas
2025-08-07 11:52 ` Jinjie Ruan
2025-08-07 13:51 ` Lorenzo Pieralisi
2025-08-08 1:20 ` Jinjie Ruan
2025-08-08 8:19 ` Lorenzo Pieralisi
2025-08-08 8:48 ` Jinjie Ruan
2025-07-03 10:25 ` [PATCH v7 23/31] irqchip/gic-v5: Enable GICv5 SMP booting Lorenzo Pieralisi
2025-07-03 10:25 ` [PATCH v7 24/31] of/irq: Add of_msi_xlate() helper function Lorenzo Pieralisi
2025-07-03 14:52 ` Rob Herring
2025-07-03 10:25 ` [PATCH v7 25/31] PCI/MSI: Add pci_msi_map_rid_ctlr_node() " Lorenzo Pieralisi
2025-07-03 10:25 ` [PATCH v7 26/31] irqchip/gic-v3: Rename GICv3 ITS MSI parent Lorenzo Pieralisi
2025-07-03 10:25 ` [PATCH v7 27/31] irqchip/msi-lib: Add IRQ_DOMAIN_FLAG_FWNODE_PARENT handling Lorenzo Pieralisi
2025-07-03 10:25 ` [PATCH v7 28/31] irqchip/gic-v5: Add GICv5 ITS support Lorenzo Pieralisi
2025-07-03 10:25 ` [PATCH v7 29/31] irqchip/gic-v5: Add GICv5 IWB support Lorenzo Pieralisi
2025-07-03 10:25 ` [PATCH v7 30/31] docs: arm64: gic-v5: Document booting requirements for GICv5 Lorenzo Pieralisi
2025-07-03 16:08 ` Catalin Marinas
2025-07-03 10:25 ` [PATCH v7 31/31] arm64: Kconfig: Enable GICv5 Lorenzo Pieralisi
2025-07-03 16:09 ` Catalin Marinas
2025-07-03 15:47 ` [PATCH v7 00/31] Arm GICv5: Host driver implementation Jonathan Cameron
2025-07-04 10:01 ` Lorenzo Pieralisi
2025-07-08 18:18 ` 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=20250703-gicv5-host-v7-18-12e71f1b3528@kernel.org \
--to=lpieralisi@kernel.org \
--cc=Jonathan.Cameron@huawei.com \
--cc=Liam.Howlett@oracle.com \
--cc=arnd@arndb.de \
--cc=bhelgaas@google.com \
--cc=catalin.marinas@arm.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=jirislaby@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=maz@kernel.org \
--cc=peter.maydell@linaro.org \
--cc=robh@kernel.org \
--cc=sascha.bischoff@arm.com \
--cc=tglx@linutronix.de \
--cc=timothy.hayes@arm.com \
--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).