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 19/* 20 21This is the stack constructed by the exception handler (low address to high address) 22 # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM 23 Reg Offset 24 === ====== 25 R0 0x00 # stmfd SP!,{R0-R12} 26 R1 0x04 27 R2 0x08 28 R3 0x0c 29 R4 0x10 30 R5 0x14 31 R6 0x18 32 R7 0x1c 33 R8 0x20 34 R9 0x24 35 R10 0x28 36 R11 0x2c 37 R12 0x30 38 SP 0x34 # reserved via adding 0x20 (32) to the SP 39 LR 0x38 40 PC 0x3c 41 CPSR 0x40 42 DFSR 0x44 43 DFAR 0x48 44 IFSR 0x4c 45 IFAR 0x50 46 47 LR 0x54 # SVC Link register (we need to restore it) 48 49 LR 0x58 # pushed by srsfd 50 CPSR 0x5c 51 52 */ 53 54 55 EXPORT ExceptionHandlersStart 56 EXPORT ExceptionHandlersEnd 57 EXPORT CommonExceptionEntry 58 EXPORT AsmCommonExceptionEntry 59 IMPORT GdbExceptionHandler 60 61 PRESERVE8 62 AREA DxeExceptionHandlers, CODE, READONLY 63 64// 65// This code gets copied to the ARM vector table 66// ExceptionHandlersStart - ExceptionHandlersEnd gets copied 67// 68ExceptionHandlersStart 69 70Reset 71 b Reset 72 73UndefinedInstruction 74 b UndefinedInstructionEntry 75 76SoftwareInterrupt 77 b SoftwareInterruptEntry 78 79PrefetchAbort 80 b PrefetchAbortEntry 81 82DataAbort 83 b DataAbortEntry 84 85ReservedException 86 b ReservedExceptionEntry 87 88Irq 89 b Irq 90 91Fiq 92 b FiqEntry 93 94 95UndefinedInstructionEntry 96 sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry 97 srsfd #0x13! ; Store return state on SVC stack 98 cpsid f, #0x13 ; Switch to SVC for common stack 99 stmfd SP!,{LR} ; Store the link register for the current mode 100 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 101 stmfd SP!,{R0-R12} ; Store the register state 102 103 mov R0,#1 ; ExceptionType 104 ldr R1,CommonExceptionEntry; 105 bx R1 106 107SoftwareInterruptEntry 108 sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry 109 srsfd #0x13! ; Store return state on SVC stack 110 cpsid f ; We are already in SVC mode 111 stmfd SP!,{LR} ; Store the link register for the current mode 112 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 113 stmfd SP!,{R0-R12} ; Store the register state 114 115 mov R0,#2 ; ExceptionType 116 ldr R1,CommonExceptionEntry 117 bx R1 118 119PrefetchAbortEntry 120 sub LR,LR,#4 121 srsfd #0x13! ; Store return state on SVC stack 122 cpsid f, #0x13 ; Switch to SVC for common stack 123 stmfd SP!,{LR} ; Store the link register for the current mode 124 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 125 stmfd SP!,{R0-R12} ; Store the register state 126 127 mov R0,#3 ; ExceptionType 128 ldr R1,CommonExceptionEntry 129 bx R1 130 131DataAbortEntry 132 sub LR,LR,#8 133 srsfd #0x13! ; Store return state on SVC stack 134 cpsid f, #0x13 ; Switch to SVC for common stack 135 stmfd SP!,{LR} ; Store the link register for the current mode 136 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 137 stmfd SP!,{R0-R12} ; Store the register state 138 139 mov R0,#4 ; ExceptionType 140 ldr R1,CommonExceptionEntry 141 bx R1 142 143ReservedExceptionEntry 144 srsfd #0x13! ; Store return state on SVC stack 145 cpsid f, #0x13 ; Switch to SVC for common stack 146 stmfd SP!,{LR} ; Store the link register for the current mode 147 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 148 stmfd SP!,{R0-R12} ; Store the register state 149 150 mov R0,#5 ; ExceptionType 151 ldr R1,CommonExceptionEntry 152 bx R1 153 154FiqEntry 155 sub LR,LR,#4 156 srsfd #0x13! ; Store return state on SVC stack 157 cps #0x13 ; Switch to SVC for common stack 158 stmfd SP!,{LR} ; Store the link register for the current mode 159 sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR 160 stmfd SP!,{R0-R12} ; Store the register state 161 ; Since we have already switch to SVC R8_fiq - R12_fiq 162 ; never get used or saved 163 mov R0,#7 ; ExceptionType 164 ldr R1,CommonExceptionEntry 165 bx R1 166 167// 168// This gets patched by the C code that patches in the vector table 169// 170CommonExceptionEntry 171 dcd 0x12345678 172 173ExceptionHandlersEnd 174 175// 176// This code runs from CpuDxe driver loaded address. It is patched into 177// CommonExceptionEntry. 178// 179AsmCommonExceptionEntry 180 mrc p15, 0, R1, c6, c0, 2 ; Read IFAR 181 str R1, [SP, #0x50] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR 182 183 mrc p15, 0, R1, c5, c0, 1 ; Read IFSR 184 str R1, [SP, #0x4c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR 185 186 mrc p15, 0, R1, c6, c0, 0 ; Read DFAR 187 str R1, [SP, #0x48] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR 188 189 mrc p15, 0, R1, c5, c0, 0 ; Read DFSR 190 str R1, [SP, #0x44] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR 191 192 ldr R1, [SP, #0x5c] ; srsfd saved pre-exception CPSR on the stack 193 str R1, [SP, #0x40] ; Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR 194 195 add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR 196 and R3, R1, #0x1f ; Check CPSR to see if User or System Mode 197 cmp R3, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1df)) 198 cmpne R3, #0x10 ; 199 stmeqed R2, {lr}^ ; save unbanked lr 200 ; else 201 stmneed R2, {lr} ; save SVC lr 202 203 204 ldr R5, [SP, #0x58] ; PC is the LR pushed by srsfd 205 ; Check to see if we have to adjust for Thumb entry 206 sub r4, r0, #1 ; if (ExceptionType == 1 || ExceptionType ==2)) { 207 cmp r4, #1 ; // UND & SVC have differnt LR adjust for Thumb 208 bhi NoAdjustNeeded 209 210 tst r1, #0x20 ; if ((CPSR & T)) == T) { // Thumb Mode on entry 211 addne R5, R5, #2 ; PC += 2; 212 str R5,[SP,#0x58] ; Update LR value pused by srsfd 213 214NoAdjustNeeded 215 216 str R5, [SP, #0x3c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.PC 217 218 sub R1, SP, #0x60 ; We pused 0x60 bytes on the stack 219 str R1, [SP, #0x34] ; Store it in EFI_SYSTEM_CONTEXT_ARM.SP 220 221 ; R0 is ExceptionType 222 mov R1,SP ; R1 is SystemContext 223 224/* 225VOID 226EFIAPI 227GdbExceptionHandler ( 228 IN EFI_EXCEPTION_TYPE ExceptionType, R0 229 IN OUT EFI_SYSTEM_CONTEXT SystemContext R1 230 ) 231 232*/ 233 blx GdbExceptionHandler ; Call exception handler 234 235 ldr R1,[SP,#0x3c] ; EFI_SYSTEM_CONTEXT_ARM.PC 236 str R1,[SP,#0x58] ; Store it back to srsfd stack slot so it can be restored 237 238 ldr R1,[SP,#0x40] ; EFI_SYSTEM_CONTEXT_ARM.CPSR 239 str R1,[SP,#0x5c] ; Store it back to srsfd stack slot so it can be restored 240 241 add R3, SP, #0x54 ; Make R3 point to SVC LR saved on entry 242 add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR 243 and R1, R1, #0x1f ; Check to see if User or System Mode 244 cmp R1, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1f)) 245 cmpne R1, #0x10 ; 246 ldmeqed R2, {lr}^ ; restore unbanked lr 247 ; else 248 ldmneed R3, {lr} ; restore SVC lr, via ldmfd SP!, {LR} 249 250 ldmfd SP!,{R0-R12} ; Restore general purpose registers 251 ; Exception handler can not change SP 252 253 add SP,SP,#0x20 ; Clear out the remaining stack space 254 ldmfd SP!,{LR} ; restore the link register for this context 255 rfefd SP! ; return from exception via srsfd stack slot 256 257 END 258 259 260