sparc32: keep PIL raised on the SMP ticker and LEON IPI exit paths
Subsystems (2)
PATCH 1/1 sparc32: keep PIL raised on the SMP ticker and LEON IPI exit paths
smp4m_ticker returns from smp4m_percpu_timer_interrupt() by writing the interrupted %psr back with traps enabled, which drops PIL before RESTORE_ALL. A level 14 tick pending again at that point is taken on top of the current trap frame, so back-to-back ticks nest one frame per tick until the 8K kernel stack runs into thread_info. Keep PIL at 15 until rett restores the interrupted %psr, as real_irq_continue does.
smp4d_ticker and smpleon_ipi exit the same way and get the same change.
Broken since 2.1.36 (sun4m), 2.1.97 (sun4d) and 2.6.33 (LEON).
---
Notes:
No Fixes: tag: this has been broken since 2.1.36 on sun4m (as smp_ticker) and since 2.1.97 on sun4d, before the git history. The LEON exit came with smpleon_ticker in 8401707ff645 ("sparc,leon:
Sparc-Leon SMP support") in 2.6.33 and moved to smpleon_ipi in 3.0; a
Fixes: tag naming one commit would date all three sites to it.
arch/sparc/kernel/entry.S | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
arch/sparc/kernel/entry.S +6 -3
@@ -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 raised until rett, or a + wr %g2, PSR_ET, %psr ! re-asserted tick nests on this frame 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 raised until rett, or a + wr %g2, PSR_ET, %psr ! re-asserted tick nests on this frame 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 raised until rett, or a + wr %g2, PSR_ET, %psr ! re-asserted IPI nests on this frame WRITE_PAUSE RESTORE_ALL
base-commit: 62f4c998b297cf233997a2b4cd6fc2d2df0319c9
Signature · 1 line
2.47.3
Andreas Larsson
maintainerHi Imre,
Quoted 30 lines · Imre Kaloz
smp4m_tickerreturns fromsmp4m_percpu_timer_interrupt()by writing the interrupted %psr back with traps enabled, which drops PIL beforeRESTORE_ALL. A level 14 tick pending again at that point is taken on top of the current trap frame, so back-to-back ticks nest one frame per tick until the 8K kernel stack runs intothread_info. Keep PIL at 15 until rett restores the interrupted %psr, asreal_irq_continuedoes.
smp4d_tickerandsmpleon_ipiexit the same way and get the same change.Broken since 2.1.36 (sun4m), 2.1.97 (sun4d) and 2.6.33 (LEON).
Signed-off-by Imre Kaloz <[email protected]>---
Notes:
No Fixes: tag: this has been broken since 2.1.36 on sun4m (assmp_ticker) and since 2.1.97 on sun4d, before the git history. The LEON exit came withsmpleon_tickerin8401707ff645("sparc,leon:
Sparc-Leon SMP support") in 2.6.33 and moved tosmpleon_ipiin 3.0; a
Fixes: tag naming one commit would date all three sites to it.arch/sparc/kernel/entry.S | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)arch/sparc/kernel/entry.S +0
-0
arch/sparc/kernel/entry.S smp4m_ticker: · line 256
Quoted 6 lines
arch/sparc/kernel/entry.S +2
-1@@ -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 raised until rett, or a + wr %g2, PSR_ET, %psr ! re-asserted tick nests on this frame
The nesting is just something that could happen. Please change language of these comments to reflect that or keep them shorter.
Quoted 24 lines
arch/sparc/kernel/entry.S +4
-2WRITE_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 raised until rett, or a + wr %g2, PSR_ET, %psr ! re-asserted tick nests on this frame 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 raised until rett, or a + wr %g2, PSR_ET, %psr ! re-asserted IPI nests on this frame WRITE_PAUSE RESTORE_ALL
Quoted 1 line
base-commit:
62f4c998b297cf233997a2b4cd6fc2d2df0319c9
Thanks,
Andreas
Quoted 3 lines · Imre Kaloz
smp4m_tickerreturns fromsmp4m_percpu_timer_interrupt()by writing the interrupted %psr back with traps enabled, which drops PIL beforeRESTORE_ALL.
I ran into the same problem independently and sent the same change as patch 1 of my series, with a description of how it shows up under qemu:
https://lore.kernel.org/sparclinux/[email protected]/
Tested under qemu 11.1.0, SS-20 with -smp 4: a multithreaded process writing a few hundred lines to the serial console sent the kernel to error state in 4 of 4 boots without the change and in 0 of 8 with it; two full runs of the uClibc-ng test suite on top completed without a crash.
arch/sparc/kernel/entry.S smpleon_ipi: · line 416
Quoted 10 lines · Imre Kaloz
arch/sparc/kernel/entry.S +2
-1@@ -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 raised until rett, or a + wr %g2, PSR_ET, %psr ! re-asserted IPI nests on this frame WRITE_PAUSE RESTORE_ALL
Tested on a GR-CPCI-GR740 board (LEON4).
// Ludwig