]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.S
ArmPkg: Remove RVCT support
[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 # SPDX-License-Identifier: BSD-2-Clause-Patent
10 #
11 #------------------------------------------------------------------------------
12
13 #include <Library/PcdLib.h>
14
15 /*
16
17 This is the stack constructed by the exception handler (low address to high address)
18 # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM
19 Reg Offset
20 === ======
21 R0 0x00 # stmfd SP!,{R0-R12}
22 R1 0x04
23 R2 0x08
24 R3 0x0c
25 R4 0x10
26 R5 0x14
27 R6 0x18
28 R7 0x1c
29 R8 0x20
30 R9 0x24
31 R10 0x28
32 R11 0x2c
33 R12 0x30
34 SP 0x34 # reserved via subtraction 0x20 (32) from SP
35 LR 0x38
36 PC 0x3c
37 CPSR 0x40
38 DFSR 0x44
39 DFAR 0x48
40 IFSR 0x4c
41 IFAR 0x50
42
43 LR 0x54 # SVC Link register (we need to restore it)
44
45 LR 0x58 # pushed by srsfd
46 CPSR 0x5c
47
48 */
49
50
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)
56
57 .text
58 .syntax unified
59 #if !defined(__APPLE__)
60 .fpu neon @ makes vpush/vpop assemble
61 #endif
62 .align 5
63
64
65 //
66 // This code gets copied to the ARM vector table
67 // ExceptionHandlersStart - ExceptionHandlersEnd gets copied
68 //
69 ASM_PFX(ExceptionHandlersStart):
70
71 ASM_PFX(Reset):
72 b ASM_PFX(ResetEntry)
73
74 ASM_PFX(UndefinedInstruction):
75 b ASM_PFX(UndefinedInstructionEntry)
76
77 ASM_PFX(SoftwareInterrupt):
78 b ASM_PFX(SoftwareInterruptEntry)
79
80 ASM_PFX(PrefetchAbort):
81 b ASM_PFX(PrefetchAbortEntry)
82
83 ASM_PFX(DataAbort):
84 b ASM_PFX(DataAbortEntry)
85
86 ASM_PFX(ReservedException):
87 b ASM_PFX(ReservedExceptionEntry)
88
89 ASM_PFX(Irq):
90 b ASM_PFX(IrqEntry)
91
92 ASM_PFX(Fiq):
93 b ASM_PFX(FiqEntry)
94
95 ASM_PFX(ResetEntry):
96 srsdb #0x13! @ Store return state on SVC stack
97 @ We are already in SVC mode
98
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
102
103 mov R0,#0 @ ExceptionType
104 ldr R1,ASM_PFX(CommonExceptionEntry)
105 bx R1
106
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
114
115 mov R0,#1 @ ExceptionType
116 ldr R1,ASM_PFX(CommonExceptionEntry)
117 bx R1
118
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
125
126 mov R0,#2 @ ExceptionType
127 ldr R1,ASM_PFX(CommonExceptionEntry)
128 bx R1
129
130 ASM_PFX(PrefetchAbortEntry):
131 sub LR,LR,#4
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
137
138 mov R0,#3 @ ExceptionType
139 ldr R1,ASM_PFX(CommonExceptionEntry)
140 bx R1
141
142 ASM_PFX(DataAbortEntry):
143 sub LR,LR,#8
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
149
150 mov R0,#4
151 ldr R1,ASM_PFX(CommonExceptionEntry)
152 bx R1
153
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
160
161 mov R0,#5
162 ldr R1,ASM_PFX(CommonExceptionEntry)
163 bx R1
164
165 ASM_PFX(IrqEntry):
166 sub LR,LR,#4
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
172
173 mov R0,#6 @ ExceptionType
174 ldr R1,ASM_PFX(CommonExceptionEntry)
175 bx R1
176
177 ASM_PFX(FiqEntry):
178 sub LR,LR,#4
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)
188 bx R1
189
190 //
191 // This gets patched by the C code that patches in the vector table
192 //
193 ASM_PFX(CommonExceptionEntry):
194 .word ASM_PFX(AsmCommonExceptionEntry)
195
196 ASM_PFX(ExceptionHandlersEnd):
197
198 //
199 // This code runs from CpuDxe driver loaded address. It is patched into
200 // CommonExceptionEntry.
201 //
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
205
206 mrc p15, 0, R1, c5, c0, 1 @ Read IFSR
207 str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
208
209 mrc p15, 0, R1, c6, c0, 0 @ Read DFAR
210 str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
211
212 mrc p15, 0, R1, c5, c0, 0 @ Read DFSR
213 str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
214
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
217
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))
221 cmpne R3, #0x10 @
222 stmdaeq R2, {lr}^ @ save unbanked lr
223 @ else
224 stmdane R2, {lr} @ save SVC lr
225
226
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
231 bhi NoAdjustNeeded
232
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
236
237 NoAdjustNeeded:
238
239 str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
240
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
243
244 @ R0 is ExceptionType
245 mov R1,SP @ R1 is SystemContext
246
247 #if (FixedPcdGet32(PcdVFPEnabled))
248 vpush {d0-d15} @ save vstm registers in case they are used in optimizations
249 #endif
250
251 mov R4, SP @ Save current SP
252 tst R4, #4
253 subne SP, SP, #4 @ Adjust SP if not 8-byte aligned
254
255 /*
256 VOID
257 EFIAPI
258 CommonCExceptionHandler (
259 IN EFI_EXCEPTION_TYPE ExceptionType, R0
260 IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
261 )
262
263 */
264 blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler
265
266 mov SP, R4 @ Restore SP
267
268 #if (FixedPcdGet32(PcdVFPEnabled))
269 vpop {d0-d15}
270 #endif
271
272 ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
273 mcr p15, 0, R1, c5, c0, 1 @ Write IFSR
274
275 ldr R1, [SP, #0x44] @ Restore EFI_SYSTEM_CONTEXT_ARM.DFSR
276 mcr p15, 0, R1, c5, c0, 0 @ Write DFSR
277
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
280
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
283
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))
288 cmpne R1, #0x10 @
289 ldmibeq R2, {lr}^ @ restore unbanked lr
290 @ else
291 ldmibne R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR}
292
293 ldmfd SP!,{R0-R12} @ Restore general purpose registers
294 @ Exception handler can not change SP
295
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
299