f80bafee8669fbcb0420d6e5173ea1f79e863082
[linux-3.10.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/page.h>
31 #include <asm/errno.h>
32 #include <asm/offset.h>
33 #include <asm/thread_info.h>
34
35         .text
36         .p2align 4
37 .globl __get_user_1
38 __get_user_1:   
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
46         .p2align 4
47 .globl __get_user_2
48 __get_user_2:
49         GET_THREAD_INFO(%r8)
50         addq $1,%rcx
51         jc 20f
52         cmpq threadinfo_addr_limit(%r8),%rcx
53         jae 20f
54         decq   %rcx
55 2:      movzwl (%rcx),%edx
56         xorl %eax,%eax
57         ret
58 20:     decq    %rcx
59         jmp     bad_get_user
60
61         .p2align 4
62 .globl __get_user_4
63 __get_user_4:
64         GET_THREAD_INFO(%r8)
65         addq $3,%rcx
66         jc 30f
67         cmpq threadinfo_addr_limit(%r8),%rcx
68         jae 30f
69         subq $3,%rcx
70 3:      movl (%rcx),%edx
71         xorl %eax,%eax
72         ret
73 30:     subq $3,%rcx
74         jmp bad_get_user
75
76         .p2align 4
77 .globl __get_user_8
78 __get_user_8:
79         GET_THREAD_INFO(%r8)
80         addq $7,%rcx
81         jc 40f
82         cmpq threadinfo_addr_limit(%r8),%rcx
83         jae     40f
84         subq    $7,%rcx
85 4:      movq (%rcx),%rdx
86         xorl %eax,%eax
87         ret
88 40:     subq $7,%rcx
89         jmp bad_get_user
90
91 bad_get_user:
92         xorl %edx,%edx
93         movq $(-EFAULT),%rax
94         ret
95
96 .section __ex_table,"a"
97         .quad 1b,bad_get_user
98         .quad 2b,bad_get_user
99         .quad 3b,bad_get_user
100         .quad 4b,bad_get_user
101 .previous