* [PATCH Dovetail 6.18 0/3] Fix IPI mapping for arm64
@ 2026-02-02 7:55 Florian Bezdeka
2026-02-02 7:55 ` [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs Florian Bezdeka
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Florian Bezdeka @ 2026-02-02 7:55 UTC (permalink / raw)
To: xenomai; +Cc: Philippe Gerum, Jan Kiszka, Florian Bezdeka
Hi all,
this is the result of a quite longish debugging session revealed by some
sporadic failures seen in CI.
Please review carefully as the code paths around the KGDB and BACKTRACE IPI
are not part of the hot path.
Backporting:
Patches 2 and 3 should go into Dovetail 6.12 as well. Older versions do
not have the BACKTRACE and KGDB IPIs implemented.
Cc: Philippe Gerum <rpm@xenomai.org>
Cc: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
Florian Bezdeka (3):
arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs
arm64: irq_pipeline: Fix size of IPI statistics array
arm64: irq_pipeline: Fix IPI_KGDB_ROUNDUP and IPI_CPU_BACKTRACE IPIs
arch/arm64/kernel/smp.c | 81 +++++++++++++++++++++++++++++--------------------
1 file changed, 48 insertions(+), 33 deletions(-)
---
base-commit: c30f265e8ac5feb0b7076141dd8877d0394e1437
change-id: 20260201-wip-flo-fixes-for-6-18-a2979277ddce
Best regards,
--
Florian Bezdeka <florian.bezdeka@siemens.com>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs
2026-02-02 7:55 [PATCH Dovetail 6.18 0/3] Fix IPI mapping for arm64 Florian Bezdeka
@ 2026-02-02 7:55 ` Florian Bezdeka
2026-02-03 13:08 ` Philippe Gerum
2026-02-02 7:55 ` [PATCH Dovetail 6.18 2/3] arm64: irq_pipeline: Fix size of IPI statistics array Florian Bezdeka
2026-02-02 7:55 ` [PATCH Dovetail 6.18 3/3] arm64: irq_pipeline: Fix IPI_KGDB_ROUNDUP and IPI_CPU_BACKTRACE IPIs Florian Bezdeka
2 siblings, 1 reply; 15+ messages in thread
From: Florian Bezdeka @ 2026-02-02 7:55 UTC (permalink / raw)
To: xenomai; +Cc: Philippe Gerum, Jan Kiszka, Florian Bezdeka
There were two problems with the mapping:
- We stopped mapping after OOB_NR_IPI (3) IPIs.
There are more IPIs after the last IPI reserved for OOB
- In the LPI case everything was mapped to the IRQ desc of CPU 0,
which seems odd. Each CPU has its own LPI used for multiplexing
inband IPIs.
The following splat was observed whent trying to handle a backtrace
IPI. This is one of the IPIs located after the OOB IPIs.
[ 115.357495] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000048
[ 115.358088] Mem abort info:
[ 115.358216] ESR = 0x0000000096000004
[ 115.358394] EC = 0x25: DABT (current EL), IL = 32 bits
[ 115.358624] SET = 0, FnV = 0
[ 115.358762] EA = 0, S1PTW = 0
[ 115.358910] FSC = 0x04: level 0 translation fault
[ 115.359117] Data abort info:
[ 115.359254] ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
[ 115.359498] CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[ 115.359718] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[ 115.359990] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000042d15000
[ 115.360386] [0000000000000048] pgd=0000000000000000, p4d=0000000000000000
[ 115.361730] Internal error: Oops: 0000000096000004 [#1] SMP
[ 115.361868] Modules linked in: cfg80211 rfkill drm fuse drm_panel_orientation_quirks ipv6
[ 115.362470] CPU: 1 UID: 0 PID: 15 Comm: rcu_preempt Not tainted 6.18.2 #1 PREEMPT
[ 115.362533] Hardware name: linux,dummy-virt (DT)
[ 115.362561] IRQ stage: Linux
[ 115.362746] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 115.362794] pc : __ipi_send_mask+0x18/0x108
[ 115.363335] lr : arm64_backtrace_ipi+0xa8/0xc0
[ 115.363372] sp : ffff80008215b840
[ 115.363388] x29: ffff80008215b840 x28: 0000000000000080 x27: ffff800081cfeec0
[ 115.363481] x26: ffff8000818b6000 x25: ffffffffffffffff x24: 0000000000000040
[ 115.363505] x23: 0000000000000001 x22: ffff800080041080 x21: ffff800082089d98
[ 115.363527] x20: ffff800081c72e40 x19: 0000000000000030 x18: 000000000000019b
[ 115.363548] x17: 74666f7320303030 x16: 3030303030303030 x15: 0000000000000001
[ 115.363569] x14: 0000000000000000 x13: 3a30207355504320 x12: ffff800081c8de70
[ 115.363590] x11: 0000000000000058 x10: 0000000000000018 x9 : ffff800081c8de70
[ 115.363633] x8 : 000000000000019c x7 : ffff800081ce5e70 x6 : ffff800081ce5e70
[ 115.363654] x5 : ffff00001fec25c8 x4 : 0000000000000000 x3 : 0000000000000000
[ 115.363674] x2 : ffff7fff9e316000 x1 : ffff800081c72e40 x0 : 0000000000000000
[ 115.363805] Call trace:
[ 115.364002] __ipi_send_mask+0x18/0x108 (P)
[ 115.364213] arm64_backtrace_ipi+0xa8/0xc0
[ 115.364266] nmi_trigger_cpumask_backtrace+0x1e0/0x1f4
[ 115.364295] arch_trigger_cpumask_backtrace+0x18/0x24
[ 115.364315] dump_cpu_task+0x74/0x80
[ 115.364337] rcu_dump_cpu_stacks+0x150/0x1b8
[ 115.364356] rcu_sched_clock_irq+0xc7c/0xebc
[ 115.364377] update_process_times+0x7c/0xe0
[ 115.364400] tick_nohz_handler+0xbc/0x150
[ 115.364420] __hrtimer_run_queues+0x168/0x2f0
[ 115.364436] hrtimer_interrupt+0xec/0x258
[ 115.364451] proxy_irq_handler+0x24/0x40
[ 115.364469] handle_synthetic_irq+0x94/0x1dc
[ 115.364503] handle_irq_desc+0x38/0x5c
[ 115.364521] arch_do_IRQ_pipelined+0x44/0x80
[ 115.364538] sync_current_irq_stage+0x160/0x200
[ 115.364555] __inband_irq_enable+0x5c/0x70
[ 115.364572] inband_irq_restore+0x28/0x40
[ 115.364589] resched_cpu+0x98/0xc0
[ 115.364606] force_qs_rnp+0x27c/0x34c
[ 115.364623] rcu_gp_fqs_loop+0x304/0x4c4
[ 115.364641] rcu_gp_kthread+0x130/0x15c
[ 115.364659] kthread+0x144/0x200
[ 115.364677] ret_from_fork+0x10/0x20
[ 115.364928] Code: 910003fd a90153f3 9100c013 a9025bf5 (f9400e75)
[ 115.365743] ---[ end trace 0000000000000000 ]---
[ 115.366033] Kernel panic - not syncing: Oops: Fatal exception in interrupt
[ 115.366216] SMP: stopping secondary CPUs
[ 116.728391] SMP: failed to stop secondary CPUs 0
[ 116.728668] Kernel Offset: disabled
[ 116.728691] CPU features: 0x082000,04046800,40004000,0400421b
[ 116.728736] Memory Limit: none
[ 116.739224] ---[ end Kernel panic - not syncing: Oops: Fatal exception in interrupt ]---
Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
arch/arm64/kernel/smp.c | 50 +++++++++++++++++++++++++------------------------
1 file changed, 26 insertions(+), 24 deletions(-)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 3a12956580a35..e8cee27dc1132 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -1020,28 +1020,25 @@ static void do_handle_IPI(int ipinr)
#ifdef CONFIG_IRQ_PIPELINE
-static inline void map_oob_ipis(int cpu)
+static inline void map_oob_ipis(int cpu, unsigned int irq)
{
int ipi;
- for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
- get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
+ for (ipi = OOB_IPI_OFFSET; ipi < nr_ipi; ipi++)
+ get_ipi_desc(cpu, ipi) = irq_to_desc(irq);
}
-static void ipi_setup_oob_sgi(void)
+static void ipi_setup_oob_sgi(unsigned int irq)
{
int cpu;
for_each_possible_cpu(cpu)
- map_oob_ipis(cpu);
+ map_oob_ipis(cpu, irq);
}
-static void ipi_setup_oob_lpi(int ncpus)
+static void ipi_setup_oob_lpi(unsigned int irq, int cpu)
{
- int cpu;
-
- for (cpu = 0; cpu < ncpus; cpu++)
- map_oob_ipis(cpu);
+ map_oob_ipis(cpu, irq);
}
static void __smp_cross_call(const struct cpumask *target, unsigned int ipinr)
@@ -1061,7 +1058,7 @@ static irqreturn_t ipi_handler(int irq, void *data)
/*
* Decode in-band IPIs (0..NR_IPI - 1) multiplexed over
- * SGI0. Out-of-band IPIs (SGI1, SGI2) have their own
+ * SGI0. Out-of-band IPIs (SGI1, SGI2, SGI3) have their own
* individual handler.
*/
pmsg = raw_cpu_ptr(&ipi_messages);
@@ -1108,10 +1105,10 @@ EXPORT_SYMBOL_GPL(irq_send_oob_ipi);
#else
-static inline void ipi_setup_oob_sgi(void)
+static inline void ipi_setup_oob_sgi(unsigned int irq)
{ }
-static inline void ipi_setup_oob_lpi(int ncpus)
+static inline void ipi_setup_oob_lpi(unsigned int irq, int cpu)
{ }
static irqreturn_t ipi_handler(int irq, void *data)
@@ -1214,6 +1211,14 @@ static void ipi_setup_sgi(int ipi)
get_ipi_desc(cpu, ipi) = irq_to_desc(irq);
irq_set_status_flags(irq, IRQ_HIDDEN);
+
+ /*
+ * irq_pipeline: although a single IPI will be requested for
+ * in-band operations, all IPI descriptors have to be mapped,
+ * so that arm64_send_ipi() can issue out-of-band IPIs as
+ * well.
+ */
+ ipi_setup_oob_sgi(irq);
}
static void ipi_setup_lpi(int ipi, int ncpus)
@@ -1233,6 +1238,14 @@ static void ipi_setup_lpi(int ipi, int ncpus)
irq_set_status_flags(irq, (IRQ_HIDDEN | IRQ_NO_BALANCING_MASK));
get_ipi_desc(cpu, ipi) = irq_to_desc(irq);
+
+ /*
+ * irq_pipeline: although a single IPI will be requested for
+ * in-band operations, all IPI descriptors have to be mapped,
+ * so that arm64_send_ipi() can issue out-of-band IPIs as
+ * well.
+ */
+ ipi_setup_oob_lpi(irq, ncpus);
}
}
@@ -1264,17 +1277,6 @@ void __init set_smp_ipi_range_percpu(int ipi_base, int n, int ncpus)
ipi_setup_lpi(i, ncpus);
}
- /*
- * irq_pipeline: although a single IPI will be requested for
- * in-band operations, all IPI descriptors have to be mapped,
- * so that arm64_send_ipi() can issue out-of-band IPIs as
- * well.
- */
- if (!percpu_ipi_descs)
- ipi_setup_oob_sgi();
- else
- ipi_setup_oob_lpi(ncpus);
-
/* Setup the boot CPU immediately */
ipi_setup(smp_processor_id());
}
--
2.39.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH Dovetail 6.18 2/3] arm64: irq_pipeline: Fix size of IPI statistics array
2026-02-02 7:55 [PATCH Dovetail 6.18 0/3] Fix IPI mapping for arm64 Florian Bezdeka
2026-02-02 7:55 ` [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs Florian Bezdeka
@ 2026-02-02 7:55 ` Florian Bezdeka
2026-02-03 11:59 ` Philippe Gerum
2026-02-02 7:55 ` [PATCH Dovetail 6.18 3/3] arm64: irq_pipeline: Fix IPI_KGDB_ROUNDUP and IPI_CPU_BACKTRACE IPIs Florian Bezdeka
2 siblings, 1 reply; 15+ messages in thread
From: Florian Bezdeka @ 2026-02-02 7:55 UTC (permalink / raw)
To: xenomai; +Cc: Philippe Gerum, Jan Kiszka, Florian Bezdeka
NR_IPI is not the last possible IPI, it's the last traceable IPI.
IPI_CPU_BACKTRACE and IPI_KGDB_ROUNDUP are located behind NR_IPI,
so access to those counters were out of bounds.
Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
arch/arm64/kernel/smp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index e8cee27dc1132..716ba0b0c274b 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -1049,7 +1049,7 @@ static void __smp_cross_call(const struct cpumask *target, unsigned int ipinr)
static DEFINE_PER_CPU(unsigned long, ipi_messages);
-static DEFINE_PER_CPU(unsigned int [NR_IPI], ipi_counts);
+static DEFINE_PER_CPU(unsigned int [MAX_IPI], ipi_counts);
static irqreturn_t ipi_handler(int irq, void *data)
{
--
2.39.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH Dovetail 6.18 3/3] arm64: irq_pipeline: Fix IPI_KGDB_ROUNDUP and IPI_CPU_BACKTRACE IPIs
2026-02-02 7:55 [PATCH Dovetail 6.18 0/3] Fix IPI mapping for arm64 Florian Bezdeka
2026-02-02 7:55 ` [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs Florian Bezdeka
2026-02-02 7:55 ` [PATCH Dovetail 6.18 2/3] arm64: irq_pipeline: Fix size of IPI statistics array Florian Bezdeka
@ 2026-02-02 7:55 ` Florian Bezdeka
2026-02-03 11:59 ` Philippe Gerum
2 siblings, 1 reply; 15+ messages in thread
From: Florian Bezdeka @ 2026-02-02 7:55 UTC (permalink / raw)
To: xenomai; +Cc: Philippe Gerum, Jan Kiszka, Florian Bezdeka
Both IPIs (IPI_KGDB_ROUNDUP and IPI_CPU_BACKTRACE) are multiplexed in
case the IRQ pipelining is enabled, so we have to set an IPI reason
in both cases.
Both cases were directly calling into the IRQ chip implementation and
forgot to set the reason. IPIs were ignored on the receiving side at
the end.
As tracing should be bypassed for all IRQs behind NR_IPI we can not
call smp_cross_call() - where setting the reason / ipi message took
place.
Setting the reason has been factored out into set_ipi_message() which
can be called with and without IRQ pipelining.
Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
arch/arm64/kernel/smp.c | 29 +++++++++++++++++++++--------
1 file changed, 21 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 716ba0b0c274b..f85392de0e6a6 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -913,6 +913,24 @@ static void __noreturn ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs
#endif
}
+#ifdef CONFIG_IRQ_PIPELINE
+
+DEFINE_PER_CPU(unsigned long, ipi_messages);
+
+static inline void set_ipi_message(const cpumask_t *target, unsigned int ipi)
+{
+ int cpu;
+
+ for_each_cpu(cpu, target)
+ set_bit(ipi, &per_cpu(ipi_messages, cpu));
+
+ wmb();
+}
+#else
+static inline void set_ipi_message(const cpumask_t *target, unsigned int ipi)
+{ }
+#endif
+
static void arm64_send_ipi(const cpumask_t *mask, unsigned int nr)
{
unsigned int cpu;
@@ -926,6 +944,7 @@ static void arm64_send_ipi(const cpumask_t *mask, unsigned int nr)
static void arm64_backtrace_ipi(cpumask_t *mask)
{
+ set_ipi_message(mask, IPI_CPU_BACKTRACE);
arm64_send_ipi(mask, IPI_CPU_BACKTRACE);
}
@@ -951,6 +970,7 @@ void kgdb_roundup_cpus(void)
if (cpu == this_cpu)
continue;
+ set_ipi_message(cpumask_of(cpu), IPI_KGDB_ROUNDUP);
__ipi_send_single(get_ipi_desc(cpu, IPI_KGDB_ROUNDUP), cpu);
}
}
@@ -1047,8 +1067,6 @@ static void __smp_cross_call(const struct cpumask *target, unsigned int ipinr)
arm64_send_ipi(target, ipinr);
}
-static DEFINE_PER_CPU(unsigned long, ipi_messages);
-
static DEFINE_PER_CPU(unsigned int [MAX_IPI], ipi_counts);
static irqreturn_t ipi_handler(int irq, void *data)
@@ -1074,13 +1092,8 @@ static irqreturn_t ipi_handler(int irq, void *data)
static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
{
- unsigned int cpu;
-
/* regular in-band IPI (multiplexed over SGI0). */
- for_each_cpu(cpu, target)
- set_bit(ipinr, &per_cpu(ipi_messages, cpu));
-
- wmb();
+ set_ipi_message(target, ipinr);
__smp_cross_call(target, 0);
}
--
2.39.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH Dovetail 6.18 2/3] arm64: irq_pipeline: Fix size of IPI statistics array
2026-02-02 7:55 ` [PATCH Dovetail 6.18 2/3] arm64: irq_pipeline: Fix size of IPI statistics array Florian Bezdeka
@ 2026-02-03 11:59 ` Philippe Gerum
0 siblings, 0 replies; 15+ messages in thread
From: Philippe Gerum @ 2026-02-03 11:59 UTC (permalink / raw)
To: Florian Bezdeka; +Cc: xenomai, Jan Kiszka
Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> NR_IPI is not the last possible IPI, it's the last traceable IPI.
> IPI_CPU_BACKTRACE and IPI_KGDB_ROUNDUP are located behind NR_IPI,
> so access to those counters were out of bounds.
>
> Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> ---
> arch/arm64/kernel/smp.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> index e8cee27dc1132..716ba0b0c274b 100644
> --- a/arch/arm64/kernel/smp.c
> +++ b/arch/arm64/kernel/smp.c
> @@ -1049,7 +1049,7 @@ static void __smp_cross_call(const struct cpumask *target, unsigned int ipinr)
>
> static DEFINE_PER_CPU(unsigned long, ipi_messages);
>
> -static DEFINE_PER_CPU(unsigned int [NR_IPI], ipi_counts);
> +static DEFINE_PER_CPU(unsigned int [MAX_IPI], ipi_counts);
>
> static irqreturn_t ipi_handler(int irq, void *data)
> {
Good catch, ack.
--
Philippe.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH Dovetail 6.18 3/3] arm64: irq_pipeline: Fix IPI_KGDB_ROUNDUP and IPI_CPU_BACKTRACE IPIs
2026-02-02 7:55 ` [PATCH Dovetail 6.18 3/3] arm64: irq_pipeline: Fix IPI_KGDB_ROUNDUP and IPI_CPU_BACKTRACE IPIs Florian Bezdeka
@ 2026-02-03 11:59 ` Philippe Gerum
0 siblings, 0 replies; 15+ messages in thread
From: Philippe Gerum @ 2026-02-03 11:59 UTC (permalink / raw)
To: Florian Bezdeka; +Cc: xenomai, Jan Kiszka
Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> Both IPIs (IPI_KGDB_ROUNDUP and IPI_CPU_BACKTRACE) are multiplexed in
> case the IRQ pipelining is enabled, so we have to set an IPI reason
> in both cases.
>
> Both cases were directly calling into the IRQ chip implementation and
> forgot to set the reason. IPIs were ignored on the receiving side at
> the end.
>
> As tracing should be bypassed for all IRQs behind NR_IPI we can not
> call smp_cross_call() - where setting the reason / ipi message took
> place.
>
> Setting the reason has been factored out into set_ipi_message() which
> can be called with and without IRQ pipelining.
>
> Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> ---
> arch/arm64/kernel/smp.c | 29 +++++++++++++++++++++--------
> 1 file changed, 21 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> index 716ba0b0c274b..f85392de0e6a6 100644
> --- a/arch/arm64/kernel/smp.c
> +++ b/arch/arm64/kernel/smp.c
> @@ -913,6 +913,24 @@ static void __noreturn ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs
> #endif
> }
>
> +#ifdef CONFIG_IRQ_PIPELINE
> +
> +DEFINE_PER_CPU(unsigned long, ipi_messages);
> +
> +static inline void set_ipi_message(const cpumask_t *target, unsigned int ipi)
> +{
> + int cpu;
> +
> + for_each_cpu(cpu, target)
> + set_bit(ipi, &per_cpu(ipi_messages, cpu));
> +
> + wmb();
> +}
> +#else
> +static inline void set_ipi_message(const cpumask_t *target, unsigned int ipi)
> +{ }
> +#endif
> +
> static void arm64_send_ipi(const cpumask_t *mask, unsigned int nr)
> {
> unsigned int cpu;
> @@ -926,6 +944,7 @@ static void arm64_send_ipi(const cpumask_t *mask, unsigned int nr)
>
> static void arm64_backtrace_ipi(cpumask_t *mask)
> {
> + set_ipi_message(mask, IPI_CPU_BACKTRACE);
> arm64_send_ipi(mask, IPI_CPU_BACKTRACE);
> }
>
> @@ -951,6 +970,7 @@ void kgdb_roundup_cpus(void)
> if (cpu == this_cpu)
> continue;
>
> + set_ipi_message(cpumask_of(cpu), IPI_KGDB_ROUNDUP);
> __ipi_send_single(get_ipi_desc(cpu, IPI_KGDB_ROUNDUP), cpu);
> }
> }
> @@ -1047,8 +1067,6 @@ static void __smp_cross_call(const struct cpumask *target, unsigned int ipinr)
> arm64_send_ipi(target, ipinr);
> }
>
> -static DEFINE_PER_CPU(unsigned long, ipi_messages);
> -
> static DEFINE_PER_CPU(unsigned int [MAX_IPI], ipi_counts);
>
> static irqreturn_t ipi_handler(int irq, void *data)
> @@ -1074,13 +1092,8 @@ static irqreturn_t ipi_handler(int irq, void *data)
>
> static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
> {
> - unsigned int cpu;
> -
> /* regular in-band IPI (multiplexed over SGI0). */
> - for_each_cpu(cpu, target)
> - set_bit(ipinr, &per_cpu(ipi_messages, cpu));
> -
> - wmb();
> + set_ipi_message(target, ipinr);
> __smp_cross_call(target, 0);
> }
Ouch, yes. Ack.
--
Philippe.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs
2026-02-02 7:55 ` [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs Florian Bezdeka
@ 2026-02-03 13:08 ` Philippe Gerum
2026-02-03 15:25 ` Florian Bezdeka
0 siblings, 1 reply; 15+ messages in thread
From: Philippe Gerum @ 2026-02-03 13:08 UTC (permalink / raw)
To: Florian Bezdeka; +Cc: xenomai, Jan Kiszka
Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> There were two problems with the mapping:
> - We stopped mapping after OOB_NR_IPI (3) IPIs.
> There are more IPIs after the last IPI reserved for OOB
Yes, but we don't need to care those, since the code should never refer
to IPIs past OOB_NR_IPI when pipelining is enabled. The last issue
regarding this would be the out-of-bound access to ipi_count[], which
your other fix addresses.
As I understand this, e.g. on a two-way system, depending on SGI/LPI
modes, we need to hook:
in SGI mode, e.g. with IRQ0-3 globally available for mapping the IPIs on
all CPUs:
CPU0: SGI0 -> IRQ0 (in-band), SGI1 -> IRQ1, SGI2 -> IRQ2, SGI3 -> IRQ3 (oob)
CPU1: SGI0 -> IRQ0 (in-band), SGI1 -> IRQ1, SGI2 -> IRQ2, SGI3 -> IRQ3 (oob)
in LPI mode, e.g. with IRQ0-3 and IRQ4-7 available from CPU0 and CPU1
resp. for mapping the IPIs:
CPU0: SGI0 -> IRQ0 (in-band), SGI1 -> IRQ1, SGI2 -> IRQ2, SGI3 -> IRQ3 (oob)
CPU1: SGI0 -> IRQ4 (in-band), SGI1 -> IRQ5, SGI2 -> IRQ6, SGI3 -> IRQ7 (oob)
The root of the issue is the backtrace code bypassing the logical IPI ->
SGI0 mapping in smp_cross_call(). In this case, requesting
BACKTRACE=IPI7 without remapping to SGI0 would break in LPI mode,
because get_ipi_desc() returns NULL for that one. So my understanding is
that we must ensure that arm64_send_ipi() for in-band IPIs never escapes
the IPI->SGI0 mapping, instead of installing IPI descriptors on the
whole range of IPIs. We must also fix the IRQ mapping in the LPI case,
which wrongly maps everything to the IRQ range used by CPU0, which makes
no sense, as you pointed out.
>
> - In the LPI case everything was mapped to the IRQ desc of CPU 0,
> which seems odd. Each CPU has its own LPI used for multiplexing
> inband IPIs.
>
> The following splat was observed whent trying to handle a backtrace
> IPI. This is one of the IPIs located after the OOB IPIs.
>
> [ 115.357495] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000048
> [ 115.358088] Mem abort info:
A simpler fix for the mapping issue: we only need to factor in the base
offset for IPIs in LPI mode:
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -1020,12 +1020,12 @@ static void do_handle_IPI(int ipinr)
#ifdef CONFIG_IRQ_PIPELINE
-static inline void map_oob_ipis(int cpu)
+static inline void map_oob_ipis(int cpu, int offset)
{
int ipi;
for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
- get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
+ get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + cpu * offset + ipi);
}
static void ipi_setup_oob_sgi(void)
@@ -1033,7 +1033,7 @@ static void ipi_setup_oob_sgi(void)
int cpu;
for_each_possible_cpu(cpu)
- map_oob_ipis(cpu);
+ map_oob_ipis(cpu, 0);
}
static void ipi_setup_oob_lpi(int ncpus)
@@ -1041,7 +1041,7 @@ static void ipi_setup_oob_lpi(int ncpus)
int cpu;
for (cpu = 0; cpu < ncpus; cpu++)
- map_oob_ipis(cpu);
+ map_oob_ipis(cpu, nr_ipi);
}
static void __smp_cross_call(const struct cpumask *target, unsigned int ipinr)
--
Philippe.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs
2026-02-03 13:08 ` Philippe Gerum
@ 2026-02-03 15:25 ` Florian Bezdeka
2026-02-03 17:22 ` Philippe Gerum
0 siblings, 1 reply; 15+ messages in thread
From: Florian Bezdeka @ 2026-02-03 15:25 UTC (permalink / raw)
To: Philippe Gerum; +Cc: xenomai, Jan Kiszka
On Tue, 2026-02-03 at 14:08 +0100, Philippe Gerum wrote:
> -static inline void map_oob_ipis(int cpu)
> +static inline void map_oob_ipis(int cpu, int offset)
> {
> int ipi;
>
> for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
> - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
> + get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + cpu * offset + ipi);
> }
I'm still quite sure that the loop is wrong and should be
+static inline void map_oob_ipis(int cpu, int offset)
{
int ipi;
- for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
- get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
+ offset = ipi_irq_base + (cpu * offset);
+
+ for (ipi = OOB_IPI_OFFSET; ipi < nr_ipi; ipi++)
+ get_ipi_desc(cpu, ipi) = irq_to_desc(offset + ipi);
}
instead. (Note OOB_NR_IPI + OOB_IPI_OFFSET vs. nr_ipi)
Example:
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);
How should that work for IPI_IRQ_WORK? IPI_IRQ_WORK is located behind
the IPIs used for OOB and get_ipi_desc(0, IPI_IRQ_WORK) would return
NULL as we skipped the mapping in map_oob_ipis().
enum ipi_msg_type {
IPI_RESCHEDULE, // INBAND
IPI_CALL_FUNC, // OOB
IPI_CPU_STOP, // OOB
IPI_CPU_STOP_NMI, // OOB
IPI_TIMER, // Unmapped
IPI_IRQ_WORK, // Unmapped
NR_IPI,
/*
* Any enum >= NR_IPI and < MAX_IPI is special and not tracable
* with trace_ipi_*
*/
IPI_CPU_BACKTRACE = NR_IPI,
IPI_KGDB_ROUNDUP,
MAX_IPI
};
I agree that we can simplify the code a bit more, like you suggested.
Florian
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs
2026-02-03 15:25 ` Florian Bezdeka
@ 2026-02-03 17:22 ` Philippe Gerum
2026-02-03 17:44 ` Philippe Gerum
2026-02-03 21:48 ` Florian Bezdeka
0 siblings, 2 replies; 15+ messages in thread
From: Philippe Gerum @ 2026-02-03 17:22 UTC (permalink / raw)
To: Florian Bezdeka; +Cc: xenomai, Jan Kiszka
Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> On Tue, 2026-02-03 at 14:08 +0100, Philippe Gerum wrote:
>> -static inline void map_oob_ipis(int cpu)
>> +static inline void map_oob_ipis(int cpu, int offset)
>> {
>> int ipi;
>>
>> for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
>> - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
>> + get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + cpu * offset + ipi);
>> }
>
> I'm still quite sure that the loop is wrong and should be
>
> +static inline void map_oob_ipis(int cpu, int offset)
> {
> int ipi;
>
> - for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
> - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
> + offset = ipi_irq_base + (cpu * offset);
> +
> + for (ipi = OOB_IPI_OFFSET; ipi < nr_ipi; ipi++)
> + get_ipi_desc(cpu, ipi) = irq_to_desc(offset + ipi);
> }
>
For ipi=SGI-0-7, the upstream implementation of ipi_setup_lpi() does:
irq = ipi_irq_base + (cpu * nr_ipi) + ipi;
get_ipi_desc(cpu, ipi) = irq_to_desc(irq);
In pipelined mode, we need to do that for ipi=SGI0 for in-band IPIs,
then for ipi=SGI1-3 for oob ones (see below). All members of
ipi_msg_type become _logical_ IPIs multiplexed over SGI0. That is the
whole point of your fix regarding CPU_BACKTRACE and KGDB_ROUNDUP.
> instead. (Note OOB_NR_IPI + OOB_IPI_OFFSET vs. nr_ipi)
The code above would map the original IPI range from SGI0-7, which we
don't have to in pipelined mode, we only use SGI0-3 here.
>
> Example:
>
> 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);
>
> How should that work for IPI_IRQ_WORK? IPI_IRQ_WORK is located behind
> the IPIs used for OOB and get_ipi_desc(0, IPI_IRQ_WORK) would return
> NULL as we skipped the mapping in map_oob_ipis().
>
Any IPI from IPI_RESCHEDULE to IPI_IRQ_WORK are multiplexed over SGI0 by
smp_cross_call(). IPI_CPU_BACKTRACE and IPI_KGDB_ROUNDUP should be as
well, but unfortunately bypassed that routine to call into
arm64_send_ipi() directly, which is invalid. So, if all call sites which
want to send an in-band IPI do this remapping so that arm64_send_ipi()
is always called with ipi=SGI0 for them, we are ok.
IOW, arm64_send_ipi() can only be called for SGI0-3, i.e. one in-band
channel over which all upstream IPIs are multiplexed, three oob IPIs the
real-time core may use as it sees fit.
I should have an Hikey Lemaker somewhere in my drawers to be excavated
that I can reconnect to my lab. Is it the hardware which shows the issue
in lpi mode, or is it a 960?
--
Philippe.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs
2026-02-03 17:22 ` Philippe Gerum
@ 2026-02-03 17:44 ` Philippe Gerum
2026-02-03 21:48 ` Florian Bezdeka
1 sibling, 0 replies; 15+ messages in thread
From: Philippe Gerum @ 2026-02-03 17:44 UTC (permalink / raw)
To: Florian Bezdeka; +Cc: xenomai, Jan Kiszka
Philippe Gerum <rpm@xenomai.org> writes:
> Florian Bezdeka <florian.bezdeka@siemens.com> writes:
>
>> On Tue, 2026-02-03 at 14:08 +0100, Philippe Gerum wrote:
>>> -static inline void map_oob_ipis(int cpu)
>>> +static inline void map_oob_ipis(int cpu, int offset)
>>> {
>>> int ipi;
>>>
>>> for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
>>> - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
>>> + get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + cpu * offset + ipi);
>>> }
>>
>> I'm still quite sure that the loop is wrong and should be
>>
>> +static inline void map_oob_ipis(int cpu, int offset)
>> {
>> int ipi;
>>
>> - for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
>> - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
>> + offset = ipi_irq_base + (cpu * offset);
>> +
>> + for (ipi = OOB_IPI_OFFSET; ipi < nr_ipi; ipi++)
>> + get_ipi_desc(cpu, ipi) = irq_to_desc(offset + ipi);
>> }
>>
>
> For ipi=SGI-0-7, the upstream implementation of ipi_setup_lpi() does:
>
> irq = ipi_irq_base + (cpu * nr_ipi) + ipi;
> get_ipi_desc(cpu, ipi) = irq_to_desc(irq);
>
> In pipelined mode, we need to do that for ipi=SGI0 for in-band IPIs,
> then for ipi=SGI1-3 for oob ones (see below). All members of
> ipi_msg_type become _logical_ IPIs multiplexed over SGI0. That is the
> whole point of your fix regarding CPU_BACKTRACE and KGDB_ROUNDUP.
>
>
>> instead. (Note OOB_NR_IPI + OOB_IPI_OFFSET vs. nr_ipi)
>
> The code above would map the original IPI range from SGI0-7, which we
> don't have to in pipelined mode, we only use SGI0-3 here.
>
>>
>> Example:
>>
>> 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);
>>
>> How should that work for IPI_IRQ_WORK? IPI_IRQ_WORK is located behind
>> the IPIs used for OOB and get_ipi_desc(0, IPI_IRQ_WORK) would return
>> NULL as we skipped the mapping in map_oob_ipis().
>>
>
> Any IPI from IPI_RESCHEDULE to IPI_IRQ_WORK are multiplexed over SGI0 by
> smp_cross_call(). IPI_CPU_BACKTRACE and IPI_KGDB_ROUNDUP should be as
> well, but unfortunately bypassed that routine to call into
> arm64_send_ipi() directly, which is invalid. So, if all call sites which
> want to send an in-band IPI do this remapping so that arm64_send_ipi()
> is always called with ipi=SGI0 for them, we are ok.
>
> IOW, arm64_send_ipi() can only be called for SGI0-3, i.e. one in-band
> channel over which all upstream IPIs are multiplexed, three oob IPIs the
> real-time core may use as it sees fit.
>
> I should have an Hikey Lemaker somewhere in my drawers to be excavated
> that I can reconnect to my lab. Is it the hardware which shows the issue
> in lpi mode, or is it a 960?
s/960/970/
--
Philippe.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs
2026-02-03 17:22 ` Philippe Gerum
2026-02-03 17:44 ` Philippe Gerum
@ 2026-02-03 21:48 ` Florian Bezdeka
2026-02-03 22:00 ` Bezdeka, Florian
1 sibling, 1 reply; 15+ messages in thread
From: Florian Bezdeka @ 2026-02-03 21:48 UTC (permalink / raw)
To: Philippe Gerum; +Cc: xenomai, Jan Kiszka
On Tue, 2026-02-03 at 18:22 +0100, Philippe Gerum wrote:
> Florian Bezdeka <florian.bezdeka@siemens.com> writes:
>
> > On Tue, 2026-02-03 at 14:08 +0100, Philippe Gerum wrote:
> > > -static inline void map_oob_ipis(int cpu)
> > > +static inline void map_oob_ipis(int cpu, int offset)
> > > {
> > > int ipi;
> > >
> > > for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
> > > - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
> > > + get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + cpu * offset + ipi);
> > > }
> >
> > I'm still quite sure that the loop is wrong and should be
> >
> > +static inline void map_oob_ipis(int cpu, int offset)
> > {
> > int ipi;
> >
> > - for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
> > - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
> > + offset = ipi_irq_base + (cpu * offset);
> > +
> > + for (ipi = OOB_IPI_OFFSET; ipi < nr_ipi; ipi++)
> > + get_ipi_desc(cpu, ipi) = irq_to_desc(offset + ipi);
> > }
> >
>
> For ipi=SGI-0-7, the upstream implementation of ipi_setup_lpi() does:
>
> irq = ipi_irq_base + (cpu * nr_ipi) + ipi;
> get_ipi_desc(cpu, ipi) = irq_to_desc(irq);
>
> In pipelined mode, we need to do that for ipi=SGI0 for in-band IPIs,
> then for ipi=SGI1-3 for oob ones (see below). All members of
> ipi_msg_type become _logical_ IPIs multiplexed over SGI0. That is the
> whole point of your fix regarding CPU_BACKTRACE and KGDB_ROUNDUP.
>
>
> > instead. (Note OOB_NR_IPI + OOB_IPI_OFFSET vs. nr_ipi)
>
> The code above would map the original IPI range from SGI0-7, which we
> don't have to in pipelined mode, we only use SGI0-3 here.
>
> >
> > Example:
> >
> > 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);
> >
> > How should that work for IPI_IRQ_WORK? IPI_IRQ_WORK is located behind
> > the IPIs used for OOB and get_ipi_desc(0, IPI_IRQ_WORK) would return
> > NULL as we skipped the mapping in map_oob_ipis().
> >
>
> Any IPI from IPI_RESCHEDULE to IPI_IRQ_WORK are multiplexed over SGI0 by
> smp_cross_call().
>
Here we go. I missed that smp_cross_call() calls __smp_cross_call() with
ipinr set to 0, unconditionally, not forwarding ipinr. I simply
overlooked that. That allows us to only map the oob IPIs as the "wrong"
mapping in arm64_send_ipi() can not happen anymore. Sorry for the
confusion.
I will send out v2 tomorrow after some more testing.
> IPI_CPU_BACKTRACE and IPI_KGDB_ROUNDUP should be as
> well, but unfortunately bypassed that routine to call into
> arm64_send_ipi() directly, which is invalid. So, if all call sites which
> want to send an in-band IPI do this remapping so that arm64_send_ipi()
> is always called with ipi=SGI0 for them, we are ok.
>
> IOW, arm64_send_ipi() can only be called for SGI0-3, i.e. one in-band
> channel over which all upstream IPIs are multiplexed, three oob IPIs the
> real-time core may use as it sees fit.
>
> I should have an Hikey Lemaker somewhere in my drawers to be excavated
> that I can reconnect to my lab. Is it the hardware which shows the issue
> in lpi mode, or is it a 960?
I can only test the SGI mode here. Everything else came up while
inspecting the code.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs
2026-02-03 21:48 ` Florian Bezdeka
@ 2026-02-03 22:00 ` Bezdeka, Florian
2026-02-04 11:44 ` Philippe Gerum
0 siblings, 1 reply; 15+ messages in thread
From: Bezdeka, Florian @ 2026-02-03 22:00 UTC (permalink / raw)
To: rpm@xenomai.org; +Cc: Kiszka, Jan, xenomai@lists.linux.dev
On Tue, 2026-02-03 at 22:48 +0100, Florian Bezdeka wrote:
> On Tue, 2026-02-03 at 18:22 +0100, Philippe Gerum wrote:
> > Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> >
> > > On Tue, 2026-02-03 at 14:08 +0100, Philippe Gerum wrote:
> > > > -static inline void map_oob_ipis(int cpu)
> > > > +static inline void map_oob_ipis(int cpu, int offset)
> > > > {
> > > > int ipi;
> > > >
> > > > for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
> > > > - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
> > > > + get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + cpu * offset + ipi);
> > > > }
> > >
> > > I'm still quite sure that the loop is wrong and should be
> > >
> > > +static inline void map_oob_ipis(int cpu, int offset)
> > > {
> > > int ipi;
> > >
> > > - for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
> > > - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
> > > + offset = ipi_irq_base + (cpu * offset);
> > > +
> > > + for (ipi = OOB_IPI_OFFSET; ipi < nr_ipi; ipi++)
> > > + get_ipi_desc(cpu, ipi) = irq_to_desc(offset + ipi);
> > > }
> > >
> >
> > For ipi=SGI-0-7, the upstream implementation of ipi_setup_lpi() does:
> >
> > irq = ipi_irq_base + (cpu * nr_ipi) + ipi;
> > get_ipi_desc(cpu, ipi) = irq_to_desc(irq);
> >
> > In pipelined mode, we need to do that for ipi=SGI0 for in-band IPIs,
> > then for ipi=SGI1-3 for oob ones (see below). All members of
> > ipi_msg_type become _logical_ IPIs multiplexed over SGI0. That is the
> > whole point of your fix regarding CPU_BACKTRACE and KGDB_ROUNDUP.
> >
> >
> > > instead. (Note OOB_NR_IPI + OOB_IPI_OFFSET vs. nr_ipi)
> >
> > The code above would map the original IPI range from SGI0-7, which we
> > don't have to in pipelined mode, we only use SGI0-3 here.
> >
> > >
> > > Example:
> > >
> > > 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);
> > >
> > > How should that work for IPI_IRQ_WORK? IPI_IRQ_WORK is located behind
> > > the IPIs used for OOB and get_ipi_desc(0, IPI_IRQ_WORK) would return
> > > NULL as we skipped the mapping in map_oob_ipis().
> > >
> >
> > Any IPI from IPI_RESCHEDULE to IPI_IRQ_WORK are multiplexed over SGI0 by
> > smp_cross_call().
> >
>
> Here we go. I missed that smp_cross_call() calls __smp_cross_call() with
> ipinr set to 0, unconditionally, not forwarding ipinr. I simply
> overlooked that. That allows us to only map the oob IPIs as the "wrong"
> mapping in arm64_send_ipi() can not happen anymore. Sorry for the
> confusion.
That didn't last long. Two ways to fix the problem at the end:
- Only map OOB IPIs as suggested by Philippe.
Means we have to modify arm64_backtrace_ipi() and
kgdb_roundup_cpus() for the dovetailing case.
Calling arm64_send_ipi() with an ipi-nr != 0 is not allowed in the
dovetailing case for inband IPIs.
- Map all IRQs as suggested by me.
Hopefully correct now...
Which way is the preferred one?
>
> I will send out v2 tomorrow after some more testing.
>
> > IPI_CPU_BACKTRACE and IPI_KGDB_ROUNDUP should be as
> > well, but unfortunately bypassed that routine to call into
> > arm64_send_ipi() directly, which is invalid. So, if all call sites which
> > want to send an in-band IPI do this remapping so that arm64_send_ipi()
> > is always called with ipi=SGI0 for them, we are ok.
> >
> > IOW, arm64_send_ipi() can only be called for SGI0-3, i.e. one in-band
> > channel over which all upstream IPIs are multiplexed, three oob IPIs the
> > real-time core may use as it sees fit.
> >
> > I should have an Hikey Lemaker somewhere in my drawers to be excavated
> > that I can reconnect to my lab. Is it the hardware which shows the issue
> > in lpi mode, or is it a 960?
>
> I can only test the SGI mode here. Everything else came up while
> inspecting the code.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs
2026-02-03 22:00 ` Bezdeka, Florian
@ 2026-02-04 11:44 ` Philippe Gerum
2026-02-04 16:46 ` Florian Bezdeka
0 siblings, 1 reply; 15+ messages in thread
From: Philippe Gerum @ 2026-02-04 11:44 UTC (permalink / raw)
To: Bezdeka, Florian; +Cc: Kiszka, Jan, xenomai@lists.linux.dev
"Bezdeka, Florian" <florian.bezdeka@siemens.com> writes:
> On Tue, 2026-02-03 at 22:48 +0100, Florian Bezdeka wrote:
>> On Tue, 2026-02-03 at 18:22 +0100, Philippe Gerum wrote:
>> > Florian Bezdeka <florian.bezdeka@siemens.com> writes:
>> >
>> > > On Tue, 2026-02-03 at 14:08 +0100, Philippe Gerum wrote:
>> > > > -static inline void map_oob_ipis(int cpu)
>> > > > +static inline void map_oob_ipis(int cpu, int offset)
>> > > > {
>> > > > int ipi;
>> > > >
>> > > > for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
>> > > > - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
>> > > > + get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + cpu * offset + ipi);
>> > > > }
>> > >
>> > > I'm still quite sure that the loop is wrong and should be
>> > >
>> > > +static inline void map_oob_ipis(int cpu, int offset)
>> > > {
>> > > int ipi;
>> > >
>> > > - for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
>> > > - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
>> > > + offset = ipi_irq_base + (cpu * offset);
>> > > +
>> > > + for (ipi = OOB_IPI_OFFSET; ipi < nr_ipi; ipi++)
>> > > + get_ipi_desc(cpu, ipi) = irq_to_desc(offset + ipi);
>> > > }
>> > >
>> >
>> > For ipi=SGI-0-7, the upstream implementation of ipi_setup_lpi() does:
>> >
>> > irq = ipi_irq_base + (cpu * nr_ipi) + ipi;
>> > get_ipi_desc(cpu, ipi) = irq_to_desc(irq);
>> >
>> > In pipelined mode, we need to do that for ipi=SGI0 for in-band IPIs,
>> > then for ipi=SGI1-3 for oob ones (see below). All members of
>> > ipi_msg_type become _logical_ IPIs multiplexed over SGI0. That is the
>> > whole point of your fix regarding CPU_BACKTRACE and KGDB_ROUNDUP.
>> >
>> >
>> > > instead. (Note OOB_NR_IPI + OOB_IPI_OFFSET vs. nr_ipi)
>> >
>> > The code above would map the original IPI range from SGI0-7, which we
>> > don't have to in pipelined mode, we only use SGI0-3 here.
>> >
>> > >
>> > > Example:
>> > >
>> > > 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);
>> > >
>> > > How should that work for IPI_IRQ_WORK? IPI_IRQ_WORK is located behind
>> > > the IPIs used for OOB and get_ipi_desc(0, IPI_IRQ_WORK) would return
>> > > NULL as we skipped the mapping in map_oob_ipis().
>> > >
>> >
>> > Any IPI from IPI_RESCHEDULE to IPI_IRQ_WORK are multiplexed over SGI0 by
>> > smp_cross_call().
>> >
>>
>> Here we go. I missed that smp_cross_call() calls __smp_cross_call() with
>> ipinr set to 0, unconditionally, not forwarding ipinr. I simply
>> overlooked that. That allows us to only map the oob IPIs as the "wrong"
>> mapping in arm64_send_ipi() can not happen anymore. Sorry for the
>> confusion.
>
> That didn't last long. Two ways to fix the problem at the end:
>
> - Only map OOB IPIs as suggested by Philippe.
> Means we have to modify arm64_backtrace_ipi() and
> kgdb_roundup_cpus() for the dovetailing case.
> Calling arm64_send_ipi() with an ipi-nr != 0 is not allowed in the
> dovetailing case for inband IPIs.
>
> - Map all IRQs as suggested by me.
>
> Hopefully correct now...
>
> Which way is the preferred one?
>
>>
Excerpt from arch/arm/kernel/smp.c:
enum ipi_msg_type {
...
/*
* SGI8-15 can be reserved by secure firmware, and thus may
* not be usable by the kernel. Please keep the above limited
* to at most 8 entries.
*/
MAX_IPI
};
This still holds true for ATF [1], so we only have 8 available SGIs
although GICv3+ do provide 16. Since we have 8 in-band IPI message types
defined by the arm64 port and we need 3 oob vectors more, we can't have
a 1:1 mapping between IPIs and SGIs.
So far we are using 4 SGIs as explained above (1 in-band + 3 oob), so we
have 4 spares ATM. The reason for moving an in-band IPI to its own SGI
using one of those spares would be to prioritize it over the bulk of
in-band messages. Therefore, the question would be: do we need such
prioritization?
[1] https://trustedfirmware-a.readthedocs.io/en/latest/porting-guide.html#function-bl31-platform-setup-mandatory
--
Philippe.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs
2026-02-04 11:44 ` Philippe Gerum
@ 2026-02-04 16:46 ` Florian Bezdeka
2026-02-04 18:04 ` Philippe Gerum
0 siblings, 1 reply; 15+ messages in thread
From: Florian Bezdeka @ 2026-02-04 16:46 UTC (permalink / raw)
To: Philippe Gerum; +Cc: Kiszka, Jan, xenomai@lists.linux.dev
On Wed, 2026-02-04 at 12:44 +0100, Philippe Gerum wrote:
> "Bezdeka, Florian" <florian.bezdeka@siemens.com> writes:
>
> > On Tue, 2026-02-03 at 22:48 +0100, Florian Bezdeka wrote:
> > > On Tue, 2026-02-03 at 18:22 +0100, Philippe Gerum wrote:
> > > > Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> > > >
> > > > > On Tue, 2026-02-03 at 14:08 +0100, Philippe Gerum wrote:
> > > > > > -static inline void map_oob_ipis(int cpu)
> > > > > > +static inline void map_oob_ipis(int cpu, int offset)
> > > > > > {
> > > > > > int ipi;
> > > > > >
> > > > > > for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
> > > > > > - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
> > > > > > + get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + cpu * offset + ipi);
> > > > > > }
> > > > >
> > > > > I'm still quite sure that the loop is wrong and should be
> > > > >
> > > > > +static inline void map_oob_ipis(int cpu, int offset)
> > > > > {
> > > > > int ipi;
> > > > >
> > > > > - for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
> > > > > - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
> > > > > + offset = ipi_irq_base + (cpu * offset);
> > > > > +
> > > > > + for (ipi = OOB_IPI_OFFSET; ipi < nr_ipi; ipi++)
> > > > > + get_ipi_desc(cpu, ipi) = irq_to_desc(offset + ipi);
> > > > > }
> > > > >
> > > >
> > > > For ipi=SGI-0-7, the upstream implementation of ipi_setup_lpi() does:
> > > >
> > > > irq = ipi_irq_base + (cpu * nr_ipi) + ipi;
> > > > get_ipi_desc(cpu, ipi) = irq_to_desc(irq);
> > > >
> > > > In pipelined mode, we need to do that for ipi=SGI0 for in-band IPIs,
> > > > then for ipi=SGI1-3 for oob ones (see below). All members of
> > > > ipi_msg_type become _logical_ IPIs multiplexed over SGI0. That is the
> > > > whole point of your fix regarding CPU_BACKTRACE and KGDB_ROUNDUP.
> > > >
> > > >
> > > > > instead. (Note OOB_NR_IPI + OOB_IPI_OFFSET vs. nr_ipi)
> > > >
> > > > The code above would map the original IPI range from SGI0-7, which we
> > > > don't have to in pipelined mode, we only use SGI0-3 here.
> > > >
> > > > >
> > > > > Example:
> > > > >
> > > > > 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);
> > > > >
> > > > > How should that work for IPI_IRQ_WORK? IPI_IRQ_WORK is located behind
> > > > > the IPIs used for OOB and get_ipi_desc(0, IPI_IRQ_WORK) would return
> > > > > NULL as we skipped the mapping in map_oob_ipis().
> > > > >
> > > >
> > > > Any IPI from IPI_RESCHEDULE to IPI_IRQ_WORK are multiplexed over SGI0 by
> > > > smp_cross_call().
> > > >
> > >
> > > Here we go. I missed that smp_cross_call() calls __smp_cross_call() with
> > > ipinr set to 0, unconditionally, not forwarding ipinr. I simply
> > > overlooked that. That allows us to only map the oob IPIs as the "wrong"
> > > mapping in arm64_send_ipi() can not happen anymore. Sorry for the
> > > confusion.
> >
> > That didn't last long. Two ways to fix the problem at the end:
> >
> > - Only map OOB IPIs as suggested by Philippe.
> > Means we have to modify arm64_backtrace_ipi() and
> > kgdb_roundup_cpus() for the dovetailing case.
> > Calling arm64_send_ipi() with an ipi-nr != 0 is not allowed in the
> > dovetailing case for inband IPIs.
> >
> > - Map all IRQs as suggested by me.
> >
> > Hopefully correct now...
> >
> > Which way is the preferred one?
> >
> > >
>
> Excerpt from arch/arm/kernel/smp.c:
>
> enum ipi_msg_type {
> ...
> /*
> * SGI8-15 can be reserved by secure firmware, and thus may
> * not be usable by the kernel. Please keep the above limited
> * to at most 8 entries.
> */
> MAX_IPI
> };
That is now taken from arch/arm instead of arch/arm64. Is that also the
case for arm64?
>
> This still holds true for ATF [1], so we only have 8 available SGIs
> although GICv3+ do provide 16. Since we have 8 in-band IPI message types
> defined by the arm64 port and we need 3 oob vectors more, we can't have
> a 1:1 mapping between IPIs and SGIs.
>
> So far we are using 4 SGIs as explained above (1 in-band + 3 oob), so we
> have 4 spares ATM. The reason for moving an in-band IPI to its own SGI
> using one of those spares would be to prioritize it over the bulk of
> in-band messages. Therefore, the question would be: do we need such
> prioritization?
I have no strong opinion on that and tried to restore what we had in the
past. Looking at 6.12 at [2] now I had to realize that this was way more
broken regarding IPI_BACKTRACE and IPI_KGDB_ROUNDUP than I had realized
up to now.
>
> [1] https://trustedfirmware-a.readthedocs.io/en/latest/porting-guide.html#function-bl31-platform-setup-mandatory
[2] https://gitlab.com/Xenomai/linux-dovetail/-/blob/v6.12.y-dovetail/arch/arm64/kernel/smp.c?ref_type=heads#L1190
What about the following end-result:
enum ipi_msg_type {
IPI_RESCHEDULE, // SGI0, used for inband multiplexing
// RESCHDULE set as reason
IPI_CALL_FUNC, // SGI1 reserved for OOB
// CALL_FUNC via SGI0 with reason set
IPI_CPU_STOP, // SGI2 reserved for OOB
// CPU_STOP via SGI0 with reason set
IPI_CPU_STOP_NMI, // SGI3 reserved for OOB
// STOP_NMI via SGI0 with reason set
// SGI4-7 unused
IPI_TIMER, // via SGI0 with reason set
IPI_IRQ_WORK, // via SGI0 with reason set
NR_IPI,
/*
* Any enum >= NR_IPI and < MAX_IPI is special and not tracable
* with trace_ipi_*
*/
IPI_CPU_BACKTRACE = NR_IPI, // via SGI0 with reason set
IPI_KGDB_ROUNDUP, // via SGI0 with reason set
MAX_IPI
};
Final questions:
Assuming SGI mode: Where are the request_percpu_irq() calls for all the
OOB SGIs? Or: How is something like irq_send_oob_ipi(2, mask) expected
to get the right IRQ descriptor in arm64_send_ipi()? Currently the
descriptor for SGI0 is returned.
Is that all just broken for a long time?
In addition I think that the trace_ipi_raise() in __smp_cross_call() is
incorrect for OOB SGIs...
Florian
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs
2026-02-04 16:46 ` Florian Bezdeka
@ 2026-02-04 18:04 ` Philippe Gerum
0 siblings, 0 replies; 15+ messages in thread
From: Philippe Gerum @ 2026-02-04 18:04 UTC (permalink / raw)
To: Florian Bezdeka; +Cc: Kiszka, Jan, xenomai@lists.linux.dev
Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> On Wed, 2026-02-04 at 12:44 +0100, Philippe Gerum wrote:
>> "Bezdeka, Florian" <florian.bezdeka@siemens.com> writes:
>>
>> > On Tue, 2026-02-03 at 22:48 +0100, Florian Bezdeka wrote:
>> > > On Tue, 2026-02-03 at 18:22 +0100, Philippe Gerum wrote:
>> > > > Florian Bezdeka <florian.bezdeka@siemens.com> writes:
>> > > >
>> > > > > On Tue, 2026-02-03 at 14:08 +0100, Philippe Gerum wrote:
>> > > > > > -static inline void map_oob_ipis(int cpu)
>> > > > > > +static inline void map_oob_ipis(int cpu, int offset)
>> > > > > > {
>> > > > > > int ipi;
>> > > > > >
>> > > > > > for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
>> > > > > > - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
>> > > > > > + get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + cpu * offset + ipi);
>> > > > > > }
>> > > > >
>> > > > > I'm still quite sure that the loop is wrong and should be
>> > > > >
>> > > > > +static inline void map_oob_ipis(int cpu, int offset)
>> > > > > {
>> > > > > int ipi;
>> > > > >
>> > > > > - for (ipi = OOB_IPI_OFFSET; ipi < OOB_NR_IPI + OOB_IPI_OFFSET; ipi++)
>> > > > > - get_ipi_desc(cpu, ipi) = irq_to_desc(ipi_irq_base + ipi);
>> > > > > + offset = ipi_irq_base + (cpu * offset);
>> > > > > +
>> > > > > + for (ipi = OOB_IPI_OFFSET; ipi < nr_ipi; ipi++)
>> > > > > + get_ipi_desc(cpu, ipi) = irq_to_desc(offset + ipi);
>> > > > > }
>> > > > >
>> > > >
>> > > > For ipi=SGI-0-7, the upstream implementation of ipi_setup_lpi() does:
>> > > >
>> > > > irq = ipi_irq_base + (cpu * nr_ipi) + ipi;
>> > > > get_ipi_desc(cpu, ipi) = irq_to_desc(irq);
>> > > >
>> > > > In pipelined mode, we need to do that for ipi=SGI0 for in-band IPIs,
>> > > > then for ipi=SGI1-3 for oob ones (see below). All members of
>> > > > ipi_msg_type become _logical_ IPIs multiplexed over SGI0. That is the
>> > > > whole point of your fix regarding CPU_BACKTRACE and KGDB_ROUNDUP.
>> > > >
>> > > >
>> > > > > instead. (Note OOB_NR_IPI + OOB_IPI_OFFSET vs. nr_ipi)
>> > > >
>> > > > The code above would map the original IPI range from SGI0-7, which we
>> > > > don't have to in pipelined mode, we only use SGI0-3 here.
>> > > >
>> > > > >
>> > > > > Example:
>> > > > >
>> > > > > 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);
>> > > > >
>> > > > > How should that work for IPI_IRQ_WORK? IPI_IRQ_WORK is located behind
>> > > > > the IPIs used for OOB and get_ipi_desc(0, IPI_IRQ_WORK) would return
>> > > > > NULL as we skipped the mapping in map_oob_ipis().
>> > > > >
>> > > >
>> > > > Any IPI from IPI_RESCHEDULE to IPI_IRQ_WORK are multiplexed over SGI0 by
>> > > > smp_cross_call().
>> > > >
>> > >
>> > > Here we go. I missed that smp_cross_call() calls __smp_cross_call() with
>> > > ipinr set to 0, unconditionally, not forwarding ipinr. I simply
>> > > overlooked that. That allows us to only map the oob IPIs as the "wrong"
>> > > mapping in arm64_send_ipi() can not happen anymore. Sorry for the
>> > > confusion.
>> >
>> > That didn't last long. Two ways to fix the problem at the end:
>> >
>> > - Only map OOB IPIs as suggested by Philippe.
>> > Means we have to modify arm64_backtrace_ipi() and
>> > kgdb_roundup_cpus() for the dovetailing case.
>> > Calling arm64_send_ipi() with an ipi-nr != 0 is not allowed in the
>> > dovetailing case for inband IPIs.
>> >
>> > - Map all IRQs as suggested by me.
>> >
>> > Hopefully correct now...
>> >
>> > Which way is the preferred one?
>> >
>> > >
>>
>> Excerpt from arch/arm/kernel/smp.c:
>>
>> enum ipi_msg_type {
>> ...
>> /*
>> * SGI8-15 can be reserved by secure firmware, and thus may
>> * not be usable by the kernel. Please keep the above limited
>> * to at most 8 entries.
>> */
>> MAX_IPI
>> };
>
> That is now taken from arch/arm instead of arch/arm64. Is that also the
> case for arm64?
>
Yes, the issue is with the trusted firmware, which is the reference
implementation for armv7-A and armv8-A.
>>
>> This still holds true for ATF [1], so we only have 8 available SGIs
>> although GICv3+ do provide 16. Since we have 8 in-band IPI message types
>> defined by the arm64 port and we need 3 oob vectors more, we can't have
>> a 1:1 mapping between IPIs and SGIs.
>>
>> So far we are using 4 SGIs as explained above (1 in-band + 3 oob), so we
>> have 4 spares ATM. The reason for moving an in-band IPI to its own SGI
>> using one of those spares would be to prioritize it over the bulk of
>> in-band messages. Therefore, the question would be: do we need such
>> prioritization?
>
> I have no strong opinion on that and tried to restore what we had in the
> past. Looking at 6.12 at [2] now I had to realize that this was way more
> broken regarding IPI_BACKTRACE and IPI_KGDB_ROUNDUP than I had realized
> up to now.
>
I depends on what you mean by "more broken", triggering a CPU backtrace
does not crash the kernel on 6.12 (unlike 6.18) because we have at least
valid ipi_desc[] on the whole IPI range although no backtrace ever shows
up. :)
>>
>> [1] https://trustedfirmware-a.readthedocs.io/en/latest/porting-guide.html#function-bl31-platform-setup-mandatory
>
> [2] https://gitlab.com/Xenomai/linux-dovetail/-/blob/v6.12.y-dovetail/arch/arm64/kernel/smp.c?ref_type=heads#L1190
>
> What about the following end-result:
>
> enum ipi_msg_type {
> IPI_RESCHEDULE, // SGI0, used for inband multiplexing
> // RESCHDULE set as reason
>
> IPI_CALL_FUNC, // SGI1 reserved for OOB
> // CALL_FUNC via SGI0 with reason set
>
> IPI_CPU_STOP, // SGI2 reserved for OOB
> // CPU_STOP via SGI0 with reason set
>
> IPI_CPU_STOP_NMI, // SGI3 reserved for OOB
> // STOP_NMI via SGI0 with reason set
>
>
> // SGI4-7 unused
>
> IPI_TIMER, // via SGI0 with reason set
> IPI_IRQ_WORK, // via SGI0 with reason set
> NR_IPI,
> /*
> * Any enum >= NR_IPI and < MAX_IPI is special and not tracable
> * with trace_ipi_*
> */
> IPI_CPU_BACKTRACE = NR_IPI, // via SGI0 with reason set
> IPI_KGDB_ROUNDUP, // via SGI0 with reason set
Yep, this is what we should have if the current scheme is kept.
> MAX_IPI
> };
>
>
>
> Final questions:
>
> Assuming SGI mode: Where are the request_percpu_irq() calls for all the
> OOB SGIs?
The real-time core takes care of this (e.g. v3 does this in
pipeline_request_resched_ipi(), pipeline_install_tick_proxy()).
> Or: How is something like irq_send_oob_ipi(2, mask) expected
> to get the right IRQ descriptor in arm64_send_ipi()? Currently the
> descriptor for SGI0 is returned.
>
No, SGI1-3 may be returned, never SGI0.
arch/arm64/include/asm/irq_pipeline.h:
#define OOB_IPI_OFFSET 1 /* SGI1 */
#define TIMER_OOB_IPI (ipi_irq_base + OOB_IPI_OFFSET)
#define RESCHEDULE_OOB_IPI (TIMER_OOB_IPI + 1)
#define CALL_FUNCTION_OOB_IPI (RESCHEDULE_OOB_IPI + 1)
and:
unsigned int sgi = irq - ipi_irq_base;
The irq numbers passed to irq_send_oob_ipi() must be one of these IPI
values otherwise the debug assertion on entry would fail, so the mapping
is correct.
> Is that all just broken for a long time?
No, that part is ok. Only CPU backtracing and KGDB were broken due to
bypassing the mapping to SGI0, due to a merge fallout after upstream
reorganized their own mapping code. Otherwise no tick, no rescheduling
would have been received ever by Xenomai. You would have noticed :)
>
> In addition I think that the trace_ipi_raise() in __smp_cross_call() is
> incorrect for OOB SGIs...
>
Yes, would not break anything, but wrong IPI label in the traces for sure.
--
Philippe.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-02-04 18:04 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-02 7:55 [PATCH Dovetail 6.18 0/3] Fix IPI mapping for arm64 Florian Bezdeka
2026-02-02 7:55 ` [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs Florian Bezdeka
2026-02-03 13:08 ` Philippe Gerum
2026-02-03 15:25 ` Florian Bezdeka
2026-02-03 17:22 ` Philippe Gerum
2026-02-03 17:44 ` Philippe Gerum
2026-02-03 21:48 ` Florian Bezdeka
2026-02-03 22:00 ` Bezdeka, Florian
2026-02-04 11:44 ` Philippe Gerum
2026-02-04 16:46 ` Florian Bezdeka
2026-02-04 18:04 ` Philippe Gerum
2026-02-02 7:55 ` [PATCH Dovetail 6.18 2/3] arm64: irq_pipeline: Fix size of IPI statistics array Florian Bezdeka
2026-02-03 11:59 ` Philippe Gerum
2026-02-02 7:55 ` [PATCH Dovetail 6.18 3/3] arm64: irq_pipeline: Fix IPI_KGDB_ROUNDUP and IPI_CPU_BACKTRACE IPIs Florian Bezdeka
2026-02-03 11:59 ` Philippe Gerum
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox