entry.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. /*
  2. * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. *
  8. * Vineetg: March 2009 (Supporting 2 levels of Interrupts)
  9. * Stack switching code can no longer reliably rely on the fact that
  10. * if we are NOT in user mode, stack is switched to kernel mode.
  11. * e.g. L2 IRQ interrupted a L1 ISR which had not yet completed
  12. * it's prologue including stack switching from user mode
  13. *
  14. * Vineetg: Aug 28th 2008: Bug #94984
  15. * -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
  16. * Normally CPU does this automatically, however when doing FAKE rtie,
  17. * we also need to explicitly do this. The problem in macros
  18. * FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
  19. * was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context
  20. *
  21. * Vineetg: May 5th 2008
  22. * -Modified CALLEE_REG save/restore macros to handle the fact that
  23. * r25 contains the kernel current task ptr
  24. * - Defined Stack Switching Macro to be reused in all intr/excp hdlrs
  25. * - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the
  26. * address Write back load ld.ab instead of seperate ld/add instn
  27. *
  28. * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
  29. */
  30. #ifndef __ASM_ARC_ENTRY_H
  31. #define __ASM_ARC_ENTRY_H
  32. #ifdef __ASSEMBLY__
  33. #include <asm/unistd.h> /* For NR_syscalls defination */
  34. #include <asm/asm-offsets.h>
  35. #include <asm/arcregs.h>
  36. #include <asm/ptrace.h>
  37. #include <asm/processor.h> /* For VMALLOC_START */
  38. #include <asm/thread_info.h> /* For THREAD_SIZE */
  39. #include <asm/mmu.h>
  40. /* Note on the LD/ST addr modes with addr reg wback
  41. *
  42. * LD.a same as LD.aw
  43. *
  44. * LD.a reg1, [reg2, x] => Pre Incr
  45. * Eff Addr for load = [reg2 + x]
  46. *
  47. * LD.ab reg1, [reg2, x] => Post Incr
  48. * Eff Addr for load = [reg2]
  49. */
  50. .macro PUSH reg
  51. st.a \reg, [sp, -4]
  52. .endm
  53. .macro PUSHAX aux
  54. lr r9, [\aux]
  55. PUSH r9
  56. .endm
  57. .macro POP reg
  58. ld.ab \reg, [sp, 4]
  59. .endm
  60. .macro POPAX aux
  61. POP r9
  62. sr r9, [\aux]
  63. .endm
  64. /*--------------------------------------------------------------
  65. * Helpers to save/restore Scratch Regs:
  66. * used by Interrupt/Exception Prologue/Epilogue
  67. *-------------------------------------------------------------*/
  68. .macro SAVE_R0_TO_R12
  69. PUSH r0
  70. PUSH r1
  71. PUSH r2
  72. PUSH r3
  73. PUSH r4
  74. PUSH r5
  75. PUSH r6
  76. PUSH r7
  77. PUSH r8
  78. PUSH r9
  79. PUSH r10
  80. PUSH r11
  81. PUSH r12
  82. .endm
  83. .macro RESTORE_R12_TO_R0
  84. POP r12
  85. POP r11
  86. POP r10
  87. POP r9
  88. POP r8
  89. POP r7
  90. POP r6
  91. POP r5
  92. POP r4
  93. POP r3
  94. POP r2
  95. POP r1
  96. POP r0
  97. #ifdef CONFIG_ARC_CURR_IN_REG
  98. ld r25, [sp, 12]
  99. #endif
  100. .endm
  101. /*--------------------------------------------------------------
  102. * Helpers to save/restore callee-saved regs:
  103. * used by several macros below
  104. *-------------------------------------------------------------*/
  105. .macro SAVE_R13_TO_R24
  106. PUSH r13
  107. PUSH r14
  108. PUSH r15
  109. PUSH r16
  110. PUSH r17
  111. PUSH r18
  112. PUSH r19
  113. PUSH r20
  114. PUSH r21
  115. PUSH r22
  116. PUSH r23
  117. PUSH r24
  118. .endm
  119. .macro RESTORE_R24_TO_R13
  120. POP r24
  121. POP r23
  122. POP r22
  123. POP r21
  124. POP r20
  125. POP r19
  126. POP r18
  127. POP r17
  128. POP r16
  129. POP r15
  130. POP r14
  131. POP r13
  132. .endm
  133. #define OFF_USER_R25_FROM_R24 (SZ_CALLEE_REGS + SZ_PT_REGS - 8)/4
  134. /*--------------------------------------------------------------
  135. * Collect User Mode callee regs as struct callee_regs - needed by
  136. * fork/do_signal/unaligned-access-emulation.
  137. * (By default only scratch regs are saved on entry to kernel)
  138. *
  139. * Special handling for r25 if used for caching Task Pointer.
  140. * It would have been saved in task->thread.user_r25 already, but to keep
  141. * the interface same it is copied into regular r25 placeholder in
  142. * struct callee_regs.
  143. *-------------------------------------------------------------*/
  144. .macro SAVE_CALLEE_SAVED_USER
  145. SAVE_R13_TO_R24
  146. #ifdef CONFIG_ARC_CURR_IN_REG
  147. ; Retrieve orig r25 and save it on stack
  148. ld.as r12, [sp, OFF_USER_R25_FROM_R24]
  149. st.a r12, [sp, -4]
  150. #else
  151. PUSH r25
  152. #endif
  153. .endm
  154. /*--------------------------------------------------------------
  155. * Save kernel Mode callee regs at the time of Contect Switch.
  156. *
  157. * Special handling for r25 if used for caching Task Pointer.
  158. * Kernel simply skips saving it since it will be loaded with
  159. * incoming task pointer anyways
  160. *-------------------------------------------------------------*/
  161. .macro SAVE_CALLEE_SAVED_KERNEL
  162. SAVE_R13_TO_R24
  163. #ifdef CONFIG_ARC_CURR_IN_REG
  164. sub sp, sp, 4
  165. #else
  166. PUSH r25
  167. #endif
  168. .endm
  169. /*--------------------------------------------------------------
  170. * Opposite of SAVE_CALLEE_SAVED_KERNEL
  171. *-------------------------------------------------------------*/
  172. .macro RESTORE_CALLEE_SAVED_KERNEL
  173. #ifdef CONFIG_ARC_CURR_IN_REG
  174. add sp, sp, 4 /* skip usual r25 placeholder */
  175. #else
  176. POP r25
  177. #endif
  178. RESTORE_R24_TO_R13
  179. .endm
  180. /*--------------------------------------------------------------
  181. * Opposite of SAVE_CALLEE_SAVED_USER
  182. *
  183. * ptrace tracer or unaligned-access fixup might have changed a user mode
  184. * callee reg which is saved back to usual r25 storage location
  185. *-------------------------------------------------------------*/
  186. .macro RESTORE_CALLEE_SAVED_USER
  187. #ifdef CONFIG_ARC_CURR_IN_REG
  188. ld.ab r12, [sp, 4]
  189. st.as r12, [sp, OFF_USER_R25_FROM_R24]
  190. #else
  191. POP r25
  192. #endif
  193. RESTORE_R24_TO_R13
  194. .endm
  195. /*--------------------------------------------------------------
  196. * Super FAST Restore callee saved regs by simply re-adjusting SP
  197. *-------------------------------------------------------------*/
  198. .macro DISCARD_CALLEE_SAVED_USER
  199. add sp, sp, SZ_CALLEE_REGS
  200. .endm
  201. /*-------------------------------------------------------------
  202. * given a tsk struct, get to the base of it's kernel mode stack
  203. * tsk->thread_info is really a PAGE, whose bottom hoists stack
  204. * which grows upwards towards thread_info
  205. *------------------------------------------------------------*/
  206. .macro GET_TSK_STACK_BASE tsk, out
  207. /* Get task->thread_info (this is essentially start of a PAGE) */
  208. ld \out, [\tsk, TASK_THREAD_INFO]
  209. /* Go to end of page where stack begins (grows upwards) */
  210. add2 \out, \out, (THREAD_SIZE)/4
  211. .endm
  212. /*--------------------------------------------------------------
  213. * Switch to Kernel Mode stack if SP points to User Mode stack
  214. *
  215. * Entry : r9 contains pre-IRQ/exception/trap status32
  216. * Exit : SP is set to kernel mode stack pointer
  217. * If CURR_IN_REG, r25 set to "current" task pointer
  218. * Clobbers: r9
  219. *-------------------------------------------------------------*/
  220. .macro SWITCH_TO_KERNEL_STK
  221. /* User Mode when this happened ? Yes: Proceed to switch stack */
  222. bbit1 r9, STATUS_U_BIT, 88f
  223. /* OK we were already in kernel mode when this event happened, thus can
  224. * assume SP is kernel mode SP. _NO_ need to do any stack switching
  225. */
  226. #ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
  227. /* However....
  228. * If Level 2 Interrupts enabled, we may end up with a corner case:
  229. * 1. User Task executing
  230. * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode)
  231. * 3. But before it could switch SP from USER to KERNEL stack
  232. * a L2 IRQ "Interrupts" L1
  233. * Thay way although L2 IRQ happened in Kernel mode, stack is still
  234. * not switched.
  235. * To handle this, we may need to switch stack even if in kernel mode
  236. * provided SP has values in range of USER mode stack ( < 0x7000_0000 )
  237. */
  238. brlo sp, VMALLOC_START, 88f
  239. /* TODO: vineetg:
  240. * We need to be a bit more cautious here. What if a kernel bug in
  241. * L1 ISR, caused SP to go whaco (some small value which looks like
  242. * USER stk) and then we take L2 ISR.
  243. * Above brlo alone would treat it as a valid L1-L2 sceanrio
  244. * instead of shouting alound
  245. * The only feasible way is to make sure this L2 happened in
  246. * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in
  247. * L1 ISR before it switches stack
  248. */
  249. #endif
  250. /* Save Pre Intr/Exception KERNEL MODE SP on kernel stack
  251. * safe-keeping not really needed, but it keeps the epilogue code
  252. * (SP restore) simpler/uniform.
  253. */
  254. b.d 66f
  255. mov r9, sp
  256. 88: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */
  257. GET_CURR_TASK_ON_CPU r9
  258. /* With current tsk in r9, get it's kernel mode stack base */
  259. GET_TSK_STACK_BASE r9, r9
  260. 66:
  261. #ifdef CONFIG_ARC_CURR_IN_REG
  262. /*
  263. * Treat r25 as scratch reg, save it on stack first
  264. * Load it with current task pointer
  265. */
  266. st r25, [r9, -4]
  267. GET_CURR_TASK_ON_CPU r25
  268. #endif
  269. /* Save Pre Intr/Exception User SP on kernel stack */
  270. st.a sp, [r9, -16] ; Make room for orig_r0, ECR, user_r25
  271. /* CAUTION:
  272. * SP should be set at the very end when we are done with everything
  273. * In case of 2 levels of interrupt we depend on value of SP to assume
  274. * that everything else is done (loading r25 etc)
  275. */
  276. /* set SP to point to kernel mode stack */
  277. mov sp, r9
  278. /* ----- Stack Switched to kernel Mode, Now save REG FILE ----- */
  279. .endm
  280. /*------------------------------------------------------------
  281. * "FAKE" a rtie to return from CPU Exception context
  282. * This is to re-enable Exceptions within exception
  283. * Look at EV_ProtV to see how this is actually used
  284. *-------------------------------------------------------------*/
  285. .macro FAKE_RET_FROM_EXCPN reg
  286. ld \reg, [sp, PT_status32]
  287. bic \reg, \reg, (STATUS_U_MASK|STATUS_DE_MASK)
  288. bset \reg, \reg, STATUS_L_BIT
  289. sr \reg, [erstatus]
  290. mov \reg, 55f
  291. sr \reg, [eret]
  292. rtie
  293. 55:
  294. .endm
  295. /*
  296. * @reg [OUT] &thread_info of "current"
  297. */
  298. .macro GET_CURR_THR_INFO_FROM_SP reg
  299. bic \reg, sp, (THREAD_SIZE - 1)
  300. .endm
  301. /*
  302. * @reg [OUT] thread_info->flags of "current"
  303. */
  304. .macro GET_CURR_THR_INFO_FLAGS reg
  305. GET_CURR_THR_INFO_FROM_SP \reg
  306. ld \reg, [\reg, THREAD_INFO_FLAGS]
  307. .endm
  308. /*--------------------------------------------------------------
  309. * For early Exception Prologue, a core reg is temporarily needed to
  310. * code the rest of prolog (stack switching). This is done by stashing
  311. * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP).
  312. *
  313. * Before saving the full regfile - this reg is restored back, only
  314. * to be saved again on kernel mode stack, as part of ptregs.
  315. *-------------------------------------------------------------*/
  316. .macro EXCPN_PROLOG_FREEUP_REG reg
  317. #ifdef CONFIG_SMP
  318. sr \reg, [ARC_REG_SCRATCH_DATA0]
  319. #else
  320. st \reg, [@ex_saved_reg1]
  321. #endif
  322. .endm
  323. .macro EXCPN_PROLOG_RESTORE_REG reg
  324. #ifdef CONFIG_SMP
  325. lr \reg, [ARC_REG_SCRATCH_DATA0]
  326. #else
  327. ld \reg, [@ex_saved_reg1]
  328. #endif
  329. .endm
  330. /*--------------------------------------------------------------
  331. * Save all registers used by Exceptions (TLB Miss, Prot-V, Mem err etc)
  332. * Requires SP to be already switched to kernel mode Stack
  333. * sp points to the next free element on the stack at exit of this macro.
  334. * Registers are pushed / popped in the order defined in struct ptregs
  335. * in asm/ptrace.h
  336. * Note that syscalls are implemented via TRAP which is also a exception
  337. * from CPU's point of view
  338. *-------------------------------------------------------------*/
  339. .macro SAVE_ALL_SYS
  340. lr r9, [ecr]
  341. st r9, [sp, 8] /* ECR */
  342. st r0, [sp, 4] /* orig_r0, needed only for sys calls */
  343. /* Restore r9 used to code the early prologue */
  344. EXCPN_PROLOG_RESTORE_REG r9
  345. SAVE_R0_TO_R12
  346. PUSH gp
  347. PUSH fp
  348. PUSH blink
  349. PUSHAX eret
  350. PUSHAX erstatus
  351. PUSH lp_count
  352. PUSHAX lp_end
  353. PUSHAX lp_start
  354. PUSHAX erbta
  355. .endm
  356. /*--------------------------------------------------------------
  357. * Restore all registers used by system call or Exceptions
  358. * SP should always be pointing to the next free stack element
  359. * when entering this macro.
  360. *
  361. * NOTE:
  362. *
  363. * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
  364. * for memory load operations. If used in that way interrupts are deffered
  365. * by hardware and that is not good.
  366. *-------------------------------------------------------------*/
  367. .macro RESTORE_ALL_SYS
  368. POPAX erbta
  369. POPAX lp_start
  370. POPAX lp_end
  371. POP r9
  372. mov lp_count, r9 ;LD to lp_count is not allowed
  373. POPAX erstatus
  374. POPAX eret
  375. POP blink
  376. POP fp
  377. POP gp
  378. RESTORE_R12_TO_R0
  379. ld sp, [sp] /* restore original sp */
  380. /* orig_r0, ECR, user_r25 skipped automatically */
  381. .endm
  382. /*--------------------------------------------------------------
  383. * Save all registers used by interrupt handlers.
  384. *-------------------------------------------------------------*/
  385. .macro SAVE_ALL_INT1
  386. /* restore original r9 to be saved as part of reg-file */
  387. #ifdef CONFIG_SMP
  388. lr r9, [ARC_REG_SCRATCH_DATA0]
  389. #else
  390. ld r9, [@int1_saved_reg]
  391. #endif
  392. /* now we are ready to save the remaining context :) */
  393. st event_IRQ1, [sp, 8] /* Dummy ECR */
  394. st 0, [sp, 4] /* orig_r0 , N/A for IRQ */
  395. SAVE_R0_TO_R12
  396. PUSH gp
  397. PUSH fp
  398. PUSH blink
  399. PUSH ilink1
  400. PUSHAX status32_l1
  401. PUSH lp_count
  402. PUSHAX lp_end
  403. PUSHAX lp_start
  404. PUSHAX bta_l1
  405. .endm
  406. .macro SAVE_ALL_INT2
  407. /* TODO-vineetg: SMP we can't use global nor can we use
  408. * SCRATCH0 as we do for int1 because while int1 is using
  409. * it, int2 can come
  410. */
  411. /* retsore original r9 , saved in sys_saved_r9 */
  412. ld r9, [@int2_saved_reg]
  413. /* now we are ready to save the remaining context :) */
  414. st event_IRQ2, [sp, 8] /* Dummy ECR */
  415. st 0, [sp, 4] /* orig_r0 , N/A for IRQ */
  416. SAVE_R0_TO_R12
  417. PUSH gp
  418. PUSH fp
  419. PUSH blink
  420. PUSH ilink2
  421. PUSHAX status32_l2
  422. PUSH lp_count
  423. PUSHAX lp_end
  424. PUSHAX lp_start
  425. PUSHAX bta_l2
  426. .endm
  427. /*--------------------------------------------------------------
  428. * Restore all registers used by interrupt handlers.
  429. *
  430. * NOTE:
  431. *
  432. * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
  433. * for memory load operations. If used in that way interrupts are deffered
  434. * by hardware and that is not good.
  435. *-------------------------------------------------------------*/
  436. .macro RESTORE_ALL_INT1
  437. POPAX bta_l1
  438. POPAX lp_start
  439. POPAX lp_end
  440. POP r9
  441. mov lp_count, r9 ;LD to lp_count is not allowed
  442. POPAX status32_l1
  443. POP ilink1
  444. POP blink
  445. POP fp
  446. POP gp
  447. RESTORE_R12_TO_R0
  448. ld sp, [sp] /* restore original sp */
  449. /* orig_r0, ECR, user_r25 skipped automatically */
  450. .endm
  451. .macro RESTORE_ALL_INT2
  452. POPAX bta_l2
  453. POPAX lp_start
  454. POPAX lp_end
  455. POP r9
  456. mov lp_count, r9 ;LD to lp_count is not allowed
  457. POPAX status32_l2
  458. POP ilink2
  459. POP blink
  460. POP fp
  461. POP gp
  462. RESTORE_R12_TO_R0
  463. ld sp, [sp] /* restore original sp */
  464. /* orig_r0, ECR, user_r25 skipped automatically */
  465. .endm
  466. /* Get CPU-ID of this core */
  467. .macro GET_CPU_ID reg
  468. lr \reg, [identity]
  469. lsr \reg, \reg, 8
  470. bmsk \reg, \reg, 7
  471. .endm
  472. #ifdef CONFIG_SMP
  473. /*-------------------------------------------------
  474. * Retrieve the current running task on this CPU
  475. * 1. Determine curr CPU id.
  476. * 2. Use it to index into _current_task[ ]
  477. */
  478. .macro GET_CURR_TASK_ON_CPU reg
  479. GET_CPU_ID \reg
  480. ld.as \reg, [@_current_task, \reg]
  481. .endm
  482. /*-------------------------------------------------
  483. * Save a new task as the "current" task on this CPU
  484. * 1. Determine curr CPU id.
  485. * 2. Use it to index into _current_task[ ]
  486. *
  487. * Coded differently than GET_CURR_TASK_ON_CPU (which uses LD.AS)
  488. * because ST r0, [r1, offset] can ONLY have s9 @offset
  489. * while LD can take s9 (4 byte insn) or LIMM (8 byte insn)
  490. */
  491. .macro SET_CURR_TASK_ON_CPU tsk, tmp
  492. GET_CPU_ID \tmp
  493. add2 \tmp, @_current_task, \tmp
  494. st \tsk, [\tmp]
  495. #ifdef CONFIG_ARC_CURR_IN_REG
  496. mov r25, \tsk
  497. #endif
  498. .endm
  499. #else /* Uniprocessor implementation of macros */
  500. .macro GET_CURR_TASK_ON_CPU reg
  501. ld \reg, [@_current_task]
  502. .endm
  503. .macro SET_CURR_TASK_ON_CPU tsk, tmp
  504. st \tsk, [@_current_task]
  505. #ifdef CONFIG_ARC_CURR_IN_REG
  506. mov r25, \tsk
  507. #endif
  508. .endm
  509. #endif /* SMP / UNI */
  510. /* ------------------------------------------------------------------
  511. * Get the ptr to some field of Current Task at @off in task struct
  512. * -Uses r25 for Current task ptr if that is enabled
  513. */
  514. #ifdef CONFIG_ARC_CURR_IN_REG
  515. .macro GET_CURR_TASK_FIELD_PTR off, reg
  516. add \reg, r25, \off
  517. .endm
  518. #else
  519. .macro GET_CURR_TASK_FIELD_PTR off, reg
  520. GET_CURR_TASK_ON_CPU \reg
  521. add \reg, \reg, \off
  522. .endm
  523. #endif /* CONFIG_ARC_CURR_IN_REG */
  524. #endif /* __ASSEMBLY__ */
  525. #endif /* __ASM_ARC_ENTRY_H */