diff options
author | Tejun Heo <tj@kernel.org> | 2013-04-30 18:27:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 20:04:02 -0400 |
commit | 196779b9b4ce1922afabdc20d0270720603bd46c (patch) | |
tree | 9628ad58fef85b4cc060f434e01fe50a8e0e333c | |
parent | 89e3f23da9c827bfa9806c3d4da83a12c1c8543a (diff) |
dump_stack: consolidate dump_stack() implementations and unify their behaviors
Both dump_stack() and show_stack() are currently implemented by each
architecture. show_stack(NULL, NULL) dumps the backtrace for the
current task as does dump_stack(). On some archs, dump_stack() prints
extra information - pid, utsname and so on - in addition to the
backtrace while the two are identical on other archs.
The usages in arch-independent code of the two functions indicate
show_stack(NULL, NULL) should print out bare backtrace while
dump_stack() is used for debugging purposes when something went wrong,
so it does make sense to print additional information on the task which
triggered dump_stack().
There's no reason to require archs to implement two separate but mostly
identical functions. It leads to unnecessary subtle information.
This patch expands the dummy fallback dump_stack() implementation in
lib/dump_stack.c such that it prints out debug information (taken from
x86) and invokes show_stack(NULL, NULL) and drops arch-specific
dump_stack() implementations in all archs except blackfin. Blackfin's
dump_stack() does something wonky that I don't understand.
Debug information can be printed separately by calling
dump_stack_print_info() so that arch-specific dump_stack()
implementation can still emit the same debug information. This is used
in blackfin.
This patch brings the following behavior changes.
* On some archs, an extra level in backtrace for show_stack() could be
printed. This is because the top frame was determined in
dump_stack() on those archs while generic dump_stack() can't do that
reliably. It can be compensated by inlining dump_stack() but not
sure whether that'd be necessary.
* Most archs didn't use to print debug info on dump_stack(). They do
now.
An example WARN dump follows.
WARNING: at kernel/workqueue.c:4841 init_workqueues+0x35/0x505()
Hardware name: empty
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.9.0-rc1-work+ #9
0000000000000009 ffff88007c861e08 ffffffff81c614dc ffff88007c861e48
ffffffff8108f50f ffffffff82228240 0000000000000040 ffffffff8234a03c
0000000000000000 0000000000000000 0000000000000000 ffff88007c861e58
Call Trace:
[<ffffffff81c614dc>] dump_stack+0x19/0x1b
[<ffffffff8108f50f>] warn_slowpath_common+0x7f/0xc0
[<ffffffff8108f56a>] warn_slowpath_null+0x1a/0x20
[<ffffffff8234a071>] init_workqueues+0x35/0x505
...
v2: CPU number added to the generic debug info as requested by s390
folks and dropped the s390 specific dump_stack(). This loses %ksp
from the debug message which the maintainers think isn't important
enough to keep the s390-specific dump_stack() implementation.
dump_stack_print_info() is moved to kernel/printk.c from
lib/dump_stack.c. Because linkage is per objecct file,
dump_stack_print_info() living in the same lib file as generic
dump_stack() means that archs which implement custom dump_stack()
- at this point, only blackfin - can't use dump_stack_print_info()
as that will bring in the generic version of dump_stack() too. v1
The v1 patch broke build on blackfin due to this issue. The build
breakage was reported by Fengguang Wu.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: David S. Miller <davem@davemloft.net>
Acked-by: Vineet Gupta <vgupta@synopsys.com>
Acked-by: Jesper Nilsson <jesper.nilsson@axis.com>
Acked-by: Vineet Gupta <vgupta@synopsys.com>
Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com> [s390 bits]
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Sam Ravnborg <sam@ravnborg.org>
Acked-by: Richard Kuo <rkuo@codeaurora.org> [hexagon bits]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
33 files changed, 32 insertions, 262 deletions
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 4037461a6493..affccb959a9e 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c | |||
@@ -169,13 +169,6 @@ void show_stack(struct task_struct *task, unsigned long *sp) | |||
169 | dik_show_trace(sp); | 169 | dik_show_trace(sp); |
170 | } | 170 | } |
171 | 171 | ||
172 | void dump_stack(void) | ||
173 | { | ||
174 | show_stack(NULL, NULL); | ||
175 | } | ||
176 | |||
177 | EXPORT_SYMBOL(dump_stack); | ||
178 | |||
179 | void | 172 | void |
180 | die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15) | 173 | die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15) |
181 | { | 174 | { |
diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c index a63ff842564b..ca0207b9d5b6 100644 --- a/arch/arc/kernel/stacktrace.c +++ b/arch/arc/kernel/stacktrace.c | |||
@@ -220,13 +220,6 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) | |||
220 | show_stacktrace(tsk, NULL); | 220 | show_stacktrace(tsk, NULL); |
221 | } | 221 | } |
222 | 222 | ||
223 | /* Expected by Rest of kernel code */ | ||
224 | void dump_stack(void) | ||
225 | { | ||
226 | show_stacktrace(NULL, NULL); | ||
227 | } | ||
228 | EXPORT_SYMBOL(dump_stack); | ||
229 | |||
230 | /* Another API expected by schedular, shows up in "ps" as Wait Channel | 223 | /* Another API expected by schedular, shows up in "ps" as Wait Channel |
231 | * Ofcourse just returning schedule( ) would be pointless so unwind until | 224 | * Ofcourse just returning schedule( ) would be pointless so unwind until |
232 | * the function is not in schedular code | 225 | * the function is not in schedular code |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 1c089119b2d7..18b32e8e4497 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -204,13 +204,6 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) | |||
204 | } | 204 | } |
205 | #endif | 205 | #endif |
206 | 206 | ||
207 | void dump_stack(void) | ||
208 | { | ||
209 | dump_backtrace(NULL, NULL); | ||
210 | } | ||
211 | |||
212 | EXPORT_SYMBOL(dump_stack); | ||
213 | |||
214 | void show_stack(struct task_struct *tsk, unsigned long *sp) | 207 | void show_stack(struct task_struct *tsk, unsigned long *sp) |
215 | { | 208 | { |
216 | dump_backtrace(NULL, tsk); | 209 | dump_backtrace(NULL, tsk); |
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index b3c5f628bdb4..61d7dd29f756 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c | |||
@@ -167,13 +167,6 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) | |||
167 | } | 167 | } |
168 | } | 168 | } |
169 | 169 | ||
170 | void dump_stack(void) | ||
171 | { | ||
172 | dump_backtrace(NULL, NULL); | ||
173 | } | ||
174 | |||
175 | EXPORT_SYMBOL(dump_stack); | ||
176 | |||
177 | void show_stack(struct task_struct *tsk, unsigned long *sp) | 170 | void show_stack(struct task_struct *tsk, unsigned long *sp) |
178 | { | 171 | { |
179 | dump_backtrace(NULL, tsk); | 172 | dump_backtrace(NULL, tsk); |
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 073c3c2fa521..89a8017e8ca6 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c | |||
@@ -204,14 +204,6 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) | |||
204 | show_stack_log_lvl(tsk, (unsigned long)stack, NULL, ""); | 204 | show_stack_log_lvl(tsk, (unsigned long)stack, NULL, ""); |
205 | } | 205 | } |
206 | 206 | ||
207 | void dump_stack(void) | ||
208 | { | ||
209 | unsigned long stack; | ||
210 | |||
211 | show_trace_log_lvl(current, &stack, NULL, ""); | ||
212 | } | ||
213 | EXPORT_SYMBOL(dump_stack); | ||
214 | |||
215 | static const char *cpu_modes[] = { | 207 | static const char *cpu_modes[] = { |
216 | "Application", "Supervisor", "Interrupt level 0", "Interrupt level 1", | 208 | "Application", "Supervisor", "Interrupt level 0", "Interrupt level 1", |
217 | "Interrupt level 2", "Interrupt level 3", "Exception", "NMI" | 209 | "Interrupt level 2", "Interrupt level 3", "Exception", "NMI" |
diff --git a/arch/blackfin/kernel/dumpstack.c b/arch/blackfin/kernel/dumpstack.c index 5cfbaa298211..95ba6d9e9a3d 100644 --- a/arch/blackfin/kernel/dumpstack.c +++ b/arch/blackfin/kernel/dumpstack.c | |||
@@ -168,6 +168,7 @@ void dump_stack(void) | |||
168 | #endif | 168 | #endif |
169 | trace_buffer_save(tflags); | 169 | trace_buffer_save(tflags); |
170 | dump_bfin_trace_buffer(); | 170 | dump_bfin_trace_buffer(); |
171 | dump_stack_print_info(KERN_DEFAULT); | ||
171 | show_stack(current, &stack); | 172 | show_stack(current, &stack); |
172 | trace_buffer_restore(tflags); | 173 | trace_buffer_restore(tflags); |
173 | } | 174 | } |
diff --git a/arch/c6x/kernel/traps.c b/arch/c6x/kernel/traps.c index 1be74e5b4788..d0b96ef25c17 100644 --- a/arch/c6x/kernel/traps.c +++ b/arch/c6x/kernel/traps.c | |||
@@ -67,15 +67,6 @@ void show_regs(struct pt_regs *regs) | |||
67 | pr_err("A31: %08lx B31: %08lx\n", regs->a31, regs->b31); | 67 | pr_err("A31: %08lx B31: %08lx\n", regs->a31, regs->b31); |
68 | } | 68 | } |
69 | 69 | ||
70 | void dump_stack(void) | ||
71 | { | ||
72 | unsigned long stack; | ||
73 | |||
74 | show_stack(current, &stack); | ||
75 | } | ||
76 | EXPORT_SYMBOL(dump_stack); | ||
77 | |||
78 | |||
79 | void die(char *str, struct pt_regs *fp, int nr) | 70 | void die(char *str, struct pt_regs *fp, int nr) |
80 | { | 71 | { |
81 | console_verbose(); | 72 | console_verbose(); |
diff --git a/arch/cris/kernel/traps.c b/arch/cris/kernel/traps.c index a11ad3229f8c..0ffda73734f5 100644 --- a/arch/cris/kernel/traps.c +++ b/arch/cris/kernel/traps.c | |||
@@ -147,13 +147,6 @@ show_stack(void) | |||
147 | #endif | 147 | #endif |
148 | 148 | ||
149 | void | 149 | void |
150 | dump_stack(void) | ||
151 | { | ||
152 | show_stack(NULL, NULL); | ||
153 | } | ||
154 | EXPORT_SYMBOL(dump_stack); | ||
155 | |||
156 | void | ||
157 | set_nmi_handler(void (*handler)(struct pt_regs *)) | 150 | set_nmi_handler(void (*handler)(struct pt_regs *)) |
158 | { | 151 | { |
159 | nmi_handler = handler; | 152 | nmi_handler = handler; |
diff --git a/arch/frv/kernel/traps.c b/arch/frv/kernel/traps.c index 5cfd1420b091..cfcd802d6f9c 100644 --- a/arch/frv/kernel/traps.c +++ b/arch/frv/kernel/traps.c | |||
@@ -466,17 +466,6 @@ asmlinkage void compound_exception(unsigned long esfr1, | |||
466 | BUG(); | 466 | BUG(); |
467 | } /* end compound_exception() */ | 467 | } /* end compound_exception() */ |
468 | 468 | ||
469 | /*****************************************************************************/ | ||
470 | /* | ||
471 | * The architecture-independent backtrace generator | ||
472 | */ | ||
473 | void dump_stack(void) | ||
474 | { | ||
475 | show_stack(NULL, NULL); | ||
476 | } | ||
477 | |||
478 | EXPORT_SYMBOL(dump_stack); | ||
479 | |||
480 | void show_stack(struct task_struct *task, unsigned long *sp) | 469 | void show_stack(struct task_struct *task, unsigned long *sp) |
481 | { | 470 | { |
482 | } | 471 | } |
diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c index 7833aa3e7c7d..cfe494dbe3da 100644 --- a/arch/h8300/kernel/traps.c +++ b/arch/h8300/kernel/traps.c | |||
@@ -164,10 +164,3 @@ void show_trace_task(struct task_struct *tsk) | |||
164 | { | 164 | { |
165 | show_stack(tsk,(unsigned long *)tsk->thread.esp0); | 165 | show_stack(tsk,(unsigned long *)tsk->thread.esp0); |
166 | } | 166 | } |
167 | |||
168 | void dump_stack(void) | ||
169 | { | ||
170 | show_stack(NULL,NULL); | ||
171 | } | ||
172 | |||
173 | EXPORT_SYMBOL(dump_stack); | ||
diff --git a/arch/hexagon/kernel/traps.c b/arch/hexagon/kernel/traps.c index be5e2dd9c9d3..cc2171b2aa04 100644 --- a/arch/hexagon/kernel/traps.c +++ b/arch/hexagon/kernel/traps.c | |||
@@ -191,14 +191,6 @@ void show_stack(struct task_struct *task, unsigned long *fp) | |||
191 | do_show_stack(task, fp, 0); | 191 | do_show_stack(task, fp, 0); |
192 | } | 192 | } |
193 | 193 | ||
194 | void dump_stack(void) | ||
195 | { | ||
196 | unsigned long *fp; | ||
197 | asm("%0 = r30" : "=r" (fp)); | ||
198 | show_stack(current, fp); | ||
199 | } | ||
200 | EXPORT_SYMBOL(dump_stack); | ||
201 | |||
202 | int die(const char *str, struct pt_regs *regs, long err) | 194 | int die(const char *str, struct pt_regs *regs, long err) |
203 | { | 195 | { |
204 | static struct { | 196 | static struct { |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index a26fc640e4ce..182bd64cc726 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -96,14 +96,6 @@ show_stack (struct task_struct *task, unsigned long *sp) | |||
96 | } | 96 | } |
97 | 97 | ||
98 | void | 98 | void |
99 | dump_stack (void) | ||
100 | { | ||
101 | show_stack(NULL, NULL); | ||
102 | } | ||
103 | |||
104 | EXPORT_SYMBOL(dump_stack); | ||
105 | |||
106 | void | ||
107 | show_regs (struct pt_regs *regs) | 99 | show_regs (struct pt_regs *regs) |
108 | { | 100 | { |
109 | unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri; | 101 | unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri; |
diff --git a/arch/m32r/kernel/traps.c b/arch/m32r/kernel/traps.c index 9fe3467a5133..a7a424f852e4 100644 --- a/arch/m32r/kernel/traps.c +++ b/arch/m32r/kernel/traps.c | |||
@@ -167,15 +167,6 @@ void show_stack(struct task_struct *task, unsigned long *sp) | |||
167 | show_trace(task, sp); | 167 | show_trace(task, sp); |
168 | } | 168 | } |
169 | 169 | ||
170 | void dump_stack(void) | ||
171 | { | ||
172 | unsigned long stack; | ||
173 | |||
174 | show_trace(current, &stack); | ||
175 | } | ||
176 | |||
177 | EXPORT_SYMBOL(dump_stack); | ||
178 | |||
179 | static void show_registers(struct pt_regs *regs) | 170 | static void show_registers(struct pt_regs *regs) |
180 | { | 171 | { |
181 | int i = 0; | 172 | int i = 0; |
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index f32ab22e7ed3..88fcd8c70e7b 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c | |||
@@ -992,18 +992,6 @@ void show_stack(struct task_struct *task, unsigned long *stack) | |||
992 | } | 992 | } |
993 | 993 | ||
994 | /* | 994 | /* |
995 | * The architecture-independent backtrace generator | ||
996 | */ | ||
997 | void dump_stack(void) | ||
998 | { | ||
999 | unsigned long stack; | ||
1000 | |||
1001 | show_trace(&stack); | ||
1002 | } | ||
1003 | |||
1004 | EXPORT_SYMBOL(dump_stack); | ||
1005 | |||
1006 | /* | ||
1007 | * The vector number returned in the frame pointer may also contain | 995 | * The vector number returned in the frame pointer may also contain |
1008 | * the "fs" (Fault Status) bits on ColdFire. These are in the bottom | 996 | * the "fs" (Fault Status) bits on ColdFire. These are in the bottom |
1009 | * 2 bits, and upper 2 bits. So we need to mask out the real vector | 997 | * 2 bits, and upper 2 bits. So we need to mask out the real vector |
diff --git a/arch/metag/kernel/traps.c b/arch/metag/kernel/traps.c index 8961f247b500..2ceeaae5b199 100644 --- a/arch/metag/kernel/traps.c +++ b/arch/metag/kernel/traps.c | |||
@@ -987,9 +987,3 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) | |||
987 | 987 | ||
988 | show_trace(tsk, sp, NULL); | 988 | show_trace(tsk, sp, NULL); |
989 | } | 989 | } |
990 | |||
991 | void dump_stack(void) | ||
992 | { | ||
993 | show_stack(NULL, NULL); | ||
994 | } | ||
995 | EXPORT_SYMBOL(dump_stack); | ||
diff --git a/arch/microblaze/kernel/traps.c b/arch/microblaze/kernel/traps.c index 30e6b5004a6a..cb619533a192 100644 --- a/arch/microblaze/kernel/traps.c +++ b/arch/microblaze/kernel/traps.c | |||
@@ -75,9 +75,3 @@ void show_stack(struct task_struct *task, unsigned long *sp) | |||
75 | 75 | ||
76 | debug_show_held_locks(task); | 76 | debug_show_held_locks(task); |
77 | } | 77 | } |
78 | |||
79 | void dump_stack(void) | ||
80 | { | ||
81 | show_stack(NULL, NULL); | ||
82 | } | ||
83 | EXPORT_SYMBOL(dump_stack); | ||
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index c3abb88170fc..b512b28cf786 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -206,19 +206,6 @@ void show_stack(struct task_struct *task, unsigned long *sp) | |||
206 | show_stacktrace(task, ®s); | 206 | show_stacktrace(task, ®s); |
207 | } | 207 | } |
208 | 208 | ||
209 | /* | ||
210 | * The architecture-independent dump_stack generator | ||
211 | */ | ||
212 | void dump_stack(void) | ||
213 | { | ||
214 | struct pt_regs regs; | ||
215 | |||
216 | prepare_frametrace(®s); | ||
217 | show_backtrace(current, ®s); | ||
218 | } | ||
219 | |||
220 | EXPORT_SYMBOL(dump_stack); | ||
221 | |||
222 | static void show_code(unsigned int __user *pc) | 209 | static void show_code(unsigned int __user *pc) |
223 | { | 210 | { |
224 | long i; | 211 | long i; |
diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c index b900e5afa0ae..a7a987c7954f 100644 --- a/arch/mn10300/kernel/traps.c +++ b/arch/mn10300/kernel/traps.c | |||
@@ -294,17 +294,6 @@ void show_stack(struct task_struct *task, unsigned long *sp) | |||
294 | } | 294 | } |
295 | 295 | ||
296 | /* | 296 | /* |
297 | * the architecture-independent dump_stack generator | ||
298 | */ | ||
299 | void dump_stack(void) | ||
300 | { | ||
301 | unsigned long stack; | ||
302 | |||
303 | show_stack(current, &stack); | ||
304 | } | ||
305 | EXPORT_SYMBOL(dump_stack); | ||
306 | |||
307 | /* | ||
308 | * dump the register file in the specified exception frame | 297 | * dump the register file in the specified exception frame |
309 | */ | 298 | */ |
310 | void show_registers_only(struct pt_regs *regs) | 299 | void show_registers_only(struct pt_regs *regs) |
diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c index 5cce396016d0..3d3f6062f49c 100644 --- a/arch/openrisc/kernel/traps.c +++ b/arch/openrisc/kernel/traps.c | |||
@@ -105,17 +105,6 @@ void show_trace_task(struct task_struct *tsk) | |||
105 | */ | 105 | */ |
106 | } | 106 | } |
107 | 107 | ||
108 | /* | ||
109 | * The architecture-independent backtrace generator | ||
110 | */ | ||
111 | void dump_stack(void) | ||
112 | { | ||
113 | unsigned long stack; | ||
114 | |||
115 | show_stack(current, &stack); | ||
116 | } | ||
117 | EXPORT_SYMBOL(dump_stack); | ||
118 | |||
119 | void show_registers(struct pt_regs *regs) | 108 | void show_registers(struct pt_regs *regs) |
120 | { | 109 | { |
121 | int i; | 110 | int i; |
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index aeb8f8f2c07a..e64cf5f09b62 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c | |||
@@ -158,14 +158,6 @@ void show_regs(struct pt_regs *regs) | |||
158 | } | 158 | } |
159 | } | 159 | } |
160 | 160 | ||
161 | |||
162 | void dump_stack(void) | ||
163 | { | ||
164 | show_stack(NULL, NULL); | ||
165 | } | ||
166 | |||
167 | EXPORT_SYMBOL(dump_stack); | ||
168 | |||
169 | static void do_show_stack(struct unwind_frame_info *info) | 161 | static void do_show_stack(struct unwind_frame_info *info) |
170 | { | 162 | { |
171 | int i = 1; | 163 | int i = 1; |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 16e77a81ab4f..624d44bb44dc 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -1362,12 +1362,6 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) | |||
1362 | } while (count++ < kstack_depth_to_print); | 1362 | } while (count++ < kstack_depth_to_print); |
1363 | } | 1363 | } |
1364 | 1364 | ||
1365 | void dump_stack(void) | ||
1366 | { | ||
1367 | show_stack(current, NULL); | ||
1368 | } | ||
1369 | EXPORT_SYMBOL(dump_stack); | ||
1370 | |||
1371 | #ifdef CONFIG_PPC64 | 1365 | #ifdef CONFIG_PPC64 |
1372 | /* Called with hard IRQs off */ | 1366 | /* Called with hard IRQs off */ |
1373 | void __ppc64_runlatch_on(void) | 1367 | void __ppc64_runlatch_on(void) |
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c index 03dce39d01ee..2f1f639d1a3d 100644 --- a/arch/s390/kernel/dumpstack.c +++ b/arch/s390/kernel/dumpstack.c | |||
@@ -129,23 +129,6 @@ static void show_last_breaking_event(struct pt_regs *regs) | |||
129 | #endif | 129 | #endif |
130 | } | 130 | } |
131 | 131 | ||
132 | /* | ||
133 | * The architecture-independent dump_stack generator | ||
134 | */ | ||
135 | void dump_stack(void) | ||
136 | { | ||
137 | printk("CPU: %d %s %s %.*s\n", | ||
138 | task_thread_info(current)->cpu, print_tainted(), | ||
139 | init_utsname()->release, | ||
140 | (int)strcspn(init_utsname()->version, " "), | ||
141 | init_utsname()->version); | ||
142 | printk("Process %s (pid: %d, task: %p, ksp: %p)\n", | ||
143 | current->comm, current->pid, current, | ||
144 | (void *) current->thread.ksp); | ||
145 | show_stack(NULL, NULL); | ||
146 | } | ||
147 | EXPORT_SYMBOL(dump_stack); | ||
148 | |||
149 | static inline int mask_bits(struct pt_regs *regs, unsigned long bits) | 132 | static inline int mask_bits(struct pt_regs *regs, unsigned long bits) |
150 | { | 133 | { |
151 | return (regs->psw.mask & bits) / ((~bits + 1) & bits); | 134 | return (regs->psw.mask & bits) / ((~bits + 1) & bits); |
diff --git a/arch/score/kernel/traps.c b/arch/score/kernel/traps.c index 0e46fb19a848..a38f435fba7b 100644 --- a/arch/score/kernel/traps.c +++ b/arch/score/kernel/traps.c | |||
@@ -149,16 +149,6 @@ static void show_registers(struct pt_regs *regs) | |||
149 | printk(KERN_NOTICE "\n"); | 149 | printk(KERN_NOTICE "\n"); |
150 | } | 150 | } |
151 | 151 | ||
152 | /* | ||
153 | * The architecture-independent dump_stack generator | ||
154 | */ | ||
155 | void dump_stack(void) | ||
156 | { | ||
157 | show_stack(current_thread_info()->task, | ||
158 | (long *) get_irq_regs()->regs[0]); | ||
159 | } | ||
160 | EXPORT_SYMBOL(dump_stack); | ||
161 | |||
162 | void __die(const char *str, struct pt_regs *regs, const char *file, | 152 | void __die(const char *str, struct pt_regs *regs, const char *file, |
163 | const char *func, unsigned long line) | 153 | const char *func, unsigned long line) |
164 | { | 154 | { |
diff --git a/arch/sh/kernel/dumpstack.c b/arch/sh/kernel/dumpstack.c index 7617dc4129ac..b959f5592604 100644 --- a/arch/sh/kernel/dumpstack.c +++ b/arch/sh/kernel/dumpstack.c | |||
@@ -158,9 +158,3 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) | |||
158 | (unsigned long)task_stack_page(tsk)); | 158 | (unsigned long)task_stack_page(tsk)); |
159 | show_trace(tsk, sp, NULL); | 159 | show_trace(tsk, sp, NULL); |
160 | } | 160 | } |
161 | |||
162 | void dump_stack(void) | ||
163 | { | ||
164 | show_stack(NULL, NULL); | ||
165 | } | ||
166 | EXPORT_SYMBOL(dump_stack); | ||
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index 2be4214b3905..dccf5f58d70f 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c | |||
@@ -164,13 +164,6 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) | |||
164 | printk("\n"); | 164 | printk("\n"); |
165 | } | 165 | } |
166 | 166 | ||
167 | void dump_stack(void) | ||
168 | { | ||
169 | show_stack(current, NULL); | ||
170 | } | ||
171 | |||
172 | EXPORT_SYMBOL(dump_stack); | ||
173 | |||
174 | /* | 167 | /* |
175 | * Note: sparc64 has a pretty intricated thread_saved_pc, check it out. | 168 | * Note: sparc64 has a pretty intricated thread_saved_pc, check it out. |
176 | */ | 169 | */ |
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index 8d38ca97aa23..b3f833ab90eb 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c | |||
@@ -2350,13 +2350,6 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) | |||
2350 | } while (++count < 16); | 2350 | } while (++count < 16); |
2351 | } | 2351 | } |
2352 | 2352 | ||
2353 | void dump_stack(void) | ||
2354 | { | ||
2355 | show_stack(current, NULL); | ||
2356 | } | ||
2357 | |||
2358 | EXPORT_SYMBOL(dump_stack); | ||
2359 | |||
2360 | static inline struct reg_window *kernel_stack_up(struct reg_window *rw) | 2353 | static inline struct reg_window *kernel_stack_up(struct reg_window *rw) |
2361 | { | 2354 | { |
2362 | unsigned long fp = rw->ins[6]; | 2355 | unsigned long fp = rw->ins[6]; |
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index e562ff80409a..7d101a2a1541 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c | |||
@@ -35,18 +35,6 @@ void show_trace(struct task_struct *task, unsigned long * stack) | |||
35 | } | 35 | } |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | /* | ||
39 | * stack dumps generator - this is used by arch-independent code. | ||
40 | * And this is identical to i386 currently. | ||
41 | */ | ||
42 | void dump_stack(void) | ||
43 | { | ||
44 | unsigned long stack; | ||
45 | |||
46 | show_trace(current, &stack); | ||
47 | } | ||
48 | EXPORT_SYMBOL(dump_stack); | ||
49 | |||
50 | /*Stolen from arch/i386/kernel/traps.c */ | 38 | /*Stolen from arch/i386/kernel/traps.c */ |
51 | static const int kstack_depth_to_print = 24; | 39 | static const int kstack_depth_to_print = 24; |
52 | 40 | ||
diff --git a/arch/unicore32/kernel/traps.c b/arch/unicore32/kernel/traps.c index 0870b68d2ad9..c54e32410ead 100644 --- a/arch/unicore32/kernel/traps.c +++ b/arch/unicore32/kernel/traps.c | |||
@@ -170,12 +170,6 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) | |||
170 | c_backtrace(fp, mode); | 170 | c_backtrace(fp, mode); |
171 | } | 171 | } |
172 | 172 | ||
173 | void dump_stack(void) | ||
174 | { | ||
175 | dump_backtrace(NULL, NULL); | ||
176 | } | ||
177 | EXPORT_SYMBOL(dump_stack); | ||
178 | |||
179 | void show_stack(struct task_struct *tsk, unsigned long *sp) | 173 | void show_stack(struct task_struct *tsk, unsigned long *sp) |
180 | { | 174 | { |
181 | dump_backtrace(NULL, tsk); | 175 | dump_backtrace(NULL, tsk); |
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index dd1a7c391c90..deb6421c9e69 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c | |||
@@ -191,24 +191,6 @@ void show_stack(struct task_struct *task, unsigned long *sp) | |||
191 | show_stack_log_lvl(task, NULL, sp, bp, ""); | 191 | show_stack_log_lvl(task, NULL, sp, bp, ""); |
192 | } | 192 | } |
193 | 193 | ||
194 | /* | ||
195 | * The architecture-independent dump_stack generator | ||
196 | */ | ||
197 | void dump_stack(void) | ||
198 | { | ||
199 | unsigned long bp; | ||
200 | unsigned long stack; | ||
201 | |||
202 | bp = stack_frame(current, NULL); | ||
203 | printk("Pid: %d, comm: %.20s %s %s %.*s\n", | ||
204 | current->pid, current->comm, print_tainted(), | ||
205 | init_utsname()->release, | ||
206 | (int)strcspn(init_utsname()->version, " "), | ||
207 | init_utsname()->version); | ||
208 | show_trace(NULL, NULL, &stack, bp); | ||
209 | } | ||
210 | EXPORT_SYMBOL(dump_stack); | ||
211 | |||
212 | static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED; | 194 | static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED; |
213 | static int die_owner = -1; | 195 | static int die_owner = -1; |
214 | static unsigned int die_nest_count; | 196 | static unsigned int die_nest_count; |
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index 923db5c15278..384b7c7c2f6d 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c | |||
@@ -481,14 +481,6 @@ void show_stack(struct task_struct *task, unsigned long *sp) | |||
481 | show_trace(task, stack); | 481 | show_trace(task, stack); |
482 | } | 482 | } |
483 | 483 | ||
484 | void dump_stack(void) | ||
485 | { | ||
486 | show_stack(current, NULL); | ||
487 | } | ||
488 | |||
489 | EXPORT_SYMBOL(dump_stack); | ||
490 | |||
491 | |||
492 | void show_code(unsigned int *pc) | 484 | void show_code(unsigned int *pc) |
493 | { | 485 | { |
494 | long i; | 486 | long i; |
diff --git a/include/linux/printk.h b/include/linux/printk.h index 4890fe62c011..7ce1f878cf6a 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h | |||
@@ -145,6 +145,7 @@ extern void wake_up_klogd(void); | |||
145 | 145 | ||
146 | void log_buf_kexec_setup(void); | 146 | void log_buf_kexec_setup(void); |
147 | void __init setup_log_buf(int early); | 147 | void __init setup_log_buf(int early); |
148 | void dump_stack_print_info(const char *log_lvl); | ||
148 | #else | 149 | #else |
149 | static inline __printf(1, 0) | 150 | static inline __printf(1, 0) |
150 | int vprintk(const char *s, va_list args) | 151 | int vprintk(const char *s, va_list args) |
@@ -182,6 +183,10 @@ static inline void log_buf_kexec_setup(void) | |||
182 | static inline void setup_log_buf(int early) | 183 | static inline void setup_log_buf(int early) |
183 | { | 184 | { |
184 | } | 185 | } |
186 | |||
187 | static inline void dump_stack_print_info(const char *log_lvl) | ||
188 | { | ||
189 | } | ||
185 | #endif | 190 | #endif |
186 | 191 | ||
187 | extern void dump_stack(void) __cold; | 192 | extern void dump_stack(void) __cold; |
diff --git a/kernel/printk.c b/kernel/printk.c index 376914e2869d..70b4b94a0eca 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/rculist.h> | 43 | #include <linux/rculist.h> |
44 | #include <linux/poll.h> | 44 | #include <linux/poll.h> |
45 | #include <linux/irq_work.h> | 45 | #include <linux/irq_work.h> |
46 | #include <linux/utsname.h> | ||
46 | 47 | ||
47 | #include <asm/uaccess.h> | 48 | #include <asm/uaccess.h> |
48 | 49 | ||
@@ -2849,4 +2850,21 @@ void kmsg_dump_rewind(struct kmsg_dumper *dumper) | |||
2849 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | 2850 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); |
2850 | } | 2851 | } |
2851 | EXPORT_SYMBOL_GPL(kmsg_dump_rewind); | 2852 | EXPORT_SYMBOL_GPL(kmsg_dump_rewind); |
2853 | |||
2854 | /** | ||
2855 | * dump_stack_print_info - print generic debug info for dump_stack() | ||
2856 | * @log_lvl: log level | ||
2857 | * | ||
2858 | * Arch-specific dump_stack() implementations can use this function to | ||
2859 | * print out the same debug information as the generic dump_stack(). | ||
2860 | */ | ||
2861 | void dump_stack_print_info(const char *log_lvl) | ||
2862 | { | ||
2863 | printk("%sCPU: %d PID: %d Comm: %.20s %s %s %.*s\n", | ||
2864 | log_lvl, raw_smp_processor_id(), current->pid, current->comm, | ||
2865 | print_tainted(), init_utsname()->release, | ||
2866 | (int)strcspn(init_utsname()->version, " "), | ||
2867 | init_utsname()->version); | ||
2868 | } | ||
2869 | |||
2852 | #endif | 2870 | #endif |
diff --git a/lib/dump_stack.c b/lib/dump_stack.c index 42f4f55c9458..53bad099ebd6 100644 --- a/lib/dump_stack.c +++ b/lib/dump_stack.c | |||
@@ -5,11 +5,16 @@ | |||
5 | 5 | ||
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
7 | #include <linux/export.h> | 7 | #include <linux/export.h> |
8 | #include <linux/sched.h> | ||
8 | 9 | ||
10 | /** | ||
11 | * dump_stack - dump the current task information and its stack trace | ||
12 | * | ||
13 | * Architectures can override this implementation by implementing its own. | ||
14 | */ | ||
9 | void dump_stack(void) | 15 | void dump_stack(void) |
10 | { | 16 | { |
11 | printk(KERN_NOTICE | 17 | dump_stack_print_info(KERN_DEFAULT); |
12 | "This architecture does not implement dump_stack()\n"); | 18 | show_stack(NULL, NULL); |
13 | } | 19 | } |
14 | |||
15 | EXPORT_SYMBOL(dump_stack); | 20 | EXPORT_SYMBOL(dump_stack); |