18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#ifndef __ASM_CSKY_UACCESS_H 58c2ecf20Sopenharmony_ci#define __ASM_CSKY_UACCESS_H 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci/* 88c2ecf20Sopenharmony_ci * User space memory access functions 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci#include <linux/compiler.h> 118c2ecf20Sopenharmony_ci#include <linux/errno.h> 128c2ecf20Sopenharmony_ci#include <linux/types.h> 138c2ecf20Sopenharmony_ci#include <linux/sched.h> 148c2ecf20Sopenharmony_ci#include <linux/string.h> 158c2ecf20Sopenharmony_ci#include <linux/version.h> 168c2ecf20Sopenharmony_ci#include <asm/segment.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic inline int access_ok(const void *addr, unsigned long size) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci unsigned long limit = current_thread_info()->addr_limit.seg; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci return (((unsigned long)addr < limit) && 238c2ecf20Sopenharmony_ci ((unsigned long)(addr + size) < limit)); 248c2ecf20Sopenharmony_ci} 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define __addr_ok(addr) (access_ok(addr, 0)) 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ciextern int __put_user_bad(void); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* 318c2ecf20Sopenharmony_ci * Tell gcc we read from memory instead of writing: this is because 328c2ecf20Sopenharmony_ci * we do not write to any memory gcc knows about, so there are no 338c2ecf20Sopenharmony_ci * aliasing issues. 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci/* 378c2ecf20Sopenharmony_ci * These are the main single-value transfer routines. They automatically 388c2ecf20Sopenharmony_ci * use the right size if we just have the right pointer type. 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * This gets kind of ugly. We want to return _two_ values in "get_user()" 418c2ecf20Sopenharmony_ci * and yet we don't want to do any pointers, because that is too much 428c2ecf20Sopenharmony_ci * of a performance impact. Thus we have a few rather ugly macros here, 438c2ecf20Sopenharmony_ci * and hide all the ugliness from the user. 448c2ecf20Sopenharmony_ci * 458c2ecf20Sopenharmony_ci * The "__xxx" versions of the user access functions are versions that 468c2ecf20Sopenharmony_ci * do not verify the address space, that must have been done previously 478c2ecf20Sopenharmony_ci * with a separate "access_ok()" call (this is used when we do multiple 488c2ecf20Sopenharmony_ci * accesses to the same area of user memory). 498c2ecf20Sopenharmony_ci * 508c2ecf20Sopenharmony_ci * As we use the same address space for kernel and user data on 518c2ecf20Sopenharmony_ci * Ckcore, we can just do these as direct assignments. (Of course, the 528c2ecf20Sopenharmony_ci * exception handling means that it's no longer "just"...) 538c2ecf20Sopenharmony_ci */ 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#define put_user(x, ptr) \ 568c2ecf20Sopenharmony_ci __put_user_check((x), (ptr), sizeof(*(ptr))) 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#define __put_user(x, ptr) \ 598c2ecf20Sopenharmony_ci __put_user_nocheck((x), (ptr), sizeof(*(ptr))) 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#define __ptr(x) ((unsigned long *)(x)) 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#define get_user(x, ptr) \ 648c2ecf20Sopenharmony_ci __get_user_check((x), (ptr), sizeof(*(ptr))) 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#define __get_user(x, ptr) \ 678c2ecf20Sopenharmony_ci __get_user_nocheck((x), (ptr), sizeof(*(ptr))) 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci#define __put_user_nocheck(x, ptr, size) \ 708c2ecf20Sopenharmony_ci({ \ 718c2ecf20Sopenharmony_ci long __pu_err = 0; \ 728c2ecf20Sopenharmony_ci typeof(*(ptr)) *__pu_addr = (ptr); \ 738c2ecf20Sopenharmony_ci typeof(*(ptr)) __pu_val = (typeof(*(ptr)))(x); \ 748c2ecf20Sopenharmony_ci if (__pu_addr) \ 758c2ecf20Sopenharmony_ci __put_user_size(__pu_val, (__pu_addr), (size), \ 768c2ecf20Sopenharmony_ci __pu_err); \ 778c2ecf20Sopenharmony_ci __pu_err; \ 788c2ecf20Sopenharmony_ci}) 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#define __put_user_check(x, ptr, size) \ 818c2ecf20Sopenharmony_ci({ \ 828c2ecf20Sopenharmony_ci long __pu_err = -EFAULT; \ 838c2ecf20Sopenharmony_ci typeof(*(ptr)) *__pu_addr = (ptr); \ 848c2ecf20Sopenharmony_ci typeof(*(ptr)) __pu_val = (typeof(*(ptr)))(x); \ 858c2ecf20Sopenharmony_ci if (access_ok(__pu_addr, size) && __pu_addr) \ 868c2ecf20Sopenharmony_ci __put_user_size(__pu_val, __pu_addr, (size), __pu_err); \ 878c2ecf20Sopenharmony_ci __pu_err; \ 888c2ecf20Sopenharmony_ci}) 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci#define __put_user_size(x, ptr, size, retval) \ 918c2ecf20Sopenharmony_cido { \ 928c2ecf20Sopenharmony_ci retval = 0; \ 938c2ecf20Sopenharmony_ci switch (size) { \ 948c2ecf20Sopenharmony_ci case 1: \ 958c2ecf20Sopenharmony_ci __put_user_asm_b(x, ptr, retval); \ 968c2ecf20Sopenharmony_ci break; \ 978c2ecf20Sopenharmony_ci case 2: \ 988c2ecf20Sopenharmony_ci __put_user_asm_h(x, ptr, retval); \ 998c2ecf20Sopenharmony_ci break; \ 1008c2ecf20Sopenharmony_ci case 4: \ 1018c2ecf20Sopenharmony_ci __put_user_asm_w(x, ptr, retval); \ 1028c2ecf20Sopenharmony_ci break; \ 1038c2ecf20Sopenharmony_ci case 8: \ 1048c2ecf20Sopenharmony_ci __put_user_asm_64(x, ptr, retval); \ 1058c2ecf20Sopenharmony_ci break; \ 1068c2ecf20Sopenharmony_ci default: \ 1078c2ecf20Sopenharmony_ci __put_user_bad(); \ 1088c2ecf20Sopenharmony_ci } \ 1098c2ecf20Sopenharmony_ci} while (0) 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/* 1128c2ecf20Sopenharmony_ci * We don't tell gcc that we are accessing memory, but this is OK 1138c2ecf20Sopenharmony_ci * because we do not write to any memory gcc knows about, so there 1148c2ecf20Sopenharmony_ci * are no aliasing issues. 1158c2ecf20Sopenharmony_ci * 1168c2ecf20Sopenharmony_ci * Note that PC at a fault is the address *after* the faulting 1178c2ecf20Sopenharmony_ci * instruction. 1188c2ecf20Sopenharmony_ci */ 1198c2ecf20Sopenharmony_ci#define __put_user_asm_b(x, ptr, err) \ 1208c2ecf20Sopenharmony_cido { \ 1218c2ecf20Sopenharmony_ci int errcode; \ 1228c2ecf20Sopenharmony_ci asm volatile( \ 1238c2ecf20Sopenharmony_ci "1: stb %1, (%2,0) \n" \ 1248c2ecf20Sopenharmony_ci " br 3f \n" \ 1258c2ecf20Sopenharmony_ci "2: mov %0, %3 \n" \ 1268c2ecf20Sopenharmony_ci " br 3f \n" \ 1278c2ecf20Sopenharmony_ci ".section __ex_table, \"a\" \n" \ 1288c2ecf20Sopenharmony_ci ".align 2 \n" \ 1298c2ecf20Sopenharmony_ci ".long 1b,2b \n" \ 1308c2ecf20Sopenharmony_ci ".previous \n" \ 1318c2ecf20Sopenharmony_ci "3: \n" \ 1328c2ecf20Sopenharmony_ci : "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode) \ 1338c2ecf20Sopenharmony_ci : "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT) \ 1348c2ecf20Sopenharmony_ci : "memory"); \ 1358c2ecf20Sopenharmony_ci} while (0) 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci#define __put_user_asm_h(x, ptr, err) \ 1388c2ecf20Sopenharmony_cido { \ 1398c2ecf20Sopenharmony_ci int errcode; \ 1408c2ecf20Sopenharmony_ci asm volatile( \ 1418c2ecf20Sopenharmony_ci "1: sth %1, (%2,0) \n" \ 1428c2ecf20Sopenharmony_ci " br 3f \n" \ 1438c2ecf20Sopenharmony_ci "2: mov %0, %3 \n" \ 1448c2ecf20Sopenharmony_ci " br 3f \n" \ 1458c2ecf20Sopenharmony_ci ".section __ex_table, \"a\" \n" \ 1468c2ecf20Sopenharmony_ci ".align 2 \n" \ 1478c2ecf20Sopenharmony_ci ".long 1b,2b \n" \ 1488c2ecf20Sopenharmony_ci ".previous \n" \ 1498c2ecf20Sopenharmony_ci "3: \n" \ 1508c2ecf20Sopenharmony_ci : "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode) \ 1518c2ecf20Sopenharmony_ci : "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT) \ 1528c2ecf20Sopenharmony_ci : "memory"); \ 1538c2ecf20Sopenharmony_ci} while (0) 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci#define __put_user_asm_w(x, ptr, err) \ 1568c2ecf20Sopenharmony_cido { \ 1578c2ecf20Sopenharmony_ci int errcode; \ 1588c2ecf20Sopenharmony_ci asm volatile( \ 1598c2ecf20Sopenharmony_ci "1: stw %1, (%2,0) \n" \ 1608c2ecf20Sopenharmony_ci " br 3f \n" \ 1618c2ecf20Sopenharmony_ci "2: mov %0, %3 \n" \ 1628c2ecf20Sopenharmony_ci " br 3f \n" \ 1638c2ecf20Sopenharmony_ci ".section __ex_table,\"a\" \n" \ 1648c2ecf20Sopenharmony_ci ".align 2 \n" \ 1658c2ecf20Sopenharmony_ci ".long 1b, 2b \n" \ 1668c2ecf20Sopenharmony_ci ".previous \n" \ 1678c2ecf20Sopenharmony_ci "3: \n" \ 1688c2ecf20Sopenharmony_ci : "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode) \ 1698c2ecf20Sopenharmony_ci : "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT) \ 1708c2ecf20Sopenharmony_ci : "memory"); \ 1718c2ecf20Sopenharmony_ci} while (0) 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci#define __put_user_asm_64(x, ptr, err) \ 1748c2ecf20Sopenharmony_cido { \ 1758c2ecf20Sopenharmony_ci int tmp; \ 1768c2ecf20Sopenharmony_ci int errcode; \ 1778c2ecf20Sopenharmony_ci typeof(*(ptr))src = (typeof(*(ptr)))x; \ 1788c2ecf20Sopenharmony_ci typeof(*(ptr))*psrc = &src; \ 1798c2ecf20Sopenharmony_ci \ 1808c2ecf20Sopenharmony_ci asm volatile( \ 1818c2ecf20Sopenharmony_ci " ldw %3, (%1, 0) \n" \ 1828c2ecf20Sopenharmony_ci "1: stw %3, (%2, 0) \n" \ 1838c2ecf20Sopenharmony_ci " ldw %3, (%1, 4) \n" \ 1848c2ecf20Sopenharmony_ci "2: stw %3, (%2, 4) \n" \ 1858c2ecf20Sopenharmony_ci " br 4f \n" \ 1868c2ecf20Sopenharmony_ci "3: mov %0, %4 \n" \ 1878c2ecf20Sopenharmony_ci " br 4f \n" \ 1888c2ecf20Sopenharmony_ci ".section __ex_table, \"a\" \n" \ 1898c2ecf20Sopenharmony_ci ".align 2 \n" \ 1908c2ecf20Sopenharmony_ci ".long 1b, 3b \n" \ 1918c2ecf20Sopenharmony_ci ".long 2b, 3b \n" \ 1928c2ecf20Sopenharmony_ci ".previous \n" \ 1938c2ecf20Sopenharmony_ci "4: \n" \ 1948c2ecf20Sopenharmony_ci : "=r"(err), "=r"(psrc), "=r"(ptr), \ 1958c2ecf20Sopenharmony_ci "=r"(tmp), "=r"(errcode) \ 1968c2ecf20Sopenharmony_ci : "0"(err), "1"(psrc), "2"(ptr), "3"(0), "4"(-EFAULT) \ 1978c2ecf20Sopenharmony_ci : "memory"); \ 1988c2ecf20Sopenharmony_ci} while (0) 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci#define __get_user_nocheck(x, ptr, size) \ 2018c2ecf20Sopenharmony_ci({ \ 2028c2ecf20Sopenharmony_ci long __gu_err; \ 2038c2ecf20Sopenharmony_ci __get_user_size(x, (ptr), (size), __gu_err); \ 2048c2ecf20Sopenharmony_ci __gu_err; \ 2058c2ecf20Sopenharmony_ci}) 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci#define __get_user_check(x, ptr, size) \ 2088c2ecf20Sopenharmony_ci({ \ 2098c2ecf20Sopenharmony_ci int __gu_err = -EFAULT; \ 2108c2ecf20Sopenharmony_ci const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ 2118c2ecf20Sopenharmony_ci if (access_ok(__gu_ptr, size) && __gu_ptr) \ 2128c2ecf20Sopenharmony_ci __get_user_size(x, __gu_ptr, size, __gu_err); \ 2138c2ecf20Sopenharmony_ci __gu_err; \ 2148c2ecf20Sopenharmony_ci}) 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci#define __get_user_size(x, ptr, size, retval) \ 2178c2ecf20Sopenharmony_cido { \ 2188c2ecf20Sopenharmony_ci switch (size) { \ 2198c2ecf20Sopenharmony_ci case 1: \ 2208c2ecf20Sopenharmony_ci __get_user_asm_common((x), ptr, "ldb", retval); \ 2218c2ecf20Sopenharmony_ci break; \ 2228c2ecf20Sopenharmony_ci case 2: \ 2238c2ecf20Sopenharmony_ci __get_user_asm_common((x), ptr, "ldh", retval); \ 2248c2ecf20Sopenharmony_ci break; \ 2258c2ecf20Sopenharmony_ci case 4: \ 2268c2ecf20Sopenharmony_ci __get_user_asm_common((x), ptr, "ldw", retval); \ 2278c2ecf20Sopenharmony_ci break; \ 2288c2ecf20Sopenharmony_ci default: \ 2298c2ecf20Sopenharmony_ci x = 0; \ 2308c2ecf20Sopenharmony_ci (retval) = __get_user_bad(); \ 2318c2ecf20Sopenharmony_ci } \ 2328c2ecf20Sopenharmony_ci} while (0) 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci#define __get_user_asm_common(x, ptr, ins, err) \ 2358c2ecf20Sopenharmony_cido { \ 2368c2ecf20Sopenharmony_ci int errcode; \ 2378c2ecf20Sopenharmony_ci asm volatile( \ 2388c2ecf20Sopenharmony_ci "1: " ins " %1, (%4,0) \n" \ 2398c2ecf20Sopenharmony_ci " br 3f \n" \ 2408c2ecf20Sopenharmony_ci /* Fix up codes */ \ 2418c2ecf20Sopenharmony_ci "2: mov %0, %2 \n" \ 2428c2ecf20Sopenharmony_ci " movi %1, 0 \n" \ 2438c2ecf20Sopenharmony_ci " br 3f \n" \ 2448c2ecf20Sopenharmony_ci ".section __ex_table,\"a\" \n" \ 2458c2ecf20Sopenharmony_ci ".align 2 \n" \ 2468c2ecf20Sopenharmony_ci ".long 1b, 2b \n" \ 2478c2ecf20Sopenharmony_ci ".previous \n" \ 2488c2ecf20Sopenharmony_ci "3: \n" \ 2498c2ecf20Sopenharmony_ci : "=r"(err), "=r"(x), "=r"(errcode) \ 2508c2ecf20Sopenharmony_ci : "0"(0), "r"(ptr), "2"(-EFAULT) \ 2518c2ecf20Sopenharmony_ci : "memory"); \ 2528c2ecf20Sopenharmony_ci} while (0) 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ciextern int __get_user_bad(void); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci#define ___copy_to_user(to, from, n) \ 2578c2ecf20Sopenharmony_cido { \ 2588c2ecf20Sopenharmony_ci int w0, w1, w2, w3; \ 2598c2ecf20Sopenharmony_ci asm volatile( \ 2608c2ecf20Sopenharmony_ci "0: cmpnei %1, 0 \n" \ 2618c2ecf20Sopenharmony_ci " bf 8f \n" \ 2628c2ecf20Sopenharmony_ci " mov %3, %1 \n" \ 2638c2ecf20Sopenharmony_ci " or %3, %2 \n" \ 2648c2ecf20Sopenharmony_ci " andi %3, 3 \n" \ 2658c2ecf20Sopenharmony_ci " cmpnei %3, 0 \n" \ 2668c2ecf20Sopenharmony_ci " bf 1f \n" \ 2678c2ecf20Sopenharmony_ci " br 5f \n" \ 2688c2ecf20Sopenharmony_ci "1: cmplti %0, 16 \n" /* 4W */ \ 2698c2ecf20Sopenharmony_ci " bt 3f \n" \ 2708c2ecf20Sopenharmony_ci " ldw %3, (%2, 0) \n" \ 2718c2ecf20Sopenharmony_ci " ldw %4, (%2, 4) \n" \ 2728c2ecf20Sopenharmony_ci " ldw %5, (%2, 8) \n" \ 2738c2ecf20Sopenharmony_ci " ldw %6, (%2, 12) \n" \ 2748c2ecf20Sopenharmony_ci "2: stw %3, (%1, 0) \n" \ 2758c2ecf20Sopenharmony_ci "9: stw %4, (%1, 4) \n" \ 2768c2ecf20Sopenharmony_ci "10: stw %5, (%1, 8) \n" \ 2778c2ecf20Sopenharmony_ci "11: stw %6, (%1, 12) \n" \ 2788c2ecf20Sopenharmony_ci " addi %2, 16 \n" \ 2798c2ecf20Sopenharmony_ci " addi %1, 16 \n" \ 2808c2ecf20Sopenharmony_ci " subi %0, 16 \n" \ 2818c2ecf20Sopenharmony_ci " br 1b \n" \ 2828c2ecf20Sopenharmony_ci "3: cmplti %0, 4 \n" /* 1W */ \ 2838c2ecf20Sopenharmony_ci " bt 5f \n" \ 2848c2ecf20Sopenharmony_ci " ldw %3, (%2, 0) \n" \ 2858c2ecf20Sopenharmony_ci "4: stw %3, (%1, 0) \n" \ 2868c2ecf20Sopenharmony_ci " addi %2, 4 \n" \ 2878c2ecf20Sopenharmony_ci " addi %1, 4 \n" \ 2888c2ecf20Sopenharmony_ci " subi %0, 4 \n" \ 2898c2ecf20Sopenharmony_ci " br 3b \n" \ 2908c2ecf20Sopenharmony_ci "5: cmpnei %0, 0 \n" /* 1B */ \ 2918c2ecf20Sopenharmony_ci " bf 13f \n" \ 2928c2ecf20Sopenharmony_ci " ldb %3, (%2, 0) \n" \ 2938c2ecf20Sopenharmony_ci "6: stb %3, (%1, 0) \n" \ 2948c2ecf20Sopenharmony_ci " addi %2, 1 \n" \ 2958c2ecf20Sopenharmony_ci " addi %1, 1 \n" \ 2968c2ecf20Sopenharmony_ci " subi %0, 1 \n" \ 2978c2ecf20Sopenharmony_ci " br 5b \n" \ 2988c2ecf20Sopenharmony_ci "7: subi %0, 4 \n" \ 2998c2ecf20Sopenharmony_ci "8: subi %0, 4 \n" \ 3008c2ecf20Sopenharmony_ci "12: subi %0, 4 \n" \ 3018c2ecf20Sopenharmony_ci " br 13f \n" \ 3028c2ecf20Sopenharmony_ci ".section __ex_table, \"a\" \n" \ 3038c2ecf20Sopenharmony_ci ".align 2 \n" \ 3048c2ecf20Sopenharmony_ci ".long 2b, 13f \n" \ 3058c2ecf20Sopenharmony_ci ".long 4b, 13f \n" \ 3068c2ecf20Sopenharmony_ci ".long 6b, 13f \n" \ 3078c2ecf20Sopenharmony_ci ".long 9b, 12b \n" \ 3088c2ecf20Sopenharmony_ci ".long 10b, 8b \n" \ 3098c2ecf20Sopenharmony_ci ".long 11b, 7b \n" \ 3108c2ecf20Sopenharmony_ci ".previous \n" \ 3118c2ecf20Sopenharmony_ci "13: \n" \ 3128c2ecf20Sopenharmony_ci : "=r"(n), "=r"(to), "=r"(from), "=r"(w0), \ 3138c2ecf20Sopenharmony_ci "=r"(w1), "=r"(w2), "=r"(w3) \ 3148c2ecf20Sopenharmony_ci : "0"(n), "1"(to), "2"(from) \ 3158c2ecf20Sopenharmony_ci : "memory"); \ 3168c2ecf20Sopenharmony_ci} while (0) 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci#define ___copy_from_user(to, from, n) \ 3198c2ecf20Sopenharmony_cido { \ 3208c2ecf20Sopenharmony_ci int tmp; \ 3218c2ecf20Sopenharmony_ci int nsave; \ 3228c2ecf20Sopenharmony_ci asm volatile( \ 3238c2ecf20Sopenharmony_ci "0: cmpnei %1, 0 \n" \ 3248c2ecf20Sopenharmony_ci " bf 7f \n" \ 3258c2ecf20Sopenharmony_ci " mov %3, %1 \n" \ 3268c2ecf20Sopenharmony_ci " or %3, %2 \n" \ 3278c2ecf20Sopenharmony_ci " andi %3, 3 \n" \ 3288c2ecf20Sopenharmony_ci " cmpnei %3, 0 \n" \ 3298c2ecf20Sopenharmony_ci " bf 1f \n" \ 3308c2ecf20Sopenharmony_ci " br 5f \n" \ 3318c2ecf20Sopenharmony_ci "1: cmplti %0, 16 \n" \ 3328c2ecf20Sopenharmony_ci " bt 3f \n" \ 3338c2ecf20Sopenharmony_ci "2: ldw %3, (%2, 0) \n" \ 3348c2ecf20Sopenharmony_ci "10: ldw %4, (%2, 4) \n" \ 3358c2ecf20Sopenharmony_ci " stw %3, (%1, 0) \n" \ 3368c2ecf20Sopenharmony_ci " stw %4, (%1, 4) \n" \ 3378c2ecf20Sopenharmony_ci "11: ldw %3, (%2, 8) \n" \ 3388c2ecf20Sopenharmony_ci "12: ldw %4, (%2, 12) \n" \ 3398c2ecf20Sopenharmony_ci " stw %3, (%1, 8) \n" \ 3408c2ecf20Sopenharmony_ci " stw %4, (%1, 12) \n" \ 3418c2ecf20Sopenharmony_ci " addi %2, 16 \n" \ 3428c2ecf20Sopenharmony_ci " addi %1, 16 \n" \ 3438c2ecf20Sopenharmony_ci " subi %0, 16 \n" \ 3448c2ecf20Sopenharmony_ci " br 1b \n" \ 3458c2ecf20Sopenharmony_ci "3: cmplti %0, 4 \n" \ 3468c2ecf20Sopenharmony_ci " bt 5f \n" \ 3478c2ecf20Sopenharmony_ci "4: ldw %3, (%2, 0) \n" \ 3488c2ecf20Sopenharmony_ci " stw %3, (%1, 0) \n" \ 3498c2ecf20Sopenharmony_ci " addi %2, 4 \n" \ 3508c2ecf20Sopenharmony_ci " addi %1, 4 \n" \ 3518c2ecf20Sopenharmony_ci " subi %0, 4 \n" \ 3528c2ecf20Sopenharmony_ci " br 3b \n" \ 3538c2ecf20Sopenharmony_ci "5: cmpnei %0, 0 \n" \ 3548c2ecf20Sopenharmony_ci " bf 7f \n" \ 3558c2ecf20Sopenharmony_ci "6: ldb %3, (%2, 0) \n" \ 3568c2ecf20Sopenharmony_ci " stb %3, (%1, 0) \n" \ 3578c2ecf20Sopenharmony_ci " addi %2, 1 \n" \ 3588c2ecf20Sopenharmony_ci " addi %1, 1 \n" \ 3598c2ecf20Sopenharmony_ci " subi %0, 1 \n" \ 3608c2ecf20Sopenharmony_ci " br 5b \n" \ 3618c2ecf20Sopenharmony_ci "8: stw %3, (%1, 0) \n" \ 3628c2ecf20Sopenharmony_ci " subi %0, 4 \n" \ 3638c2ecf20Sopenharmony_ci " bf 7f \n" \ 3648c2ecf20Sopenharmony_ci "9: subi %0, 8 \n" \ 3658c2ecf20Sopenharmony_ci " bf 7f \n" \ 3668c2ecf20Sopenharmony_ci "13: stw %3, (%1, 8) \n" \ 3678c2ecf20Sopenharmony_ci " subi %0, 12 \n" \ 3688c2ecf20Sopenharmony_ci " bf 7f \n" \ 3698c2ecf20Sopenharmony_ci ".section __ex_table, \"a\" \n" \ 3708c2ecf20Sopenharmony_ci ".align 2 \n" \ 3718c2ecf20Sopenharmony_ci ".long 2b, 7f \n" \ 3728c2ecf20Sopenharmony_ci ".long 4b, 7f \n" \ 3738c2ecf20Sopenharmony_ci ".long 6b, 7f \n" \ 3748c2ecf20Sopenharmony_ci ".long 10b, 8b \n" \ 3758c2ecf20Sopenharmony_ci ".long 11b, 9b \n" \ 3768c2ecf20Sopenharmony_ci ".long 12b,13b \n" \ 3778c2ecf20Sopenharmony_ci ".previous \n" \ 3788c2ecf20Sopenharmony_ci "7: \n" \ 3798c2ecf20Sopenharmony_ci : "=r"(n), "=r"(to), "=r"(from), "=r"(nsave), \ 3808c2ecf20Sopenharmony_ci "=r"(tmp) \ 3818c2ecf20Sopenharmony_ci : "0"(n), "1"(to), "2"(from) \ 3828c2ecf20Sopenharmony_ci : "memory"); \ 3838c2ecf20Sopenharmony_ci} while (0) 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ciunsigned long raw_copy_from_user(void *to, const void *from, unsigned long n); 3868c2ecf20Sopenharmony_ciunsigned long raw_copy_to_user(void *to, const void *from, unsigned long n); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ciunsigned long clear_user(void *to, unsigned long n); 3898c2ecf20Sopenharmony_ciunsigned long __clear_user(void __user *to, unsigned long n); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_cilong strncpy_from_user(char *dst, const char *src, long count); 3928c2ecf20Sopenharmony_cilong __strncpy_from_user(char *dst, const char *src, long count); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci/* 3958c2ecf20Sopenharmony_ci * Return the size of a string (including the ending 0) 3968c2ecf20Sopenharmony_ci * 3978c2ecf20Sopenharmony_ci * Return 0 on exception, a value greater than N if too long 3988c2ecf20Sopenharmony_ci */ 3998c2ecf20Sopenharmony_cilong strnlen_user(const char *src, long n); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci#define strlen_user(str) strnlen_user(str, 32767) 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cistruct exception_table_entry { 4048c2ecf20Sopenharmony_ci unsigned long insn; 4058c2ecf20Sopenharmony_ci unsigned long nextinsn; 4068c2ecf20Sopenharmony_ci}; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ciextern int fixup_exception(struct pt_regs *regs); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci#endif /* __ASM_CSKY_UACCESS_H */ 411