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