Merge branch 'preempt' into release
[sfrench/cifs-2.6.git] / arch / blackfin / kernel / traps.c
index 8eeb457ce5d5fc6cc6541a174be1c6989113328a..56464cb8edf3105e9a105a9e823eb22b3fead290 100644 (file)
@@ -100,7 +100,11 @@ static void decode_address(char *buf, unsigned long address)
        char *modname;
        char *delim = ":";
        char namebuf[128];
+#endif
+
+       buf += sprintf(buf, "<0x%08lx> ", address);
 
+#ifdef CONFIG_KALLSYMS
        /* look up the address and see if we are in kernel space */
        symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
 
@@ -108,23 +112,33 @@ static void decode_address(char *buf, unsigned long address)
                /* yeah! kernel space! */
                if (!modname)
                        modname = delim = "";
-               sprintf(buf, "<0x%p> { %s%s%s%s + 0x%lx }",
-                             (void *)address, delim, modname, delim, symname,
-                             (unsigned long)offset);
+               sprintf(buf, "{ %s%s%s%s + 0x%lx }",
+                       delim, modname, delim, symname,
+                       (unsigned long)offset);
                return;
-
        }
 #endif
 
-       /* Problem in fixed code section? */
        if (address >= FIXED_CODE_START && address < FIXED_CODE_END) {
-               sprintf(buf, "<0x%p> /* Maybe fixed code section */", (void *)address);
+               /* Problem in fixed code section? */
+               strcat(buf, "/* Maybe fixed code section */");
+               return;
+
+       } else if (address < CONFIG_BOOT_LOAD) {
+               /* Problem somewhere before the kernel start address */
+               strcat(buf, "/* Maybe null pointer? */");
+               return;
+
+       } else if (address >= COREMMR_BASE) {
+               strcat(buf, "/* core mmrs */");
+               return;
+
+       } else if (address >= SYSMMR_BASE) {
+               strcat(buf, "/* system mmrs */");
                return;
-       }
 
-       /* Problem somewhere before the kernel start address */
-       if (address < CONFIG_BOOT_LOAD) {
-               sprintf(buf, "<0x%p> /* Maybe null pointer? */", (void *)address);
+       } else if (address >= L1_ROM_START && address < L1_ROM_START + L1_ROM_LENGTH) {
+               strcat(buf, "/* on-chip L1 ROM */");
                return;
        }
 
@@ -172,18 +186,16 @@ static void decode_address(char *buf, unsigned long address)
                                                offset = (address - vma->vm_start) +
                                                         (vma->vm_pgoff << PAGE_SHIFT);
 
-                                       sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
-                                               (void *)address, name, offset);
+                                       sprintf(buf, "[ %s + 0x%lx ]", name, offset);
                                } else
-                                       sprintf(buf, "<0x%p> [ %s vma:0x%lx-0x%lx]",
-                                               (void *)address, name,
-                                               vma->vm_start, vma->vm_end);
+                                       sprintf(buf, "[ %s vma:0x%lx-0x%lx]",
+                                               name, vma->vm_start, vma->vm_end);
 
                                if (!in_atomic)
                                        mmput(mm);
 
-                               if (!strlen(buf))
-                                       sprintf(buf, "<0x%p> [ %s ] dynamic memory", (void *)address, name);
+                               if (buf[0] == '\0')
+                                       sprintf(buf, "[ %s ] dynamic memory", name);
 
                                goto done;
                        }
@@ -193,7 +205,7 @@ static void decode_address(char *buf, unsigned long address)
        }
 
        /* we were unable to find this address anywhere */
-       sprintf(buf, "<0x%p> /* kernel dynamic memory */", (void *)address);
+       sprintf(buf, "/* kernel dynamic memory */");
 
 done:
        write_unlock_irqrestore(&tasklist_lock, flags);
@@ -212,17 +224,17 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
        console_verbose();
        oops_in_progress = 1;
 #ifdef CONFIG_DEBUG_VERBOSE
-       printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
+       printk(KERN_EMERG "Double Fault\n");
 #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
        if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) == VEC_UNCOV) {
-               unsigned int cpu = smp_processor_id();
+               unsigned int cpu = raw_smp_processor_id();
                char buf[150];
-               decode_address(buf, cpu_pda[cpu].retx);
+               decode_address(buf, cpu_pda[cpu].retx_doublefault);
                printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
-                       (unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf);
-               decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
+                       (unsigned int)cpu_pda[cpu].seqstat_doublefault & SEQSTAT_EXCAUSE, buf);
+               decode_address(buf, cpu_pda[cpu].dcplb_doublefault_addr);
                printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %s\n", buf);
-               decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
+               decode_address(buf, cpu_pda[cpu].icplb_doublefault_addr);
                printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %s\n", buf);
 
                decode_address(buf, fp->retx);
@@ -245,13 +257,13 @@ static int kernel_mode_regs(struct pt_regs *regs)
        return regs->ipend & 0xffc0;
 }
 
-asmlinkage void trap_c(struct pt_regs *fp)
+asmlinkage notrace void trap_c(struct pt_regs *fp)
 {
 #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
        int j;
 #endif
 #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
-       unsigned int cpu = smp_processor_id();
+       unsigned int cpu = raw_smp_processor_id();
 #endif
        const char *strerror = NULL;
        int sig = 0;
@@ -267,11 +279,6 @@ asmlinkage void trap_c(struct pt_regs *fp)
         * double faults if the stack has become corrupt
         */
 
-#ifndef CONFIG_KGDB
-       /* IPEND is skipped if KGDB isn't enabled (see entry code) */
-       fp->ipend = bfin_read_IPEND();
-#endif
-
        /* trap_c() will be called for exceptions. During exceptions
         * processing, the pc value should be set with retx value.
         * With this change we can cleanup some code in signal.c- TODO
@@ -404,7 +411,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
        /* 0x23 - Data CPLB protection violation, handled here */
        case VEC_CPLB_VL:
                info.si_code = ILL_CPLB_VI;
-               sig = SIGBUS;
+               sig = SIGSEGV;
                strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE);
                CHK_DEBUGGER_TRAP_MAYBE();
                break;
@@ -570,11 +577,12 @@ asmlinkage void trap_c(struct pt_regs *fp)
        if (kernel_mode_regs(fp) || (current && !current->mm)) {
                console_verbose();
                oops_in_progress = 1;
-               if (strerror)
-                       verbose_printk(strerror);
        }
 
        if (sig != SIGTRAP) {
+               if (strerror)
+                       verbose_printk(strerror);
+
                dump_bfin_process(fp);
                dump_bfin_mem(fp);
                show_regs(fp);
@@ -583,15 +591,14 @@ asmlinkage void trap_c(struct pt_regs *fp)
 #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
                if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M)
                        verbose_printk(KERN_NOTICE "No trace since you do not have "
-                               "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n"
-                               KERN_NOTICE "\n");
+                              "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n\n");
                else
 #endif
                        dump_bfin_trace_buffer();
 
                if (oops_in_progress) {
                        /* Dump the current kernel stack */
-                       verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n");
+                       verbose_printk(KERN_NOTICE "Kernel Stack\n");
                        show_stack(current, NULL);
                        print_modules();
 #ifndef CONFIG_ACCESS_CHECK
@@ -620,7 +627,9 @@ asmlinkage void trap_c(struct pt_regs *fp)
                force_sig_info(sig, &info, current);
        }
 
-       if (ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8))
+       if ((ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8)) ||
+           (ANOMALY_05000281 && trapnr == VEC_HWERR) ||
+           (ANOMALY_05000189 && (trapnr == VEC_CPLB_I_VL || trapnr == VEC_CPLB_VL)))
                fp->pc = SAFE_USER_INSTRUCTION;
 
  traps_done:
@@ -902,11 +911,11 @@ void show_stack(struct task_struct *task, unsigned long *stack)
                frame_no = 0;
 
                for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
-                    addr <= endstack; addr++, i++) {
+                    addr < endstack; addr++, i++) {
 
                        ret_addr = 0;
                        if (!j && i % 8 == 0)
-                               printk("\n" KERN_NOTICE "%p:",addr);
+                               printk(KERN_NOTICE "%p:",addr);
 
                        /* if it is an odd address, or zero, just skip it */
                        if (*addr & 0x1 || !*addr)
@@ -947,6 +956,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
        }
 #endif
 }
+EXPORT_SYMBOL(show_stack);
 
 void dump_stack(void)
 {
@@ -996,9 +1006,9 @@ void dump_bfin_process(struct pt_regs *fp)
 
                printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu);
                if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
-                       verbose_printk(KERN_NOTICE  "TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
-                               KERN_NOTICE " BSS = 0x%p-0x%p  USER-STACK = 0x%p\n"
-                               KERN_NOTICE "\n",
+                       verbose_printk(KERN_NOTICE
+                               "TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
+                               " BSS = 0x%p-0x%p  USER-STACK = 0x%p\n\n",
                                (void *)current->mm->start_code,
                                (void *)current->mm->end_code,
                                (void *)current->mm->start_data,
@@ -1009,8 +1019,8 @@ void dump_bfin_process(struct pt_regs *fp)
                else
                        verbose_printk(KERN_NOTICE "invalid mm\n");
        } else
-               verbose_printk(KERN_NOTICE "\n" KERN_NOTICE
-                    "No Valid process in current context\n");
+               verbose_printk(KERN_NOTICE
+                              "No Valid process in current context\n");
 #endif
 }
 
@@ -1028,7 +1038,7 @@ void dump_bfin_mem(struct pt_regs *fp)
             addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10;
             addr++) {
                if (!((unsigned long)addr & 0xF))
-                       verbose_printk("\n" KERN_NOTICE "0x%p: ", addr);
+                       verbose_printk(KERN_NOTICE "0x%p: ", addr);
 
                if (!get_instruction(&val, addr)) {
                                val = 0;
@@ -1056,9 +1066,9 @@ void dump_bfin_mem(struct pt_regs *fp)
            oops_in_progress)){
                verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n");
 #ifndef CONFIG_DEBUG_HWERR
-               verbose_printk(KERN_NOTICE "The remaining message may be meaningless\n"
-                       KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a"
-                        " better idea where it came from\n");
+               verbose_printk(KERN_NOTICE
+"The remaining message may be meaningless\n"
+"You should enable CONFIG_DEBUG_HWERR to get a better idea where it came from\n");
 #else
                /* If we are handling only one peripheral interrupt
                 * and current mm and pid are valid, and the last error
@@ -1088,7 +1098,7 @@ void show_regs(struct pt_regs *fp)
        struct irqaction *action;
        unsigned int i;
        unsigned long flags = 0;
-       unsigned int cpu = smp_processor_id();
+       unsigned int cpu = raw_smp_processor_id();
        unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
 
        verbose_printk(KERN_NOTICE "\n");
@@ -1114,9 +1124,16 @@ void show_regs(struct pt_regs *fp)
 
        verbose_printk(KERN_NOTICE "%s", linux_banner);
 
-       verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
-       verbose_printk(KERN_NOTICE " SEQSTAT: %08lx  IPEND: %04lx  SYSCFG: %04lx\n",
-               (long)fp->seqstat, fp->ipend, fp->syscfg);
+       verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n", print_tainted());
+       verbose_printk(KERN_NOTICE " SEQSTAT: %08lx  IPEND: %04lx  IMASK: %04lx  SYSCFG: %04lx\n",
+               (long)fp->seqstat, fp->ipend, cpu_pda[raw_smp_processor_id()].ex_imask, fp->syscfg);
+       if (fp->ipend & EVT_IRPTEN)
+               verbose_printk(KERN_NOTICE "  Global Interrupts Disabled (IPEND[4])\n");
+       if (!(cpu_pda[raw_smp_processor_id()].ex_imask & (EVT_IVG13 | EVT_IVG12 | EVT_IVG11 |
+                       EVT_IVG10 | EVT_IVG9 | EVT_IVG8 | EVT_IVG7 | EVT_IVTMR)))
+               verbose_printk(KERN_NOTICE "  Peripheral interrupts masked off\n");
+       if (!(cpu_pda[raw_smp_processor_id()].ex_imask & (EVT_IVG15 | EVT_IVG14)))
+               verbose_printk(KERN_NOTICE "  Kernel interrupts masked off\n");
        if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) {
                verbose_printk(KERN_NOTICE "  HWERRCAUSE: 0x%lx\n",
                        (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
@@ -1184,7 +1201,7 @@ unlock:
                verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
        }
 
-       verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n");
+       verbose_printk(KERN_NOTICE "PROCESSOR STATE:\n");
        verbose_printk(KERN_NOTICE " R0 : %08lx    R1 : %08lx    R2 : %08lx    R3 : %08lx\n",
                fp->r0, fp->r1, fp->r2, fp->r3);
        verbose_printk(KERN_NOTICE " R4 : %08lx    R5 : %08lx    R6 : %08lx    R7 : %08lx\n",