context_gcc.S 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /*
  2. * Copyright (c) 2006-2020, 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. */
  10. /*
  11. *enable gtimer
  12. */
  13. .globl rt_hw_gtimer_enable
  14. rt_hw_gtimer_enable:
  15. MOV X0,#1
  16. MSR CNTP_CTL_EL0,X0
  17. RET
  18. /*
  19. *set gtimer CNTP_TVAL_EL0 value
  20. */
  21. .globl rt_hw_set_gtimer_val
  22. rt_hw_set_gtimer_val:
  23. MSR CNTP_TVAL_EL0,X0
  24. RET
  25. /*
  26. *get gtimer CNTP_TVAL_EL0 value
  27. */
  28. .globl rt_hw_get_gtimer_val
  29. rt_hw_get_gtimer_val:
  30. MRS X0,CNTP_TVAL_EL0
  31. RET
  32. .globl rt_hw_get_cntpct_val
  33. rt_hw_get_cntpct_val:
  34. MRS X0, CNTPCT_EL0
  35. RET
  36. /*
  37. *get gtimer frq value
  38. */
  39. .globl rt_hw_get_gtimer_frq
  40. rt_hw_get_gtimer_frq:
  41. MRS X0,CNTFRQ_EL0
  42. RET
  43. .macro SAVE_CONTEXT
  44. /* Switch to use the EL0 stack pointer. */
  45. MSR SPSEL, #0
  46. /* Save the entire context. */
  47. STP X0, X1, [SP, #-0x10]!
  48. STP X2, X3, [SP, #-0x10]!
  49. STP X4, X5, [SP, #-0x10]!
  50. STP X6, X7, [SP, #-0x10]!
  51. STP X8, X9, [SP, #-0x10]!
  52. STP X10, X11, [SP, #-0x10]!
  53. STP X12, X13, [SP, #-0x10]!
  54. STP X14, X15, [SP, #-0x10]!
  55. STP X16, X17, [SP, #-0x10]!
  56. STP X18, X19, [SP, #-0x10]!
  57. STP X20, X21, [SP, #-0x10]!
  58. STP X22, X23, [SP, #-0x10]!
  59. STP X24, X25, [SP, #-0x10]!
  60. STP X26, X27, [SP, #-0x10]!
  61. STP X28, X29, [SP, #-0x10]!
  62. STP X30, XZR, [SP, #-0x10]!
  63. MRS X0, CurrentEL
  64. CMP X0, 0xc
  65. B.EQ 3f
  66. CMP X0, 0x8
  67. B.EQ 2f
  68. CMP X0, 0x4
  69. B.EQ 1f
  70. B .
  71. 3:
  72. MRS X3, SPSR_EL3
  73. /* Save the ELR. */
  74. MRS X2, ELR_EL3
  75. B 0f
  76. 2:
  77. MRS X3, SPSR_EL2
  78. /* Save the ELR. */
  79. MRS X2, ELR_EL2
  80. B 0f
  81. 1:
  82. MRS X3, SPSR_EL1
  83. MRS X2, ELR_EL1
  84. B 0f
  85. 0:
  86. STP X2, X3, [SP, #-0x10]!
  87. MOV X0, SP /* Move SP into X0 for saving. */
  88. /* Switch to use the ELx stack pointer. */
  89. MSR SPSEL, #1
  90. .endm
  91. .macro SAVE_CONTEXT_T
  92. /* Switch to use the EL0 stack pointer. */
  93. MSR SPSEL, #0
  94. /* Save the entire context. */
  95. STP X0, X1, [SP, #-0x10]!
  96. STP X2, X3, [SP, #-0x10]!
  97. STP X4, X5, [SP, #-0x10]!
  98. STP X6, X7, [SP, #-0x10]!
  99. STP X8, X9, [SP, #-0x10]!
  100. STP X10, X11, [SP, #-0x10]!
  101. STP X12, X13, [SP, #-0x10]!
  102. STP X14, X15, [SP, #-0x10]!
  103. STP X16, X17, [SP, #-0x10]!
  104. STP X18, X19, [SP, #-0x10]!
  105. STP X20, X21, [SP, #-0x10]!
  106. STP X22, X23, [SP, #-0x10]!
  107. STP X24, X25, [SP, #-0x10]!
  108. STP X26, X27, [SP, #-0x10]!
  109. STP X28, X29, [SP, #-0x10]!
  110. STP X30, XZR, [SP, #-0x10]!
  111. MRS X0, CurrentEL
  112. CMP X0, 0xc
  113. B.EQ 3f
  114. CMP X0, 0x8
  115. B.EQ 2f
  116. CMP X0, 0x4
  117. B.EQ 1f
  118. B .
  119. 3:
  120. MRS X3, SPSR_EL3
  121. MOV X2, X30
  122. B 0f
  123. 2:
  124. MRS X3, SPSR_EL2
  125. MOV X2, X30
  126. B 0f
  127. 1:
  128. MRS X3, SPSR_EL1
  129. MOV X2, X30
  130. B 0f
  131. 0:
  132. STP X2, X3, [SP, #-0x10]!
  133. MOV X0, SP /* Move SP into X0 for saving. */
  134. /* Switch to use the ELx stack pointer. */
  135. MSR SPSEL, #1
  136. .endm
  137. .macro RESTORE_CONTEXT
  138. /* Switch to use the EL0 stack pointer. */
  139. MSR SPSEL, #0
  140. /* Set the SP to point to the stack of the task being restored. */
  141. MOV SP, X0
  142. LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */
  143. MRS X0, CurrentEL
  144. CMP X0, 0xc
  145. B.EQ 3f
  146. CMP X0, 0x8
  147. B.EQ 2f
  148. CMP X0, 0x4
  149. B.EQ 1f
  150. B .
  151. 3:
  152. MSR SPSR_EL3, X3
  153. MSR ELR_EL3, X2
  154. B 0f
  155. 2:
  156. MSR SPSR_EL2, X3
  157. MSR ELR_EL2, X2
  158. B 0f
  159. 1:
  160. MSR SPSR_EL1, X3
  161. MSR ELR_EL1, X2
  162. B 0f
  163. 0:
  164. LDP X30, XZR, [SP], #0x10
  165. LDP X28, X29, [SP], #0x10
  166. LDP X26, X27, [SP], #0x10
  167. LDP X24, X25, [SP], #0x10
  168. LDP X22, X23, [SP], #0x10
  169. LDP X20, X21, [SP], #0x10
  170. LDP X18, X19, [SP], #0x10
  171. LDP X16, X17, [SP], #0x10
  172. LDP X14, X15, [SP], #0x10
  173. LDP X12, X13, [SP], #0x10
  174. LDP X10, X11, [SP], #0x10
  175. LDP X8, X9, [SP], #0x10
  176. LDP X6, X7, [SP], #0x10
  177. LDP X4, X5, [SP], #0x10
  178. LDP X2, X3, [SP], #0x10
  179. LDP X0, X1, [SP], #0x10
  180. /* Switch to use the ELx stack pointer. _RB_ Might not be required. */
  181. MSR SPSEL, #1
  182. ERET
  183. .endm
  184. .text
  185. /*
  186. * rt_base_t rt_hw_interrupt_disable();
  187. */
  188. .globl rt_hw_interrupt_disable
  189. rt_hw_interrupt_disable:
  190. MRS X0, DAIF
  191. MSR DAIFSet, #3
  192. DSB SY
  193. RET
  194. /*
  195. * void rt_hw_interrupt_enable(rt_base_t level);
  196. */
  197. .globl rt_hw_interrupt_enable
  198. rt_hw_interrupt_enable:
  199. DSB SY
  200. MOV X1, #0xC0
  201. ANDS X0, X0, X1
  202. B.NE rt_hw_interrupt_enable_exit
  203. MSR DAIFClr, #3
  204. rt_hw_interrupt_enable_exit:
  205. RET
  206. /*
  207. * void rt_hw_context_switch_to(rt_ubase_t to);
  208. * r0 --> to
  209. */
  210. .globl rt_hw_context_switch_to
  211. rt_hw_context_switch_to:
  212. LDR X0, [X0]
  213. RESTORE_CONTEXT
  214. .text
  215. /*
  216. * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
  217. * r0 --> from
  218. * r1 --> to
  219. */
  220. .globl rt_hw_context_switch
  221. rt_hw_context_switch:
  222. MOV X8,X0
  223. MOV X9,X1
  224. SAVE_CONTEXT_T
  225. STR X0, [X8] // store sp in preempted tasks TCB
  226. LDR X0, [X9] // get new task stack pointer
  227. RESTORE_CONTEXT
  228. /*
  229. * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
  230. */
  231. .globl rt_thread_switch_interrupt_flag
  232. .globl rt_interrupt_from_thread
  233. .globl rt_interrupt_to_thread
  234. .globl rt_hw_context_switch_interrupt
  235. rt_hw_context_switch_interrupt:
  236. ADR X2, rt_thread_switch_interrupt_flag
  237. LDR X3, [X2]
  238. CMP X3, #1
  239. B.EQ _reswitch
  240. ADR X4, rt_interrupt_from_thread // set rt_interrupt_from_thread
  241. MOV X3, #1 // set rt_thread_switch_interrupt_flag to 1
  242. STR X0, [X4]
  243. STR X3, [X2]
  244. _reswitch:
  245. ADR X2, rt_interrupt_to_thread // set rt_interrupt_to_thread
  246. STR X1, [X2]
  247. RET
  248. .text
  249. // -- Exception handlers ----------------------------------
  250. .align 8
  251. .globl vector_fiq
  252. vector_fiq:
  253. SAVE_CONTEXT
  254. STP X0, X1, [SP, #-0x10]!
  255. BL rt_hw_trap_fiq
  256. LDP X0, X1, [SP], #0x10
  257. RESTORE_CONTEXT
  258. .globl rt_interrupt_enter
  259. .globl rt_interrupt_leave
  260. .globl rt_thread_switch_interrupt_flag
  261. .globl rt_interrupt_from_thread
  262. .globl rt_interrupt_to_thread
  263. // -------------------------------------------------------------------
  264. .align 8
  265. .globl vector_irq
  266. vector_irq:
  267. SAVE_CONTEXT
  268. STP X0, X1, [SP, #-0x10]!
  269. BL rt_interrupt_enter
  270. BL rt_hw_trap_irq
  271. BL rt_interrupt_leave
  272. LDP X0, X1, [SP], #0x10
  273. // if rt_thread_switch_interrupt_flag set, jump to
  274. // rt_hw_context_switch_interrupt_do and don't return
  275. ADR X1, rt_thread_switch_interrupt_flag
  276. LDR X2, [X1]
  277. CMP X2, #1
  278. B.NE vector_irq_exit
  279. MOV X2, #0 // clear flag
  280. STR X2, [X1]
  281. ADR X3, rt_interrupt_from_thread
  282. LDR X4, [X3]
  283. STR x0, [X4] // store sp in preempted tasks's TCB
  284. ADR x3, rt_interrupt_to_thread
  285. LDR X4, [X3]
  286. LDR x0, [X4] // get new task's stack pointer
  287. vector_irq_exit:
  288. RESTORE_CONTEXT
  289. // -------------------------------------------------
  290. .align 8
  291. .globl vector_error
  292. vector_error:
  293. SAVE_CONTEXT
  294. BL rt_hw_trap_error
  295. B .