]> err.no Git - linux-2.6/blobdiff - arch/x86/kernel/traps_64.c
Merge git://git.infradead.org/~dedekind/ubi-2.6
[linux-2.6] / arch / x86 / kernel / traps_64.c
index 0bba7924604e1c3d9c5ca7f6ce30b85788f70f1c..adff76ea97c4732de4b7766272c8b6ad26ace478 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/kdebug.h>
 #include <linux/utsname.h>
 
+#include <mach_traps.h>
+
 #if defined(CONFIG_EDAC)
 #include <linux/edac.h>
 #endif
@@ -84,7 +86,7 @@ static inline void conditional_sti(struct pt_regs *regs)
 
 static inline void preempt_conditional_sti(struct pt_regs *regs)
 {
-       preempt_disable();
+       inc_preempt_count();
        if (regs->flags & X86_EFLAGS_IF)
                local_irq_enable();
 }
@@ -95,20 +97,20 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
                local_irq_disable();
        /* Make sure to not schedule here because we could be running
           on an exception stack. */
-       preempt_enable_no_resched();
+       dec_preempt_count();
 }
 
 int kstack_depth_to_print = 12;
 
-#ifdef CONFIG_KALLSYMS
 void printk_address(unsigned long address, int reliable)
 {
+#ifdef CONFIG_KALLSYMS
        unsigned long offset = 0, symsize;
        const char *symname;
        char *modname;
        char *delim = ":";
-       char namebuf[128];
-       char reliab[4] = "";;
+       char namebuf[KSYM_NAME_LEN];
+       char reliab[4] = "";
 
        symname = kallsyms_lookup(address, &symsize, &offset,
                                        &modname, namebuf);
@@ -120,16 +122,13 @@ void printk_address(unsigned long address, int reliable)
                strcpy(reliab, "? ");
 
        if (!modname)
-               modname = delim = "";           
+               modname = delim = "";
        printk(" [<%016lx>] %s%s%s%s%s+0x%lx/0x%lx\n",
                address, reliab, delim, modname, delim, symname, offset, symsize);
-}
 #else
-void printk_address(unsigned long address, int reliable)
-{
        printk(" [<%016lx>]\n", address);
-}
 #endif
+}
 
 static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
                                        unsigned *usedp, char **idp)
@@ -217,7 +216,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
 static inline int valid_stack_ptr(struct thread_info *tinfo,
                        void *p, unsigned int size, void *end)
 {
-       void *t = (void *)tinfo;
+       void *t = tinfo;
        if (end) {
                if (p < end && p >= (end-THREAD_SIZE))
                        return 1;
@@ -582,7 +581,7 @@ int __kprobes __die(const char * str, struct pt_regs * regs, long err)
        add_taint(TAINT_DIE);
        /* Executive summary in case the oops scrolled away */
        printk(KERN_ALERT "RIP ");
-       printk_address(regs->ip, regs->bp);
+       printk_address(regs->ip, 1);
        printk(" RSP <%016lx>\n", regs->sp);
        if (kexec_should_crash(current))
                crash_kexec(regs);
@@ -601,10 +600,16 @@ void die(const char * str, struct pt_regs * regs, long err)
        oops_end(flags, regs, SIGSEGV);
 }
 
-void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
+notrace __kprobes void
+die_nmi(char *str, struct pt_regs *regs, int do_panic)
 {
-       unsigned long flags = oops_begin();
+       unsigned long flags;
+
+       if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) ==
+           NOTIFY_STOP)
+               return;
 
+       flags = oops_begin();
        /*
         * We are in trouble anyway, lets at least try
         * to get a message out.
@@ -642,11 +647,14 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
                tsk->thread.trap_no = trapnr;
 
                if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
-                   printk_ratelimit())
+                   printk_ratelimit()) {
                        printk(KERN_INFO
-                              "%s[%d] trap %s ip:%lx sp:%lx error:%lx\n",
+                              "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
                               tsk->comm, tsk->pid, str,
                               regs->ip, regs->sp, error_code);
+                       print_vma_addr(" in ", regs->ip);
+                       printk("\n");
+               }
 
                if (info)
                        force_sig_info(signr, info, tsk);
@@ -741,11 +749,14 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
                tsk->thread.trap_no = 13;
 
                if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
-                   printk_ratelimit())
+                   printk_ratelimit()) {
                        printk(KERN_INFO
-                      "%s[%d] general protection ip:%lx sp:%lx error:%lx\n",
+                      "%s[%d] general protection ip:%lx sp:%lx error:%lx",
                               tsk->comm, tsk->pid,
                               regs->ip, regs->sp, error_code);
+                       print_vma_addr(" in ", regs->ip);
+                       printk("\n");
+               }
 
                force_sig(SIGSEGV, tsk);
                return;
@@ -762,7 +773,7 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
        die("general protection fault", regs, error_code);
 }
 
-static __kprobes void
+static notrace __kprobes void
 mem_parity_error(unsigned char reason, struct pt_regs * regs)
 {
        printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
@@ -786,7 +797,7 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs)
        outb(reason, 0x61);
 }
 
-static __kprobes void
+static notrace __kprobes void
 io_check_error(unsigned char reason, struct pt_regs * regs)
 {
        printk("NMI: IOCK error (debug interrupt?)\n");
@@ -800,9 +811,11 @@ io_check_error(unsigned char reason, struct pt_regs * regs)
        outb(reason, 0x61);
 }
 
-static __kprobes void
+static notrace __kprobes void
 unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
 {
+       if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
+               return;
        printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
                reason);
        printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
@@ -815,7 +828,7 @@ unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
 
 /* Runs on IST stack. This code must keep interrupts off all the time.
    Nested NMIs are prevented by the CPU. */
-asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)
+asmlinkage notrace  __kprobes void default_do_nmi(struct pt_regs *regs)
 {
        unsigned char reason = 0;
        int cpu;
@@ -1111,11 +1124,24 @@ asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
 asmlinkage void math_state_restore(void)
 {
        struct task_struct *me = current;
-       clts();                 /* Allow maths ops (or we recurse) */
 
-       if (!used_math())
-               init_fpu(me);
-       restore_fpu_checking(&me->thread.i387.fxsave);
+       if (!used_math()) {
+               local_irq_enable();
+               /*
+                * does a slab alloc which can sleep
+                */
+               if (init_fpu(me)) {
+                       /*
+                        * ran out of memory!
+                        */
+                       do_group_exit(SIGKILL);
+                       return;
+               }
+               local_irq_disable();
+       }
+
+       clts();                 /* Allow maths ops (or we recurse) */
+       restore_fpu_checking(&me->thread.xstate->fxsave);
        task_thread_info(me)->status |= TS_USEDFPU;
        me->fpu_counter++;
 }
@@ -1150,6 +1176,10 @@ void __init trap_init(void)
        set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
 #endif
        
+       /*
+        * initialize the per thread extended state:
+        */
+        init_thread_xstate();
        /*
         * Should be a barrier for any external CPU state.
         */