1 From 65722736c3baf29e02e964a09e85c9ef71c48e8d Mon Sep 17 00:00:00 2001
2 From: Nicholas Piggin <npiggin@gmail.com>
3 Date: Sat, 22 Oct 2022 15:22:07 +1000
4 Subject: powerpc/64s/interrupt: Fix clear of PACA_IRQS_HARD_DIS when returning to soft-masked context
6 From: Nicholas Piggin <npiggin@gmail.com>
8 commit 65722736c3baf29e02e964a09e85c9ef71c48e8d upstream.
10 Commit a4cb3651a1743 ("powerpc/64s/interrupt: Fix lost interrupts when
11 returning to soft-masked context") fixed the problem of pending irqs
12 being cleared when clearing the HARD_DIS bit, but then it didn't clear
13 the bit at all. This change clears HARD_DIS without affecting other bits
16 When an interrupt hits in a soft-masked section that has MSR[EE]=1, it
17 can hard disable and set PACA_IRQS_HARD_DIS, which must be cleared when
18 returning to the EE=1 caller (unless it was set due to a MUST_HARD_MASK
19 interrupt becoming pending). Failure to clear this leaves the
20 returned-to context running with MSR[EE]=1 and PACA_IRQS_HARD_DIS, which
21 confuses irq assertions and could be dangerous for code that might test
24 This was observed in a hash MMU kernel where a kernel hash fault hits in
25 a local_irqs_disabled region that has EE=1. The hash fault also runs
26 with EE=1, then as it returns, a decrementer hits in the restart section
27 and the irq restart code hard-masks which sets the PACA_IRQ_HARD_DIS
28 flag, which is not clear when the original context is returned to.
30 Reported-by: Sachin Sant <sachinp@linux.ibm.com>
31 Fixes: a4cb3651a1743 ("powerpc/64s/interrupt: Fix lost interrupts when returning to soft-masked context")
32 Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
33 Tested-by: Sachin Sant <sachinp@linux.ibm.com>
34 Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
35 Link: https://lore.kernel.org/r/20221022052207.471328-1-npiggin@gmail.com
36 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
38 arch/powerpc/kernel/interrupt_64.S | 13 +++++++++++--
39 1 file changed, 11 insertions(+), 2 deletions(-)
41 --- a/arch/powerpc/kernel/interrupt_64.S
42 +++ b/arch/powerpc/kernel/interrupt_64.S
43 @@ -565,15 +565,24 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\s
44 * Returning to soft-disabled context.
45 * Check if a MUST_HARD_MASK interrupt has become pending, in which
46 * case we need to disable MSR[EE] in the return context.
48 + * The MSR[EE] check catches among other things the short incoherency
49 + * in hard_irq_disable() between clearing MSR[EE] and setting
50 + * PACA_IRQ_HARD_DIS.
54 beq .Lfast_kernel_interrupt_return_\srr\() // EE already disabled
55 lbz r11,PACAIRQHAPPENED(r13)
56 andi. r10,r11,PACA_IRQ_MUST_HARD_MASK
57 - beq .Lfast_kernel_interrupt_return_\srr\() // No HARD_MASK pending
58 + bne 1f // HARD_MASK is pending
59 + // No HARD_MASK pending, clear possible HARD_DIS set by interrupt
60 + andi. r11,r11,(~PACA_IRQ_HARD_DIS)@l
61 + stb r11,PACAIRQHAPPENED(r13)
62 + b .Lfast_kernel_interrupt_return_\srr\()
64 - /* Must clear MSR_EE from _MSR */
66 +1: /* Must clear MSR_EE from _MSR */
67 #ifdef CONFIG_PPC_BOOK3S
69 /* Clear valid before changing _MSR */