os_cpu_a.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. #include "riscv_encoding.h"
  2. #include "cpufeature.h"
  3. #ifndef __riscv_32e
  4. #define portRegNum 32
  5. #else
  6. #define portRegNum 14
  7. #endif
  8. #define portCONTEXT_SIZE ( portRegNum * REGBYTES )
  9. .extern OSTCBCur
  10. .extern OSTCBHighRdy
  11. .extern xPortTaskSwitch
  12. .global prvPortStartFirstTask
  13. .global exc_entry
  14. .global irq_entry
  15. .global default_intexc_handler
  16. .global eclic_msip_handler
  17. .section .text.entry
  18. .align 8
  19. /**
  20. * \brief Global interrupt disabled
  21. * \details
  22. * This function disable global interrupt.
  23. * \remarks
  24. * - All the interrupt requests will be ignored by CPU.
  25. */
  26. .macro DISABLE_MIE
  27. csrc CSR_MSTATUS, MSTATUS_MIE
  28. .endm
  29. /**
  30. * \brief Macro for context save
  31. * \details
  32. * This macro save ABI defined caller saved registers in the stack.
  33. * \remarks
  34. * - This Macro could use to save context when you enter to interrupt
  35. * or exception
  36. */
  37. /* Save caller registers */
  38. .macro SAVE_CONTEXT
  39. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  40. #else
  41. csrrw sp, CSR_MSCRATCHCSWL, sp
  42. /* Allocate stack space for context saving */
  43. #ifndef __riscv_32e
  44. addi sp, sp, -20*REGBYTES
  45. #else
  46. addi sp, sp, -14*REGBYTES
  47. #endif /* __riscv_32e */
  48. STORE x1, 0*REGBYTES(sp)
  49. STORE x4, 1*REGBYTES(sp)
  50. STORE x5, 2*REGBYTES(sp)
  51. STORE x6, 3*REGBYTES(sp)
  52. STORE x7, 4*REGBYTES(sp)
  53. STORE x10, 5*REGBYTES(sp)
  54. STORE x11, 6*REGBYTES(sp)
  55. STORE x12, 7*REGBYTES(sp)
  56. STORE x13, 8*REGBYTES(sp)
  57. STORE x14, 9*REGBYTES(sp)
  58. STORE x15, 10*REGBYTES(sp)
  59. #ifndef __riscv_32e
  60. STORE x16, 14*REGBYTES(sp)
  61. STORE x17, 15*REGBYTES(sp)
  62. STORE x28, 16*REGBYTES(sp)
  63. STORE x29, 17*REGBYTES(sp)
  64. STORE x30, 18*REGBYTES(sp)
  65. STORE x31, 19*REGBYTES(sp)
  66. #endif /* __riscv_32e */
  67. #endif
  68. .endm
  69. /**
  70. * \brief Macro for restore caller registers
  71. * \details
  72. * This macro restore ABI defined caller saved registers from stack.
  73. * \remarks
  74. * - You could use this macro to restore context before you want return
  75. * from interrupt or exeception
  76. */
  77. /* Restore caller registers */
  78. .macro RESTORE_CONTEXT
  79. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  80. #else
  81. LOAD x1, 0*REGBYTES(sp)
  82. LOAD x4, 1*REGBYTES(sp)
  83. LOAD x5, 2*REGBYTES(sp)
  84. LOAD x6, 3*REGBYTES(sp)
  85. LOAD x7, 4*REGBYTES(sp)
  86. LOAD x10, 5*REGBYTES(sp)
  87. LOAD x11, 6*REGBYTES(sp)
  88. LOAD x12, 7*REGBYTES(sp)
  89. LOAD x13, 8*REGBYTES(sp)
  90. LOAD x14, 9*REGBYTES(sp)
  91. LOAD x15, 10*REGBYTES(sp)
  92. #ifndef __riscv_32e
  93. LOAD x16, 14*REGBYTES(sp)
  94. LOAD x17, 15*REGBYTES(sp)
  95. LOAD x28, 16*REGBYTES(sp)
  96. LOAD x29, 17*REGBYTES(sp)
  97. LOAD x30, 18*REGBYTES(sp)
  98. LOAD x31, 19*REGBYTES(sp)
  99. /* De-allocate the stack space */
  100. addi sp, sp, 20*REGBYTES
  101. #else
  102. /* De-allocate the stack space */
  103. addi sp, sp, 14*REGBYTES
  104. #endif /* __riscv_32e */
  105. csrrw sp, CSR_MSCRATCHCSWL, sp
  106. #endif
  107. .endm
  108. /**
  109. * \brief Macro for save necessary CSRs to stack
  110. * \details
  111. * This macro store MCAUSE, MEPC, MSUBM to stack.
  112. */
  113. .macro SAVE_CSR_CONTEXT
  114. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  115. #else
  116. /* Store CSR mcause to stack using pushmcause */
  117. csrrwi x0, CSR_PUSHMCAUSE, 11
  118. /* Store CSR mepc to stack using pushmepc */
  119. csrrwi x0, CSR_PUSHMEPC, 12
  120. /* Store CSR msub to stack using pushmsub */
  121. csrrwi x0, CSR_PUSHMSUBM, 13
  122. #endif
  123. .endm
  124. /**
  125. * \brief Macro for restore necessary CSRs from stack
  126. * \details
  127. * This macro restore MSUBM, MEPC, MCAUSE from stack.
  128. */
  129. .macro RESTORE_CSR_CONTEXT
  130. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  131. #else
  132. LOAD x5, 13*REGBYTES(sp)
  133. csrw CSR_MSUBM, x5
  134. LOAD x5, 12*REGBYTES(sp)
  135. csrw CSR_MEPC, x5
  136. LOAD x5, 11*REGBYTES(sp)
  137. csrw CSR_MCAUSE, x5
  138. #endif
  139. .endm
  140. /**
  141. * \brief Exception/NMI Entry
  142. * \details
  143. * This function provide common entry functions for exception/nmi.
  144. * \remarks
  145. * This function provide a default exception/nmi entry.
  146. * ABI defined caller save register and some CSR registers
  147. * to be saved before enter interrupt handler and be restored before return.
  148. */
  149. .section .text.trap
  150. /* In CLIC mode, the exeception entry must be 64bytes aligned */
  151. .align 6
  152. .type exc_entry, @function
  153. exc_entry:
  154. /* Save the caller saving registers (context) */
  155. SAVE_CONTEXT
  156. /* Save the necessary CSR registers */
  157. SAVE_CSR_CONTEXT
  158. /*
  159. * Set the exception handler function arguments
  160. * argument 1: mcause value
  161. * argument 2: current stack point(SP) value
  162. */
  163. csrr a0, mcause
  164. mv a1, sp
  165. /*
  166. * TODO: Call the exception handler function
  167. * By default, the function template is provided in
  168. * system_Device.c, you can adjust it as you want
  169. */
  170. call core_exception_handler
  171. /* Restore the necessary CSR registers */
  172. RESTORE_CSR_CONTEXT
  173. /* Restore the caller saving registers (context) */
  174. RESTORE_CONTEXT
  175. /* Return to regular code */
  176. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  177. csrrwi x0, CSR_POPXRET, 0
  178. #else
  179. mret
  180. #endif
  181. .size exc_entry, . - exc_entry
  182. /**
  183. * \brief Non-Vector Interrupt Entry
  184. * \details
  185. * This function provide common entry functions for handling
  186. * non-vector interrupts
  187. * \remarks
  188. * This function provide a default non-vector interrupt entry.
  189. * ABI defined caller save register and some CSR registers need
  190. * to be saved before enter interrupt handler and be restored before return.
  191. */
  192. .section .text.irq
  193. /* In CLIC mode, the interrupt entry must be 4bytes aligned */
  194. .align 2
  195. .type irq_entry, @function
  196. /* This label will be set to MTVT2 register */
  197. irq_entry:
  198. /* Save the caller saving registers (context) */
  199. SAVE_CONTEXT
  200. /* Save the necessary CSR registers */
  201. SAVE_CSR_CONTEXT
  202. /* This special CSR read/write operation, which is actually
  203. * claim the CLIC to find its pending highest ID, if the ID
  204. * is not 0, then automatically enable the mstatus.MIE, and
  205. * jump to its vector-entry-label, and update the link register
  206. */
  207. csrrw ra, CSR_JALMNXTI, ra
  208. /* Critical section with interrupts disabled */
  209. DISABLE_MIE
  210. /* Restore the necessary CSR registers */
  211. RESTORE_CSR_CONTEXT
  212. /* Restore the caller saving registers (context) */
  213. RESTORE_CONTEXT
  214. /* Return to regular code */
  215. #if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
  216. csrrwi x0, CSR_POPXRET, 0
  217. #else
  218. mret
  219. #endif
  220. .size irq_entry, . - irq_entry
  221. /* Default Handler for Exceptions / Interrupts */
  222. Undef_Handler:
  223. .type default_intexc_handler, @function
  224. default_intexc_handler:
  225. 1:
  226. j 1b
  227. .size default_intexc_handler, . - default_intexc_handler
  228. /* Start the first task. This also clears the bit that indicates the FPU is
  229. in use in case the FPU was used before the scheduler was started - which
  230. would otherwise result in the unnecessary leaving of space in the stack
  231. for lazy saving of FPU registers. */
  232. .align 3
  233. .type prvPortStartFirstTask, @function
  234. prvPortStartFirstTask:
  235. /* Setup Interrupt Stack using
  236. The stack that was used by main()
  237. before the scheduler is started is
  238. no longer required after the scheduler is started.
  239. Interrupt stack pointer is stored in CSR_MSCRATCH */
  240. la t0, _sp
  241. csrw CSR_MSCRATCH, t0
  242. LOAD sp, OSTCBHighRdy /* Load OSTCBHighRdy. */
  243. LOAD sp, 0x0(sp) /* Read sp from first TCB member */
  244. /* Pop PC from stack and set MEPC */
  245. LOAD t0, 0 * REGBYTES(sp)
  246. csrw CSR_MEPC, t0
  247. /* Pop mstatus from stack and set it */
  248. LOAD t0, (portRegNum - 1) * REGBYTES(sp)
  249. csrw CSR_MSTATUS, t0
  250. /* Interrupt still disable here */
  251. /* Restore Registers from Stack */
  252. LOAD x1, 1 * REGBYTES(sp) /* RA */
  253. LOAD x5, 2 * REGBYTES(sp)
  254. LOAD x6, 3 * REGBYTES(sp)
  255. LOAD x7, 4 * REGBYTES(sp)
  256. LOAD x8, 5 * REGBYTES(sp)
  257. LOAD x9, 6 * REGBYTES(sp)
  258. LOAD x10, 7 * REGBYTES(sp)
  259. LOAD x11, 8 * REGBYTES(sp)
  260. LOAD x12, 9 * REGBYTES(sp)
  261. LOAD x13, 10 * REGBYTES(sp)
  262. LOAD x14, 11 * REGBYTES(sp)
  263. LOAD x15, 12 * REGBYTES(sp)
  264. #ifndef __riscv_32e
  265. LOAD x16, 13 * REGBYTES(sp)
  266. LOAD x17, 14 * REGBYTES(sp)
  267. LOAD x18, 15 * REGBYTES(sp)
  268. LOAD x19, 16 * REGBYTES(sp)
  269. LOAD x20, 17 * REGBYTES(sp)
  270. LOAD x21, 18 * REGBYTES(sp)
  271. LOAD x22, 19 * REGBYTES(sp)
  272. LOAD x23, 20 * REGBYTES(sp)
  273. LOAD x24, 21 * REGBYTES(sp)
  274. LOAD x25, 22 * REGBYTES(sp)
  275. LOAD x26, 23 * REGBYTES(sp)
  276. LOAD x27, 24 * REGBYTES(sp)
  277. LOAD x28, 25 * REGBYTES(sp)
  278. LOAD x29, 26 * REGBYTES(sp)
  279. LOAD x30, 27 * REGBYTES(sp)
  280. LOAD x31, 28 * REGBYTES(sp)
  281. #endif
  282. addi sp, sp, portCONTEXT_SIZE
  283. mret
  284. .size prvPortStartFirstTask, . - prvPortStartFirstTask
  285. .section .text
  286. .align 2
  287. .type eclic_msip_handler, @function
  288. eclic_msip_handler:
  289. addi sp, sp, -portCONTEXT_SIZE
  290. STORE x1, 1 * REGBYTES(sp) /* RA */
  291. STORE x5, 2 * REGBYTES(sp)
  292. STORE x6, 3 * REGBYTES(sp)
  293. STORE x7, 4 * REGBYTES(sp)
  294. STORE x8, 5 * REGBYTES(sp)
  295. STORE x9, 6 * REGBYTES(sp)
  296. STORE x10, 7 * REGBYTES(sp)
  297. STORE x11, 8 * REGBYTES(sp)
  298. STORE x12, 9 * REGBYTES(sp)
  299. STORE x13, 10 * REGBYTES(sp)
  300. STORE x14, 11 * REGBYTES(sp)
  301. STORE x15, 12 * REGBYTES(sp)
  302. #ifndef __riscv_32e
  303. STORE x16, 13 * REGBYTES(sp)
  304. STORE x17, 14 * REGBYTES(sp)
  305. STORE x18, 15 * REGBYTES(sp)
  306. STORE x19, 16 * REGBYTES(sp)
  307. STORE x20, 17 * REGBYTES(sp)
  308. STORE x21, 18 * REGBYTES(sp)
  309. STORE x22, 19 * REGBYTES(sp)
  310. STORE x23, 20 * REGBYTES(sp)
  311. STORE x24, 21 * REGBYTES(sp)
  312. STORE x25, 22 * REGBYTES(sp)
  313. STORE x26, 23 * REGBYTES(sp)
  314. STORE x27, 24 * REGBYTES(sp)
  315. STORE x28, 25 * REGBYTES(sp)
  316. STORE x29, 26 * REGBYTES(sp)
  317. STORE x30, 27 * REGBYTES(sp)
  318. STORE x31, 28 * REGBYTES(sp)
  319. #endif
  320. /* Push mstatus to stack */
  321. csrr t0, CSR_MSTATUS
  322. STORE t0, (portRegNum - 1) * REGBYTES(sp)
  323. /* Push additional registers */
  324. /* Store sp to task stack */
  325. LOAD t0, OSTCBCur
  326. STORE sp, 0(t0)
  327. csrr t0, CSR_MEPC
  328. STORE t0, 0(sp)
  329. jal xPortTaskSwitch
  330. /* Switch task context */
  331. LOAD t0, OSTCBHighRdy /* Load OSTCBHighRdy. */
  332. LOAD sp, 0x0(t0) /* Read sp from first TCB member */
  333. /* Pop PC from stack and set MEPC */
  334. LOAD t0, 0 * REGBYTES(sp)
  335. csrw CSR_MEPC, t0
  336. /* Pop additional registers */
  337. /* Pop mstatus from stack and set it */
  338. LOAD t0, (portRegNum - 1) * REGBYTES(sp)
  339. csrw CSR_MSTATUS, t0
  340. /* Interrupt still disable here */
  341. /* Restore Registers from Stack */
  342. LOAD x1, 1 * REGBYTES(sp) /* RA */
  343. LOAD x5, 2 * REGBYTES(sp)
  344. LOAD x6, 3 * REGBYTES(sp)
  345. LOAD x7, 4 * REGBYTES(sp)
  346. LOAD x8, 5 * REGBYTES(sp)
  347. LOAD x9, 6 * REGBYTES(sp)
  348. LOAD x10, 7 * REGBYTES(sp)
  349. LOAD x11, 8 * REGBYTES(sp)
  350. LOAD x12, 9 * REGBYTES(sp)
  351. LOAD x13, 10 * REGBYTES(sp)
  352. LOAD x14, 11 * REGBYTES(sp)
  353. LOAD x15, 12 * REGBYTES(sp)
  354. #ifndef __riscv_32e
  355. LOAD x16, 13 * REGBYTES(sp)
  356. LOAD x17, 14 * REGBYTES(sp)
  357. LOAD x18, 15 * REGBYTES(sp)
  358. LOAD x19, 16 * REGBYTES(sp)
  359. LOAD x20, 17 * REGBYTES(sp)
  360. LOAD x21, 18 * REGBYTES(sp)
  361. LOAD x22, 19 * REGBYTES(sp)
  362. LOAD x23, 20 * REGBYTES(sp)
  363. LOAD x24, 21 * REGBYTES(sp)
  364. LOAD x25, 22 * REGBYTES(sp)
  365. LOAD x26, 23 * REGBYTES(sp)
  366. LOAD x27, 24 * REGBYTES(sp)
  367. LOAD x28, 25 * REGBYTES(sp)
  368. LOAD x29, 26 * REGBYTES(sp)
  369. LOAD x30, 27 * REGBYTES(sp)
  370. LOAD x31, 28 * REGBYTES(sp)
  371. #endif
  372. addi sp, sp, portCONTEXT_SIZE
  373. mret
  374. .size eclic_msip_handler, . - eclic_msip_handler