1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * printk_safe.c - Safe printk for printk-deadlock-prone contexts
6 #include <linux/preempt.h>
9 #include <linux/cpumask.h>
10 #include <linux/printk.h>
11 #include <linux/console.h>
12 #include <linux/kprobes.h>
13 #include <linux/delay.h>
17 static DEFINE_PER_CPU(int, printk_context);
19 /* Can be preempted by NMI. */
20 void __printk_safe_enter(void)
22 this_cpu_inc(printk_context);
25 /* Can be preempted by NMI. */
26 void __printk_safe_exit(void)
28 this_cpu_dec(printk_context);
31 asmlinkage int vprintk(const char *fmt, va_list args)
33 #ifdef CONFIG_KGDB_KDB
34 /* Allow to pass printk() to kdb but avoid a recursion. */
35 if (unlikely(kdb_trap_printk && kdb_printf_cpu < 0))
36 return vkdb_printf(KDB_MSGSRC_PRINTK, fmt, args);
40 * Use the main logbuf even in NMI. But avoid calling console
41 * drivers that might have their own locks.
43 if (this_cpu_read(printk_context) || in_nmi()) {
46 len = vprintk_store(0, LOGLEVEL_DEFAULT, NULL, fmt, args);
47 defer_console_output();
52 return vprintk_default(fmt, args);
54 EXPORT_SYMBOL(vprintk);
57 * try_block_console_kthreads() - Try to block console kthreads and
58 * make the global console_lock() avaialble
60 * @timeout_ms: The maximum time (in ms) to wait.
62 * Prevent console kthreads from starting processing new messages. Wait
63 * until the global console_lock() become available.
65 * Context: Can be called in any context.
67 void try_block_console_kthreads(int timeout_ms)
69 block_console_kthreads = true;
71 /* Do not wait when the console lock could not be safely taken. */
72 if (this_cpu_read(printk_context) || in_nmi())
75 while (timeout_ms > 0) {
76 if (console_trylock()) {