copy_user_64.S 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * Copyright 2008 Vitaly Mayatskikh <vmayatsk@redhat.com>
  3. * Copyright 2002 Andi Kleen, SuSE Labs.
  4. * Subject to the GNU Public License v2.
  5. *
  6. * Functions to copy from and to user space.
  7. */
  8. #include <linux/linkage.h>
  9. #include <asm/dwarf2.h>
  10. #define FIX_ALIGNMENT 1
  11. #include <asm/current.h>
  12. #include <asm/asm-offsets.h>
  13. #include <asm/thread_info.h>
  14. #include <asm/cpufeature.h>
  15. .macro ALTERNATIVE_JUMP feature,orig,alt
  16. 0:
  17. .byte 0xe9 /* 32bit jump */
  18. .long \orig-1f /* by default jump to orig */
  19. 1:
  20. .section .altinstr_replacement,"ax"
  21. 2: .byte 0xe9 /* near jump with 32bit immediate */
  22. .long \alt-1b /* offset */ /* or alternatively to alt */
  23. .previous
  24. .section .altinstructions,"a"
  25. .align 8
  26. .quad 0b
  27. .quad 2b
  28. .byte \feature /* when feature is set */
  29. .byte 5
  30. .byte 5
  31. .previous
  32. .endm
  33. .macro ALIGN_DESTINATION
  34. #ifdef FIX_ALIGNMENT
  35. /* check for bad alignment of destination */
  36. movl %edi,%ecx
  37. andl $7,%ecx
  38. jz 102f /* already aligned */
  39. subl $8,%ecx
  40. negl %ecx
  41. subl %ecx,%edx
  42. 100: movb (%rsi),%al
  43. 101: movb %al,(%rdi)
  44. incq %rsi
  45. incq %rdi
  46. decl %ecx
  47. jnz 100b
  48. 102:
  49. .section .fixup,"ax"
  50. 103: addl %ecx,%edx /* ecx is zerorest also */
  51. jmp copy_user_handle_tail
  52. .previous
  53. .section __ex_table,"a"
  54. .align 8
  55. .quad 100b,103b
  56. .quad 101b,103b
  57. .previous
  58. #endif
  59. .endm
  60. /* Standard copy_to_user with segment limit checking */
  61. ENTRY(copy_to_user)
  62. CFI_STARTPROC
  63. GET_THREAD_INFO(%rax)
  64. movq %rdi,%rcx
  65. addq %rdx,%rcx
  66. jc bad_to_user
  67. cmpq TI_addr_limit(%rax),%rcx
  68. jae bad_to_user
  69. ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
  70. CFI_ENDPROC
  71. ENDPROC(copy_to_user)
  72. /* Standard copy_from_user with segment limit checking */
  73. ENTRY(copy_from_user)
  74. CFI_STARTPROC
  75. GET_THREAD_INFO(%rax)
  76. movq %rsi,%rcx
  77. addq %rdx,%rcx
  78. jc bad_from_user
  79. cmpq TI_addr_limit(%rax),%rcx
  80. jae bad_from_user
  81. ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
  82. CFI_ENDPROC
  83. ENDPROC(copy_from_user)
  84. ENTRY(copy_user_generic)
  85. CFI_STARTPROC
  86. ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
  87. CFI_ENDPROC
  88. ENDPROC(copy_user_generic)
  89. ENTRY(__copy_from_user_inatomic)
  90. CFI_STARTPROC
  91. ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
  92. CFI_ENDPROC
  93. ENDPROC(__copy_from_user_inatomic)
  94. .section .fixup,"ax"
  95. /* must zero dest */
  96. ENTRY(bad_from_user)
  97. bad_from_user:
  98. CFI_STARTPROC
  99. movl %edx,%ecx
  100. xorl %eax,%eax
  101. rep
  102. stosb
  103. bad_to_user:
  104. movl %edx,%eax
  105. ret
  106. CFI_ENDPROC
  107. ENDPROC(bad_from_user)
  108. .previous
  109. /*
  110. * copy_user_generic_unrolled - memory copy with exception handling.
  111. * This version is for CPUs like P4 that don't have efficient micro
  112. * code for rep movsq
  113. *
  114. * Input:
  115. * rdi destination
  116. * rsi source
  117. * rdx count
  118. *
  119. * Output:
  120. * eax uncopied bytes or 0 if successfull.
  121. */
  122. ENTRY(copy_user_generic_unrolled)
  123. CFI_STARTPROC
  124. cmpl $8,%edx
  125. jb 20f /* less then 8 bytes, go to byte copy loop */
  126. ALIGN_DESTINATION
  127. movl %edx,%ecx
  128. andl $63,%edx
  129. shrl $6,%ecx
  130. jz 17f
  131. 1: movq (%rsi),%r8
  132. 2: movq 1*8(%rsi),%r9
  133. 3: movq 2*8(%rsi),%r10
  134. 4: movq 3*8(%rsi),%r11
  135. 5: movq %r8,(%rdi)
  136. 6: movq %r9,1*8(%rdi)
  137. 7: movq %r10,2*8(%rdi)
  138. 8: movq %r11,3*8(%rdi)
  139. 9: movq 4*8(%rsi),%r8
  140. 10: movq 5*8(%rsi),%r9
  141. 11: movq 6*8(%rsi),%r10
  142. 12: movq 7*8(%rsi),%r11
  143. 13: movq %r8,4*8(%rdi)
  144. 14: movq %r9,5*8(%rdi)
  145. 15: movq %r10,6*8(%rdi)
  146. 16: movq %r11,7*8(%rdi)
  147. leaq 64(%rsi),%rsi
  148. leaq 64(%rdi),%rdi
  149. decl %ecx
  150. jnz 1b
  151. 17: movl %edx,%ecx
  152. andl $7,%edx
  153. shrl $3,%ecx
  154. jz 20f
  155. 18: movq (%rsi),%r8
  156. 19: movq %r8,(%rdi)
  157. leaq 8(%rsi),%rsi
  158. leaq 8(%rdi),%rdi
  159. decl %ecx
  160. jnz 18b
  161. 20: andl %edx,%edx
  162. jz 23f
  163. movl %edx,%ecx
  164. 21: movb (%rsi),%al
  165. 22: movb %al,(%rdi)
  166. incq %rsi
  167. incq %rdi
  168. decl %ecx
  169. jnz 21b
  170. 23: xor %eax,%eax
  171. ret
  172. .section .fixup,"ax"
  173. 30: shll $6,%ecx
  174. addl %ecx,%edx
  175. jmp 60f
  176. 40: lea (%rdx,%rcx,8),%rdx
  177. jmp 60f
  178. 50: movl %ecx,%edx
  179. 60: jmp copy_user_handle_tail /* ecx is zerorest also */
  180. .previous
  181. .section __ex_table,"a"
  182. .align 8
  183. .quad 1b,30b
  184. .quad 2b,30b
  185. .quad 3b,30b
  186. .quad 4b,30b
  187. .quad 5b,30b
  188. .quad 6b,30b
  189. .quad 7b,30b
  190. .quad 8b,30b
  191. .quad 9b,30b
  192. .quad 10b,30b
  193. .quad 11b,30b
  194. .quad 12b,30b
  195. .quad 13b,30b
  196. .quad 14b,30b
  197. .quad 15b,30b
  198. .quad 16b,30b
  199. .quad 18b,40b
  200. .quad 19b,40b
  201. .quad 21b,50b
  202. .quad 22b,50b
  203. .previous
  204. CFI_ENDPROC
  205. ENDPROC(copy_user_generic_unrolled)
  206. /* Some CPUs run faster using the string copy instructions.
  207. * This is also a lot simpler. Use them when possible.
  208. *
  209. * Only 4GB of copy is supported. This shouldn't be a problem
  210. * because the kernel normally only writes from/to page sized chunks
  211. * even if user space passed a longer buffer.
  212. * And more would be dangerous because both Intel and AMD have
  213. * errata with rep movsq > 4GB. If someone feels the need to fix
  214. * this please consider this.
  215. *
  216. * Input:
  217. * rdi destination
  218. * rsi source
  219. * rdx count
  220. *
  221. * Output:
  222. * eax uncopied bytes or 0 if successful.
  223. */
  224. ENTRY(copy_user_generic_string)
  225. CFI_STARTPROC
  226. andl %edx,%edx
  227. jz 4f
  228. cmpl $8,%edx
  229. jb 2f /* less than 8 bytes, go to byte copy loop */
  230. ALIGN_DESTINATION
  231. movl %edx,%ecx
  232. shrl $3,%ecx
  233. andl $7,%edx
  234. 1: rep
  235. movsq
  236. 2: movl %edx,%ecx
  237. 3: rep
  238. movsb
  239. 4: xorl %eax,%eax
  240. ret
  241. .section .fixup,"ax"
  242. 11: lea (%rdx,%rcx,8),%rcx
  243. 12: movl %ecx,%edx /* ecx is zerorest also */
  244. jmp copy_user_handle_tail
  245. .previous
  246. .section __ex_table,"a"
  247. .align 8
  248. .quad 1b,11b
  249. .quad 3b,12b
  250. .previous
  251. CFI_ENDPROC
  252. ENDPROC(copy_user_generic_string)