Commit a7cba02d authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman

powerpc: allow soft-NMI watchdog to cover timer interrupts with large decrementers

Large decrementers (e.g., POWER9) can take a very long time to wrap,
so when the timer iterrupt handler sets the decrementer to max so as
to avoid taking another decrementer interrupt when hard enabling
interrupts before running timers, it effectively disables the soft
NMI coverage for timer interrupts.

Fix this by using the traditional 31-bit value instead, which wraps
after a few seconds. masked interrupt code does the same thing, and
in normal operation neither of these paths would ever wrap even the
31 bit value.

Note: the SMP watchdog should catch timer interrupt lockups, but it
is preferable for the local soft-NMI to catch them, mainly to avoid
the IPI.
Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 3f984620
......@@ -578,22 +578,29 @@ void timer_interrupt(struct pt_regs *regs)
struct pt_regs *old_regs;
u64 now;
/* Ensure a positive value is written to the decrementer, or else
* some CPUs will continue to take decrementer exceptions.
*/
set_dec(decrementer_max);
/* Some implementations of hotplug will get timer interrupts while
* offline, just ignore these and we also need to set
* decrementers_next_tb as MAX to make sure __check_irq_replay
* don't replay timer interrupt when return, otherwise we'll trap
* here infinitely :(
*/
if (!cpu_online(smp_processor_id())) {
if (unlikely(!cpu_online(smp_processor_id()))) {
*next_tb = ~(u64)0;
set_dec(decrementer_max);
return;
}
/* Ensure a positive value is written to the decrementer, or else
* some CPUs will continue to take decrementer exceptions. When the
* PPC_WATCHDOG (decrementer based) is configured, keep this at most
* 31 bits, which is about 4 seconds on most systems, which gives
* the watchdog a chance of catching timer interrupt hard lockups.
*/
if (IS_ENABLED(CONFIG_PPC_WATCHDOG))
set_dec(0x7fffffff);
else
set_dec(decrementer_max);
/* Conditionally hard-enable interrupts now that the DEC has been
* bumped to its maximum value
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment