]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/i386/kernel/traps.c
Merge branch 'intelfb-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airli...
[linux-2.6-omap-h63xx.git] / arch / i386 / kernel / traps.c
index de5386b01d389bb795626e61e882d40eafd3b29d..dcc14477af1f0a5d16e083252389ba1d74173eac 100644 (file)
@@ -92,22 +92,21 @@ asmlinkage void spurious_interrupt_bug(void);
 asmlinkage void machine_check(void);
 
 static int kstack_depth_to_print = 24;
-struct notifier_block *i386die_chain;
-static DEFINE_SPINLOCK(die_notifier_lock);
+ATOMIC_NOTIFIER_HEAD(i386die_chain);
 
 int register_die_notifier(struct notifier_block *nb)
 {
-       int err = 0;
-       unsigned long flags;
-
        vmalloc_sync_all();
-       spin_lock_irqsave(&die_notifier_lock, flags);
-       err = notifier_chain_register(&i386die_chain, nb);
-       spin_unlock_irqrestore(&die_notifier_lock, flags);
-       return err;
+       return atomic_notifier_chain_register(&i386die_chain, nb);
 }
 EXPORT_SYMBOL(register_die_notifier);
 
+int unregister_die_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_unregister(&i386die_chain, nb);
+}
+EXPORT_SYMBOL(unregister_die_notifier);
+
 static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
 {
        return  p > (void *)tinfo &&
@@ -131,9 +130,8 @@ static inline int print_addr_and_symbol(unsigned long addr, char *log_lvl,
        print_symbol("%s", addr);
 
        printed = (printed + 1) % CONFIG_STACK_BACKTRACE_COLS;
-
        if (printed)
-               printk("  ");
+               printk(" ");
        else
                printk("\n");
 
@@ -151,6 +149,12 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
        while (valid_stack_ptr(tinfo, (void *)ebp)) {
                addr = *(unsigned long *)(ebp + 4);
                printed = print_addr_and_symbol(addr, log_lvl, printed);
+               /*
+                * break out of recursive entries (such as
+                * end_of_stack_stop_unwind_function):
+                */
+               if (ebp == *(unsigned long *)ebp)
+                       break;
                ebp = *(unsigned long *)ebp;
        }
 #else
@@ -213,7 +217,6 @@ static void show_stack_log_lvl(struct task_struct *task, unsigned long *esp,
        }
 
        stack = esp;
-       printk(log_lvl);
        for(i = 0; i < kstack_depth_to_print; i++) {
                if (kstack_end(stack))
                        break;
@@ -271,8 +274,9 @@ void show_registers(struct pt_regs *regs)
                regs->esi, regs->edi, regs->ebp, esp);
        printk(KERN_EMERG "ds: %04x   es: %04x   ss: %04x\n",
                regs->xds & 0xffff, regs->xes & 0xffff, ss);
-       printk(KERN_EMERG "Process %s (pid: %d, threadinfo=%p task=%p)",
-               current->comm, current->pid, current_thread_info(), current);
+       printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
+               TASK_COMM_LEN, current->comm, current->pid,
+               current_thread_info(), current, current->thread_info);
        /*
         * When in-kernel, we also print out the stack and code at the
         * time of the fault..
@@ -366,6 +370,9 @@ void die(const char * str, struct pt_regs * regs, long err)
 
        if (++die.lock_owner_depth < 3) {
                int nl = 0;
+               unsigned long esp;
+               unsigned short ss;
+
                handle_BUG(regs);
                printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
 #ifdef CONFIG_PREEMPT
@@ -386,8 +393,23 @@ void die(const char * str, struct pt_regs * regs, long err)
 #endif
                if (nl)
                        printk("\n");
-       notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
-               show_registers(regs);
+               if (notify_die(DIE_OOPS, str, regs, err,
+                                       current->thread.trap_no, SIGSEGV) !=
+                               NOTIFY_STOP) {
+                       show_registers(regs);
+                       /* Executive summary in case the oops scrolled away */
+                       esp = (unsigned long) (&regs->esp);
+                       savesegment(ss, ss);
+                       if (user_mode(regs)) {
+                               esp = regs->esp;
+                               ss = regs->xss & 0xffff;
+                       }
+                       printk(KERN_EMERG "EIP: [<%08lx>] ", regs->eip);
+                       print_symbol("%s", regs->eip);
+                       printk(" SS:ESP %04x:%08lx\n", ss, esp);
+               }
+               else
+                       regs = NULL;
        } else
                printk(KERN_EMERG "Recursive die() failure, output suppressed\n");
 
@@ -395,6 +417,9 @@ void die(const char * str, struct pt_regs * regs, long err)
        die.lock_owner = -1;
        spin_unlock_irqrestore(&die.lock, flags);
 
+       if (!regs)
+               return;
+
        if (kexec_should_crash(current))
                crash_kexec(regs);
 
@@ -623,7 +648,7 @@ static DEFINE_SPINLOCK(nmi_print_lock);
 
 void die_nmi (struct pt_regs *regs, const char *msg)
 {
-       if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 0, SIGINT) ==
+       if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) ==
            NOTIFY_STOP)
                return;
 
@@ -662,7 +687,7 @@ static void default_do_nmi(struct pt_regs * regs)
                reason = get_nmi_reason();
  
        if (!(reason & 0xc0)) {
-               if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
+               if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
                                                        == NOTIFY_STOP)
                        return;
 #ifdef CONFIG_X86_LOCAL_APIC
@@ -678,7 +703,7 @@ static void default_do_nmi(struct pt_regs * regs)
                unknown_nmi_error(reason, regs);
                return;
        }
-       if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP)
+       if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
                return;
        if (reason & 0x80)
                mem_parity_error(reason, regs);
@@ -1187,6 +1212,6 @@ void __init trap_init(void)
 static int __init kstack_setup(char *s)
 {
        kstack_depth_to_print = simple_strtoul(s, NULL, 0);
-       return 0;
+       return 1;
 }
 __setup("kstack=", kstack_setup);