1#------------------------------------------------------------------------------
2#
3# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
4# Copyright (c) 2011 - 2012, ARM Ltd. All rights reserved.<BR>
5#
6# This program and the accompanying materials
7# are licensed and made available under the terms and conditions of the BSD License
8# which accompanies this distribution.  The full text of the license may be found at
9# http://opensource.org/licenses/bsd-license.php
10#
11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13#
14#------------------------------------------------------------------------------
15
16#include <Library/PcdLib.h>
17
18/*
19
20This is the stack constructed by the exception handler (low address to high address)
21                # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM
22  Reg   Offset
23  ===   ======
24  R0    0x00    # stmfd     SP!,{R0-R12}
25  R1    0x04
26  R2    0x08
27  R3    0x0c
28  R4    0x10
29  R5    0x14
30  R6    0x18
31  R7    0x1c
32  R8    0x20
33  R9    0x24
34  R10   0x28
35  R11   0x2c
36  R12   0x30
37  SP    0x34    # reserved via adding 0x20 (32) to the SP
38  LR    0x38
39  PC    0x3c
40  CPSR  0x40
41  DFSR  0x44
42  DFAR  0x48
43  IFSR  0x4c
44  IFAR  0x50
45
46  LR    0x54    # SVC Link register (we need to restore it)
47
48  LR    0x58    # pushed by srsfd
49  CPSR  0x5c
50
51 */
52
53GCC_ASM_EXPORT(DebugAgentVectorTable)
54GCC_ASM_IMPORT(DefaultExceptionHandler)
55
56.text
57#if !defined(__APPLE__)
58.fpu neon    @ makes vpush/vpop assemble
59#endif
60.align 5
61
62
63//
64// This code gets copied to the ARM vector table
65// ExceptionHandlersStart - ExceptionHandlersEnd gets copied
66//
67ASM_PFX(DebugAgentVectorTable):
68  b ASM_PFX(ResetEntry)
69  b ASM_PFX(UndefinedInstructionEntry)
70  b ASM_PFX(SoftwareInterruptEntry)
71  b ASM_PFX(PrefetchAbortEntry)
72  b ASM_PFX(DataAbortEntry)
73  b ASM_PFX(ReservedExceptionEntry)
74  b ASM_PFX(IrqEntry)
75  b ASM_PFX(FiqEntry)
76
77ASM_PFX(ResetEntry):
78  srsdb     #0x13!                    @ Store return state on SVC stack
79                                      @ We are already in SVC mode
80
81  stmfd     SP!,{LR}                  @ Store the link register for the current mode
82  sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
83  stmfd     SP!,{R0-R12}              @ Store the register state
84
85  mov       R0,#0                     @ ExceptionType
86  ldr       R1,ASM_PFX(CommonExceptionEntry)
87  bx        R1
88
89ASM_PFX(UndefinedInstructionEntry):
90  sub       LR, LR, #4                @ Only -2 for Thumb, adjust in CommonExceptionEntry
91  srsdb     #0x13!                    @ Store return state on SVC stack
92  cps       #0x13                     @ Switch to SVC for common stack
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,#1                     @ ExceptionType
98  ldr       R1,ASM_PFX(CommonExceptionEntry)
99  bx        R1
100
101ASM_PFX(SoftwareInterruptEntry):
102  sub       LR, LR, #4                @ Only -2 for Thumb, adjust in CommonExceptionEntry
103  srsdb     #0x13!                    @ Store return state on SVC stack
104                                      @ We are already in SVC mode
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,#2                     @ ExceptionType
110  ldr       R1,ASM_PFX(CommonExceptionEntry)
111  bx        R1
112
113ASM_PFX(PrefetchAbortEntry):
114  sub       LR,LR,#4
115  srsdb     #0x13!                    @ Store return state on SVC stack
116  cps       #0x13                     @ Switch to SVC for common stack
117  stmfd     SP!,{LR}                  @ Store the link register for the current mode
118  sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
119  stmfd     SP!,{R0-R12}              @ Store the register state
120
121  mov       R0,#3                     @ ExceptionType
122  ldr       R1,ASM_PFX(CommonExceptionEntry)
123  bx        R1
124
125ASM_PFX(DataAbortEntry):
126  sub       LR,LR,#8
127  srsdb     #0x13!                    @ Store return state on SVC stack
128  cps       #0x13                     @ Switch to SVC for common stack
129  stmfd     SP!,{LR}                  @ Store the link register for the current mode
130  sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
131  stmfd     SP!,{R0-R12}              @ Store the register state
132
133  mov       R0,#4
134  ldr       R1,ASM_PFX(CommonExceptionEntry)
135  bx        R1
136
137ASM_PFX(ReservedExceptionEntry):
138  srsdb     #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,#5
145  ldr       R1,ASM_PFX(CommonExceptionEntry)
146  bx        R1
147
148ASM_PFX(IrqEntry):
149  sub       LR,LR,#4
150  srsdb     #0x13!                    @ Store return state on SVC stack
151  cps       #0x13                     @ Switch to SVC for common stack
152  stmfd     SP!,{LR}                  @ Store the link register for the current mode
153  sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
154  stmfd     SP!,{R0-R12}              @ Store the register state
155
156  mov       R0,#6                     @ ExceptionType
157  ldr       R1,ASM_PFX(CommonExceptionEntry)
158  bx        R1
159
160ASM_PFX(FiqEntry):
161  sub       LR,LR,#4
162  srsdb     #0x13!                    @ Store return state on SVC stack
163  cps       #0x13                     @ Switch to SVC for common stack
164  stmfd     SP!,{LR}                  @ Store the link register for the current mode
165  sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
166  stmfd     SP!,{R0-R12}              @ Store the register state
167                                      @ Since we have already switch to SVC R8_fiq - R12_fiq
168                                      @ never get used or saved
169  mov       R0,#7                     @ ExceptionType
170  ldr       R1,ASM_PFX(CommonExceptionEntry)
171  bx        R1
172
173//
174// This gets patched by the C code that patches in the vector table
175//
176ASM_PFX(CommonExceptionEntry):
177  .word       ASM_PFX(AsmCommonExceptionEntry)
178
179ASM_PFX(ExceptionHandlersEnd):
180
181//
182// This code runs from CpuDxe driver loaded address. It is patched into
183// CommonExceptionEntry.
184//
185ASM_PFX(AsmCommonExceptionEntry):
186  mrc       p15, 0, R1, c6, c0, 2   @ Read IFAR
187  str       R1, [SP, #0x50]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
188
189  mrc       p15, 0, R1, c5, c0, 1   @ Read IFSR
190  str       R1, [SP, #0x4c]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
191
192  mrc       p15, 0, R1, c6, c0, 0   @ Read DFAR
193  str       R1, [SP, #0x48]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
194
195  mrc       p15, 0, R1, c5, c0, 0   @ Read DFSR
196  str       R1, [SP, #0x44]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
197
198  ldr       R1, [SP, #0x5c]         @ srsdb saved pre-exception CPSR on the stack
199  str       R1, [SP, #0x40]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
200
201  add       R2, SP, #0x38           @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
202  and       R3, R1, #0x1f           @ Check CPSR to see if User or System Mode
203  cmp       R3, #0x1f               @ if ((CPSR == 0x10) || (CPSR == 0x1df))
204  cmpne     R3, #0x10               @
205  stmeqed   R2, {lr}^               @   save unbanked lr
206                                    @ else
207  stmneed   R2, {lr}                @   save SVC lr
208
209
210  ldr       R5, [SP, #0x58]         @ PC is the LR pushed by srsfd
211                                    @ Check to see if we have to adjust for Thumb entry
212  sub       r4, r0, #1              @ if (ExceptionType == 1 || ExceptionType ==2)) {
213  cmp       r4, #1                  @   // UND & SVC have differnt LR adjust for Thumb
214  bhi       NoAdjustNeeded
215
216  tst       r1, #0x20               @   if ((CPSR & T)) == T) {  // Thumb Mode on entry
217  addne     R5, R5, #2              @     PC += 2@
218  str       R5,[SP,#0x58]           @ Update LR value pused by srsfd
219
220NoAdjustNeeded:
221
222  str       R5, [SP, #0x3c]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
223
224  sub       R1, SP, #0x60           @ We pused 0x60 bytes on the stack
225  str       R1, [SP, #0x34]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP
226
227                                    @ R0 is ExceptionType
228  mov       R1,SP                   @ R1 is SystemContext
229
230#if (FixedPcdGet32(PcdVFPEnabled))
231  vpush     {d0-d15}                @ save vstm registers in case they are used in optimizations
232#endif
233
234/*
235VOID
236EFIAPI
237DefaultExceptionHandler (
238  IN     EFI_EXCEPTION_TYPE           ExceptionType,   R0
239  IN OUT EFI_SYSTEM_CONTEXT           SystemContext    R1
240  )
241
242*/
243  blx       ASM_PFX(DefaultExceptionHandler)  @ Call exception handler
244
245#if (FixedPcdGet32(PcdVFPEnabled))
246  vpop      {d0-d15}
247#endif
248
249  ldr       R1, [SP, #0x4c]         @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
250  mcr       p15, 0, R1, c5, c0, 1   @ Write IFSR
251
252  ldr       R1, [SP, #0x44]         @ sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR
253  mcr       p15, 0, R1, c5, c0, 0   @ Write DFSR
254
255  ldr       R1,[SP,#0x3c]           @ EFI_SYSTEM_CONTEXT_ARM.PC
256  str       R1,[SP,#0x58]           @ Store it back to srsfd stack slot so it can be restored
257
258  ldr       R1,[SP,#0x40]           @ EFI_SYSTEM_CONTEXT_ARM.CPSR
259  str       R1,[SP,#0x5c]           @ Store it back to srsfd stack slot so it can be restored
260
261  add       R3, SP, #0x54           @ Make R3 point to SVC LR saved on entry
262  add       R2, SP, #0x38           @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
263  and       R1, R1, #0x1f           @ Check to see if User or System Mode
264  cmp       R1, #0x1f               @ if ((CPSR == 0x10) || (CPSR == 0x1f))
265  cmpne     R1, #0x10               @
266  ldmeqed   R2, {lr}^               @   restore unbanked lr
267                                    @ else
268  ldmneed   R3, {lr}                @   restore SVC lr, via ldmfd SP!, {LR}
269
270  ldmfd     SP!,{R0-R12}            @ Restore general purpose registers
271                                    @ Exception handler can not change SP
272
273  add       SP,SP,#0x20             @ Clear out the remaining stack space
274  ldmfd     SP!,{LR}                @ restore the link register for this context
275  rfefd     SP!                     @ return from exception via srsfd stack slot
276
277