portASM.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /*
  2. * FreeRTOS Kernel <DEVELOPMENT BRANCH>
  3. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * SPDX-License-Identifier: MIT
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  8. * this software and associated documentation files (the "Software"), to deal in
  9. * the Software without restriction, including without limitation the rights to
  10. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  11. * the Software, and to permit persons to whom the Software is furnished to do so,
  12. * subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in all
  15. * copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  19. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  20. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  21. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. *
  24. * https://www.FreeRTOS.org
  25. * https://github.com/FreeRTOS
  26. *
  27. */
  28. .text
  29. /* Variables and functions. */
  30. .extern ullMaxAPIPriorityMask
  31. .extern pxCurrentTCB
  32. .extern vTaskSwitchContext
  33. .extern vApplicationIRQHandler
  34. .extern ullPortInterruptNesting
  35. .extern ullPortTaskHasFPUContext
  36. .extern ullCriticalNesting
  37. .extern ullPortYieldRequired
  38. .extern ullICCEOIR
  39. .extern ullICCIAR
  40. .extern _freertos_vector_table
  41. .global FreeRTOS_IRQ_Handler
  42. .global FreeRTOS_SWI_Handler
  43. .global vPortRestoreTaskContext
  44. .macro portSAVE_CONTEXT
  45. /* Switch to use the EL0 stack pointer. */
  46. MSR SPSEL, #0
  47. /* Save the entire context. */
  48. STP X0, X1, [SP, #-0x10]!
  49. STP X2, X3, [SP, #-0x10]!
  50. STP X4, X5, [SP, #-0x10]!
  51. STP X6, X7, [SP, #-0x10]!
  52. STP X8, X9, [SP, #-0x10]!
  53. STP X10, X11, [SP, #-0x10]!
  54. STP X12, X13, [SP, #-0x10]!
  55. STP X14, X15, [SP, #-0x10]!
  56. STP X16, X17, [SP, #-0x10]!
  57. STP X18, X19, [SP, #-0x10]!
  58. STP X20, X21, [SP, #-0x10]!
  59. STP X22, X23, [SP, #-0x10]!
  60. STP X24, X25, [SP, #-0x10]!
  61. STP X26, X27, [SP, #-0x10]!
  62. STP X28, X29, [SP, #-0x10]!
  63. STP X30, XZR, [SP, #-0x10]!
  64. /* Save the SPSR. */
  65. #if defined( GUEST )
  66. MRS X3, SPSR_EL1
  67. MRS X2, ELR_EL1
  68. #else
  69. MRS X3, SPSR_EL3
  70. /* Save the ELR. */
  71. MRS X2, ELR_EL3
  72. #endif
  73. STP X2, X3, [SP, #-0x10]!
  74. /* Save the critical section nesting depth. */
  75. LDR X0, ullCriticalNestingConst
  76. LDR X3, [X0]
  77. /* Save the FPU context indicator. */
  78. LDR X0, ullPortTaskHasFPUContextConst
  79. LDR X2, [X0]
  80. /* Save the FPU context, if any (32 128-bit registers). */
  81. CMP X2, #0
  82. B.EQ 1f
  83. STP Q0, Q1, [SP,#-0x20]!
  84. STP Q2, Q3, [SP,#-0x20]!
  85. STP Q4, Q5, [SP,#-0x20]!
  86. STP Q6, Q7, [SP,#-0x20]!
  87. STP Q8, Q9, [SP,#-0x20]!
  88. STP Q10, Q11, [SP,#-0x20]!
  89. STP Q12, Q13, [SP,#-0x20]!
  90. STP Q14, Q15, [SP,#-0x20]!
  91. STP Q16, Q17, [SP,#-0x20]!
  92. STP Q18, Q19, [SP,#-0x20]!
  93. STP Q20, Q21, [SP,#-0x20]!
  94. STP Q22, Q23, [SP,#-0x20]!
  95. STP Q24, Q25, [SP,#-0x20]!
  96. STP Q26, Q27, [SP,#-0x20]!
  97. STP Q28, Q29, [SP,#-0x20]!
  98. STP Q30, Q31, [SP,#-0x20]!
  99. 1:
  100. /* Store the critical nesting count and FPU context indicator. */
  101. STP X2, X3, [SP, #-0x10]!
  102. LDR X0, pxCurrentTCBConst
  103. LDR X1, [X0]
  104. MOV X0, SP /* Move SP into X0 for saving. */
  105. STR X0, [X1]
  106. /* Switch to use the ELx stack pointer. */
  107. MSR SPSEL, #1
  108. .endm
  109. ; /**********************************************************************/
  110. .macro portRESTORE_CONTEXT
  111. /* Switch to use the EL0 stack pointer. */
  112. MSR SPSEL, #0
  113. /* Set the SP to point to the stack of the task being restored. */
  114. LDR X0, pxCurrentTCBConst
  115. LDR X1, [X0]
  116. LDR X0, [X1]
  117. MOV SP, X0
  118. LDP X2, X3, [SP], #0x10 /* Critical nesting and FPU context. */
  119. /* Set the PMR register to be correct for the current critical nesting
  120. depth. */
  121. LDR X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */
  122. MOV X1, #255 /* X1 holds the unmask value. */
  123. LDR X4, ullICCPMRConst /* X4 holds the address of the ICCPMR constant. */
  124. CMP X3, #0
  125. LDR X5, [X4] /* X5 holds the address of the ICCPMR register. */
  126. B.EQ 1f
  127. LDR X6, ullMaxAPIPriorityMaskConst
  128. LDR X1, [X6] /* X1 holds the mask value. */
  129. 1:
  130. STR W1, [X5] /* Write the mask value to ICCPMR. */
  131. DSB SY /* _RB_Barriers probably not required here. */
  132. ISB SY
  133. STR X3, [X0] /* Restore the task's critical nesting count. */
  134. /* Restore the FPU context indicator. */
  135. LDR X0, ullPortTaskHasFPUContextConst
  136. STR X2, [X0]
  137. /* Restore the FPU context, if any. */
  138. CMP X2, #0
  139. B.EQ 1f
  140. LDP Q30, Q31, [SP], #0x20
  141. LDP Q28, Q29, [SP], #0x20
  142. LDP Q26, Q27, [SP], #0x20
  143. LDP Q24, Q25, [SP], #0x20
  144. LDP Q22, Q23, [SP], #0x20
  145. LDP Q20, Q21, [SP], #0x20
  146. LDP Q18, Q19, [SP], #0x20
  147. LDP Q16, Q17, [SP], #0x20
  148. LDP Q14, Q15, [SP], #0x20
  149. LDP Q12, Q13, [SP], #0x20
  150. LDP Q10, Q11, [SP], #0x20
  151. LDP Q8, Q9, [SP], #0x20
  152. LDP Q6, Q7, [SP], #0x20
  153. LDP Q4, Q5, [SP], #0x20
  154. LDP Q2, Q3, [SP], #0x20
  155. LDP Q0, Q1, [SP], #0x20
  156. 1:
  157. LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */
  158. #if defined( GUEST )
  159. /* Restore the SPSR. */
  160. MSR SPSR_EL1, X3
  161. /* Restore the ELR. */
  162. MSR ELR_EL1, X2
  163. #else
  164. /* Restore the SPSR. */
  165. MSR SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */
  166. /* Restore the ELR. */
  167. MSR ELR_EL3, X2
  168. #endif
  169. LDP X30, XZR, [SP], #0x10
  170. LDP X28, X29, [SP], #0x10
  171. LDP X26, X27, [SP], #0x10
  172. LDP X24, X25, [SP], #0x10
  173. LDP X22, X23, [SP], #0x10
  174. LDP X20, X21, [SP], #0x10
  175. LDP X18, X19, [SP], #0x10
  176. LDP X16, X17, [SP], #0x10
  177. LDP X14, X15, [SP], #0x10
  178. LDP X12, X13, [SP], #0x10
  179. LDP X10, X11, [SP], #0x10
  180. LDP X8, X9, [SP], #0x10
  181. LDP X6, X7, [SP], #0x10
  182. LDP X4, X5, [SP], #0x10
  183. LDP X2, X3, [SP], #0x10
  184. LDP X0, X1, [SP], #0x10
  185. /* Switch to use the ELx stack pointer. _RB_ Might not be required. */
  186. MSR SPSEL, #1
  187. ERET
  188. .endm
  189. /******************************************************************************
  190. * FreeRTOS_SWI_Handler handler is used to perform a context switch.
  191. *****************************************************************************/
  192. .align 8
  193. .type FreeRTOS_SWI_Handler, %function
  194. FreeRTOS_SWI_Handler:
  195. /* Save the context of the current task and select a new task to run. */
  196. portSAVE_CONTEXT
  197. #if defined( GUEST )
  198. MRS X0, ESR_EL1
  199. #else
  200. MRS X0, ESR_EL3
  201. #endif
  202. LSR X1, X0, #26
  203. #if defined( GUEST )
  204. CMP X1, #0x15 /* 0x15 = SVC instruction. */
  205. #else
  206. CMP X1, #0x17 /* 0x17 = SMC instruction. */
  207. #endif
  208. B.NE FreeRTOS_Abort
  209. BL vTaskSwitchContext
  210. portRESTORE_CONTEXT
  211. FreeRTOS_Abort:
  212. /* Full ESR is in X0, exception class code is in X1. */
  213. B .
  214. /******************************************************************************
  215. * vPortRestoreTaskContext is used to start the scheduler.
  216. *****************************************************************************/
  217. .align 8
  218. .type vPortRestoreTaskContext, %function
  219. vPortRestoreTaskContext:
  220. .set freertos_vector_base, _freertos_vector_table
  221. /* Install the FreeRTOS interrupt handlers. */
  222. LDR X1, =freertos_vector_base
  223. #if defined( GUEST )
  224. MSR VBAR_EL1, X1
  225. #else
  226. MSR VBAR_EL3, X1
  227. #endif
  228. DSB SY
  229. ISB SY
  230. /* Start the first task. */
  231. portRESTORE_CONTEXT
  232. /******************************************************************************
  233. * FreeRTOS_IRQ_Handler handles IRQ entry and exit.
  234. *****************************************************************************/
  235. .align 8
  236. .type FreeRTOS_IRQ_Handler, %function
  237. FreeRTOS_IRQ_Handler:
  238. /* Save volatile registers. */
  239. STP X0, X1, [SP, #-0x10]!
  240. STP X2, X3, [SP, #-0x10]!
  241. STP X4, X5, [SP, #-0x10]!
  242. STP X6, X7, [SP, #-0x10]!
  243. STP X8, X9, [SP, #-0x10]!
  244. STP X10, X11, [SP, #-0x10]!
  245. STP X12, X13, [SP, #-0x10]!
  246. STP X14, X15, [SP, #-0x10]!
  247. STP X16, X17, [SP, #-0x10]!
  248. STP X18, X19, [SP, #-0x10]!
  249. STP X29, X30, [SP, #-0x10]!
  250. /* Save the SPSR and ELR. */
  251. #if defined( GUEST )
  252. MRS X3, SPSR_EL1
  253. MRS X2, ELR_EL1
  254. #else
  255. MRS X3, SPSR_EL3
  256. MRS X2, ELR_EL3
  257. #endif
  258. STP X2, X3, [SP, #-0x10]!
  259. /* Increment the interrupt nesting counter. */
  260. LDR X5, ullPortInterruptNestingConst
  261. LDR X1, [X5] /* Old nesting count in X1. */
  262. ADD X6, X1, #1
  263. STR X6, [X5] /* Address of nesting count variable in X5. */
  264. /* Maintain the interrupt nesting information across the function call. */
  265. STP X1, X5, [SP, #-0x10]!
  266. /* Read value from the interrupt acknowledge register, which is stored in W0
  267. for future parameter and interrupt clearing use. */
  268. LDR X2, ullICCIARConst
  269. LDR X3, [X2]
  270. LDR W0, [X3] /* ICCIAR in W0 as parameter. */
  271. /* Maintain the ICCIAR value across the function call. */
  272. STP X0, X1, [SP, #-0x10]!
  273. /* Call the C handler. */
  274. BL vApplicationIRQHandler
  275. /* Disable interrupts. */
  276. MSR DAIFSET, #2
  277. DSB SY
  278. ISB SY
  279. /* Restore the ICCIAR value. */
  280. LDP X0, X1, [SP], #0x10
  281. /* End IRQ processing by writing ICCIAR to the EOI register. */
  282. LDR X4, ullICCEOIRConst
  283. LDR X4, [X4]
  284. STR W0, [X4]
  285. /* Restore the critical nesting count. */
  286. LDP X1, X5, [SP], #0x10
  287. STR X1, [X5]
  288. /* Has interrupt nesting unwound? */
  289. CMP X1, #0
  290. B.NE Exit_IRQ_No_Context_Switch
  291. /* Is a context switch required? */
  292. LDR X0, ullPortYieldRequiredConst
  293. LDR X1, [X0]
  294. CMP X1, #0
  295. B.EQ Exit_IRQ_No_Context_Switch
  296. /* Reset ullPortYieldRequired to 0. */
  297. MOV X2, #0
  298. STR X2, [X0]
  299. /* Restore volatile registers. */
  300. LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
  301. #if defined( GUEST )
  302. MSR SPSR_EL1, X5
  303. MSR ELR_EL1, X4
  304. #else
  305. MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
  306. MSR ELR_EL3, X4
  307. #endif
  308. DSB SY
  309. ISB SY
  310. LDP X29, X30, [SP], #0x10
  311. LDP X18, X19, [SP], #0x10
  312. LDP X16, X17, [SP], #0x10
  313. LDP X14, X15, [SP], #0x10
  314. LDP X12, X13, [SP], #0x10
  315. LDP X10, X11, [SP], #0x10
  316. LDP X8, X9, [SP], #0x10
  317. LDP X6, X7, [SP], #0x10
  318. LDP X4, X5, [SP], #0x10
  319. LDP X2, X3, [SP], #0x10
  320. LDP X0, X1, [SP], #0x10
  321. /* Save the context of the current task and select a new task to run. */
  322. portSAVE_CONTEXT
  323. BL vTaskSwitchContext
  324. portRESTORE_CONTEXT
  325. Exit_IRQ_No_Context_Switch:
  326. /* Restore volatile registers. */
  327. LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
  328. #if defined( GUEST )
  329. MSR SPSR_EL1, X5
  330. MSR ELR_EL1, X4
  331. #else
  332. MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
  333. MSR ELR_EL3, X4
  334. #endif
  335. DSB SY
  336. ISB SY
  337. LDP X29, X30, [SP], #0x10
  338. LDP X18, X19, [SP], #0x10
  339. LDP X16, X17, [SP], #0x10
  340. LDP X14, X15, [SP], #0x10
  341. LDP X12, X13, [SP], #0x10
  342. LDP X10, X11, [SP], #0x10
  343. LDP X8, X9, [SP], #0x10
  344. LDP X6, X7, [SP], #0x10
  345. LDP X4, X5, [SP], #0x10
  346. LDP X2, X3, [SP], #0x10
  347. LDP X0, X1, [SP], #0x10
  348. ERET
  349. .align 8
  350. pxCurrentTCBConst: .dword pxCurrentTCB
  351. ullCriticalNestingConst: .dword ullCriticalNesting
  352. ullPortTaskHasFPUContextConst: .dword ullPortTaskHasFPUContext
  353. ullICCPMRConst: .dword ullICCPMR
  354. ullMaxAPIPriorityMaskConst: .dword ullMaxAPIPriorityMask
  355. ullPortInterruptNestingConst: .dword ullPortInterruptNesting
  356. ullPortYieldRequiredConst: .dword ullPortYieldRequired
  357. ullICCIARConst: .dword ullICCIAR
  358. ullICCEOIRConst: .dword ullICCEOIR
  359. vApplicationIRQHandlerConst: .word vApplicationIRQHandler
  360. .end