copy_user.S
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:4k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* Copyright 2002 Andi Kleen, SuSE Labs.
  2.  * Subject to the GNU Public License v2.
  3.  * 
  4.  * Functions to copy from and to user space.
  5.  */  
  6. #define FIX_ALIGNMENT 1
  7. #define movnti movq  /* write to cache for now */
  8. #define prefetch prefetcht2
  9. #include <asm/current.h>
  10. #include <asm/offset.h>
  11. /* Standard copy_to_user with segment limit checking */
  12. .globl copy_to_user
  13. .p2align 
  14. copy_to_user:
  15. GET_CURRENT(%rax)
  16. movq %rdi,%rcx
  17. addq %rdx,%rcx
  18. jc  bad_to_user
  19. cmpq tsk_addr_limit(%rax),%rcx
  20. jae bad_to_user
  21. jmp copy_user_generic
  22. /* Standard copy_from_user with segment limit checking */
  23. .globl copy_from_user
  24. .p2align 
  25. copy_from_user:
  26. GET_CURRENT(%rax)
  27. movq %rsi,%rcx
  28. addq %rdx,%rcx
  29. jc  bad_from_user
  30. cmpq tsk_addr_limit(%rax),%rcx
  31. jae  bad_from_user
  32. /* FALL THROUGH to copy_user_generic */
  33. .section .fixup,"ax"
  34. /* must zero dest */
  35. bad_from_user:
  36. movl %edx,%ecx
  37. xorl %eax,%eax
  38. rep
  39. stosb
  40. bad_to_user:
  41. movl %edx,%eax
  42. ret
  43. .previous
  44. /*
  45.  * copy_user_generic - memory copy with exception handling.
  46.  * 
  47.  * Input:
  48.  * rdi destination
  49.  * rsi source
  50.  * rdx count
  51.  *
  52.  * Output:
  53.  * eax uncopied bytes or 0 if successfull. 
  54.  */
  55. .globl copy_user_generic
  56. copy_user_generic:
  57. /* Put the first cacheline into cache. This should handle
  58.    the small movements in ioctls etc., but not penalize the bigger
  59.    filesystem data copies too much. */
  60. pushq %rbx
  61. prefetch (%rsi)
  62. xorl %eax,%eax /*zero for the exception handler */
  63. #ifdef FIX_ALIGNMENT
  64. /* check for bad alignment of destination */
  65. movl %edi,%ecx
  66. andl $7,%ecx
  67. jnz  bad_alignment
  68. after_bad_alignment:
  69. #endif
  70. movq %rdx,%rcx
  71. movl $64,%ebx
  72. shrq $6,%rdx
  73. decq %rdx
  74. js   handle_tail
  75. jz   loop_no_prefetch
  76. loop:
  77. prefetch 64(%rsi)
  78. loop_no_prefetch:
  79. s1: movq (%rsi),%r11
  80. s2: movq 1*8(%rsi),%r8
  81. s3: movq 2*8(%rsi),%r9
  82. s4: movq 3*8(%rsi),%r10
  83. d1: movnti %r11,(%rdi)
  84. d2: movnti %r8,1*8(%rdi)
  85. d3: movnti %r9,2*8(%rdi)
  86. d4: movnti %r10,3*8(%rdi)
  87. s5: movq 4*8(%rsi),%r11
  88. s6: movq 5*8(%rsi),%r8
  89. s7: movq 6*8(%rsi),%r9
  90. s8: movq 7*8(%rsi),%r10
  91. d5: movnti %r11,4*8(%rdi)
  92. d6: movnti %r8,5*8(%rdi)
  93. d7: movnti %r9,6*8(%rdi)
  94. d8: movnti %r10,7*8(%rdi)
  95. addq %rbx,%rsi
  96. addq %rbx,%rdi
  97. decq %rdx
  98. jz   loop_no_prefetch
  99. jns  loop
  100. handle_tail:
  101. movl %ecx,%edx
  102. andl $63,%ecx
  103. shrl $3,%ecx
  104. jz   handle_7
  105. movl $8,%ebx
  106. loop_8:
  107. s9: movq (%rsi),%r8
  108. d9: movq %r8,(%rdi)
  109. addq %rbx,%rdi
  110. addq %rbx,%rsi
  111. decl %ecx
  112. jnz loop_8
  113. handle_7:
  114. movl %edx,%ecx
  115. andl $7,%ecx
  116. jz   ende
  117. loop_1:
  118. s10: movb (%rsi),%bl
  119. d10: movb %bl,(%rdi)
  120. incq %rdi
  121. incq %rsi
  122. decl %ecx
  123. jnz loop_1
  124. ende:
  125. sfence
  126. popq %rbx
  127. ret
  128. #ifdef FIX_ALIGNMENT   
  129. /* align destination */
  130. bad_alignment:
  131. movl $8,%r9d
  132. subl %ecx,%r9d
  133. movl %r9d,%ecx
  134. subq %r9,%rdx
  135. jz   small_align
  136. js   small_align
  137. align_1:
  138. s11: movb (%rsi),%bl
  139. d11: movb %bl,(%rdi)
  140. incq %rsi
  141. incq %rdi
  142. decl %ecx
  143. jnz align_1
  144. jmp after_bad_alignment
  145. small_align:
  146. addq %r9,%rdx
  147. jmp handle_7
  148. #endif
  149. /* table sorted by exception address */
  150. .section __ex_table,"a"
  151. .align 8
  152. .quad s1,s1e
  153. .quad s2,s2e
  154. .quad s3,s3e
  155. .quad s4,s4e
  156. .quad d1,s1e
  157. .quad d2,s2e
  158. .quad d3,s3e
  159. .quad d4,s4e
  160. .quad s5,s5e
  161. .quad s6,s6e
  162. .quad s7,s7e
  163. .quad s8,s8e
  164. .quad d5,s5e
  165. .quad d6,s6e
  166. .quad d7,s7e
  167. .quad d8,s8e
  168. .quad s9,e_quad
  169. .quad d9,e_quad
  170. .quad s10,e_byte
  171. .quad d10,e_byte
  172. #ifdef FIX_ALIGNMENT
  173. .quad s11,e_byte
  174. .quad d11,e_byte
  175. #endif
  176. .quad e5,e_zero
  177. .previous
  178. /* compute 64-offset for main loop. 8 bytes accuracy with error on the 
  179.    pessimistic side. this is gross. it would be better to fix the 
  180.    interface. */
  181. /* eax: zero, ebx: 64 */
  182. s1e:  addl $8,%eax
  183. s2e:  addl $8,%eax
  184. s3e:  addl $8,%eax
  185. s4e:  addl $8,%eax
  186. s5e:  addl $8,%eax
  187. s6e:  addl $8,%eax
  188. s7e:  addl $8,%eax
  189. s8e:  addl $8,%eax
  190. addq %rbx,%rdi /* +64 */
  191. subq %rax,%rdi  /* correct destination with computed offset */
  192. shlq $6,%rdx /* loop counter * 64 (stride length) */
  193. addq %rax,%rdx /* add offset to loopcnt */
  194. andl $63,%ecx /* remaining bytes */
  195. addq %rcx,%rdx /* add them */
  196. jmp zero_rest
  197. /* exception on quad word loop in tail handling */
  198. /* ecx: loopcnt/8, %edx: length, rdi: correct */
  199. e_quad:
  200. shll $3,%ecx
  201. andl $7,%edx
  202. addl %ecx,%edx
  203. /* edx: bytes to zero, rdi: dest, eax:zero */
  204. zero_rest:
  205. movq %rdx,%rcx
  206. e_byte:
  207. xorl %eax,%eax
  208. e5: rep 
  209. stosb
  210. /* when there is another exception while zeroing the rest just return */
  211. e_zero:
  212. movq %rdx,%rax
  213. jmp ende