Re: [PATCH 1/4] sparc32: keep PIL raised until the IRQ frame is gone
From: Andreas Larsson
Date: Thu Oct 15 2026 - 08:40:17 EST
On 2026-10-15 10:55, Ramin Moussavi wrote:
> The per-cpu timer interrupts on sun4m and sun4d SMP, and the LEON SMP
> IPI, leave their handler with
>
> wr %l0, PSR_ET, %psr
> WRITE_PAUSE
> RESTORE_ALL
>
> %l0 is the PSR at trap time, so this turns traps back on at the PIL of
> the interrupted code, usually 0, while the trap frame is still on the
> stack. Any interrupt that is pending at that point is taken on top of
> the frame, and if it leaves through the same path it opens the same
> window one level deeper. A source that keeps firing makes the nesting
> unbounded: the kernel stack runs into its thread_info, w_saved and the
> task pointer get overwritten, and the next window trap stores through
> them with traps disabled. The CPU goes to error state.
>
> The generic path does not have this problem. real_irq_continue keeps
> PIL at 15 after handler_irq and lets ret_trap_entry restore the old PIL
> together with the rett. It was fixed that way in Linux 2.1.129
> (entry.S 1.153, November 1998):
>
> - wr %l0, PSR_ET, %psr
> + or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq
> + wr %g2, PSR_ET, %psr ! keep ET up
>
> smp_ticker had been added in 2.1.36 with a copy of the old exit, and
> kept it through the rename to smp4m_ticker and the addition of
> smp4d_ticker in 2.1.97. smpleon_ipi copied the pattern in 2011. Do the
> same as real_irq_continue in all three.
>
> On hardware the window is a few instructions long and no interrupt
> source refills it that fast. qemu does: its ESCC finishes a transmit
> instantly, and since 8.2 it takes a pending interrupt right after rett
> (930f1865cc65 "target/sparc: Clear may_lookup for npc == DYNAMIC_PC").
> A burst of console output on an SS-20 with -smp 4 is enough. A trap
> ring buffer in trap_setup showed the level 12 serial interrupt taken
> over and over at smp4m_ticker+0x34, timer ticks nesting further down,
> and the frames sinking below the thread_info.
>
> Tested on qemu 11.1.0, SS-20, -smp 4, with a test that writes a few
> hundred lines to the serial console from a multithreaded process: the
> kernel went to error state in 4 of 4 boots before, and booted cleanly
> 8 of 8 times after. Two full runs of the uClibc-ng test suite on top
> then completed without a crash. LEON SMP was tested on qemu's
> leon3_generic with -smp 4, where a full run of the suite completed
> without a crash as well. sun4d gets the same one line change but was
> not run; qemu has no sun4d machine.
>
> Cc: stable@xxxxxxxxxxxxxxx
> Assisted-by: Claude:claude-opus-5-5
> Signed-off-by: Ramin Moussavi <ramin.moussavi@xxxxxxxxx>
> ---
> arch/sparc/kernel/entry.S | 9 ++++++---
> 1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
> index ea51ef52c952..87d03a58446e 100644
> --- a/arch/sparc/kernel/entry.S
> +++ b/arch/sparc/kernel/entry.S
> @@ -252,7 +252,8 @@ smp4m_ticker:
> WRITE_PAUSE
> call smp4m_percpu_timer_interrupt
> add %sp, STACKFRAME_SZ, %o0
> - wr %l0, PSR_ET, %psr
> + or %l0, PSR_PIL, %g2 ! keep PIL up until the frame is gone
> + wr %g2, PSR_ET, %psr
> WRITE_PAUSE
> RESTORE_ALL
>
> @@ -353,7 +354,8 @@ smp4d_ticker:
> WRITE_PAUSE
> call smp4d_percpu_timer_interrupt
> add %sp, STACKFRAME_SZ, %o0
> - wr %l0, PSR_ET, %psr
> + or %l0, PSR_PIL, %g2 ! keep PIL up until the frame is gone
> + wr %g2, PSR_ET, %psr
> WRITE_PAUSE
> RESTORE_ALL
>
> @@ -407,7 +409,8 @@ smpleon_ipi:
> WRITE_PAUSE
> call leonsmp_ipi_interrupt
> add %sp, STACKFRAME_SZ, %o1 ! pt_regs
> - wr %l0, PSR_ET, %psr
> + or %l0, PSR_PIL, %g2 ! keep PIL up until the frame is gone
> + wr %g2, PSR_ET, %psr
> WRITE_PAUSE
> RESTORE_ALL
>
>
> base-commit: d419d682257d813f6cb7a28e42b35d0edf4ad038
Hi Ramin,
Thanks for the patch! This patch however has the exact same change as
https://lore.kernel.org/sparclinux/20260927005658.8242-1-kaloz@xxxxxxxxxx/#r
that is not yet picked up but not forgotten.
Could you add a Tested-by: in that thread instead and describe on what
you have tested there. Feel free to link to this thread as a lore link
in your answer as your two writeups complement each other nicely.
Thanks,
Andreas