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