xref: /linux-6.15/lib/dump_stack.c (revision d167706f)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Provide a default dump_stack() function for architectures
41da177e4SLinus Torvalds  * which don't implement their own.
51da177e4SLinus Torvalds  */
61da177e4SLinus Torvalds 
71da177e4SLinus Torvalds #include <linux/kernel.h>
822f4e66dSStephen Boyd #include <linux/buildid.h>
98bc3bcc9SPaul Gortmaker #include <linux/export.h>
10196779b9STejun Heo #include <linux/sched.h>
11b17b0153SIngo Molnar #include <linux/sched/debug.h>
12b58d9774SAlex Thorlton #include <linux/smp.h>
13b58d9774SAlex Thorlton #include <linux/atomic.h>
14e36df28fSDave Young #include <linux/kexec.h>
15e36df28fSDave Young #include <linux/utsname.h>
16a8b62fd0SPeter Zijlstra #include <linux/stop_machine.h>
17e36df28fSDave Young 
18e36df28fSDave Young static char dump_stack_arch_desc_str[128];
19e36df28fSDave Young 
20e36df28fSDave Young /**
21e36df28fSDave Young  * dump_stack_set_arch_desc - set arch-specific str to show with task dumps
22e36df28fSDave Young  * @fmt: printf-style format string
23e36df28fSDave Young  * @...: arguments for the format string
24e36df28fSDave Young  *
25e36df28fSDave Young  * The configured string will be printed right after utsname during task
26e36df28fSDave Young  * dumps.  Usually used to add arch-specific system identifiers.  If an
27e36df28fSDave Young  * arch wants to make use of such an ID string, it should initialize this
28e36df28fSDave Young  * as soon as possible during boot.
29e36df28fSDave Young  */
dump_stack_set_arch_desc(const char * fmt,...)30e36df28fSDave Young void __init dump_stack_set_arch_desc(const char *fmt, ...)
31e36df28fSDave Young {
32e36df28fSDave Young 	va_list args;
33e36df28fSDave Young 
34e36df28fSDave Young 	va_start(args, fmt);
35e36df28fSDave Young 	vsnprintf(dump_stack_arch_desc_str, sizeof(dump_stack_arch_desc_str),
36e36df28fSDave Young 		  fmt, args);
37e36df28fSDave Young 	va_end(args);
38e36df28fSDave Young }
39e36df28fSDave Young 
4022f4e66dSStephen Boyd #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)
4122f4e66dSStephen Boyd #define BUILD_ID_FMT " %20phN"
4222f4e66dSStephen Boyd #define BUILD_ID_VAL vmlinux_build_id
4322f4e66dSStephen Boyd #else
4422f4e66dSStephen Boyd #define BUILD_ID_FMT "%s"
4522f4e66dSStephen Boyd #define BUILD_ID_VAL ""
4622f4e66dSStephen Boyd #endif
4722f4e66dSStephen Boyd 
48e36df28fSDave Young /**
49e36df28fSDave Young  * dump_stack_print_info - print generic debug info for dump_stack()
50e36df28fSDave Young  * @log_lvl: log level
51e36df28fSDave Young  *
52e36df28fSDave Young  * Arch-specific dump_stack() implementations can use this function to
53e36df28fSDave Young  * print out the same debug information as the generic dump_stack().
54e36df28fSDave Young  */
dump_stack_print_info(const char * log_lvl)55e36df28fSDave Young void dump_stack_print_info(const char *log_lvl)
56e36df28fSDave Young {
57*d167706fSSebastian Andrzej Siewior 	printk("%sCPU: %d UID: %u PID: %d Comm: %.20s %s%s %s %.*s %s " BUILD_ID_FMT "\n",
58d2917ff1SSuren Baghdasaryan 	       log_lvl, raw_smp_processor_id(),
59d2917ff1SSuren Baghdasaryan 	       __kuid_val(current_real_cred()->euid),
60d2917ff1SSuren Baghdasaryan 	       current->pid, current->comm,
61e36df28fSDave Young 	       kexec_crash_loaded() ? "Kdump: loaded " : "",
62e36df28fSDave Young 	       print_tainted(),
63e36df28fSDave Young 	       init_utsname()->release,
64e36df28fSDave Young 	       (int)strcspn(init_utsname()->version, " "),
65*d167706fSSebastian Andrzej Siewior 	       init_utsname()->version, preempt_model_str(), BUILD_ID_VAL);
66e36df28fSDave Young 
672f183c68SJani Nikula 	if (get_taint())
682f183c68SJani Nikula 		printk("%s%s\n", log_lvl, print_tainted_verbose());
692f183c68SJani Nikula 
70e36df28fSDave Young 	if (dump_stack_arch_desc_str[0] != '\0')
71e36df28fSDave Young 		printk("%sHardware name: %s\n",
72e36df28fSDave Young 		       log_lvl, dump_stack_arch_desc_str);
73e36df28fSDave Young 
74e36df28fSDave Young 	print_worker_info(log_lvl, current);
75a8b62fd0SPeter Zijlstra 	print_stop_info(log_lvl, current);
761538e339SDavid Vernet 	print_scx_info(log_lvl, current);
77e36df28fSDave Young }
78e36df28fSDave Young 
79e36df28fSDave Young /**
80e36df28fSDave Young  * show_regs_print_info - print generic debug info for show_regs()
81e36df28fSDave Young  * @log_lvl: log level
82e36df28fSDave Young  *
83e36df28fSDave Young  * show_regs() implementations can use this function to print out generic
84e36df28fSDave Young  * debug information.
85e36df28fSDave Young  */
show_regs_print_info(const char * log_lvl)86e36df28fSDave Young void show_regs_print_info(const char *log_lvl)
87e36df28fSDave Young {
88e36df28fSDave Young 	dump_stack_print_info(log_lvl);
89e36df28fSDave Young }
90b58d9774SAlex Thorlton 
__dump_stack(const char * log_lvl)914469c0f1SAlexander Potapenko static void __dump_stack(const char *log_lvl)
92b58d9774SAlex Thorlton {
934469c0f1SAlexander Potapenko 	dump_stack_print_info(log_lvl);
944469c0f1SAlexander Potapenko 	show_stack(NULL, NULL, log_lvl);
95b58d9774SAlex Thorlton }
961da177e4SLinus Torvalds 
97196779b9STejun Heo /**
9883a29bebSRandy Dunlap  * dump_stack_lvl - dump the current task information and its stack trace
9983a29bebSRandy Dunlap  * @log_lvl: log level
100196779b9STejun Heo  *
101196779b9STejun Heo  * Architectures can override this implementation by implementing its own.
102196779b9STejun Heo  */
dump_stack_lvl(const char * log_lvl)1034469c0f1SAlexander Potapenko asmlinkage __visible void dump_stack_lvl(const char *log_lvl)
1041da177e4SLinus Torvalds {
1057412dc6dSJohn Ogness 	bool in_panic = this_cpu_in_panic();
106d7ce3692SEric Dumazet 	unsigned long flags;
107b58d9774SAlex Thorlton 
108b58d9774SAlex Thorlton 	/*
109b58d9774SAlex Thorlton 	 * Permit this cpu to perform nested stack dumps while serialising
1107412dc6dSJohn Ogness 	 * against other CPUs, unless this CPU is in panic.
1117412dc6dSJohn Ogness 	 *
1127412dc6dSJohn Ogness 	 * When in panic, non-panic CPUs are not permitted to store new
1137412dc6dSJohn Ogness 	 * printk messages so there is no need to synchronize the output.
1147412dc6dSJohn Ogness 	 * This avoids potential deadlock in panic() if another CPU is
1157412dc6dSJohn Ogness 	 * holding and unable to release the printk_cpu_sync.
116b58d9774SAlex Thorlton 	 */
1177412dc6dSJohn Ogness 	if (!in_panic)
118faebd693SJohn Ogness 		printk_cpu_sync_get_irqsave(flags);
1197412dc6dSJohn Ogness 
1204469c0f1SAlexander Potapenko 	__dump_stack(log_lvl);
1217412dc6dSJohn Ogness 
1227412dc6dSJohn Ogness 	if (!in_panic)
123faebd693SJohn Ogness 		printk_cpu_sync_put_irqrestore(flags);
124b58d9774SAlex Thorlton }
1254469c0f1SAlexander Potapenko EXPORT_SYMBOL(dump_stack_lvl);
1264469c0f1SAlexander Potapenko 
dump_stack(void)1274469c0f1SAlexander Potapenko asmlinkage __visible void dump_stack(void)
1284469c0f1SAlexander Potapenko {
1294469c0f1SAlexander Potapenko 	dump_stack_lvl(KERN_DEFAULT);
1304469c0f1SAlexander Potapenko }
1311da177e4SLinus Torvalds EXPORT_SYMBOL(dump_stack);
132