copy_user.S 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
  4. */
  5. #include <linux/export.h>
  6. #include <asm/alternative-asm.h>
  7. #include <asm/asm.h>
  8. #include <asm/asmmacro.h>
  9. #include <asm/asm-extable.h>
  10. #include <asm/cpu.h>
  11. #include <asm/regdef.h>
  12. #include <asm/unwind_hints.h>
  13. SYM_FUNC_START(__copy_user)
  14. #ifdef CONFIG_32BIT
  15. b __copy_user_generic
  16. #else
  17. /*
  18. * Some CPUs support hardware unaligned access
  19. */
  20. ALTERNATIVE "b __copy_user_generic", \
  21. "b __copy_user_fast", CPU_FEATURE_UAL
  22. #endif
  23. SYM_FUNC_END(__copy_user)
  24. EXPORT_SYMBOL(__copy_user)
  25. /*
  26. * unsigned long __copy_user_generic(void *to, const void *from, size_t n)
  27. *
  28. * a0: to
  29. * a1: from
  30. * a2: n
  31. */
  32. SYM_FUNC_START(__copy_user_generic)
  33. beqz a2, 3f
  34. 1: ld.b t0, a1, 0
  35. 2: st.b t0, a0, 0
  36. PTR_ADDI a0, a0, 1
  37. PTR_ADDI a1, a1, 1
  38. PTR_ADDI a2, a2, -1
  39. bgtz a2, 1b
  40. 3: move a0, a2
  41. jr ra
  42. _asm_extable 1b, 3b
  43. _asm_extable 2b, 3b
  44. SYM_FUNC_END(__copy_user_generic)
  45. #ifdef CONFIG_64BIT
  46. /*
  47. * unsigned long __copy_user_fast(void *to, const void *from, unsigned long n)
  48. *
  49. * a0: to
  50. * a1: from
  51. * a2: n
  52. */
  53. SYM_FUNC_START(__copy_user_fast)
  54. sltui t0, a2, 9
  55. bnez t0, .Lsmall
  56. 0: ld.d t0, a1, 0
  57. 1: st.d t0, a0, 0
  58. add.d a3, a1, a2
  59. add.d a2, a0, a2
  60. /* align up destination address */
  61. andi t1, a0, 7
  62. sub.d t0, zero, t1
  63. addi.d t0, t0, 8
  64. add.d a1, a1, t0
  65. add.d a0, a0, t0
  66. addi.d a4, a3, -64
  67. bgeu a1, a4, .Llt64
  68. /* copy 64 bytes at a time */
  69. .Lloop64:
  70. 2: ld.d t0, a1, 0
  71. 3: ld.d t1, a1, 8
  72. 4: ld.d t2, a1, 16
  73. 5: ld.d t3, a1, 24
  74. 6: ld.d t4, a1, 32
  75. 7: ld.d t5, a1, 40
  76. 8: ld.d t6, a1, 48
  77. 9: ld.d t7, a1, 56
  78. 10: st.d t0, a0, 0
  79. 11: st.d t1, a0, 8
  80. 12: st.d t2, a0, 16
  81. 13: st.d t3, a0, 24
  82. 14: st.d t4, a0, 32
  83. 15: st.d t5, a0, 40
  84. 16: st.d t6, a0, 48
  85. 17: st.d t7, a0, 56
  86. addi.d a1, a1, 64
  87. addi.d a0, a0, 64
  88. bltu a1, a4, .Lloop64
  89. /* copy the remaining bytes */
  90. .Llt64:
  91. addi.d a4, a3, -32
  92. bgeu a1, a4, .Llt32
  93. 18: ld.d t0, a1, 0
  94. 19: ld.d t1, a1, 8
  95. 20: ld.d t2, a1, 16
  96. 21: ld.d t3, a1, 24
  97. 22: st.d t0, a0, 0
  98. 23: st.d t1, a0, 8
  99. 24: st.d t2, a0, 16
  100. 25: st.d t3, a0, 24
  101. addi.d a1, a1, 32
  102. addi.d a0, a0, 32
  103. .Llt32:
  104. addi.d a4, a3, -16
  105. bgeu a1, a4, .Llt16
  106. 26: ld.d t0, a1, 0
  107. 27: ld.d t1, a1, 8
  108. 28: st.d t0, a0, 0
  109. 29: st.d t1, a0, 8
  110. addi.d a1, a1, 16
  111. addi.d a0, a0, 16
  112. .Llt16:
  113. addi.d a4, a3, -8
  114. bgeu a1, a4, .Llt8
  115. 30: ld.d t0, a1, 0
  116. 31: st.d t0, a0, 0
  117. addi.d a1, a1, 8
  118. addi.d a0, a0, 8
  119. .Llt8:
  120. 32: ld.d t0, a3, -8
  121. 33: st.d t0, a2, -8
  122. /* return */
  123. move a0, zero
  124. jr ra
  125. .align 5
  126. .Lsmall:
  127. pcaddi t0, 8
  128. slli.d a3, a2, 5
  129. add.d t0, t0, a3
  130. jr t0
  131. .align 5
  132. move a0, zero
  133. jr ra
  134. .align 5
  135. 34: ld.b t0, a1, 0
  136. 35: st.b t0, a0, 0
  137. move a0, zero
  138. jr ra
  139. .align 5
  140. 36: ld.h t0, a1, 0
  141. 37: st.h t0, a0, 0
  142. move a0, zero
  143. jr ra
  144. .align 5
  145. 38: ld.h t0, a1, 0
  146. 39: ld.b t1, a1, 2
  147. 40: st.h t0, a0, 0
  148. 41: st.b t1, a0, 2
  149. move a0, zero
  150. jr ra
  151. .align 5
  152. 42: ld.w t0, a1, 0
  153. 43: st.w t0, a0, 0
  154. move a0, zero
  155. jr ra
  156. .align 5
  157. 44: ld.w t0, a1, 0
  158. 45: ld.b t1, a1, 4
  159. 46: st.w t0, a0, 0
  160. 47: st.b t1, a0, 4
  161. move a0, zero
  162. jr ra
  163. .align 5
  164. 48: ld.w t0, a1, 0
  165. 49: ld.h t1, a1, 4
  166. 50: st.w t0, a0, 0
  167. 51: st.h t1, a0, 4
  168. move a0, zero
  169. jr ra
  170. .align 5
  171. 52: ld.w t0, a1, 0
  172. 53: ld.w t1, a1, 3
  173. 54: st.w t0, a0, 0
  174. 55: st.w t1, a0, 3
  175. move a0, zero
  176. jr ra
  177. .align 5
  178. 56: ld.d t0, a1, 0
  179. 57: st.d t0, a0, 0
  180. move a0, zero
  181. jr ra
  182. /* fixup and ex_table */
  183. .Llarge_fixup:
  184. sub.d a2, a2, a0
  185. .Lsmall_fixup:
  186. 58: ld.b t0, a1, 0
  187. 59: st.b t0, a0, 0
  188. addi.d a0, a0, 1
  189. addi.d a1, a1, 1
  190. addi.d a2, a2, -1
  191. bgt a2, zero, 58b
  192. .Lexit:
  193. move a0, a2
  194. jr ra
  195. _asm_extable 0b, .Lsmall_fixup
  196. _asm_extable 1b, .Lsmall_fixup
  197. _asm_extable 2b, .Llarge_fixup
  198. _asm_extable 3b, .Llarge_fixup
  199. _asm_extable 4b, .Llarge_fixup
  200. _asm_extable 5b, .Llarge_fixup
  201. _asm_extable 6b, .Llarge_fixup
  202. _asm_extable 7b, .Llarge_fixup
  203. _asm_extable 8b, .Llarge_fixup
  204. _asm_extable 9b, .Llarge_fixup
  205. _asm_extable 10b, .Llarge_fixup
  206. _asm_extable 11b, .Llarge_fixup
  207. _asm_extable 12b, .Llarge_fixup
  208. _asm_extable 13b, .Llarge_fixup
  209. _asm_extable 14b, .Llarge_fixup
  210. _asm_extable 15b, .Llarge_fixup
  211. _asm_extable 16b, .Llarge_fixup
  212. _asm_extable 17b, .Llarge_fixup
  213. _asm_extable 18b, .Llarge_fixup
  214. _asm_extable 19b, .Llarge_fixup
  215. _asm_extable 20b, .Llarge_fixup
  216. _asm_extable 21b, .Llarge_fixup
  217. _asm_extable 22b, .Llarge_fixup
  218. _asm_extable 23b, .Llarge_fixup
  219. _asm_extable 24b, .Llarge_fixup
  220. _asm_extable 25b, .Llarge_fixup
  221. _asm_extable 26b, .Llarge_fixup
  222. _asm_extable 27b, .Llarge_fixup
  223. _asm_extable 28b, .Llarge_fixup
  224. _asm_extable 29b, .Llarge_fixup
  225. _asm_extable 30b, .Llarge_fixup
  226. _asm_extable 31b, .Llarge_fixup
  227. _asm_extable 32b, .Llarge_fixup
  228. _asm_extable 33b, .Llarge_fixup
  229. _asm_extable 34b, .Lexit
  230. _asm_extable 35b, .Lexit
  231. _asm_extable 36b, .Lsmall_fixup
  232. _asm_extable 37b, .Lsmall_fixup
  233. _asm_extable 38b, .Lsmall_fixup
  234. _asm_extable 39b, .Lsmall_fixup
  235. _asm_extable 40b, .Lsmall_fixup
  236. _asm_extable 41b, .Lsmall_fixup
  237. _asm_extable 42b, .Lsmall_fixup
  238. _asm_extable 43b, .Lsmall_fixup
  239. _asm_extable 44b, .Lsmall_fixup
  240. _asm_extable 45b, .Lsmall_fixup
  241. _asm_extable 46b, .Lsmall_fixup
  242. _asm_extable 47b, .Lsmall_fixup
  243. _asm_extable 48b, .Lsmall_fixup
  244. _asm_extable 49b, .Lsmall_fixup
  245. _asm_extable 50b, .Lsmall_fixup
  246. _asm_extable 51b, .Lsmall_fixup
  247. _asm_extable 52b, .Lsmall_fixup
  248. _asm_extable 53b, .Lsmall_fixup
  249. _asm_extable 54b, .Lsmall_fixup
  250. _asm_extable 55b, .Lsmall_fixup
  251. _asm_extable 56b, .Lsmall_fixup
  252. _asm_extable 57b, .Lsmall_fixup
  253. _asm_extable 58b, .Lexit
  254. _asm_extable 59b, .Lexit
  255. SYM_FUNC_END(__copy_user_fast)
  256. STACK_FRAME_NON_STANDARD __copy_user_fast
  257. #endif