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/kprobes.h>
15 /* Context where printk messages are never suppressed */
16 static atomic_t force_con
;
18 void printk_force_console_enter(void)
20 atomic_inc(&force_con
);
23 void printk_force_console_exit(void)
25 atomic_dec(&force_con
);
28 bool is_printk_force_console(void)
30 return atomic_read(&force_con
);
33 static DEFINE_PER_CPU(int, printk_context
);
35 /* Can be preempted by NMI. */
36 void __printk_safe_enter(void)
38 this_cpu_inc(printk_context
);
41 /* Can be preempted by NMI. */
42 void __printk_safe_exit(void)
44 this_cpu_dec(printk_context
);
47 void __printk_deferred_enter(void)
50 __printk_safe_enter();
53 void __printk_deferred_exit(void)
59 bool is_printk_legacy_deferred(void)
62 * The per-CPU variable @printk_context can be read safely in any
63 * context. CPU migration is always disabled when set.
65 return (force_legacy_kthread() ||
66 this_cpu_read(printk_context
) ||
70 asmlinkage
int vprintk(const char *fmt
, va_list args
)
72 #ifdef CONFIG_KGDB_KDB
73 /* Allow to pass printk() to kdb but avoid a recursion. */
74 if (unlikely(kdb_trap_printk
&& kdb_printf_cpu
< 0))
75 return vkdb_printf(KDB_MSGSRC_PRINTK
, fmt
, args
);
79 * Use the main logbuf even in NMI. But avoid calling console
80 * drivers that might have their own locks.
82 if (is_printk_legacy_deferred())
83 return vprintk_deferred(fmt
, args
);
86 return vprintk_default(fmt
, args
);
88 EXPORT_SYMBOL(vprintk
);