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