1 #------------------------------------------------------------------------------
3 # Use ARMv6 instruction to operate on a single stack
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>
9 # SPDX-License-Identifier: BSD-2-Clause-Patent
11 #------------------------------------------------------------------------------
13 #include <Library/PcdLib.h>
17 This is the stack constructed by the exception handler (low address to high address)
18 # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM
21 R0 0x00 # stmfd SP!,{R0-R12}
34 SP 0x34 # reserved via subtraction 0x20 (32) from SP
43 LR 0x54 # SVC Link register (we need to restore it)
45 LR 0x58 # pushed by srsfd
51 GCC_ASM_EXPORT(ExceptionHandlersStart)
52 GCC_ASM_EXPORT(ExceptionHandlersEnd)
53 GCC_ASM_EXPORT(CommonExceptionEntry)
54 GCC_ASM_EXPORT(AsmCommonExceptionEntry)
55 GCC_ASM_EXPORT(CommonCExceptionHandler)
59 #if !defined(__APPLE__)
60 .fpu neon @ makes vpush/vpop assemble
66 // This code gets copied to the ARM vector table
67 // ExceptionHandlersStart - ExceptionHandlersEnd gets copied
69 ASM_PFX(ExceptionHandlersStart):
74 ASM_PFX(UndefinedInstruction):
75 b ASM_PFX(UndefinedInstructionEntry)
77 ASM_PFX(SoftwareInterrupt):
78 b ASM_PFX(SoftwareInterruptEntry)
80 ASM_PFX(PrefetchAbort):
81 b ASM_PFX(PrefetchAbortEntry)
84 b ASM_PFX(DataAbortEntry)
86 ASM_PFX(ReservedException):
87 b ASM_PFX(ReservedExceptionEntry)
96 srsdb #0x13! @ Store return state on SVC stack
97 @ We are already in SVC mode
99 stmfd SP!,{LR} @ Store the link register for the current mode
100 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
101 stmfd SP!,{R0-R12} @ Store the register state
103 mov R0,#0 @ ExceptionType
104 ldr R1,ASM_PFX(CommonExceptionEntry)
107 ASM_PFX(UndefinedInstructionEntry):
108 sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry
109 srsdb #0x13! @ Store return state on SVC stack
110 cps #0x13 @ Switch to SVC for common stack
111 stmfd SP!,{LR} @ Store the link register for the current mode
112 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
113 stmfd SP!,{R0-R12} @ Store the register state
115 mov R0,#1 @ ExceptionType
116 ldr R1,ASM_PFX(CommonExceptionEntry)
119 ASM_PFX(SoftwareInterruptEntry):
120 srsdb #0x13! @ Store return state on SVC stack
121 @ We are already in SVC mode
122 stmfd SP!,{LR} @ Store the link register for the current mode
123 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
124 stmfd SP!,{R0-R12} @ Store the register state
126 mov R0,#2 @ ExceptionType
127 ldr R1,ASM_PFX(CommonExceptionEntry)
130 ASM_PFX(PrefetchAbortEntry):
132 srsdb #0x13! @ Store return state on SVC stack
133 cps #0x13 @ Switch to SVC for common stack
134 stmfd SP!,{LR} @ Store the link register for the current mode
135 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
136 stmfd SP!,{R0-R12} @ Store the register state
138 mov R0,#3 @ ExceptionType
139 ldr R1,ASM_PFX(CommonExceptionEntry)
142 ASM_PFX(DataAbortEntry):
144 srsdb #0x13! @ Store return state on SVC stack
145 cps #0x13 @ Switch to SVC for common stack
146 stmfd SP!,{LR} @ Store the link register for the current mode
147 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
148 stmfd SP!,{R0-R12} @ Store the register state
151 ldr R1,ASM_PFX(CommonExceptionEntry)
154 ASM_PFX(ReservedExceptionEntry):
155 srsdb #0x13! @ Store return state on SVC stack
156 cps #0x13 @ Switch to SVC for common stack
157 stmfd SP!,{LR} @ Store the link register for the current mode
158 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
159 stmfd SP!,{R0-R12} @ Store the register state
162 ldr R1,ASM_PFX(CommonExceptionEntry)
167 srsdb #0x13! @ Store return state on SVC stack
168 cps #0x13 @ Switch to SVC for common stack
169 stmfd SP!,{LR} @ Store the link register for the current mode
170 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
171 stmfd SP!,{R0-R12} @ Store the register state
173 mov R0,#6 @ ExceptionType
174 ldr R1,ASM_PFX(CommonExceptionEntry)
179 srsdb #0x13! @ Store return state on SVC stack
180 cps #0x13 @ Switch to SVC for common stack
181 stmfd SP!,{LR} @ Store the link register for the current mode
182 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
183 stmfd SP!,{R0-R12} @ Store the register state
184 @ Since we have already switch to SVC R8_fiq - R12_fiq
185 @ never get used or saved
186 mov R0,#7 @ ExceptionType
187 ldr R1,ASM_PFX(CommonExceptionEntry)
191 // This gets patched by the C code that patches in the vector table
193 ASM_PFX(CommonExceptionEntry):
194 .word ASM_PFX(AsmCommonExceptionEntry)
196 ASM_PFX(ExceptionHandlersEnd):
199 // This code runs from CpuDxe driver loaded address. It is patched into
200 // CommonExceptionEntry.
202 ASM_PFX(AsmCommonExceptionEntry):
203 mrc p15, 0, R1, c6, c0, 2 @ Read IFAR
204 str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
206 mrc p15, 0, R1, c5, c0, 1 @ Read IFSR
207 str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
209 mrc p15, 0, R1, c6, c0, 0 @ Read DFAR
210 str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
212 mrc p15, 0, R1, c5, c0, 0 @ Read DFSR
213 str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
215 ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack
216 str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
218 add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
219 and R3, R1, #0x1f @ Check CPSR to see if User or System Mode
220 cmp R3, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))
222 stmdaeq R2, {lr}^ @ save unbanked lr
224 stmdane R2, {lr} @ save SVC lr
227 ldr R5, [SP, #0x58] @ PC is the LR pushed by srsfd
228 @ Check to see if we have to adjust for Thumb entry
229 sub r4, r0, #1 @ if (ExceptionType == 1 || ExceptionType == 2)) {
230 cmp r4, #1 @ // UND & SVC have different LR adjust for Thumb
233 tst r1, #0x20 @ if ((CPSR & T)) == T) { // Thumb Mode on entry
234 addne R5, R5, #2 @ PC += 2;
235 strne R5,[SP,#0x58] @ Update LR value pushed by srsfd
239 str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
241 add R1, SP, #0x60 @ We pushed 0x60 bytes on the stack
242 str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP
244 @ R0 is ExceptionType
245 mov R1,SP @ R1 is SystemContext
247 #if (FixedPcdGet32(PcdVFPEnabled))
248 vpush {d0-d15} @ save vstm registers in case they are used in optimizations
251 mov R4, SP @ Save current SP
253 subne SP, SP, #4 @ Adjust SP if not 8-byte aligned
258 CommonCExceptionHandler (
259 IN EFI_EXCEPTION_TYPE ExceptionType, R0
260 IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
264 blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler
266 mov SP, R4 @ Restore SP
268 #if (FixedPcdGet32(PcdVFPEnabled))
272 ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
273 mcr p15, 0, R1, c5, c0, 1 @ Write IFSR
275 ldr R1, [SP, #0x44] @ Restore EFI_SYSTEM_CONTEXT_ARM.DFSR
276 mcr p15, 0, R1, c5, c0, 0 @ Write DFSR
278 ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC
279 str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored
281 ldr R1,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR
282 str R1,[SP,#0x5c] @ Store it back to srsfd stack slot so it can be restored
284 add R3, SP, #0x54 @ Make R3 point to SVC LR saved on entry
285 add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
286 and R1, R1, #0x1f @ Check to see if User or System Mode
287 cmp R1, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))
289 ldmibeq R2, {lr}^ @ restore unbanked lr
291 ldmibne R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR}
293 ldmfd SP!,{R0-R12} @ Restore general purpose registers
294 @ Exception handler can not change SP
296 add SP,SP,#0x20 @ Clear out the remaining stack space
297 ldmfd SP!,{LR} @ restore the link register for this context
298 rfefd SP! @ return from exception via srsfd stack slot