Re: [PATCH Dovetail 6.18 1/3] arm64: irq_pipeline: Fix mapping of SGI/LPI IPIs

Bezdeka, Florian
2026-02-03T22:00:57Z

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.