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