entry-arcv2.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __ASM_ARC_ENTRY_ARCV2_H
  3. #define __ASM_ARC_ENTRY_ARCV2_H
  4. #include <asm/asm-offsets.h>
  5. #include <asm/dsp-impl.h>
  6. #include <asm/irqflags-arcv2.h>
  7. #include <asm/thread_info.h> /* For THREAD_SIZE */
  8. /*
  9. * Interrupt/Exception stack layout (pt_regs) for ARCv2
  10. * (End of struct aligned to end of page [unless nested])
  11. *
  12. * INTERRUPT EXCEPTION
  13. *
  14. * manual --------------------- manual
  15. * | orig_r0 |
  16. * | event/ECR |
  17. * | bta |
  18. * | user_r25 |
  19. * | gp |
  20. * | fp |
  21. * | sp |
  22. * | r12 |
  23. * | r30 |
  24. * | r58 |
  25. * | r59 |
  26. * hw autosave ---------------------
  27. * optional | r0 |
  28. * | r1 |
  29. * ~ ~
  30. * | r9 |
  31. * | r10 |
  32. * | r11 |
  33. * | blink |
  34. * | lpe |
  35. * | lps |
  36. * | lpc |
  37. * | ei base |
  38. * | ldi base |
  39. * | jli base |
  40. * ---------------------
  41. * hw autosave | pc / eret |
  42. * mandatory | stat32 / erstatus |
  43. * ---------------------
  44. */
  45. /*------------------------------------------------------------------------*/
  46. .macro INTERRUPT_PROLOGUE
  47. ; (A) Before jumping to Interrupt Vector, hardware micro-ops did following:
  48. ; 1. SP auto-switched to kernel mode stack
  49. ; 2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0)
  50. ; 3. Auto save: (mandatory) Push PC and STAT32 on stack
  51. ; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE
  52. ; 4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI
  53. ;
  54. ; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair
  55. #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
  56. ; carve pt_regs on stack (case #3), PC/STAT32 already on stack
  57. sub sp, sp, SZ_PT_REGS - 8
  58. __SAVE_REGFILE_HARD
  59. #else
  60. ; carve pt_regs on stack (case #4), which grew partially already
  61. sub sp, sp, PT_r0
  62. #endif
  63. __SAVE_REGFILE_SOFT
  64. .endm
  65. /*------------------------------------------------------------------------*/
  66. .macro EXCEPTION_PROLOGUE
  67. ; (A) Before jumping to Exception Vector, hardware micro-ops did following:
  68. ; 1. SP auto-switched to kernel mode stack
  69. ; 2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0)
  70. ;
  71. ; (B) Manually save the complete reg file below
  72. sub sp, sp, SZ_PT_REGS ; carve pt_regs
  73. ; _HARD saves r10 clobbered by _SOFT as scratch hence comes first
  74. __SAVE_REGFILE_HARD
  75. __SAVE_REGFILE_SOFT
  76. st r0, [sp] ; orig_r0
  77. lr r10, [eret]
  78. lr r11, [erstatus]
  79. ST2 r10, r11, PT_ret
  80. lr r10, [ecr]
  81. lr r11, [erbta]
  82. ST2 r10, r11, PT_event
  83. ; OUTPUT: r10 has ECR expected by EV_Trap
  84. .endm
  85. /*------------------------------------------------------------------------
  86. * This macro saves the registers manually which would normally be autosaved
  87. * by hardware on taken interrupts. It is used by
  88. * - exception handlers (which don't have autosave)
  89. * - interrupt autosave disabled due to CONFIG_ARC_IRQ_NO_AUTOSAVE
  90. */
  91. .macro __SAVE_REGFILE_HARD
  92. ST2 r0, r1, PT_r0
  93. ST2 r2, r3, PT_r2
  94. ST2 r4, r5, PT_r4
  95. ST2 r6, r7, PT_r6
  96. ST2 r8, r9, PT_r8
  97. ST2 r10, r11, PT_r10
  98. st blink, [sp, PT_blink]
  99. lr r10, [lp_end]
  100. lr r11, [lp_start]
  101. ST2 r10, r11, PT_lpe
  102. st lp_count, [sp, PT_lpc]
  103. ; skip JLI, LDI, EI for now
  104. .endm
  105. /*------------------------------------------------------------------------
  106. * This macros saves a bunch of other registers which can't be autosaved for
  107. * various reasons:
  108. * - r12: the last caller saved scratch reg since hardware saves in pairs so r0-r11
  109. * - r30: free reg, used by gcc as scratch
  110. * - ACCL/ACCH pair when they exist
  111. */
  112. .macro __SAVE_REGFILE_SOFT
  113. ST2 gp, fp, PT_r26 ; gp (r26), fp (r27)
  114. st r12, [sp, PT_sp + 4]
  115. st r30, [sp, PT_sp + 8]
  116. ; Saving pt_regs->sp correctly requires some extra work due to the way
  117. ; Auto stack switch works
  118. ; - U mode: retrieve it from AUX_USER_SP
  119. ; - K mode: add the offset from current SP where H/w starts auto push
  120. ;
  121. ; 1. Utilize the fact that Z bit is set if Intr taken in U mode
  122. ; 2. Upon entry SP is always saved (for any inspection, unwinding etc),
  123. ; but on return, restored only if U mode
  124. lr r10, [AUX_USER_SP] ; U mode SP
  125. ; ISA requires ADD.nz to have same dest and src reg operands
  126. mov.nz r10, sp
  127. add.nz r10, r10, SZ_PT_REGS ; K mode SP
  128. st r10, [sp, PT_sp] ; SP (pt_regs->sp)
  129. #ifdef CONFIG_ARC_CURR_IN_REG
  130. st r25, [sp, PT_user_r25]
  131. GET_CURR_TASK_ON_CPU r25
  132. #endif
  133. #ifdef CONFIG_ARC_HAS_ACCL_REGS
  134. ST2 r58, r59, PT_r58
  135. #endif
  136. /* clobbers r10, r11 registers pair */
  137. DSP_SAVE_REGFILE_IRQ
  138. .endm
  139. /*------------------------------------------------------------------------*/
  140. .macro __RESTORE_REGFILE_SOFT
  141. LD2 gp, fp, PT_r26 ; gp (r26), fp (r27)
  142. ld r12, [sp, PT_r12]
  143. ld r30, [sp, PT_r30]
  144. ; Restore SP (into AUX_USER_SP) only if returning to U mode
  145. ; - for K mode, it will be implicitly restored as stack is unwound
  146. ; - Z flag set on K is inverse of what hardware does on interrupt entry
  147. ; but that doesn't really matter
  148. bz 1f
  149. ld r10, [sp, PT_sp] ; SP (pt_regs->sp)
  150. sr r10, [AUX_USER_SP]
  151. 1:
  152. #ifdef CONFIG_ARC_CURR_IN_REG
  153. ld r25, [sp, PT_user_r25]
  154. #endif
  155. /* clobbers r10, r11 registers pair */
  156. DSP_RESTORE_REGFILE_IRQ
  157. #ifdef CONFIG_ARC_HAS_ACCL_REGS
  158. LD2 r58, r59, PT_r58
  159. #endif
  160. .endm
  161. /*------------------------------------------------------------------------*/
  162. .macro __RESTORE_REGFILE_HARD
  163. ld blink, [sp, PT_blink]
  164. LD2 r10, r11, PT_lpe
  165. sr r10, [lp_end]
  166. sr r11, [lp_start]
  167. ld r10, [sp, PT_lpc] ; lp_count can't be target of LD
  168. mov lp_count, r10
  169. LD2 r0, r1, PT_r0
  170. LD2 r2, r3, PT_r2
  171. LD2 r4, r5, PT_r4
  172. LD2 r6, r7, PT_r6
  173. LD2 r8, r9, PT_r8
  174. LD2 r10, r11, PT_r10
  175. .endm
  176. /*------------------------------------------------------------------------*/
  177. .macro INTERRUPT_EPILOGUE
  178. ; INPUT: r0 has STAT32 of calling context
  179. ; INPUT: Z flag set if returning to K mode
  180. ; _SOFT clobbers r10 restored by _HARD hence the order
  181. __RESTORE_REGFILE_SOFT
  182. #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
  183. __RESTORE_REGFILE_HARD
  184. ; SP points to PC/STAT32: hw restores them despite NO_AUTOSAVE
  185. add sp, sp, SZ_PT_REGS - 8
  186. #else
  187. add sp, sp, PT_r0
  188. #endif
  189. .endm
  190. /*------------------------------------------------------------------------*/
  191. .macro EXCEPTION_EPILOGUE
  192. ; INPUT: r0 has STAT32 of calling context
  193. btst r0, STATUS_U_BIT ; Z flag set if K, used in restoring SP
  194. ld r10, [sp, PT_event + 4]
  195. sr r10, [erbta]
  196. LD2 r10, r11, PT_ret
  197. sr r10, [eret]
  198. sr r11, [erstatus]
  199. __RESTORE_REGFILE_SOFT
  200. __RESTORE_REGFILE_HARD
  201. add sp, sp, SZ_PT_REGS
  202. .endm
  203. .macro FAKE_RET_FROM_EXCPN
  204. lr r9, [status32]
  205. bic r9, r9, STATUS_AE_MASK
  206. or r9, r9, STATUS_IE_MASK
  207. kflag r9
  208. .endm
  209. /* Get thread_info of "current" tsk */
  210. .macro GET_CURR_THR_INFO_FROM_SP reg
  211. bmskn \reg, sp, THREAD_SHIFT - 1
  212. .endm
  213. /* Get CPU-ID of this core */
  214. .macro GET_CPU_ID reg
  215. lr \reg, [identity]
  216. xbfu \reg, \reg, 0xE8 /* 00111 01000 */
  217. /* M = 8-1 N = 8 */
  218. .endm
  219. #endif