Commit 82bd1d7d authored by Mike Frysinger's avatar Mike Frysinger

Blackfin: push down exception oops checking

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