]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.S
ArmPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / ArmPkg / Library / ArmExceptionLib / Arm / ExceptionSupport.S
CommitLineData
2939c778
EC
1#------------------------------------------------------------------------------\r
2#\r
3# Use ARMv6 instruction to operate on a single stack\r
4#\r
5# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
6# Copyright (c) 2014, ARM Limited. All rights reserved.<BR>\r
7# Copyright (c) 2016 HP Development Company, L.P.<BR>\r
8#\r
4059386c 9# SPDX-License-Identifier: BSD-2-Clause-Patent\r
2939c778
EC
10#\r
11#------------------------------------------------------------------------------\r
12\r
13#include <Library/PcdLib.h>\r
14\r
15/*\r
16\r
17This is the stack constructed by the exception handler (low address to high address)\r
18 # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM\r
19 Reg Offset\r
20 === ======\r
21 R0 0x00 # stmfd SP!,{R0-R12}\r
22 R1 0x04\r
23 R2 0x08\r
24 R3 0x0c\r
25 R4 0x10\r
26 R5 0x14\r
27 R6 0x18\r
28 R7 0x1c\r
29 R8 0x20\r
30 R9 0x24\r
31 R10 0x28\r
32 R11 0x2c\r
33 R12 0x30\r
34 SP 0x34 # reserved via subtraction 0x20 (32) from SP\r
35 LR 0x38\r
36 PC 0x3c\r
37 CPSR 0x40\r
38 DFSR 0x44\r
39 DFAR 0x48\r
40 IFSR 0x4c\r
41 IFAR 0x50\r
42\r
43 LR 0x54 # SVC Link register (we need to restore it)\r
44\r
45 LR 0x58 # pushed by srsfd\r
46 CPSR 0x5c\r
47\r
48 */\r
49\r
50\r
51GCC_ASM_EXPORT(ExceptionHandlersStart)\r
52GCC_ASM_EXPORT(ExceptionHandlersEnd)\r
53GCC_ASM_EXPORT(CommonExceptionEntry)\r
54GCC_ASM_EXPORT(AsmCommonExceptionEntry)\r
55GCC_ASM_EXPORT(CommonCExceptionHandler)\r
56\r
57.text\r
58.syntax unified\r
59#if !defined(__APPLE__)\r
60.fpu neon @ makes vpush/vpop assemble\r
61#endif\r
62.align 5\r
63\r
64\r
65//\r
66// This code gets copied to the ARM vector table\r
67// ExceptionHandlersStart - ExceptionHandlersEnd gets copied\r
68//\r
69ASM_PFX(ExceptionHandlersStart):\r
70\r
71ASM_PFX(Reset):\r
72 b ASM_PFX(ResetEntry)\r
73\r
74ASM_PFX(UndefinedInstruction):\r
75 b ASM_PFX(UndefinedInstructionEntry)\r
76\r
77ASM_PFX(SoftwareInterrupt):\r
78 b ASM_PFX(SoftwareInterruptEntry)\r
79\r
80ASM_PFX(PrefetchAbort):\r
81 b ASM_PFX(PrefetchAbortEntry)\r
82\r
83ASM_PFX(DataAbort):\r
84 b ASM_PFX(DataAbortEntry)\r
85\r
86ASM_PFX(ReservedException):\r
87 b ASM_PFX(ReservedExceptionEntry)\r
88\r
89ASM_PFX(Irq):\r
90 b ASM_PFX(IrqEntry)\r
91\r
92ASM_PFX(Fiq):\r
93 b ASM_PFX(FiqEntry)\r
94\r
95ASM_PFX(ResetEntry):\r
96 srsdb #0x13! @ Store return state on SVC stack\r
97 @ We are already in SVC mode\r
98\r
99 stmfd SP!,{LR} @ Store the link register for the current mode\r
100 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
101 stmfd SP!,{R0-R12} @ Store the register state\r
102\r
103 mov R0,#0 @ ExceptionType\r
104 ldr R1,ASM_PFX(CommonExceptionEntry)\r
105 bx R1\r
106\r
107ASM_PFX(UndefinedInstructionEntry):\r
108 sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry\r
109 srsdb #0x13! @ Store return state on SVC stack\r
110 cps #0x13 @ Switch to SVC for common stack\r
111 stmfd SP!,{LR} @ Store the link register for the current mode\r
112 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
113 stmfd SP!,{R0-R12} @ Store the register state\r
114\r
115 mov R0,#1 @ ExceptionType\r
116 ldr R1,ASM_PFX(CommonExceptionEntry)\r
117 bx R1\r
118\r
119ASM_PFX(SoftwareInterruptEntry):\r
120 srsdb #0x13! @ Store return state on SVC stack\r
121 @ We are already in SVC mode\r
122 stmfd SP!,{LR} @ Store the link register for the current mode\r
123 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
124 stmfd SP!,{R0-R12} @ Store the register state\r
125\r
126 mov R0,#2 @ ExceptionType\r
127 ldr R1,ASM_PFX(CommonExceptionEntry)\r
128 bx R1\r
129\r
130ASM_PFX(PrefetchAbortEntry):\r
131 sub LR,LR,#4\r
132 srsdb #0x13! @ Store return state on SVC stack\r
133 cps #0x13 @ Switch to SVC for common stack\r
134 stmfd SP!,{LR} @ Store the link register for the current mode\r
135 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
136 stmfd SP!,{R0-R12} @ Store the register state\r
137\r
138 mov R0,#3 @ ExceptionType\r
139 ldr R1,ASM_PFX(CommonExceptionEntry)\r
140 bx R1\r
141\r
142ASM_PFX(DataAbortEntry):\r
143 sub LR,LR,#8\r
144 srsdb #0x13! @ Store return state on SVC stack\r
145 cps #0x13 @ Switch to SVC for common stack\r
146 stmfd SP!,{LR} @ Store the link register for the current mode\r
147 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
148 stmfd SP!,{R0-R12} @ Store the register state\r
149\r
150 mov R0,#4\r
151 ldr R1,ASM_PFX(CommonExceptionEntry)\r
152 bx R1\r
153\r
154ASM_PFX(ReservedExceptionEntry):\r
155 srsdb #0x13! @ Store return state on SVC stack\r
156 cps #0x13 @ Switch to SVC for common stack\r
157 stmfd SP!,{LR} @ Store the link register for the current mode\r
158 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
159 stmfd SP!,{R0-R12} @ Store the register state\r
160\r
161 mov R0,#5\r
162 ldr R1,ASM_PFX(CommonExceptionEntry)\r
163 bx R1\r
164\r
165ASM_PFX(IrqEntry):\r
166 sub LR,LR,#4\r
167 srsdb #0x13! @ Store return state on SVC stack\r
168 cps #0x13 @ Switch to SVC for common stack\r
169 stmfd SP!,{LR} @ Store the link register for the current mode\r
170 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
171 stmfd SP!,{R0-R12} @ Store the register state\r
172\r
173 mov R0,#6 @ ExceptionType\r
174 ldr R1,ASM_PFX(CommonExceptionEntry)\r
175 bx R1\r
176\r
177ASM_PFX(FiqEntry):\r
178 sub LR,LR,#4\r
179 srsdb #0x13! @ Store return state on SVC stack\r
180 cps #0x13 @ Switch to SVC for common stack\r
181 stmfd SP!,{LR} @ Store the link register for the current mode\r
182 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
183 stmfd SP!,{R0-R12} @ Store the register state\r
184 @ Since we have already switch to SVC R8_fiq - R12_fiq\r
185 @ never get used or saved\r
186 mov R0,#7 @ ExceptionType\r
187 ldr R1,ASM_PFX(CommonExceptionEntry)\r
188 bx R1\r
189\r
190//\r
191// This gets patched by the C code that patches in the vector table\r
192//\r
193ASM_PFX(CommonExceptionEntry):\r
194 .word ASM_PFX(AsmCommonExceptionEntry)\r
195\r
196ASM_PFX(ExceptionHandlersEnd):\r
197\r
198//\r
199// This code runs from CpuDxe driver loaded address. It is patched into\r
200// CommonExceptionEntry.\r
201//\r
202ASM_PFX(AsmCommonExceptionEntry):\r
203 mrc p15, 0, R1, c6, c0, 2 @ Read IFAR\r
204 str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR\r
205\r
206 mrc p15, 0, R1, c5, c0, 1 @ Read IFSR\r
207 str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR\r
208\r
209 mrc p15, 0, R1, c6, c0, 0 @ Read DFAR\r
210 str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR\r
211\r
212 mrc p15, 0, R1, c5, c0, 0 @ Read DFSR\r
213 str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR\r
214\r
215 ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack\r
216 str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR\r
217\r
218 add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
219 and R3, R1, #0x1f @ Check CPSR to see if User or System Mode\r
220 cmp R3, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))\r
221 cmpne R3, #0x10 @\r
222 stmdaeq R2, {lr}^ @ save unbanked lr\r
223 @ else\r
224 stmdane R2, {lr} @ save SVC lr\r
225\r
226\r
227 ldr R5, [SP, #0x58] @ PC is the LR pushed by srsfd\r
228 @ Check to see if we have to adjust for Thumb entry\r
229 sub r4, r0, #1 @ if (ExceptionType == 1 || ExceptionType == 2)) {\r
230 cmp r4, #1 @ // UND & SVC have differnt LR adjust for Thumb\r
231 bhi NoAdjustNeeded\r
232\r
233 tst r1, #0x20 @ if ((CPSR & T)) == T) { // Thumb Mode on entry\r
234 addne R5, R5, #2 @ PC += 2;\r
235 strne R5,[SP,#0x58] @ Update LR value pushed by srsfd\r
236\r
237NoAdjustNeeded:\r
238\r
239 str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC\r
240\r
241 add R1, SP, #0x60 @ We pushed 0x60 bytes on the stack\r
242 str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP\r
243\r
244 @ R0 is ExceptionType\r
245 mov R1,SP @ R1 is SystemContext\r
246\r
247#if (FixedPcdGet32(PcdVFPEnabled))\r
248 vpush {d0-d15} @ save vstm registers in case they are used in optimizations\r
249#endif\r
250\r
251 mov R4, SP @ Save current SP\r
252 tst R4, #4\r
253 subne SP, SP, #4 @ Adjust SP if not 8-byte aligned\r
254\r
255/*\r
256VOID\r
257EFIAPI\r
258CommonCExceptionHandler (\r
259 IN EFI_EXCEPTION_TYPE ExceptionType, R0\r
260 IN OUT EFI_SYSTEM_CONTEXT SystemContext R1\r
261 )\r
262\r
263*/\r
264 blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler\r
265\r
266 mov SP, R4 @ Restore SP\r
267\r
268#if (FixedPcdGet32(PcdVFPEnabled))\r
269 vpop {d0-d15}\r
270#endif\r
271\r
272 ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR\r
273 mcr p15, 0, R1, c5, c0, 1 @ Write IFSR\r
274\r
275 ldr R1, [SP, #0x44] @ Restore EFI_SYSTEM_CONTEXT_ARM.DFSR\r
276 mcr p15, 0, R1, c5, c0, 0 @ Write DFSR\r
277\r
278 ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC\r
279 str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored\r
280\r
281 ldr R1,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR\r
282 str R1,[SP,#0x5c] @ Store it back to srsfd stack slot so it can be restored\r
283\r
284 add R3, SP, #0x54 @ Make R3 point to SVC LR saved on entry\r
285 add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
286 and R1, R1, #0x1f @ Check to see if User or System Mode\r
287 cmp R1, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))\r
288 cmpne R1, #0x10 @\r
289 ldmibeq R2, {lr}^ @ restore unbanked lr\r
290 @ else\r
291 ldmibne R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR}\r
292\r
293 ldmfd SP!,{R0-R12} @ Restore general purpose registers\r
294 @ Exception handler can not change SP\r
295\r
296 add SP,SP,#0x20 @ Clear out the remaining stack space\r
297 ldmfd SP!,{LR} @ restore the link register for this context\r
298 rfefd SP! @ return from exception via srsfd stack slot\r
299\r