context_gcc.S 6.8 KB

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