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