]> Git Repo - linux.git/blob - arch/loongarch/include/asm/uaccess.h
crypto: testmgr - allow ecdsa-nist-p256 and -p384 in FIPS mode
[linux.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_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 */
This page took 0.049433 seconds and 4 git commands to generate.