]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S
646aca76a405de2c413cfc76bc9a09b2d7583aea
[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.
6 #
7 # All rights reserved. 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 .align 3
61
62
63 //
64 // This code gets copied to the ARM vector table
65 // ExceptionHandlersStart - ExceptionHandlersEnd gets copied
66 //
67 ASM_PFX(ExceptionHandlersStart):
68
69 ASM_PFX(Reset):
70 b ASM_PFX(ResetEntry)
71
72 ASM_PFX(UndefinedInstruction):
73 b ASM_PFX(UndefinedInstructionEntry)
74
75 ASM_PFX(SoftwareInterrupt):
76 b ASM_PFX(SoftwareInterruptEntry)
77
78 ASM_PFX(PrefetchAbort):
79 b ASM_PFX(PrefetchAbortEntry)
80
81 ASM_PFX(DataAbort):
82 b ASM_PFX(DataAbortEntry)
83
84 ASM_PFX(ReservedException):
85 b ASM_PFX(ReservedExceptionEntry)
86
87 ASM_PFX(Irq):
88 b ASM_PFX(IrqEntry)
89
90 ASM_PFX(Fiq):
91 b ASM_PFX(FiqEntry)
92
93 ASM_PFX(ResetEntry):
94 srsdb #0x13! @ Store return state on SVC stack
95 @ We are already in SVC mode
96
97 stmfd SP!,{LR} @ Store the link register for the current mode
98 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
99 stmfd SP!,{R0-R12} @ Store the register state
100
101 mov R0,#0 @ ExceptionType
102 ldr R1,ASM_PFX(CommonExceptionEntry)
103 bx R1
104
105 ASM_PFX(UndefinedInstructionEntry):
106 sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry
107 srsdb #0x13! @ Store return state on SVC stack
108 cps #0x13 @ Switch to SVC for common stack
109 stmfd SP!,{LR} @ Store the link register for the current mode
110 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
111 stmfd SP!,{R0-R12} @ Store the register state
112
113 mov R0,#1 @ ExceptionType
114 ldr R1,ASM_PFX(CommonExceptionEntry)
115 bx R1
116
117 ASM_PFX(SoftwareInterruptEntry):
118 sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry
119 srsdb #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,ASM_PFX(CommonExceptionEntry)
127 bx R1
128
129 ASM_PFX(PrefetchAbortEntry):
130 sub LR,LR,#4
131 srsdb #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,ASM_PFX(CommonExceptionEntry)
139 bx R1
140
141 ASM_PFX(DataAbortEntry):
142 sub LR,LR,#8
143 srsdb #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
150 ldr R1,ASM_PFX(CommonExceptionEntry)
151 bx R1
152
153 ASM_PFX(ReservedExceptionEntry):
154 srsdb #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
161 ldr R1,ASM_PFX(CommonExceptionEntry)
162 bx R1
163
164 ASM_PFX(IrqEntry):
165 sub LR,LR,#4
166 srsdb #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,ASM_PFX(CommonExceptionEntry)
174 bx R1
175
176 ASM_PFX(FiqEntry):
177 sub LR,LR,#4
178 srsdb #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,ASM_PFX(CommonExceptionEntry)
187 bx R1
188
189 //
190 // This gets patched by the C code that patches in the vector table
191 //
192 ASM_PFX(CommonExceptionEntry):
193 .byte 0x12
194 .byte 0x34
195 .byte 0x56
196 .byte 0x78
197
198 ASM_PFX(ExceptionHandlersEnd):
199
200 //
201 // This code runs from CpuDxe driver loaded address. It is patched into
202 // CommonExceptionEntry.
203 //
204 ASM_PFX(AsmCommonExceptionEntry):
205 mrc p15, 0, R1, c6, c0, 2 @ Read IFAR
206 str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
207
208 mrc p15, 0, R1, c5, c0, 1 @ Read IFSR
209 str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
210
211 mrc p15, 0, R1, c6, c0, 0 @ Read DFAR
212 str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
213
214 mrc p15, 0, R1, c5, c0, 0 @ Read DFSR
215 str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
216
217 ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack
218 str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
219
220 add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
221 and R3, R1, #0x1f @ Check CPSR to see if User or System Mode
222 cmp R3, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1df))
223 cmpne R3, #0x10 @
224 stmeqed R2, {lr}^ @ save unbanked lr
225 @ else
226 stmneed R2, {lr} @ save SVC lr
227
228
229 ldr R5, [SP, #0x58] @ PC is the LR pushed by srsfd
230 @ Check to see if we have to adjust for Thumb entry
231 sub r4, r0, #1 @ if (ExceptionType == 1 || ExceptionType ==2)) {
232 cmp r4, #1 @ // UND & SVC have differnt LR adjust for Thumb
233 bhi NoAdjustNeeded
234
235 tst r1, #0x20 @ if ((CPSR & T)) == T) { // Thumb Mode on entry
236 addne R5, R5, #2 @ PC += 2@
237 str R5,[SP,#0x58] @ Update LR value pused by srsfd
238
239 NoAdjustNeeded:
240
241 str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
242
243 sub R1, SP, #0x60 @ We pused 0x60 bytes on the stack
244 str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP
245
246 @ R0 is ExceptionType
247 mov R1,SP @ R1 is SystemContext
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 ASM_PFX(CommonCExceptionHandler) @ Call exception handler
259
260 ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC
261 str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored
262
263 ldr R1,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR
264 str R1,[SP,#0x5c] @ Store it back to srsfd stack slot so it can be restored
265
266 add R3, SP, #0x54 @ Make R3 point to SVC LR saved on entry
267 add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
268 and R1, R1, #0x1f @ Check to see if User or System Mode
269 cmp R1, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))
270 cmpne R1, #0x10 @
271 ldmeqed R2, {lr}^ @ restore unbanked lr
272 @ else
273 ldmneed R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR}
274
275 ldmfd SP!,{R0-R12} @ Restore general purpose registers
276 @ Exception handler can not change SP
277
278 add SP,SP,#0x20 @ Clear out the remaining stack space
279 ldmfd SP!,{LR} @ restore the link register for this context
280 rfefd SP! @ return from exception via srsfd stack slot
281