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 GCC_ASM_EXPORT(DebugAgentVectorTable)
     54 GCC_ASM_IMPORT(DefaultExceptionHandler)
     55 
     56 .text
     57 .syntax unified
     58 #if !defined(__APPLE__)
     59 .fpu neon    @ makes vpush/vpop assemble
     60 #endif
     61 .align 5
     62 
     63 
     64 //
     65 // This code gets copied to the ARM vector table
     66 // ExceptionHandlersStart - ExceptionHandlersEnd gets copied
     67 //
     68 ASM_PFX(DebugAgentVectorTable):
     69   b ASM_PFX(ResetEntry)
     70   b ASM_PFX(UndefinedInstructionEntry)
     71   b ASM_PFX(SoftwareInterruptEntry)
     72   b ASM_PFX(PrefetchAbortEntry)
     73   b ASM_PFX(DataAbortEntry)
     74   b ASM_PFX(ReservedExceptionEntry)
     75   b ASM_PFX(IrqEntry)
     76   b ASM_PFX(FiqEntry)
     77 
     78 ASM_PFX(ResetEntry):
     79   srsdb     #0x13!                    @ Store return state on SVC stack
     80                                       @ We are already in SVC mode
     81 
     82   stmfd     SP!,{LR}                  @ Store the link register for the current mode
     83   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
     84   stmfd     SP!,{R0-R12}              @ Store the register state
     85 
     86   mov       R0,#0                     @ ExceptionType
     87   ldr       R1,ASM_PFX(CommonExceptionEntry)
     88   bx        R1
     89 
     90 ASM_PFX(UndefinedInstructionEntry):
     91   sub       LR, LR, #4                @ Only -2 for Thumb, adjust in CommonExceptionEntry
     92   srsdb     #0x13!                    @ Store return state on SVC stack
     93   cps       #0x13                     @ Switch to SVC for common stack
     94   stmfd     SP!,{LR}                  @ Store the link register for the current mode
     95   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
     96   stmfd     SP!,{R0-R12}              @ Store the register state
     97 
     98   mov       R0,#1                     @ ExceptionType
     99   ldr       R1,ASM_PFX(CommonExceptionEntry)
    100   bx        R1
    101 
    102 ASM_PFX(SoftwareInterruptEntry):
    103   sub       LR, LR, #4                @ Only -2 for Thumb, adjust in CommonExceptionEntry
    104   srsdb     #0x13!                    @ Store return state on SVC stack
    105                                       @ We are already in SVC mode
    106   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    107   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    108   stmfd     SP!,{R0-R12}              @ Store the register state
    109 
    110   mov       R0,#2                     @ ExceptionType
    111   ldr       R1,ASM_PFX(CommonExceptionEntry)
    112   bx        R1
    113 
    114 ASM_PFX(PrefetchAbortEntry):
    115   sub       LR,LR,#4
    116   srsdb     #0x13!                    @ Store return state on SVC stack
    117   cps       #0x13                     @ Switch to SVC for common stack
    118   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    119   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    120   stmfd     SP!,{R0-R12}              @ Store the register state
    121 
    122   mov       R0,#3                     @ ExceptionType
    123   ldr       R1,ASM_PFX(CommonExceptionEntry)
    124   bx        R1
    125 
    126 ASM_PFX(DataAbortEntry):
    127   sub       LR,LR,#8
    128   srsdb     #0x13!                    @ Store return state on SVC stack
    129   cps       #0x13                     @ Switch to SVC for common stack
    130   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    131   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    132   stmfd     SP!,{R0-R12}              @ Store the register state
    133 
    134   mov       R0,#4
    135   ldr       R1,ASM_PFX(CommonExceptionEntry)
    136   bx        R1
    137 
    138 ASM_PFX(ReservedExceptionEntry):
    139   srsdb     #0x13!                    @ Store return state on SVC stack
    140   cps       #0x13                     @ Switch to SVC for common stack
    141   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    142   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    143   stmfd     SP!,{R0-R12}              @ Store the register state
    144 
    145   mov       R0,#5
    146   ldr       R1,ASM_PFX(CommonExceptionEntry)
    147   bx        R1
    148 
    149 ASM_PFX(IrqEntry):
    150   sub       LR,LR,#4
    151   srsdb     #0x13!                    @ Store return state on SVC stack
    152   cps       #0x13                     @ Switch to SVC for common stack
    153   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    154   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    155   stmfd     SP!,{R0-R12}              @ Store the register state
    156 
    157   mov       R0,#6                     @ ExceptionType
    158   ldr       R1,ASM_PFX(CommonExceptionEntry)
    159   bx        R1
    160 
    161 ASM_PFX(FiqEntry):
    162   sub       LR,LR,#4
    163   srsdb     #0x13!                    @ Store return state on SVC stack
    164   cps       #0x13                     @ Switch to SVC for common stack
    165   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    166   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    167   stmfd     SP!,{R0-R12}              @ Store the register state
    168                                       @ Since we have already switch to SVC R8_fiq - R12_fiq
    169                                       @ never get used or saved
    170   mov       R0,#7                     @ ExceptionType
    171   ldr       R1,ASM_PFX(CommonExceptionEntry)
    172   bx        R1
    173 
    174 //
    175 // This gets patched by the C code that patches in the vector table
    176 //
    177 ASM_PFX(CommonExceptionEntry):
    178   .word       ASM_PFX(AsmCommonExceptionEntry)
    179 
    180 ASM_PFX(ExceptionHandlersEnd):
    181 
    182 //
    183 // This code runs from CpuDxe driver loaded address. It is patched into
    184 // CommonExceptionEntry.
    185 //
    186 ASM_PFX(AsmCommonExceptionEntry):
    187   mrc       p15, 0, R1, c6, c0, 2   @ Read IFAR
    188   str       R1, [SP, #0x50]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
    189 
    190   mrc       p15, 0, R1, c5, c0, 1   @ Read IFSR
    191   str       R1, [SP, #0x4c]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
    192 
    193   mrc       p15, 0, R1, c6, c0, 0   @ Read DFAR
    194   str       R1, [SP, #0x48]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
    195 
    196   mrc       p15, 0, R1, c5, c0, 0   @ Read DFSR
    197   str       R1, [SP, #0x44]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
    198 
    199   ldr       R1, [SP, #0x5c]         @ srsdb saved pre-exception CPSR on the stack
    200   str       R1, [SP, #0x40]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
    201 
    202   add       R2, SP, #0x38           @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
    203   and       R3, R1, #0x1f           @ Check CPSR to see if User or System Mode
    204   cmp       R3, #0x1f               @ if ((CPSR == 0x10) || (CPSR == 0x1df))
    205   cmpne     R3, #0x10               @
    206   stmdaeq   R2, {lr}^               @   save unbanked lr
    207                                     @ else
    208   stmdane   R2, {lr}                @   save SVC lr
    209 
    210 
    211   ldr       R5, [SP, #0x58]         @ PC is the LR pushed by srsfd
    212                                     @ Check to see if we have to adjust for Thumb entry
    213   sub       r4, r0, #1              @ if (ExceptionType == 1 || ExceptionType ==2)) {
    214   cmp       r4, #1                  @   // UND & SVC have different LR adjust for Thumb
    215   bhi       NoAdjustNeeded
    216 
    217   tst       r1, #0x20               @   if ((CPSR & T)) == T) {  // Thumb Mode on entry
    218   addne     R5, R5, #2              @     PC += 2@
    219   str       R5,[SP,#0x58]           @ Update LR value pused by srsfd
    220 
    221 NoAdjustNeeded:
    222 
    223   str       R5, [SP, #0x3c]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
    224 
    225   sub       R1, SP, #0x60           @ We pused 0x60 bytes on the stack
    226   str       R1, [SP, #0x34]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP
    227 
    228                                     @ R0 is ExceptionType
    229   mov       R1,SP                   @ R1 is SystemContext
    230 
    231 #if (FixedPcdGet32(PcdVFPEnabled))
    232   vpush     {d0-d15}                @ save vstm registers in case they are used in optimizations
    233 #endif
    234 
    235 /*
    236 VOID
    237 EFIAPI
    238 DefaultExceptionHandler (
    239   IN     EFI_EXCEPTION_TYPE           ExceptionType,   R0
    240   IN OUT EFI_SYSTEM_CONTEXT           SystemContext    R1
    241   )
    242 
    243 */
    244   blx       ASM_PFX(DefaultExceptionHandler)  @ Call exception handler
    245 
    246 #if (FixedPcdGet32(PcdVFPEnabled))
    247   vpop      {d0-d15}
    248 #endif
    249 
    250   ldr       R1, [SP, #0x4c]         @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
    251   mcr       p15, 0, R1, c5, c0, 1   @ Write IFSR
    252 
    253   ldr       R1, [SP, #0x44]         @ sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR
    254   mcr       p15, 0, R1, c5, c0, 0   @ Write DFSR
    255 
    256   ldr       R1,[SP,#0x3c]           @ EFI_SYSTEM_CONTEXT_ARM.PC
    257   str       R1,[SP,#0x58]           @ Store it back to srsfd stack slot so it can be restored
    258 
    259   ldr       R1,[SP,#0x40]           @ EFI_SYSTEM_CONTEXT_ARM.CPSR
    260   str       R1,[SP,#0x5c]           @ Store it back to srsfd stack slot so it can be restored
    261 
    262   add       R3, SP, #0x54           @ Make R3 point to SVC LR saved on entry
    263   add       R2, SP, #0x38           @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
    264   and       R1, R1, #0x1f           @ Check to see if User or System Mode
    265   cmp       R1, #0x1f               @ if ((CPSR == 0x10) || (CPSR == 0x1f))
    266   cmpne     R1, #0x10               @
    267   ldmibeq   R2, {lr}^               @   restore unbanked lr
    268                                     @ else
    269   ldmibne   R3, {lr}                @   restore SVC lr, via ldmfd SP!, {LR}
    270 
    271   ldmfd     SP!,{R0-R12}            @ Restore general purpose registers
    272                                     @ Exception handler can not change SP
    273 
    274   add       SP,SP,#0x20             @ Clear out the remaining stack space
    275   ldmfd     SP!,{LR}                @ restore the link register for this context
    276   rfefd     SP!                     @ return from exception via srsfd stack slot
    277 
    278