mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
powerpc/64s/interrupt: Fix clear of PACA_IRQS_HARD_DIS when returning to soft-masked context
Commita4cb3651a1
("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 <sachinp@linux.ibm.com> Fixes:a4cb3651a1
("powerpc/64s/interrupt: Fix lost interrupts when returning to soft-masked context") Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Tested-by: Sachin Sant <sachinp@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20221022052207.471328-1-npiggin@gmail.com
This commit is contained in:
parent
dc398a084d
commit
65722736c3
@ -532,15 +532,24 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel)
|
||||
* Returning to soft-disabled context.
|
||||
* Check if a MUST_HARD_MASK interrupt has become pending, in which
|
||||
* case we need to disable MSR[EE] in the return context.
|
||||
*
|
||||
* The MSR[EE] check catches among other things the short incoherency
|
||||
* in hard_irq_disable() between clearing MSR[EE] and setting
|
||||
* PACA_IRQ_HARD_DIS.
|
||||
*/
|
||||
ld r12,_MSR(r1)
|
||||
andi. r10,r12,MSR_EE
|
||||
beq .Lfast_kernel_interrupt_return_\srr\() // EE already disabled
|
||||
lbz r11,PACAIRQHAPPENED(r13)
|
||||
andi. r10,r11,PACA_IRQ_MUST_HARD_MASK
|
||||
beq .Lfast_kernel_interrupt_return_\srr\() // No HARD_MASK pending
|
||||
bne 1f // HARD_MASK is pending
|
||||
// No HARD_MASK pending, clear possible HARD_DIS set by interrupt
|
||||
andi. r11,r11,(~PACA_IRQ_HARD_DIS)@l
|
||||
stb r11,PACAIRQHAPPENED(r13)
|
||||
b .Lfast_kernel_interrupt_return_\srr\()
|
||||
|
||||
/* Must clear MSR_EE from _MSR */
|
||||
|
||||
1: /* Must clear MSR_EE from _MSR */
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
li r10,0
|
||||
/* Clear valid before changing _MSR */
|
||||
|
Loading…
Reference in New Issue
Block a user