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