#include <asm/cacheflush.h>
#include <asm/blackfin.h>
#include <asm/irq_handler.h>
+#include <linux/irq.h>
#include <asm/trace.h>
#include <asm/fixed_code.h>
}
/* 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);
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");
}
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 */
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 */
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, handled here */
case VEC_CPLB_VL:
info.si_code = ILL_CPLB_VI;
sig = SIGBUS;
- printk(KERN_NOTICE EXC_0x23);
+ 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,
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 */
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;
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)
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 here */
case VEC_CPLB_I_VL:
info.si_code = ILL_CPLB_VI;
sig = SIGBUS;
- printk(KERN_NOTICE EXC_0x2B);
+ 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 */
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;
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 */
/* 0x3D - Reserved, Caught by default */
/* 0x3E - Reserved, Caught by default */
/* 0x3F - Reserved, Caught by default */
+ case VEC_HWERR:
+ info.si_code = BUS_ADRALN;
+ sig = SIGBUS;
+ switch (fp->seqstat & SEQSTAT_HWERRCAUSE) {
+ /* System MMR Error */
+ case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
+ info.si_code = BUS_ADRALN;
+ sig = SIGBUS;
+ printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
+ break;
+ /* External Memory Addressing Error */
+ case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
+ info.si_code = BUS_ADRERR;
+ sig = SIGBUS;
+ printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
+ break;
+ /* Performance Monitor Overflow */
+ case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
+ printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
+ break;
+ /* RAISE 5 instruction */
+ case (SEQSTAT_HWERRCAUSE_RAISE_5):
+ printk(KERN_NOTICE HWC_x18(KERN_NOTICE));
+ break;
+ default: /* Reserved */
+ printk(KERN_NOTICE HWC_default(KERN_NOTICE));
+ break;
+ }
+ CHK_DEBUGGER_TRAP();
+ break;
default:
info.si_code = TRAP_ILLTRAP;
sig = SIGTRAP;
if (sig != SIGTRAP) {
unsigned long stack;
- dump_bfin_regs(fp, (void *)fp->retx);
+ dump_bfin_process(fp);
+ /* Is it an interrupt, or an exception? */
+ if (trapnr == VEC_HWERR)
+ dump_bfin_mem((void *)fp->pc);
+ else
+ 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
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;
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
* context, which should mean an oops is happening
*/
if (oops_in_progress && x >= 0x0040 && x <= 0x0047 && i <= 0)
- panic("\n\nWARNING : You should reconfigure"
+ printk(KERN_EMERG "\n"
+ KERN_EMERG "WARNING : You should reconfigure"
" the kernel to turn on\n"
- " 'Hardware error interrupt"
- " debugging'\n"
- " The rest of this error"
- " is meanless\n");
+ KERN_EMERG " 'Hardware error interrupt debugging'\n"
+ KERN_EMERG " The rest of this error is meanless\n");
#endif
if (i == (unsigned int)retaddr)
printk("[%04x]", x);
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];
+ struct irqaction *action;
+ unsigned int i;
+ unsigned long flags;
printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\n");
printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n",
(long)fp->seqstat, fp->ipend, fp->syscfg);
+ printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n",
+ (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
+ printk(KERN_NOTICE " EXCAUSE : 0x%lx\n",
+ fp->seqstat & SEQSTAT_EXCAUSE);
+ for (i = 6; i <= 15 ; i++) {
+ if (fp->ipend & (1 << i)) {
+ decode_address(buf, bfin_read32(EVT0 + 4*i));
+ printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf);
+ }
+ }
+
+ /* if no interrupts are going off, don't print this out */
+ if (fp->ipend & ~0x3F) {
+ for (i = 0; i < (NR_IRQS - 1); i++) {
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if (!action)
+ goto unlock;
+
+ decode_address(buf, (unsigned int)action->handler);
+ printk(KERN_NOTICE " logical irq %3d mapped : %s", i, buf);
+ for (action = action->next; action; action = action->next) {
+ decode_address(buf, (unsigned int)action->handler);
+ printk(", %s", buf);
+ }
+ printk("\n");
+unlock:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ }
+ }
decode_address(buf, fp->rete);
printk(KERN_NOTICE " RETE: %s\n", buf);
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) {
+ if (((long)fp->seqstat & SEQSTAT_EXCAUSE) &&
+ (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
decode_address(buf, bfin_read_DCPLB_FAULT_ADDR());
printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
decode_address(buf, bfin_read_ICPLB_FAULT_ADDR());
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");
}