Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1da177e4 LT |
2 | /* |
3 | * Provide a default dump_stack() function for architectures | |
4 | * which don't implement their own. | |
5 | */ | |
6 | ||
7 | #include <linux/kernel.h> | |
22f4e66d | 8 | #include <linux/buildid.h> |
8bc3bcc9 | 9 | #include <linux/export.h> |
196779b9 | 10 | #include <linux/sched.h> |
b17b0153 | 11 | #include <linux/sched/debug.h> |
b58d9774 AT |
12 | #include <linux/smp.h> |
13 | #include <linux/atomic.h> | |
e36df28f DY |
14 | #include <linux/kexec.h> |
15 | #include <linux/utsname.h> | |
a8b62fd0 | 16 | #include <linux/stop_machine.h> |
e36df28f DY |
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(dump_stack_arch_desc_str, sizeof(dump_stack_arch_desc_str), | |
36 | fmt, args); | |
37 | va_end(args); | |
38 | } | |
39 | ||
22f4e66d SB |
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 | ||
e36df28f DY |
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 | { | |
d167706f | 57 | printk("%sCPU: %d UID: %u PID: %d Comm: %.20s %s%s %s %.*s %s " BUILD_ID_FMT "\n", |
d2917ff1 SB |
58 | log_lvl, raw_smp_processor_id(), |
59 | __kuid_val(current_real_cred()->euid), | |
60 | current->pid, current->comm, | |
e36df28f DY |
61 | kexec_crash_loaded() ? "Kdump: loaded " : "", |
62 | print_tainted(), | |
63 | init_utsname()->release, | |
64 | (int)strcspn(init_utsname()->version, " "), | |
d167706f | 65 | init_utsname()->version, preempt_model_str(), BUILD_ID_VAL); |
e36df28f | 66 | |
2f183c68 JN |
67 | if (get_taint()) |
68 | printk("%s%s\n", log_lvl, print_tainted_verbose()); | |
69 | ||
e36df28f DY |
70 | if (dump_stack_arch_desc_str[0] != '\0') |
71 | printk("%sHardware name: %s\n", | |
72 | log_lvl, dump_stack_arch_desc_str); | |
73 | ||
74 | print_worker_info(log_lvl, current); | |
a8b62fd0 | 75 | print_stop_info(log_lvl, current); |
1538e339 | 76 | print_scx_info(log_lvl, current); |
e36df28f DY |
77 | } |
78 | ||
79 | /** | |
80 | * show_regs_print_info - print generic debug info for show_regs() | |
81 | * @log_lvl: log level | |
82 | * | |
83 | * show_regs() implementations can use this function to print out generic | |
84 | * debug information. | |
85 | */ | |
86 | void show_regs_print_info(const char *log_lvl) | |
87 | { | |
88 | dump_stack_print_info(log_lvl); | |
89 | } | |
b58d9774 | 90 | |
4469c0f1 | 91 | static void __dump_stack(const char *log_lvl) |
b58d9774 | 92 | { |
4469c0f1 AP |
93 | dump_stack_print_info(log_lvl); |
94 | show_stack(NULL, NULL, log_lvl); | |
b58d9774 | 95 | } |
1da177e4 | 96 | |
196779b9 | 97 | /** |
83a29beb RD |
98 | * dump_stack_lvl - dump the current task information and its stack trace |
99 | * @log_lvl: log level | |
196779b9 TH |
100 | * |
101 | * Architectures can override this implementation by implementing its own. | |
102 | */ | |
4469c0f1 | 103 | asmlinkage __visible void dump_stack_lvl(const char *log_lvl) |
1da177e4 | 104 | { |
7412dc6d | 105 | bool in_panic = this_cpu_in_panic(); |
d7ce3692 | 106 | unsigned long flags; |
b58d9774 AT |
107 | |
108 | /* | |
109 | * Permit this cpu to perform nested stack dumps while serialising | |
7412dc6d JO |
110 | * against other CPUs, unless this CPU is in panic. |
111 | * | |
112 | * When in panic, non-panic CPUs are not permitted to store new | |
113 | * printk messages so there is no need to synchronize the output. | |
114 | * This avoids potential deadlock in panic() if another CPU is | |
115 | * holding and unable to release the printk_cpu_sync. | |
b58d9774 | 116 | */ |
7412dc6d JO |
117 | if (!in_panic) |
118 | printk_cpu_sync_get_irqsave(flags); | |
119 | ||
4469c0f1 | 120 | __dump_stack(log_lvl); |
7412dc6d JO |
121 | |
122 | if (!in_panic) | |
123 | printk_cpu_sync_put_irqrestore(flags); | |
1da177e4 | 124 | } |
4469c0f1 AP |
125 | EXPORT_SYMBOL(dump_stack_lvl); |
126 | ||
127 | asmlinkage __visible void dump_stack(void) | |
128 | { | |
129 | dump_stack_lvl(KERN_DEFAULT); | |
130 | } | |
1da177e4 | 131 | EXPORT_SYMBOL(dump_stack); |