xref: /linux/arch/loongarch/include/asm/uaccess.h (revision 9551a26f17d9445eed497bd7c639d48dfc3c0af4)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4  *
5  * Derived from MIPS:
6  * Copyright (C) 1996, 1997, 1998, 1999, 2000, 03, 04 by Ralf Baechle
7  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8  * Copyright (C) 2007  Maciej W. Rozycki
9  * Copyright (C) 2014, Imagination Technologies Ltd.
10  */
11 #ifndef _ASM_UACCESS_H
12 #define _ASM_UACCESS_H
13 
14 #include <linux/kernel.h>
15 #include <linux/string.h>
16 #include <linux/extable.h>
17 #include <asm/pgtable.h>
18 #include <asm/extable.h>
19 #include <asm/asm-extable.h>
20 #include <asm-generic/access_ok.h>
21 
22 #define __LSW	0
23 #define __MSW	1
24 
25 extern u64 __ua_limit;
26 
27 #ifdef CONFIG_64BIT
28 #define __UA_LIMIT	__ua_limit
29 #else
30 #define __UA_LIMIT	0x80000000UL
31 #endif
32 
33 /*
34  * get_user: - Get a simple variable from user space.
35  * @x:	 Variable to store result.
36  * @ptr: Source address, in user space.
37  *
38  * Context: User context only. This function may sleep if pagefaults are
39  *          enabled.
40  *
41  * This macro copies a single simple variable from user space to kernel
42  * space.  It supports simple types like char and int, but not larger
43  * data types like structures or arrays.
44  *
45  * @ptr must have pointer-to-simple-variable type, and the result of
46  * dereferencing @ptr must be assignable to @x without a cast.
47  *
48  * Returns zero on success, or -EFAULT on error.
49  * On error, the variable @x is set to zero.
50  */
51 #define get_user(x, ptr) \
52 ({									\
53 	const __typeof__(*(ptr)) __user *__p = (ptr);			\
54 									\
55 	might_fault();							\
56 	access_ok(__p, sizeof(*__p)) ? __get_user((x), __p) :		\
57 				       ((x) = 0, -EFAULT);		\
58 })
59 
60 /*
61  * put_user: - Write a simple value into user space.
62  * @x:	 Value to copy to user space.
63  * @ptr: Destination address, in user space.
64  *
65  * Context: User context only. This function may sleep if pagefaults are
66  *          enabled.
67  *
68  * This macro copies a single simple value from kernel space to user
69  * space.  It supports simple types like char and int, but not larger
70  * data types like structures or arrays.
71  *
72  * @ptr must have pointer-to-simple-variable type, and @x must be assignable
73  * to the result of dereferencing @ptr.
74  *
75  * Returns zero on success, or -EFAULT on error.
76  */
77 #define put_user(x, ptr) \
78 ({									\
79 	__typeof__(*(ptr)) __user *__p = (ptr);				\
80 									\
81 	might_fault();							\
82 	access_ok(__p, sizeof(*__p)) ? __put_user((x), __p) : -EFAULT;	\
83 })
84 
85 /*
86  * __get_user: - Get a simple variable from user space, with less checking.
87  * @x:	 Variable to store result.
88  * @ptr: Source address, in user space.
89  *
90  * Context: User context only. This function may sleep if pagefaults are
91  *          enabled.
92  *
93  * This macro copies a single simple variable from user space to kernel
94  * space.  It supports simple types like char and int, but not larger
95  * data types like structures or arrays.
96  *
97  * @ptr must have pointer-to-simple-variable type, and the result of
98  * dereferencing @ptr must be assignable to @x without a cast.
99  *
100  * Caller must check the pointer with access_ok() before calling this
101  * function.
102  *
103  * Returns zero on success, or -EFAULT on error.
104  * On error, the variable @x is set to zero.
105  */
106 #define __get_user(x, ptr) \
107 ({									\
108 	int __gu_err = 0;						\
109 									\
110 	__chk_user_ptr(ptr);						\
111 	__get_user_common((x), sizeof(*(ptr)), ptr);			\
112 	__gu_err;							\
113 })
114 
115 /*
116  * __put_user: - Write a simple value into user space, with less checking.
117  * @x:	 Value to copy to user space.
118  * @ptr: Destination address, in user space.
119  *
120  * Context: User context only. This function may sleep if pagefaults are
121  *          enabled.
122  *
123  * This macro copies a single simple value from kernel space to user
124  * space.  It supports simple types like char and int, but not larger
125  * data types like structures or arrays.
126  *
127  * @ptr must have pointer-to-simple-variable type, and @x must be assignable
128  * to the result of dereferencing @ptr.
129  *
130  * Caller must check the pointer with access_ok() before calling this
131  * function.
132  *
133  * Returns zero on success, or -EFAULT on error.
134  */
135 
136 #define __put_user(x, ptr) \
137 ({									\
138 	int __pu_err = 0;						\
139 	__typeof__(*(ptr)) __pu_val;					\
140 									\
141 	__pu_val = (x);							\
142 	__chk_user_ptr(ptr);						\
143 	__put_user_common(ptr, sizeof(*(ptr)));				\
144 	__pu_err;							\
145 })
146 
147 struct __large_struct { unsigned long buf[100]; };
148 #define __m(x) (*(struct __large_struct __user *)(x))
149 
150 #define __get_user_common(val, size, ptr)				\
151 do {									\
152 	switch (size) {							\
153 	case 1: __get_data_asm(val, "ld.b", ptr); break;		\
154 	case 2: __get_data_asm(val, "ld.h", ptr); break;		\
155 	case 4: __get_data_asm(val, "ld.w", ptr); break;		\
156 	case 8: __get_data_asm_8(val, ptr); break;			\
157 	default: BUILD_BUG(); break;					\
158 	}								\
159 } while (0)
160 
161 #define __get_kernel_common(val, size, ptr) __get_user_common(val, size, ptr)
162 
163 #define __get_data_asm(val, insn, ptr)					\
164 {									\
165 	long __gu_tmp;							\
166 									\
167 	__asm__ __volatile__(						\
168 	"1:	" insn "	%1, %2				\n"	\
169 	"2:							\n"	\
170 	_ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 2b, %0, %1)			\
171 	: "+r" (__gu_err), "=r" (__gu_tmp)				\
172 	: "m" (__m(ptr)));						\
173 									\
174 	(val) = (__typeof__(*(ptr))) __gu_tmp;				\
175 }
176 
177 #ifdef CONFIG_64BIT
178 #define __get_data_asm_8(val, ptr) \
179 	__get_data_asm(val, "ld.d", ptr)
180 #else /* !CONFIG_64BIT */
181 #define __get_data_asm_8(val, ptr)					\
182 {									\
183 	u32 __lo, __hi;							\
184 	u32 __user *__ptr = (u32 __user *)(ptr);			\
185 									\
186 	__asm__ __volatile__ (						\
187 		"1:\n"							\
188 		"	ld.w %1, %3				\n"	\
189 		"2:\n"							\
190 		"	ld.w %2, %4				\n"	\
191 		"3:\n"							\
192 		_ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 3b, %0, %1)		\
193 		_ASM_EXTABLE_UACCESS_ERR_ZERO(2b, 3b, %0, %1)		\
194 		: "+r" (__gu_err), "=&r" (__lo), "=r" (__hi)		\
195 		: "m" (__ptr[__LSW]), "m" (__ptr[__MSW]));		\
196 	if (__gu_err)							\
197 		__hi = 0;						\
198 	(val) = (__typeof__(val))((__typeof__((val)-(val)))		\
199 		((((u64)__hi << 32) | __lo)));				\
200 }
201 #endif /* CONFIG_64BIT */
202 
203 #define __put_user_common(ptr, size)					\
204 do {									\
205 	switch (size) {							\
206 	case 1: __put_data_asm("st.b", ptr); break;			\
207 	case 2: __put_data_asm("st.h", ptr); break;			\
208 	case 4: __put_data_asm("st.w", ptr); break;			\
209 	case 8: __put_data_asm_8(ptr); break;				\
210 	default: BUILD_BUG(); break;					\
211 	}								\
212 } while (0)
213 
214 #define __put_kernel_common(ptr, size) __put_user_common(ptr, size)
215 
216 #define __put_data_asm(insn, ptr)					\
217 {									\
218 	__asm__ __volatile__(						\
219 	"1:	" insn "	%z2, %1		# __put_user_asm\n"	\
220 	"2:							\n"	\
221 	_ASM_EXTABLE_UACCESS_ERR(1b, 2b, %0)				\
222 	: "+r" (__pu_err), "=m" (__m(ptr))				\
223 	: "Jr" (__pu_val));						\
224 }
225 
226 #ifdef CONFIG_64BIT
227 #define __put_data_asm_8(ptr) \
228 	__put_data_asm("st.d", ptr)
229 #else /* !CONFIG_64BIT */
230 #define __put_data_asm_8(ptr)						\
231 {									\
232 	u32 __user *__ptr = (u32 __user *)(ptr);			\
233 	u64 __x = (__typeof__((__pu_val)-(__pu_val)))(__pu_val);	\
234 									\
235 	__asm__ __volatile__ (						\
236 		"1:\n"							\
237 		"	st.w %z3, %1				\n"	\
238 		"2:\n"							\
239 		"	st.w %z4, %2				\n"	\
240 		"3:\n"							\
241 		_ASM_EXTABLE_UACCESS_ERR(1b, 3b, %0)			\
242 		_ASM_EXTABLE_UACCESS_ERR(2b, 3b, %0)			\
243 		: "+r" (__pu_err),					\
244 			"=m" (__ptr[__LSW]),				\
245 			"=m" (__ptr[__MSW])				\
246 		: "rJ" (__x), "rJ" (__x >> 32));			\
247 }
248 #endif /* CONFIG_64BIT */
249 
250 #define __get_kernel_nofault(dst, src, type, err_label)			\
251 do {									\
252 	int __gu_err = 0;						\
253 									\
254 	__get_kernel_common(*((type *)(dst)), sizeof(type),		\
255 			    (__force type *)(src));			\
256 	if (unlikely(__gu_err))						\
257 		goto err_label;						\
258 } while (0)
259 
260 #define __put_kernel_nofault(dst, src, type, err_label)			\
261 do {									\
262 	type __pu_val;							\
263 	int __pu_err = 0;						\
264 									\
265 	__pu_val = *(__force type *)(src);				\
266 	__put_kernel_common(((type *)(dst)), sizeof(type));		\
267 	if (unlikely(__pu_err))						\
268 		goto err_label;						\
269 } while (0)
270 
271 extern unsigned long __copy_user(void *to, const void *from, __kernel_size_t n);
272 
273 static inline unsigned long __must_check
raw_copy_from_user(void * to,const void __user * from,unsigned long n)274 raw_copy_from_user(void *to, const void __user *from, unsigned long n)
275 {
276 	return __copy_user(to, (__force const void *)from, n);
277 }
278 
279 static inline unsigned long __must_check
raw_copy_to_user(void __user * to,const void * from,unsigned long n)280 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
281 {
282 	return __copy_user((__force void *)to, from, n);
283 }
284 
285 #define INLINE_COPY_FROM_USER
286 #define INLINE_COPY_TO_USER
287 
288 /*
289  * __clear_user: - Zero a block of memory in user space, with less checking.
290  * @addr: Destination address, in user space.
291  * @size: Number of bytes to zero.
292  *
293  * Zero a block of memory in user space.  Caller must check
294  * the specified block with access_ok() before calling this function.
295  *
296  * Returns number of bytes that could not be cleared.
297  * On success, this will be zero.
298  */
299 extern unsigned long __clear_user(void __user *addr, __kernel_size_t size);
300 
301 #define clear_user(addr, n)						\
302 ({									\
303 	void __user *__cl_addr = (addr);				\
304 	unsigned long __cl_size = (n);					\
305 	if (__cl_size && access_ok(__cl_addr, __cl_size))		\
306 		__cl_size = __clear_user(__cl_addr, __cl_size);		\
307 	__cl_size;							\
308 })
309 
310 extern long strncpy_from_user(char *to, const char __user *from, long n);
311 extern long strnlen_user(const char __user *str, long n);
312 
313 #endif /* _ASM_UACCESS_H */
314