Skip to content

Commit 6572273

Browse files
npigginmpe
authored andcommitted
powerpc/64s/interrupt: Fix clear of PACA_IRQS_HARD_DIS when returning to soft-masked context
Commit a4cb365 ("powerpc/64s/interrupt: Fix lost interrupts when returning to soft-masked context") fixed the problem of pending irqs being cleared when clearing the HARD_DIS bit, but then it didn't clear the bit at all. This change clears HARD_DIS without affecting other bits in the mask. When an interrupt hits in a soft-masked section that has MSR[EE]=1, it can hard disable and set PACA_IRQS_HARD_DIS, which must be cleared when returning to the EE=1 caller (unless it was set due to a MUST_HARD_MASK interrupt becoming pending). Failure to clear this leaves the returned-to context running with MSR[EE]=1 and PACA_IRQS_HARD_DIS, which confuses irq assertions and could be dangerous for code that might test the flag. This was observed in a hash MMU kernel where a kernel hash fault hits in a local_irqs_disabled region that has EE=1. The hash fault also runs with EE=1, then as it returns, a decrementer hits in the restart section and the irq restart code hard-masks which sets the PACA_IRQ_HARD_DIS flag, which is not clear when the original context is returned to. Reported-by: Sachin Sant <[email protected]> Fixes: a4cb365 ("powerpc/64s/interrupt: Fix lost interrupts when returning to soft-masked context") Signed-off-by: Nicholas Piggin <[email protected]> Tested-by: Sachin Sant <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent dc398a0 commit 6572273

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

arch/powerpc/kernel/interrupt_64.S

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -532,15 +532,24 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel)
532532
* Returning to soft-disabled context.
533533
* Check if a MUST_HARD_MASK interrupt has become pending, in which
534534
* case we need to disable MSR[EE] in the return context.
535+
*
536+
* The MSR[EE] check catches among other things the short incoherency
537+
* in hard_irq_disable() between clearing MSR[EE] and setting
538+
* PACA_IRQ_HARD_DIS.
535539
*/
536540
ld r12,_MSR(r1)
537541
andi. r10,r12,MSR_EE
538542
beq .Lfast_kernel_interrupt_return_\srr\() // EE already disabled
539543
lbz r11,PACAIRQHAPPENED(r13)
540544
andi. r10,r11,PACA_IRQ_MUST_HARD_MASK
541-
beq .Lfast_kernel_interrupt_return_\srr\() // No HARD_MASK pending
545+
bne 1f // HARD_MASK is pending
546+
// No HARD_MASK pending, clear possible HARD_DIS set by interrupt
547+
andi. r11,r11,(~PACA_IRQ_HARD_DIS)@l
548+
stb r11,PACAIRQHAPPENED(r13)
549+
b .Lfast_kernel_interrupt_return_\srr\()
550+
542551

543-
/* Must clear MSR_EE from _MSR */
552+
1: /* Must clear MSR_EE from _MSR */
544553
#ifdef CONFIG_PPC_BOOK3S
545554
li r10,0
546555
/* Clear valid before changing _MSR */

0 commit comments

Comments
 (0)