arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / arch / loongarch / include / asm / uaccess.h
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 */