18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
48c2ecf20Sopenharmony_ci * Copyright (C) 2008-2009 PetaLogix
58c2ecf20Sopenharmony_ci * Copyright (C) 2006 Atmark Techno, Inc.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#ifndef _ASM_MICROBLAZE_UACCESS_H
98c2ecf20Sopenharmony_ci#define _ASM_MICROBLAZE_UACCESS_H
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/kernel.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <asm/mmu.h>
148c2ecf20Sopenharmony_ci#include <asm/page.h>
158c2ecf20Sopenharmony_ci#include <linux/pgtable.h>
168c2ecf20Sopenharmony_ci#include <asm/extable.h>
178c2ecf20Sopenharmony_ci#include <linux/string.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/*
208c2ecf20Sopenharmony_ci * On Microblaze the fs value is actually the top of the corresponding
218c2ecf20Sopenharmony_ci * address space.
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * The fs value determines whether argument validity checking should be
248c2ecf20Sopenharmony_ci * performed or not. If get_fs() == USER_DS, checking is performed, with
258c2ecf20Sopenharmony_ci * get_fs() == KERNEL_DS, checking is bypassed.
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci * For historical reasons, these macros are grossly misnamed.
288c2ecf20Sopenharmony_ci *
298c2ecf20Sopenharmony_ci * For non-MMU arch like Microblaze, KERNEL_DS and USER_DS is equal.
308c2ecf20Sopenharmony_ci */
318c2ecf20Sopenharmony_ci# define MAKE_MM_SEG(s)       ((mm_segment_t) { (s) })
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#  ifndef CONFIG_MMU
348c2ecf20Sopenharmony_ci#  define KERNEL_DS	MAKE_MM_SEG(0)
358c2ecf20Sopenharmony_ci#  define USER_DS	KERNEL_DS
368c2ecf20Sopenharmony_ci#  else
378c2ecf20Sopenharmony_ci#  define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
388c2ecf20Sopenharmony_ci#  define USER_DS	MAKE_MM_SEG(TASK_SIZE - 1)
398c2ecf20Sopenharmony_ci#  endif
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci# define get_fs()	(current_thread_info()->addr_limit)
428c2ecf20Sopenharmony_ci# define set_fs(val)	(current_thread_info()->addr_limit = (val))
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci# define uaccess_kernel()	(get_fs().seg == KERNEL_DS.seg)
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#ifndef CONFIG_MMU
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/* Check against bounds of physical memory */
498c2ecf20Sopenharmony_cistatic inline int ___range_ok(unsigned long addr, unsigned long size)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	return ((addr < memory_start) ||
528c2ecf20Sopenharmony_ci		((addr + size - 1) > (memory_start + memory_size - 1)));
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define __range_ok(addr, size) \
568c2ecf20Sopenharmony_ci		___range_ok((unsigned long)(addr), (unsigned long)(size))
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci#define access_ok(addr, size) (__range_ok((addr), (size)) == 0)
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci#else
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic inline int access_ok(const void __user *addr, unsigned long size)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	if (!size)
658c2ecf20Sopenharmony_ci		goto ok;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	if ((get_fs().seg < ((unsigned long)addr)) ||
688c2ecf20Sopenharmony_ci			(get_fs().seg < ((unsigned long)addr + size - 1))) {
698c2ecf20Sopenharmony_ci		pr_devel("ACCESS fail at 0x%08x (size 0x%x), seg 0x%08x\n",
708c2ecf20Sopenharmony_ci			(__force u32)addr, (u32)size,
718c2ecf20Sopenharmony_ci			(u32)get_fs().seg);
728c2ecf20Sopenharmony_ci		return 0;
738c2ecf20Sopenharmony_ci	}
748c2ecf20Sopenharmony_ciok:
758c2ecf20Sopenharmony_ci	pr_devel("ACCESS OK at 0x%08x (size 0x%x), seg 0x%08x\n",
768c2ecf20Sopenharmony_ci			(__force u32)addr, (u32)size,
778c2ecf20Sopenharmony_ci			(u32)get_fs().seg);
788c2ecf20Sopenharmony_ci	return 1;
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci#endif
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci#ifdef CONFIG_MMU
838c2ecf20Sopenharmony_ci# define __FIXUP_SECTION	".section .fixup,\"ax\"\n"
848c2ecf20Sopenharmony_ci# define __EX_TABLE_SECTION	".section __ex_table,\"a\"\n"
858c2ecf20Sopenharmony_ci#else
868c2ecf20Sopenharmony_ci# define __FIXUP_SECTION	".section .discard,\"ax\"\n"
878c2ecf20Sopenharmony_ci# define __EX_TABLE_SECTION	".section .discard,\"ax\"\n"
888c2ecf20Sopenharmony_ci#endif
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ciextern unsigned long __copy_tofrom_user(void __user *to,
918c2ecf20Sopenharmony_ci		const void __user *from, unsigned long size);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci/* Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail. */
948c2ecf20Sopenharmony_cistatic inline unsigned long __must_check __clear_user(void __user *to,
958c2ecf20Sopenharmony_ci							unsigned long n)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	/* normal memset with two words to __ex_table */
988c2ecf20Sopenharmony_ci	__asm__ __volatile__ (				\
998c2ecf20Sopenharmony_ci			"1:	sb	r0, %1, r0;"	\
1008c2ecf20Sopenharmony_ci			"	addik	%0, %0, -1;"	\
1018c2ecf20Sopenharmony_ci			"	bneid	%0, 1b;"	\
1028c2ecf20Sopenharmony_ci			"	addik	%1, %1, 1;"	\
1038c2ecf20Sopenharmony_ci			"2:			"	\
1048c2ecf20Sopenharmony_ci			__EX_TABLE_SECTION		\
1058c2ecf20Sopenharmony_ci			".word	1b,2b;"			\
1068c2ecf20Sopenharmony_ci			".previous;"			\
1078c2ecf20Sopenharmony_ci		: "=r"(n), "=r"(to)			\
1088c2ecf20Sopenharmony_ci		: "0"(n), "1"(to)
1098c2ecf20Sopenharmony_ci	);
1108c2ecf20Sopenharmony_ci	return n;
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistatic inline unsigned long __must_check clear_user(void __user *to,
1148c2ecf20Sopenharmony_ci							unsigned long n)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	might_fault();
1178c2ecf20Sopenharmony_ci	if (unlikely(!access_ok(to, n)))
1188c2ecf20Sopenharmony_ci		return n;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	return __clear_user(to, n);
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci/* put_user and get_user macros */
1248c2ecf20Sopenharmony_ciextern long __user_bad(void);
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci#define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err)	\
1278c2ecf20Sopenharmony_ci({								\
1288c2ecf20Sopenharmony_ci	__asm__ __volatile__ (					\
1298c2ecf20Sopenharmony_ci			"1:"	insn	" %1, %2, r0;"		\
1308c2ecf20Sopenharmony_ci			"	addk	%0, r0, r0;"		\
1318c2ecf20Sopenharmony_ci			"2:			"		\
1328c2ecf20Sopenharmony_ci			__FIXUP_SECTION				\
1338c2ecf20Sopenharmony_ci			"3:	brid	2b;"			\
1348c2ecf20Sopenharmony_ci			"	addik	%0, r0, %3;"		\
1358c2ecf20Sopenharmony_ci			".previous;"				\
1368c2ecf20Sopenharmony_ci			__EX_TABLE_SECTION			\
1378c2ecf20Sopenharmony_ci			".word	1b,3b;"				\
1388c2ecf20Sopenharmony_ci			".previous;"				\
1398c2ecf20Sopenharmony_ci		: "=&r"(__gu_err), "=r"(__gu_val)		\
1408c2ecf20Sopenharmony_ci		: "r"(__gu_ptr), "i"(-EFAULT)			\
1418c2ecf20Sopenharmony_ci	);							\
1428c2ecf20Sopenharmony_ci})
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci/**
1458c2ecf20Sopenharmony_ci * get_user: - Get a simple variable from user space.
1468c2ecf20Sopenharmony_ci * @x:   Variable to store result.
1478c2ecf20Sopenharmony_ci * @ptr: Source address, in user space.
1488c2ecf20Sopenharmony_ci *
1498c2ecf20Sopenharmony_ci * Context: User context only. This function may sleep if pagefaults are
1508c2ecf20Sopenharmony_ci *          enabled.
1518c2ecf20Sopenharmony_ci *
1528c2ecf20Sopenharmony_ci * This macro copies a single simple variable from user space to kernel
1538c2ecf20Sopenharmony_ci * space.  It supports simple types like char and int, but not larger
1548c2ecf20Sopenharmony_ci * data types like structures or arrays.
1558c2ecf20Sopenharmony_ci *
1568c2ecf20Sopenharmony_ci * @ptr must have pointer-to-simple-variable type, and the result of
1578c2ecf20Sopenharmony_ci * dereferencing @ptr must be assignable to @x without a cast.
1588c2ecf20Sopenharmony_ci *
1598c2ecf20Sopenharmony_ci * Returns zero on success, or -EFAULT on error.
1608c2ecf20Sopenharmony_ci * On error, the variable @x is set to zero.
1618c2ecf20Sopenharmony_ci */
1628c2ecf20Sopenharmony_ci#define get_user(x, ptr) ({				\
1638c2ecf20Sopenharmony_ci	const typeof(*(ptr)) __user *__gu_ptr = (ptr);	\
1648c2ecf20Sopenharmony_ci	access_ok(__gu_ptr, sizeof(*__gu_ptr)) ?	\
1658c2ecf20Sopenharmony_ci		__get_user(x, __gu_ptr) : -EFAULT;	\
1668c2ecf20Sopenharmony_ci})
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci#define __get_user(x, ptr)						\
1698c2ecf20Sopenharmony_ci({									\
1708c2ecf20Sopenharmony_ci	long __gu_err;							\
1718c2ecf20Sopenharmony_ci	switch (sizeof(*(ptr))) {					\
1728c2ecf20Sopenharmony_ci	case 1:								\
1738c2ecf20Sopenharmony_ci		__get_user_asm("lbu", (ptr), x, __gu_err);		\
1748c2ecf20Sopenharmony_ci		break;							\
1758c2ecf20Sopenharmony_ci	case 2:								\
1768c2ecf20Sopenharmony_ci		__get_user_asm("lhu", (ptr), x, __gu_err);		\
1778c2ecf20Sopenharmony_ci		break;							\
1788c2ecf20Sopenharmony_ci	case 4:								\
1798c2ecf20Sopenharmony_ci		__get_user_asm("lw", (ptr), x, __gu_err);		\
1808c2ecf20Sopenharmony_ci		break;							\
1818c2ecf20Sopenharmony_ci	case 8: {							\
1828c2ecf20Sopenharmony_ci		__u64 __x = 0;						\
1838c2ecf20Sopenharmony_ci		__gu_err = raw_copy_from_user(&__x, ptr, 8) ?		\
1848c2ecf20Sopenharmony_ci							-EFAULT : 0;	\
1858c2ecf20Sopenharmony_ci		(x) = (typeof(x))(typeof((x) - (x)))__x;		\
1868c2ecf20Sopenharmony_ci		break;							\
1878c2ecf20Sopenharmony_ci	}								\
1888c2ecf20Sopenharmony_ci	default:							\
1898c2ecf20Sopenharmony_ci		/* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\
1908c2ecf20Sopenharmony_ci	}								\
1918c2ecf20Sopenharmony_ci	__gu_err;							\
1928c2ecf20Sopenharmony_ci})
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci#define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err)	\
1968c2ecf20Sopenharmony_ci({								\
1978c2ecf20Sopenharmony_ci	__asm__ __volatile__ (					\
1988c2ecf20Sopenharmony_ci			"1:"	insn	" %1, %2, r0;"		\
1998c2ecf20Sopenharmony_ci			"	addk	%0, r0, r0;"		\
2008c2ecf20Sopenharmony_ci			"2:			"		\
2018c2ecf20Sopenharmony_ci			__FIXUP_SECTION				\
2028c2ecf20Sopenharmony_ci			"3:	brid	2b;"			\
2038c2ecf20Sopenharmony_ci			"	addik	%0, r0, %3;"		\
2048c2ecf20Sopenharmony_ci			".previous;"				\
2058c2ecf20Sopenharmony_ci			__EX_TABLE_SECTION			\
2068c2ecf20Sopenharmony_ci			".word	1b,3b;"				\
2078c2ecf20Sopenharmony_ci			".previous;"				\
2088c2ecf20Sopenharmony_ci		: "=&r"(__gu_err)				\
2098c2ecf20Sopenharmony_ci		: "r"(__gu_val), "r"(__gu_ptr), "i"(-EFAULT)	\
2108c2ecf20Sopenharmony_ci	);							\
2118c2ecf20Sopenharmony_ci})
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci#define __put_user_asm_8(__gu_ptr, __gu_val, __gu_err)		\
2148c2ecf20Sopenharmony_ci({								\
2158c2ecf20Sopenharmony_ci	__asm__ __volatile__ ("	lwi	%0, %1, 0;"		\
2168c2ecf20Sopenharmony_ci			"1:	swi	%0, %2, 0;"		\
2178c2ecf20Sopenharmony_ci			"	lwi	%0, %1, 4;"		\
2188c2ecf20Sopenharmony_ci			"2:	swi	%0, %2, 4;"		\
2198c2ecf20Sopenharmony_ci			"	addk	%0, r0, r0;"		\
2208c2ecf20Sopenharmony_ci			"3:			"		\
2218c2ecf20Sopenharmony_ci			__FIXUP_SECTION				\
2228c2ecf20Sopenharmony_ci			"4:	brid	3b;"			\
2238c2ecf20Sopenharmony_ci			"	addik	%0, r0, %3;"		\
2248c2ecf20Sopenharmony_ci			".previous;"				\
2258c2ecf20Sopenharmony_ci			__EX_TABLE_SECTION			\
2268c2ecf20Sopenharmony_ci			".word	1b,4b,2b,4b;"			\
2278c2ecf20Sopenharmony_ci			".previous;"				\
2288c2ecf20Sopenharmony_ci		: "=&r"(__gu_err)				\
2298c2ecf20Sopenharmony_ci		: "r"(&__gu_val), "r"(__gu_ptr), "i"(-EFAULT)	\
2308c2ecf20Sopenharmony_ci		);						\
2318c2ecf20Sopenharmony_ci})
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci/**
2348c2ecf20Sopenharmony_ci * put_user: - Write a simple value into user space.
2358c2ecf20Sopenharmony_ci * @x:   Value to copy to user space.
2368c2ecf20Sopenharmony_ci * @ptr: Destination address, in user space.
2378c2ecf20Sopenharmony_ci *
2388c2ecf20Sopenharmony_ci * Context: User context only. This function may sleep if pagefaults are
2398c2ecf20Sopenharmony_ci *          enabled.
2408c2ecf20Sopenharmony_ci *
2418c2ecf20Sopenharmony_ci * This macro copies a single simple value from kernel space to user
2428c2ecf20Sopenharmony_ci * space.  It supports simple types like char and int, but not larger
2438c2ecf20Sopenharmony_ci * data types like structures or arrays.
2448c2ecf20Sopenharmony_ci *
2458c2ecf20Sopenharmony_ci * @ptr must have pointer-to-simple-variable type, and @x must be assignable
2468c2ecf20Sopenharmony_ci * to the result of dereferencing @ptr.
2478c2ecf20Sopenharmony_ci *
2488c2ecf20Sopenharmony_ci * Returns zero on success, or -EFAULT on error.
2498c2ecf20Sopenharmony_ci */
2508c2ecf20Sopenharmony_ci#define put_user(x, ptr)						\
2518c2ecf20Sopenharmony_ci	__put_user_check((x), (ptr), sizeof(*(ptr)))
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci#define __put_user_check(x, ptr, size)					\
2548c2ecf20Sopenharmony_ci({									\
2558c2ecf20Sopenharmony_ci	typeof(*(ptr)) volatile __pu_val = x;				\
2568c2ecf20Sopenharmony_ci	typeof(*(ptr)) __user *__pu_addr = (ptr);			\
2578c2ecf20Sopenharmony_ci	int __pu_err = 0;						\
2588c2ecf20Sopenharmony_ci									\
2598c2ecf20Sopenharmony_ci	if (access_ok(__pu_addr, size)) {			\
2608c2ecf20Sopenharmony_ci		switch (size) {						\
2618c2ecf20Sopenharmony_ci		case 1:							\
2628c2ecf20Sopenharmony_ci			__put_user_asm("sb", __pu_addr, __pu_val,	\
2638c2ecf20Sopenharmony_ci				       __pu_err);			\
2648c2ecf20Sopenharmony_ci			break;						\
2658c2ecf20Sopenharmony_ci		case 2:							\
2668c2ecf20Sopenharmony_ci			__put_user_asm("sh", __pu_addr, __pu_val,	\
2678c2ecf20Sopenharmony_ci				       __pu_err);			\
2688c2ecf20Sopenharmony_ci			break;						\
2698c2ecf20Sopenharmony_ci		case 4:							\
2708c2ecf20Sopenharmony_ci			__put_user_asm("sw", __pu_addr, __pu_val,	\
2718c2ecf20Sopenharmony_ci				       __pu_err);			\
2728c2ecf20Sopenharmony_ci			break;						\
2738c2ecf20Sopenharmony_ci		case 8:							\
2748c2ecf20Sopenharmony_ci			__put_user_asm_8(__pu_addr, __pu_val, __pu_err);\
2758c2ecf20Sopenharmony_ci			break;						\
2768c2ecf20Sopenharmony_ci		default:						\
2778c2ecf20Sopenharmony_ci			__pu_err = __user_bad();			\
2788c2ecf20Sopenharmony_ci			break;						\
2798c2ecf20Sopenharmony_ci		}							\
2808c2ecf20Sopenharmony_ci	} else {							\
2818c2ecf20Sopenharmony_ci		__pu_err = -EFAULT;					\
2828c2ecf20Sopenharmony_ci	}								\
2838c2ecf20Sopenharmony_ci	__pu_err;							\
2848c2ecf20Sopenharmony_ci})
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci#define __put_user(x, ptr)						\
2878c2ecf20Sopenharmony_ci({									\
2888c2ecf20Sopenharmony_ci	__typeof__(*(ptr)) volatile __gu_val = (x);			\
2898c2ecf20Sopenharmony_ci	long __gu_err = 0;						\
2908c2ecf20Sopenharmony_ci	switch (sizeof(__gu_val)) {					\
2918c2ecf20Sopenharmony_ci	case 1:								\
2928c2ecf20Sopenharmony_ci		__put_user_asm("sb", (ptr), __gu_val, __gu_err);	\
2938c2ecf20Sopenharmony_ci		break;							\
2948c2ecf20Sopenharmony_ci	case 2:								\
2958c2ecf20Sopenharmony_ci		__put_user_asm("sh", (ptr), __gu_val, __gu_err);	\
2968c2ecf20Sopenharmony_ci		break;							\
2978c2ecf20Sopenharmony_ci	case 4:								\
2988c2ecf20Sopenharmony_ci		__put_user_asm("sw", (ptr), __gu_val, __gu_err);	\
2998c2ecf20Sopenharmony_ci		break;							\
3008c2ecf20Sopenharmony_ci	case 8:								\
3018c2ecf20Sopenharmony_ci		__put_user_asm_8((ptr), __gu_val, __gu_err);		\
3028c2ecf20Sopenharmony_ci		break;							\
3038c2ecf20Sopenharmony_ci	default:							\
3048c2ecf20Sopenharmony_ci		/*__gu_err = -EINVAL;*/	__gu_err = __user_bad();	\
3058c2ecf20Sopenharmony_ci	}								\
3068c2ecf20Sopenharmony_ci	__gu_err;							\
3078c2ecf20Sopenharmony_ci})
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_cistatic inline unsigned long
3108c2ecf20Sopenharmony_ciraw_copy_from_user(void *to, const void __user *from, unsigned long n)
3118c2ecf20Sopenharmony_ci{
3128c2ecf20Sopenharmony_ci	return __copy_tofrom_user((__force void __user *)to, from, n);
3138c2ecf20Sopenharmony_ci}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic inline unsigned long
3168c2ecf20Sopenharmony_ciraw_copy_to_user(void __user *to, const void *from, unsigned long n)
3178c2ecf20Sopenharmony_ci{
3188c2ecf20Sopenharmony_ci	return __copy_tofrom_user(to, (__force const void __user *)from, n);
3198c2ecf20Sopenharmony_ci}
3208c2ecf20Sopenharmony_ci#define INLINE_COPY_FROM_USER
3218c2ecf20Sopenharmony_ci#define INLINE_COPY_TO_USER
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci/*
3248c2ecf20Sopenharmony_ci * Copy a null terminated string from userspace.
3258c2ecf20Sopenharmony_ci */
3268c2ecf20Sopenharmony_ciextern int __strncpy_user(char *to, const char __user *from, int len);
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_cistatic inline long
3298c2ecf20Sopenharmony_cistrncpy_from_user(char *dst, const char __user *src, long count)
3308c2ecf20Sopenharmony_ci{
3318c2ecf20Sopenharmony_ci	if (!access_ok(src, 1))
3328c2ecf20Sopenharmony_ci		return -EFAULT;
3338c2ecf20Sopenharmony_ci	return __strncpy_user(dst, src, count);
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci/*
3378c2ecf20Sopenharmony_ci * Return the size of a string (including the ending 0)
3388c2ecf20Sopenharmony_ci *
3398c2ecf20Sopenharmony_ci * Return 0 on exception, a value greater than N if too long
3408c2ecf20Sopenharmony_ci */
3418c2ecf20Sopenharmony_ciextern int __strnlen_user(const char __user *sstr, int len);
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_cistatic inline long strnlen_user(const char __user *src, long n)
3448c2ecf20Sopenharmony_ci{
3458c2ecf20Sopenharmony_ci	if (!access_ok(src, 1))
3468c2ecf20Sopenharmony_ci		return 0;
3478c2ecf20Sopenharmony_ci	return __strnlen_user(src, n);
3488c2ecf20Sopenharmony_ci}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci#endif /* _ASM_MICROBLAZE_UACCESS_H */
351