context_gcc.S 8.7 KB

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