diff options
Diffstat (limited to 'arch/blackfin/kernel/traps.c')
-rw-r--r-- | arch/blackfin/kernel/traps.c | 147 |
1 files changed, 86 insertions, 61 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index cfa05436c97..21a55ef19cb 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -158,7 +158,7 @@ static void decode_address(char *buf, unsigned long address) } /* we were unable to find this address anywhere */ - sprintf(buf, "[<0x%p>]", (void *)address); + sprintf(buf, "<0x%p> /* unknown address */", (void *)address); done: write_unlock_irqrestore(&tasklist_lock, flags); @@ -169,7 +169,9 @@ asmlinkage void double_fault_c(struct pt_regs *fp) console_verbose(); oops_in_progress = 1; printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); - dump_bfin_regs(fp, (void *)fp->retx); + dump_bfin_process(fp); + dump_bfin_mem((void *)fp->retx); + show_regs(fp); panic("Double Fault - unrecoverable event\n"); } @@ -250,7 +252,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_EXCPT03: info.si_code = SEGV_STACKFLOW; sig = SIGSEGV; - printk(KERN_NOTICE EXC_0x03); + printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x04 - User Defined, Caught by default */ @@ -279,7 +281,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_OVFLOW: info.si_code = TRAP_TRACEFLOW; sig = SIGTRAP; - printk(KERN_NOTICE EXC_0x11); + printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x12 - Reserved, Caught by default */ @@ -301,36 +303,35 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_UNDEF_I: info.si_code = ILL_ILLOPC; sig = SIGILL; - printk(KERN_NOTICE EXC_0x21); + printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x22 - Illegal Instruction Combination, handled here */ case VEC_ILGAL_I: info.si_code = ILL_ILLPARAOP; sig = SIGILL; - printk(KERN_NOTICE EXC_0x22); + printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; - /* 0x23 - Data CPLB Protection Violation, - normal case is handled in _cplb_hdr */ + /* 0x23 - Data CPLB protection violation, handled here */ case VEC_CPLB_VL: info.si_code = ILL_CPLB_VI; - sig = SIGILL; - printk(KERN_NOTICE EXC_0x23); + sig = SIGBUS; + printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x24 - Data access misaligned, handled here */ case VEC_MISALI_D: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x24); + printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x25 - Unrecoverable Event, handled here */ case VEC_UNCOV: info.si_code = ILL_ILLEXCPT; sig = SIGILL; - printk(KERN_NOTICE EXC_0x25); + printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, @@ -338,7 +339,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_CPLB_M: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x26); + printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ @@ -349,7 +350,7 @@ asmlinkage void trap_c(struct pt_regs *fp) printk(KERN_NOTICE "NULL pointer access (probably)\n"); #else sig = SIGILL; - printk(KERN_NOTICE EXC_0x27); + printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); #endif CHK_DEBUGGER_TRAP(); break; @@ -357,7 +358,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_WATCH: info.si_code = TRAP_WATCHPT; sig = SIGTRAP; - pr_debug(EXC_0x28); + pr_debug(EXC_0x28(KERN_DEBUG)); CHK_DEBUGGER_TRAP_MAYBE(); /* Check if this is a watchpoint in kernel space */ if (fp->ipend & 0xffc0) @@ -379,22 +380,21 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_MISALI_I: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x2A); + printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; - /* 0x2B - Instruction CPLB protection Violation, - handled in _cplb_hdr */ + /* 0x2B - Instruction CPLB protection violation, handled here */ case VEC_CPLB_I_VL: info.si_code = ILL_CPLB_VI; - sig = SIGILL; - printk(KERN_NOTICE EXC_0x2B); + sig = SIGBUS; + printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ case VEC_CPLB_I_M: info.si_code = ILL_CPLB_MISS; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x2C); + printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x2D - Instruction CPLB Multiple Hits, handled here */ @@ -405,7 +405,7 @@ asmlinkage void trap_c(struct pt_regs *fp) printk(KERN_NOTICE "Jump to address 0 - 0x0fff\n"); #else sig = SIGILL; - printk(KERN_NOTICE EXC_0x2D); + printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); #endif CHK_DEBUGGER_TRAP(); break; @@ -413,7 +413,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_ILL_RES: info.si_code = ILL_PRVOPC; sig = SIGILL; - printk(KERN_NOTICE EXC_0x2E); + printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x2F - Reserved, Caught by default */ @@ -446,7 +446,9 @@ asmlinkage void trap_c(struct pt_regs *fp) if (sig != SIGTRAP) { unsigned long stack; - dump_bfin_regs(fp, (void *)fp->retx); + dump_bfin_process(fp); + dump_bfin_mem((void *)fp->retx); + show_regs(fp); /* Print out the trace buffer if it makes sense */ #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE @@ -460,22 +462,25 @@ asmlinkage void trap_c(struct pt_regs *fp) show_stack(current, &stack); if (oops_in_progress) { #ifndef CONFIG_ACCESS_CHECK - printk(KERN_EMERG "Hey - dork - please turn on " - "CONFIG_ACCESS_CHECK\n"); + printk(KERN_EMERG "Please turn on " + "CONFIG_ACCESS_CHECK\n"); #endif panic("Kernel exception"); } - - /* Ensure that bad return addresses don't end up in an infinite - * loop, due to speculative loads/reads - */ - fp->pc = SAFE_USER_INSTRUCTION; } + info.si_signo = sig; info.si_errno = 0; info.si_addr = (void *)fp->pc; force_sig_info(sig, &info, current); + /* Ensure that bad return addresses don't end up in an infinite + * loop, due to speculative loads/reads. This needs to be done after + * the signal has been sent. + */ + if (trapnr == VEC_CPLB_I_M && sig != SIGTRAP) + fp->pc = SAFE_USER_INSTRUCTION; + trace_buffer_restore(j); return; } @@ -600,37 +605,48 @@ void dump_stack(void) show_stack(current, &stack); trace_buffer_restore(tflags); } - EXPORT_SYMBOL(dump_stack); -void dump_bfin_regs(struct pt_regs *fp, void *retaddr) +void dump_bfin_process(struct pt_regs *fp) { - char buf [150]; + /* We should be able to look at fp->ipend, but we don't push it on the + * stack all the time, so do this until we fix that */ + unsigned int context = bfin_read_IPEND(); + + if (oops_in_progress) + printk(KERN_EMERG "Kernel OOPS in progress\n"); + + if (context & 0x0020) + printk(KERN_NOTICE "Deferred excecption or HW Error context\n"); + else if (context & 0x3FC0) + printk(KERN_NOTICE "Interrupt context\n"); + else if (context & 0x4000) + printk(KERN_NOTICE "Deferred Interrupt context\n"); + else if (context & 0x8000) + printk(KERN_NOTICE "Kernel process context\n"); + + if (current->pid && current->mm) { + printk(KERN_NOTICE "CURRENT PROCESS:\n"); + printk(KERN_NOTICE "COMM=%s PID=%d\n", + current->comm, current->pid); + + 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", + (void *)current->mm->start_code, + (void *)current->mm->end_code, + (void *)current->mm->start_data, + (void *)current->mm->end_data, + (void *)current->mm->end_data, + (void *)current->mm->brk, + (void *)current->mm->start_stack); + } else + printk(KERN_NOTICE "\n" KERN_NOTICE + "No Valid process in current context\n"); +} - if (!oops_in_progress) { - if (current->pid && current->mm) { - printk(KERN_NOTICE "\n" KERN_NOTICE "CURRENT PROCESS:\n"); - printk(KERN_NOTICE "COMM=%s PID=%d\n", - current->comm, current->pid); - - 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", - (void *)current->mm->start_code, - (void *)current->mm->end_code, - (void *)current->mm->start_data, - (void *)current->mm->end_data, - (void *)current->mm->end_data, - (void *)current->mm->brk, - (void *)current->mm->start_stack); - } else { - printk (KERN_NOTICE "\n" KERN_NOTICE - "No Valid pid - Either things are really messed up," - " or you are in the kernel\n"); - } - } else { - printk(KERN_NOTICE "Kernel or interrupt exception\n"); - } +void dump_bfin_mem(void *retaddr) +{ if (retaddr >= (void *)FIXED_CODE_START && retaddr < (void *)physical_mem_end #if L1_CODE_LENGTH != 0 @@ -671,8 +687,13 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr) printk("\n"); } else printk("\n" KERN_NOTICE - "Cannot look at the [PC] for it is" - " in unreadable memory - sorry\n"); + "Cannot look at the [PC] <%p> for it is" + " in unreadable memory - sorry\n", retaddr); +} + +void show_regs(struct pt_regs *fp) +{ + char buf [150]; printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\n"); printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", @@ -686,6 +707,8 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr) printk(KERN_NOTICE " RETX: %s\n", buf); decode_address(buf, fp->rets); printk(KERN_NOTICE " RETS: %s\n", buf); + decode_address(buf, fp->pc); + printk(KERN_NOTICE " PC: %s\n", buf); if ((long)fp->seqstat & SEQSTAT_EXCAUSE) { decode_address(buf, bfin_read_DCPLB_FAULT_ADDR()); @@ -800,7 +823,9 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp) printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR()); printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR()); - dump_bfin_regs(fp, (void *)fp->retx); + dump_bfin_process(fp); + dump_bfin_mem((void *)fp->retx); + show_regs(fp); dump_stack(); panic("Unrecoverable event\n"); } |