trap.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. */
  9. #include <rthw.h>
  10. #include <rtthread.h>
  11. #include "encoding.h"
  12. #include "stack.h"
  13. #include "sbi.h"
  14. #include "riscv.h"
  15. #include "tick.h"
  16. #include "plic.h"
  17. #include "lwp_arch.h"
  18. void dump_regs(struct rt_hw_stack_frame *regs)
  19. {
  20. rt_kprintf("--------------Dump Registers-----------------\n");
  21. rt_kprintf("Function Registers:\n");
  22. rt_kprintf("\tra(x1) = 0x%p\tuser_sp = 0x%p\n", regs->ra, regs->user_sp_exc_stack);
  23. rt_kprintf("\tgp(x3) = 0x%p\ttp(x4) = 0x%p\n", regs->gp, regs->tp);
  24. rt_kprintf("Temporary Registers:\n");
  25. rt_kprintf("\tt0(x5) = 0x%p\tt1(x6) = 0x%p\n", regs->t0, regs->t1);
  26. rt_kprintf("\tt2(x7) = 0x%p\n", regs->t2);
  27. rt_kprintf("\tt3(x28) = 0x%p\tt4(x29) = 0x%p\n", regs->t3, regs->t4);
  28. rt_kprintf("\tt5(x30) = 0x%p\tt6(x31) = 0x%p\n", regs->t5, regs->t6);
  29. rt_kprintf("Saved Registers:\n");
  30. rt_kprintf("\ts0/fp(x8) = 0x%p\ts1(x9) = 0x%p\n", regs->s0_fp, regs->s1);
  31. rt_kprintf("\ts2(x18) = 0x%p\ts3(x19) = 0x%p\n", regs->s2, regs->s3);
  32. rt_kprintf("\ts4(x20) = 0x%p\ts5(x21) = 0x%p\n", regs->s4, regs->s5);
  33. rt_kprintf("\ts6(x22) = 0x%p\ts7(x23) = 0x%p\n", regs->s6, regs->s7);
  34. rt_kprintf("\ts8(x24) = 0x%p\ts9(x25) = 0x%p\n", regs->s8, regs->s9);
  35. rt_kprintf("\ts10(x26) = 0x%p\ts11(x27) = 0x%p\n", regs->s10, regs->s11);
  36. rt_kprintf("Function Arguments Registers:\n");
  37. rt_kprintf("\ta0(x10) = 0x%p\ta1(x11) = 0x%p\n", regs->a0, regs->a1);
  38. rt_kprintf("\ta2(x12) = 0x%p\ta3(x13) = 0x%p\n", regs->a2, regs->a3);
  39. rt_kprintf("\ta4(x14) = 0x%p\ta5(x15) = 0x%p\n", regs->a4, regs->a5);
  40. rt_kprintf("\ta6(x16) = 0x%p\ta7(x17) = 0x%p\n", regs->a6, regs->a7);
  41. rt_kprintf("sstatus = 0x%p\n", regs->sstatus);
  42. rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SIE) ? "Supervisor Interrupt Enabled" : "Supervisor Interrupt Disabled");
  43. rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled");
  44. rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode");
  45. rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SUM) ? "Permit to Access User Page" : "Not Permit to Access User Page");
  46. rt_kprintf("\t%s\n", (regs->sstatus & (1 << 19)) ? "Permit to Read Executable-only Page" : "Not Permit to Read Executable-only Page");
  47. rt_size_t satp_v = read_csr(satp);
  48. rt_kprintf("satp = 0x%p\n", satp_v);
  49. rt_kprintf("\tCurrent Page Table(Physical) = 0x%p\n", __MASKVALUE(satp_v, __MASK(44)) << PAGE_OFFSET_BIT);
  50. rt_kprintf("\tCurrent ASID = 0x%p\n", __MASKVALUE(satp_v >> 44, __MASK(16)) << PAGE_OFFSET_BIT);
  51. const char *mode_str = "Unknown Address Translation/Protection Mode";
  52. switch (__MASKVALUE(satp_v >> 60, __MASK(4)))
  53. {
  54. case 0:
  55. mode_str = "No Address Translation/Protection Mode";
  56. break;
  57. case 8:
  58. mode_str = "Page-based 39-bit Virtual Addressing Mode";
  59. break;
  60. case 9:
  61. mode_str = "Page-based 48-bit Virtual Addressing Mode";
  62. break;
  63. }
  64. rt_kprintf("\tMode = %s\n", mode_str);
  65. rt_kprintf("-----------------Dump OK---------------------\n");
  66. }
  67. static const char *Exception_Name[] =
  68. {
  69. "Instruction Address Misaligned",
  70. "Instruction Access Fault",
  71. "Illegal Instruction",
  72. "Breakpoint",
  73. "Load Address Misaligned",
  74. "Load Access Fault",
  75. "Store/AMO Address Misaligned",
  76. "Store/AMO Access Fault",
  77. "Environment call from U-mode",
  78. "Environment call from S-mode",
  79. "Reserved-10",
  80. "Reserved-11",
  81. "Instruction Page Fault",
  82. "Load Page Fault",
  83. "Reserved-14",
  84. "Store/AMO Page Fault"};
  85. static const char *Interrupt_Name[] =
  86. {
  87. "User Software Interrupt",
  88. "Supervisor Software Interrupt",
  89. "Reversed-2",
  90. "Reversed-3",
  91. "User Timer Interrupt",
  92. "Supervisor Timer Interrupt",
  93. "Reversed-6",
  94. "Reversed-7",
  95. "User External Interrupt",
  96. "Supervisor External Interrupt",
  97. "Reserved-10",
  98. "Reserved-11",
  99. };
  100. enum
  101. {
  102. EP_INSTRUCTION_ADDRESS_MISALIGNED = 0,
  103. EP_INSTRUCTION_ACCESS_FAULT,
  104. EP_ILLEGAL_INSTRUCTION,
  105. EP_BREAKPOINT,
  106. EP_LOAD_ADDRESS_MISALIGNED,
  107. EP_LOAD_ACCESS_FAULT,
  108. EP_STORE_ADDRESS_MISALIGNED,
  109. EP_STORE_ACCESS_FAULT,
  110. EP_ENVIRONMENT_CALL_U_MODE,
  111. EP_ENVIRONMENT_CALL_S_MODE,
  112. EP_RESERVED10,
  113. EP_ENVIRONMENT_CALL_M_MODE,
  114. EP_INSTRUCTION_PAGE_FAULT, /* page attr */
  115. EP_LOAD_PAGE_FAULT, /* read data */
  116. EP_RESERVED14,
  117. EP_STORE_PAGE_FAULT, /* write data */
  118. };
  119. extern struct rt_irq_desc irq_desc[];
  120. #include "rtdbg.h"
  121. #include "encoding.h"
  122. void sys_exit(int value);
  123. static const char *get_exception_msg(int id)
  124. {
  125. const char *msg;
  126. if (id < sizeof(Exception_Name) / sizeof(const char *))
  127. {
  128. msg = Exception_Name[id];
  129. }
  130. else
  131. {
  132. msg = "Unknown Exception";
  133. }
  134. return msg;
  135. }
  136. void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw_stack_frame *sp)
  137. {
  138. rt_size_t id = __MASKVALUE(scause, __MASK(63UL));
  139. #ifdef RT_USING_USERSPACE
  140. /* user page fault */
  141. if (id == EP_LOAD_PAGE_FAULT ||
  142. id == EP_STORE_PAGE_FAULT)
  143. {
  144. if (arch_expand_user_stack((void *)stval))
  145. {
  146. return;
  147. }
  148. }
  149. #endif
  150. LOG_E("[FATAL ERROR] Exception %ld:%s\n", id, get_exception_msg(id));
  151. LOG_E("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
  152. dump_regs(sp);
  153. rt_hw_backtrace((uint32_t *)sp->s0_fp, sepc);
  154. LOG_E("User Fault, killing thread: %s", rt_thread_self()->name);
  155. sys_exit(-1);
  156. }
  157. static void vector_enable(struct rt_hw_stack_frame *sp)
  158. {
  159. sp->sstatus |= SSTATUS_VS_INITIAL;
  160. }
  161. /**
  162. * detect V/D support, and do not distinguish V/D instruction
  163. */
  164. static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *sp)
  165. {
  166. // first 7 bits is opcode
  167. int opcode = stval & 0x7f;
  168. int csr = (stval & 0xFFF00000) >> 20;
  169. // ref riscv-v-spec-1.0, [Vector Instruction Formats]
  170. int width = ((stval & 0x7000) >> 12) - 1;
  171. int flag = 0;
  172. switch (opcode)
  173. {
  174. case 0x57: // V
  175. case 0x27: // scalar FLOAT
  176. case 0x07:
  177. case 0x73: // CSR
  178. flag = 1;
  179. break;
  180. }
  181. if (flag)
  182. {
  183. vector_enable(sp);
  184. }
  185. return flag;
  186. }
  187. static void handle_nested_trap_panic(
  188. rt_size_t cause,
  189. rt_size_t tval,
  190. rt_size_t epc,
  191. struct rt_hw_stack_frame *eframe)
  192. {
  193. LOG_E("\n-------- [SEVER ERROR] --------");
  194. LOG_E("Nested trap detected");
  195. LOG_E("scause:0x%p,stval:0x%p,sepc:0x%p\n", cause, tval, epc);
  196. dump_regs(eframe);
  197. rt_hw_cpu_shutdown();
  198. }
  199. #ifndef RT_USING_SMP
  200. static volatile int nested = 0;
  201. #define ENTER_TRAP \
  202. nested += 1
  203. #define EXIT_TRAP \
  204. nested -= 1
  205. #define CHECK_NESTED_PANIC(cause, tval, epc, eframe) \
  206. if (nested != 1) \
  207. handle_nested_trap_panic(cause, tval, epc, eframe)
  208. #endif /* RT_USING_SMP */
  209. /* Trap entry */
  210. void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw_stack_frame *sp)
  211. {
  212. ENTER_TRAP;
  213. rt_size_t id = __MASKVALUE(scause, __MASK(63UL));
  214. const char *msg;
  215. /* supervisor external interrupt */
  216. if (scause == (uint64_t)(0x8000000000000005))
  217. {
  218. rt_interrupt_enter();
  219. tick_isr();
  220. rt_interrupt_leave();
  221. }
  222. else if (scause == (uint64_t)(0x8000000000000009))
  223. {
  224. rt_interrupt_enter();
  225. int plic_irq = plic_claim();
  226. plic_complete(plic_irq);
  227. irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param);
  228. rt_interrupt_leave();
  229. }
  230. else
  231. {
  232. // trap cannot nested when handling another trap / interrupt
  233. CHECK_NESTED_PANIC(scause, stval, sepc, sp);
  234. rt_size_t id = __MASKVALUE(scause, __MASK(63UL));
  235. const char *msg;
  236. if (scause >> 63)
  237. {
  238. if (id < sizeof(Interrupt_Name) / sizeof(const char *))
  239. {
  240. msg = Interrupt_Name[id];
  241. }
  242. else
  243. {
  244. msg = "Unknown Interrupt";
  245. }
  246. rt_kprintf("Unhandled Interrupt %ld:%s\n", id, msg);
  247. }
  248. else
  249. {
  250. #ifdef ENABLE_VECTOR
  251. if (scause == 0x2)
  252. {
  253. if (!(sp->sstatus & SSTATUS_VS) && illegal_inst_recoverable(stval, sp))
  254. goto _exit;
  255. }
  256. #endif /* ENABLE_VECTOR */
  257. if (!(sp->sstatus & 0x100))
  258. {
  259. handle_user(scause, stval, sepc, sp);
  260. // if handle_user() return here, jump to u mode then
  261. goto _exit;
  262. }
  263. // handle kernel exception:
  264. rt_kprintf("Unhandled Exception %ld:%s\n", id, get_exception_msg(id));
  265. }
  266. rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
  267. dump_regs(sp);
  268. rt_kprintf("--------------Thread list--------------\n");
  269. rt_kprintf("current thread: %s\n", rt_thread_self()->name);
  270. extern struct rt_thread *rt_current_thread;
  271. rt_kprintf("--------------Backtrace--------------\n");
  272. rt_hw_backtrace((uint32_t *)sp->s0_fp, sepc);
  273. while (1)
  274. ;
  275. }
  276. _exit:
  277. EXIT_TRAP;
  278. return ;
  279. }