diff options
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r-- | arch/i386/kernel/traps.c | 73 |
1 files changed, 42 insertions, 31 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 2bf8b55b91f8..0d4005dc06c5 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -100,13 +100,13 @@ int register_die_notifier(struct notifier_block *nb) | |||
100 | vmalloc_sync_all(); | 100 | vmalloc_sync_all(); |
101 | return atomic_notifier_chain_register(&i386die_chain, nb); | 101 | return atomic_notifier_chain_register(&i386die_chain, nb); |
102 | } | 102 | } |
103 | EXPORT_SYMBOL(register_die_notifier); | 103 | EXPORT_SYMBOL(register_die_notifier); /* used modular by kdb */ |
104 | 104 | ||
105 | int unregister_die_notifier(struct notifier_block *nb) | 105 | int unregister_die_notifier(struct notifier_block *nb) |
106 | { | 106 | { |
107 | return atomic_notifier_chain_unregister(&i386die_chain, nb); | 107 | return atomic_notifier_chain_unregister(&i386die_chain, nb); |
108 | } | 108 | } |
109 | EXPORT_SYMBOL(unregister_die_notifier); | 109 | EXPORT_SYMBOL(unregister_die_notifier); /* used modular by kdb */ |
110 | 110 | ||
111 | static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) | 111 | static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) |
112 | { | 112 | { |
@@ -187,10 +187,21 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, | |||
187 | if (unwind_init_blocked(&info, task) == 0) | 187 | if (unwind_init_blocked(&info, task) == 0) |
188 | unw_ret = show_trace_unwind(&info, log_lvl); | 188 | unw_ret = show_trace_unwind(&info, log_lvl); |
189 | } | 189 | } |
190 | if (unw_ret > 0) { | 190 | if (unw_ret > 0 && !arch_unw_user_mode(&info)) { |
191 | if (call_trace > 0) | 191 | #ifdef CONFIG_STACK_UNWIND |
192 | print_symbol("DWARF2 unwinder stuck at %s\n", | ||
193 | UNW_PC(&info)); | ||
194 | if (call_trace == 1) { | ||
195 | printk("Leftover inexact backtrace:\n"); | ||
196 | if (UNW_SP(&info)) | ||
197 | stack = (void *)UNW_SP(&info); | ||
198 | } else if (call_trace > 1) | ||
192 | return; | 199 | return; |
193 | printk("%sLegacy call trace:\n", log_lvl); | 200 | else |
201 | printk("Full inexact backtrace again:\n"); | ||
202 | #else | ||
203 | printk("Inexact backtrace:\n"); | ||
204 | #endif | ||
194 | } | 205 | } |
195 | } | 206 | } |
196 | 207 | ||
@@ -324,35 +335,35 @@ void show_registers(struct pt_regs *regs) | |||
324 | 335 | ||
325 | static void handle_BUG(struct pt_regs *regs) | 336 | static void handle_BUG(struct pt_regs *regs) |
326 | { | 337 | { |
338 | unsigned long eip = regs->eip; | ||
327 | unsigned short ud2; | 339 | unsigned short ud2; |
328 | unsigned short line; | ||
329 | char *file; | ||
330 | char c; | ||
331 | unsigned long eip; | ||
332 | |||
333 | eip = regs->eip; | ||
334 | 340 | ||
335 | if (eip < PAGE_OFFSET) | 341 | if (eip < PAGE_OFFSET) |
336 | goto no_bug; | 342 | return; |
337 | if (__get_user(ud2, (unsigned short __user *)eip)) | 343 | if (__get_user(ud2, (unsigned short __user *)eip)) |
338 | goto no_bug; | 344 | return; |
339 | if (ud2 != 0x0b0f) | 345 | if (ud2 != 0x0b0f) |
340 | goto no_bug; | 346 | return; |
341 | if (__get_user(line, (unsigned short __user *)(eip + 2))) | ||
342 | goto bug; | ||
343 | if (__get_user(file, (char * __user *)(eip + 4)) || | ||
344 | (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) | ||
345 | file = "<bad filename>"; | ||
346 | 347 | ||
347 | printk(KERN_EMERG "------------[ cut here ]------------\n"); | 348 | printk(KERN_EMERG "------------[ cut here ]------------\n"); |
348 | printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line); | ||
349 | 349 | ||
350 | no_bug: | 350 | #ifdef CONFIG_DEBUG_BUGVERBOSE |
351 | return; | 351 | do { |
352 | unsigned short line; | ||
353 | char *file; | ||
354 | char c; | ||
355 | |||
356 | if (__get_user(line, (unsigned short __user *)(eip + 2))) | ||
357 | break; | ||
358 | if (__get_user(file, (char * __user *)(eip + 4)) || | ||
359 | (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) | ||
360 | file = "<bad filename>"; | ||
352 | 361 | ||
353 | /* Here we know it was a BUG but file-n-line is unavailable */ | 362 | printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line); |
354 | bug: | 363 | return; |
355 | printk(KERN_EMERG "Kernel BUG\n"); | 364 | } while (0); |
365 | #endif | ||
366 | printk(KERN_EMERG "Kernel BUG at [verbose debug info unavailable]\n"); | ||
356 | } | 367 | } |
357 | 368 | ||
358 | /* This is gone through when something in the kernel | 369 | /* This is gone through when something in the kernel |
@@ -442,11 +453,9 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
442 | if (in_interrupt()) | 453 | if (in_interrupt()) |
443 | panic("Fatal exception in interrupt"); | 454 | panic("Fatal exception in interrupt"); |
444 | 455 | ||
445 | if (panic_on_oops) { | 456 | if (panic_on_oops) |
446 | printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); | 457 | panic("Fatal exception: panic_on_oops"); |
447 | ssleep(5); | 458 | |
448 | panic("Fatal exception"); | ||
449 | } | ||
450 | oops_exit(); | 459 | oops_exit(); |
451 | do_exit(SIGSEGV); | 460 | do_exit(SIGSEGV); |
452 | } | 461 | } |
@@ -1238,8 +1247,10 @@ static int __init call_trace_setup(char *s) | |||
1238 | call_trace = -1; | 1247 | call_trace = -1; |
1239 | else if (strcmp(s, "both") == 0) | 1248 | else if (strcmp(s, "both") == 0) |
1240 | call_trace = 0; | 1249 | call_trace = 0; |
1241 | else if (strcmp(s, "new") == 0) | 1250 | else if (strcmp(s, "newfallback") == 0) |
1242 | call_trace = 1; | 1251 | call_trace = 1; |
1252 | else if (strcmp(s, "new") == 2) | ||
1253 | call_trace = 2; | ||
1243 | return 1; | 1254 | return 1; |
1244 | } | 1255 | } |
1245 | __setup("call_trace=", call_trace_setup); | 1256 | __setup("call_trace=", call_trace_setup); |