1 /* 2 * File : mips_excpt.c 3 * This file is part of RT-Thread RTOS 4 * COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, write to the Free Software Foundation, Inc., 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Change Logs: 21 * Date Author Notes 22 * 2016��9��7�� Urey the first version 23 */ 24 25 #include <rtthread.h> 26 #include <rthw.h> 27 #include <stdio.h> 28 29 #include "mips.h" 30 #include "mips_excpt.h" 31 32 extern int backtrace(void); 33 int backtrace_ctx(mips_reg_ctx *ctx); 34 35 extern long list_thread(void); 36 37 const static char *regstr[] = { 38 "$0 zero", "$1 at", "$2 v0", "$3 v1", "$4 a0", "$5 a1", "$6 a2", "$7 a3", 39 "$8 t0", "$9 t1", "$10 t2", "$11 t3", "$12 t4", "$13 t5", "$14 t6", "$15 t7", 40 "$16 s0", "$17 s1", "$18 s2", "$19 s3", "$20 s4", "$21 s5", "$22 s6", "$23 s7", 41 "$24 t8", "$25 t9", "$26 k0", "$27 k1", "$28 gp", "$29 sp", "$30 fp", "$31 ra" 42 }; 43 44 static const char *cause_strings[32] = 45 { 46 /* 0 */ "Int", 47 /* 1 */ "TLB Mods", 48 /* 2 */ "TLB Load", 49 /* 3 */ "TLB Store", 50 /* 4 */ "Address Load", 51 /* 5 */ "Address Store", 52 /* 6 */ "Instruction Bus Error", 53 /* 7 */ "Data Bus Error", 54 /* 8 */ "Syscall", 55 /* 9 */ "Breakpoint", 56 /* 10 */ "Reserved Instruction", 57 /* 11 */ "Coprocessor Unuseable", 58 /* 12 */ "Overflow", 59 /* 13 */ "Trap", 60 /* 14 */ "Instruction Virtual Coherency Error", 61 /* 15 */ "FP Exception", 62 /* 16 */ "Reserved 16", 63 /* 17 */ "Reserved 17", 64 /* 18 */ "Reserved 18", 65 /* 19 */ "Reserved 19", 66 /* 20 */ "Reserved 20", 67 /* 21 */ "Reserved 21", 68 /* 22 */ "Reserved 22", 69 /* 23 */ "Watch", 70 /* 24 */ "Reserved 24", 71 /* 25 */ "Reserved 25", 72 /* 26 */ "Reserved 26", 73 /* 27 */ "Reserved 27", 74 /* 28 */ "Reserved 28", 75 /* 29 */ "Reserved 29", 76 /* 30 */ "Reserved 30", 77 /* 31 */ "Data Virtual Coherency Error" 78 }; 79 80 81 /** 82 * exception handle table 83 */ 84 exception_func_t sys_exception_handlers[32]; 85 86 static void mod_handler(mips_reg_ctx *regs) 87 { 88 rt_kprintf("tlb modification exception\n"); 89 rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc()); 90 rt_kprintf(" cause: 0x%08x\n", read_c0_cause()); 91 92 list_thread(); 93 94 printf("-----------------------------------------------------\n"); 95 printf("BACKTRACE:\n"); 96 backtrace(); 97 printf("-----------------------------------------------------\n"); 98 99 rt_hw_cpu_shutdown(); 100 } 101 102 static void tlbl_handler(mips_reg_ctx *regs) 103 { 104 rt_kprintf("tlb exception: load\n"); 105 rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc()); 106 rt_kprintf(" cause: 0x%08x\n", read_c0_cause()); 107 108 list_thread(); 109 110 printf("-----------------------------------------------------\n"); 111 printf("BACKTRACE:\n"); 112 backtrace(); 113 printf("-----------------------------------------------------\n"); 114 115 rt_hw_cpu_shutdown(); 116 } 117 118 static void tlbs_handler(mips_reg_ctx *regs) 119 { 120 rt_kprintf("tlb exception: store\n"); 121 rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc()); 122 rt_kprintf(" cause: 0x%08x\n", read_c0_cause()); 123 124 list_thread(); 125 126 printf("-----------------------------------------------------\n"); 127 printf("BACKTRACE:\n"); 128 backtrace(); 129 printf("-----------------------------------------------------\n"); 130 131 rt_hw_cpu_shutdown(); 132 } 133 134 static void adel_handler(mips_reg_ctx *regs) 135 { 136 rt_kprintf("address error exception: load\n"); 137 rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc()); 138 rt_kprintf(" cause: 0x%08x\n", read_c0_cause()); 139 140 list_thread(); 141 rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, rt_thread_self()->name); 142 143 printf("-----------------------------------------------------\n"); 144 printf("BACKTRACE:\n"); 145 backtrace(); 146 printf("-----------------------------------------------------\n"); 147 148 rt_hw_cpu_shutdown(); 149 } 150 151 static void ades_handler(mips_reg_ctx *regs) 152 { 153 rt_kprintf("address error exception: store\n"); 154 rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc()); 155 rt_kprintf(" cause: 0x%08x\n", read_c0_cause()); 156 157 list_thread(); 158 159 printf("-----------------------------------------------------\n"); 160 printf("BACKTRACE:\n"); 161 backtrace(); 162 printf("-----------------------------------------------------\n"); 163 164 rt_hw_cpu_shutdown(); 165 } 166 167 static void fpe_handler(mips_reg_ctx *regs) 168 { 169 rt_kprintf("floating point exception\n"); 170 rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc()); 171 rt_kprintf(" cause: 0x%08x\n", read_c0_cause()); 172 173 list_thread(); 174 175 printf("-----------------------------------------------------\n"); 176 printf("BACKTRACE:\n"); 177 backtrace(); 178 printf("-----------------------------------------------------\n"); 179 180 rt_hw_cpu_shutdown(); 181 } 182 183 184 static void unhandled_exception_handle(mips_reg_ctx *regs) 185 { 186 int i; 187 unsigned int cause = read_c0_cause(); 188 unsigned int exc = (cause >> 2) & 0x1f; 189 190 rt_kprintf("exception happens, epc: 0x%08x\n", regs->CP0EPC); 191 rt_kprintf(" cause: 0x%08x\n", regs->CP0Cause); 192 193 for (i = 0; i < 32; i++) 194 { 195 if (i % 4 == 0) 196 printf("\n"); 197 printf("%8s %08x ", regstr[i], regs->regs[i]); 198 } 199 printf("\n"); 200 201 list_thread(); 202 rt_hw_cpu_shutdown(); 203 } 204 205 static void install_default_exception_handler(void) 206 { 207 int i; 208 209 for (i=0; i<sizeof(sys_exception_handlers)/sizeof(sys_exception_handlers[0]); i++) 210 sys_exception_handlers[i] = (exception_func_t)unhandled_exception_handle; 211 212 sys_exception_handlers[EX_MOD] = mod_handler; 213 sys_exception_handlers[EX_TLBL] = tlbl_handler; 214 sys_exception_handlers[EX_TLBS] = tlbs_handler; 215 sys_exception_handlers[EX_ADEL] = adel_handler; 216 sys_exception_handlers[EX_ADES] = ades_handler; 217 sys_exception_handlers[EX_FPE] = fpe_handler; 218 } 219 220 int rt_hw_exception_init(void) 221 { 222 /* install the default exception handler */ 223 install_default_exception_handler(); 224 225 return RT_EOK; 226 } 227 228 /** 229 * setup the exception handle 230 */ 231 exception_func_t rt_set_except_vector(int n, exception_func_t func) 232 { 233 exception_func_t old_handler = sys_exception_handlers[n]; 234 235 if ((n == 0) || (n > 32) || (!func)) 236 { 237 return 0; 238 } 239 240 sys_exception_handlers[n] = func; 241 242 return old_handler; 243 } 244 245 void mips_exception_handler(mips_reg_ctx *ctx) 246 { 247 static int read_epc_count = 0; 248 static int epc_save = 0; 249 int i; 250 unsigned int epc; 251 252 //��� read_epc_count>0 ˵�� c_except_handler �ڶ� epc ʱ�����ˣ����� epc ������һ���µ��쳣 253 if (read_epc_count > 0) 254 { 255 printf("ERROR: read epc fail when except handle\n"); 256 epc = epc_save; 257 read_epc_count = 0; 258 } 259 else 260 { 261 read_epc_count++; 262 epc_save = 0; 263 epc = read_c0_epc(); 264 epc_save = epc; 265 266 if (epc != 0) 267 { 268 printf("-----------------------------------------------------\n"); 269 for (i = 0; i < 4; i++) 270 { 271 printf("%08x:\t%08x\n", 272 (epc - 4 * 4 + i * 4), 273 *(unsigned int *) ((epc - 4 * 4 + i * 4) | 0xa0000000)); 274 } 275 for (i = 0; i < 4; i++) 276 { 277 printf("%08x:\t%08x\n", 278 (epc + i * 4), 279 *(unsigned int *) ((epc + i * 4) | 0xa0000000)); 280 } 281 printf("-----------------------------------------------------\n"); 282 } 283 284 read_epc_count--; 285 } 286 287 printf("-----------------------------------------------------\n"); 288 unsigned int cause = read_c0_cause(); 289 unsigned int exc = (cause >> 2) & 0x1f; 290 printf("CAUSE=%08x --> %s\n", cause, cause_strings[exc]); 291 printf("EPC=%08x\n", epc); 292 293 for (i = 0; i < 32; i++) 294 { 295 if ((i != 0) && (i % 4 == 0)) 296 printf("\n"); 297 printf("%8s %08x ", regstr[i], ctx->regs[i]); 298 } 299 printf("\n-----------------------------------------------------\n"); 300 printf("%s: \t %8x\n","CP0Status ", ctx->CP0Status); 301 printf("%s: \t %8x\n","CP0DataHI ", ctx->CP0DataHI); 302 printf("%s: \t %8x\n","CP0DataLO ", ctx->CP0DataLO); 303 printf("%s: \t %8x\n","CP0BadVAddr", ctx->CP0BadVAddr); 304 printf("%s: \t %8x\n","CP0Cause ", ctx->CP0Cause); 305 printf("%s: \t %8x\n","CP0EPC ", ctx->CP0EPC); 306 printf("-----------------------------------------------------\n"); 307 308 #if 0 309 switch (exc) 310 { 311 case EX_MOD: 312 /* TLB modified */ 313 break; 314 315 case EX_TLBL: /* TLB exc(load or ifetch) */ 316 case EX_TLBS: /* TLB exception (store) */ 317 318 break; 319 320 case EX_ADEL: /* Address err(load or ifetch) */ 321 case EX_ADES: /* Address error (store) */ 322 323 break; 324 325 case EX_IBE: /* Instruction Bus Error */ 326 case EX_DBE: /* Data Bus Error */ 327 328 break; 329 330 case EX_SYS: /* Syscall */ 331 332 break; 333 334 case EX_BP: /* Breakpoint */ 335 case EX_TR: /* Trap instruction */ 336 337 break; 338 case EX_RI: /* Reserved instruction */ 339 340 break; 341 case EX_FPE: /* floating point exception */ 342 break; 343 344 case EX_CPU: /* CoProcessor Unusable */ 345 346 break; 347 case EX_OV: /* OVerflow */ 348 case EX_C2E: /* COP2 exception */ 349 case EX_MDMX: /* MDMX exception */ 350 case EX_WATCH: /* Watch exception */ 351 case EX_MCHECK: /* Machine check exception */ 352 case EX_CacheErr: /* Cache error caused re-entry */ 353 /* to Debug Mode */ 354 355 break; 356 default: 357 rt_kprintf("Unknow exception: %d\r\n", exc); 358 break; 359 } 360 #else 361 sys_exception_handlers[exc](ctx); 362 #endif 363 364 rt_hw_cpu_shutdown(); 365 } 366 367 368 void mips_cache_error_handler (unsigned int Addr) 369 { 370 rt_kprintf("cache exception happens, epc: 0x%08x\n", read_c0_epc()); 371 list_thread(); 372 rt_hw_cpu_shutdown(); 373 } 374 375 void mips_tlb_refill_handler(void) 376 { 377 rt_kprintf("tlb-miss happens, epc: 0x%08x\n", read_c0_epc()); 378 rt_kprintf(" cause: 0x%08x\n", read_c0_cause()); 379 list_thread(); 380 rt_kprintf("current thread: %s\n", rt_thread_self()->name); 381 rt_hw_cpu_shutdown(); 382 } 383