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/console.h> 12 #include <linux/kprobes.h> 13 #include <linux/delay.h> 14 15 #include "internal.h" 16 17 static DEFINE_PER_CPU(int, printk_context); 18 19 /* Can be preempted by NMI. */ 20 void __printk_safe_enter(void) 21 { 22 this_cpu_inc(printk_context); 23 } 24 25 /* Can be preempted by NMI. */ 26 void __printk_safe_exit(void) 27 { 28 this_cpu_dec(printk_context); 29 } 30 31 asmlinkage int vprintk(const char *fmt, va_list args) 32 { 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); 37 #endif 38 39 /* 40 * Use the main logbuf even in NMI. But avoid calling console 41 * drivers that might have their own locks. 42 */ 43 if (this_cpu_read(printk_context) || in_nmi()) { 44 int len; 45 46 len = vprintk_store(0, LOGLEVEL_DEFAULT, NULL, fmt, args); 47 defer_console_output(); 48 return len; 49 } 50 51 /* No obstacles. */ 52 return vprintk_default(fmt, args); 53 } 54 EXPORT_SYMBOL(vprintk); 55 56 /** 57 * try_block_console_kthreads() - Try to block console kthreads and 58 * make the global console_lock() avaialble 59 * 60 * @timeout_ms: The maximum time (in ms) to wait. 61 * 62 * Prevent console kthreads from starting processing new messages. Wait 63 * until the global console_lock() become available. 64 * 65 * Context: Can be called in any context. 66 */ 67 void try_block_console_kthreads(int timeout_ms) 68 { 69 block_console_kthreads = true; 70 71 /* Do not wait when the console lock could not be safely taken. */ 72 if (this_cpu_read(printk_context) || in_nmi()) 73 return; 74 75 while (timeout_ms > 0) { 76 if (console_trylock()) { 77 console_unlock(); 78 return; 79 } 80 81 udelay(1000); 82 timeout_ms -= 1; 83 } 84 } 85