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 20 This 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 53 EXPORT DebugAgentVectorTable 54 IMPORT DefaultExceptionHandler 55 56 PRESERVE8 57 AREA DebugAgentException, CODE, READONLY, CODEALIGN, ALIGN=5 58 59 // 60 // This code gets copied to the ARM vector table 61 // ExceptionHandlersStart - ExceptionHandlersEnd gets copied 62 // 63 DebugAgentVectorTable FUNCTION 64 b ResetEntry 65 b UndefinedInstructionEntry 66 b SoftwareInterruptEntry 67 b PrefetchAbortEntry 68 b DataAbortEntry 69 b ReservedExceptionEntry 70 b IrqEntry 71 b FiqEntry 72 ENDFUNC 73 74 ResetEntry 75 srsfd #0x13! ; Store return state on SVC stack 76 ; We are already in SVC mode 77 stmfd SP!,{LR} ; Store the link register for the current mode 78 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 79 stmfd SP!,{R0-R12} ; Store the register state 80 81 mov R0,#0 ; ExceptionType 82 ldr R1,CommonExceptionEntry 83 bx R1 84 85 UndefinedInstructionEntry 86 sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry 87 srsfd #0x13! ; Store return state on SVC stack 88 cps #0x13 ; Switch to SVC for common stack 89 stmfd SP!,{LR} ; Store the link register for the current mode 90 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 91 stmfd SP!,{R0-R12} ; Store the register state 92 93 mov R0,#1 ; ExceptionType 94 ldr R1,CommonExceptionEntry; 95 bx R1 96 97 SoftwareInterruptEntry 98 sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry 99 srsfd #0x13! ; Store return state on SVC stack 100 ; We are already in SVC mode 101 stmfd SP!,{LR} ; Store the link register for the current mode 102 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 103 stmfd SP!,{R0-R12} ; Store the register state 104 105 mov R0,#2 ; ExceptionType 106 ldr R1,CommonExceptionEntry 107 bx R1 108 109 PrefetchAbortEntry 110 sub LR,LR,#4 111 srsfd #0x13! ; Store return state on SVC stack 112 cps #0x13 ; Switch to SVC for common stack 113 stmfd SP!,{LR} ; Store the link register for the current mode 114 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 115 stmfd SP!,{R0-R12} ; Store the register state 116 117 mov R0,#3 ; ExceptionType 118 ldr R1,CommonExceptionEntry 119 bx R1 120 121 DataAbortEntry 122 sub LR,LR,#8 123 srsfd #0x13! ; Store return state on SVC stack 124 cps #0x13 ; Switch to SVC for common stack 125 stmfd SP!,{LR} ; Store the link register for the current mode 126 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 127 stmfd SP!,{R0-R12} ; Store the register state 128 129 mov R0,#4 ; ExceptionType 130 ldr R1,CommonExceptionEntry 131 bx R1 132 133 ReservedExceptionEntry 134 srsfd #0x13! ; Store return state on SVC stack 135 cps #0x13 ; Switch to SVC for common stack 136 stmfd SP!,{LR} ; Store the link register for the current mode 137 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 138 stmfd SP!,{R0-R12} ; Store the register state 139 140 mov R0,#5 ; ExceptionType 141 ldr R1,CommonExceptionEntry 142 bx R1 143 144 IrqEntry 145 sub LR,LR,#4 146 srsfd #0x13! ; Store return state on SVC stack 147 cps #0x13 ; Switch to SVC for common stack 148 stmfd SP!,{LR} ; Store the link register for the current mode 149 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 150 stmfd SP!,{R0-R12} ; Store the register state 151 152 mov R0,#6 ; ExceptionType 153 ldr R1,CommonExceptionEntry 154 bx R1 155 156 FiqEntry 157 sub LR,LR,#4 158 srsfd #0x13! ; Store return state on SVC stack 159 cps #0x13 ; Switch to SVC for common stack 160 stmfd SP!,{LR} ; Store the link register for the current mode 161 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 162 stmfd SP!,{R0-R12} ; Store the register state 163 ; Since we have already switch to SVC R8_fiq - R12_fiq 164 ; never get used or saved 165 mov R0,#7 ; ExceptionType 166 ldr R1,CommonExceptionEntry 167 bx R1 168 169 // 170 // This gets patched by the C code that patches in the vector table 171 // 172 CommonExceptionEntry 173 dcd AsmCommonExceptionEntry 174 175 ExceptionHandlersEnd 176 177 // 178 // This code runs from CpuDxe driver loaded address. It is patched into 179 // CommonExceptionEntry. 180 // 181 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] ; srsfd 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 216 NoAdjustNeeded 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 #if (FixedPcdGet32(PcdVFPEnabled)) 227 vpush {d0-d15} ; save vstm registers in case they are used in optimizations 228 #endif 229 230 /* 231 VOID 232 EFIAPI 233 DefaultExceptionHandler ( 234 IN EFI_EXCEPTION_TYPE ExceptionType, R0 235 IN OUT EFI_SYSTEM_CONTEXT SystemContext R1 236 ) 237 238 */ 239 blx DefaultExceptionHandler ; Call exception handler 240 241 #if (FixedPcdGet32(PcdVFPEnabled)) 242 vpop {d0-d15} 243 #endif 244 245 ldr R1, [SP, #0x4c] ; Restore EFI_SYSTEM_CONTEXT_ARM.IFSR 246 mcr p15, 0, R1, c5, c0, 1 ; Write IFSR 247 248 ldr R1, [SP, #0x44] ; sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR 249 mcr p15, 0, R1, c5, c0, 0 ; Write DFSR 250 251 ldr R1,[SP,#0x3c] ; EFI_SYSTEM_CONTEXT_ARM.PC 252 str R1,[SP,#0x58] ; Store it back to srsfd stack slot so it can be restored 253 254 ldr R1,[SP,#0x40] ; EFI_SYSTEM_CONTEXT_ARM.CPSR 255 str R1,[SP,#0x5c] ; Store it back to srsfd stack slot so it can be restored 256 257 add R3, SP, #0x54 ; Make R3 point to SVC LR saved on entry 258 add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR 259 and R1, R1, #0x1f ; Check to see if User or System Mode 260 cmp R1, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1f)) 261 cmpne R1, #0x10 ; 262 ldmeqed R2, {lr}^ ; restore unbanked lr 263 ; else 264 ldmneed R3, {lr} ; restore SVC lr, via ldmfd SP!, {LR} 265 266 ldmfd SP!,{R0-R12} ; Restore general purpose registers 267 ; Exception handler can not change SP 268 269 add SP,SP,#0x20 ; Clear out the remaining stack space 270 ldmfd SP!,{LR} ; restore the link register for this context 271 rfefd SP! ; return from exception via srsfd stack slot 272 273 END 274