1 #include <rtthread.h> 2 #include <asm/processor.h> 3 #include <asm/ppc4xx-uic.h> 4 5 /* Returns 0 if exception not found and fixup otherwise. */ 6 extern unsigned long search_exception_table(unsigned long); 7 8 /* THIS NEEDS CHANGING to use the board info structure. 9 */ 10 #define END_OF_MEM 0x800000 11 #define UICB0_ALL 0 12 13 #define ESR_MCI 0x80000000 14 #define ESR_PIL 0x08000000 15 #define ESR_PPR 0x04000000 16 #define ESR_PTR 0x02000000 17 #define ESR_DST 0x00800000 18 #define ESR_DIZ 0x00400000 19 #define ESR_U0F 0x00008000 20 21 rt_inline void set_tsr(unsigned long val) 22 { 23 mtspr(SPRN_TSR, val); 24 } 25 26 rt_inline rt_uint32_t get_esr(void) 27 { 28 rt_uint32_t val; 29 30 val = mfspr(SPRN_ESR); 31 return val; 32 } 33 34 /* 35 * Trap & Exception support 36 */ 37 38 void print_backtrace(unsigned long *sp) 39 { 40 int cnt = 0; 41 unsigned long i; 42 43 rt_kprintf("Call backtrace: "); 44 while (sp) { 45 if ((rt_uint32_t)sp > END_OF_MEM) 46 break; 47 48 i = sp[1]; 49 if (cnt++ % 7 == 0) 50 rt_kprintf("\n"); 51 rt_kprintf("%08lX ", i); 52 if (cnt > 32) break; 53 sp = (unsigned long *)*sp; 54 } 55 rt_kprintf("\n"); 56 } 57 58 void show_regs(struct pt_regs * regs) 59 { 60 int i; 61 62 rt_kprintf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DEAR: %08lX\n", 63 regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar); 64 rt_kprintf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", 65 regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, 66 regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0, 67 regs->msr&MSR_IR ? 1 : 0, 68 regs->msr&MSR_DR ? 1 : 0); 69 70 rt_kprintf("\n"); 71 for (i = 0; i < 32; i++) { 72 if ((i % 8) == 0) { 73 rt_kprintf("GPR%02d: ", i); 74 } 75 76 rt_kprintf("%08lX ", regs->gpr[i]); 77 if ((i % 8) == 7) { 78 rt_kprintf("\n"); 79 } 80 } 81 } 82 83 void panic(const char *fmt, ...) 84 { 85 while(1); 86 } 87 88 void 89 _exception(int signr, struct pt_regs *regs) 90 { 91 show_regs(regs); 92 print_backtrace((unsigned long *)regs->gpr[1]); 93 panic("Exception"); 94 } 95 96 unsigned long 97 search_exception_table(unsigned long addr) 98 { 99 unsigned long ret = 0; 100 101 /* There is only the kernel to search. */ 102 // ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); 103 /* if the serial port does not hang in exception, rt_kprintf can be used */ 104 if (ret) return ret; 105 106 return 0; 107 } 108 109 /* 110 * Handle external interrupts 111 */ 112 void external_interrupt(struct pt_regs *regs) 113 { 114 u32 uic_msr; 115 116 /* 117 * Read masked interrupt status register to determine interrupt source 118 */ 119 uic_msr = mfdcr(uic0msr); 120 121 mtdcr(uic0sr, (uic_msr & UICB0_ALL)); 122 123 if (uic_msr & ~(UICB0_ALL)) 124 { 125 uic_interrupt(UIC0_DCR_BASE, 0); 126 } 127 128 return; 129 } 130 131 void MachineCheckException(struct pt_regs *regs) 132 { 133 unsigned long fixup, val; 134 135 if ((fixup = search_exception_table(regs->nip)) != 0) { 136 regs->nip = fixup; 137 val = mfspr(MCSR); 138 /* Clear MCSR */ 139 mtspr(SPRN_MCSR, val); 140 return; 141 } 142 143 rt_kprintf("Machine Check Exception.\n"); 144 rt_kprintf("Caused by (from msr): "); 145 rt_kprintf("regs %p ", regs); 146 147 val = get_esr(); 148 149 if (val& ESR_IMCP) { 150 rt_kprintf("Instruction"); 151 mtspr(ESR, val & ~ESR_IMCP); 152 } else { 153 rt_kprintf("Data"); 154 } 155 rt_kprintf(" machine check.\n"); 156 157 show_regs(regs); 158 print_backtrace((unsigned long *)regs->gpr[1]); 159 panic("machine check"); 160 } 161 162 void AlignmentException(struct pt_regs *regs) 163 { 164 show_regs(regs); 165 print_backtrace((unsigned long *)regs->gpr[1]); 166 panic("Alignment Exception"); 167 } 168 169 void ProgramCheckException(struct pt_regs *regs) 170 { 171 long esr_val; 172 173 show_regs(regs); 174 175 esr_val = get_esr(); 176 if( esr_val & ESR_PIL ) 177 rt_kprintf( "** Illegal Instruction **\n" ); 178 else if( esr_val & ESR_PPR ) 179 rt_kprintf( "** Privileged Instruction **\n" ); 180 else if( esr_val & ESR_PTR ) 181 rt_kprintf( "** Trap Instruction **\n" ); 182 183 print_backtrace((unsigned long *)regs->gpr[1]); 184 panic("Program Check Exception"); 185 } 186 187 void DecrementerPITException(struct pt_regs *regs) 188 { 189 /* reset PIT interrupt */ 190 set_tsr(0x08000000); 191 192 /* increase a OS Tick */ 193 rt_tick_increase(); 194 } 195 196 void UnknownException(struct pt_regs *regs) 197 { 198 199 rt_kprintf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", 200 regs->nip, regs->msr, regs->trap); 201 _exception(0, regs); 202 } 203 204 void DebugException(struct pt_regs *regs) 205 { 206 rt_kprintf("Debugger trap at @ %lx @regs %lx\n", regs->nip, (rt_uint32_t)regs ); 207 show_regs(regs); 208 } 209