powerpc/64s: prevent recursive replay_soft_interrupts causing superfluous interrupt
authorNicholas Piggin <npiggin@gmail.com>
Sat, 23 Jan 2021 06:12:44 +0000 (16:12 +1000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 3 Feb 2021 22:28:46 +0000 (23:28 +0100)
commitae02c0008c2794bc00b1adc3954249c27df3bf09
tree5fea5f53d2ff85ed835759231e9ef36e7e4eb88d
parent5f78c6ce1f6fa7ab1bd81860f4655cd9f5d5d28a
powerpc/64s: prevent recursive replay_soft_interrupts causing superfluous interrupt

[ Upstream commit 4025c784c573cab7e3f84746cc82b8033923ec62 ]

When an asynchronous interrupt calls irq_exit, it checks for softirqs
that may have been created, and runs them. Running softirqs enables
local irqs, which can replay pending interrupts causing recursion in
replay_soft_interrupts. This abridged trace shows how this can occur:

! NIP replay_soft_interrupts
  LR  interrupt_exit_kernel_prepare
  Call Trace:
    interrupt_exit_kernel_prepare (unreliable)
    interrupt_return
  --- interrupt: ea0 at __rb_reserve_next
  NIP __rb_reserve_next
  LR __rb_reserve_next
  Call Trace:
    ring_buffer_lock_reserve
    trace_function
    function_trace_call
    ftrace_call
    __do_softirq
    irq_exit
    timer_interrupt
!   replay_soft_interrupts
    interrupt_exit_kernel_prepare
    interrupt_return
  --- interrupt: ea0 at arch_local_irq_restore

This can not be prevented easily, because softirqs must not block hard
irqs, so it has to be dealt with.

The recursion is bounded by design in the softirq code because softirq
replay disables softirqs and loops around again to check for new
softirqs created while it ran, so that's not a problem.

However it does mess up interrupt replay state, causing superfluous
interrupts when the second replay_soft_interrupts clears a pending
interrupt, leaving it still set in the first call in the 'happened'
local variable.

Fix this by not caching a copy of irqs_happened across interrupt
handler calls.

Fixes: 3282a3da25bd ("powerpc/64: Implement soft interrupt replay in C")
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210123061244.2076145-1-npiggin@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/powerpc/kernel/irq.c