diff options
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r-- | arch/i386/kernel/traps.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 313ac1f7dc5a..7e9edafffd8a 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -92,7 +92,11 @@ asmlinkage void spurious_interrupt_bug(void); | |||
92 | asmlinkage void machine_check(void); | 92 | asmlinkage void machine_check(void); |
93 | 93 | ||
94 | static int kstack_depth_to_print = 24; | 94 | static int kstack_depth_to_print = 24; |
95 | #ifdef CONFIG_STACK_UNWIND | ||
95 | static int call_trace = 1; | 96 | static int call_trace = 1; |
97 | #else | ||
98 | #define call_trace (-1) | ||
99 | #endif | ||
96 | ATOMIC_NOTIFIER_HEAD(i386die_chain); | 100 | ATOMIC_NOTIFIER_HEAD(i386die_chain); |
97 | 101 | ||
98 | int register_die_notifier(struct notifier_block *nb) | 102 | int register_die_notifier(struct notifier_block *nb) |
@@ -188,10 +192,20 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, | |||
188 | unw_ret = show_trace_unwind(&info, log_lvl); | 192 | unw_ret = show_trace_unwind(&info, log_lvl); |
189 | } | 193 | } |
190 | if (unw_ret > 0) { | 194 | if (unw_ret > 0) { |
191 | if (call_trace > 0) | 195 | if (call_trace == 1 && !arch_unw_user_mode(&info)) { |
196 | print_symbol("DWARF2 unwinder stuck at %s\n", | ||
197 | UNW_PC(&info)); | ||
198 | if (UNW_SP(&info) >= PAGE_OFFSET) { | ||
199 | printk("Leftover inexact backtrace:\n"); | ||
200 | stack = (void *)UNW_SP(&info); | ||
201 | } else | ||
202 | printk("Full inexact backtrace again:\n"); | ||
203 | } else if (call_trace >= 1) | ||
192 | return; | 204 | return; |
193 | printk("%sLegacy call trace:\n", log_lvl); | 205 | else |
194 | } | 206 | printk("Full inexact backtrace again:\n"); |
207 | } else | ||
208 | printk("Inexact backtrace:\n"); | ||
195 | } | 209 | } |
196 | 210 | ||
197 | if (task == current) { | 211 | if (task == current) { |
@@ -442,11 +456,9 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
442 | if (in_interrupt()) | 456 | if (in_interrupt()) |
443 | panic("Fatal exception in interrupt"); | 457 | panic("Fatal exception in interrupt"); |
444 | 458 | ||
445 | if (panic_on_oops) { | 459 | if (panic_on_oops) |
446 | printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); | ||
447 | ssleep(5); | ||
448 | panic("Fatal exception"); | 460 | panic("Fatal exception"); |
449 | } | 461 | |
450 | oops_exit(); | 462 | oops_exit(); |
451 | do_exit(SIGSEGV); | 463 | do_exit(SIGSEGV); |
452 | } | 464 | } |
@@ -1232,14 +1244,18 @@ static int __init kstack_setup(char *s) | |||
1232 | } | 1244 | } |
1233 | __setup("kstack=", kstack_setup); | 1245 | __setup("kstack=", kstack_setup); |
1234 | 1246 | ||
1247 | #ifdef CONFIG_STACK_UNWIND | ||
1235 | static int __init call_trace_setup(char *s) | 1248 | static int __init call_trace_setup(char *s) |
1236 | { | 1249 | { |
1237 | if (strcmp(s, "old") == 0) | 1250 | if (strcmp(s, "old") == 0) |
1238 | call_trace = -1; | 1251 | call_trace = -1; |
1239 | else if (strcmp(s, "both") == 0) | 1252 | else if (strcmp(s, "both") == 0) |
1240 | call_trace = 0; | 1253 | call_trace = 0; |
1241 | else if (strcmp(s, "new") == 0) | 1254 | else if (strcmp(s, "newfallback") == 0) |
1242 | call_trace = 1; | 1255 | call_trace = 1; |
1256 | else if (strcmp(s, "new") == 2) | ||
1257 | call_trace = 2; | ||
1243 | return 1; | 1258 | return 1; |
1244 | } | 1259 | } |
1245 | __setup("call_trace=", call_trace_setup); | 1260 | __setup("call_trace=", call_trace_setup); |
1261 | #endif | ||