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 {
5722f4e66dSStephen Boyd printk("%sCPU: %d PID: %d Comm: %.20s %s%s %s %.*s" BUILD_ID_FMT "\n",
58e36df28fSDave Young log_lvl, raw_smp_processor_id(), current->pid, current->comm,
59e36df28fSDave Young kexec_crash_loaded() ? "Kdump: loaded " : "",
60e36df28fSDave Young print_tainted(),
61e36df28fSDave Young init_utsname()->release,
62e36df28fSDave Young (int)strcspn(init_utsname()->version, " "),
6322f4e66dSStephen Boyd init_utsname()->version, BUILD_ID_VAL);
64e36df28fSDave Young
65e36df28fSDave Young if (dump_stack_arch_desc_str[0] != '\0')
66e36df28fSDave Young printk("%sHardware name: %s\n",
67e36df28fSDave Young log_lvl, dump_stack_arch_desc_str);
68e36df28fSDave Young
69e36df28fSDave Young print_worker_info(log_lvl, current);
70a8b62fd0SPeter Zijlstra print_stop_info(log_lvl, current);
71e36df28fSDave Young }
72e36df28fSDave Young
73e36df28fSDave Young /**
74e36df28fSDave Young * show_regs_print_info - print generic debug info for show_regs()
75e36df28fSDave Young * @log_lvl: log level
76e36df28fSDave Young *
77e36df28fSDave Young * show_regs() implementations can use this function to print out generic
78e36df28fSDave Young * debug information.
79e36df28fSDave Young */
show_regs_print_info(const char * log_lvl)80e36df28fSDave Young void show_regs_print_info(const char *log_lvl)
81e36df28fSDave Young {
82e36df28fSDave Young dump_stack_print_info(log_lvl);
83e36df28fSDave Young }
84b58d9774SAlex Thorlton
__dump_stack(const char * log_lvl)854469c0f1SAlexander Potapenko static void __dump_stack(const char *log_lvl)
86b58d9774SAlex Thorlton {
874469c0f1SAlexander Potapenko dump_stack_print_info(log_lvl);
884469c0f1SAlexander Potapenko show_stack(NULL, NULL, log_lvl);
89b58d9774SAlex Thorlton }
901da177e4SLinus Torvalds
91196779b9STejun Heo /**
9283a29bebSRandy Dunlap * dump_stack_lvl - dump the current task information and its stack trace
9383a29bebSRandy Dunlap * @log_lvl: log level
94196779b9STejun Heo *
95196779b9STejun Heo * Architectures can override this implementation by implementing its own.
96196779b9STejun Heo */
dump_stack_lvl(const char * log_lvl)974469c0f1SAlexander Potapenko asmlinkage __visible void dump_stack_lvl(const char *log_lvl)
981da177e4SLinus Torvalds {
99d7ce3692SEric Dumazet unsigned long flags;
100b58d9774SAlex Thorlton
101b58d9774SAlex Thorlton /*
102b58d9774SAlex Thorlton * Permit this cpu to perform nested stack dumps while serialising
103b58d9774SAlex Thorlton * against other CPUs
104b58d9774SAlex Thorlton */
105*faebd693SJohn Ogness printk_cpu_sync_get_irqsave(flags);
1064469c0f1SAlexander Potapenko __dump_stack(log_lvl);
107*faebd693SJohn Ogness printk_cpu_sync_put_irqrestore(flags);
108b58d9774SAlex Thorlton }
1094469c0f1SAlexander Potapenko EXPORT_SYMBOL(dump_stack_lvl);
1104469c0f1SAlexander Potapenko
dump_stack(void)1114469c0f1SAlexander Potapenko asmlinkage __visible void dump_stack(void)
1124469c0f1SAlexander Potapenko {
1134469c0f1SAlexander Potapenko dump_stack_lvl(KERN_DEFAULT);
1144469c0f1SAlexander Potapenko }
1151da177e4SLinus Torvalds EXPORT_SYMBOL(dump_stack);
116