Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee13...
[pandora-kernel.git] / arch / x86_64 / lib / getuser.S
1 /*
2  * __get_user functions.
3  *
4  * (C) Copyright 1998 Linus Torvalds
5  * (C) Copyright 2005 Andi Kleen
6  *
7  * These functions have a non-standard call interface
8  * to make them more efficient, especially as they
9  * return an error value in addition to the "real"
10  * return value.
11  */
12
13 /*
14  * __get_user_X
15  *
16  * Inputs:      %rcx contains the address.
17  *              The register is modified, but all changes are undone
18  *              before returning because the C code doesn't know about it.
19  *
20  * Outputs:     %rax is error code (0 or -EFAULT)
21  *              %rdx contains zero-extended value
22  * 
23  * %r8 is destroyed.
24  *
25  * These functions should not modify any other registers,
26  * as they get called from within inline assembly.
27  */
28
29 #include <linux/linkage.h>
30 #include <asm/dwarf2.h>
31 #include <asm/page.h>
32 #include <asm/errno.h>
33 #include <asm/asm-offsets.h>
34 #include <asm/thread_info.h>
35
36         .text
37 ENTRY(__get_user_1)
38         CFI_STARTPROC
39         GET_THREAD_INFO(%r8)
40         cmpq threadinfo_addr_limit(%r8),%rcx
41         jae bad_get_user
42 1:      movzb (%rcx),%edx
43         xorl %eax,%eax
44         ret
45         CFI_ENDPROC
46 ENDPROC(__get_user_1)
47
48 ENTRY(__get_user_2)
49         CFI_STARTPROC
50         GET_THREAD_INFO(%r8)
51         addq $1,%rcx
52         jc 20f
53         cmpq threadinfo_addr_limit(%r8),%rcx
54         jae 20f
55         decq   %rcx
56 2:      movzwl (%rcx),%edx
57         xorl %eax,%eax
58         ret
59 20:     decq    %rcx
60         jmp     bad_get_user
61         CFI_ENDPROC
62 ENDPROC(__get_user_2)
63
64 ENTRY(__get_user_4)
65         CFI_STARTPROC
66         GET_THREAD_INFO(%r8)
67         addq $3,%rcx
68         jc 30f
69         cmpq threadinfo_addr_limit(%r8),%rcx
70         jae 30f
71         subq $3,%rcx
72 3:      movl (%rcx),%edx
73         xorl %eax,%eax
74         ret
75 30:     subq $3,%rcx
76         jmp bad_get_user
77         CFI_ENDPROC
78 ENDPROC(__get_user_4)
79
80 ENTRY(__get_user_8)
81         CFI_STARTPROC
82         GET_THREAD_INFO(%r8)
83         addq $7,%rcx
84         jc 40f
85         cmpq threadinfo_addr_limit(%r8),%rcx
86         jae     40f
87         subq    $7,%rcx
88 4:      movq (%rcx),%rdx
89         xorl %eax,%eax
90         ret
91 40:     subq $7,%rcx
92         jmp bad_get_user
93         CFI_ENDPROC
94 ENDPROC(__get_user_8)
95
96 bad_get_user:
97         CFI_STARTPROC
98         xorl %edx,%edx
99         movq $(-EFAULT),%rax
100         ret
101         CFI_ENDPROC
102 END(bad_get_user)
103
104 .section __ex_table,"a"
105         .quad 1b,bad_get_user
106         .quad 2b,bad_get_user
107         .quad 3b,bad_get_user
108         .quad 4b,bad_get_user
109 .previous