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