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