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