ExceptionSupport.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  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. #include <Library/PcdLib.h>
  18. /*
  19. This is the stack constructed by the exception handler (low address to high address)
  20. # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM
  21. Reg Offset
  22. === ======
  23. R0 0x00 # stmfd SP!,{R0-R12}
  24. R1 0x04
  25. R2 0x08
  26. R3 0x0c
  27. R4 0x10
  28. R5 0x14
  29. R6 0x18
  30. R7 0x1c
  31. R8 0x20
  32. R9 0x24
  33. R10 0x28
  34. R11 0x2c
  35. R12 0x30
  36. SP 0x34 # reserved via subtraction 0x20 (32) from SP
  37. LR 0x38
  38. PC 0x3c
  39. CPSR 0x40
  40. DFSR 0x44
  41. DFAR 0x48
  42. IFSR 0x4c
  43. IFAR 0x50
  44. LR 0x54 # SVC Link register (we need to restore it)
  45. LR 0x58 # pushed by srsfd
  46. CPSR 0x5c
  47. */
  48. GCC_ASM_EXPORT(ExceptionHandlersStart)
  49. GCC_ASM_EXPORT(ExceptionHandlersEnd)
  50. GCC_ASM_EXPORT(CommonExceptionEntry)
  51. GCC_ASM_EXPORT(AsmCommonExceptionEntry)
  52. GCC_ASM_EXPORT(CommonCExceptionHandler)
  53. .text
  54. #if !defined(__APPLE__)
  55. .fpu neon @ makes vpush/vpop assemble
  56. #endif
  57. .align 5
  58. //
  59. // This code gets copied to the ARM vector table
  60. // ExceptionHandlersStart - ExceptionHandlersEnd gets copied
  61. //
  62. ASM_PFX(ExceptionHandlersStart):
  63. ASM_PFX(Reset):
  64. b ASM_PFX(ResetEntry)
  65. ASM_PFX(UndefinedInstruction):
  66. b ASM_PFX(UndefinedInstructionEntry)
  67. ASM_PFX(SoftwareInterrupt):
  68. b ASM_PFX(SoftwareInterruptEntry)
  69. ASM_PFX(PrefetchAbort):
  70. b ASM_PFX(PrefetchAbortEntry)
  71. ASM_PFX(DataAbort):
  72. b ASM_PFX(DataAbortEntry)
  73. ASM_PFX(ReservedException):
  74. b ASM_PFX(ReservedExceptionEntry)
  75. ASM_PFX(Irq):
  76. b ASM_PFX(IrqEntry)
  77. ASM_PFX(Fiq):
  78. b ASM_PFX(FiqEntry)
  79. ASM_PFX(ResetEntry):
  80. srsdb #0x13! @ Store return state on SVC stack
  81. @ We are already in SVC mode
  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. mov R0,#0 @ ExceptionType
  86. ldr R1,ASM_PFX(CommonExceptionEntry)
  87. bx R1
  88. ASM_PFX(UndefinedInstructionEntry):
  89. sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry
  90. srsdb #0x13! @ Store return state on SVC stack
  91. cps #0x13 @ Switch to SVC for common stack
  92. stmfd SP!,{LR} @ Store the link register for the current mode
  93. sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
  94. stmfd SP!,{R0-R12} @ Store the register state
  95. mov R0,#1 @ ExceptionType
  96. ldr R1,ASM_PFX(CommonExceptionEntry)
  97. bx R1
  98. ASM_PFX(SoftwareInterruptEntry):
  99. srsdb #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. mov R0,#2 @ ExceptionType
  105. ldr R1,ASM_PFX(CommonExceptionEntry)
  106. bx R1
  107. ASM_PFX(PrefetchAbortEntry):
  108. sub LR,LR,#4
  109. srsdb #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. mov R0,#3 @ ExceptionType
  115. ldr R1,ASM_PFX(CommonExceptionEntry)
  116. bx R1
  117. ASM_PFX(DataAbortEntry):
  118. sub LR,LR,#8
  119. srsdb #0x13! @ Store return state on SVC stack
  120. cps #0x13 @ Switch to SVC for common stack
  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. mov R0,#4
  125. ldr R1,ASM_PFX(CommonExceptionEntry)
  126. bx R1
  127. ASM_PFX(ReservedExceptionEntry):
  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. mov R0,#5
  134. ldr R1,ASM_PFX(CommonExceptionEntry)
  135. bx R1
  136. ASM_PFX(IrqEntry):
  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. mov R0,#6 @ ExceptionType
  144. ldr R1,ASM_PFX(CommonExceptionEntry)
  145. bx R1
  146. ASM_PFX(FiqEntry):
  147. sub LR,LR,#4
  148. srsdb #0x13! @ Store return state on SVC stack
  149. cps #0x13 @ Switch to SVC for common stack
  150. stmfd SP!,{LR} @ Store the link register for the current mode
  151. sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
  152. stmfd SP!,{R0-R12} @ Store the register state
  153. @ Since we have already switch to SVC R8_fiq - R12_fiq
  154. @ never get used or saved
  155. mov R0,#7 @ ExceptionType
  156. ldr R1,ASM_PFX(CommonExceptionEntry)
  157. bx R1
  158. //
  159. // This gets patched by the C code that patches in the vector table
  160. //
  161. ASM_PFX(CommonExceptionEntry):
  162. .word ASM_PFX(AsmCommonExceptionEntry)
  163. ASM_PFX(ExceptionHandlersEnd):
  164. //
  165. // This code runs from CpuDxe driver loaded address. It is patched into
  166. // CommonExceptionEntry.
  167. //
  168. ASM_PFX(AsmCommonExceptionEntry):
  169. mrc p15, 0, R1, c6, c0, 2 @ Read IFAR
  170. str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
  171. mrc p15, 0, R1, c5, c0, 1 @ Read IFSR
  172. str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
  173. mrc p15, 0, R1, c6, c0, 0 @ Read DFAR
  174. str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
  175. mrc p15, 0, R1, c5, c0, 0 @ Read DFSR
  176. str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
  177. ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack
  178. str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
  179. add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
  180. and R3, R1, #0x1f @ Check CPSR to see if User or System Mode
  181. cmp R3, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))
  182. cmpne R3, #0x10 @
  183. stmeqed R2, {lr}^ @ save unbanked lr
  184. @ else
  185. stmneed R2, {lr} @ save SVC lr
  186. ldr R5, [SP, #0x58] @ PC is the LR pushed by srsfd
  187. @ Check to see if we have to adjust for Thumb entry
  188. sub r4, r0, #1 @ if (ExceptionType == 1 || ExceptionType == 2)) {
  189. cmp r4, #1 @ // UND & SVC have differnt LR adjust for Thumb
  190. bhi NoAdjustNeeded
  191. tst r1, #0x20 @ if ((CPSR & T)) == T) { // Thumb Mode on entry
  192. addne R5, R5, #2 @ PC += 2;
  193. strne R5,[SP,#0x58] @ Update LR value pushed by srsfd
  194. NoAdjustNeeded:
  195. str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
  196. add R1, SP, #0x60 @ We pushed 0x60 bytes on the stack
  197. str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP
  198. @ R0 is ExceptionType
  199. mov R1,SP @ R1 is SystemContext
  200. #if (FixedPcdGet32(PcdVFPEnabled))
  201. vpush {d0-d15} @ save vstm registers in case they are used in optimizations
  202. #endif
  203. mov R4, SP @ Save current SP
  204. tst R4, #4
  205. subne SP, SP, #4 @ Adjust SP if not 8-byte aligned
  206. /*
  207. VOID
  208. EFIAPI
  209. CommonCExceptionHandler (
  210. IN EFI_EXCEPTION_TYPE ExceptionType, R0
  211. IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
  212. )
  213. */
  214. blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler
  215. mov SP, R4 @ Restore SP
  216. #if (FixedPcdGet32(PcdVFPEnabled))
  217. vpop {d0-d15}
  218. #endif
  219. ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
  220. mcr p15, 0, R1, c5, c0, 1 @ Write IFSR
  221. ldr R1, [SP, #0x44] @ Restore EFI_SYSTEM_CONTEXT_ARM.DFSR
  222. mcr p15, 0, R1, c5, c0, 0 @ Write DFSR
  223. ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC
  224. str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored
  225. ldr R1,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR
  226. str R1,[SP,#0x5c] @ Store it back to srsfd stack slot so it can be restored
  227. add R3, SP, #0x54 @ Make R3 point to SVC LR saved on entry
  228. add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
  229. and R1, R1, #0x1f @ Check to see if User or System Mode
  230. cmp R1, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))
  231. cmpne R1, #0x10 @
  232. ldmeqed R2, {lr}^ @ restore unbanked lr
  233. @ else
  234. ldmneed R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR}
  235. ldmfd SP!,{R0-R12} @ Restore general purpose registers
  236. @ Exception handler can not change SP
  237. add SP,SP,#0x20 @ Clear out the remaining stack space
  238. ldmfd SP!,{LR} @ restore the link register for this context
  239. rfefd SP! @ return from exception via srsfd stack slot