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