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