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