1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
4 * Copyright (C) 2008-2009 PetaLogix
5 * Copyright (C) 2006 Atmark Techno, Inc.
8 #ifndef _ASM_MICROBLAZE_UACCESS_H
9 #define _ASM_MICROBLAZE_UACCESS_H
11 #include <linux/kernel.h>
15 #include <linux/pgtable.h>
16 #include <asm/extable.h>
17 #include <linux/string.h>
18 #include <asm-generic/access_ok.h>
20 # define __FIXUP_SECTION ".section .fixup,\"ax\"\n"
21 # define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"
23 extern unsigned long __copy_tofrom_user(void __user
*to
,
24 const void __user
*from
, unsigned long size
);
26 /* Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail. */
27 static inline unsigned long __must_check
__clear_user(void __user
*to
,
30 /* normal memset with two words to __ex_table */
31 __asm__
__volatile__ ( \
33 " addik %0, %0, -1;" \
46 static inline unsigned long __must_check
clear_user(void __user
*to
,
50 if (unlikely(!access_ok(to
, n
)))
53 return __clear_user(to
, n
);
56 /* put_user and get_user macros */
57 extern long __user_bad(void);
59 #define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \
61 __asm__ __volatile__ ( \
62 "1:" insn " %1, %2, r0;" \
67 " addik %0, r0, %3;" \
72 : "=&r"(__gu_err), "=r"(__gu_val) \
73 : "r"(__gu_ptr), "i"(-EFAULT) \
78 * get_user: - Get a simple variable from user space.
79 * @x: Variable to store result.
80 * @ptr: Source address, in user space.
82 * Context: User context only. This function may sleep if pagefaults are
85 * This macro copies a single simple variable from user space to kernel
86 * space. It supports simple types like char and int, but not larger
87 * data types like structures or arrays.
89 * @ptr must have pointer-to-simple-variable type, and the result of
90 * dereferencing @ptr must be assignable to @x without a cast.
92 * Returns zero on success, or -EFAULT on error.
93 * On error, the variable @x is set to zero.
95 #define get_user(x, ptr) ({ \
96 const typeof(*(ptr)) __user *__gu_ptr = (ptr); \
97 access_ok(__gu_ptr, sizeof(*__gu_ptr)) ? \
98 __get_user(x, __gu_ptr) : -EFAULT; \
101 #define __get_user(x, ptr) \
104 switch (sizeof(*(ptr))) { \
106 __get_user_asm("lbu", (ptr), x, __gu_err); \
109 __get_user_asm("lhu", (ptr), x, __gu_err); \
112 __get_user_asm("lw", (ptr), x, __gu_err); \
116 __gu_err = raw_copy_from_user(&__x, ptr, 8) ? \
118 (x) = (typeof(x))(typeof((x) - (x)))__x; \
122 /* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\
128 #define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \
130 __asm__ __volatile__ ( \
131 "1:" insn " %1, %2, r0;" \
132 " addk %0, r0, r0;" \
136 " addik %0, r0, %3;" \
142 : "r"(__gu_val), "r"(__gu_ptr), "i"(-EFAULT) \
146 #define __put_user_asm_8(__gu_ptr, __gu_val, __gu_err) \
148 __asm__ __volatile__ (" lwi %0, %1, 0;" \
149 "1: swi %0, %2, 0;" \
151 "2: swi %0, %2, 4;" \
152 " addk %0, r0, r0;" \
156 " addik %0, r0, %3;" \
159 ".word 1b,4b,2b,4b;" \
162 : "r"(&__gu_val), "r"(__gu_ptr), "i"(-EFAULT) \
167 * put_user: - Write a simple value into user space.
168 * @x: Value to copy to user space.
169 * @ptr: Destination address, in user space.
171 * Context: User context only. This function may sleep if pagefaults are
174 * This macro copies a single simple value from kernel space to user
175 * space. It supports simple types like char and int, but not larger
176 * data types like structures or arrays.
178 * @ptr must have pointer-to-simple-variable type, and @x must be assignable
179 * to the result of dereferencing @ptr.
181 * Returns zero on success, or -EFAULT on error.
183 #define put_user(x, ptr) \
184 __put_user_check((x), (ptr), sizeof(*(ptr)))
186 #define __put_user_check(x, ptr, size) \
188 typeof(*(ptr)) volatile __pu_val = x; \
189 typeof(*(ptr)) __user *__pu_addr = (ptr); \
192 if (access_ok(__pu_addr, size)) { \
195 __put_user_asm("sb", __pu_addr, __pu_val, \
199 __put_user_asm("sh", __pu_addr, __pu_val, \
203 __put_user_asm("sw", __pu_addr, __pu_val, \
207 __put_user_asm_8(__pu_addr, __pu_val, __pu_err);\
210 __pu_err = __user_bad(); \
214 __pu_err = -EFAULT; \
219 #define __put_user(x, ptr) \
221 __typeof__(*(ptr)) volatile __gu_val = (x); \
223 switch (sizeof(__gu_val)) { \
225 __put_user_asm("sb", (ptr), __gu_val, __gu_err); \
228 __put_user_asm("sh", (ptr), __gu_val, __gu_err); \
231 __put_user_asm("sw", (ptr), __gu_val, __gu_err); \
234 __put_user_asm_8((ptr), __gu_val, __gu_err); \
237 /*__gu_err = -EINVAL;*/ __gu_err = __user_bad(); \
242 static inline unsigned long
243 raw_copy_from_user(void *to
, const void __user
*from
, unsigned long n
)
245 return __copy_tofrom_user((__force
void __user
*)to
, from
, n
);
248 static inline unsigned long
249 raw_copy_to_user(void __user
*to
, const void *from
, unsigned long n
)
251 return __copy_tofrom_user(to
, (__force
const void __user
*)from
, n
);
253 #define INLINE_COPY_FROM_USER
254 #define INLINE_COPY_TO_USER
257 * Copy a null terminated string from userspace.
259 __must_check
long strncpy_from_user(char *dst
, const char __user
*src
,
263 * Return the size of a string (including the ending 0)
265 * Return 0 on exception, a value greater than N if too long
267 __must_check
long strnlen_user(const char __user
*sstr
, long len
);
269 #endif /* _ASM_MICROBLAZE_UACCESS_H */