crunch-bits.S 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * arch/arm/kernel/crunch-bits.S
  4. * Cirrus MaverickCrunch context switching and handling
  5. *
  6. * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
  7. *
  8. * Shamelessly stolen from the iWMMXt code by Nicolas Pitre, which is
  9. * Copyright (c) 2003-2004, MontaVista Software, Inc.
  10. */
  11. #include <linux/linkage.h>
  12. #include <asm/ptrace.h>
  13. #include <asm/thread_info.h>
  14. #include <asm/asm-offsets.h>
  15. #include <asm/assembler.h>
  16. #include <mach/ep93xx-regs.h>
  17. /*
  18. * We can't use hex constants here due to a bug in gas.
  19. */
  20. #define CRUNCH_MVDX0 0
  21. #define CRUNCH_MVDX1 8
  22. #define CRUNCH_MVDX2 16
  23. #define CRUNCH_MVDX3 24
  24. #define CRUNCH_MVDX4 32
  25. #define CRUNCH_MVDX5 40
  26. #define CRUNCH_MVDX6 48
  27. #define CRUNCH_MVDX7 56
  28. #define CRUNCH_MVDX8 64
  29. #define CRUNCH_MVDX9 72
  30. #define CRUNCH_MVDX10 80
  31. #define CRUNCH_MVDX11 88
  32. #define CRUNCH_MVDX12 96
  33. #define CRUNCH_MVDX13 104
  34. #define CRUNCH_MVDX14 112
  35. #define CRUNCH_MVDX15 120
  36. #define CRUNCH_MVAX0L 128
  37. #define CRUNCH_MVAX0M 132
  38. #define CRUNCH_MVAX0H 136
  39. #define CRUNCH_MVAX1L 140
  40. #define CRUNCH_MVAX1M 144
  41. #define CRUNCH_MVAX1H 148
  42. #define CRUNCH_MVAX2L 152
  43. #define CRUNCH_MVAX2M 156
  44. #define CRUNCH_MVAX2H 160
  45. #define CRUNCH_MVAX3L 164
  46. #define CRUNCH_MVAX3M 168
  47. #define CRUNCH_MVAX3H 172
  48. #define CRUNCH_DSPSC 176
  49. #define CRUNCH_SIZE 184
  50. .text
  51. /*
  52. * Lazy switching of crunch coprocessor context
  53. *
  54. * r10 = struct thread_info pointer
  55. * r9 = ret_from_exception
  56. * lr = undefined instr exit
  57. *
  58. * called from prefetch exception handler with interrupts enabled
  59. */
  60. ENTRY(crunch_task_enable)
  61. inc_preempt_count r10, r3
  62. ldr r8, =(EP93XX_APB_VIRT_BASE + 0x00130000) @ syscon addr
  63. ldr r1, [r8, #0x80]
  64. tst r1, #0x00800000 @ access to crunch enabled?
  65. bne 2f @ if so no business here
  66. mov r3, #0xaa @ unlock syscon swlock
  67. str r3, [r8, #0xc0]
  68. orr r1, r1, #0x00800000 @ enable access to crunch
  69. str r1, [r8, #0x80]
  70. ldr r3, =crunch_owner
  71. add r0, r10, #TI_CRUNCH_STATE @ get task crunch save area
  72. ldr r2, [sp, #60] @ current task pc value
  73. ldr r1, [r3] @ get current crunch owner
  74. str r0, [r3] @ this task now owns crunch
  75. sub r2, r2, #4 @ adjust pc back
  76. str r2, [sp, #60]
  77. ldr r2, [r8, #0x80]
  78. mov r2, r2 @ flush out enable (@@@)
  79. teq r1, #0 @ test for last ownership
  80. mov lr, r9 @ normal exit from exception
  81. beq crunch_load @ no owner, skip save
  82. crunch_save:
  83. cfstr64 mvdx0, [r1, #CRUNCH_MVDX0] @ save 64b registers
  84. cfstr64 mvdx1, [r1, #CRUNCH_MVDX1]
  85. cfstr64 mvdx2, [r1, #CRUNCH_MVDX2]
  86. cfstr64 mvdx3, [r1, #CRUNCH_MVDX3]
  87. cfstr64 mvdx4, [r1, #CRUNCH_MVDX4]
  88. cfstr64 mvdx5, [r1, #CRUNCH_MVDX5]
  89. cfstr64 mvdx6, [r1, #CRUNCH_MVDX6]
  90. cfstr64 mvdx7, [r1, #CRUNCH_MVDX7]
  91. cfstr64 mvdx8, [r1, #CRUNCH_MVDX8]
  92. cfstr64 mvdx9, [r1, #CRUNCH_MVDX9]
  93. cfstr64 mvdx10, [r1, #CRUNCH_MVDX10]
  94. cfstr64 mvdx11, [r1, #CRUNCH_MVDX11]
  95. cfstr64 mvdx12, [r1, #CRUNCH_MVDX12]
  96. cfstr64 mvdx13, [r1, #CRUNCH_MVDX13]
  97. cfstr64 mvdx14, [r1, #CRUNCH_MVDX14]
  98. cfstr64 mvdx15, [r1, #CRUNCH_MVDX15]
  99. #ifdef __ARMEB__
  100. #error fix me for ARMEB
  101. #endif
  102. cfmv32al mvfx0, mvax0 @ save 72b accumulators
  103. cfstr32 mvfx0, [r1, #CRUNCH_MVAX0L]
  104. cfmv32am mvfx0, mvax0
  105. cfstr32 mvfx0, [r1, #CRUNCH_MVAX0M]
  106. cfmv32ah mvfx0, mvax0
  107. cfstr32 mvfx0, [r1, #CRUNCH_MVAX0H]
  108. cfmv32al mvfx0, mvax1
  109. cfstr32 mvfx0, [r1, #CRUNCH_MVAX1L]
  110. cfmv32am mvfx0, mvax1
  111. cfstr32 mvfx0, [r1, #CRUNCH_MVAX1M]
  112. cfmv32ah mvfx0, mvax1
  113. cfstr32 mvfx0, [r1, #CRUNCH_MVAX1H]
  114. cfmv32al mvfx0, mvax2
  115. cfstr32 mvfx0, [r1, #CRUNCH_MVAX2L]
  116. cfmv32am mvfx0, mvax2
  117. cfstr32 mvfx0, [r1, #CRUNCH_MVAX2M]
  118. cfmv32ah mvfx0, mvax2
  119. cfstr32 mvfx0, [r1, #CRUNCH_MVAX2H]
  120. cfmv32al mvfx0, mvax3
  121. cfstr32 mvfx0, [r1, #CRUNCH_MVAX3L]
  122. cfmv32am mvfx0, mvax3
  123. cfstr32 mvfx0, [r1, #CRUNCH_MVAX3M]
  124. cfmv32ah mvfx0, mvax3
  125. cfstr32 mvfx0, [r1, #CRUNCH_MVAX3H]
  126. cfmv32sc mvdx0, dspsc @ save status word
  127. cfstr64 mvdx0, [r1, #CRUNCH_DSPSC]
  128. teq r0, #0 @ anything to load?
  129. cfldr64eq mvdx0, [r1, #CRUNCH_MVDX0] @ mvdx0 was clobbered
  130. beq 1f
  131. crunch_load:
  132. cfldr64 mvdx0, [r0, #CRUNCH_DSPSC] @ load status word
  133. cfmvsc32 dspsc, mvdx0
  134. cfldr32 mvfx0, [r0, #CRUNCH_MVAX0L] @ load 72b accumulators
  135. cfmval32 mvax0, mvfx0
  136. cfldr32 mvfx0, [r0, #CRUNCH_MVAX0M]
  137. cfmvam32 mvax0, mvfx0
  138. cfldr32 mvfx0, [r0, #CRUNCH_MVAX0H]
  139. cfmvah32 mvax0, mvfx0
  140. cfldr32 mvfx0, [r0, #CRUNCH_MVAX1L]
  141. cfmval32 mvax1, mvfx0
  142. cfldr32 mvfx0, [r0, #CRUNCH_MVAX1M]
  143. cfmvam32 mvax1, mvfx0
  144. cfldr32 mvfx0, [r0, #CRUNCH_MVAX1H]
  145. cfmvah32 mvax1, mvfx0
  146. cfldr32 mvfx0, [r0, #CRUNCH_MVAX2L]
  147. cfmval32 mvax2, mvfx0
  148. cfldr32 mvfx0, [r0, #CRUNCH_MVAX2M]
  149. cfmvam32 mvax2, mvfx0
  150. cfldr32 mvfx0, [r0, #CRUNCH_MVAX2H]
  151. cfmvah32 mvax2, mvfx0
  152. cfldr32 mvfx0, [r0, #CRUNCH_MVAX3L]
  153. cfmval32 mvax3, mvfx0
  154. cfldr32 mvfx0, [r0, #CRUNCH_MVAX3M]
  155. cfmvam32 mvax3, mvfx0
  156. cfldr32 mvfx0, [r0, #CRUNCH_MVAX3H]
  157. cfmvah32 mvax3, mvfx0
  158. cfldr64 mvdx0, [r0, #CRUNCH_MVDX0] @ load 64b registers
  159. cfldr64 mvdx1, [r0, #CRUNCH_MVDX1]
  160. cfldr64 mvdx2, [r0, #CRUNCH_MVDX2]
  161. cfldr64 mvdx3, [r0, #CRUNCH_MVDX3]
  162. cfldr64 mvdx4, [r0, #CRUNCH_MVDX4]
  163. cfldr64 mvdx5, [r0, #CRUNCH_MVDX5]
  164. cfldr64 mvdx6, [r0, #CRUNCH_MVDX6]
  165. cfldr64 mvdx7, [r0, #CRUNCH_MVDX7]
  166. cfldr64 mvdx8, [r0, #CRUNCH_MVDX8]
  167. cfldr64 mvdx9, [r0, #CRUNCH_MVDX9]
  168. cfldr64 mvdx10, [r0, #CRUNCH_MVDX10]
  169. cfldr64 mvdx11, [r0, #CRUNCH_MVDX11]
  170. cfldr64 mvdx12, [r0, #CRUNCH_MVDX12]
  171. cfldr64 mvdx13, [r0, #CRUNCH_MVDX13]
  172. cfldr64 mvdx14, [r0, #CRUNCH_MVDX14]
  173. cfldr64 mvdx15, [r0, #CRUNCH_MVDX15]
  174. 1:
  175. #ifdef CONFIG_PREEMPT_COUNT
  176. get_thread_info r10
  177. #endif
  178. 2: dec_preempt_count r10, r3
  179. ret lr
  180. /*
  181. * Back up crunch regs to save area and disable access to them
  182. * (mainly for gdb or sleep mode usage)
  183. *
  184. * r0 = struct thread_info pointer of target task or NULL for any
  185. */
  186. ENTRY(crunch_task_disable)
  187. stmfd sp!, {r4, r5, lr}
  188. mrs ip, cpsr
  189. orr r2, ip, #PSR_I_BIT @ disable interrupts
  190. msr cpsr_c, r2
  191. ldr r4, =(EP93XX_APB_VIRT_BASE + 0x00130000) @ syscon addr
  192. ldr r3, =crunch_owner
  193. add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area
  194. ldr r1, [r3] @ get current crunch owner
  195. teq r1, #0 @ any current owner?
  196. beq 1f @ no: quit
  197. teq r0, #0 @ any owner?
  198. teqne r1, r2 @ or specified one?
  199. bne 1f @ no: quit
  200. ldr r5, [r4, #0x80] @ enable access to crunch
  201. mov r2, #0xaa
  202. str r2, [r4, #0xc0]
  203. orr r5, r5, #0x00800000
  204. str r5, [r4, #0x80]
  205. mov r0, #0 @ nothing to load
  206. str r0, [r3] @ no more current owner
  207. ldr r2, [r4, #0x80] @ flush out enable (@@@)
  208. mov r2, r2
  209. bl crunch_save
  210. mov r2, #0xaa @ disable access to crunch
  211. str r2, [r4, #0xc0]
  212. bic r5, r5, #0x00800000
  213. str r5, [r4, #0x80]
  214. ldr r5, [r4, #0x80] @ flush out enable (@@@)
  215. mov r5, r5
  216. 1: msr cpsr_c, ip @ restore interrupt mode
  217. ldmfd sp!, {r4, r5, pc}
  218. /*
  219. * Copy crunch state to given memory address
  220. *
  221. * r0 = struct thread_info pointer of target task
  222. * r1 = memory address where to store crunch state
  223. *
  224. * this is called mainly in the creation of signal stack frames
  225. */
  226. ENTRY(crunch_task_copy)
  227. mrs ip, cpsr
  228. orr r2, ip, #PSR_I_BIT @ disable interrupts
  229. msr cpsr_c, r2
  230. ldr r3, =crunch_owner
  231. add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area
  232. ldr r3, [r3] @ get current crunch owner
  233. teq r2, r3 @ does this task own it...
  234. beq 1f
  235. @ current crunch values are in the task save area
  236. msr cpsr_c, ip @ restore interrupt mode
  237. mov r0, r1
  238. mov r1, r2
  239. mov r2, #CRUNCH_SIZE
  240. b memcpy
  241. 1: @ this task owns crunch regs -- grab a copy from there
  242. mov r0, #0 @ nothing to load
  243. mov r3, lr @ preserve return address
  244. bl crunch_save
  245. msr cpsr_c, ip @ restore interrupt mode
  246. ret r3
  247. /*
  248. * Restore crunch state from given memory address
  249. *
  250. * r0 = struct thread_info pointer of target task
  251. * r1 = memory address where to get crunch state from
  252. *
  253. * this is used to restore crunch state when unwinding a signal stack frame
  254. */
  255. ENTRY(crunch_task_restore)
  256. mrs ip, cpsr
  257. orr r2, ip, #PSR_I_BIT @ disable interrupts
  258. msr cpsr_c, r2
  259. ldr r3, =crunch_owner
  260. add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area
  261. ldr r3, [r3] @ get current crunch owner
  262. teq r2, r3 @ does this task own it...
  263. beq 1f
  264. @ this task doesn't own crunch regs -- use its save area
  265. msr cpsr_c, ip @ restore interrupt mode
  266. mov r0, r2
  267. mov r2, #CRUNCH_SIZE
  268. b memcpy
  269. 1: @ this task owns crunch regs -- load them directly
  270. mov r0, r1
  271. mov r1, #0 @ nothing to save
  272. mov r3, lr @ preserve return address
  273. bl crunch_load
  274. msr cpsr_c, ip @ restore interrupt mode
  275. ret r3