coprocessor.S 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * arch/xtensa/kernel/coprocessor.S
  3. *
  4. * Xtensa processor configuration-specific table of coprocessor and
  5. * other custom register layout information.
  6. *
  7. * This file is subject to the terms and conditions of the GNU General Public
  8. * License. See the file "COPYING" in the main directory of this archive
  9. * for more details.
  10. *
  11. * Copyright (C) 2003 - 2007 Tensilica Inc.
  12. */
  13. #include <linux/linkage.h>
  14. #include <asm/asm-offsets.h>
  15. #include <asm/asmmacro.h>
  16. #include <asm/coprocessor.h>
  17. #include <asm/current.h>
  18. #include <asm/regs.h>
  19. /*
  20. * Rules for coprocessor state manipulation on SMP:
  21. *
  22. * - a task may have live coprocessors only on one CPU.
  23. *
  24. * - whether coprocessor context of task T is live on some CPU is
  25. * denoted by T's thread_info->cpenable.
  26. *
  27. * - non-zero thread_info->cpenable means that thread_info->cp_owner_cpu
  28. * is valid in the T's thread_info. Zero thread_info->cpenable means that
  29. * coprocessor context is valid in the T's thread_info.
  30. *
  31. * - if a coprocessor context of task T is live on CPU X, only CPU X changes
  32. * T's thread_info->cpenable, cp_owner_cpu and coprocessor save area.
  33. * This is done by making sure that for the task T with live coprocessor
  34. * on CPU X cpenable SR is 0 when T runs on any other CPU Y.
  35. * When fast_coprocessor exception is taken on CPU Y it goes to the
  36. * C-level do_coprocessor that uses IPI to make CPU X flush T's coprocessors.
  37. */
  38. #if XTENSA_HAVE_COPROCESSORS
  39. /*
  40. * Macros for lazy context switch.
  41. */
  42. #define SAVE_CP_REGS(x) \
  43. .if XTENSA_HAVE_COPROCESSOR(x); \
  44. .align 4; \
  45. .Lsave_cp_regs_cp##x: \
  46. xchal_cp##x##_store a2 a3 a4 a5 a6; \
  47. ret; \
  48. .endif
  49. #define LOAD_CP_REGS(x) \
  50. .if XTENSA_HAVE_COPROCESSOR(x); \
  51. .align 4; \
  52. .Lload_cp_regs_cp##x: \
  53. xchal_cp##x##_load a2 a3 a4 a5 a6; \
  54. ret; \
  55. .endif
  56. #define CP_REGS_TAB(x) \
  57. .if XTENSA_HAVE_COPROCESSOR(x); \
  58. .long .Lsave_cp_regs_cp##x; \
  59. .long .Lload_cp_regs_cp##x; \
  60. .else; \
  61. .long 0, 0; \
  62. .endif; \
  63. .long THREAD_XTREGS_CP##x
  64. #define CP_REGS_TAB_SAVE 0
  65. #define CP_REGS_TAB_LOAD 4
  66. #define CP_REGS_TAB_OFFSET 8
  67. __XTENSA_HANDLER
  68. SAVE_CP_REGS(0)
  69. SAVE_CP_REGS(1)
  70. SAVE_CP_REGS(2)
  71. SAVE_CP_REGS(3)
  72. SAVE_CP_REGS(4)
  73. SAVE_CP_REGS(5)
  74. SAVE_CP_REGS(6)
  75. SAVE_CP_REGS(7)
  76. LOAD_CP_REGS(0)
  77. LOAD_CP_REGS(1)
  78. LOAD_CP_REGS(2)
  79. LOAD_CP_REGS(3)
  80. LOAD_CP_REGS(4)
  81. LOAD_CP_REGS(5)
  82. LOAD_CP_REGS(6)
  83. LOAD_CP_REGS(7)
  84. .align 4
  85. .Lcp_regs_jump_table:
  86. CP_REGS_TAB(0)
  87. CP_REGS_TAB(1)
  88. CP_REGS_TAB(2)
  89. CP_REGS_TAB(3)
  90. CP_REGS_TAB(4)
  91. CP_REGS_TAB(5)
  92. CP_REGS_TAB(6)
  93. CP_REGS_TAB(7)
  94. /*
  95. * Entry condition:
  96. *
  97. * a0: trashed, original value saved on stack (PT_AREG0)
  98. * a1: a1
  99. * a2: new stack pointer, original in DEPC
  100. * a3: a3
  101. * depc: a2, original value saved on stack (PT_DEPC)
  102. * excsave_1: dispatch table
  103. *
  104. * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
  105. * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
  106. */
  107. ENTRY(fast_coprocessor)
  108. s32i a3, a2, PT_AREG3
  109. #ifdef CONFIG_SMP
  110. /*
  111. * Check if any coprocessor context is live on another CPU
  112. * and if so go through the C-level coprocessor exception handler
  113. * to flush it to memory.
  114. */
  115. GET_THREAD_INFO (a0, a2)
  116. l32i a3, a0, THREAD_CPENABLE
  117. beqz a3, .Lload_local
  118. /*
  119. * Pairs with smp_wmb in local_coprocessor_release_all
  120. * and with both memws below.
  121. */
  122. memw
  123. l32i a3, a0, THREAD_CPU
  124. l32i a0, a0, THREAD_CP_OWNER_CPU
  125. beq a0, a3, .Lload_local
  126. rsr a0, ps
  127. l32i a3, a2, PT_AREG3
  128. bbci.l a0, PS_UM_BIT, 1f
  129. call0 user_exception
  130. 1: call0 kernel_exception
  131. #endif
  132. /* Save remaining registers a1-a3 and SAR */
  133. .Lload_local:
  134. rsr a3, sar
  135. s32i a1, a2, PT_AREG1
  136. s32i a3, a2, PT_SAR
  137. mov a1, a2
  138. rsr a2, depc
  139. s32i a2, a1, PT_AREG2
  140. /* The hal macros require up to 4 temporary registers. We use a3..a6. */
  141. s32i a4, a1, PT_AREG4
  142. s32i a5, a1, PT_AREG5
  143. s32i a6, a1, PT_AREG6
  144. s32i a7, a1, PT_AREG7
  145. s32i a8, a1, PT_AREG8
  146. s32i a9, a1, PT_AREG9
  147. s32i a10, a1, PT_AREG10
  148. /* Find coprocessor number. Subtract first CP EXCCAUSE from EXCCAUSE */
  149. rsr a3, exccause
  150. addi a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
  151. /* Set corresponding CPENABLE bit -> (sar:cp-index, a3: 1<<cp-index)*/
  152. ssl a3 # SAR: 32 - coprocessor_number
  153. movi a2, 1
  154. rsr a0, cpenable
  155. sll a2, a2
  156. or a0, a0, a2
  157. wsr a0, cpenable
  158. rsync
  159. /* Get coprocessor save/load table entry (a7). */
  160. movi a7, .Lcp_regs_jump_table
  161. addx8 a7, a3, a7
  162. addx4 a7, a3, a7
  163. /* Retrieve previous owner (a8). */
  164. rsr a0, excsave1 # exc_table
  165. addx4 a0, a3, a0 # entry for CP
  166. l32i a8, a0, EXC_TABLE_COPROCESSOR_OWNER
  167. /* Set new owner (a9). */
  168. GET_THREAD_INFO (a9, a1)
  169. l32i a4, a9, THREAD_CPU
  170. s32i a9, a0, EXC_TABLE_COPROCESSOR_OWNER
  171. s32i a4, a9, THREAD_CP_OWNER_CPU
  172. /*
  173. * Enable coprocessor for the new owner. (a2 = 1 << CP number)
  174. * This can be done before loading context into the coprocessor.
  175. */
  176. l32i a4, a9, THREAD_CPENABLE
  177. or a4, a4, a2
  178. /*
  179. * Make sure THREAD_CP_OWNER_CPU is in memory before updating
  180. * THREAD_CPENABLE
  181. */
  182. memw # (2)
  183. s32i a4, a9, THREAD_CPENABLE
  184. beqz a8, 1f # skip 'save' if no previous owner
  185. /* Disable coprocessor for previous owner. (a2 = 1 << CP number) */
  186. l32i a10, a8, THREAD_CPENABLE
  187. xor a10, a10, a2
  188. /* Get context save area and call save routine. */
  189. l32i a2, a7, CP_REGS_TAB_OFFSET
  190. l32i a3, a7, CP_REGS_TAB_SAVE
  191. add a2, a2, a8
  192. callx0 a3
  193. /*
  194. * Make sure coprocessor context and THREAD_CP_OWNER_CPU are in memory
  195. * before updating THREAD_CPENABLE
  196. */
  197. memw # (3)
  198. s32i a10, a8, THREAD_CPENABLE
  199. 1:
  200. /* Get context save area and call load routine. */
  201. l32i a2, a7, CP_REGS_TAB_OFFSET
  202. l32i a3, a7, CP_REGS_TAB_LOAD
  203. add a2, a2, a9
  204. callx0 a3
  205. /* Restore all registers and return from exception handler. */
  206. l32i a10, a1, PT_AREG10
  207. l32i a9, a1, PT_AREG9
  208. l32i a8, a1, PT_AREG8
  209. l32i a7, a1, PT_AREG7
  210. l32i a6, a1, PT_AREG6
  211. l32i a5, a1, PT_AREG5
  212. l32i a4, a1, PT_AREG4
  213. l32i a0, a1, PT_SAR
  214. l32i a3, a1, PT_AREG3
  215. l32i a2, a1, PT_AREG2
  216. wsr a0, sar
  217. l32i a0, a1, PT_AREG0
  218. l32i a1, a1, PT_AREG1
  219. rfe
  220. ENDPROC(fast_coprocessor)
  221. .text
  222. /*
  223. * coprocessor_flush(struct thread_info*, index)
  224. * a2 a3
  225. *
  226. * Save coprocessor registers for coprocessor 'index'.
  227. * The register values are saved to or loaded from the coprocessor area
  228. * inside the task_info structure.
  229. *
  230. * Note that this function doesn't update the coprocessor_owner information!
  231. *
  232. */
  233. ENTRY(coprocessor_flush)
  234. abi_entry_default
  235. movi a4, .Lcp_regs_jump_table
  236. addx8 a4, a3, a4
  237. addx4 a3, a3, a4
  238. l32i a4, a3, CP_REGS_TAB_SAVE
  239. beqz a4, 1f
  240. l32i a3, a3, CP_REGS_TAB_OFFSET
  241. add a2, a2, a3
  242. mov a7, a0
  243. callx0 a4
  244. mov a0, a7
  245. 1:
  246. abi_ret_default
  247. ENDPROC(coprocessor_flush)
  248. #endif /* XTENSA_HAVE_COPROCESSORS */