18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2012 Regents of the University of California 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This file was copied from include/asm-generic/uaccess.h 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef _ASM_RISCV_UACCESS_H 98c2ecf20Sopenharmony_ci#define _ASM_RISCV_UACCESS_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <asm/pgtable.h> /* for TASK_SIZE */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci * User space memory access functions 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci#ifdef CONFIG_MMU 178c2ecf20Sopenharmony_ci#include <linux/errno.h> 188c2ecf20Sopenharmony_ci#include <linux/compiler.h> 198c2ecf20Sopenharmony_ci#include <linux/thread_info.h> 208c2ecf20Sopenharmony_ci#include <asm/byteorder.h> 218c2ecf20Sopenharmony_ci#include <asm/extable.h> 228c2ecf20Sopenharmony_ci#include <asm/asm.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define __enable_user_access() \ 258c2ecf20Sopenharmony_ci __asm__ __volatile__ ("csrs sstatus, %0" : : "r" (SR_SUM) : "memory") 268c2ecf20Sopenharmony_ci#define __disable_user_access() \ 278c2ecf20Sopenharmony_ci __asm__ __volatile__ ("csrc sstatus, %0" : : "r" (SR_SUM) : "memory") 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/** 308c2ecf20Sopenharmony_ci * access_ok: - Checks if a user space pointer is valid 318c2ecf20Sopenharmony_ci * @addr: User space pointer to start of block to check 328c2ecf20Sopenharmony_ci * @size: Size of block to check 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * Context: User context only. This function may sleep. 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * Checks if a pointer to a block of memory in user space is valid. 378c2ecf20Sopenharmony_ci * 388c2ecf20Sopenharmony_ci * Returns true (nonzero) if the memory block may be valid, false (zero) 398c2ecf20Sopenharmony_ci * if it is definitely invalid. 408c2ecf20Sopenharmony_ci * 418c2ecf20Sopenharmony_ci * Note that, depending on architecture, this function probably just 428c2ecf20Sopenharmony_ci * checks that the pointer is in the user space range - after calling 438c2ecf20Sopenharmony_ci * this function, memory access functions may still return -EFAULT. 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_ci#define access_ok(addr, size) ({ \ 468c2ecf20Sopenharmony_ci __chk_user_ptr(addr); \ 478c2ecf20Sopenharmony_ci likely(__access_ok((unsigned long __force)(addr), (size))); \ 488c2ecf20Sopenharmony_ci}) 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* 518c2ecf20Sopenharmony_ci * Ensure that the range [addr, addr+size) is within the process's 528c2ecf20Sopenharmony_ci * address space 538c2ecf20Sopenharmony_ci */ 548c2ecf20Sopenharmony_cistatic inline int __access_ok(unsigned long addr, unsigned long size) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci return size <= TASK_SIZE && addr <= TASK_SIZE - size; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* 608c2ecf20Sopenharmony_ci * The exception table consists of pairs of addresses: the first is the 618c2ecf20Sopenharmony_ci * address of an instruction that is allowed to fault, and the second is 628c2ecf20Sopenharmony_ci * the address at which the program should continue. No registers are 638c2ecf20Sopenharmony_ci * modified, so it is entirely up to the continuation code to figure out 648c2ecf20Sopenharmony_ci * what to do. 658c2ecf20Sopenharmony_ci * 668c2ecf20Sopenharmony_ci * All the routines below use bits of fixup code that are out of line 678c2ecf20Sopenharmony_ci * with the main instruction path. This means when everything is well, 688c2ecf20Sopenharmony_ci * we don't even have to jump over them. Further, they do not intrude 698c2ecf20Sopenharmony_ci * on our cache or tlb entries. 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#define __LSW 0 738c2ecf20Sopenharmony_ci#define __MSW 1 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/* 768c2ecf20Sopenharmony_ci * The "__xxx" versions of the user access functions do not verify the address 778c2ecf20Sopenharmony_ci * space - it must have been done previously with a separate "access_ok()" 788c2ecf20Sopenharmony_ci * call. 798c2ecf20Sopenharmony_ci */ 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#define __get_user_asm(insn, x, ptr, err) \ 828c2ecf20Sopenharmony_cido { \ 838c2ecf20Sopenharmony_ci uintptr_t __tmp; \ 848c2ecf20Sopenharmony_ci __typeof__(x) __x; \ 858c2ecf20Sopenharmony_ci __asm__ __volatile__ ( \ 868c2ecf20Sopenharmony_ci "1:\n" \ 878c2ecf20Sopenharmony_ci " " insn " %1, %3\n" \ 888c2ecf20Sopenharmony_ci "2:\n" \ 898c2ecf20Sopenharmony_ci " .section .fixup,\"ax\"\n" \ 908c2ecf20Sopenharmony_ci " .balign 4\n" \ 918c2ecf20Sopenharmony_ci "3:\n" \ 928c2ecf20Sopenharmony_ci " li %0, %4\n" \ 938c2ecf20Sopenharmony_ci " li %1, 0\n" \ 948c2ecf20Sopenharmony_ci " jump 2b, %2\n" \ 958c2ecf20Sopenharmony_ci " .previous\n" \ 968c2ecf20Sopenharmony_ci " .section __ex_table,\"a\"\n" \ 978c2ecf20Sopenharmony_ci " .balign " RISCV_SZPTR "\n" \ 988c2ecf20Sopenharmony_ci " " RISCV_PTR " 1b, 3b\n" \ 998c2ecf20Sopenharmony_ci " .previous" \ 1008c2ecf20Sopenharmony_ci : "+r" (err), "=&r" (__x), "=r" (__tmp) \ 1018c2ecf20Sopenharmony_ci : "m" (*(ptr)), "i" (-EFAULT)); \ 1028c2ecf20Sopenharmony_ci (x) = __x; \ 1038c2ecf20Sopenharmony_ci} while (0) 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 1068c2ecf20Sopenharmony_ci#define __get_user_8(x, ptr, err) \ 1078c2ecf20Sopenharmony_ci __get_user_asm("ld", x, ptr, err) 1088c2ecf20Sopenharmony_ci#else /* !CONFIG_64BIT */ 1098c2ecf20Sopenharmony_ci#define __get_user_8(x, ptr, err) \ 1108c2ecf20Sopenharmony_cido { \ 1118c2ecf20Sopenharmony_ci u32 __user *__ptr = (u32 __user *)(ptr); \ 1128c2ecf20Sopenharmony_ci u32 __lo, __hi; \ 1138c2ecf20Sopenharmony_ci uintptr_t __tmp; \ 1148c2ecf20Sopenharmony_ci __asm__ __volatile__ ( \ 1158c2ecf20Sopenharmony_ci "1:\n" \ 1168c2ecf20Sopenharmony_ci " lw %1, %4\n" \ 1178c2ecf20Sopenharmony_ci "2:\n" \ 1188c2ecf20Sopenharmony_ci " lw %2, %5\n" \ 1198c2ecf20Sopenharmony_ci "3:\n" \ 1208c2ecf20Sopenharmony_ci " .section .fixup,\"ax\"\n" \ 1218c2ecf20Sopenharmony_ci " .balign 4\n" \ 1228c2ecf20Sopenharmony_ci "4:\n" \ 1238c2ecf20Sopenharmony_ci " li %0, %6\n" \ 1248c2ecf20Sopenharmony_ci " li %1, 0\n" \ 1258c2ecf20Sopenharmony_ci " li %2, 0\n" \ 1268c2ecf20Sopenharmony_ci " jump 3b, %3\n" \ 1278c2ecf20Sopenharmony_ci " .previous\n" \ 1288c2ecf20Sopenharmony_ci " .section __ex_table,\"a\"\n" \ 1298c2ecf20Sopenharmony_ci " .balign " RISCV_SZPTR "\n" \ 1308c2ecf20Sopenharmony_ci " " RISCV_PTR " 1b, 4b\n" \ 1318c2ecf20Sopenharmony_ci " " RISCV_PTR " 2b, 4b\n" \ 1328c2ecf20Sopenharmony_ci " .previous" \ 1338c2ecf20Sopenharmony_ci : "+r" (err), "=&r" (__lo), "=r" (__hi), \ 1348c2ecf20Sopenharmony_ci "=r" (__tmp) \ 1358c2ecf20Sopenharmony_ci : "m" (__ptr[__LSW]), "m" (__ptr[__MSW]), \ 1368c2ecf20Sopenharmony_ci "i" (-EFAULT)); \ 1378c2ecf20Sopenharmony_ci (x) = (__typeof__(x))((__typeof__((x)-(x)))( \ 1388c2ecf20Sopenharmony_ci (((u64)__hi << 32) | __lo))); \ 1398c2ecf20Sopenharmony_ci} while (0) 1408c2ecf20Sopenharmony_ci#endif /* CONFIG_64BIT */ 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci#define __get_user_nocheck(x, __gu_ptr, __gu_err) \ 1438c2ecf20Sopenharmony_cido { \ 1448c2ecf20Sopenharmony_ci switch (sizeof(*__gu_ptr)) { \ 1458c2ecf20Sopenharmony_ci case 1: \ 1468c2ecf20Sopenharmony_ci __get_user_asm("lb", (x), __gu_ptr, __gu_err); \ 1478c2ecf20Sopenharmony_ci break; \ 1488c2ecf20Sopenharmony_ci case 2: \ 1498c2ecf20Sopenharmony_ci __get_user_asm("lh", (x), __gu_ptr, __gu_err); \ 1508c2ecf20Sopenharmony_ci break; \ 1518c2ecf20Sopenharmony_ci case 4: \ 1528c2ecf20Sopenharmony_ci __get_user_asm("lw", (x), __gu_ptr, __gu_err); \ 1538c2ecf20Sopenharmony_ci break; \ 1548c2ecf20Sopenharmony_ci case 8: \ 1558c2ecf20Sopenharmony_ci __get_user_8((x), __gu_ptr, __gu_err); \ 1568c2ecf20Sopenharmony_ci break; \ 1578c2ecf20Sopenharmony_ci default: \ 1588c2ecf20Sopenharmony_ci BUILD_BUG(); \ 1598c2ecf20Sopenharmony_ci } \ 1608c2ecf20Sopenharmony_ci} while (0) 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci/** 1638c2ecf20Sopenharmony_ci * __get_user: - Get a simple variable from user space, with less checking. 1648c2ecf20Sopenharmony_ci * @x: Variable to store result. 1658c2ecf20Sopenharmony_ci * @ptr: Source address, in user space. 1668c2ecf20Sopenharmony_ci * 1678c2ecf20Sopenharmony_ci * Context: User context only. This function may sleep. 1688c2ecf20Sopenharmony_ci * 1698c2ecf20Sopenharmony_ci * This macro copies a single simple variable from user space to kernel 1708c2ecf20Sopenharmony_ci * space. It supports simple types like char and int, but not larger 1718c2ecf20Sopenharmony_ci * data types like structures or arrays. 1728c2ecf20Sopenharmony_ci * 1738c2ecf20Sopenharmony_ci * @ptr must have pointer-to-simple-variable type, and the result of 1748c2ecf20Sopenharmony_ci * dereferencing @ptr must be assignable to @x without a cast. 1758c2ecf20Sopenharmony_ci * 1768c2ecf20Sopenharmony_ci * Caller must check the pointer with access_ok() before calling this 1778c2ecf20Sopenharmony_ci * function. 1788c2ecf20Sopenharmony_ci * 1798c2ecf20Sopenharmony_ci * Returns zero on success, or -EFAULT on error. 1808c2ecf20Sopenharmony_ci * On error, the variable @x is set to zero. 1818c2ecf20Sopenharmony_ci */ 1828c2ecf20Sopenharmony_ci#define __get_user(x, ptr) \ 1838c2ecf20Sopenharmony_ci({ \ 1848c2ecf20Sopenharmony_ci const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ 1858c2ecf20Sopenharmony_ci long __gu_err = 0; \ 1868c2ecf20Sopenharmony_ci \ 1878c2ecf20Sopenharmony_ci __chk_user_ptr(__gu_ptr); \ 1888c2ecf20Sopenharmony_ci \ 1898c2ecf20Sopenharmony_ci __enable_user_access(); \ 1908c2ecf20Sopenharmony_ci __get_user_nocheck(x, __gu_ptr, __gu_err); \ 1918c2ecf20Sopenharmony_ci __disable_user_access(); \ 1928c2ecf20Sopenharmony_ci \ 1938c2ecf20Sopenharmony_ci __gu_err; \ 1948c2ecf20Sopenharmony_ci}) 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci/** 1978c2ecf20Sopenharmony_ci * get_user: - Get a simple variable from user space. 1988c2ecf20Sopenharmony_ci * @x: Variable to store result. 1998c2ecf20Sopenharmony_ci * @ptr: Source address, in user space. 2008c2ecf20Sopenharmony_ci * 2018c2ecf20Sopenharmony_ci * Context: User context only. This function may sleep. 2028c2ecf20Sopenharmony_ci * 2038c2ecf20Sopenharmony_ci * This macro copies a single simple variable from user space to kernel 2048c2ecf20Sopenharmony_ci * space. It supports simple types like char and int, but not larger 2058c2ecf20Sopenharmony_ci * data types like structures or arrays. 2068c2ecf20Sopenharmony_ci * 2078c2ecf20Sopenharmony_ci * @ptr must have pointer-to-simple-variable type, and the result of 2088c2ecf20Sopenharmony_ci * dereferencing @ptr must be assignable to @x without a cast. 2098c2ecf20Sopenharmony_ci * 2108c2ecf20Sopenharmony_ci * Returns zero on success, or -EFAULT on error. 2118c2ecf20Sopenharmony_ci * On error, the variable @x is set to zero. 2128c2ecf20Sopenharmony_ci */ 2138c2ecf20Sopenharmony_ci#define get_user(x, ptr) \ 2148c2ecf20Sopenharmony_ci({ \ 2158c2ecf20Sopenharmony_ci const __typeof__(*(ptr)) __user *__p = (ptr); \ 2168c2ecf20Sopenharmony_ci might_fault(); \ 2178c2ecf20Sopenharmony_ci access_ok(__p, sizeof(*__p)) ? \ 2188c2ecf20Sopenharmony_ci __get_user((x), __p) : \ 2198c2ecf20Sopenharmony_ci ((x) = (__force __typeof__(x))0, -EFAULT); \ 2208c2ecf20Sopenharmony_ci}) 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci#define __put_user_asm(insn, x, ptr, err) \ 2238c2ecf20Sopenharmony_cido { \ 2248c2ecf20Sopenharmony_ci uintptr_t __tmp; \ 2258c2ecf20Sopenharmony_ci __typeof__(*(ptr)) __x = x; \ 2268c2ecf20Sopenharmony_ci __asm__ __volatile__ ( \ 2278c2ecf20Sopenharmony_ci "1:\n" \ 2288c2ecf20Sopenharmony_ci " " insn " %z3, %2\n" \ 2298c2ecf20Sopenharmony_ci "2:\n" \ 2308c2ecf20Sopenharmony_ci " .section .fixup,\"ax\"\n" \ 2318c2ecf20Sopenharmony_ci " .balign 4\n" \ 2328c2ecf20Sopenharmony_ci "3:\n" \ 2338c2ecf20Sopenharmony_ci " li %0, %4\n" \ 2348c2ecf20Sopenharmony_ci " jump 2b, %1\n" \ 2358c2ecf20Sopenharmony_ci " .previous\n" \ 2368c2ecf20Sopenharmony_ci " .section __ex_table,\"a\"\n" \ 2378c2ecf20Sopenharmony_ci " .balign " RISCV_SZPTR "\n" \ 2388c2ecf20Sopenharmony_ci " " RISCV_PTR " 1b, 3b\n" \ 2398c2ecf20Sopenharmony_ci " .previous" \ 2408c2ecf20Sopenharmony_ci : "+r" (err), "=r" (__tmp), "=m" (*(ptr)) \ 2418c2ecf20Sopenharmony_ci : "rJ" (__x), "i" (-EFAULT)); \ 2428c2ecf20Sopenharmony_ci} while (0) 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 2458c2ecf20Sopenharmony_ci#define __put_user_8(x, ptr, err) \ 2468c2ecf20Sopenharmony_ci __put_user_asm("sd", x, ptr, err) 2478c2ecf20Sopenharmony_ci#else /* !CONFIG_64BIT */ 2488c2ecf20Sopenharmony_ci#define __put_user_8(x, ptr, err) \ 2498c2ecf20Sopenharmony_cido { \ 2508c2ecf20Sopenharmony_ci u32 __user *__ptr = (u32 __user *)(ptr); \ 2518c2ecf20Sopenharmony_ci u64 __x = (__typeof__((x)-(x)))(x); \ 2528c2ecf20Sopenharmony_ci uintptr_t __tmp; \ 2538c2ecf20Sopenharmony_ci __asm__ __volatile__ ( \ 2548c2ecf20Sopenharmony_ci "1:\n" \ 2558c2ecf20Sopenharmony_ci " sw %z4, %2\n" \ 2568c2ecf20Sopenharmony_ci "2:\n" \ 2578c2ecf20Sopenharmony_ci " sw %z5, %3\n" \ 2588c2ecf20Sopenharmony_ci "3:\n" \ 2598c2ecf20Sopenharmony_ci " .section .fixup,\"ax\"\n" \ 2608c2ecf20Sopenharmony_ci " .balign 4\n" \ 2618c2ecf20Sopenharmony_ci "4:\n" \ 2628c2ecf20Sopenharmony_ci " li %0, %6\n" \ 2638c2ecf20Sopenharmony_ci " jump 3b, %1\n" \ 2648c2ecf20Sopenharmony_ci " .previous\n" \ 2658c2ecf20Sopenharmony_ci " .section __ex_table,\"a\"\n" \ 2668c2ecf20Sopenharmony_ci " .balign " RISCV_SZPTR "\n" \ 2678c2ecf20Sopenharmony_ci " " RISCV_PTR " 1b, 4b\n" \ 2688c2ecf20Sopenharmony_ci " " RISCV_PTR " 2b, 4b\n" \ 2698c2ecf20Sopenharmony_ci " .previous" \ 2708c2ecf20Sopenharmony_ci : "+r" (err), "=r" (__tmp), \ 2718c2ecf20Sopenharmony_ci "=m" (__ptr[__LSW]), \ 2728c2ecf20Sopenharmony_ci "=m" (__ptr[__MSW]) \ 2738c2ecf20Sopenharmony_ci : "rJ" (__x), "rJ" (__x >> 32), "i" (-EFAULT)); \ 2748c2ecf20Sopenharmony_ci} while (0) 2758c2ecf20Sopenharmony_ci#endif /* CONFIG_64BIT */ 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci#define __put_user_nocheck(x, __gu_ptr, __pu_err) \ 2788c2ecf20Sopenharmony_cido { \ 2798c2ecf20Sopenharmony_ci switch (sizeof(*__gu_ptr)) { \ 2808c2ecf20Sopenharmony_ci case 1: \ 2818c2ecf20Sopenharmony_ci __put_user_asm("sb", (x), __gu_ptr, __pu_err); \ 2828c2ecf20Sopenharmony_ci break; \ 2838c2ecf20Sopenharmony_ci case 2: \ 2848c2ecf20Sopenharmony_ci __put_user_asm("sh", (x), __gu_ptr, __pu_err); \ 2858c2ecf20Sopenharmony_ci break; \ 2868c2ecf20Sopenharmony_ci case 4: \ 2878c2ecf20Sopenharmony_ci __put_user_asm("sw", (x), __gu_ptr, __pu_err); \ 2888c2ecf20Sopenharmony_ci break; \ 2898c2ecf20Sopenharmony_ci case 8: \ 2908c2ecf20Sopenharmony_ci __put_user_8((x), __gu_ptr, __pu_err); \ 2918c2ecf20Sopenharmony_ci break; \ 2928c2ecf20Sopenharmony_ci default: \ 2938c2ecf20Sopenharmony_ci BUILD_BUG(); \ 2948c2ecf20Sopenharmony_ci } \ 2958c2ecf20Sopenharmony_ci} while (0) 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci/** 2988c2ecf20Sopenharmony_ci * __put_user: - Write a simple value into user space, with less checking. 2998c2ecf20Sopenharmony_ci * @x: Value to copy to user space. 3008c2ecf20Sopenharmony_ci * @ptr: Destination address, in user space. 3018c2ecf20Sopenharmony_ci * 3028c2ecf20Sopenharmony_ci * Context: User context only. This function may sleep. 3038c2ecf20Sopenharmony_ci * 3048c2ecf20Sopenharmony_ci * This macro copies a single simple value from kernel space to user 3058c2ecf20Sopenharmony_ci * space. It supports simple types like char and int, but not larger 3068c2ecf20Sopenharmony_ci * data types like structures or arrays. 3078c2ecf20Sopenharmony_ci * 3088c2ecf20Sopenharmony_ci * @ptr must have pointer-to-simple-variable type, and @x must be assignable 3098c2ecf20Sopenharmony_ci * to the result of dereferencing @ptr. The value of @x is copied to avoid 3108c2ecf20Sopenharmony_ci * re-ordering where @x is evaluated inside the block that enables user-space 3118c2ecf20Sopenharmony_ci * access (thus bypassing user space protection if @x is a function). 3128c2ecf20Sopenharmony_ci * 3138c2ecf20Sopenharmony_ci * Caller must check the pointer with access_ok() before calling this 3148c2ecf20Sopenharmony_ci * function. 3158c2ecf20Sopenharmony_ci * 3168c2ecf20Sopenharmony_ci * Returns zero on success, or -EFAULT on error. 3178c2ecf20Sopenharmony_ci */ 3188c2ecf20Sopenharmony_ci#define __put_user(x, ptr) \ 3198c2ecf20Sopenharmony_ci({ \ 3208c2ecf20Sopenharmony_ci __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ 3218c2ecf20Sopenharmony_ci __typeof__(*__gu_ptr) __val = (x); \ 3228c2ecf20Sopenharmony_ci long __pu_err = 0; \ 3238c2ecf20Sopenharmony_ci \ 3248c2ecf20Sopenharmony_ci __chk_user_ptr(__gu_ptr); \ 3258c2ecf20Sopenharmony_ci \ 3268c2ecf20Sopenharmony_ci __enable_user_access(); \ 3278c2ecf20Sopenharmony_ci __put_user_nocheck(__val, __gu_ptr, __pu_err); \ 3288c2ecf20Sopenharmony_ci __disable_user_access(); \ 3298c2ecf20Sopenharmony_ci \ 3308c2ecf20Sopenharmony_ci __pu_err; \ 3318c2ecf20Sopenharmony_ci}) 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci/** 3348c2ecf20Sopenharmony_ci * put_user: - Write a simple value into user space. 3358c2ecf20Sopenharmony_ci * @x: Value to copy to user space. 3368c2ecf20Sopenharmony_ci * @ptr: Destination address, in user space. 3378c2ecf20Sopenharmony_ci * 3388c2ecf20Sopenharmony_ci * Context: User context only. This function may sleep. 3398c2ecf20Sopenharmony_ci * 3408c2ecf20Sopenharmony_ci * This macro copies a single simple value from kernel space to user 3418c2ecf20Sopenharmony_ci * space. It supports simple types like char and int, but not larger 3428c2ecf20Sopenharmony_ci * data types like structures or arrays. 3438c2ecf20Sopenharmony_ci * 3448c2ecf20Sopenharmony_ci * @ptr must have pointer-to-simple-variable type, and @x must be assignable 3458c2ecf20Sopenharmony_ci * to the result of dereferencing @ptr. 3468c2ecf20Sopenharmony_ci * 3478c2ecf20Sopenharmony_ci * Returns zero on success, or -EFAULT on error. 3488c2ecf20Sopenharmony_ci */ 3498c2ecf20Sopenharmony_ci#define put_user(x, ptr) \ 3508c2ecf20Sopenharmony_ci({ \ 3518c2ecf20Sopenharmony_ci __typeof__(*(ptr)) __user *__p = (ptr); \ 3528c2ecf20Sopenharmony_ci might_fault(); \ 3538c2ecf20Sopenharmony_ci access_ok(__p, sizeof(*__p)) ? \ 3548c2ecf20Sopenharmony_ci __put_user((x), __p) : \ 3558c2ecf20Sopenharmony_ci -EFAULT; \ 3568c2ecf20Sopenharmony_ci}) 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ciunsigned long __must_check __asm_copy_to_user(void __user *to, 3608c2ecf20Sopenharmony_ci const void *from, unsigned long n); 3618c2ecf20Sopenharmony_ciunsigned long __must_check __asm_copy_from_user(void *to, 3628c2ecf20Sopenharmony_ci const void __user *from, unsigned long n); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic inline unsigned long 3658c2ecf20Sopenharmony_ciraw_copy_from_user(void *to, const void __user *from, unsigned long n) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci return __asm_copy_from_user(to, from, n); 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_cistatic inline unsigned long 3718c2ecf20Sopenharmony_ciraw_copy_to_user(void __user *to, const void *from, unsigned long n) 3728c2ecf20Sopenharmony_ci{ 3738c2ecf20Sopenharmony_ci return __asm_copy_to_user(to, from, n); 3748c2ecf20Sopenharmony_ci} 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ciextern long strncpy_from_user(char *dest, const char __user *src, long count); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ciextern long __must_check strlen_user(const char __user *str); 3798c2ecf20Sopenharmony_ciextern long __must_check strnlen_user(const char __user *str, long n); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ciextern 3828c2ecf20Sopenharmony_ciunsigned long __must_check __clear_user(void __user *addr, unsigned long n); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_cistatic inline 3858c2ecf20Sopenharmony_ciunsigned long __must_check clear_user(void __user *to, unsigned long n) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci might_fault(); 3888c2ecf20Sopenharmony_ci return access_ok(to, n) ? 3898c2ecf20Sopenharmony_ci __clear_user(to, n) : n; 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci/* 3938c2ecf20Sopenharmony_ci * Atomic compare-and-exchange, but with a fixup for userspace faults. Faults 3948c2ecf20Sopenharmony_ci * will set "err" to -EFAULT, while successful accesses return the previous 3958c2ecf20Sopenharmony_ci * value. 3968c2ecf20Sopenharmony_ci */ 3978c2ecf20Sopenharmony_ci#define __cmpxchg_user(ptr, old, new, err, size, lrb, scb) \ 3988c2ecf20Sopenharmony_ci({ \ 3998c2ecf20Sopenharmony_ci __typeof__(ptr) __ptr = (ptr); \ 4008c2ecf20Sopenharmony_ci __typeof__(*(ptr)) __old = (old); \ 4018c2ecf20Sopenharmony_ci __typeof__(*(ptr)) __new = (new); \ 4028c2ecf20Sopenharmony_ci __typeof__(*(ptr)) __ret; \ 4038c2ecf20Sopenharmony_ci __typeof__(err) __err = 0; \ 4048c2ecf20Sopenharmony_ci register unsigned int __rc; \ 4058c2ecf20Sopenharmony_ci __enable_user_access(); \ 4068c2ecf20Sopenharmony_ci switch (size) { \ 4078c2ecf20Sopenharmony_ci case 4: \ 4088c2ecf20Sopenharmony_ci __asm__ __volatile__ ( \ 4098c2ecf20Sopenharmony_ci "0:\n" \ 4108c2ecf20Sopenharmony_ci " lr.w" #scb " %[ret], %[ptr]\n" \ 4118c2ecf20Sopenharmony_ci " bne %[ret], %z[old], 1f\n" \ 4128c2ecf20Sopenharmony_ci " sc.w" #lrb " %[rc], %z[new], %[ptr]\n" \ 4138c2ecf20Sopenharmony_ci " bnez %[rc], 0b\n" \ 4148c2ecf20Sopenharmony_ci "1:\n" \ 4158c2ecf20Sopenharmony_ci ".section .fixup,\"ax\"\n" \ 4168c2ecf20Sopenharmony_ci ".balign 4\n" \ 4178c2ecf20Sopenharmony_ci "2:\n" \ 4188c2ecf20Sopenharmony_ci " li %[err], %[efault]\n" \ 4198c2ecf20Sopenharmony_ci " jump 1b, %[rc]\n" \ 4208c2ecf20Sopenharmony_ci ".previous\n" \ 4218c2ecf20Sopenharmony_ci ".section __ex_table,\"a\"\n" \ 4228c2ecf20Sopenharmony_ci ".balign " RISCV_SZPTR "\n" \ 4238c2ecf20Sopenharmony_ci " " RISCV_PTR " 1b, 2b\n" \ 4248c2ecf20Sopenharmony_ci ".previous\n" \ 4258c2ecf20Sopenharmony_ci : [ret] "=&r" (__ret), \ 4268c2ecf20Sopenharmony_ci [rc] "=&r" (__rc), \ 4278c2ecf20Sopenharmony_ci [ptr] "+A" (*__ptr), \ 4288c2ecf20Sopenharmony_ci [err] "=&r" (__err) \ 4298c2ecf20Sopenharmony_ci : [old] "rJ" (__old), \ 4308c2ecf20Sopenharmony_ci [new] "rJ" (__new), \ 4318c2ecf20Sopenharmony_ci [efault] "i" (-EFAULT)); \ 4328c2ecf20Sopenharmony_ci break; \ 4338c2ecf20Sopenharmony_ci case 8: \ 4348c2ecf20Sopenharmony_ci __asm__ __volatile__ ( \ 4358c2ecf20Sopenharmony_ci "0:\n" \ 4368c2ecf20Sopenharmony_ci " lr.d" #scb " %[ret], %[ptr]\n" \ 4378c2ecf20Sopenharmony_ci " bne %[ret], %z[old], 1f\n" \ 4388c2ecf20Sopenharmony_ci " sc.d" #lrb " %[rc], %z[new], %[ptr]\n" \ 4398c2ecf20Sopenharmony_ci " bnez %[rc], 0b\n" \ 4408c2ecf20Sopenharmony_ci "1:\n" \ 4418c2ecf20Sopenharmony_ci ".section .fixup,\"ax\"\n" \ 4428c2ecf20Sopenharmony_ci ".balign 4\n" \ 4438c2ecf20Sopenharmony_ci "2:\n" \ 4448c2ecf20Sopenharmony_ci " li %[err], %[efault]\n" \ 4458c2ecf20Sopenharmony_ci " jump 1b, %[rc]\n" \ 4468c2ecf20Sopenharmony_ci ".previous\n" \ 4478c2ecf20Sopenharmony_ci ".section __ex_table,\"a\"\n" \ 4488c2ecf20Sopenharmony_ci ".balign " RISCV_SZPTR "\n" \ 4498c2ecf20Sopenharmony_ci " " RISCV_PTR " 1b, 2b\n" \ 4508c2ecf20Sopenharmony_ci ".previous\n" \ 4518c2ecf20Sopenharmony_ci : [ret] "=&r" (__ret), \ 4528c2ecf20Sopenharmony_ci [rc] "=&r" (__rc), \ 4538c2ecf20Sopenharmony_ci [ptr] "+A" (*__ptr), \ 4548c2ecf20Sopenharmony_ci [err] "=&r" (__err) \ 4558c2ecf20Sopenharmony_ci : [old] "rJ" (__old), \ 4568c2ecf20Sopenharmony_ci [new] "rJ" (__new), \ 4578c2ecf20Sopenharmony_ci [efault] "i" (-EFAULT)); \ 4588c2ecf20Sopenharmony_ci break; \ 4598c2ecf20Sopenharmony_ci default: \ 4608c2ecf20Sopenharmony_ci BUILD_BUG(); \ 4618c2ecf20Sopenharmony_ci } \ 4628c2ecf20Sopenharmony_ci __disable_user_access(); \ 4638c2ecf20Sopenharmony_ci (err) = __err; \ 4648c2ecf20Sopenharmony_ci __ret; \ 4658c2ecf20Sopenharmony_ci}) 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci#define HAVE_GET_KERNEL_NOFAULT 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci#define __get_kernel_nofault(dst, src, type, err_label) \ 4708c2ecf20Sopenharmony_cido { \ 4718c2ecf20Sopenharmony_ci long __kr_err; \ 4728c2ecf20Sopenharmony_ci \ 4738c2ecf20Sopenharmony_ci __get_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err); \ 4748c2ecf20Sopenharmony_ci if (unlikely(__kr_err)) \ 4758c2ecf20Sopenharmony_ci goto err_label; \ 4768c2ecf20Sopenharmony_ci} while (0) 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci#define __put_kernel_nofault(dst, src, type, err_label) \ 4798c2ecf20Sopenharmony_cido { \ 4808c2ecf20Sopenharmony_ci long __kr_err; \ 4818c2ecf20Sopenharmony_ci \ 4828c2ecf20Sopenharmony_ci __put_user_nocheck(*((type *)(src)), (type *)(dst), __kr_err); \ 4838c2ecf20Sopenharmony_ci if (unlikely(__kr_err)) \ 4848c2ecf20Sopenharmony_ci goto err_label; \ 4858c2ecf20Sopenharmony_ci} while (0) 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci#else /* CONFIG_MMU */ 4888c2ecf20Sopenharmony_ci#include <asm-generic/uaccess.h> 4898c2ecf20Sopenharmony_ci#endif /* CONFIG_MMU */ 4908c2ecf20Sopenharmony_ci#endif /* _ASM_RISCV_UACCESS_H */ 491