Home | History | Annotate | Download | only in Arm
      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