exceptions.S 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* SPDX-License-Identifier: GPL-2.0+ */
  2. /*
  3. * (C) Copyright 2013
  4. * David Feng <fenghua@phytium.com.cn>
  5. */
  6. #include <asm-offsets.h>
  7. #include <config.h>
  8. #include <asm/ptrace.h>
  9. #include <asm/macro.h>
  10. #include <linux/linkage.h>
  11. /*
  12. * AArch64 exception vectors:
  13. * We have four types of exceptions:
  14. * - synchronous: traps, data aborts, undefined instructions, ...
  15. * - IRQ: group 1 (normal) interrupts
  16. * - FIQ: group 0 or secure interrupts
  17. * - SError: fatal system errors
  18. * There are entries for all four of those for different contexts:
  19. * - from same exception level, when using the SP_EL0 stack pointer
  20. * - from same exception level, when using the SP_ELx stack pointer
  21. * - from lower exception level, when this is AArch64
  22. * - from lower exception level, when this is AArch32
  23. * Each of those 16 entries have space for 32 instructions, each entry must
  24. * be 128 byte aligned, the whole table must be 2K aligned.
  25. * The 32 instructions are not enough to save and restore all registers and
  26. * to branch to the actual handler, so we split this up:
  27. * Each entry saves the LR, branches to the save routine, then to the actual
  28. * handler, then to the restore routine. The save and restore routines are
  29. * each split in half and stuffed in the unused gap between the entries.
  30. * Also as we do not run anything in a lower exception level, we just provide
  31. * the first 8 entries for exceptions from the same EL.
  32. */
  33. .align 11
  34. .globl vectors
  35. vectors:
  36. .align 7 /* Current EL Synchronous Thread */
  37. stp x29, x30, [sp, #-16]!
  38. bl _exception_entry
  39. bl do_bad_sync
  40. b exception_exit
  41. /*
  42. * Save (most of) the GP registers to the stack frame.
  43. * This is the first part of the shared routine called into from all entries.
  44. */
  45. _exception_entry:
  46. stp x27, x28, [sp, #-16]!
  47. stp x25, x26, [sp, #-16]!
  48. stp x23, x24, [sp, #-16]!
  49. stp x21, x22, [sp, #-16]!
  50. stp x19, x20, [sp, #-16]!
  51. stp x17, x18, [sp, #-16]!
  52. stp x15, x16, [sp, #-16]!
  53. stp x13, x14, [sp, #-16]!
  54. stp x11, x12, [sp, #-16]!
  55. stp x9, x10, [sp, #-16]!
  56. stp x7, x8, [sp, #-16]!
  57. stp x5, x6, [sp, #-16]!
  58. stp x3, x4, [sp, #-16]!
  59. stp x1, x2, [sp, #-16]!
  60. b _save_el_regs /* jump to the second part */
  61. .align 7 /* Current EL IRQ Thread */
  62. stp x29, x30, [sp, #-16]!
  63. bl _exception_entry
  64. bl do_bad_irq
  65. b exception_exit
  66. /*
  67. * Save exception specific context: ESR and ELR, for all exception levels.
  68. * This is the second part of the shared routine called into from all entries.
  69. */
  70. _save_el_regs:
  71. /* Could be running at EL3/EL2/EL1 */
  72. switch_el x11, 3f, 2f, 1f
  73. 3: mrs x1, esr_el3
  74. mrs x2, elr_el3
  75. b 0f
  76. 2: mrs x1, esr_el2
  77. mrs x2, elr_el2
  78. b 0f
  79. 1: mrs x1, esr_el1
  80. mrs x2, elr_el1
  81. 0:
  82. stp x2, x0, [sp, #-16]!
  83. mov x0, sp
  84. ret
  85. .align 7 /* Current EL FIQ Thread */
  86. stp x29, x30, [sp, #-16]!
  87. bl _exception_entry
  88. bl do_bad_fiq
  89. /* falling through to _exception_exit */
  90. /*
  91. * Restore the exception return address, for all exception levels.
  92. * This is the first part of the shared routine called into from all entries.
  93. */
  94. exception_exit:
  95. ldp x2, x0, [sp],#16
  96. switch_el x11, 3f, 2f, 1f
  97. 3: msr elr_el3, x2
  98. b _restore_regs
  99. 2: msr elr_el2, x2
  100. b _restore_regs
  101. 1: msr elr_el1, x2
  102. b _restore_regs /* jump to the second part */
  103. .align 7 /* Current EL Error Thread */
  104. stp x29, x30, [sp, #-16]!
  105. bl _exception_entry
  106. bl do_bad_error
  107. b exception_exit
  108. /*
  109. * Restore the general purpose registers from the exception stack, then return.
  110. * This is the second part of the shared routine called into from all entries.
  111. */
  112. _restore_regs:
  113. ldp x1, x2, [sp],#16
  114. ldp x3, x4, [sp],#16
  115. ldp x5, x6, [sp],#16
  116. ldp x7, x8, [sp],#16
  117. ldp x9, x10, [sp],#16
  118. ldp x11, x12, [sp],#16
  119. ldp x13, x14, [sp],#16
  120. ldp x15, x16, [sp],#16
  121. ldp x17, x18, [sp],#16
  122. ldp x19, x20, [sp],#16
  123. ldp x21, x22, [sp],#16
  124. ldp x23, x24, [sp],#16
  125. ldp x25, x26, [sp],#16
  126. ldp x27, x28, [sp],#16
  127. ldp x29, x30, [sp],#16
  128. eret
  129. .align 7 /* Current EL (SP_ELx) Synchronous Handler */
  130. stp x29, x30, [sp, #-16]!
  131. bl _exception_entry
  132. bl do_sync
  133. b exception_exit
  134. .align 7 /* Current EL (SP_ELx) IRQ Handler */
  135. stp x29, x30, [sp, #-16]!
  136. bl _exception_entry
  137. bl do_irq
  138. b exception_exit
  139. .align 7 /* Current EL (SP_ELx) FIQ Handler */
  140. stp x29, x30, [sp, #-16]!
  141. bl _exception_entry
  142. bl do_fiq
  143. b exception_exit
  144. .align 7 /* Current EL (SP_ELx) Error Handler */
  145. stp x29, x30, [sp, #-16]!
  146. bl _exception_entry
  147. bl do_error
  148. b exception_exit