diff options
Diffstat (limited to 'arch/ppc/kernel/traps.c')
-rw-r--r-- | arch/ppc/kernel/traps.c | 185 |
1 files changed, 50 insertions, 135 deletions
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index c78568905c3..a467a429c2f 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -194,11 +194,7 @@ static inline int check_io_access(struct pt_regs *regs) /* On 4xx, the reason for the machine check or program exception is in the ESR. */ #define get_reason(regs) ((regs)->dsisr) -#ifndef CONFIG_FSL_BOOKE #define get_mc_reason(regs) ((regs)->dsisr) -#else -#define get_mc_reason(regs) (mfspr(SPRN_MCSR)) -#endif #define REASON_FP ESR_FP #define REASON_ILLEGAL (ESR_PIL | ESR_PUO) #define REASON_PRIVILEGED ESR_PPR @@ -231,39 +227,25 @@ platform_machine_check(struct pt_regs *regs) { } -void machine_check_exception(struct pt_regs *regs) +#if defined(CONFIG_4xx) +int machine_check_4xx(struct pt_regs *regs) { unsigned long reason = get_mc_reason(regs); - if (user_mode(regs)) { - regs->msr |= MSR_RI; - _exception(SIGBUS, regs, BUS_ADRERR, regs->nip); - return; - } - -#if defined(CONFIG_8xx) && defined(CONFIG_PCI) - /* the qspan pci read routines can cause machine checks -- Cort */ - bad_page_fault(regs, regs->dar, SIGBUS); - return; -#endif - - if (debugger_fault_handler) { - debugger_fault_handler(regs); - regs->msr |= MSR_RI; - return; - } - - if (check_io_access(regs)) - return; - -#if defined(CONFIG_4xx) && !defined(CONFIG_440A) if (reason & ESR_IMCP) { printk("Instruction"); mtspr(SPRN_ESR, reason & ~ESR_IMCP); } else printk("Data"); printk(" machine check in kernel mode.\n"); -#elif defined(CONFIG_440A) + + return 0; +} + +int machine_check_440A(struct pt_regs *regs) +{ + unsigned long reason = get_mc_reason(regs); + printk("Machine check in kernel mode.\n"); if (reason & ESR_IMCP){ printk("Instruction Synchronous Machine Check exception\n"); @@ -293,55 +275,13 @@ void machine_check_exception(struct pt_regs *regs) /* Clear MCSR */ mtspr(SPRN_MCSR, mcsr); } -#elif defined (CONFIG_E500) - printk("Machine check in kernel mode.\n"); - printk("Caused by (from MCSR=%lx): ", reason); - - if (reason & MCSR_MCP) - printk("Machine Check Signal\n"); - if (reason & MCSR_ICPERR) - printk("Instruction Cache Parity Error\n"); - if (reason & MCSR_DCP_PERR) - printk("Data Cache Push Parity Error\n"); - if (reason & MCSR_DCPERR) - printk("Data Cache Parity Error\n"); - if (reason & MCSR_GL_CI) - printk("Guarded Load or Cache-Inhibited stwcx.\n"); - if (reason & MCSR_BUS_IAERR) - printk("Bus - Instruction Address Error\n"); - if (reason & MCSR_BUS_RAERR) - printk("Bus - Read Address Error\n"); - if (reason & MCSR_BUS_WAERR) - printk("Bus - Write Address Error\n"); - if (reason & MCSR_BUS_IBERR) - printk("Bus - Instruction Data Error\n"); - if (reason & MCSR_BUS_RBERR) - printk("Bus - Read Data Bus Error\n"); - if (reason & MCSR_BUS_WBERR) - printk("Bus - Write Data Bus Error\n"); - if (reason & MCSR_BUS_IPERR) - printk("Bus - Instruction Parity Error\n"); - if (reason & MCSR_BUS_RPERR) - printk("Bus - Read Parity Error\n"); -#elif defined (CONFIG_E200) - printk("Machine check in kernel mode.\n"); - printk("Caused by (from MCSR=%lx): ", reason); - - if (reason & MCSR_MCP) - printk("Machine Check Signal\n"); - if (reason & MCSR_CP_PERR) - printk("Cache Push Parity Error\n"); - if (reason & MCSR_CPERR) - printk("Cache Parity Error\n"); - if (reason & MCSR_EXCP_ERR) - printk("ISI, ITLB, or Bus Error on first instruction fetch for an exception handler\n"); - if (reason & MCSR_BUS_IRERR) - printk("Bus - Read Bus Error on instruction fetch\n"); - if (reason & MCSR_BUS_DRERR) - printk("Bus - Read Bus Error on data load\n"); - if (reason & MCSR_BUS_WRERR) - printk("Bus - Write Bus Error on buffered store or cache line push\n"); -#else /* !CONFIG_4xx && !CONFIG_E500 && !CONFIG_E200 */ + return 0; +} +#else +int machine_check_generic(struct pt_regs *regs) +{ + unsigned long reason = get_mc_reason(regs); + printk("Machine check in kernel mode.\n"); printk("Caused by (from SRR1=%lx): ", reason); switch (reason & 0x601F0000) { @@ -371,7 +311,39 @@ void machine_check_exception(struct pt_regs *regs) default: printk("Unknown values in msr\n"); } -#endif /* CONFIG_4xx */ + return 0; +} +#endif /* everything else */ + +void machine_check_exception(struct pt_regs *regs) +{ + int recover = 0; + + if (cur_cpu_spec->machine_check) + recover = cur_cpu_spec->machine_check(regs); + if (recover > 0) + return; + + if (user_mode(regs)) { + regs->msr |= MSR_RI; + _exception(SIGBUS, regs, BUS_ADRERR, regs->nip); + return; + } + +#if defined(CONFIG_8xx) && defined(CONFIG_PCI) + /* the qspan pci read routines can cause machine checks -- Cort */ + bad_page_fault(regs, regs->dar, SIGBUS); + return; +#endif + + if (debugger_fault_handler) { + debugger_fault_handler(regs); + regs->msr |= MSR_RI; + return; + } + + if (check_io_access(regs)) + return; /* * Optional platform-provided routine to print out @@ -830,63 +802,6 @@ void altivec_assist_exception(struct pt_regs *regs) } #endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_E500 -void performance_monitor_exception(struct pt_regs *regs) -{ - perf_irq(regs); -} -#endif - -#ifdef CONFIG_FSL_BOOKE -void CacheLockingException(struct pt_regs *regs, unsigned long address, - unsigned long error_code) -{ - /* We treat cache locking instructions from the user - * as priv ops, in the future we could try to do - * something smarter - */ - if (error_code & (ESR_DLK|ESR_ILK)) - _exception(SIGILL, regs, ILL_PRVOPC, regs->nip); - return; -} -#endif /* CONFIG_FSL_BOOKE */ - -#ifdef CONFIG_SPE -void SPEFloatingPointException(struct pt_regs *regs) -{ - unsigned long spefscr; - int fpexc_mode; - int code = 0; - - spefscr = current->thread.spefscr; - fpexc_mode = current->thread.fpexc_mode; - - /* Hardware does not necessarily set sticky - * underflow/overflow/invalid flags */ - if ((spefscr & SPEFSCR_FOVF) && (fpexc_mode & PR_FP_EXC_OVF)) { - code = FPE_FLTOVF; - spefscr |= SPEFSCR_FOVFS; - } - else if ((spefscr & SPEFSCR_FUNF) && (fpexc_mode & PR_FP_EXC_UND)) { - code = FPE_FLTUND; - spefscr |= SPEFSCR_FUNFS; - } - else if ((spefscr & SPEFSCR_FDBZ) && (fpexc_mode & PR_FP_EXC_DIV)) - code = FPE_FLTDIV; - else if ((spefscr & SPEFSCR_FINV) && (fpexc_mode & PR_FP_EXC_INV)) { - code = FPE_FLTINV; - spefscr |= SPEFSCR_FINVS; - } - else if ((spefscr & (SPEFSCR_FG | SPEFSCR_FX)) && (fpexc_mode & PR_FP_EXC_RES)) - code = FPE_FLTRES; - - current->thread.spefscr = spefscr; - - _exception(SIGFPE, regs, code, regs->nip); - return; -} -#endif - #ifdef CONFIG_BOOKE_WDT /* * Default handler for a Watchdog exception, |