mips_excpt.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  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. #include <rtthread.h>
  25. #include <rthw.h>
  26. #include <stdio.h>
  27. #include "mips.h"
  28. #include "mips_excpt.h"
  29. extern int backtrace(void);
  30. int backtrace_ctx(mips_reg_ctx *ctx);
  31. extern long list_thread(void);
  32. const static char *regstr[] = {
  33. "$0 zero", "$1 at", "$2 v0", "$3 v1", "$4 a0", "$5 a1", "$6 a2", "$7 a3",
  34. "$8 t0", "$9 t1", "$10 t2", "$11 t3", "$12 t4", "$13 t5", "$14 t6", "$15 t7",
  35. "$16 s0", "$17 s1", "$18 s2", "$19 s3", "$20 s4", "$21 s5", "$22 s6", "$23 s7",
  36. "$24 t8", "$25 t9", "$26 k0", "$27 k1", "$28 gp", "$29 sp", "$30 fp", "$31 ra"
  37. };
  38. static const char *cause_strings[32] =
  39. {
  40. /* 0 */ "Int",
  41. /* 1 */ "TLB Mods",
  42. /* 2 */ "TLB Load",
  43. /* 3 */ "TLB Store",
  44. /* 4 */ "Address Load",
  45. /* 5 */ "Address Store",
  46. /* 6 */ "Instruction Bus Error",
  47. /* 7 */ "Data Bus Error",
  48. /* 8 */ "Syscall",
  49. /* 9 */ "Breakpoint",
  50. /* 10 */ "Reserved Instruction",
  51. /* 11 */ "Coprocessor Unuseable",
  52. /* 12 */ "Overflow",
  53. /* 13 */ "Trap",
  54. /* 14 */ "Instruction Virtual Coherency Error",
  55. /* 15 */ "FP Exception",
  56. /* 16 */ "Reserved 16",
  57. /* 17 */ "Reserved 17",
  58. /* 18 */ "Reserved 18",
  59. /* 19 */ "Reserved 19",
  60. /* 20 */ "Reserved 20",
  61. /* 21 */ "Reserved 21",
  62. /* 22 */ "Reserved 22",
  63. /* 23 */ "Watch",
  64. /* 24 */ "Reserved 24",
  65. /* 25 */ "Reserved 25",
  66. /* 26 */ "Reserved 26",
  67. /* 27 */ "Reserved 27",
  68. /* 28 */ "Reserved 28",
  69. /* 29 */ "Reserved 29",
  70. /* 30 */ "Reserved 30",
  71. /* 31 */ "Data Virtual Coherency Error"
  72. };
  73. /**
  74. * exception handle table
  75. */
  76. exception_func_t sys_exception_handlers[32];
  77. static void mod_handler(mips_reg_ctx *regs)
  78. {
  79. rt_kprintf("tlb modification exception\n");
  80. rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
  81. rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
  82. list_thread();
  83. printf("-----------------------------------------------------\n");
  84. printf("BACKTRACE:\n");
  85. backtrace();
  86. printf("-----------------------------------------------------\n");
  87. rt_hw_cpu_shutdown();
  88. }
  89. static void tlbl_handler(mips_reg_ctx *regs)
  90. {
  91. rt_kprintf("tlb exception: load\n");
  92. rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
  93. rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
  94. list_thread();
  95. printf("-----------------------------------------------------\n");
  96. printf("BACKTRACE:\n");
  97. backtrace();
  98. printf("-----------------------------------------------------\n");
  99. rt_hw_cpu_shutdown();
  100. }
  101. static void tlbs_handler(mips_reg_ctx *regs)
  102. {
  103. rt_kprintf("tlb exception: store\n");
  104. rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
  105. rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
  106. list_thread();
  107. printf("-----------------------------------------------------\n");
  108. printf("BACKTRACE:\n");
  109. backtrace();
  110. printf("-----------------------------------------------------\n");
  111. rt_hw_cpu_shutdown();
  112. }
  113. static void adel_handler(mips_reg_ctx *regs)
  114. {
  115. rt_kprintf("address error exception: load\n");
  116. rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
  117. rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
  118. list_thread();
  119. rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, rt_thread_self()->name);
  120. printf("-----------------------------------------------------\n");
  121. printf("BACKTRACE:\n");
  122. backtrace();
  123. printf("-----------------------------------------------------\n");
  124. rt_hw_cpu_shutdown();
  125. }
  126. static void ades_handler(mips_reg_ctx *regs)
  127. {
  128. rt_kprintf("address error exception: store\n");
  129. rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
  130. rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
  131. list_thread();
  132. printf("-----------------------------------------------------\n");
  133. printf("BACKTRACE:\n");
  134. backtrace();
  135. printf("-----------------------------------------------------\n");
  136. rt_hw_cpu_shutdown();
  137. }
  138. static void fpe_handler(mips_reg_ctx *regs)
  139. {
  140. rt_kprintf("floating point exception\n");
  141. rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
  142. rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
  143. list_thread();
  144. printf("-----------------------------------------------------\n");
  145. printf("BACKTRACE:\n");
  146. backtrace();
  147. printf("-----------------------------------------------------\n");
  148. rt_hw_cpu_shutdown();
  149. }
  150. static void unhandled_exception_handle(mips_reg_ctx *regs)
  151. {
  152. int i;
  153. unsigned int cause = read_c0_cause();
  154. unsigned int exc = (cause >> 2) & 0x1f;
  155. rt_kprintf("exception happens, epc: 0x%08x\n", regs->CP0EPC);
  156. rt_kprintf(" cause: 0x%08x\n", regs->CP0Cause);
  157. for (i = 0; i < 32; i++)
  158. {
  159. if (i % 4 == 0)
  160. printf("\n");
  161. printf("%8s %08x ", regstr[i], regs->regs[i]);
  162. }
  163. printf("\n");
  164. list_thread();
  165. rt_hw_cpu_shutdown();
  166. }
  167. static void install_default_exception_handler(void)
  168. {
  169. int i;
  170. for (i=0; i<sizeof(sys_exception_handlers)/sizeof(sys_exception_handlers[0]); i++)
  171. sys_exception_handlers[i] = (exception_func_t)unhandled_exception_handle;
  172. sys_exception_handlers[EX_MOD] = mod_handler;
  173. sys_exception_handlers[EX_TLBL] = tlbl_handler;
  174. sys_exception_handlers[EX_TLBS] = tlbs_handler;
  175. sys_exception_handlers[EX_ADEL] = adel_handler;
  176. sys_exception_handlers[EX_ADES] = ades_handler;
  177. sys_exception_handlers[EX_FPE] = fpe_handler;
  178. }
  179. int rt_hw_exception_init(void)
  180. {
  181. /* install the default exception handler */
  182. install_default_exception_handler();
  183. return RT_EOK;
  184. }
  185. /**
  186. * setup the exception handle
  187. */
  188. exception_func_t rt_set_except_vector(int n, exception_func_t func)
  189. {
  190. exception_func_t old_handler = sys_exception_handlers[n];
  191. if ((n == 0) || (n > 32) || (!func))
  192. {
  193. return 0;
  194. }
  195. sys_exception_handlers[n] = func;
  196. return old_handler;
  197. }
  198. void mips_exception_handler(mips_reg_ctx *ctx)
  199. {
  200. static int read_epc_count = 0;
  201. static int epc_save = 0;
  202. int i;
  203. unsigned int epc;
  204. //如果 read_epc_count>0 说明 c_except_handler 在读 epc 时重入了,即读 epc 导致了一个新的异常
  205. if (read_epc_count > 0)
  206. {
  207. printf("ERROR: read epc fail when except handle\n");
  208. epc = epc_save;
  209. read_epc_count = 0;
  210. }
  211. else
  212. {
  213. read_epc_count++;
  214. epc_save = 0;
  215. epc = read_c0_epc();
  216. epc_save = epc;
  217. if (epc != 0)
  218. {
  219. printf("-----------------------------------------------------\n");
  220. for (i = 0; i < 4; i++)
  221. {
  222. printf("%08x:\t%08x\n",
  223. (epc - 4 * 4 + i * 4),
  224. *(unsigned int *) ((epc - 4 * 4 + i * 4) | 0xa0000000));
  225. }
  226. for (i = 0; i < 4; i++)
  227. {
  228. printf("%08x:\t%08x\n",
  229. (epc + i * 4),
  230. *(unsigned int *) ((epc + i * 4) | 0xa0000000));
  231. }
  232. printf("-----------------------------------------------------\n");
  233. }
  234. read_epc_count--;
  235. }
  236. printf("-----------------------------------------------------\n");
  237. unsigned int cause = read_c0_cause();
  238. unsigned int exc = (cause >> 2) & 0x1f;
  239. printf("CAUSE=%08x --> %s\n", cause, cause_strings[exc]);
  240. printf("EPC=%08x\n", epc);
  241. for (i = 0; i < 32; i++)
  242. {
  243. if ((i != 0) && (i % 4 == 0))
  244. printf("\n");
  245. printf("%8s %08x ", regstr[i], ctx->regs[i]);
  246. }
  247. printf("\n-----------------------------------------------------\n");
  248. printf("%s: \t %8x\n","CP0Status ", ctx->CP0Status);
  249. printf("%s: \t %8x\n","CP0DataHI ", ctx->CP0DataHI);
  250. printf("%s: \t %8x\n","CP0DataLO ", ctx->CP0DataLO);
  251. printf("%s: \t %8x\n","CP0BadVAddr", ctx->CP0BadVAddr);
  252. printf("%s: \t %8x\n","CP0Cause ", ctx->CP0Cause);
  253. printf("%s: \t %8x\n","CP0EPC ", ctx->CP0EPC);
  254. printf("-----------------------------------------------------\n");
  255. #if 0
  256. switch (exc)
  257. {
  258. case EX_MOD:
  259. /* TLB modified */
  260. break;
  261. case EX_TLBL: /* TLB exc(load or ifetch) */
  262. case EX_TLBS: /* TLB exception (store) */
  263. break;
  264. case EX_ADEL: /* Address err(load or ifetch) */
  265. case EX_ADES: /* Address error (store) */
  266. break;
  267. case EX_IBE: /* Instruction Bus Error */
  268. case EX_DBE: /* Data Bus Error */
  269. break;
  270. case EX_SYS: /* Syscall */
  271. break;
  272. case EX_BP: /* Breakpoint */
  273. case EX_TR: /* Trap instruction */
  274. break;
  275. case EX_RI: /* Reserved instruction */
  276. break;
  277. case EX_FPE: /* floating point exception */
  278. break;
  279. case EX_CPU: /* CoProcessor Unusable */
  280. break;
  281. case EX_OV: /* OVerflow */
  282. case EX_C2E: /* COP2 exception */
  283. case EX_MDMX: /* MDMX exception */
  284. case EX_WATCH: /* Watch exception */
  285. case EX_MCHECK: /* Machine check exception */
  286. case EX_CacheErr: /* Cache error caused re-entry */
  287. /* to Debug Mode */
  288. break;
  289. default:
  290. rt_kprintf("Unknow exception: %d\r\n", exc);
  291. break;
  292. }
  293. #else
  294. sys_exception_handlers[exc](ctx);
  295. #endif
  296. rt_hw_cpu_shutdown();
  297. }
  298. void mips_cache_error_handler (unsigned int Addr)
  299. {
  300. rt_kprintf("cache exception happens, epc: 0x%08x\n", read_c0_epc());
  301. list_thread();
  302. rt_hw_cpu_shutdown();
  303. }
  304. void mips_tlb_refill_handler(void)
  305. {
  306. rt_kprintf("tlb-miss happens, epc: 0x%08x\n", read_c0_epc());
  307. rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
  308. list_thread();
  309. rt_kprintf("current thread: %s\n", rt_thread_self()->name);
  310. rt_hw_cpu_shutdown();
  311. }