Merge tag 'edac_for_4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp
[sfrench/cifs-2.6.git] / arch / x86 / lib / getuser.S
1 /*
2  * __get_user functions.
3  *
4  * (C) Copyright 1998 Linus Torvalds
5  * (C) Copyright 2005 Andi Kleen
6  * (C) Copyright 2008 Glauber Costa
7  *
8  * These functions have a non-standard call interface
9  * to make them more efficient, especially as they
10  * return an error value in addition to the "real"
11  * return value.
12  */
13
14 /*
15  * __get_user_X
16  *
17  * Inputs:      %[r|e]ax contains the address.
18  *
19  * Outputs:     %[r|e]ax is error code (0 or -EFAULT)
20  *              %[r|e]dx contains zero-extended value
21  *              %ecx contains the high half for 32-bit __get_user_8
22  *
23  *
24  * These functions should not modify any other registers,
25  * as they get called from within inline assembly.
26  */
27
28 #include <linux/linkage.h>
29 #include <asm/page_types.h>
30 #include <asm/errno.h>
31 #include <asm/asm-offsets.h>
32 #include <asm/thread_info.h>
33 #include <asm/asm.h>
34 #include <asm/smap.h>
35
36         .text
37 ENTRY(__get_user_1)
38         mov PER_CPU_VAR(current_task), %_ASM_DX
39         cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
40         jae bad_get_user
41         ASM_STAC
42 1:      movzbl (%_ASM_AX),%edx
43         xor %eax,%eax
44         ASM_CLAC
45         ret
46 ENDPROC(__get_user_1)
47
48 ENTRY(__get_user_2)
49         add $1,%_ASM_AX
50         jc bad_get_user
51         mov PER_CPU_VAR(current_task), %_ASM_DX
52         cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
53         jae bad_get_user
54         ASM_STAC
55 2:      movzwl -1(%_ASM_AX),%edx
56         xor %eax,%eax
57         ASM_CLAC
58         ret
59 ENDPROC(__get_user_2)
60
61 ENTRY(__get_user_4)
62         add $3,%_ASM_AX
63         jc bad_get_user
64         mov PER_CPU_VAR(current_task), %_ASM_DX
65         cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
66         jae bad_get_user
67         ASM_STAC
68 3:      movl -3(%_ASM_AX),%edx
69         xor %eax,%eax
70         ASM_CLAC
71         ret
72 ENDPROC(__get_user_4)
73
74 ENTRY(__get_user_8)
75 #ifdef CONFIG_X86_64
76         add $7,%_ASM_AX
77         jc bad_get_user
78         mov PER_CPU_VAR(current_task), %_ASM_DX
79         cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
80         jae bad_get_user
81         ASM_STAC
82 4:      movq -7(%_ASM_AX),%rdx
83         xor %eax,%eax
84         ASM_CLAC
85         ret
86 #else
87         add $7,%_ASM_AX
88         jc bad_get_user_8
89         mov PER_CPU_VAR(current_task), %_ASM_DX
90         cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
91         jae bad_get_user_8
92         ASM_STAC
93 4:      movl -7(%_ASM_AX),%edx
94 5:      movl -3(%_ASM_AX),%ecx
95         xor %eax,%eax
96         ASM_CLAC
97         ret
98 #endif
99 ENDPROC(__get_user_8)
100
101
102 bad_get_user:
103         xor %edx,%edx
104         mov $(-EFAULT),%_ASM_AX
105         ASM_CLAC
106         ret
107 END(bad_get_user)
108
109 #ifdef CONFIG_X86_32
110 bad_get_user_8:
111         xor %edx,%edx
112         xor %ecx,%ecx
113         mov $(-EFAULT),%_ASM_AX
114         ASM_CLAC
115         ret
116 END(bad_get_user_8)
117 #endif
118
119         _ASM_EXTABLE(1b,bad_get_user)
120         _ASM_EXTABLE(2b,bad_get_user)
121         _ASM_EXTABLE(3b,bad_get_user)
122 #ifdef CONFIG_X86_64
123         _ASM_EXTABLE(4b,bad_get_user)
124 #else
125         _ASM_EXTABLE(4b,bad_get_user_8)
126         _ASM_EXTABLE(5b,bad_get_user_8)
127 #endif