aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r--arch/i386/kernel/traps.c73
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}
103EXPORT_SYMBOL(register_die_notifier); 103EXPORT_SYMBOL(register_die_notifier); /* used modular by kdb */
104 104
105int unregister_die_notifier(struct notifier_block *nb) 105int 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}
109EXPORT_SYMBOL(unregister_die_notifier); 109EXPORT_SYMBOL(unregister_die_notifier); /* used modular by kdb */
110 110
111static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) 111static 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
325static void handle_BUG(struct pt_regs *regs) 336static 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
350no_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);
354bug: 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);