Commit | Line | Data |
---|---|---|
1da177e4 LT |
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> | |
8d379dad | 30 | #include <asm/dwarf2.h> |
1da177e4 LT |
31 | #include <asm/page.h> |
32 | #include <asm/errno.h> | |
e2d5df93 | 33 | #include <asm/asm-offsets.h> |
1da177e4 LT |
34 | #include <asm/thread_info.h> |
35 | ||
36 | .text | |
8d379dad JB |
37 | ENTRY(__get_user_1) |
38 | CFI_STARTPROC | |
1da177e4 LT |
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 | |
8d379dad JB |
45 | CFI_ENDPROC |
46 | ENDPROC(__get_user_1) | |
1da177e4 | 47 | |
8d379dad JB |
48 | ENTRY(__get_user_2) |
49 | CFI_STARTPROC | |
1da177e4 LT |
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 | |
8d379dad JB |
61 | CFI_ENDPROC |
62 | ENDPROC(__get_user_2) | |
1da177e4 | 63 | |
8d379dad JB |
64 | ENTRY(__get_user_4) |
65 | CFI_STARTPROC | |
1da177e4 LT |
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 | |
8d379dad JB |
77 | CFI_ENDPROC |
78 | ENDPROC(__get_user_4) | |
1da177e4 | 79 | |
8d379dad JB |
80 | ENTRY(__get_user_8) |
81 | CFI_STARTPROC | |
1da177e4 LT |
82 | GET_THREAD_INFO(%r8) |
83 | addq $7,%rcx | |
3a6fd752 | 84 | jc 40f |
1da177e4 | 85 | cmpq threadinfo_addr_limit(%r8),%rcx |
3a6fd752 | 86 | jae 40f |
1da177e4 LT |
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 | |
8d379dad JB |
93 | CFI_ENDPROC |
94 | ENDPROC(__get_user_8) | |
1da177e4 LT |
95 | |
96 | bad_get_user: | |
8d379dad | 97 | CFI_STARTPROC |
1da177e4 LT |
98 | xorl %edx,%edx |
99 | movq $(-EFAULT),%rax | |
100 | ret | |
8d379dad JB |
101 | CFI_ENDPROC |
102 | END(bad_get_user) | |
1da177e4 LT |
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 |