entry-compact.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
  4. * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  5. *
  6. * Vineetg: March 2009 (Supporting 2 levels of Interrupts)
  7. * Stack switching code can no longer reliably rely on the fact that
  8. * if we are NOT in user mode, stack is switched to kernel mode.
  9. * e.g. L2 IRQ interrupted a L1 ISR which had not yet completed
  10. * its prologue including stack switching from user mode
  11. *
  12. * Vineetg: Aug 28th 2008: Bug #94984
  13. * -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
  14. * Normally CPU does this automatically, however when doing FAKE rtie,
  15. * we also need to explicitly do this. The problem in macros
  16. * FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
  17. * was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context
  18. *
  19. * Vineetg: May 5th 2008
  20. * -Modified CALLEE_REG save/restore macros to handle the fact that
  21. * r25 contains the kernel current task ptr
  22. * - Defined Stack Switching Macro to be reused in all intr/excp hdlrs
  23. * - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the
  24. * address Write back load ld.ab instead of separate ld/add instn
  25. *
  26. * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
  27. */
  28. #ifndef __ASM_ARC_ENTRY_COMPACT_H
  29. #define __ASM_ARC_ENTRY_COMPACT_H
  30. #include <asm/asm-offsets.h>
  31. #include <asm/irqflags-compact.h>
  32. #include <asm/thread_info.h> /* For THREAD_SIZE */
  33. /* Note on the LD/ST addr modes with addr reg wback
  34. *
  35. * LD.a same as LD.aw
  36. *
  37. * LD.a reg1, [reg2, x] => Pre Incr
  38. * Eff Addr for load = [reg2 + x]
  39. *
  40. * LD.ab reg1, [reg2, x] => Post Incr
  41. * Eff Addr for load = [reg2]
  42. */
  43. .macro PUSHAX aux
  44. lr r9, [\aux]
  45. push r9
  46. .endm
  47. .macro POPAX aux
  48. pop r9
  49. sr r9, [\aux]
  50. .endm
  51. .macro SAVE_R0_TO_R12
  52. push r0
  53. push r1
  54. push r2
  55. push r3
  56. push r4
  57. push r5
  58. push r6
  59. push r7
  60. push r8
  61. push r9
  62. push r10
  63. push r11
  64. push r12
  65. .endm
  66. .macro RESTORE_R12_TO_R0
  67. pop r12
  68. pop r11
  69. pop r10
  70. pop r9
  71. pop r8
  72. pop r7
  73. pop r6
  74. pop r5
  75. pop r4
  76. pop r3
  77. pop r2
  78. pop r1
  79. pop r0
  80. .endm
  81. .macro SAVE_ABI_CALLEE_REGS
  82. push r13
  83. push r14
  84. push r15
  85. push r16
  86. push r17
  87. push r18
  88. push r19
  89. push r20
  90. push r21
  91. push r22
  92. push r23
  93. push r24
  94. push r25
  95. .endm
  96. .macro RESTORE_ABI_CALLEE_REGS
  97. pop r25
  98. pop r24
  99. pop r23
  100. pop r22
  101. pop r21
  102. pop r20
  103. pop r19
  104. pop r18
  105. pop r17
  106. pop r16
  107. pop r15
  108. pop r14
  109. pop r13
  110. .endm
  111. /*--------------------------------------------------------------
  112. * Switch to Kernel Mode stack if SP points to User Mode stack
  113. *
  114. * Entry : r9 contains pre-IRQ/exception/trap status32
  115. * Exit : SP set to K mode stack
  116. * SP at the time of entry (K/U) saved @ pt_regs->sp
  117. * Clobbers: r9
  118. *-------------------------------------------------------------*/
  119. .macro SWITCH_TO_KERNEL_STK
  120. /* User Mode when this happened ? Yes: Proceed to switch stack */
  121. bbit1 r9, STATUS_U_BIT, 88f
  122. /* OK we were already in kernel mode when this event happened, thus can
  123. * assume SP is kernel mode SP. _NO_ need to do any stack switching
  124. */
  125. #ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
  126. /* However....
  127. * If Level 2 Interrupts enabled, we may end up with a corner case:
  128. * 1. User Task executing
  129. * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode)
  130. * 3. But before it could switch SP from USER to KERNEL stack
  131. * a L2 IRQ "Interrupts" L1
  132. * That way although L2 IRQ happened in Kernel mode, stack is still
  133. * not switched.
  134. * To handle this, we may need to switch stack even if in kernel mode
  135. * provided SP has values in range of USER mode stack ( < 0x7000_0000 )
  136. */
  137. brlo sp, VMALLOC_START, 88f
  138. /* TODO: vineetg:
  139. * We need to be a bit more cautious here. What if a kernel bug in
  140. * L1 ISR, caused SP to go whaco (some small value which looks like
  141. * USER stk) and then we take L2 ISR.
  142. * Above brlo alone would treat it as a valid L1-L2 scenario
  143. * instead of shouting around
  144. * The only feasible way is to make sure this L2 happened in
  145. * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in
  146. * L1 ISR before it switches stack
  147. */
  148. #endif
  149. /*------Intr/Ecxp happened in kernel mode, SP already setup ------ */
  150. /* save it nevertheless @ pt_regs->sp for uniformity */
  151. b.d 66f
  152. st sp, [sp, PT_sp - SZ_PT_REGS]
  153. 88: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */
  154. GET_CURR_TASK_ON_CPU r9
  155. /* With current tsk in r9, get its kernel mode stack base */
  156. GET_TSK_STACK_BASE r9, r9
  157. /* save U mode SP @ pt_regs->sp */
  158. st sp, [r9, PT_sp - SZ_PT_REGS]
  159. /* final SP switch */
  160. mov sp, r9
  161. 66:
  162. .endm
  163. /*------------------------------------------------------------
  164. * "FAKE" a rtie to return from CPU Exception context
  165. * This is to re-enable Exceptions within exception
  166. * Look at EV_ProtV to see how this is actually used
  167. *-------------------------------------------------------------*/
  168. .macro FAKE_RET_FROM_EXCPN
  169. lr r9, [status32]
  170. bclr r9, r9, STATUS_AE_BIT
  171. or r9, r9, (STATUS_E1_MASK|STATUS_E2_MASK)
  172. sr r9, [erstatus]
  173. mov r9, 55f
  174. sr r9, [eret]
  175. rtie
  176. 55:
  177. .endm
  178. /*--------------------------------------------------------------
  179. * For early Exception/ISR Prologue, a core reg is temporarily needed to
  180. * code the rest of prolog (stack switching). This is done by stashing
  181. * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP).
  182. *
  183. * Before saving the full regfile - this reg is restored back, only
  184. * to be saved again on kernel mode stack, as part of pt_regs.
  185. *-------------------------------------------------------------*/
  186. .macro PROLOG_FREEUP_REG reg, mem
  187. st \reg, [\mem]
  188. .endm
  189. .macro PROLOG_RESTORE_REG reg, mem
  190. ld \reg, [\mem]
  191. .endm
  192. /*--------------------------------------------------------------
  193. * Exception Entry prologue
  194. * -Switches stack to K mode (if not already)
  195. * -Saves the register file
  196. *
  197. * After this it is safe to call the "C" handlers
  198. *-------------------------------------------------------------*/
  199. .macro EXCEPTION_PROLOGUE_KEEP_AE
  200. /* Need at least 1 reg to code the early exception prologue */
  201. PROLOG_FREEUP_REG r9, @ex_saved_reg1
  202. /* U/K mode at time of exception (stack not switched if already K) */
  203. lr r9, [erstatus]
  204. /* ARC700 doesn't provide auto-stack switching */
  205. SWITCH_TO_KERNEL_STK
  206. st.a r0, [sp, -8] /* orig_r0 needed for syscall (skip ECR slot) */
  207. sub sp, sp, 4 /* skip pt_regs->sp, already saved above */
  208. /* Restore r9 used to code the early prologue */
  209. PROLOG_RESTORE_REG r9, @ex_saved_reg1
  210. /* now we are ready to save the regfile */
  211. SAVE_R0_TO_R12
  212. PUSH gp
  213. PUSH fp
  214. PUSH blink
  215. PUSHAX eret
  216. PUSHAX erstatus
  217. PUSH lp_count
  218. PUSHAX lp_end
  219. PUSHAX lp_start
  220. PUSHAX erbta
  221. lr r10, [ecr]
  222. st r10, [sp, PT_event]
  223. #ifdef CONFIG_ARC_CURR_IN_REG
  224. /* gp already saved on stack: now load with "current" */
  225. GET_CURR_TASK_ON_CPU gp
  226. #endif
  227. ; OUTPUT: r10 has ECR expected by EV_Trap
  228. .endm
  229. .macro EXCEPTION_PROLOGUE
  230. EXCEPTION_PROLOGUE_KEEP_AE ; return ECR in r10
  231. lr r0, [efa]
  232. mov r1, sp
  233. FAKE_RET_FROM_EXCPN ; clobbers r9
  234. .endm
  235. /*--------------------------------------------------------------
  236. * Restore all registers used by system call or Exceptions
  237. * SP should always be pointing to the next free stack element
  238. * when entering this macro.
  239. *
  240. * NOTE:
  241. *
  242. * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
  243. * for memory load operations. If used in that way interrupts are deferred
  244. * by hardware and that is not good.
  245. *-------------------------------------------------------------*/
  246. .macro EXCEPTION_EPILOGUE
  247. POPAX erbta
  248. POPAX lp_start
  249. POPAX lp_end
  250. POP r9
  251. mov lp_count, r9 ;LD to lp_count is not allowed
  252. POPAX erstatus
  253. POPAX eret
  254. POP blink
  255. POP fp
  256. POP gp
  257. RESTORE_R12_TO_R0
  258. ld sp, [sp] /* restore original sp */
  259. /* orig_r0, ECR skipped automatically */
  260. .endm
  261. /* Dummy ECR values for Interrupts */
  262. #define event_IRQ1 0x0031abcd
  263. #define event_IRQ2 0x0032abcd
  264. .macro INTERRUPT_PROLOGUE LVL
  265. /* free up r9 as scratchpad */
  266. PROLOG_FREEUP_REG r9, @int\LVL\()_saved_reg
  267. /* Which mode (user/kernel) was the system in when intr occurred */
  268. lr r9, [status32_l\LVL\()]
  269. SWITCH_TO_KERNEL_STK
  270. st.a 0x003\LVL\()abcd, [sp, -4] /* Dummy ECR */
  271. sub sp, sp, 8 /* skip orig_r0 (not needed)
  272. skip pt_regs->sp, already saved above */
  273. /* Restore r9 used to code the early prologue */
  274. PROLOG_RESTORE_REG r9, @int\LVL\()_saved_reg
  275. SAVE_R0_TO_R12
  276. PUSH gp
  277. PUSH fp
  278. PUSH blink
  279. PUSH ilink\LVL\()
  280. PUSHAX status32_l\LVL\()
  281. PUSH lp_count
  282. PUSHAX lp_end
  283. PUSHAX lp_start
  284. PUSHAX bta_l\LVL\()
  285. #ifdef CONFIG_ARC_CURR_IN_REG
  286. /* gp already saved on stack: now load with "current" */
  287. GET_CURR_TASK_ON_CPU gp
  288. #endif
  289. .endm
  290. /*--------------------------------------------------------------
  291. * Restore all registers used by interrupt handlers.
  292. *
  293. * NOTE:
  294. *
  295. * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
  296. * for memory load operations. If used in that way interrupts are deferred
  297. * by hardware and that is not good.
  298. *-------------------------------------------------------------*/
  299. .macro INTERRUPT_EPILOGUE LVL
  300. POPAX bta_l\LVL\()
  301. POPAX lp_start
  302. POPAX lp_end
  303. POP r9
  304. mov lp_count, r9 ;LD to lp_count is not allowed
  305. POPAX status32_l\LVL\()
  306. POP ilink\LVL\()
  307. POP blink
  308. POP fp
  309. POP gp
  310. RESTORE_R12_TO_R0
  311. ld sp, [sp] /* restore original sp; orig_r0, ECR skipped implicitly */
  312. .endm
  313. /* Get thread_info of "current" tsk */
  314. .macro GET_CURR_THR_INFO_FROM_SP reg
  315. bic \reg, sp, (THREAD_SIZE - 1)
  316. .endm
  317. /* Get CPU-ID of this core */
  318. .macro GET_CPU_ID reg
  319. lr \reg, [identity]
  320. lsr \reg, \reg, 8
  321. bmsk \reg, \reg, 7
  322. .endm
  323. #endif /* __ASM_ARC_ENTRY_COMPACT_H */