1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Provide a default dump_stack() function for architectures 4 * which don't implement their own. 5 */ 6 7 #include <linux/kernel.h> 8 #include <linux/export.h> 9 #include <linux/sched.h> 10 #include <linux/sched/debug.h> 11 #include <linux/smp.h> 12 #include <linux/atomic.h> 13 #include <linux/kexec.h> 14 #include <linux/utsname.h> 15 16 static char dump_stack_arch_desc_str[128]; 17 18 /** 19 * dump_stack_set_arch_desc - set arch-specific str to show with task dumps 20 * @fmt: printf-style format string 21 * @...: arguments for the format string 22 * 23 * The configured string will be printed right after utsname during task 24 * dumps. Usually used to add arch-specific system identifiers. If an 25 * arch wants to make use of such an ID string, it should initialize this 26 * as soon as possible during boot. 27 */ 28 void __init dump_stack_set_arch_desc(const char *fmt, ...) 29 { 30 va_list args; 31 32 va_start(args, fmt); 33 vsnprintf(dump_stack_arch_desc_str, sizeof(dump_stack_arch_desc_str), 34 fmt, args); 35 va_end(args); 36 } 37 38 /** 39 * dump_stack_print_info - print generic debug info for dump_stack() 40 * @log_lvl: log level 41 * 42 * Arch-specific dump_stack() implementations can use this function to 43 * print out the same debug information as the generic dump_stack(). 44 */ 45 void dump_stack_print_info(const char *log_lvl) 46 { 47 printk("%sCPU: %d PID: %d Comm: %.20s %s%s %s %.*s\n", 48 log_lvl, raw_smp_processor_id(), current->pid, current->comm, 49 kexec_crash_loaded() ? "Kdump: loaded " : "", 50 print_tainted(), 51 init_utsname()->release, 52 (int)strcspn(init_utsname()->version, " "), 53 init_utsname()->version); 54 55 if (dump_stack_arch_desc_str[0] != '\0') 56 printk("%sHardware name: %s\n", 57 log_lvl, dump_stack_arch_desc_str); 58 59 print_worker_info(log_lvl, current); 60 } 61 62 /** 63 * show_regs_print_info - print generic debug info for show_regs() 64 * @log_lvl: log level 65 * 66 * show_regs() implementations can use this function to print out generic 67 * debug information. 68 */ 69 void show_regs_print_info(const char *log_lvl) 70 { 71 dump_stack_print_info(log_lvl); 72 } 73 74 static void __dump_stack(void) 75 { 76 dump_stack_print_info(KERN_DEFAULT); 77 show_stack(NULL, NULL, KERN_DEFAULT); 78 } 79 80 /** 81 * dump_stack - dump the current task information and its stack trace 82 * 83 * Architectures can override this implementation by implementing its own. 84 */ 85 #ifdef CONFIG_SMP 86 static atomic_t dump_lock = ATOMIC_INIT(-1); 87 88 asmlinkage __visible void dump_stack(void) 89 { 90 unsigned long flags; 91 int was_locked; 92 int old; 93 int cpu; 94 95 /* 96 * Permit this cpu to perform nested stack dumps while serialising 97 * against other CPUs 98 */ 99 retry: 100 local_irq_save(flags); 101 cpu = smp_processor_id(); 102 old = atomic_cmpxchg(&dump_lock, -1, cpu); 103 if (old == -1) { 104 was_locked = 0; 105 } else if (old == cpu) { 106 was_locked = 1; 107 } else { 108 local_irq_restore(flags); 109 /* 110 * Wait for the lock to release before jumping to 111 * atomic_cmpxchg() in order to mitigate the thundering herd 112 * problem. 113 */ 114 do { cpu_relax(); } while (atomic_read(&dump_lock) != -1); 115 goto retry; 116 } 117 118 __dump_stack(); 119 120 if (!was_locked) 121 atomic_set(&dump_lock, -1); 122 123 local_irq_restore(flags); 124 } 125 #else 126 asmlinkage __visible void dump_stack(void) 127 { 128 __dump_stack(); 129 } 130 #endif 131 EXPORT_SYMBOL(dump_stack); 132