trap.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /*
  2. * Copyright (c) 2021 - 2022 hpmicro
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. *
  6. */
  7. #include "hpm_common.h"
  8. #include "hpm_soc.h"
  9. #include <rtthread.h>
  10. #include "riscv-stackframe.h"
  11. #define MCAUSE_INSTR_ADDR_MISALIGNED (0U) //!< Instruction Address misaligned
  12. #define MCAUSE_INSTR_ACCESS_FAULT (1U) //!< Instruction access fault
  13. #define MCAUSE_ILLEGAL_INSTR (2U) //!< Illegal instruction
  14. #define MCAUSE_BREAKPOINT (3U) //!< Breakpoint
  15. #define MCAUSE_LOAD_ADDR_MISALIGNED (4U) //!< Load address misaligned
  16. #define MCAUSE_LOAD_ACCESS_FAULT (5U) //!< Load access fault
  17. #define MCAUSE_STORE_AMO_ADDR_MISALIGNED (6U) //!< Store/AMO address misaligned
  18. #define MCAUSE_STORE_AMO_ACCESS_FAULT (7U) //!< Store/AMO access fault
  19. #define MCAUSE_ECALL_FROM_USER_MODE (8U) //!< Environment call from User mode
  20. #define MCAUSE_ECALL_FROM_SUPERVISOR_MODE (9U) //!< Environment call from Supervisor mode
  21. #define MCAUSE_ECALL_FROM_MACHINE_MODE (11U) //!< Environment call from machine mode
  22. #define MCAUSE_INSTR_PAGE_FAULT (12U) //!< Instruction page fault
  23. #define MCAUSE_LOAD_PAGE_FAULT (13) //!< Load page fault
  24. #define MCAUSE_STORE_AMO_PAGE_FAULT (15U) //!< Store/AMO page fault
  25. #define IRQ_S_SOFT 1
  26. #define IRQ_H_SOFT 2
  27. #define IRQ_M_SOFT 3
  28. #define IRQ_S_TIMER 5
  29. #define IRQ_H_TIMER 6
  30. #define IRQ_M_TIMER 7
  31. #define IRQ_S_EXT 9
  32. #define IRQ_H_EXT 10
  33. #define IRQ_M_EXT 11
  34. #define IRQ_COP 12
  35. #define IRQ_HOST 13
  36. typedef void (*isr_func_t)(void);
  37. static volatile rt_hw_stack_frame_t *s_stack_frame;
  38. static void rt_show_stack_frame(void);
  39. __attribute((weak)) void mchtmr_isr(void)
  40. {
  41. }
  42. __attribute__((weak)) void mswi_isr(void)
  43. {
  44. }
  45. __attribute__((weak)) void syscall_handler(uint32_t n, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3)
  46. {
  47. }
  48. uint32_t exception_handler(uint32_t cause, uint32_t epc)
  49. {
  50. /* Unhandled Trap */
  51. uint32_t mdcause = read_csr(CSR_MDCAUSE);
  52. uint32_t mtval = read_csr(CSR_MTVAL);
  53. switch (cause)
  54. {
  55. case MCAUSE_INSTR_ADDR_MISALIGNED:
  56. rt_kprintf("exception: instruction address was mis-aligned, mtval=0x%08x\n", mtval);
  57. break;
  58. case MCAUSE_INSTR_ACCESS_FAULT:
  59. rt_kprintf("exception: instruction access fault happened, mtval=0x%08x, epc=0x%08x\n", mtval, epc);
  60. switch (mdcause & 0x07)
  61. {
  62. case 1:
  63. rt_kprintf("mdcause: ECC/Parity error\r\n");
  64. break;
  65. case 2:
  66. rt_kprintf("mdcause: PMP instruction access violation \r\n");
  67. break;
  68. case 3:
  69. rt_kprintf("mdcause: BUS error\r\n");
  70. break;
  71. case 4:
  72. rt_kprintf("mdcause: PMP empty hole access \r\n");
  73. break;
  74. default:
  75. rt_kprintf("mdcause: reserved \r\n");
  76. break;
  77. }
  78. break;
  79. case MCAUSE_ILLEGAL_INSTR:
  80. rt_kprintf("exception: illegal instruction was met, mtval=0x%08x\n", mtval);
  81. switch (mdcause & 0x07)
  82. {
  83. case 0:
  84. rt_kprintf("mdcause: the actual faulting instruction is stored in the mtval CSR\r\n");
  85. break;
  86. case 1:
  87. rt_kprintf("mdcause: FP disabled exception \r\n");
  88. break;
  89. case 2:
  90. rt_kprintf("mdcause: ACE disabled exception \r\n");
  91. break;
  92. default:
  93. rt_kprintf("mdcause: reserved \r\n");
  94. break;
  95. }
  96. break;
  97. case MCAUSE_BREAKPOINT:
  98. rt_kprintf("exception: breakpoint was hit, mtval=0x%08x\n", mtval);
  99. break;
  100. case MCAUSE_LOAD_ADDR_MISALIGNED:
  101. rt_kprintf("exception: load address was mis-aligned, mtval=0x%08x\n", mtval);
  102. break;
  103. case MCAUSE_LOAD_ACCESS_FAULT:
  104. rt_kprintf("exception: load access fault happened, epc=%08x, mdcause=0x%x\n", epc, mdcause);
  105. switch (mdcause & 0x07)
  106. {
  107. case 1:
  108. rt_kprintf("mdcause: ECC/Parity error\r\n");
  109. break;
  110. case 2:
  111. rt_kprintf("mdcause: PMP instruction access violation \r\n");
  112. break;
  113. case 3:
  114. rt_kprintf("mdcause: BUS error\r\n");
  115. break;
  116. case 4:
  117. rt_kprintf("mdcause: Misaligned access \r\n");
  118. break;
  119. case 5:
  120. rt_kprintf("mdcause: PMP empty hole access \r\n");
  121. break;
  122. case 6:
  123. rt_kprintf("mdcause: PMA attribute inconsistency\r\n");
  124. break;
  125. default:
  126. rt_kprintf("mdcause: reserved \r\n");
  127. break;
  128. }
  129. break;
  130. case MCAUSE_STORE_AMO_ADDR_MISALIGNED:
  131. rt_kprintf("exception: store amo address was misaligned, epc=%08x\n", epc);
  132. break;
  133. case MCAUSE_STORE_AMO_ACCESS_FAULT:
  134. rt_kprintf("exception: store amo access fault happened, epc=%08x\n", epc);
  135. switch (mdcause & 0x07)
  136. {
  137. case 1:
  138. rt_kprintf("mdcause: ECC/Parity error\r\n");
  139. break;
  140. case 2:
  141. rt_kprintf("mdcause: PMP instruction access violation \r\n");
  142. break;
  143. case 3:
  144. rt_kprintf("mdcause: BUS error\r\n");
  145. break;
  146. case 4:
  147. rt_kprintf("mdcause: Misaligned access \r\n");
  148. break;
  149. case 5:
  150. rt_kprintf("mdcause: PMP empty hole access \r\n");
  151. break;
  152. case 6:
  153. rt_kprintf("mdcause: PMA attribute inconsistency\r\n");
  154. break;
  155. case 7:
  156. rt_kprintf("mdcause: PMA NAMO exception \r\n");
  157. default:
  158. rt_kprintf("mdcause: reserved \r\n");
  159. break;
  160. }
  161. break;
  162. default:
  163. rt_kprintf("Unknown exception happened, cause=%d\n", cause);
  164. break;
  165. }
  166. rt_show_stack_frame();
  167. while (1)
  168. {
  169. }
  170. }
  171. void trap_entry(rt_hw_stack_frame_t *stack_frame);
  172. void trap_entry(rt_hw_stack_frame_t *stack_frame)
  173. {
  174. uint32_t mcause = read_csr(CSR_MCAUSE);
  175. uint32_t mepc = read_csr(CSR_MEPC);
  176. uint32_t mstatus = read_csr(CSR_MSTATUS);
  177. s_stack_frame = stack_frame;
  178. #if SUPPORT_PFT_ARCH
  179. uint32_t mxstatus = read_csr(CSR_MXSTATUS);
  180. #endif
  181. #ifdef __riscv_dsp
  182. int ucode = read_csr(CSR_UCODE);
  183. #endif
  184. #ifdef __riscv_flen
  185. int fcsr = read_fcsr();
  186. #endif
  187. /* clobbers list for ecall */
  188. #ifdef __riscv_32e
  189. __asm volatile("" : : :"t0", "a0", "a1", "a2", "a3");
  190. #else
  191. __asm volatile("" : : :"a7", "a0", "a1", "a2", "a3");
  192. #endif
  193. /* Do your trap handling */
  194. uint32_t cause_type = mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK;
  195. uint32_t irq_index;
  196. if (mcause & CSR_MCAUSE_INTERRUPT_MASK)
  197. {
  198. switch (cause_type)
  199. {
  200. /* Machine timer interrupt */
  201. case IRQ_M_TIMER:
  202. mchtmr_isr();
  203. break;
  204. /* Machine EXT interrupt */
  205. case IRQ_M_EXT:
  206. /* Claim interrupt */
  207. irq_index = __plic_claim_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_M_MODE);
  208. /* Execute EXT interrupt handler */
  209. if (irq_index > 0)
  210. {
  211. ((isr_func_t) __vector_table[irq_index])();
  212. /* Complete interrupt */
  213. __plic_complete_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_M_MODE, irq_index);
  214. }
  215. break;
  216. /* Machine SWI interrupt */
  217. case IRQ_M_SOFT:
  218. mswi_isr();
  219. intc_m_complete_swi();
  220. break;
  221. }
  222. }
  223. else if (cause_type == MCAUSE_ECALL_FROM_MACHINE_MODE)
  224. {
  225. /* Machine Syscal call */
  226. __asm volatile(
  227. "mv a4, a3\n"
  228. "mv a3, a2\n"
  229. "mv a2, a1\n"
  230. "mv a1, a0\n"
  231. #ifdef __riscv_32e
  232. "mv a0, t0\n"
  233. #else
  234. "mv a0, a7\n"
  235. #endif
  236. "call syscall_handler\n"
  237. : : : "a4"
  238. );
  239. mepc += 4;
  240. }
  241. else
  242. {
  243. mepc = exception_handler(mcause, mepc);
  244. }
  245. /* Restore CSR */
  246. write_csr(CSR_MSTATUS, mstatus);
  247. write_csr(CSR_MEPC, mepc);
  248. #if SUPPORT_PFT_ARCH
  249. write_csr(CSR_MXSTATUS, mxstatus);
  250. #endif
  251. #ifdef __riscv_dsp
  252. write_csr(CSR_UCODE, ucode);
  253. #endif
  254. #ifdef __riscv_flen
  255. write_fcsr(fcsr);
  256. #endif
  257. }
  258. static void rt_show_stack_frame(void)
  259. {
  260. rt_kprintf("Stack frame:\r\n----------------------------------------\r\n");
  261. rt_kprintf("ra : 0x%08x\r\n", s_stack_frame->ra);
  262. rt_kprintf("mstatus : 0x%08x\r\n", read_csr(CSR_MSTATUS));
  263. rt_kprintf("t0 : 0x%08x\r\n", s_stack_frame->t0);
  264. rt_kprintf("t1 : 0x%08x\r\n", s_stack_frame->t1);
  265. rt_kprintf("t2 : 0x%08x\r\n", s_stack_frame->t2);
  266. rt_kprintf("a0 : 0x%08x\r\n", s_stack_frame->a0);
  267. rt_kprintf("a1 : 0x%08x\r\n", s_stack_frame->a1);
  268. rt_kprintf("a2 : 0x%08x\r\n", s_stack_frame->a2);
  269. rt_kprintf("a3 : 0x%08x\r\n", s_stack_frame->a3);
  270. rt_kprintf("a4 : 0x%08x\r\n", s_stack_frame->a4);
  271. rt_kprintf("a5 : 0x%08x\r\n", s_stack_frame->a5);
  272. rt_kprintf("a6 : 0x%08x\r\n", s_stack_frame->a6);
  273. rt_kprintf("a7 : 0x%08x\r\n", s_stack_frame->a7);
  274. rt_kprintf("t3 : 0x%08x\r\n", s_stack_frame->t3);
  275. rt_kprintf("t4 : 0x%08x\r\n", s_stack_frame->t4);
  276. rt_kprintf("t5 : 0x%08x\r\n", s_stack_frame->t5);
  277. rt_kprintf("t6 : 0x%08x\r\n", s_stack_frame->t6);
  278. }