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/buildid.h> |
9 | #include <linux/export.h> |
10 | #include <linux/sched.h> |
11 | #include <linux/sched/debug.h> |
12 | #include <linux/smp.h> |
13 | #include <linux/atomic.h> |
14 | #include <linux/kexec.h> |
15 | #include <linux/utsname.h> |
16 | #include <linux/stop_machine.h> |
17 | |
18 | static char dump_stack_arch_desc_str[128]; |
19 | |
20 | /** |
21 | * dump_stack_set_arch_desc - set arch-specific str to show with task dumps |
22 | * @fmt: printf-style format string |
23 | * @...: arguments for the format string |
24 | * |
25 | * The configured string will be printed right after utsname during task |
26 | * dumps. Usually used to add arch-specific system identifiers. If an |
27 | * arch wants to make use of such an ID string, it should initialize this |
28 | * as soon as possible during boot. |
29 | */ |
30 | void __init dump_stack_set_arch_desc(const char *fmt, ...) |
31 | { |
32 | va_list args; |
33 | |
34 | va_start(args, fmt); |
35 | vsnprintf(buf: dump_stack_arch_desc_str, size: sizeof(dump_stack_arch_desc_str), |
36 | fmt, args); |
37 | va_end(args); |
38 | } |
39 | |
40 | #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) |
41 | #define BUILD_ID_FMT " %20phN" |
42 | #define BUILD_ID_VAL vmlinux_build_id |
43 | #else |
44 | #define BUILD_ID_FMT "%s" |
45 | #define BUILD_ID_VAL "" |
46 | #endif |
47 | |
48 | /** |
49 | * dump_stack_print_info - print generic debug info for dump_stack() |
50 | * @log_lvl: log level |
51 | * |
52 | * Arch-specific dump_stack() implementations can use this function to |
53 | * print out the same debug information as the generic dump_stack(). |
54 | */ |
55 | void dump_stack_print_info(const char *log_lvl) |
56 | { |
57 | printk("%sCPU: %d PID: %d Comm: %.20s %s%s %s %.*s" BUILD_ID_FMT "\n" , |
58 | log_lvl, raw_smp_processor_id(), current->pid, current->comm, |
59 | kexec_crash_loaded() ? "Kdump: loaded " : "" , |
60 | print_tainted(), |
61 | init_utsname()->release, |
62 | (int)strcspn(init_utsname()->version, " " ), |
63 | init_utsname()->version, BUILD_ID_VAL); |
64 | |
65 | if (dump_stack_arch_desc_str[0] != '\0') |
66 | printk("%sHardware name: %s\n" , |
67 | log_lvl, dump_stack_arch_desc_str); |
68 | |
69 | print_worker_info(log_lvl, current); |
70 | print_stop_info(log_lvl, current); |
71 | } |
72 | |
73 | /** |
74 | * show_regs_print_info - print generic debug info for show_regs() |
75 | * @log_lvl: log level |
76 | * |
77 | * show_regs() implementations can use this function to print out generic |
78 | * debug information. |
79 | */ |
80 | void show_regs_print_info(const char *log_lvl) |
81 | { |
82 | dump_stack_print_info(log_lvl); |
83 | } |
84 | |
85 | static void __dump_stack(const char *log_lvl) |
86 | { |
87 | dump_stack_print_info(log_lvl); |
88 | show_stack(NULL, NULL, loglvl: log_lvl); |
89 | } |
90 | |
91 | /** |
92 | * dump_stack_lvl - dump the current task information and its stack trace |
93 | * @log_lvl: log level |
94 | * |
95 | * Architectures can override this implementation by implementing its own. |
96 | */ |
97 | asmlinkage __visible void dump_stack_lvl(const char *log_lvl) |
98 | { |
99 | unsigned long flags; |
100 | |
101 | /* |
102 | * Permit this cpu to perform nested stack dumps while serialising |
103 | * against other CPUs |
104 | */ |
105 | printk_cpu_sync_get_irqsave(flags); |
106 | __dump_stack(log_lvl); |
107 | printk_cpu_sync_put_irqrestore(flags); |
108 | } |
109 | EXPORT_SYMBOL(dump_stack_lvl); |
110 | |
111 | asmlinkage __visible void dump_stack(void) |
112 | { |
113 | dump_stack_lvl(KERN_DEFAULT); |
114 | } |
115 | EXPORT_SYMBOL(dump_stack); |
116 | |