Home | History | Annotate | Download | only in Arm
      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 
     21 This 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 //
     68 ExceptionHandlersStart
     69 
     70 Reset
     71   b   Reset
     72 
     73 UndefinedInstruction
     74   b   UndefinedInstructionEntry
     75 
     76 SoftwareInterrupt
     77   b   SoftwareInterruptEntry
     78 
     79 PrefetchAbort
     80   b   PrefetchAbortEntry
     81 
     82 DataAbort
     83   b   DataAbortEntry
     84 
     85 ReservedException
     86   b   ReservedExceptionEntry
     87 
     88 Irq
     89   b   Irq
     90 
     91 Fiq
     92   b   FiqEntry
     93 
     94 
     95 UndefinedInstructionEntry
     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 
    107 SoftwareInterruptEntry
    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 
    119 PrefetchAbortEntry
    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 
    131 DataAbortEntry
    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 
    143 ReservedExceptionEntry
    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 
    154 FiqEntry
    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 //
    170 CommonExceptionEntry
    171   dcd       0x12345678
    172 
    173 ExceptionHandlersEnd
    174 
    175 //
    176 // This code runs from CpuDxe driver loaded address. It is patched into
    177 // CommonExceptionEntry.
    178 //
    179 AsmCommonExceptionEntry
    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 
    214 NoAdjustNeeded
    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 /*
    225 VOID
    226 EFIAPI
    227 GdbExceptionHandler (
    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