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