/* Copyright 2002 Andi Kleen, SuSE Labs. * Subject to the GNU Public License v2. * * Functions to copy from and to user space. */ #include #include #include /* Standard copy_to_user with segment limit checking */ .globl copy_to_user .p2align 4 copy_to_user: GET_THREAD_INFO(%rax) movq %rdi,%rcx addq %rdx,%rcx jc bad_to_user cmpq threadinfo_addr_limit(%rax),%rcx jae bad_to_user jmp copy_user_generic /* Standard copy_from_user with segment limit checking */ .globl copy_from_user .p2align 4 copy_from_user: GET_THREAD_INFO(%rax) movq %rsi,%rcx addq %rdx,%rcx jc bad_from_user cmpq threadinfo_addr_limit(%rax),%rcx jae bad_from_user /* FALL THROUGH to copy_user_generic */ .section .fixup,"ax" /* must zero dest */ bad_from_user: movl %edx,%ecx xorl %eax,%eax rep stosb bad_to_user: movl %edx,%eax ret .previous /* * copy_user_generic - memory copy with exception handling. * * Input: * rdi destination * rsi source * rdx count * * Only 4GB of copy is supported. This shouldn't be a problem * because the kernel normally only writes from/to page sized chunks * even if user space passed a longer buffer. * And more would be dangerous because both Intel and AMD have * errata with rep movsq > 4GB. If someone feels the need to fix * this please consider this. * * Output: * eax uncopied bytes or 0 if successful. */ .globl copy_user_generic copy_user_generic: movl %edx,%ecx shrl $3,%ecx andl $7,%edx jz 5f 1: rep movsq movl %edx,%ecx xor %eax,%eax 2: rep movsb ret /* align here? */ 5: xorl %eax,%eax 6: rep movsq ret .section .fixup,"ax" 3: lea (%rdx,%rcx,8),%rax ret 4: movl %ecx,%eax ret .previous .section __ex_table,"a" .quad 1b,3b .quad 2b,4b .quad 6b,4b .previous