ExceptionSupport.asm 11 KB

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