Skip to content

Commit

Permalink
printk: restore flushing of NMI buffers on remote CPUs after NMI back…
Browse files Browse the repository at this point in the history
…traces

printk from NMI context relies on irq work being raised on the local CPU
to print to console. This can be a problem if the NMI was raised by a
lockup detector to print lockup stack and regs, because the CPU may not
enable irqs (because it is locked up).

Introduce printk_trigger_flush() that can be called another CPU to try
to get those messages to the console, call that where printk_safe_flush
was previously called.

Fixes: 93d102f ("printk: remove safe buffers")
Cc: stable@vger.kernel.org # 5.15
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Reviewed-by: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Petr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20211107045116.1754411-1-npiggin@gmail.com
  • Loading branch information
Nicholas Piggin authored and Petr Mladek committed Nov 10, 2021
1 parent 26d1982 commit 5d5e452
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 0 deletions.
6 changes: 6 additions & 0 deletions arch/powerpc/kernel/watchdog.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@ static void watchdog_smp_panic(int cpu, u64 tb)
if (sysctl_hardlockup_all_cpu_backtrace)
trigger_allbutself_cpu_backtrace();

/*
* Force flush any remote buffers that might be stuck in IRQ context
* and therefore could not run their irq_work.
*/
printk_trigger_flush();

if (hardlockup_panic)
nmi_panic(NULL, "Hard LOCKUP");

Expand Down
4 changes: 4 additions & 0 deletions include/linux/printk.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ void dump_stack_print_info(const char *log_lvl);
void show_regs_print_info(const char *log_lvl);
extern asmlinkage void dump_stack_lvl(const char *log_lvl) __cold;
extern asmlinkage void dump_stack(void) __cold;
void printk_trigger_flush(void);
#else
static inline __printf(1, 0)
int vprintk(const char *s, va_list args)
Expand Down Expand Up @@ -282,6 +283,9 @@ static inline void dump_stack_lvl(const char *log_lvl)
static inline void dump_stack(void)
{
}
static inline void printk_trigger_flush(void)
{
}
#endif

#ifdef CONFIG_SMP
Expand Down
5 changes: 5 additions & 0 deletions kernel/printk/printk.c
Original file line number Diff line number Diff line change
Expand Up @@ -3261,6 +3261,11 @@ void defer_console_output(void)
preempt_enable();
}

void printk_trigger_flush(void)
{
defer_console_output();
}

int vprintk_deferred(const char *fmt, va_list args)
{
int r;
Expand Down
6 changes: 6 additions & 0 deletions lib/nmi_backtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ void nmi_trigger_cpumask_backtrace(const cpumask_t *mask,
touch_softlockup_watchdog();
}

/*
* Force flush any remote buffers that might be stuck in IRQ context
* and therefore could not run their irq_work.
*/
printk_trigger_flush();

clear_bit_unlock(0, &backtrace_flag);
put_cpu();
}
Expand Down

0 comments on commit 5d5e452

Please sign in to comment.