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#
7# 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
19This 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
53GCC_ASM_EXPORT(ExceptionHandlersStart)
54GCC_ASM_EXPORT(ExceptionHandlersEnd)
55GCC_ASM_EXPORT(CommonExceptionEntry)
56GCC_ASM_EXPORT(AsmCommonExceptionEntry)
57GCC_ASM_EXPORT(GdbExceptionHandler)
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//
67ASM_PFX(ExceptionHandlersStart):
68
69ASM_PFX(Reset):
70  b ASM_PFX(Reset)
71
72ASM_PFX(UndefinedInstruction):
73  b ASM_PFX(UndefinedInstructionEntry)
74
75ASM_PFX(SoftwareInterrupt):
76  b ASM_PFX(SoftwareInterruptEntry)
77
78ASM_PFX(PrefetchAbort):
79  b ASM_PFX(PrefetchAbortEntry)
80
81ASM_PFX(DataAbort):
82  b ASM_PFX(DataAbortEntry)
83
84ASM_PFX(ReservedException):
85  b ASM_PFX(ReservedExceptionEntry)
86
87ASM_PFX(Irq):
88  b ASM_PFX(Irq)
89
90ASM_PFX(Fiq):
91  b ASM_PFX(FiqEntry)
92
93
94ASM_PFX(UndefinedInstructionEntry):
95  sub       LR, LR, #4                @ Only -2 for Thumb, adjust in CommonExceptionEntry
96  srsdb     #0x13!                    @ Store return state on SVC stack
97  cpsid     f,#0x13                   @ Switch to SVC for common stack
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,#1                     @ ExceptionType
103  ldr       R1,ASM_PFX(CommonExceptionEntry)
104  bx        R1
105
106ASM_PFX(SoftwareInterruptEntry):
107  sub       LR, LR, #4                @ Only -2 for Thumb, adjust in CommonExceptionEntry
108  srsdb     #0x13!                    @ Store return state on SVC stack
109  cpsid     f                         @ We are already in SVC mode
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,#2                     @ ExceptionType
115  ldr       R1,ASM_PFX(CommonExceptionEntry)
116  bx        R1
117
118ASM_PFX(PrefetchAbortEntry):
119  sub       LR,LR,#4
120  srsdb     #0x13!                    @ Store return state on SVC stack
121  cpsid     f,#0x13                   @ Switch to SVC for common stack
122  stmfd     SP!,{LR}                  @ Store the link register for the current mode
123  sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
124  stmfd     SP!,{R0-R12}              @ Store the register state
125
126  mov       R0,#3                     @ ExceptionType
127  ldr       R1,ASM_PFX(CommonExceptionEntry)
128  bx        R1
129
130ASM_PFX(DataAbortEntry):
131  sub       LR,LR,#8
132  srsdb     #0x13!                    @ Store return state on SVC stack
133  cpsid     f,#0x13                   @ Switch to SVC for common stack
134  stmfd     SP!,{LR}                  @ Store the link register for the current mode
135  sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
136  stmfd     SP!,{R0-R12}              @ Store the register state
137
138  mov       R0,#4
139  ldr       R1,ASM_PFX(CommonExceptionEntry)
140  bx        R1
141
142ASM_PFX(ReservedExceptionEntry):
143  srsdb     #0x13!                    @ Store return state on SVC stack
144  cpsid     f,#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,#5
150  ldr       R1,ASM_PFX(CommonExceptionEntry)
151  bx        R1
152
153ASM_PFX(FiqEntry):
154  sub       LR,LR,#4
155  srsdb     #0x13!                    @ Store return state on SVC stack
156  cps       #0x13                     @ Switch to SVC for common stack
157  stmfd     SP!,{LR}                  @ Store the link register for the current mode
158  sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
159  stmfd     SP!,{R0-R12}              @ Store the register state
160                                      @ Since we have already switch to SVC R8_fiq - R12_fiq
161                                      @ never get used or saved
162  mov       R0,#7                     @ ExceptionType
163  ldr       R1,ASM_PFX(CommonExceptionEntry)
164  bx        R1
165
166//
167// This gets patched by the C code that patches in the vector table
168//
169ASM_PFX(CommonExceptionEntry):
170  .byte       0x12
171  .byte       0x34
172  .byte       0x56
173  .byte       0x78
174
175ASM_PFX(ExceptionHandlersEnd):
176
177//
178// This code runs from CpuDxe driver loaded address. It is patched into
179// CommonExceptionEntry.
180//
181ASM_PFX(AsmCommonExceptionEntry):
182  mrc       p15, 0, R1, c6, c0, 2   @ Read IFAR
183  str       R1, [SP, #0x50]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
184
185  mrc       p15, 0, R1, c5, c0, 1   @ Read IFSR
186  str       R1, [SP, #0x4c]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
187
188  mrc       p15, 0, R1, c6, c0, 0   @ Read DFAR
189  str       R1, [SP, #0x48]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
190
191  mrc       p15, 0, R1, c5, c0, 0   @ Read DFSR
192  str       R1, [SP, #0x44]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
193
194  ldr       R1, [SP, #0x5c]         @ srsdb saved pre-exception CPSR on the stack
195  str       R1, [SP, #0x40]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
196
197  add       R2, SP, #0x38           @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
198  and       R3, R1, #0x1f           @ Check CPSR to see if User or System Mode
199  cmp       R3, #0x1f               @ if ((CPSR == 0x10) || (CPSR == 0x1df))
200  cmpne     R3, #0x10               @
201  stmeqed   R2, {lr}^               @   save unbanked lr
202                                    @ else
203  stmneed   R2, {lr}                @   save SVC lr
204
205
206  ldr       R5, [SP, #0x58]         @ PC is the LR pushed by srsfd
207                                    @ Check to see if we have to adjust for Thumb entry
208  sub       r4, r0, #1              @ if (ExceptionType == 1 || ExceptionType ==2)) {
209  cmp       r4, #1                  @   // UND & SVC have differnt LR adjust for Thumb
210  bhi       NoAdjustNeeded
211
212  tst       r1, #0x20               @   if ((CPSR & T)) == T) {  // Thumb Mode on entry
213  addne     R5, R5, #2              @     PC += 2@
214  str       R5,[SP,#0x58]           @ Update LR value pused by srsfd
215
216NoAdjustNeeded:
217
218  str       R5, [SP, #0x3c]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
219
220  sub       R1, SP, #0x60           @ We pused 0x60 bytes on the stack
221  str       R1, [SP, #0x34]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP
222
223                                    @ R0 is ExceptionType
224  mov       R1,SP                   @ R1 is SystemContext
225
226/*
227VOID
228EFIAPI
229GdbExceptionHandler (
230  IN     EFI_EXCEPTION_TYPE           ExceptionType,   R0
231  IN OUT EFI_SYSTEM_CONTEXT           SystemContext    R1
232  )
233
234*/
235  blx       ASM_PFX(GdbExceptionHandler)  @ Call exception handler
236
237  ldr       R1,[SP,#0x3c]           @ EFI_SYSTEM_CONTEXT_ARM.PC
238  str       R1,[SP,#0x58]           @ Store it back to srsfd stack slot so it can be restored
239
240  ldr       R1,[SP,#0x40]           @ EFI_SYSTEM_CONTEXT_ARM.CPSR
241  str       R1,[SP,#0x5c]           @ Store it back to srsfd stack slot so it can be restored
242
243  add       R3, SP, #0x54           @ Make R3 point to SVC LR saved on entry
244  add       R2, SP, #0x38           @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
245  and       R1, R1, #0x1f           @ Check to see if User or System Mode
246  cmp       R1, #0x1f               @ if ((CPSR == 0x10) || (CPSR == 0x1f))
247  cmpne     R1, #0x10               @
248  ldmeqed   R2, {lr}^               @   restore unbanked lr
249                                    @ else
250  ldmneed   R3, {lr}                @   restore SVC lr, via ldmfd SP!, {LR}
251
252  ldmfd     SP!,{R0-R12}            @ Restore general purpose registers
253                                    @ Exception handler can not change SP
254
255  add       SP,SP,#0x20             @ Clear out the remaining stack space
256  ldmfd     SP!,{LR}                @ restore the link register for this context
257  rfefd     SP!                     @ return from exception via srsfd stack slot
258
259