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