Skip to content

Commit

Permalink
powerpc/64s/interrupt: Fix lost interrupts when returning to soft-mas…
Browse files Browse the repository at this point in the history
…ked context

commit a4cb365 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: e485f6c ("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>
  • Loading branch information
npiggin authored and gregkh committed Oct 21, 2022
1 parent 9974d22 commit bb3ff5c
Showing 1 changed file with 13 additions and 2 deletions.
15 changes: 13 additions & 2 deletions arch/powerpc/kernel/interrupt_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down

0 comments on commit bb3ff5c

Please sign in to comment.