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