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 # Copyright (c) 2014, ARM Limited. All rights reserved.<BR>
      7 # Copyright (c) 2016 HP Development Company, L.P.<BR>
      8 #
      9 # This program and the accompanying materials
     10 # are licensed and made available under the terms and conditions of the BSD License
     11 # which accompanies this distribution.  The full text of the license may be found at
     12 # http://opensource.org/licenses/bsd-license.php
     13 #
     14 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     15 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     16 #
     17 #------------------------------------------------------------------------------
     18 
     19 #include <Library/PcdLib.h>
     20 
     21 /*
     22 
     23 This is the stack constructed by the exception handler (low address to high address)
     24                 # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM
     25   Reg   Offset
     26   ===   ======
     27   R0    0x00    # stmfd     SP!,{R0-R12}
     28   R1    0x04
     29   R2    0x08
     30   R3    0x0c
     31   R4    0x10
     32   R5    0x14
     33   R6    0x18
     34   R7    0x1c
     35   R8    0x20
     36   R9    0x24
     37   R10   0x28
     38   R11   0x2c
     39   R12   0x30
     40   SP    0x34    # reserved via subtraction 0x20 (32) from SP
     41   LR    0x38
     42   PC    0x3c
     43   CPSR  0x40
     44   DFSR  0x44
     45   DFAR  0x48
     46   IFSR  0x4c
     47   IFAR  0x50
     48 
     49   LR    0x54    # SVC Link register (we need to restore it)
     50 
     51   LR    0x58    # pushed by srsfd
     52   CPSR  0x5c
     53 
     54  */
     55 
     56 
     57 GCC_ASM_EXPORT(ExceptionHandlersStart)
     58 GCC_ASM_EXPORT(ExceptionHandlersEnd)
     59 GCC_ASM_EXPORT(CommonExceptionEntry)
     60 GCC_ASM_EXPORT(AsmCommonExceptionEntry)
     61 GCC_ASM_EXPORT(CommonCExceptionHandler)
     62 
     63 .text
     64 .syntax unified
     65 #if !defined(__APPLE__)
     66 .fpu neon    @ makes vpush/vpop assemble
     67 #endif
     68 .align 5
     69 
     70 
     71 //
     72 // This code gets copied to the ARM vector table
     73 // ExceptionHandlersStart - ExceptionHandlersEnd gets copied
     74 //
     75 ASM_PFX(ExceptionHandlersStart):
     76 
     77 ASM_PFX(Reset):
     78   b ASM_PFX(ResetEntry)
     79 
     80 ASM_PFX(UndefinedInstruction):
     81   b ASM_PFX(UndefinedInstructionEntry)
     82 
     83 ASM_PFX(SoftwareInterrupt):
     84   b ASM_PFX(SoftwareInterruptEntry)
     85 
     86 ASM_PFX(PrefetchAbort):
     87   b ASM_PFX(PrefetchAbortEntry)
     88 
     89 ASM_PFX(DataAbort):
     90   b ASM_PFX(DataAbortEntry)
     91 
     92 ASM_PFX(ReservedException):
     93   b ASM_PFX(ReservedExceptionEntry)
     94 
     95 ASM_PFX(Irq):
     96   b ASM_PFX(IrqEntry)
     97 
     98 ASM_PFX(Fiq):
     99   b ASM_PFX(FiqEntry)
    100 
    101 ASM_PFX(ResetEntry):
    102   srsdb     #0x13!                    @ Store return state on SVC stack
    103                                       @ We are already in SVC mode
    104 
    105   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    106   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    107   stmfd     SP!,{R0-R12}              @ Store the register state
    108 
    109   mov       R0,#0                     @ ExceptionType
    110   ldr       R1,ASM_PFX(CommonExceptionEntry)
    111   bx        R1
    112 
    113 ASM_PFX(UndefinedInstructionEntry):
    114   sub       LR, LR, #4                @ Only -2 for Thumb, adjust in CommonExceptionEntry
    115   srsdb     #0x13!                    @ Store return state on SVC stack
    116   cps       #0x13                     @ Switch to SVC for common stack
    117   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    118   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    119   stmfd     SP!,{R0-R12}              @ Store the register state
    120 
    121   mov       R0,#1                     @ ExceptionType
    122   ldr       R1,ASM_PFX(CommonExceptionEntry)
    123   bx        R1
    124 
    125 ASM_PFX(SoftwareInterruptEntry):
    126   srsdb     #0x13!                    @ Store return state on SVC stack
    127                                       @ We are already in SVC mode
    128   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    129   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    130   stmfd     SP!,{R0-R12}              @ Store the register state
    131 
    132   mov       R0,#2                     @ ExceptionType
    133   ldr       R1,ASM_PFX(CommonExceptionEntry)
    134   bx        R1
    135 
    136 ASM_PFX(PrefetchAbortEntry):
    137   sub       LR,LR,#4
    138   srsdb     #0x13!                    @ Store return state on SVC stack
    139   cps       #0x13                     @ Switch to SVC for common stack
    140   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    141   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    142   stmfd     SP!,{R0-R12}              @ Store the register state
    143 
    144   mov       R0,#3                     @ ExceptionType
    145   ldr       R1,ASM_PFX(CommonExceptionEntry)
    146   bx        R1
    147 
    148 ASM_PFX(DataAbortEntry):
    149   sub       LR,LR,#8
    150   srsdb     #0x13!                    @ Store return state on SVC stack
    151   cps       #0x13                     @ Switch to SVC for common stack
    152   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    153   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    154   stmfd     SP!,{R0-R12}              @ Store the register state
    155 
    156   mov       R0,#4
    157   ldr       R1,ASM_PFX(CommonExceptionEntry)
    158   bx        R1
    159 
    160 ASM_PFX(ReservedExceptionEntry):
    161   srsdb     #0x13!                    @ Store return state on SVC stack
    162   cps       #0x13                     @ Switch to SVC for common stack
    163   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    164   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    165   stmfd     SP!,{R0-R12}              @ Store the register state
    166 
    167   mov       R0,#5
    168   ldr       R1,ASM_PFX(CommonExceptionEntry)
    169   bx        R1
    170 
    171 ASM_PFX(IrqEntry):
    172   sub       LR,LR,#4
    173   srsdb     #0x13!                    @ Store return state on SVC stack
    174   cps       #0x13                     @ Switch to SVC for common stack
    175   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    176   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    177   stmfd     SP!,{R0-R12}              @ Store the register state
    178 
    179   mov       R0,#6                     @ ExceptionType
    180   ldr       R1,ASM_PFX(CommonExceptionEntry)
    181   bx        R1
    182 
    183 ASM_PFX(FiqEntry):
    184   sub       LR,LR,#4
    185   srsdb     #0x13!                    @ Store return state on SVC stack
    186   cps       #0x13                     @ Switch to SVC for common stack
    187   stmfd     SP!,{LR}                  @ Store the link register for the current mode
    188   sub       SP,SP,#0x20               @ Save space for SP, LR, PC, IFAR - CPSR
    189   stmfd     SP!,{R0-R12}              @ Store the register state
    190                                       @ Since we have already switch to SVC R8_fiq - R12_fiq
    191                                       @ never get used or saved
    192   mov       R0,#7                     @ ExceptionType
    193   ldr       R1,ASM_PFX(CommonExceptionEntry)
    194   bx        R1
    195 
    196 //
    197 // This gets patched by the C code that patches in the vector table
    198 //
    199 ASM_PFX(CommonExceptionEntry):
    200   .word       ASM_PFX(AsmCommonExceptionEntry)
    201 
    202 ASM_PFX(ExceptionHandlersEnd):
    203 
    204 //
    205 // This code runs from CpuDxe driver loaded address. It is patched into
    206 // CommonExceptionEntry.
    207 //
    208 ASM_PFX(AsmCommonExceptionEntry):
    209   mrc       p15, 0, R1, c6, c0, 2   @ Read IFAR
    210   str       R1, [SP, #0x50]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
    211 
    212   mrc       p15, 0, R1, c5, c0, 1   @ Read IFSR
    213   str       R1, [SP, #0x4c]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
    214 
    215   mrc       p15, 0, R1, c6, c0, 0   @ Read DFAR
    216   str       R1, [SP, #0x48]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
    217 
    218   mrc       p15, 0, R1, c5, c0, 0   @ Read DFSR
    219   str       R1, [SP, #0x44]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
    220 
    221   ldr       R1, [SP, #0x5c]         @ srsdb saved pre-exception CPSR on the stack
    222   str       R1, [SP, #0x40]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
    223 
    224   add       R2, SP, #0x38           @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
    225   and       R3, R1, #0x1f           @ Check CPSR to see if User or System Mode
    226   cmp       R3, #0x1f               @ if ((CPSR == 0x10) || (CPSR == 0x1f))
    227   cmpne     R3, #0x10               @
    228   stmdaeq   R2, {lr}^               @   save unbanked lr
    229                                     @ else
    230   stmdane   R2, {lr}                @   save SVC lr
    231 
    232 
    233   ldr       R5, [SP, #0x58]         @ PC is the LR pushed by srsfd
    234                                     @ Check to see if we have to adjust for Thumb entry
    235   sub       r4, r0, #1              @ if (ExceptionType == 1 || ExceptionType == 2)) {
    236   cmp       r4, #1                  @   // UND & SVC have differnt LR adjust for Thumb
    237   bhi       NoAdjustNeeded
    238 
    239   tst       r1, #0x20               @   if ((CPSR & T)) == T) {  // Thumb Mode on entry
    240   addne     R5, R5, #2              @     PC += 2;
    241   strne     R5,[SP,#0x58]           @ Update LR value pushed by srsfd
    242 
    243 NoAdjustNeeded:
    244 
    245   str       R5, [SP, #0x3c]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
    246 
    247   add       R1, SP, #0x60           @ We pushed 0x60 bytes on the stack
    248   str       R1, [SP, #0x34]         @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP
    249 
    250                                     @ R0 is ExceptionType
    251   mov       R1,SP                   @ R1 is SystemContext
    252 
    253 #if (FixedPcdGet32(PcdVFPEnabled))
    254   vpush     {d0-d15}                @ save vstm registers in case they are used in optimizations
    255 #endif
    256 
    257   mov       R4, SP                  @ Save current SP
    258   tst       R4, #4
    259   subne     SP, SP, #4              @ Adjust SP if not 8-byte aligned
    260 
    261 /*
    262 VOID
    263 EFIAPI
    264 CommonCExceptionHandler (
    265   IN     EFI_EXCEPTION_TYPE           ExceptionType,   R0
    266   IN OUT EFI_SYSTEM_CONTEXT           SystemContext    R1
    267   )
    268 
    269 */
    270   blx       ASM_PFX(CommonCExceptionHandler)  @ Call exception handler
    271 
    272   mov       SP, R4                  @ Restore SP
    273 
    274 #if (FixedPcdGet32(PcdVFPEnabled))
    275   vpop      {d0-d15}
    276 #endif
    277 
    278   ldr       R1, [SP, #0x4c]         @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
    279   mcr       p15, 0, R1, c5, c0, 1   @ Write IFSR
    280 
    281   ldr       R1, [SP, #0x44]         @ Restore EFI_SYSTEM_CONTEXT_ARM.DFSR
    282   mcr       p15, 0, R1, c5, c0, 0   @ Write DFSR
    283 
    284   ldr       R1,[SP,#0x3c]           @ EFI_SYSTEM_CONTEXT_ARM.PC
    285   str       R1,[SP,#0x58]           @ Store it back to srsfd stack slot so it can be restored
    286 
    287   ldr       R1,[SP,#0x40]           @ EFI_SYSTEM_CONTEXT_ARM.CPSR
    288   str       R1,[SP,#0x5c]           @ Store it back to srsfd stack slot so it can be restored
    289 
    290   add       R3, SP, #0x54           @ Make R3 point to SVC LR saved on entry
    291   add       R2, SP, #0x38           @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
    292   and       R1, R1, #0x1f           @ Check to see if User or System Mode
    293   cmp       R1, #0x1f               @ if ((CPSR == 0x10) || (CPSR == 0x1f))
    294   cmpne     R1, #0x10               @
    295   ldmibeq   R2, {lr}^               @   restore unbanked lr
    296                                     @ else
    297   ldmibne   R3, {lr}                @   restore SVC lr, via ldmfd SP!, {LR}
    298 
    299   ldmfd     SP!,{R0-R12}            @ Restore general purpose registers
    300                                     @ Exception handler can not change SP
    301 
    302   add       SP,SP,#0x20             @ Clear out the remaining stack space
    303   ldmfd     SP!,{LR}                @ restore the link register for this context
    304   rfefd     SP!                     @ return from exception via srsfd stack slot
    305 
    306