File Index
Files and directories
Sign in
FILE

uaccess.h

File preview with syntax highlighting.

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