clear_user.S 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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(__clear_user)
  14. /*
  15. * Some CPUs support hardware unaligned access
  16. */
  17. ALTERNATIVE "b __clear_user_generic", \
  18. "b __clear_user_fast", CPU_FEATURE_UAL
  19. SYM_FUNC_END(__clear_user)
  20. EXPORT_SYMBOL(__clear_user)
  21. /*
  22. * unsigned long __clear_user_generic(void *addr, size_t size)
  23. *
  24. * a0: addr
  25. * a1: size
  26. */
  27. SYM_FUNC_START(__clear_user_generic)
  28. beqz a1, 2f
  29. 1: st.b zero, a0, 0
  30. addi.d a0, a0, 1
  31. addi.d a1, a1, -1
  32. bgtz a1, 1b
  33. 2: move a0, a1
  34. jr ra
  35. _asm_extable 1b, 2b
  36. SYM_FUNC_END(__clear_user_generic)
  37. /*
  38. * unsigned long __clear_user_fast(void *addr, unsigned long size)
  39. *
  40. * a0: addr
  41. * a1: size
  42. */
  43. SYM_FUNC_START(__clear_user_fast)
  44. sltui t0, a1, 9
  45. bnez t0, .Lsmall
  46. add.d a2, a0, a1
  47. 0: st.d zero, a0, 0
  48. /* align up address */
  49. addi.d a0, a0, 8
  50. bstrins.d a0, zero, 2, 0
  51. addi.d a3, a2, -64
  52. bgeu a0, a3, .Llt64
  53. /* set 64 bytes at a time */
  54. .Lloop64:
  55. 1: st.d zero, a0, 0
  56. 2: st.d zero, a0, 8
  57. 3: st.d zero, a0, 16
  58. 4: st.d zero, a0, 24
  59. 5: st.d zero, a0, 32
  60. 6: st.d zero, a0, 40
  61. 7: st.d zero, a0, 48
  62. 8: st.d zero, a0, 56
  63. addi.d a0, a0, 64
  64. bltu a0, a3, .Lloop64
  65. /* set the remaining bytes */
  66. .Llt64:
  67. addi.d a3, a2, -32
  68. bgeu a0, a3, .Llt32
  69. 9: st.d zero, a0, 0
  70. 10: st.d zero, a0, 8
  71. 11: st.d zero, a0, 16
  72. 12: st.d zero, a0, 24
  73. addi.d a0, a0, 32
  74. .Llt32:
  75. addi.d a3, a2, -16
  76. bgeu a0, a3, .Llt16
  77. 13: st.d zero, a0, 0
  78. 14: st.d zero, a0, 8
  79. addi.d a0, a0, 16
  80. .Llt16:
  81. addi.d a3, a2, -8
  82. bgeu a0, a3, .Llt8
  83. 15: st.d zero, a0, 0
  84. addi.d a0, a0, 8
  85. .Llt8:
  86. 16: st.d zero, a2, -8
  87. /* return */
  88. move a0, zero
  89. jr ra
  90. .align 4
  91. .Lsmall:
  92. pcaddi t0, 4
  93. slli.d a2, a1, 4
  94. add.d t0, t0, a2
  95. jr t0
  96. .align 4
  97. move a0, zero
  98. jr ra
  99. .align 4
  100. 17: st.b zero, a0, 0
  101. move a0, zero
  102. jr ra
  103. .align 4
  104. 18: st.h zero, a0, 0
  105. move a0, zero
  106. jr ra
  107. .align 4
  108. 19: st.h zero, a0, 0
  109. 20: st.b zero, a0, 2
  110. move a0, zero
  111. jr ra
  112. .align 4
  113. 21: st.w zero, a0, 0
  114. move a0, zero
  115. jr ra
  116. .align 4
  117. 22: st.w zero, a0, 0
  118. 23: st.b zero, a0, 4
  119. move a0, zero
  120. jr ra
  121. .align 4
  122. 24: st.w zero, a0, 0
  123. 25: st.h zero, a0, 4
  124. move a0, zero
  125. jr ra
  126. .align 4
  127. 26: st.w zero, a0, 0
  128. 27: st.w zero, a0, 3
  129. move a0, zero
  130. jr ra
  131. .align 4
  132. 28: st.d zero, a0, 0
  133. move a0, zero
  134. jr ra
  135. /* fixup and ex_table */
  136. .Llarge_fixup:
  137. sub.d a1, a2, a0
  138. .Lsmall_fixup:
  139. 29: st.b zero, a0, 0
  140. addi.d a0, a0, 1
  141. addi.d a1, a1, -1
  142. bgt a1, zero, 29b
  143. .Lexit:
  144. move a0, a1
  145. jr ra
  146. _asm_extable 0b, .Lsmall_fixup
  147. _asm_extable 1b, .Llarge_fixup
  148. _asm_extable 2b, .Llarge_fixup
  149. _asm_extable 3b, .Llarge_fixup
  150. _asm_extable 4b, .Llarge_fixup
  151. _asm_extable 5b, .Llarge_fixup
  152. _asm_extable 6b, .Llarge_fixup
  153. _asm_extable 7b, .Llarge_fixup
  154. _asm_extable 8b, .Llarge_fixup
  155. _asm_extable 9b, .Llarge_fixup
  156. _asm_extable 10b, .Llarge_fixup
  157. _asm_extable 11b, .Llarge_fixup
  158. _asm_extable 12b, .Llarge_fixup
  159. _asm_extable 13b, .Llarge_fixup
  160. _asm_extable 14b, .Llarge_fixup
  161. _asm_extable 15b, .Llarge_fixup
  162. _asm_extable 16b, .Llarge_fixup
  163. _asm_extable 17b, .Lexit
  164. _asm_extable 18b, .Lsmall_fixup
  165. _asm_extable 19b, .Lsmall_fixup
  166. _asm_extable 20b, .Lsmall_fixup
  167. _asm_extable 21b, .Lsmall_fixup
  168. _asm_extable 22b, .Lsmall_fixup
  169. _asm_extable 23b, .Lsmall_fixup
  170. _asm_extable 24b, .Lsmall_fixup
  171. _asm_extable 25b, .Lsmall_fixup
  172. _asm_extable 26b, .Lsmall_fixup
  173. _asm_extable 27b, .Lsmall_fixup
  174. _asm_extable 28b, .Lsmall_fixup
  175. _asm_extable 29b, .Lexit
  176. SYM_FUNC_END(__clear_user_fast)
  177. STACK_FRAME_NON_STANDARD __clear_user_fast