Skip to content

Commit

Permalink
Blackfin: push down exception oops checking
Browse files Browse the repository at this point in the history
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: Mike Frysinger <vapier@gentoo.org>
  • Loading branch information
Mike Frysinger committed Jun 13, 2009
1 parent 6510a20 commit 82bd1d7
Showing 1 changed file with 43 additions and 45 deletions.
88 changes: 43 additions & 45 deletions arch/blackfin/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -308,15 +297,15 @@ 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;
/* 0x03 - User Defined, userspace stack overflow */
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 */
Expand Down Expand Up @@ -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 */
Expand All @@ -354,15 +343,15 @@ 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;
/* 0x11 - Trace Buffer Full, handled here */
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 */
Expand Down Expand Up @@ -401,54 +390,54 @@ 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,
error case is handled here */
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:
info.si_code = ILL_CPLB_MULHIT;
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 */
Expand All @@ -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;
Expand All @@ -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
Expand All @@ -477,39 +466,39 @@ 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:
info.si_code = ILL_CPLB_MULHIT;
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 */
Expand Down Expand Up @@ -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):
Expand All @@ -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",
Expand All @@ -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);
Expand Down

0 comments on commit 82bd1d7

Please sign in to comment.