Re: [PATCH v4 16/26] genirq: Allow per-cpu interrupt sharing for non-overlapping affinities

Marc Zyngier
2025-12-04T14:21:55Z

On Thu, 04 Dec 2025 10:56:13 +0000,
Daniel Thompson <danielt@kernel.org> wrote:
>
> On Mon, Oct 20, 2025 at 01:29:33PM +0100, Marc Zyngier wrote:
> > Interrupt sharing for percpu-devid interrupts is forbidden, and
> > for good reasons. These are interrupts generated *from* a CPU and
> > handled by itself (timer, for example). Nobody in their right mind
> > would put two devices on the same pin (and if they have, they get to
> > keep the pieces...).
> >
> > But this also prevents more benign cases, where devices are connected
> > to groups of CPUs, and for which the affinities are not overlapping.
> > Effectively, the only thing they share is the interrupt number, and
> > nothing else.
> >
> > Let's tweak the definition of IRQF_SHARED applied to percpu_devid
> > interrupts to allow this particular case. This results in extra
> > validation at the point of the interrupt being setup and freed,
> > as well as a tiny bit of extra complexity for interrupts at handling
> > time (to pick the correct irqaction).
> >
> > Tested-by: Will Deacon <will@kernel.org>
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
>
> I picked up this patch via linux-next and it appears be causing boot
> regressions on MIPS/qemu. This patch was identified with a bisect and
> a git revert of this patch from the linux-next tip resolves the problem
> (specifically, next-20251204 with git revert bdf4e2ac295f).
>
> I'm running the code as part of the kgdb test suite but the system
> doesn't survive long enough for kgdb to be involved. In fact I was able
> to reduce things to the following reproduction with all the kgdb pieces
> removed:
>
> make malta_kvm_defconfig generic/64r6.config
> ../scripts/config \
> --enable WERROR --enable CPU_MIPS64_R6 --enable MIPS_CPS \
> --enable BLK_DEV_INITRD --set-val FRAME_WARN 2048
> make olddefconfig
> make -j$(nproc) all
> qemu-system-mips64el -cpu I6400 -M malta -m 1G -smp 2 \
> -kernel vmlinux -nographic \
> -append " console=ttyS0,115200 clk_ignore_unused"

Many thanks for the minimal reproducer, that really helped a lot!

[...]

> CPU 0 Unable to handle kernel paging request at virtual address 0000000000000000, epc == ffffffff801c2398, ra == ffffffff801bab00
> Oops[#1]:
> CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.18.0-next-20251204 #20 NONE
> Hardware name: mti,malta
> $ 0 : 0000000000000000 0000000000000001 0000000000000000 0000000000000000
> $ 4 : 0000000000000001 a8000000020e8008 0000000000000000 ffffffff80c23b80
> $ 8 : 0000000000000004 0000000000000000 0000000000000000 000000000000002f
> $12 : a8000000020f4000 0000000000003ff0 0000000000003000 0000000000000003
> $16 : ffffffff80d095c0 ffffffff80ceb410 0000000000000019 ffffffff80c378c0
> $20 : ffffffff80c4bec8 0000000000000000 ffffffff80e00000 ffffffff80de0000
> $24 : 0000000000000000 0000000000000010
> $28 : ffffffff80c20000 a8000000020f7ec0 a800000000e12fcd ffffffff801bab00
> epc : ffffffff801c2398 handle_percpu_devid_irq+0xb8/0x250
> ra : ffffffff801bab00 handle_irq_desc+0x48/0x88
> Status: 1400a4e2 KX SX UX KERNEL EXL
> Cause : 00800408 (ExcCode 02)
> BadVA : 0000000000000000
> PrId : 0001a900 (MIPS I6400)
> Modules linked in:
> Process swapper/0 (pid: 0, threadinfo=(____ptrval____), task=(____ptrval____), tls=0000000000000000)
> Stack : ffffffff80c35a2c 0000000000000002 ffffffff80e00000 0fffffffffffffff
> ffffffff80c50000 0000000000000001 0000000000000003 ffffffff801bab00
> 0000000000000000 ffffffff805d82a8 0000000000000000 0000000000000008
> 0000000000000000 0000000000000000 0000000000000000 5189d95a7a4f4800
> a800000002014300 0000000000000002 0000000000000001 000000000000001f
> ffffffff80e00000 0000000000000004 0000000000000000 ffffffff801bab00
> 0000000000000000 ffffffff809ec128 0000000000000001 fffffffffffffffb
> 0000000000000001 ffffffff805d7ebc 0000000000000000 0000000000000000
> ffffffff80c23c80 ffffffff80c50000 ffffffff80de0000 ffffffff80db0000
> 0000000000000000 ffffffff80112f10 ffffffff80c23c80 0000000000000000
> Call Trace:
> [<ffffffff801c2398>] handle_percpu_devid_irq+0xb8/0x250
> [<ffffffff801bab00>] handle_irq_desc+0x48/0x88
> [<ffffffff805d82a8>] gic_irq_dispatch+0xc0/0x288
> [<ffffffff801bab00>] handle_irq_desc+0x48/0x88
> [<ffffffff809ec128>] do_domain_IRQ+0x28/0x40
> [<ffffffff805d7ebc>] plat_irq_dispatch+0x64/0xe8
> [<ffffffff80112f10>] handle_int+0x134/0x140
> [<ffffffff80110dc8>] calibrate_delay+0x158/0x290
> [<ffffffff80d58e48>] start_kernel+0x754/0x7a4

This hack fixes it for me, but really, mips needs to grow up and stop
using these antiquated APIs.

Can please you give it a go?

Thanks,

M.

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 0bb29316b4362..8b1b4c8a4f54c 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2470,6 +2470,9 @@ int setup_percpu_irq(unsigned int irq, struct irqaction *act)
if (retval < 0)
return retval;

+ if (!act->affinity)
+ act->affinity = cpu_online_mask;
+
retval = __setup_irq(irq, desc, act);

if (retval)

--
Without deviation from the norm, progress is not possible.