ExceptionSupport.S 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. //
  2. // Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
  3. // Portion of Copyright (c) 2014 NVIDIA Corporation. All rights reserved.<BR>
  4. // Copyright (c) 2016 HP Development Company, L.P.
  5. //
  6. // SPDX-License-Identifier: BSD-2-Clause-Patent
  7. //
  8. //------------------------------------------------------------------------------
  9. #include <Chipset/AArch64.h>
  10. #include <Library/PcdLib.h>
  11. #include <AsmMacroIoLibV8.h>
  12. #include <Protocol/DebugSupport.h> // for exception type definitions
  13. /*
  14. This is the stack constructed by the exception handler (low address to high address).
  15. X0 to FAR makes up the EFI_SYSTEM_CONTEXT for AArch64.
  16. UINT64 X0; 0x000
  17. UINT64 X1; 0x008
  18. UINT64 X2; 0x010
  19. UINT64 X3; 0x018
  20. UINT64 X4; 0x020
  21. UINT64 X5; 0x028
  22. UINT64 X6; 0x030
  23. UINT64 X7; 0x038
  24. UINT64 X8; 0x040
  25. UINT64 X9; 0x048
  26. UINT64 X10; 0x050
  27. UINT64 X11; 0x058
  28. UINT64 X12; 0x060
  29. UINT64 X13; 0x068
  30. UINT64 X14; 0x070
  31. UINT64 X15; 0x078
  32. UINT64 X16; 0x080
  33. UINT64 X17; 0x088
  34. UINT64 X18; 0x090
  35. UINT64 X19; 0x098
  36. UINT64 X20; 0x0a0
  37. UINT64 X21; 0x0a8
  38. UINT64 X22; 0x0b0
  39. UINT64 X23; 0x0b8
  40. UINT64 X24; 0x0c0
  41. UINT64 X25; 0x0c8
  42. UINT64 X26; 0x0d0
  43. UINT64 X27; 0x0d8
  44. UINT64 X28; 0x0e0
  45. UINT64 FP; 0x0e8 // x29 - Frame Pointer
  46. UINT64 LR; 0x0f0 // x30 - Link Register
  47. UINT64 SP; 0x0f8 // x31 - Stack Pointer
  48. // FP/SIMD Registers. 128bit if used as Q-regs.
  49. UINT64 V0[2]; 0x100
  50. UINT64 V1[2]; 0x110
  51. UINT64 V2[2]; 0x120
  52. UINT64 V3[2]; 0x130
  53. UINT64 V4[2]; 0x140
  54. UINT64 V5[2]; 0x150
  55. UINT64 V6[2]; 0x160
  56. UINT64 V7[2]; 0x170
  57. UINT64 V8[2]; 0x180
  58. UINT64 V9[2]; 0x190
  59. UINT64 V10[2]; 0x1a0
  60. UINT64 V11[2]; 0x1b0
  61. UINT64 V12[2]; 0x1c0
  62. UINT64 V13[2]; 0x1d0
  63. UINT64 V14[2]; 0x1e0
  64. UINT64 V15[2]; 0x1f0
  65. UINT64 V16[2]; 0x200
  66. UINT64 V17[2]; 0x210
  67. UINT64 V18[2]; 0x220
  68. UINT64 V19[2]; 0x230
  69. UINT64 V20[2]; 0x240
  70. UINT64 V21[2]; 0x250
  71. UINT64 V22[2]; 0x260
  72. UINT64 V23[2]; 0x270
  73. UINT64 V24[2]; 0x280
  74. UINT64 V25[2]; 0x290
  75. UINT64 V26[2]; 0x2a0
  76. UINT64 V27[2]; 0x2b0
  77. UINT64 V28[2]; 0x2c0
  78. UINT64 V29[2]; 0x2d0
  79. UINT64 V30[2]; 0x2e0
  80. UINT64 V31[2]; 0x2f0
  81. // System Context
  82. UINT64 ELR; 0x300 // Exception Link Register
  83. UINT64 SPSR; 0x308 // Saved Processor Status Register
  84. UINT64 FPSR; 0x310 // Floating Point Status Register
  85. UINT64 ESR; 0x318 // Exception syndrome register
  86. UINT64 FAR; 0x320 // Fault Address Register
  87. UINT64 Padding;0x328 // Required for stack alignment
  88. */
  89. GCC_ASM_EXPORT(ExceptionHandlersEnd)
  90. GCC_ASM_EXPORT(CommonCExceptionHandler)
  91. GCC_ASM_EXPORT(RegisterEl0Stack)
  92. .text
  93. #define GP_CONTEXT_SIZE (32 * 8)
  94. #define FP_CONTEXT_SIZE (32 * 16)
  95. #define SYS_CONTEXT_SIZE ( 6 * 8) // 5 SYS regs + Alignment requirement (ie: the stack must be aligned on 0x10)
  96. //
  97. // There are two methods for installing AArch64 exception vectors:
  98. // 1. Install a copy of the vectors to a location specified by a PCD
  99. // 2. Write VBAR directly, requiring that vectors have proper alignment (2K)
  100. // The conditional below adjusts the alignment requirement based on which
  101. // exception vector initialization method is used.
  102. //
  103. #if defined(ARM_RELOCATE_VECTORS)
  104. GCC_ASM_EXPORT(ExceptionHandlersStart)
  105. ASM_PFX(ExceptionHandlersStart):
  106. #else
  107. VECTOR_BASE(ExceptionHandlersStart)
  108. #endif
  109. .macro ExceptionEntry, val, sp=SPx
  110. //
  111. // Our backtrace and register dump code is written in C and so it requires
  112. // a stack. This makes it difficult to produce meaningful diagnostics when
  113. // the stack pointer has been corrupted. So in such cases (i.e., when taking
  114. // synchronous exceptions), this macro is expanded with \sp set to SP0, in
  115. // which case we switch to the SP_EL0 stack pointer, which has been
  116. // initialized to point to a buffer that has been set aside for this purpose.
  117. //
  118. // Since 'sp' may no longer refer to the stack frame that was active when
  119. // the exception was taken, we may have to switch back and forth between
  120. // SP_EL0 and SP_ELx to record the correct value for SP in the context struct.
  121. //
  122. .ifnc \sp, SPx
  123. msr SPsel, xzr
  124. .endif
  125. // Move the stackpointer so we can reach our structure with the str instruction.
  126. sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
  127. // Push the GP registers so we can record the exception context
  128. stp x0, x1, [sp, #-GP_CONTEXT_SIZE]!
  129. stp x2, x3, [sp, #0x10]
  130. stp x4, x5, [sp, #0x20]
  131. stp x6, x7, [sp, #0x30]
  132. stp x8, x9, [sp, #0x40]
  133. stp x10, x11, [sp, #0x50]
  134. stp x12, x13, [sp, #0x60]
  135. stp x14, x15, [sp, #0x70]
  136. stp x16, x17, [sp, #0x80]
  137. stp x18, x19, [sp, #0x90]
  138. stp x20, x21, [sp, #0xa0]
  139. stp x22, x23, [sp, #0xb0]
  140. stp x24, x25, [sp, #0xc0]
  141. stp x26, x27, [sp, #0xd0]
  142. stp x28, x29, [sp, #0xe0]
  143. add x28, sp, #(GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
  144. .ifnc \sp, SPx
  145. msr SPsel, #1
  146. mov x7, sp
  147. msr SPsel, xzr
  148. .else
  149. mov x7, x28
  150. .endif
  151. stp x30, x7, [sp, #0xf0]
  152. // Record the type of exception that occurred.
  153. mov x0, #\val
  154. // Jump to our general handler to deal with all the common parts and process the exception.
  155. #if defined(ARM_RELOCATE_VECTORS)
  156. ldr x1, =ASM_PFX(CommonExceptionEntry)
  157. br x1
  158. .ltorg
  159. #else
  160. b ASM_PFX(CommonExceptionEntry)
  161. #endif
  162. .endm
  163. //
  164. // Current EL with SP0 : 0x0 - 0x180
  165. //
  166. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_SYNC)
  167. ASM_PFX(SynchronousExceptionSP0):
  168. ExceptionEntry EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS
  169. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_IRQ)
  170. ASM_PFX(IrqSP0):
  171. ExceptionEntry EXCEPT_AARCH64_IRQ
  172. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_FIQ)
  173. ASM_PFX(FiqSP0):
  174. ExceptionEntry EXCEPT_AARCH64_FIQ
  175. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_SERR)
  176. ASM_PFX(SErrorSP0):
  177. ExceptionEntry EXCEPT_AARCH64_SERROR
  178. //
  179. // Current EL with SPx: 0x200 - 0x380
  180. //
  181. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_SYNC)
  182. ASM_PFX(SynchronousExceptionSPx):
  183. ExceptionEntry EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS, SP0
  184. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_IRQ)
  185. ASM_PFX(IrqSPx):
  186. ExceptionEntry EXCEPT_AARCH64_IRQ
  187. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_FIQ)
  188. ASM_PFX(FiqSPx):
  189. ExceptionEntry EXCEPT_AARCH64_FIQ
  190. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_SERR)
  191. ASM_PFX(SErrorSPx):
  192. ExceptionEntry EXCEPT_AARCH64_SERROR
  193. //
  194. // Lower EL using AArch64 : 0x400 - 0x580
  195. //
  196. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_SYNC)
  197. ASM_PFX(SynchronousExceptionA64):
  198. ExceptionEntry EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS
  199. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_IRQ)
  200. ASM_PFX(IrqA64):
  201. ExceptionEntry EXCEPT_AARCH64_IRQ
  202. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_FIQ)
  203. ASM_PFX(FiqA64):
  204. ExceptionEntry EXCEPT_AARCH64_FIQ
  205. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_SERR)
  206. ASM_PFX(SErrorA64):
  207. ExceptionEntry EXCEPT_AARCH64_SERROR
  208. //
  209. // Lower EL using AArch32 : 0x600 - 0x780
  210. //
  211. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_SYNC)
  212. ASM_PFX(SynchronousExceptionA32):
  213. ExceptionEntry EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS
  214. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_IRQ)
  215. ASM_PFX(IrqA32):
  216. ExceptionEntry EXCEPT_AARCH64_IRQ
  217. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_FIQ)
  218. ASM_PFX(FiqA32):
  219. ExceptionEntry EXCEPT_AARCH64_FIQ
  220. VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_SERR)
  221. ASM_PFX(SErrorA32):
  222. ExceptionEntry EXCEPT_AARCH64_SERROR
  223. VECTOR_END(ExceptionHandlersStart)
  224. ASM_PFX(ExceptionHandlersEnd):
  225. ASM_PFX(CommonExceptionEntry):
  226. EL1_OR_EL2_OR_EL3(x1)
  227. 1:mrs x2, elr_el1 // Exception Link Register
  228. mrs x3, spsr_el1 // Saved Processor Status Register 32bit
  229. mrs x5, esr_el1 // EL1 Exception syndrome register 32bit
  230. mrs x6, far_el1 // EL1 Fault Address Register
  231. b 4f
  232. 2:mrs x2, elr_el2 // Exception Link Register
  233. mrs x3, spsr_el2 // Saved Processor Status Register 32bit
  234. mrs x5, esr_el2 // EL2 Exception syndrome register 32bit
  235. mrs x6, far_el2 // EL2 Fault Address Register
  236. b 4f
  237. 3:mrs x2, elr_el3 // Exception Link Register
  238. mrs x3, spsr_el3 // Saved Processor Status Register 32bit
  239. mrs x5, esr_el3 // EL3 Exception syndrome register 32bit
  240. mrs x6, far_el3 // EL3 Fault Address Register
  241. 4:mrs x4, fpsr // Floating point Status Register 32bit
  242. // Save the SYS regs
  243. stp x2, x3, [x28, #-SYS_CONTEXT_SIZE]!
  244. stp x4, x5, [x28, #0x10]
  245. str x6, [x28, #0x20]
  246. // Push FP regs to Stack.
  247. stp q0, q1, [x28, #-FP_CONTEXT_SIZE]!
  248. stp q2, q3, [x28, #0x20]
  249. stp q4, q5, [x28, #0x40]
  250. stp q6, q7, [x28, #0x60]
  251. stp q8, q9, [x28, #0x80]
  252. stp q10, q11, [x28, #0xa0]
  253. stp q12, q13, [x28, #0xc0]
  254. stp q14, q15, [x28, #0xe0]
  255. stp q16, q17, [x28, #0x100]
  256. stp q18, q19, [x28, #0x120]
  257. stp q20, q21, [x28, #0x140]
  258. stp q22, q23, [x28, #0x160]
  259. stp q24, q25, [x28, #0x180]
  260. stp q26, q27, [x28, #0x1a0]
  261. stp q28, q29, [x28, #0x1c0]
  262. stp q30, q31, [x28, #0x1e0]
  263. // x0 still holds the exception type.
  264. // Set x1 to point to the top of our struct on the Stack
  265. mov x1, sp
  266. // CommonCExceptionHandler (
  267. // IN EFI_EXCEPTION_TYPE ExceptionType, R0
  268. // IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
  269. // )
  270. // Call the handler as defined above
  271. // For now we spin in the handler if we received an abort of some kind.
  272. // We do not try to recover.
  273. bl ASM_PFX(CommonCExceptionHandler) // Call exception handler
  274. // Pop as many GP regs as we can before entering the critical section below
  275. ldp x2, x3, [sp, #0x10]
  276. ldp x4, x5, [sp, #0x20]
  277. ldp x6, x7, [sp, #0x30]
  278. ldp x8, x9, [sp, #0x40]
  279. ldp x10, x11, [sp, #0x50]
  280. ldp x12, x13, [sp, #0x60]
  281. ldp x14, x15, [sp, #0x70]
  282. ldp x16, x17, [sp, #0x80]
  283. ldp x18, x19, [sp, #0x90]
  284. ldp x20, x21, [sp, #0xa0]
  285. ldp x22, x23, [sp, #0xb0]
  286. ldp x24, x25, [sp, #0xc0]
  287. ldp x26, x27, [sp, #0xd0]
  288. ldp x0, x1, [sp], #0xe0
  289. // Pop FP regs from Stack.
  290. ldp q2, q3, [x28, #0x20]
  291. ldp q4, q5, [x28, #0x40]
  292. ldp q6, q7, [x28, #0x60]
  293. ldp q8, q9, [x28, #0x80]
  294. ldp q10, q11, [x28, #0xa0]
  295. ldp q12, q13, [x28, #0xc0]
  296. ldp q14, q15, [x28, #0xe0]
  297. ldp q16, q17, [x28, #0x100]
  298. ldp q18, q19, [x28, #0x120]
  299. ldp q20, q21, [x28, #0x140]
  300. ldp q22, q23, [x28, #0x160]
  301. ldp q24, q25, [x28, #0x180]
  302. ldp q26, q27, [x28, #0x1a0]
  303. ldp q28, q29, [x28, #0x1c0]
  304. ldp q30, q31, [x28, #0x1e0]
  305. ldp q0, q1, [x28], #FP_CONTEXT_SIZE
  306. // Pop the SYS regs we need
  307. ldp x29, x30, [x28]
  308. ldr x28, [x28, #0x10]
  309. msr fpsr, x28
  310. //
  311. // Disable interrupt(IRQ and FIQ) before restoring context,
  312. // or else the context will be corrupted by interrupt reentrance.
  313. // Interrupt mask will be restored from spsr by hardware when we call eret
  314. //
  315. msr daifset, #3
  316. isb
  317. EL1_OR_EL2_OR_EL3(x28)
  318. 1:msr elr_el1, x29 // Exception Link Register
  319. msr spsr_el1, x30 // Saved Processor Status Register 32bit
  320. b 4f
  321. 2:msr elr_el2, x29 // Exception Link Register
  322. msr spsr_el2, x30 // Saved Processor Status Register 32bit
  323. b 4f
  324. 3:msr elr_el3, x29 // Exception Link Register
  325. msr spsr_el3, x30 // Saved Processor Status Register 32bit
  326. 4:
  327. // pop remaining GP regs and return from exception.
  328. ldr x30, [sp, #0xf0 - 0xe0]
  329. ldp x28, x29, [sp], #GP_CONTEXT_SIZE - 0xe0
  330. // Adjust SP to be where we started from when we came into the handler.
  331. // The handler can not change the SP.
  332. add sp, sp, #FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE
  333. eret
  334. ASM_PFX(RegisterEl0Stack):
  335. msr sp_el0, x0
  336. ret