|
@@ -359,3 +359,201 @@ asmlinkage notrace void trap_c(struct pt_regs *fp)
|
|
|
strerror = KERN_NOTICE HWC_x2(KERN_NOTICE);
|
|
|
break;
|
|
|
/* External Memory Addressing Error */
|
|
|
+ case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
|
|
|
+ if (ANOMALY_05000310) {
|
|
|
+ static unsigned long anomaly_rets;
|
|
|
+
|
|
|
+ if ((fp->pc >= (L1_CODE_START + L1_CODE_LENGTH - 512)) &&
|
|
|
+ (fp->pc < (L1_CODE_START + L1_CODE_LENGTH))) {
|
|
|
+ /*
|
|
|
+ * A false hardware error will happen while fetching at
|
|
|
+ * the L1 instruction SRAM boundary. Ignore it.
|
|
|
+ */
|
|
|
+ anomaly_rets = fp->rets;
|
|
|
+ goto traps_done;
|
|
|
+ } else if (fp->rets == anomaly_rets) {
|
|
|
+ /*
|
|
|
+ * While boundary code returns to a function, at the ret
|
|
|
+ * point, a new false hardware error might occur too based
|
|
|
+ * on tests. Ignore it too.
|
|
|
+ */
|
|
|
+ goto traps_done;
|
|
|
+ } else if ((fp->rets >= (L1_CODE_START + L1_CODE_LENGTH - 512)) &&
|
|
|
+ (fp->rets < (L1_CODE_START + L1_CODE_LENGTH))) {
|
|
|
+ /*
|
|
|
+ * If boundary code calls a function, at the entry point,
|
|
|
+ * a new false hardware error maybe happen based on tests.
|
|
|
+ * Ignore it too.
|
|
|
+ */
|
|
|
+ goto traps_done;
|
|
|
+ } else
|
|
|
+ anomaly_rets = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ info.si_code = BUS_ADRERR;
|
|
|
+ sig = SIGBUS;
|
|
|
+ strerror = KERN_NOTICE HWC_x3(KERN_NOTICE);
|
|
|
+ break;
|
|
|
+ /* Performance Monitor Overflow */
|
|
|
+ case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
|
|
|
+ strerror = 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_MAYBE();
|
|
|
+ break;
|
|
|
+ /*
|
|
|
+ * We should be handling all known exception types above,
|
|
|
+ * if we get here we hit a reserved one, so panic
|
|
|
+ */
|
|
|
+ default:
|
|
|
+ info.si_code = ILL_ILLPARAOP;
|
|
|
+ sig = SIGILL;
|
|
|
+ verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
|
|
|
+ (fp->seqstat & SEQSTAT_EXCAUSE));
|
|
|
+ CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ BUG_ON(sig == 0);
|
|
|
+
|
|
|
+ /* If the fault was caused by a kernel thread, or interrupt handler
|
|
|
+ * we will kernel panic, so the system reboots.
|
|
|
+ */
|
|
|
+ if (kernel_mode_regs(fp) || (current && !current->mm)) {
|
|
|
+ console_verbose();
|
|
|
+ oops_in_progress = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sig != SIGTRAP) {
|
|
|
+ if (strerror)
|
|
|
+ verbose_printk(strerror);
|
|
|
+
|
|
|
+ dump_bfin_process(fp);
|
|
|
+ dump_bfin_mem(fp);
|
|
|
+ show_regs(fp);
|
|
|
+
|
|
|
+ /* Print out the trace buffer if it makes sense */
|
|
|
+#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\n");
|
|
|
+ else
|
|
|
+#endif
|
|
|
+ dump_bfin_trace_buffer();
|
|
|
+
|
|
|
+ if (oops_in_progress) {
|
|
|
+ /* Dump the current kernel stack */
|
|
|
+ verbose_printk(KERN_NOTICE "Kernel Stack\n");
|
|
|
+ show_stack(current, NULL);
|
|
|
+ print_modules();
|
|
|
+#ifndef CONFIG_ACCESS_CHECK
|
|
|
+ verbose_printk(KERN_EMERG "Please turn on "
|
|
|
+ "CONFIG_ACCESS_CHECK\n");
|
|
|
+#endif
|
|
|
+ panic("Kernel exception");
|
|
|
+ } else {
|
|
|
+#ifdef CONFIG_DEBUG_VERBOSE
|
|
|
+ unsigned long *stack;
|
|
|
+ /* Dump the user space stack */
|
|
|
+ stack = (unsigned long *)rdusp();
|
|
|
+ verbose_printk(KERN_NOTICE "Userspace Stack\n");
|
|
|
+ show_stack(NULL, stack);
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+#ifdef CONFIG_IPIPE
|
|
|
+ if (!ipipe_trap_notify(fp->seqstat & 0x3f, fp))
|
|
|
+#endif
|
|
|
+ {
|
|
|
+ info.si_signo = sig;
|
|
|
+ info.si_errno = 0;
|
|
|
+ switch (trapnr) {
|
|
|
+ case VEC_CPLB_VL:
|
|
|
+ case VEC_MISALI_D:
|
|
|
+ case VEC_CPLB_M:
|
|
|
+ case VEC_CPLB_MHIT:
|
|
|
+ info.si_addr = (void __user *)cpu_pda[cpu].dcplb_fault_addr;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ info.si_addr = (void __user *)fp->pc;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ force_sig_info(sig, &info, current);
|
|
|
+ }
|
|
|
+
|
|
|
+ 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:
|
|
|
+ trace_buffer_restore(j);
|
|
|
+}
|
|
|
+
|
|
|
+asmlinkage void double_fault_c(struct pt_regs *fp)
|
|
|
+{
|
|
|
+#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
|
|
|
+ int j;
|
|
|
+ trace_buffer_save(j);
|
|
|
+#endif
|
|
|
+
|
|
|
+ console_verbose();
|
|
|
+ oops_in_progress = 1;
|
|
|
+#ifdef CONFIG_DEBUG_VERBOSE
|
|
|
+ printk(KERN_EMERG "Double Fault\n");
|
|
|
+#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
|
|
|
+ if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) {
|
|
|
+ unsigned int cpu = raw_smp_processor_id();
|
|
|
+ char buf[150];
|
|
|
+ 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_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_doublefault_addr);
|
|
|
+ printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf);
|
|
|
+
|
|
|
+ decode_address(buf, fp->retx);
|
|
|
+ printk(KERN_NOTICE "The instruction at %s caused a double exception\n", buf);
|
|
|
+ } else
|
|
|
+#endif
|
|
|
+ {
|
|
|
+ dump_bfin_process(fp);
|
|
|
+ dump_bfin_mem(fp);
|
|
|
+ show_regs(fp);
|
|
|
+ dump_bfin_trace_buffer();
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ panic("Double Fault - unrecoverable event");
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
|
|
|
+{
|
|
|
+ switch (cplb_panic) {
|
|
|
+ case CPLB_NO_UNLOCKED:
|
|
|
+ printk(KERN_EMERG "All CPLBs are locked\n");
|
|
|
+ break;
|
|
|
+ case CPLB_PROT_VIOL:
|
|
|
+ return;
|
|
|
+ case CPLB_NO_ADDR_MATCH:
|
|
|
+ return;
|
|
|
+ case CPLB_UNKNOWN_ERR:
|
|
|
+ printk(KERN_EMERG "Unknown CPLB Exception\n");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ oops_in_progress = 1;
|
|
|
+
|
|
|
+ dump_bfin_process(fp);
|
|
|
+ dump_bfin_mem(fp);
|
|
|
+ show_regs(fp);
|