context_gcc.S 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  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. * 2018-10-06 ZhaoXiaowei the first version
  9. * 2021-11-04 GuEe-GUI set sp with SP_ELx
  10. * 2021-12-28 GuEe-GUI add fpu and smp support
  11. */
  12. #include "rtconfig.h"
  13. #include "asm_fpu.h"
  14. #ifdef RT_USING_SMP
  15. #define rt_hw_interrupt_disable rt_hw_local_irq_disable
  16. #define rt_hw_interrupt_enable rt_hw_local_irq_enable
  17. #endif
  18. /*
  19. *enable gtimer
  20. */
  21. .globl rt_hw_gtimer_enable
  22. rt_hw_gtimer_enable:
  23. MOV X0,#1
  24. MSR CNTP_CTL_EL0,X0
  25. RET
  26. /*
  27. *disable gtimer
  28. */
  29. .globl rt_hw_gtimer_disable
  30. rt_hw_gtimer_disable:
  31. MSR CNTP_CTL_EL0,XZR
  32. RET
  33. /*
  34. *set gtimer CNTP_TVAL_EL0 value
  35. */
  36. .globl rt_hw_set_gtimer_val
  37. rt_hw_set_gtimer_val:
  38. MSR CNTP_TVAL_EL0,X0
  39. RET
  40. /*
  41. *get gtimer CNTP_TVAL_EL0 value
  42. */
  43. .globl rt_hw_get_gtimer_val
  44. rt_hw_get_gtimer_val:
  45. MRS X0,CNTP_TVAL_EL0
  46. RET
  47. .globl rt_hw_get_cntpct_val
  48. rt_hw_get_cntpct_val:
  49. MRS X0, CNTPCT_EL0
  50. RET
  51. /*
  52. *get gtimer frq value
  53. */
  54. .globl rt_hw_get_gtimer_frq
  55. rt_hw_get_gtimer_frq:
  56. MRS X0,CNTFRQ_EL0
  57. RET
  58. /*
  59. *set gtimer frq value (only in EL3)
  60. */
  61. .globl rt_hw_set_gtimer_frq
  62. rt_hw_set_gtimer_frq:
  63. MRS X1, CurrentEL
  64. CMP X1, 0xc
  65. BNE rt_hw_set_gtimer_frq_exit
  66. MSR CNTFRQ_EL0, X0
  67. MOV X0, XZR
  68. rt_hw_set_gtimer_frq_exit:
  69. RET
  70. .macro SAVE_CONTEXT
  71. /* Save the entire context. */
  72. SAVE_FPU SP
  73. STP X0, X1, [SP, #-0x10]!
  74. STP X2, X3, [SP, #-0x10]!
  75. STP X4, X5, [SP, #-0x10]!
  76. STP X6, X7, [SP, #-0x10]!
  77. STP X8, X9, [SP, #-0x10]!
  78. STP X10, X11, [SP, #-0x10]!
  79. STP X12, X13, [SP, #-0x10]!
  80. STP X14, X15, [SP, #-0x10]!
  81. STP X16, X17, [SP, #-0x10]!
  82. STP X18, X19, [SP, #-0x10]!
  83. STP X20, X21, [SP, #-0x10]!
  84. STP X22, X23, [SP, #-0x10]!
  85. STP X24, X25, [SP, #-0x10]!
  86. STP X26, X27, [SP, #-0x10]!
  87. STP X28, X29, [SP, #-0x10]!
  88. MRS X28, FPCR
  89. MRS X29, FPSR
  90. STP X28, X29, [SP, #-0x10]!
  91. STP X30, XZR, [SP, #-0x10]!
  92. MRS X0, CurrentEL
  93. CMP X0, 0xc
  94. B.EQ 3f
  95. CMP X0, 0x8
  96. B.EQ 2f
  97. CMP X0, 0x4
  98. B.EQ 1f
  99. B .
  100. 3:
  101. MRS X3, SPSR_EL3
  102. /* Save the ELR. */
  103. MRS X2, ELR_EL3
  104. B 0f
  105. 2:
  106. MRS X3, SPSR_EL2
  107. /* Save the ELR. */
  108. MRS X2, ELR_EL2
  109. B 0f
  110. 1:
  111. MRS X3, SPSR_EL1
  112. MRS X2, ELR_EL1
  113. B 0f
  114. 0:
  115. STP X2, X3, [SP, #-0x10]!
  116. MOV X0, SP /* Move SP into X0 for saving. */
  117. .endm
  118. .macro SAVE_CONTEXT_T
  119. /* Save the entire context. */
  120. SAVE_FPU SP
  121. STP X0, X1, [SP, #-0x10]!
  122. STP X2, X3, [SP, #-0x10]!
  123. STP X4, X5, [SP, #-0x10]!
  124. STP X6, X7, [SP, #-0x10]!
  125. STP X8, X9, [SP, #-0x10]!
  126. STP X10, X11, [SP, #-0x10]!
  127. STP X12, X13, [SP, #-0x10]!
  128. STP X14, X15, [SP, #-0x10]!
  129. STP X16, X17, [SP, #-0x10]!
  130. STP X18, X19, [SP, #-0x10]!
  131. STP X20, X21, [SP, #-0x10]!
  132. STP X22, X23, [SP, #-0x10]!
  133. STP X24, X25, [SP, #-0x10]!
  134. STP X26, X27, [SP, #-0x10]!
  135. STP X28, X29, [SP, #-0x10]!
  136. MRS X28, FPCR
  137. MRS X29, FPSR
  138. STP X28, X29, [SP, #-0x10]!
  139. STP X30, XZR, [SP, #-0x10]!
  140. MRS X0, CurrentEL
  141. CMP X0, 0xc
  142. B.EQ 3f
  143. CMP X0, 0x8
  144. B.EQ 2f
  145. CMP X0, 0x4
  146. B.EQ 1f
  147. B .
  148. 3:
  149. MOV X3, #((3 << 6) | 0x0d) /* EL3h */
  150. MOV X2, X30
  151. B 0f
  152. 2:
  153. MOV X3, #((3 << 6) | 0x09) /* EL2h */
  154. MOV X2, X30
  155. B 0f
  156. 1:
  157. MOV X3, #((3 << 6) | 0x05) /* EL1h */
  158. MOV X2, X30
  159. B 0f
  160. 0:
  161. STP X2, X3, [SP, #-0x10]!
  162. MOV X0, SP /* Move SP into X0 for saving. */
  163. .endm
  164. .macro RESTORE_CONTEXT
  165. /* Set the SP to point to the stack of the task being restored. */
  166. MOV SP, X0
  167. LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */
  168. MRS X0, CurrentEL
  169. CMP X0, 0xc
  170. B.EQ 3f
  171. CMP X0, 0x8
  172. B.EQ 2f
  173. CMP X0, 0x4
  174. B.EQ 1f
  175. B .
  176. 3:
  177. MSR SPSR_EL3, X3
  178. MSR ELR_EL3, X2
  179. B 0f
  180. 2:
  181. MSR SPSR_EL2, X3
  182. MSR ELR_EL2, X2
  183. B 0f
  184. 1:
  185. MSR SPSR_EL1, X3
  186. MSR ELR_EL1, X2
  187. B 0f
  188. 0:
  189. LDP X30, XZR, [SP], #0x10
  190. LDP X28, X29, [SP], #0x10
  191. MSR FPCR, X28
  192. MSR FPSR, X29
  193. LDP X28, X29, [SP], #0x10
  194. LDP X26, X27, [SP], #0x10
  195. LDP X24, X25, [SP], #0x10
  196. LDP X22, X23, [SP], #0x10
  197. LDP X20, X21, [SP], #0x10
  198. LDP X18, X19, [SP], #0x10
  199. LDP X16, X17, [SP], #0x10
  200. LDP X14, X15, [SP], #0x10
  201. LDP X12, X13, [SP], #0x10
  202. LDP X10, X11, [SP], #0x10
  203. LDP X8, X9, [SP], #0x10
  204. LDP X6, X7, [SP], #0x10
  205. LDP X4, X5, [SP], #0x10
  206. LDP X2, X3, [SP], #0x10
  207. LDP X0, X1, [SP], #0x10
  208. RESTORE_FPU SP
  209. ERET
  210. .endm
  211. .text
  212. /*
  213. * rt_base_t rt_hw_interrupt_disable();
  214. */
  215. .globl rt_hw_interrupt_disable
  216. rt_hw_interrupt_disable:
  217. MRS X0, DAIF
  218. MSR DAIFSet, #3
  219. DSB SY
  220. RET
  221. /*
  222. * void rt_hw_interrupt_enable(rt_base_t level);
  223. */
  224. .globl rt_hw_interrupt_enable
  225. rt_hw_interrupt_enable:
  226. DSB SY
  227. MOV X1, #0xC0
  228. ANDS X0, X0, X1
  229. B.NE rt_hw_interrupt_enable_exit
  230. MSR DAIFClr, #3
  231. rt_hw_interrupt_enable_exit:
  232. RET
  233. /*
  234. * #ifdef RT_USING_SMP
  235. * void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread);
  236. * #else
  237. * void rt_hw_context_switch_to(rt_ubase_t to);
  238. * #endif
  239. * X0 --> to
  240. * X1 --> to_thread
  241. */
  242. .globl rt_hw_context_switch_to
  243. rt_hw_context_switch_to:
  244. #ifdef RT_USING_SMP
  245. STR X0, [SP, #-0x8]!
  246. MOV X0, X1
  247. BL rt_cpus_lock_status_restore
  248. LDR X0, [SP], #0x8
  249. #endif /*RT_USING_SMP*/
  250. LDR X0, [X0]
  251. RESTORE_CONTEXT
  252. .text
  253. /*
  254. * #ifdef RT_USING_SMP
  255. * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
  256. * #else
  257. * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
  258. * #endif
  259. * X0 --> from
  260. * X1 --> to
  261. * X2 --> to_thread
  262. */
  263. .globl rt_hw_context_switch
  264. rt_hw_context_switch:
  265. #ifdef RT_USING_SMP
  266. STP X0, X1, [SP, #-0x10]!
  267. STR X30, [SP, #-0x8]!
  268. MOV X0, X2
  269. BL rt_cpus_lock_status_restore
  270. LDR X30, [SP], #0x8
  271. LDP X0, X1, [SP], #0x10
  272. #endif /*RT_USING_SMP*/
  273. MOV X8,X0
  274. MOV X9,X1
  275. SAVE_CONTEXT_T
  276. STR X0, [X8] // store sp in preempted tasks TCB
  277. LDR X0, [X9] // get new task stack pointer
  278. RESTORE_CONTEXT
  279. /*
  280. * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
  281. */
  282. .globl rt_thread_switch_interrupt_flag
  283. .globl rt_interrupt_from_thread
  284. .globl rt_interrupt_to_thread
  285. .globl rt_hw_context_switch_interrupt
  286. rt_hw_context_switch_interrupt:
  287. #ifdef RT_USING_SMP
  288. /* x0 = context */
  289. /* x1 = &current_thread->sp */
  290. /* x2 = &to_thread->sp, */
  291. /* x3 = to_thread TCB */
  292. STR X0, [X1]
  293. LDR X0, [x2]
  294. MOV SP, X0
  295. MOV X0, X3
  296. BL rt_cpus_lock_status_restore
  297. MOV X0, SP
  298. RESTORE_CONTEXT
  299. #else
  300. LDR X2, =rt_thread_switch_interrupt_flag
  301. LDR X3, [X2]
  302. CMP X3, #1
  303. B.EQ _reswitch
  304. LDR X4, =rt_interrupt_from_thread // set rt_interrupt_from_thread
  305. MOV X3, #1 // set rt_thread_switch_interrupt_flag to 1
  306. STR X0, [X4]
  307. STR X3, [X2]
  308. _reswitch:
  309. LDR X2, =rt_interrupt_to_thread // set rt_interrupt_to_thread
  310. STR X1, [X2]
  311. RET
  312. #endif
  313. .text
  314. // -- Exception handlers ----------------------------------
  315. .align 8
  316. .globl vector_fiq
  317. vector_fiq:
  318. SAVE_CONTEXT
  319. STP X0, X1, [SP, #-0x10]!
  320. BL rt_hw_trap_fiq
  321. LDP X0, X1, [SP], #0x10
  322. RESTORE_CONTEXT
  323. .globl rt_interrupt_enter
  324. .globl rt_interrupt_leave
  325. .globl rt_thread_switch_interrupt_flag
  326. .globl rt_interrupt_from_thread
  327. .globl rt_interrupt_to_thread
  328. // -------------------------------------------------------------------
  329. .align 8
  330. .globl vector_irq
  331. vector_irq:
  332. SAVE_CONTEXT
  333. STP X0, X1, [SP, #-0x10]!
  334. BL rt_interrupt_enter
  335. BL rt_hw_trap_irq
  336. BL rt_interrupt_leave
  337. LDP X0, X1, [SP], #0x10
  338. #ifdef RT_USING_SMP
  339. /* Never reture If can switch */
  340. BL rt_scheduler_do_irq_switch
  341. MOV X0, SP
  342. #endif
  343. // if rt_thread_switch_interrupt_flag set, jump to
  344. // rt_hw_context_switch_interrupt_do and don't return
  345. LDR X1, =rt_thread_switch_interrupt_flag
  346. LDR X2, [X1]
  347. CMP X2, #1
  348. B.NE vector_irq_exit
  349. MOV X2, #0 // clear flag
  350. STR X2, [X1]
  351. LDR X3, =rt_interrupt_from_thread
  352. LDR X4, [X3]
  353. STR x0, [X4] // store sp in preempted tasks's TCB
  354. LDR x3, =rt_interrupt_to_thread
  355. LDR X4, [X3]
  356. LDR x0, [X4] // get new task's stack pointer
  357. vector_irq_exit:
  358. RESTORE_CONTEXT
  359. // -------------------------------------------------
  360. .align 8
  361. .globl vector_error
  362. vector_error:
  363. SAVE_CONTEXT
  364. BL rt_hw_trap_error
  365. B .