aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2006-06-26 07:57:47 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-26 13:48:18 -0400
commitc33bd9aac0597eeedaaa01ea5aafe456894b2f2b (patch)
treecdac9bb99eb3943feccc2a21d09a1524a8867cb0 /arch/x86_64
parentfe7cacc1c25e286872b878c5d46880b620cd1e2d (diff)
[PATCH] i386/x86-64: fall back to old-style call trace if no unwinding
If no unwinding is possible at all for a certain exception instance, fall back to the old style call trace instead of not showing any trace at all. Also, allow setting the stack trace mode at the command line. Signed-off-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/kernel/traps.c51
1 files changed, 35 insertions, 16 deletions
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index eb1534ff1f5f..bd0891f4c2c7 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -107,6 +107,7 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
107} 107}
108 108
109static int kstack_depth_to_print = 10; 109static int kstack_depth_to_print = 10;
110static int call_trace = 1;
110 111
111#ifdef CONFIG_KALLSYMS 112#ifdef CONFIG_KALLSYMS
112#include <linux/kallsyms.h> 113#include <linux/kallsyms.h>
@@ -190,11 +191,12 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
190 return NULL; 191 return NULL;
191} 192}
192 193
193static void show_trace_unwind(struct unwind_frame_info *info, void *context) 194static int show_trace_unwind(struct unwind_frame_info *info, void *context)
194{ 195{
195 int i = 11; 196 int i = 11, n = 0;
196 197
197 while (unwind(info) == 0 && UNW_PC(info)) { 198 while (unwind(info) == 0 && UNW_PC(info)) {
199 ++n;
198 if (i > 50) { 200 if (i > 50) {
199 printk("\n "); 201 printk("\n ");
200 i = 7; 202 i = 7;
@@ -205,6 +207,7 @@ static void show_trace_unwind(struct unwind_frame_info *info, void *context)
205 break; 207 break;
206 } 208 }
207 printk("\n"); 209 printk("\n");
210 return n;
208} 211}
209 212
210/* 213/*
@@ -218,27 +221,32 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
218{ 221{
219 const unsigned cpu = safe_smp_processor_id(); 222 const unsigned cpu = safe_smp_processor_id();
220 unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; 223 unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
221 int i; 224 int i = 11;
222 unsigned used = 0; 225 unsigned used = 0;
223 struct unwind_frame_info info;
224 226
225 printk("\nCall Trace:"); 227 printk("\nCall Trace:");
226 228
227 if (!tsk) 229 if (!tsk)
228 tsk = current; 230 tsk = current;
229 231
230 if (regs) { 232 if (call_trace >= 0) {
231 if (unwind_init_frame_info(&info, tsk, regs) == 0) { 233 int unw_ret = 0;
232 show_trace_unwind(&info, NULL); 234 struct unwind_frame_info info;
233 return; 235
236 if (regs) {
237 if (unwind_init_frame_info(&info, tsk, regs) == 0)
238 unw_ret = show_trace_unwind(&info, NULL);
239 } else if (tsk == current)
240 unw_ret = unwind_init_running(&info, show_trace_unwind, NULL);
241 else {
242 if (unwind_init_blocked(&info, tsk) == 0)
243 unw_ret = show_trace_unwind(&info, NULL);
234 } 244 }
235 } else if (tsk == current) { 245 if (unw_ret > 0) {
236 if (unwind_init_running(&info, show_trace_unwind, NULL) == 0) 246 if (call_trace > 0)
237 return; 247 return;
238 } else { 248 printk("Legacy call trace:");
239 if (unwind_init_blocked(&info, tsk) == 0) { 249 i = 18;
240 show_trace_unwind(&info, NULL);
241 return;
242 } 250 }
243 } 251 }
244 252
@@ -264,7 +272,7 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
264 } \ 272 } \
265 } while (0) 273 } while (0)
266 274
267 for(i = 11; ; ) { 275 for(; ; ) {
268 const char *id; 276 const char *id;
269 unsigned long *estack_end; 277 unsigned long *estack_end;
270 estack_end = in_exception_stack(cpu, (unsigned long)stack, 278 estack_end = in_exception_stack(cpu, (unsigned long)stack,
@@ -1052,3 +1060,14 @@ static int __init kstack_setup(char *s)
1052} 1060}
1053__setup("kstack=", kstack_setup); 1061__setup("kstack=", kstack_setup);
1054 1062
1063static int __init call_trace_setup(char *s)
1064{
1065 if (strcmp(s, "old") == 0)
1066 call_trace = -1;
1067 else if (strcmp(s, "both") == 0)
1068 call_trace = 0;
1069 else if (strcmp(s, "new") == 0)
1070 call_trace = 1;
1071 return 1;
1072}
1073__setup("call_trace=", call_trace_setup);