summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2022-10-13 16:44:18 +1000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-10-21 12:39:28 +0200
commitbb3ff5c52b2793b40b986af8b3c2b74ebd0f8b44 (patch)
tree42a5c64f6eb47147248a67c17ccfdf17be7d17b6 /arch
parent9974d220c5073d035b5469d1d8ecd71da86c7afd (diff)
downloadlinux-stable-bb3ff5c52b2793b40b986af8b3c2b74ebd0f8b44.tar.gz
linux-stable-bb3ff5c52b2793b40b986af8b3c2b74ebd0f8b44.tar.bz2
linux-stable-bb3ff5c52b2793b40b986af8b3c2b74ebd0f8b44.zip
powerpc/64s/interrupt: Fix lost interrupts when returning to soft-masked context
commit a4cb3651a174366cc85a677da9e3681fbe97fdae upstream. It's possible for an interrupt returning to an irqs-disabled context to lose a pending soft-masked irq because it branches to part of the exit code for irqs-enabled contexts, which is meant to clear only the PACA_IRQS_HARD_DIS flag from PACAIRQHAPPENED by zeroing the byte. This just looks like a simple thinko from a recent commit (if there was no hard mask pending, there would be no reason to clear it anyway). This also adds comment to the code that actually does need to clear the flag. Fixes: e485f6c751e0a ("powerpc/64/interrupt: Fix return to masked context after hard-mask irq becomes pending") Reported-by: Sachin Sant <sachinp@linux.ibm.com> Reported-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20221013064418.1311104-1-npiggin@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/interrupt_64.S15
1 files changed, 13 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/interrupt_64.S b/arch/powerpc/kernel/interrupt_64.S
index d76376ce7291..2ca1c037ea25 100644
--- a/arch/powerpc/kernel/interrupt_64.S
+++ b/arch/powerpc/kernel/interrupt_64.S
@@ -571,7 +571,7 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel)
beq .Lfast_kernel_interrupt_return_\srr\() // EE already disabled
lbz r11,PACAIRQHAPPENED(r13)
andi. r10,r11,PACA_IRQ_MUST_HARD_MASK
- beq 1f // No HARD_MASK pending
+ beq .Lfast_kernel_interrupt_return_\srr\() // No HARD_MASK pending
/* Must clear MSR_EE from _MSR */
#ifdef CONFIG_PPC_BOOK3S
@@ -588,12 +588,23 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel)
b .Lfast_kernel_interrupt_return_\srr\()
.Linterrupt_return_\srr\()_soft_enabled:
+ /*
+ * In the soft-enabled case, need to double-check that we have no
+ * pending interrupts that might have come in before we reached the
+ * restart section of code, and restart the exit so those can be
+ * handled.
+ *
+ * If there are none, it is be possible that the interrupt still
+ * has PACA_IRQ_HARD_DIS set, which needs to be cleared for the
+ * interrupted context. This clear will not clobber a new pending
+ * interrupt coming in, because we're in the restart section, so
+ * such would return to the restart location.
+ */
#ifdef CONFIG_PPC_BOOK3S
lbz r11,PACAIRQHAPPENED(r13)
andi. r11,r11,(~PACA_IRQ_HARD_DIS)@l
bne- interrupt_return_\srr\()_kernel_restart
#endif
-1:
li r11,0
stb r11,PACAIRQHAPPENED(r13) // clear the possible HARD_DIS