diff options
Diffstat (limited to 'cpu/ppc4xx/traps.c')
-rw-r--r-- | cpu/ppc4xx/traps.c | 207 |
1 files changed, 162 insertions, 45 deletions
diff --git a/cpu/ppc4xx/traps.c b/cpu/ppc4xx/traps.c index 6aecca2..38b6f89 100644 --- a/cpu/ppc4xx/traps.c +++ b/cpu/ppc4xx/traps.c @@ -36,7 +36,9 @@ #include <command.h> #include <asm/processor.h> -#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_CMD_KGDB) int (*debugger_exception_handler)(struct pt_regs *) = 0; #endif @@ -45,8 +47,7 @@ extern unsigned long search_exception_table(unsigned long); /* THIS NEEDS CHANGING to use the board info structure. */ -#define END_OF_MEM 0x00400000 - +#define END_OF_MEM (gd->bd->bi_memstart + gd->bd->bi_memsize) static __inline__ void set_tsr(unsigned long val) { @@ -77,7 +78,7 @@ static __inline__ unsigned long get_esr(void) #define ESR_DIZ 0x00400000 #define ESR_U0F 0x00008000 -#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) +#if defined(CONFIG_CMD_BEDBUG) extern void do_bedbug_breakpoint(struct pt_regs *); #endif @@ -110,7 +111,7 @@ void show_regs(struct pt_regs * regs) { int i; - printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n", + printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DEAR: %08lX\n", regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar); printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, @@ -120,14 +121,12 @@ void show_regs(struct pt_regs * regs) printf("\n"); for (i = 0; i < 32; i++) { - if ((i % 8) == 0) - { + if ((i % 8) == 0) { printf("GPR%02d: ", i); } printf("%08lX ", regs->gpr[i]); - if ((i % 8) == 7) - { + if ((i % 8) == 7) { printf("\n"); } } @@ -139,48 +138,166 @@ _exception(int signr, struct pt_regs *regs) { show_regs(regs); print_backtrace((unsigned long *)regs->gpr[1]); - panic("Exception in kernel pc %lx signal %d",regs->nip,signr); + panic("Exception"); } void MachineCheckException(struct pt_regs *regs) { - unsigned long fixup; + unsigned long fixup, val; +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + u32 value2; + int corr_ecc = 0; + int uncorr_ecc = 0; +#endif - /* Probing PCI using config cycles cause this exception - * when a device is not present. Catch it and return to - * the PCI exception handler. - */ if ((fixup = search_exception_table(regs->nip)) != 0) { regs->nip = fixup; + val = mfspr(MCSR); + /* Clear MCSR */ + mtspr(SPRN_MCSR, val); return; } -#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#if defined(CONFIG_CMD_KGDB) if (debugger_exception_handler && (*debugger_exception_handler)(regs)) return; #endif - printf("Machine check in kernel mode.\n"); + printf("Machine Check Exception.\n"); printf("Caused by (from msr): "); - printf("regs %p ",regs); - switch( regs->msr & 0x000F0000) { - case (0x80000000>>12): - printf("Machine check signal - probably due to mm fault\n" - "with mmu off\n"); + printf("regs %p ", regs); + + val = get_esr(); + +#if !defined(CONFIG_440) + if (val& ESR_IMCP) { + printf("Instruction"); + mtspr(ESR, val & ~ESR_IMCP); + } else { + printf("Data"); + } + printf(" machine check.\n"); + +#elif defined(CONFIG_440) + if (val& ESR_IMCP){ + printf("Instruction Synchronous Machine Check exception\n"); + mtspr(SPRN_ESR, val & ~ESR_IMCP); + } else { + val = mfspr(MCSR); + if (val & MCSR_IB) + printf("Instruction Read PLB Error\n"); + if (val & MCSR_DRB) + printf("Data Read PLB Error\n"); + if (val & MCSR_DWB) + printf("Data Write PLB Error\n"); + if (val & MCSR_TLBP) + printf("TLB Parity Error\n"); + if (val & MCSR_ICP){ + /*flush_instruction_cache(); */ + printf("I-Cache Parity Error\n"); + } + if (val & MCSR_DCSP) + printf("D-Cache Search Parity Error\n"); + if (val & MCSR_DCFP) + printf("D-Cache Flush Parity Error\n"); + if (val & MCSR_IMPE) + printf("Machine Check exception is imprecise\n"); + + /* Clear MCSR */ + mtspr(SPRN_MCSR, val); + } +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + mfsdram(DDR0_00, val) ; + printf("DDR0: DDR0_00 %p\n", val); + val = (val >> 16) & 0xff; + if (val & 0x80) + printf("DDR0: At least one interrupt active\n"); + if (val & 0x40) + printf("DDR0: DRAM initialization complete.\n"); + if (val & 0x20) { + printf("DDR0: Multiple uncorrectable ECC events.\n"); + uncorr_ecc = 1; + } + if (val & 0x10) { + printf("DDR0: Single uncorrectable ECC event.\n"); + uncorr_ecc = 1; + } + if (val & 0x08) { + printf("DDR0: Multiple correctable ECC events.\n"); + corr_ecc = 1; + } + if (val & 0x04) { + printf("DDR0: Single correctable ECC event.\n"); + corr_ecc = 1; + } + if (val & 0x02) + printf("Multiple accesses outside the defined" + " physical memory space detected\n"); + if (val & 0x01) + printf("DDR0: Single access outside the defined" + " physical memory space detected.\n"); + + mfsdram(DDR0_01, val); + val = (val >> 8) & 0x7; + switch (val ) { + case 0: + printf("DDR0: Write Out-of-Range command\n"); + break; + case 1: + printf("DDR0: Read Out-of-Range command\n"); break; - case (0x80000000>>13): - printf("Transfer error ack signal\n"); + case 2: + printf("DDR0: Masked write Out-of-Range command\n"); break; - case (0x80000000>>14): - printf("Data parity signal\n"); + case 4: + printf("DDR0: Wrap write Out-of-Range command\n"); break; - case (0x80000000>>15): - printf("Address parity signal\n"); + case 5: + printf("DDR0: Wrap read Out-of-Range command\n"); break; default: - printf("Unknown values in msr\n"); + mfsdram(DDR0_01, value2); + printf("DDR0: No DDR0 error know 0x%x %p\n", val, value2); } + mfsdram(DDR0_23, val); + if (((val >> 16) & 0xff) && corr_ecc) + printf("DDR0: Syndrome for correctable ECC event 0x%x\n", + (val >> 16) & 0xff); + mfsdram(DDR0_23, val); + if (((val >> 8) & 0xff) && uncorr_ecc) + printf("DDR0: Syndrome for uncorrectable ECC event 0x%x\n", + (val >> 8) & 0xff); + mfsdram(DDR0_33, val); + if (val) + printf("DDR0: Address of command that caused an " + "Out-of-Range interrupt %p\n", val); + mfsdram(DDR0_34, val); + if (val && uncorr_ecc) + printf("DDR0: Address of uncorrectable ECC event %p\n", val); + mfsdram(DDR0_35, val); + if (val && uncorr_ecc) + printf("DDR0: Address of uncorrectable ECC event %p\n", val); + mfsdram(DDR0_36, val); + if (val && uncorr_ecc) + printf("DDR0: Data of uncorrectable ECC event 0x%08x\n", val); + mfsdram(DDR0_37, val); + if (val && uncorr_ecc) + printf("DDR0: Data of uncorrectable ECC event 0x%08x\n", val); + mfsdram(DDR0_38, val); + if (val && corr_ecc) + printf("DDR0: Address of correctable ECC event %p\n", val); + mfsdram(DDR0_39, val); + if (val && corr_ecc) + printf("DDR0: Address of correctable ECC event %p\n", val); + mfsdram(DDR0_40, val); + if (val && corr_ecc) + printf("DDR0: Data of correctable ECC event 0x%08x\n", val); + mfsdram(DDR0_41, val); + if (val && corr_ecc) + printf("DDR0: Data of correctable ECC event 0x%08x\n", val); +#endif /* CONFIG_440EPX */ +#endif /* CONFIG_440 */ show_regs(regs); print_backtrace((unsigned long *)regs->gpr[1]); panic("machine check"); @@ -189,7 +306,7 @@ MachineCheckException(struct pt_regs *regs) void AlignmentException(struct pt_regs *regs) { -#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#if defined(CONFIG_CMD_KGDB) if (debugger_exception_handler && (*debugger_exception_handler)(regs)) return; #endif @@ -204,7 +321,7 @@ ProgramCheckException(struct pt_regs *regs) { long esr_val; -#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#if defined(CONFIG_CMD_KGDB) if (debugger_exception_handler && (*debugger_exception_handler)(regs)) return; #endif @@ -224,7 +341,7 @@ ProgramCheckException(struct pt_regs *regs) } void -PITException(struct pt_regs *regs) +DecrementerPITException(struct pt_regs *regs) { /* * Reset PIT interrupt @@ -241,7 +358,7 @@ PITException(struct pt_regs *regs) void UnknownException(struct pt_regs *regs) { -#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#if defined(CONFIG_CMD_KGDB) if (debugger_exception_handler && (*debugger_exception_handler)(regs)) return; #endif @@ -256,7 +373,7 @@ DebugException(struct pt_regs *regs) { printf("Debugger trap at @ %lx\n", regs->nip ); show_regs(regs); -#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) +#if defined(CONFIG_CMD_BEDBUG) do_bedbug_breakpoint( regs ); #endif } @@ -272,17 +389,17 @@ addr_probe(uint *addr) __asm__ __volatile__( \ "1: lwz %0,0(%1)\n" \ - " eieio\n" \ - " li %0,0\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: li %0,-1\n" \ - " b 2b\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 2\n" \ - " .long 1b,3b\n" \ - ".text" \ - : "=r" (retval) : "r"(addr)); + " eieio\n" \ + " li %0,0\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: li %0,-1\n" \ + " b 2b\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 2\n" \ + " .long 1b,3b\n" \ + ".text" \ + : "=r" (retval) : "r"(addr)); return (retval); #endif |