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