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