diff options
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r-- | arch/blackfin/kernel/traps.c | 88 |
1 files changed, 43 insertions, 45 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index ed7127b1b9f..d279552fe9b 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -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); |