]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm
240e1e38ae7d788331c1a57a067fbd50acb582b4
[mirror_edk2.git] / ArmPkg / Drivers / CpuDxe / ExceptionSupport.ARMv6.asm
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 EXPORT ExceptionHandlersStart
56 EXPORT ExceptionHandlersEnd
57 EXPORT CommonExceptionEntry
58 EXPORT AsmCommonExceptionEntry
59 IMPORT CommonCExceptionHandler
60
61 PRESERVE8
62 AREA DxeExceptionHandlers, CODE, READONLY
63
64 ALIGN 32
65
66 //
67 // This code gets copied to the ARM vector table
68 // ExceptionHandlersStart - ExceptionHandlersEnd gets copied
69 //
70 ExceptionHandlersStart
71
72 Reset
73 b ResetEntry
74
75 UndefinedInstruction
76 b UndefinedInstructionEntry
77
78 SoftwareInterrupt
79 b SoftwareInterruptEntry
80
81 PrefetchAbort
82 b PrefetchAbortEntry
83
84 DataAbort
85 b DataAbortEntry
86
87 ReservedException
88 b ReservedExceptionEntry
89
90 Irq
91 b IrqEntry
92
93 Fiq
94 b FiqEntry
95
96 ResetEntry
97 srsfd #0x13! ; Store return state on SVC stack
98 ; 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
102
103 mov R0,#0 ; ExceptionType
104 ldr R1,CommonExceptionEntry
105 bx R1
106
107 UndefinedInstructionEntry
108 sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry
109 srsfd #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,CommonExceptionEntry;
117 bx R1
118
119 SoftwareInterruptEntry
120 sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry
121 srsfd #0x13! ; Store return state on SVC stack
122 ; We are already in SVC mode
123 stmfd SP!,{LR} ; Store the link register for the current mode
124 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
125 stmfd SP!,{R0-R12} ; Store the register state
126
127 mov R0,#2 ; ExceptionType
128 ldr R1,CommonExceptionEntry
129 bx R1
130
131 PrefetchAbortEntry
132 sub LR,LR,#4
133 srsfd #0x13! ; Store return state on SVC stack
134 cps #0x13 ; Switch to SVC for common stack
135 stmfd SP!,{LR} ; Store the link register for the current mode
136 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
137 stmfd SP!,{R0-R12} ; Store the register state
138
139 mov R0,#3 ; ExceptionType
140 ldr R1,CommonExceptionEntry
141 bx R1
142
143 DataAbortEntry
144 sub LR,LR,#8
145 srsfd #0x13! ; Store return state on SVC stack
146 cps #0x13 ; Switch to SVC for common stack
147 stmfd SP!,{LR} ; Store the link register for the current mode
148 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
149 stmfd SP!,{R0-R12} ; Store the register state
150
151 mov R0,#4 ; ExceptionType
152 ldr R1,CommonExceptionEntry
153 bx R1
154
155 ReservedExceptionEntry
156 srsfd #0x13! ; Store return state on SVC stack
157 cps #0x13 ; Switch to SVC for common stack
158 stmfd SP!,{LR} ; Store the link register for the current mode
159 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
160 stmfd SP!,{R0-R12} ; Store the register state
161
162 mov R0,#5 ; ExceptionType
163 ldr R1,CommonExceptionEntry
164 bx R1
165
166 IrqEntry
167 sub LR,LR,#4
168 srsfd #0x13! ; Store return state on SVC stack
169 cps #0x13 ; Switch to SVC for common stack
170 stmfd SP!,{LR} ; Store the link register for the current mode
171 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
172 stmfd SP!,{R0-R12} ; Store the register state
173
174 mov R0,#6 ; ExceptionType
175 ldr R1,CommonExceptionEntry
176 bx R1
177
178 FiqEntry
179 sub LR,LR,#4
180 srsfd #0x13! ; Store return state on SVC stack
181 cps #0x13 ; Switch to SVC for common stack
182 stmfd SP!,{LR} ; Store the link register for the current mode
183 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR
184 stmfd SP!,{R0-R12} ; Store the register state
185 ; Since we have already switch to SVC R8_fiq - R12_fiq
186 ; never get used or saved
187 mov R0,#7 ; ExceptionType
188 ldr R1,CommonExceptionEntry
189 bx R1
190
191 //
192 // This gets patched by the C code that patches in the vector table
193 //
194 CommonExceptionEntry
195 dcd AsmCommonExceptionEntry
196
197 ExceptionHandlersEnd
198
199 //
200 // This code runs from CpuDxe driver loaded address. It is patched into
201 // CommonExceptionEntry.
202 //
203 AsmCommonExceptionEntry
204 mrc p15, 0, R1, c6, c0, 2 ; Read IFAR
205 str R1, [SP, #0x50] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
206
207 mrc p15, 0, R1, c5, c0, 1 ; Read IFSR
208 str R1, [SP, #0x4c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
209
210 mrc p15, 0, R1, c6, c0, 0 ; Read DFAR
211 str R1, [SP, #0x48] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
212
213 mrc p15, 0, R1, c5, c0, 0 ; Read DFSR
214 str R1, [SP, #0x44] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
215
216 ldr R1, [SP, #0x5c] ; srsfd saved pre-exception CPSR on the stack
217 str R1, [SP, #0x40] ; Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
218
219 add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
220 and R3, R1, #0x1f ; Check CPSR to see if User or System Mode
221 cmp R3, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1df))
222 cmpne R3, #0x10 ;
223 stmeqed R2, {lr}^ ; save unbanked lr
224 ; else
225 stmneed R2, {lr} ; save SVC lr
226
227
228 ldr R5, [SP, #0x58] ; PC is the LR pushed by srsfd
229 ; Check to see if we have to adjust for Thumb entry
230 sub r4, r0, #1 ; if (ExceptionType == 1 || ExceptionType ==2)) {
231 cmp r4, #1 ; // UND & SVC have differnt LR adjust for Thumb
232 bhi NoAdjustNeeded
233
234 tst r1, #0x20 ; if ((CPSR & T)) == T) { // Thumb Mode on entry
235 addne R5, R5, #2 ; PC += 2;
236 str R5,[SP,#0x58] ; Update LR value pused by srsfd
237
238 NoAdjustNeeded
239
240 str R5, [SP, #0x3c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.PC
241
242 sub R1, SP, #0x60 ; We pused 0x60 bytes on the stack
243 str R1, [SP, #0x34] ; Store it in EFI_SYSTEM_CONTEXT_ARM.SP
244
245 ; R0 is ExceptionType
246 mov R1,SP ; R1 is SystemContext
247
248 #if (FixedPcdGet32(PcdVFPEnabled))
249 vpush {d0-d15} ; save vstm registers in case they are used in optimizations
250 #endif
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 CommonCExceptionHandler ; Call exception handler
262
263 #if (FixedPcdGet32(PcdVFPEnabled))
264 vpop {d0-d15}
265 #endif
266
267 ldr R1, [SP, #0x4c] ; Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
268 mcr p15, 0, R1, c5, c0, 1 ; Write IFSR
269
270 ldr R1, [SP, #0x44] ; sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR
271 mcr p15, 0, R1, c5, c0, 0 ; Write DFSR
272
273 ldr R1,[SP,#0x3c] ; EFI_SYSTEM_CONTEXT_ARM.PC
274 str R1,[SP,#0x58] ; Store it back to srsfd stack slot so it can be restored
275
276 ldr R1,[SP,#0x40] ; EFI_SYSTEM_CONTEXT_ARM.CPSR
277 str R1,[SP,#0x5c] ; Store it back to srsfd stack slot so it can be restored
278
279 add R3, SP, #0x54 ; Make R3 point to SVC LR saved on entry
280 add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
281 and R1, R1, #0x1f ; Check to see if User or System Mode
282 cmp R1, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1f))
283 cmpne R1, #0x10 ;
284 ldmeqed R2, {lr}^ ; restore unbanked lr
285 ; else
286 ldmneed R3, {lr} ; restore SVC lr, via ldmfd SP!, {LR}
287
288 ldmfd SP!,{R0-R12} ; Restore general purpose registers
289 ; Exception handler can not change SP
290
291 add SP,SP,#0x20 ; Clear out the remaining stack space
292 ldmfd SP!,{LR} ; restore the link register for this context
293 rfefd SP! ; return from exception via srsfd stack slot
294
295 END
296
297