]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Drivers/CpuDxe/ArmV6/ExceptionSupport.S
86d2a7135fce84a62b8c90bc01ead955effa2f47
[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 #
7 # This program and the accompanying materials
8 # are licensed and made available under the terms and conditions of the BSD License
9 # which accompanies this distribution. The full text of the license may be found at
10 # http://opensource.org/licenses/bsd-license.php
11 #
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 #
15 #------------------------------------------------------------------------------
16
17 #include <Library/PcdLib.h>
18
19 /*
20
21 This is the stack constructed by the exception handler (low address to high address)
22 # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM
23 Reg Offset
24 === ======
25 R0 0x00 # stmfd SP!,{R0-R12}
26 R1 0x04
27 R2 0x08
28 R3 0x0c
29 R4 0x10
30 R5 0x14
31 R6 0x18
32 R7 0x1c
33 R8 0x20
34 R9 0x24
35 R10 0x28
36 R11 0x2c
37 R12 0x30
38 SP 0x34 # reserved via adding 0x20 (32) to the SP
39 LR 0x38
40 PC 0x3c
41 CPSR 0x40
42 DFSR 0x44
43 DFAR 0x48
44 IFSR 0x4c
45 IFAR 0x50
46
47 LR 0x54 # SVC Link register (we need to restore it)
48
49 LR 0x58 # pushed by srsfd
50 CPSR 0x5c
51
52 */
53
54
55 GCC_ASM_EXPORT(ExceptionHandlersStart)
56 GCC_ASM_EXPORT(ExceptionHandlersEnd)
57 GCC_ASM_EXPORT(CommonExceptionEntry)
58 GCC_ASM_EXPORT(AsmCommonExceptionEntry)
59 GCC_ASM_EXPORT(CommonCExceptionHandler)
60
61 .text
62 #if !defined(__APPLE__)
63 .fpu neon @ makes vpush/vpop assemble
64 #endif
65 .align 5
66
67
68 //
69 // This code gets copied to the ARM vector table
70 // ExceptionHandlersStart - ExceptionHandlersEnd gets copied
71 //
72 ASM_PFX(ExceptionHandlersStart):
73
74 ASM_PFX(Reset):
75 b ASM_PFX(ResetEntry)
76
77 ASM_PFX(UndefinedInstruction):
78 b ASM_PFX(UndefinedInstructionEntry)
79
80 ASM_PFX(SoftwareInterrupt):
81 b ASM_PFX(SoftwareInterruptEntry)
82
83 ASM_PFX(PrefetchAbort):
84 b ASM_PFX(PrefetchAbortEntry)
85
86 ASM_PFX(DataAbort):
87 b ASM_PFX(DataAbortEntry)
88
89 ASM_PFX(ReservedException):
90 b ASM_PFX(ReservedExceptionEntry)
91
92 ASM_PFX(Irq):
93 b ASM_PFX(IrqEntry)
94
95 ASM_PFX(Fiq):
96 b ASM_PFX(FiqEntry)
97
98 ASM_PFX(ResetEntry):
99 srsdb #0x13! @ Store return state on SVC stack
100 @ We are already in SVC mode
101
102 stmfd SP!,{LR} @ Store the link register for the current mode
103 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
104 stmfd SP!,{R0-R12} @ Store the register state
105
106 mov R0,#0 @ ExceptionType
107 ldr R1,ASM_PFX(CommonExceptionEntry)
108 bx R1
109
110 ASM_PFX(UndefinedInstructionEntry):
111 sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry
112 srsdb #0x13! @ Store return state on SVC stack
113 cps #0x13 @ Switch to SVC for common stack
114 stmfd SP!,{LR} @ Store the link register for the current mode
115 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
116 stmfd SP!,{R0-R12} @ Store the register state
117
118 mov R0,#1 @ ExceptionType
119 ldr R1,ASM_PFX(CommonExceptionEntry)
120 bx R1
121
122 ASM_PFX(SoftwareInterruptEntry):
123 sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry
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 == 0x1df))
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 str R5,[SP,#0x58] @ Update LR value pused by srsfd
240
241 NoAdjustNeeded:
242
243 str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
244
245 sub R1, SP, #0x60 @ We pused 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 /*
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 #if (FixedPcdGet32(PcdVFPEnabled))
267 vpop {d0-d15}
268 #endif
269
270 ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
271 mcr p15, 0, R1, c5, c0, 1 @ Write IFSR
272
273 ldr R1, [SP, #0x44] @ sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR
274 mcr p15, 0, R1, c5, c0, 0 @ Write DFSR
275
276 ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC
277 str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored
278
279 ldr R1,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR
280 str R1,[SP,#0x5c] @ Store it back to srsfd stack slot so it can be restored
281
282 add R3, SP, #0x54 @ Make R3 point to SVC LR saved on entry
283 add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
284 and R1, R1, #0x1f @ Check to see if User or System Mode
285 cmp R1, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))
286 cmpne R1, #0x10 @
287 ldmeqed R2, {lr}^ @ restore unbanked lr
288 @ else
289 ldmneed R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR}
290
291 ldmfd SP!,{R0-R12} @ Restore general purpose registers
292 @ Exception handler can not change SP
293
294 add SP,SP,#0x20 @ Clear out the remaining stack space
295 ldmfd SP!,{LR} @ restore the link register for this context
296 rfefd SP! @ return from exception via srsfd stack slot
297