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