blob: 79422b6559c33008dfb485ebf1638d5dfd71f973 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* 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
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 #include <asm/current.h>
Sam Ravnborge2d5df92005-09-09 21:28:48 +02008 #include <asm/asm-offsets.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 #include <asm/thread_info.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010
11/* Standard copy_to_user with segment limit checking */
12 .globl copy_to_user
13 .p2align 4
14copy_to_user:
15 GET_THREAD_INFO(%rax)
16 movq %rdi,%rcx
17 addq %rdx,%rcx
18 jc bad_to_user
19 cmpq threadinfo_addr_limit(%rax),%rcx
20 jae bad_to_user
Andi Kleen2cbc9ee2006-01-11 22:44:45 +010021 jmp copy_user_generic
Linus Torvalds1da177e2005-04-16 15:20:36 -070022
23/* Standard copy_from_user with segment limit checking */
24 .globl copy_from_user
25 .p2align 4
26copy_from_user:
27 GET_THREAD_INFO(%rax)
28 movq %rsi,%rcx
29 addq %rdx,%rcx
30 jc bad_from_user
31 cmpq threadinfo_addr_limit(%rax),%rcx
32 jae bad_from_user
33 /* FALL THROUGH to copy_user_generic */
34
35 .section .fixup,"ax"
36 /* must zero dest */
37bad_from_user:
38 movl %edx,%ecx
39 xorl %eax,%eax
40 rep
41 stosb
42bad_to_user:
43 movl %edx,%eax
44 ret
45 .previous
46
47
48/*
49 * copy_user_generic - memory copy with exception handling.
50 *
51 * Input:
52 * rdi destination
53 * rsi source
54 * rdx count
55 *
Andi Kleen2cbc9ee2006-01-11 22:44:45 +010056 * Only 4GB of copy is supported. This shouldn't be a problem
57 * because the kernel normally only writes from/to page sized chunks
58 * even if user space passed a longer buffer.
59 * And more would be dangerous because both Intel and AMD have
60 * errata with rep movsq > 4GB. If someone feels the need to fix
61 * this please consider this.
62 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 * Output:
64 * eax uncopied bytes or 0 if successful.
65 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
Andi Kleen2cbc9ee2006-01-11 22:44:45 +010067 .globl copy_user_generic
68copy_user_generic:
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 movl %edx,%ecx
70 shrl $3,%ecx
71 andl $7,%edx
Andi Kleen2cbc9ee2006-01-11 22:44:45 +010072 jz 5f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731: rep
74 movsq
75 movl %edx,%ecx
Andi Kleen2cbc9ee2006-01-11 22:44:45 +010076 xor %eax,%eax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772: rep
78 movsb
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 ret
Andi Kleen2cbc9ee2006-01-11 22:44:45 +010080 /* align here? */
815: xorl %eax,%eax
826: rep movsq
83 ret
84
85 .section .fixup,"ax"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863: lea (%rdx,%rcx,8),%rax
87 ret
Andi Kleen2cbc9ee2006-01-11 22:44:45 +0100884: movl %ecx,%eax
89 ret
90 .previous
91
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 .section __ex_table,"a"
93 .quad 1b,3b
94 .quad 2b,4b
Andi Kleen2cbc9ee2006-01-11 22:44:45 +010095 .quad 6b,4b
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 .previous