a4e165fdc7fe24f593fd9b5c9b6456d264478560
[mirror_edk2.git] / ArmPkg / Drivers / CpuDxe / ExceptionSupport.ARMv6.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 /*
18
19 This is the stack constructed by the exception handler (low address to high address)
20 # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM
21 Reg Offset
22 === ======
23 R0 0x00 # stmfd SP!,{R0-R12}
24 R1 0x04
25 R2 0x08
26 R3 0x0c
27 R4 0x10
28 R5 0x14
29 R6 0x18
30 R7 0x1c
31 R8 0x20
32 R9 0x24
33 R10 0x28
34 R11 0x2c
35 R12 0x30
36 SP 0x34 # reserved via adding 0x20 (32) to the SP
37 LR 0x38
38 PC 0x3c
39 CPSR 0x40
40 DFSR 0x44
41 DFAR 0x48
42 IFSR 0x4c
43 IFAR 0x50
44
45 LR 0x54 # SVC Link register (we need to restore it)
46
47 LR 0x58 # pushed by srsfd
48 CPSR 0x5c
49
50 */
51
52
53 .globl ASM_PFX(ExceptionHandlersStart)
54 .globl ASM_PFX(ExceptionHandlersEnd)
55 .globl ASM_PFX(CommonExceptionEntry)
56 .globl ASM_PFX(AsmCommonExceptionEntry)
57 .globl ASM_PFX(CommonCExceptionHandler)
58
59 .text
60 .fpu neon @ makes vpush/vpop assemble
61 .align 3
62
63
64 //
65 // This code gets copied to the ARM vector table
66 // ExceptionHandlersStart - ExceptionHandlersEnd gets copied
67 //
68 ASM_PFX(ExceptionHandlersStart):
69
70 ASM_PFX(Reset):
71 b ASM_PFX(ResetEntry)
72
73 ASM_PFX(UndefinedInstruction):
74 b ASM_PFX(UndefinedInstructionEntry)
75
76 ASM_PFX(SoftwareInterrupt):
77 b ASM_PFX(SoftwareInterruptEntry)
78
79 ASM_PFX(PrefetchAbort):
80 b ASM_PFX(PrefetchAbortEntry)
81
82 ASM_PFX(DataAbort):
83 b ASM_PFX(DataAbortEntry)
84
85 ASM_PFX(ReservedException):
86 b ASM_PFX(ReservedExceptionEntry)
87
88 ASM_PFX(Irq):
89 b ASM_PFX(IrqEntry)
90
91 ASM_PFX(Fiq):
92 b ASM_PFX(FiqEntry)
93
94 ASM_PFX(ResetEntry):
95 srsdb #0x13! @ Store return state on SVC stack
96 @ We are already in SVC mode
97
98 stmfd SP!,{LR} @ Store the link register for the current mode
99 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
100 stmfd SP!,{R0-R12} @ Store the register state
101
102 mov R0,#0 @ ExceptionType
103 ldr R1,ASM_PFX(CommonExceptionEntry)
104 bx R1
105
106 ASM_PFX(UndefinedInstructionEntry):
107 sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry
108 srsdb #0x13! @ Store return state on SVC stack
109 cps #0x13 @ Switch to SVC for common stack
110 stmfd SP!,{LR} @ Store the link register for the current mode
111 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
112 stmfd SP!,{R0-R12} @ Store the register state
113
114 mov R0,#1 @ ExceptionType
115 ldr R1,ASM_PFX(CommonExceptionEntry)
116 bx R1
117
118 ASM_PFX(SoftwareInterruptEntry):
119 sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry
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 .byte 0x12
195 .byte 0x34
196 .byte 0x56
197 .byte 0x78
198
199 ASM_PFX(ExceptionHandlersEnd):
200
201 //
202 // This code runs from CpuDxe driver loaded address. It is patched into
203 // CommonExceptionEntry.
204 //
205 ASM_PFX(AsmCommonExceptionEntry):
206 mrc p15, 0, R1, c6, c0, 2 @ Read IFAR
207 str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
208
209 mrc p15, 0, R1, c5, c0, 1 @ Read IFSR
210 str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
211
212 mrc p15, 0, R1, c6, c0, 0 @ Read DFAR
213 str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
214
215 mrc p15, 0, R1, c5, c0, 0 @ Read DFSR
216 str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
217
218 ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack
219 str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
220
221 add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
222 and R3, R1, #0x1f @ Check CPSR to see if User or System Mode
223 cmp R3, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1df))
224 cmpne R3, #0x10 @
225 stmeqed R2, {lr}^ @ save unbanked lr
226 @ else
227 stmneed R2, {lr} @ save SVC lr
228
229
230 ldr R5, [SP, #0x58] @ PC is the LR pushed by srsfd
231 @ Check to see if we have to adjust for Thumb entry
232 sub r4, r0, #1 @ if (ExceptionType == 1 || ExceptionType ==2)) {
233 cmp r4, #1 @ // UND & SVC have differnt LR adjust for Thumb
234 bhi NoAdjustNeeded
235
236 tst r1, #0x20 @ if ((CPSR & T)) == T) { // Thumb Mode on entry
237 addne R5, R5, #2 @ PC += 2@
238 str R5,[SP,#0x58] @ Update LR value pused by srsfd
239
240 NoAdjustNeeded:
241
242 str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
243
244 sub R1, SP, #0x60 @ We pused 0x60 bytes on the stack
245 str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP
246
247 @ R0 is ExceptionType
248 mov R1,SP @ R1 is SystemContext
249
250 vpush {d0-d15} @ save vstm registers in case they are used in optimizations
251
252 /*
253 VOID
254 EFIAPI
255 CommonCExceptionHandler (
256 IN EFI_EXCEPTION_TYPE ExceptionType, R0
257 IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
258 )
259
260 */
261 blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler
262
263 vpop {d0-d15}
264
265 ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
266 mcr p15, 0, R1, c5, c0, 1 @ Write IFSR
267
268 ldr R1, [SP, #0x44] @ sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR
269 mcr p15, 0, R1, c5, c0, 0 @ Write DFSR
270
271 ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC
272 str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored
273
274 ldr R1,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR
275 str R1,[SP,#0x5c] @ Store it back to srsfd stack slot so it can be restored
276
277 add R3, SP, #0x54 @ Make R3 point to SVC LR saved on entry
278 add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
279 and R1, R1, #0x1f @ Check to see if User or System Mode
280 cmp R1, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))
281 cmpne R1, #0x10 @
282 ldmeqed R2, {lr}^ @ restore unbanked lr
283 @ else
284 ldmneed R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR}
285
286 ldmfd SP!,{R0-R12} @ Restore general purpose registers
287 @ Exception handler can not change SP
288
289 add SP,SP,#0x20 @ Clear out the remaining stack space
290 ldmfd SP!,{LR} @ restore the link register for this context
291 rfefd SP! @ return from exception via srsfd stack slot
292