irq_armv8mml.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * Copyright (c) 2016-2023 Arm Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * -----------------------------------------------------------------------------
  19. *
  20. * Project: CMSIS-RTOS RTX
  21. * Title: ARMv8-M Mainline Exception handlers
  22. *
  23. * -----------------------------------------------------------------------------
  24. */
  25. .syntax unified
  26. #include "rtx_def.h"
  27. #if (defined(__ARM_FP) && (__ARM_FP > 0))
  28. .equ FPU_USED, 1
  29. #else
  30. .equ FPU_USED, 0
  31. #endif
  32. #if (defined(__ARM_FEATURE_MVE) && (__ARM_FEATURE_MVE > 0))
  33. .equ MVE_USED, 1
  34. #else
  35. .equ MVE_USED, 0
  36. #endif
  37. .equ I_T_RUN_OFS, 20 // osRtxInfo.thread.run offset
  38. .equ TCB_SM_OFS, 48 // TCB.stack_mem offset
  39. .equ TCB_SP_OFS, 56 // TCB.SP offset
  40. .equ TCB_SF_OFS, 34 // TCB.stack_frame offset
  41. .equ TCB_TZM_OFS, 64 // TCB.tz_memory offset
  42. .equ TCB_ZONE_OFS,68 // TCB.zone offset
  43. .equ FPCCR, 0xE000EF34 // FPCCR Address
  44. .equ osRtxErrorStackOverflow, 1 // Stack overflow
  45. .equ osRtxErrorSVC, 6 // Invalid SVC function called
  46. .section ".rodata"
  47. .global irqRtxLib // Non weak library reference
  48. irqRtxLib:
  49. .byte 0
  50. .thumb
  51. .section ".text"
  52. .align 2
  53. .eabi_attribute Tag_ABI_align_preserved, 1
  54. .thumb_func
  55. .type SVC_Handler, %function
  56. .global SVC_Handler
  57. .fnstart
  58. .cantunwind
  59. SVC_Handler:
  60. tst lr,#0x04 // Determine return stack from EXC_RETURN bit 2
  61. ite eq
  62. mrseq r0,msp // Get MSP if return stack is MSP
  63. mrsne r0,psp // Get PSP if return stack is PSP
  64. ldr r1,[r0,#24] // Load saved PC from stack
  65. ldrb r1,[r1,#-2] // Load SVC number
  66. cmp r1,#0 // Check SVC number
  67. bne SVC_User // Branch if not SVC 0
  68. #ifdef RTX_SVC_PTR_CHECK
  69. ldr r12,[r0,#16] // Load function address from stack
  70. sub r1,r12,#1 // Clear T-bit of function address
  71. lsls r2,r1,#30 // Check if 4-byte aligned
  72. beq SVC_PtrBoundsCheck // Branch if address is aligned
  73. SVC_PtrInvalid:
  74. push {r0,lr} // Save SP and EXC_RETURN
  75. movs r0,#osRtxErrorSVC // Parameter: code
  76. mov r1,r12 // Parameter: object_id
  77. bl osRtxKernelErrorNotify // Call osRtxKernelErrorNotify
  78. pop {r12,lr} // Restore SP and EXC_RETURN
  79. b SVC_Context // Branch to context handling
  80. SVC_PtrBoundsCheck:
  81. ldr r2,=Image$$RTX_SVC_VENEERS$$Base
  82. ldr r3,=Image$$RTX_SVC_VENEERS$$Length
  83. subs r2,r1,r2 // Subtract SVC table base address
  84. cmp r2,r3 // Compare with SVC table boundaries
  85. bhs SVC_PtrInvalid // Branch if address is out of bounds
  86. #endif // RTX_SVC_PTR_CHECK
  87. push {r0,lr} // Save SP and EXC_RETURN
  88. ldm r0,{r0-r3,r12} // Load function parameters and address from stack
  89. blx r12 // Call service function
  90. pop {r12,lr} // Restore SP and EXC_RETURN
  91. str r0,[r12] // Store function return value
  92. SVC_Context:
  93. ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run
  94. ldm r3,{r1,r2} // Load osRtxInfo.thread.run: curr & next
  95. cmp r1,r2 // Check if thread switch is required
  96. it eq
  97. bxeq lr // Exit when threads are the same
  98. str r2,[r3] // osRtxInfo.thread.run: curr = next
  99. .if (FPU_USED != 0) || (MVE_USED != 0)
  100. cbnz r1,SVC_ContextSave // Branch if running thread is not deleted
  101. SVC_FP_LazyState:
  102. tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4
  103. bne SVC_ContextRestore // Branch if not extended stack frame
  104. ldr r3,=FPCCR // FPCCR Address
  105. ldr r0,[r3] // Load FPCCR
  106. bic r0,r0,#1 // Clear LSPACT (Lazy state preservation)
  107. str r0,[r3] // Store FPCCR
  108. b SVC_ContextRestore // Branch to context restore handling
  109. .else
  110. cbz r1,SVC_ContextRestore // Branch if running thread is deleted
  111. .endif
  112. SVC_ContextSave:
  113. #ifdef RTX_TZ_CONTEXT
  114. ldr r0,[r1,#TCB_TZM_OFS] // Load TrustZone memory identifier
  115. cbz r0,SVC_ContextSave_NS // Branch if there is no secure context
  116. push {r1,r2,r12,lr} // Save registers and EXC_RETURN
  117. bl TZ_StoreContext_S // Store secure context
  118. pop {r1,r2,r12,lr} // Restore registers and EXC_RETURN
  119. #endif
  120. SVC_ContextSave_NS:
  121. #if (DOMAIN_NS != 0)
  122. tst lr,#0x40 // Check domain of interrupted thread
  123. bne SVC_ContextSaveSP // Branch if secure
  124. #endif
  125. #ifdef RTX_STACK_CHECK
  126. sub r12,r12,#32 // Calculate SP: space for R4..R11
  127. .if (FPU_USED != 0) || (MVE_USED != 0)
  128. tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4
  129. it eq // If extended stack frame
  130. subeq r12,r12,#64 // Additional space for S16..S31
  131. .endif
  132. SVC_ContextSaveSP:
  133. str r12,[r1,#TCB_SP_OFS] // Store SP
  134. strb lr, [r1,#TCB_SF_OFS] // Store stack frame information
  135. push {r1,r2} // Save osRtxInfo.thread.run: curr & next
  136. mov r0,r1 // Parameter: osRtxInfo.thread.run.curr
  137. bl osRtxThreadStackCheck // Check if thread stack is overrun
  138. pop {r1,r2} // Restore osRtxInfo.thread.run: curr & next
  139. cbnz r0,SVC_ContextSaveRegs // Branch when stack check is ok
  140. .if (FPU_USED != 0) || (MVE_USED != 0)
  141. mov r4,r1 // Assign osRtxInfo.thread.run.curr to R4
  142. .endif
  143. movs r0,#osRtxErrorStackOverflow // Parameter: r0=code, r1=object_id
  144. bl osRtxKernelErrorNotify // Call osRtxKernelErrorNotify
  145. ldr r3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.thread.run
  146. ldr r2,[r3,#4] // Load osRtxInfo.thread.run: next
  147. str r2,[r3] // osRtxInfo.thread.run: curr = next
  148. movs r1,#0 // Simulate deleted running thread
  149. .if (FPU_USED != 0) || (MVE_USED != 0)
  150. ldrsb lr,[r4,#TCB_SF_OFS] // Load stack frame information
  151. b SVC_FP_LazyState // Branch to FP lazy state handling
  152. .else
  153. b SVC_ContextRestore // Branch to context restore handling
  154. .endif
  155. SVC_ContextSaveRegs:
  156. ldrsb lr,[r1,#TCB_SF_OFS] // Load stack frame information
  157. #if (DOMAIN_NS != 0)
  158. tst lr,#0x40 // Check domain of interrupted thread
  159. bne SVC_ContextRestore // Branch if secure
  160. #endif
  161. ldr r12,[r1,#TCB_SP_OFS] // Load SP
  162. .if (FPU_USED != 0) || (MVE_USED != 0)
  163. tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4
  164. it eq // If extended stack frame
  165. vstmiaeq r12!,{s16-s31} // Save VFP S16..S31
  166. .endif
  167. stm r12,{r4-r11} // Save R4..R11
  168. #else
  169. stmdb r12!,{r4-r11} // Save R4..R11
  170. .if (FPU_USED != 0) || (MVE_USED != 0)
  171. tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4
  172. it eq // If extended stack frame
  173. vstmdbeq r12!,{s16-s31} // Save VFP S16.S31
  174. .endif
  175. SVC_ContextSaveSP:
  176. str r12,[r1,#TCB_SP_OFS] // Store SP
  177. strb lr, [r1,#TCB_SF_OFS] // Store stack frame information
  178. #endif // RTX_STACK_CHECK
  179. SVC_ContextRestore:
  180. movs r4,r2 // Assign osRtxInfo.thread.run.next to R4, clear Z flag
  181. #ifdef RTX_EXECUTION_ZONE
  182. ldrb r0,[r2,#TCB_ZONE_OFS] // Load osRtxInfo.thread.run.next: zone
  183. cbz r1,SVC_ZoneSetup // Branch if running thread is deleted (Z flag unchanged)
  184. ldrb r1,[r1,#TCB_ZONE_OFS] // Load osRtxInfo.thread.run.curr: zone
  185. cmp r0,r1 // Check if next:zone == curr:zone
  186. SVC_ZoneSetup:
  187. it ne // If zone has changed or running thread is deleted
  188. blne osZoneSetup_Callback // Setup zone for next thread
  189. #endif // RTX_EXECUTION_ZONE
  190. #ifdef RTX_TZ_CONTEXT
  191. ldr r0,[r4,#TCB_TZM_OFS] // Load TrustZone memory identifier
  192. cmp r0,#0
  193. it ne // If TrustZone memory allocated
  194. blne TZ_LoadContext_S // Load secure context
  195. #endif
  196. ldr r0,[r4,#TCB_SP_OFS] // Load SP
  197. ldr r1,[r4,#TCB_SM_OFS] // Load stack memory base
  198. msr psplim,r1 // Set PSPLIM
  199. ldrsb lr,[r4,#TCB_SF_OFS] // Load stack frame information
  200. #if (DOMAIN_NS != 0)
  201. tst lr,#0x40 // Check domain of interrupted thread
  202. itt ne // If secure
  203. msrne psp,r0 // Set PSP
  204. bxne lr // Exit from handler
  205. #endif
  206. .if (FPU_USED != 0) || (MVE_USED != 0)
  207. tst lr,#0x10 // Determine stack frame from EXC_RETURN bit 4
  208. it eq // If extended stack frame
  209. vldmiaeq r0!,{s16-s31} // Restore VFP S16..S31
  210. .endif
  211. ldmia r0!,{r4-r11} // Restore R4..R11
  212. msr psp,r0 // Set PSP
  213. SVC_Exit:
  214. bx lr // Exit from handler
  215. SVC_User:
  216. ldr r2,=osRtxUserSVC // Load address of SVC table
  217. ldr r3,[r2] // Load SVC maximum number
  218. cmp r1,r3 // Check SVC number range
  219. bhi SVC_Exit // Branch if out of range
  220. push {r0,lr} // Save SP and EXC_RETURN
  221. ldr r12,[r2,r1,lsl #2] // Load address of SVC function
  222. ldm r0,{r0-r3} // Load function parameters from stack
  223. blx r12 // Call service function
  224. pop {r12,lr} // Restore SP and EXC_RETURN
  225. str r0,[r12] // Store function return value
  226. bx lr // Return from handler
  227. .fnend
  228. .size SVC_Handler, .-SVC_Handler
  229. .thumb_func
  230. .type PendSV_Handler, %function
  231. .global PendSV_Handler
  232. .fnstart
  233. .cantunwind
  234. PendSV_Handler:
  235. push {r0,lr} // Save EXC_RETURN
  236. bl osRtxPendSV_Handler // Call osRtxPendSV_Handler
  237. pop {r0,lr} // Restore EXC_RETURN
  238. mrs r12,psp // Save PSP to R12
  239. b SVC_Context // Branch to context handling
  240. .fnend
  241. .size PendSV_Handler, .-PendSV_Handler
  242. .thumb_func
  243. .type SysTick_Handler, %function
  244. .global SysTick_Handler
  245. .fnstart
  246. .cantunwind
  247. SysTick_Handler:
  248. push {r0,lr} // Save EXC_RETURN
  249. bl osRtxTick_Handler // Call osRtxTick_Handler
  250. pop {r0,lr} // Restore EXC_RETURN
  251. mrs r12,psp // Save PSP to R12
  252. b SVC_Context // Branch to context handling
  253. .fnend
  254. .size SysTick_Handler, .-SysTick_Handler
  255. #ifdef RTX_SAFETY_FEATURES
  256. .thumb_func
  257. .type osFaultResume, %function
  258. .global osFaultResume
  259. .fnstart
  260. .cantunwind
  261. osFaultResume:
  262. mrs r12,psp // Save PSP to R12
  263. b SVC_Context // Branch to context handling
  264. .fnend
  265. .size osFaultResume, .-osFaultResume
  266. #endif // RTX_SAFETY_FEATURES
  267. .end