|
@@ -239,6 +239,11 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
|
|
|
|
|
|
}
|
|
|
|
|
|
+static int kernel_mode_regs(struct pt_regs *regs)
|
|
|
+{
|
|
|
+ return regs->ipend & 0xffc0;
|
|
|
+}
|
|
|
+
|
|
|
asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
{
|
|
|
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
|
|
@@ -247,6 +252,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
|
|
unsigned int cpu = smp_processor_id();
|
|
|
#endif
|
|
|
+ const char *strerror = NULL;
|
|
|
int sig = 0;
|
|
|
siginfo_t info;
|
|
|
unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
|
|
@@ -260,27 +266,10 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
* double faults if the stack has become corrupt
|
|
|
*/
|
|
|
|
|
|
- /* If the fault was caused by a kernel thread, or interrupt handler
|
|
|
- * we will kernel panic, so the system reboots.
|
|
|
- * If KGDB is enabled, don't set this for kernel breakpoints
|
|
|
- */
|
|
|
-
|
|
|
- /* TODO: check to see if we are in some sort of deferred HWERR
|
|
|
- * that we should be able to recover from, not kernel panic
|
|
|
- */
|
|
|
- if ((bfin_read_IPEND() & 0xFFC0) && (trapnr != VEC_STEP)
|
|
|
-#ifdef CONFIG_KGDB
|
|
|
- && (trapnr != VEC_EXCPT02)
|
|
|
+#ifndef CONFIG_KGDB
|
|
|
+ /* IPEND is skipped if KGDB isn't enabled (see entry code) */
|
|
|
+ fp->ipend = bfin_read_IPEND();
|
|
|
#endif
|
|
|
- ){
|
|
|
- console_verbose();
|
|
|
- oops_in_progress = 1;
|
|
|
- } else if (current) {
|
|
|
- if (current->mm == NULL) {
|
|
|
- console_verbose();
|
|
|
- oops_in_progress = 1;
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
/* trap_c() will be called for exceptions. During exceptions
|
|
|
* processing, the pc value should be set with retx value.
|
|
@@ -308,7 +297,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
sig = SIGTRAP;
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
/* Check if this is a breakpoint in kernel space */
|
|
|
- if (fp->ipend & 0xffc0)
|
|
|
+ if (kernel_mode_regs(fp))
|
|
|
goto traps_done;
|
|
|
else
|
|
|
break;
|
|
@@ -316,7 +305,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
case VEC_EXCPT03:
|
|
|
info.si_code = SEGV_STACKFLOW;
|
|
|
sig = SIGSEGV;
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x03(KERN_NOTICE);
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
/* 0x02 - KGDB initial connection and break signal trap */
|
|
@@ -345,7 +334,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
case VEC_EXCPT04 ... VEC_EXCPT15:
|
|
|
info.si_code = ILL_ILLPARAOP;
|
|
|
sig = SIGILL;
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x04(KERN_NOTICE);
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
/* 0x10 HW Single step, handled here */
|
|
@@ -354,7 +343,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
sig = SIGTRAP;
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
/* Check if this is a single step in kernel space */
|
|
|
- if (fp->ipend & 0xffc0)
|
|
|
+ if (kernel_mode_regs(fp))
|
|
|
goto traps_done;
|
|
|
else
|
|
|
break;
|
|
@@ -362,7 +351,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
case VEC_OVFLOW:
|
|
|
info.si_code = TRAP_TRACEFLOW;
|
|
|
sig = SIGTRAP;
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x11(KERN_NOTICE);
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
/* 0x12 - Reserved, Caught by default */
|
|
@@ -401,35 +390,35 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
#endif
|
|
|
info.si_code = ILL_ILLOPC;
|
|
|
sig = SIGILL;
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x21(KERN_NOTICE);
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
/* 0x22 - Illegal Instruction Combination, handled here */
|
|
|
case VEC_ILGAL_I:
|
|
|
info.si_code = ILL_ILLPARAOP;
|
|
|
sig = SIGILL;
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x22(KERN_NOTICE);
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
/* 0x23 - Data CPLB protection violation, handled here */
|
|
|
case VEC_CPLB_VL:
|
|
|
info.si_code = ILL_CPLB_VI;
|
|
|
sig = SIGBUS;
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE);
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
/* 0x24 - Data access misaligned, handled here */
|
|
|
case VEC_MISALI_D:
|
|
|
info.si_code = BUS_ADRALN;
|
|
|
sig = SIGBUS;
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x24(KERN_NOTICE);
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
/* 0x25 - Unrecoverable Event, handled here */
|
|
|
case VEC_UNCOV:
|
|
|
info.si_code = ILL_ILLEXCPT;
|
|
|
sig = SIGILL;
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x25(KERN_NOTICE);
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
/* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
|
|
@@ -437,7 +426,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
case VEC_CPLB_M:
|
|
|
info.si_code = BUS_ADRALN;
|
|
|
sig = SIGBUS;
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x26(KERN_NOTICE);
|
|
|
break;
|
|
|
/* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
|
|
|
case VEC_CPLB_MHIT:
|
|
@@ -445,10 +434,10 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
sig = SIGSEGV;
|
|
|
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
|
|
if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START)
|
|
|
- verbose_printk(KERN_NOTICE "NULL pointer access\n");
|
|
|
+ strerror = KERN_NOTICE "NULL pointer access\n";
|
|
|
else
|
|
|
#endif
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x27(KERN_NOTICE);
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
/* 0x28 - Emulation Watchpoint, handled here */
|
|
@@ -458,7 +447,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
pr_debug(EXC_0x28(KERN_DEBUG));
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
/* Check if this is a watchpoint in kernel space */
|
|
|
- if (fp->ipend & 0xffc0)
|
|
|
+ if (kernel_mode_regs(fp))
|
|
|
goto traps_done;
|
|
|
else
|
|
|
break;
|
|
@@ -467,7 +456,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */
|
|
|
info.si_code = BUS_OPFETCH;
|
|
|
sig = SIGBUS;
|
|
|
- verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n");
|
|
|
+ strerror = KERN_NOTICE "BF535: VEC_ISTRU_VL\n";
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
#else
|
|
@@ -477,21 +466,21 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
case VEC_MISALI_I:
|
|
|
info.si_code = BUS_ADRALN;
|
|
|
sig = SIGBUS;
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x2A(KERN_NOTICE);
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
/* 0x2B - Instruction CPLB protection violation, handled here */
|
|
|
case VEC_CPLB_I_VL:
|
|
|
info.si_code = ILL_CPLB_VI;
|
|
|
sig = SIGBUS;
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x2B(KERN_NOTICE);
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
/* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
|
|
|
case VEC_CPLB_I_M:
|
|
|
info.si_code = ILL_CPLB_MISS;
|
|
|
sig = SIGBUS;
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x2C(KERN_NOTICE);
|
|
|
break;
|
|
|
/* 0x2D - Instruction CPLB Multiple Hits, handled here */
|
|
|
case VEC_CPLB_I_MHIT:
|
|
@@ -499,17 +488,17 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
sig = SIGSEGV;
|
|
|
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
|
|
if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START)
|
|
|
- verbose_printk(KERN_NOTICE "Jump to NULL address\n");
|
|
|
+ strerror = KERN_NOTICE "Jump to NULL address\n";
|
|
|
else
|
|
|
#endif
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x2D(KERN_NOTICE);
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
/* 0x2E - Illegal use of Supervisor Resource, handled here */
|
|
|
case VEC_ILL_RES:
|
|
|
info.si_code = ILL_PRVOPC;
|
|
|
sig = SIGILL;
|
|
|
- verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE EXC_0x2E(KERN_NOTICE);
|
|
|
CHK_DEBUGGER_TRAP_MAYBE();
|
|
|
break;
|
|
|
/* 0x2F - Reserved, Caught by default */
|
|
@@ -537,17 +526,17 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
|
|
|
info.si_code = BUS_ADRALN;
|
|
|
sig = SIGBUS;
|
|
|
- verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE HWC_x2(KERN_NOTICE);
|
|
|
break;
|
|
|
/* External Memory Addressing Error */
|
|
|
case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
|
|
|
info.si_code = BUS_ADRERR;
|
|
|
sig = SIGBUS;
|
|
|
- verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE HWC_x3(KERN_NOTICE);
|
|
|
break;
|
|
|
/* Performance Monitor Overflow */
|
|
|
case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
|
|
|
- verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
|
|
|
+ strerror = KERN_NOTICE HWC_x12(KERN_NOTICE);
|
|
|
break;
|
|
|
/* RAISE 5 instruction */
|
|
|
case (SEQSTAT_HWERRCAUSE_RAISE_5):
|
|
@@ -564,7 +553,6 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
* if we get here we hit a reserved one, so panic
|
|
|
*/
|
|
|
default:
|
|
|
- oops_in_progress = 1;
|
|
|
info.si_code = ILL_ILLPARAOP;
|
|
|
sig = SIGILL;
|
|
|
verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
|
|
@@ -575,6 +563,16 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|
|
|
|
|
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 (strerror)
|
|
|
+ verbose_printk(strerror);
|
|
|
+ }
|
|
|
+
|
|
|
if (sig != SIGTRAP) {
|
|
|
dump_bfin_process(fp);
|
|
|
dump_bfin_mem(fp);
|