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