Skip to contentSkip to conversation

sparc32: keep PIL raised on the SMP ticker and LEON IPI exit paths

PATCH Superseded Imre Kaloz 4 participants 4 messages Sep 27 – Oct 16

Subsystems (2)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Imre Kaloz

author
#0 lore raw

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
index ea51ef52c952..7288da5f6727 100644
@@ -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
maintainer
#1 lore raw

Hi Imre,

Quoted 30 lines · Imre Kaloz

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 +0 -0
index ea51ef52c952..7288da5f6727 100644

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 -2
 	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
 
Quoted 1 line

base-commit: 62f4c998b297cf233997a2b4cd6fc2d2df0319c9

Thanks,
Andreas

Tested-by on v1 1/1
#2 lore raw
In reply to Imre Kaloz
Quoted 3 lines · Imre Kaloz

smp4m_ticker returns from smp4m_percpu_timer_interrupt() by writing the interrupted %psr back with traps enabled, which drops PIL before RESTORE_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.

Tested-by on v1 1/1
#3 lore raw
In reply to Imre Kaloz

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