1 | // SPDX-License-Identifier: GPL-2.0-or-later |
---|---|
2 | /* |
3 | * printk_safe.c - Safe printk for printk-deadlock-prone contexts |
4 | */ |
5 | |
6 | #include <linux/preempt.h> |
7 | #include <linux/kdb.h> |
8 | #include <linux/smp.h> |
9 | #include <linux/cpumask.h> |
10 | #include <linux/printk.h> |
11 | #include <linux/kprobes.h> |
12 | |
13 | #include "internal.h" |
14 | |
15 | static DEFINE_PER_CPU(int, printk_context); |
16 | |
17 | /* Can be preempted by NMI. */ |
18 | void __printk_safe_enter(void) |
19 | { |
20 | this_cpu_inc(printk_context); |
21 | } |
22 | |
23 | /* Can be preempted by NMI. */ |
24 | void __printk_safe_exit(void) |
25 | { |
26 | this_cpu_dec(printk_context); |
27 | } |
28 | |
29 | asmlinkage int vprintk(const char *fmt, va_list args) |
30 | { |
31 | #ifdef CONFIG_KGDB_KDB |
32 | /* Allow to pass printk() to kdb but avoid a recursion. */ |
33 | if (unlikely(kdb_trap_printk && kdb_printf_cpu < 0)) |
34 | return vkdb_printf(src: KDB_MSGSRC_PRINTK, fmt, args); |
35 | #endif |
36 | |
37 | /* |
38 | * Use the main logbuf even in NMI. But avoid calling console |
39 | * drivers that might have their own locks. |
40 | */ |
41 | if (this_cpu_read(printk_context) || in_nmi()) |
42 | return vprintk_deferred(fmt, args); |
43 | |
44 | /* No obstacles. */ |
45 | return vprintk_default(fmt, args); |
46 | } |
47 | EXPORT_SYMBOL(vprintk); |
48 |