162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  arch/arm/include/asm/uaccess.h
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#ifndef _ASMARM_UACCESS_H
662306a36Sopenharmony_ci#define _ASMARM_UACCESS_H
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci/*
962306a36Sopenharmony_ci * User space memory access functions
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci#include <linux/string.h>
1262306a36Sopenharmony_ci#include <asm/page.h>
1362306a36Sopenharmony_ci#include <asm/domain.h>
1462306a36Sopenharmony_ci#include <asm/unaligned.h>
1562306a36Sopenharmony_ci#include <asm/unified.h>
1662306a36Sopenharmony_ci#include <asm/compiler.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include <asm/extable.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/*
2162306a36Sopenharmony_ci * These two functions allow hooking accesses to userspace to increase
2262306a36Sopenharmony_ci * system integrity by ensuring that the kernel can not inadvertantly
2362306a36Sopenharmony_ci * perform such accesses (eg, via list poison values) which could then
2462306a36Sopenharmony_ci * be exploited for priviledge escalation.
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_cistatic __always_inline unsigned int uaccess_save_and_enable(void)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci#ifdef CONFIG_CPU_SW_DOMAIN_PAN
2962306a36Sopenharmony_ci	unsigned int old_domain = get_domain();
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	/* Set the current domain access to permit user accesses */
3262306a36Sopenharmony_ci	set_domain((old_domain & ~domain_mask(DOMAIN_USER)) |
3362306a36Sopenharmony_ci		   domain_val(DOMAIN_USER, DOMAIN_CLIENT));
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	return old_domain;
3662306a36Sopenharmony_ci#else
3762306a36Sopenharmony_ci	return 0;
3862306a36Sopenharmony_ci#endif
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic __always_inline void uaccess_restore(unsigned int flags)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci#ifdef CONFIG_CPU_SW_DOMAIN_PAN
4462306a36Sopenharmony_ci	/* Restore the user access mask */
4562306a36Sopenharmony_ci	set_domain(flags);
4662306a36Sopenharmony_ci#endif
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/*
5062306a36Sopenharmony_ci * These two are intentionally not defined anywhere - if the kernel
5162306a36Sopenharmony_ci * code generates any references to them, that's a bug.
5262306a36Sopenharmony_ci */
5362306a36Sopenharmony_ciextern int __get_user_bad(void);
5462306a36Sopenharmony_ciextern int __put_user_bad(void);
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#ifdef CONFIG_MMU
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/*
5962306a36Sopenharmony_ci * This is a type: either unsigned long, if the argument fits into
6062306a36Sopenharmony_ci * that type, or otherwise unsigned long long.
6162306a36Sopenharmony_ci */
6262306a36Sopenharmony_ci#define __inttype(x) \
6362306a36Sopenharmony_ci	__typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci/*
6662306a36Sopenharmony_ci * Sanitise a uaccess pointer such that it becomes NULL if addr+size
6762306a36Sopenharmony_ci * is above the current addr_limit.
6862306a36Sopenharmony_ci */
6962306a36Sopenharmony_ci#define uaccess_mask_range_ptr(ptr, size)			\
7062306a36Sopenharmony_ci	((__typeof__(ptr))__uaccess_mask_range_ptr(ptr, size))
7162306a36Sopenharmony_cistatic inline void __user *__uaccess_mask_range_ptr(const void __user *ptr,
7262306a36Sopenharmony_ci						    size_t size)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	void __user *safe_ptr = (void __user *)ptr;
7562306a36Sopenharmony_ci	unsigned long tmp;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	asm volatile(
7862306a36Sopenharmony_ci	"	.syntax unified\n"
7962306a36Sopenharmony_ci	"	sub	%1, %3, #1\n"
8062306a36Sopenharmony_ci	"	subs	%1, %1, %0\n"
8162306a36Sopenharmony_ci	"	addhs	%1, %1, #1\n"
8262306a36Sopenharmony_ci	"	subshs	%1, %1, %2\n"
8362306a36Sopenharmony_ci	"	movlo	%0, #0\n"
8462306a36Sopenharmony_ci	: "+r" (safe_ptr), "=&r" (tmp)
8562306a36Sopenharmony_ci	: "r" (size), "r" (TASK_SIZE)
8662306a36Sopenharmony_ci	: "cc");
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	csdb();
8962306a36Sopenharmony_ci	return safe_ptr;
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci/*
9362306a36Sopenharmony_ci * Single-value transfer routines.  They automatically use the right
9462306a36Sopenharmony_ci * size if we just have the right pointer type.  Note that the functions
9562306a36Sopenharmony_ci * which read from user space (*get_*) need to take care not to leak
9662306a36Sopenharmony_ci * kernel data even if the calling code is buggy and fails to check
9762306a36Sopenharmony_ci * the return value.  This means zeroing out the destination variable
9862306a36Sopenharmony_ci * or buffer on error.  Normally this is done out of line by the
9962306a36Sopenharmony_ci * fixup code, but there are a few places where it intrudes on the
10062306a36Sopenharmony_ci * main code path.  When we only write to user space, there is no
10162306a36Sopenharmony_ci * problem.
10262306a36Sopenharmony_ci */
10362306a36Sopenharmony_ciextern int __get_user_1(void *);
10462306a36Sopenharmony_ciextern int __get_user_2(void *);
10562306a36Sopenharmony_ciextern int __get_user_4(void *);
10662306a36Sopenharmony_ciextern int __get_user_32t_8(void *);
10762306a36Sopenharmony_ciextern int __get_user_8(void *);
10862306a36Sopenharmony_ciextern int __get_user_64t_1(void *);
10962306a36Sopenharmony_ciextern int __get_user_64t_2(void *);
11062306a36Sopenharmony_ciextern int __get_user_64t_4(void *);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci#define __GUP_CLOBBER_1	"lr", "cc"
11362306a36Sopenharmony_ci#ifdef CONFIG_CPU_USE_DOMAINS
11462306a36Sopenharmony_ci#define __GUP_CLOBBER_2	"ip", "lr", "cc"
11562306a36Sopenharmony_ci#else
11662306a36Sopenharmony_ci#define __GUP_CLOBBER_2 "lr", "cc"
11762306a36Sopenharmony_ci#endif
11862306a36Sopenharmony_ci#define __GUP_CLOBBER_4	"lr", "cc"
11962306a36Sopenharmony_ci#define __GUP_CLOBBER_32t_8 "lr", "cc"
12062306a36Sopenharmony_ci#define __GUP_CLOBBER_8	"lr", "cc"
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci#define __get_user_x(__r2, __p, __e, __l, __s)				\
12362306a36Sopenharmony_ci	   __asm__ __volatile__ (					\
12462306a36Sopenharmony_ci		__asmeq("%0", "r0") __asmeq("%1", "r2")			\
12562306a36Sopenharmony_ci		__asmeq("%3", "r1")					\
12662306a36Sopenharmony_ci		"bl	__get_user_" #__s				\
12762306a36Sopenharmony_ci		: "=&r" (__e), "=r" (__r2)				\
12862306a36Sopenharmony_ci		: "0" (__p), "r" (__l)					\
12962306a36Sopenharmony_ci		: __GUP_CLOBBER_##__s)
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci/* narrowing a double-word get into a single 32bit word register: */
13262306a36Sopenharmony_ci#ifdef __ARMEB__
13362306a36Sopenharmony_ci#define __get_user_x_32t(__r2, __p, __e, __l, __s)			\
13462306a36Sopenharmony_ci	__get_user_x(__r2, __p, __e, __l, 32t_8)
13562306a36Sopenharmony_ci#else
13662306a36Sopenharmony_ci#define __get_user_x_32t __get_user_x
13762306a36Sopenharmony_ci#endif
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci/*
14062306a36Sopenharmony_ci * storing result into proper least significant word of 64bit target var,
14162306a36Sopenharmony_ci * different only for big endian case where 64 bit __r2 lsw is r3:
14262306a36Sopenharmony_ci */
14362306a36Sopenharmony_ci#ifdef __ARMEB__
14462306a36Sopenharmony_ci#define __get_user_x_64t(__r2, __p, __e, __l, __s)		        \
14562306a36Sopenharmony_ci	   __asm__ __volatile__ (					\
14662306a36Sopenharmony_ci		__asmeq("%0", "r0") __asmeq("%1", "r2")			\
14762306a36Sopenharmony_ci		__asmeq("%3", "r1")					\
14862306a36Sopenharmony_ci		"bl	__get_user_64t_" #__s				\
14962306a36Sopenharmony_ci		: "=&r" (__e), "=r" (__r2)				\
15062306a36Sopenharmony_ci		: "0" (__p), "r" (__l)					\
15162306a36Sopenharmony_ci		: __GUP_CLOBBER_##__s)
15262306a36Sopenharmony_ci#else
15362306a36Sopenharmony_ci#define __get_user_x_64t __get_user_x
15462306a36Sopenharmony_ci#endif
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci#define __get_user_check(x, p)						\
15862306a36Sopenharmony_ci	({								\
15962306a36Sopenharmony_ci		unsigned long __limit = TASK_SIZE - 1; \
16062306a36Sopenharmony_ci		register typeof(*(p)) __user *__p asm("r0") = (p);	\
16162306a36Sopenharmony_ci		register __inttype(x) __r2 asm("r2");			\
16262306a36Sopenharmony_ci		register unsigned long __l asm("r1") = __limit;		\
16362306a36Sopenharmony_ci		register int __e asm("r0");				\
16462306a36Sopenharmony_ci		unsigned int __ua_flags = uaccess_save_and_enable();	\
16562306a36Sopenharmony_ci		int __tmp_e;						\
16662306a36Sopenharmony_ci		switch (sizeof(*(__p))) {				\
16762306a36Sopenharmony_ci		case 1:							\
16862306a36Sopenharmony_ci			if (sizeof((x)) >= 8)				\
16962306a36Sopenharmony_ci				__get_user_x_64t(__r2, __p, __e, __l, 1); \
17062306a36Sopenharmony_ci			else						\
17162306a36Sopenharmony_ci				__get_user_x(__r2, __p, __e, __l, 1);	\
17262306a36Sopenharmony_ci			break;						\
17362306a36Sopenharmony_ci		case 2:							\
17462306a36Sopenharmony_ci			if (sizeof((x)) >= 8)				\
17562306a36Sopenharmony_ci				__get_user_x_64t(__r2, __p, __e, __l, 2); \
17662306a36Sopenharmony_ci			else						\
17762306a36Sopenharmony_ci				__get_user_x(__r2, __p, __e, __l, 2);	\
17862306a36Sopenharmony_ci			break;						\
17962306a36Sopenharmony_ci		case 4:							\
18062306a36Sopenharmony_ci			if (sizeof((x)) >= 8)				\
18162306a36Sopenharmony_ci				__get_user_x_64t(__r2, __p, __e, __l, 4); \
18262306a36Sopenharmony_ci			else						\
18362306a36Sopenharmony_ci				__get_user_x(__r2, __p, __e, __l, 4);	\
18462306a36Sopenharmony_ci			break;						\
18562306a36Sopenharmony_ci		case 8:							\
18662306a36Sopenharmony_ci			if (sizeof((x)) < 8)				\
18762306a36Sopenharmony_ci				__get_user_x_32t(__r2, __p, __e, __l, 4); \
18862306a36Sopenharmony_ci			else						\
18962306a36Sopenharmony_ci				__get_user_x(__r2, __p, __e, __l, 8);	\
19062306a36Sopenharmony_ci			break;						\
19162306a36Sopenharmony_ci		default: __e = __get_user_bad(); break;			\
19262306a36Sopenharmony_ci		}							\
19362306a36Sopenharmony_ci		__tmp_e = __e;						\
19462306a36Sopenharmony_ci		uaccess_restore(__ua_flags);				\
19562306a36Sopenharmony_ci		x = (typeof(*(p))) __r2;				\
19662306a36Sopenharmony_ci		__tmp_e;						\
19762306a36Sopenharmony_ci	})
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci#define get_user(x, p)							\
20062306a36Sopenharmony_ci	({								\
20162306a36Sopenharmony_ci		might_fault();						\
20262306a36Sopenharmony_ci		__get_user_check(x, p);					\
20362306a36Sopenharmony_ci	 })
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ciextern int __put_user_1(void *, unsigned int);
20662306a36Sopenharmony_ciextern int __put_user_2(void *, unsigned int);
20762306a36Sopenharmony_ciextern int __put_user_4(void *, unsigned int);
20862306a36Sopenharmony_ciextern int __put_user_8(void *, unsigned long long);
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci#define __put_user_check(__pu_val, __ptr, __err, __s)			\
21162306a36Sopenharmony_ci	({								\
21262306a36Sopenharmony_ci		unsigned long __limit = TASK_SIZE - 1; \
21362306a36Sopenharmony_ci		register typeof(__pu_val) __r2 asm("r2") = __pu_val;	\
21462306a36Sopenharmony_ci		register const void __user *__p asm("r0") = __ptr;	\
21562306a36Sopenharmony_ci		register unsigned long __l asm("r1") = __limit;		\
21662306a36Sopenharmony_ci		register int __e asm("r0");				\
21762306a36Sopenharmony_ci		__asm__ __volatile__ (					\
21862306a36Sopenharmony_ci			__asmeq("%0", "r0") __asmeq("%2", "r2")		\
21962306a36Sopenharmony_ci			__asmeq("%3", "r1")				\
22062306a36Sopenharmony_ci			"bl	__put_user_" #__s			\
22162306a36Sopenharmony_ci			: "=&r" (__e)					\
22262306a36Sopenharmony_ci			: "0" (__p), "r" (__r2), "r" (__l)		\
22362306a36Sopenharmony_ci			: "ip", "lr", "cc");				\
22462306a36Sopenharmony_ci		__err = __e;						\
22562306a36Sopenharmony_ci	})
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci#else /* CONFIG_MMU */
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci#define get_user(x, p)	__get_user(x, p)
23062306a36Sopenharmony_ci#define __put_user_check __put_user_nocheck
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci#endif /* CONFIG_MMU */
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci#include <asm-generic/access_ok.h>
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci#ifdef CONFIG_CPU_SPECTRE
23762306a36Sopenharmony_ci/*
23862306a36Sopenharmony_ci * When mitigating Spectre variant 1, it is not worth fixing the non-
23962306a36Sopenharmony_ci * verifying accessors, because we need to add verification of the
24062306a36Sopenharmony_ci * address space there.  Force these to use the standard get_user()
24162306a36Sopenharmony_ci * version instead.
24262306a36Sopenharmony_ci */
24362306a36Sopenharmony_ci#define __get_user(x, ptr) get_user(x, ptr)
24462306a36Sopenharmony_ci#else
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci/*
24762306a36Sopenharmony_ci * The "__xxx" versions of the user access functions do not verify the
24862306a36Sopenharmony_ci * address space - it must have been done previously with a separate
24962306a36Sopenharmony_ci * "access_ok()" call.
25062306a36Sopenharmony_ci *
25162306a36Sopenharmony_ci * The "xxx_error" versions set the third argument to EFAULT if an
25262306a36Sopenharmony_ci * error occurs, and leave it unchanged on success.  Note that these
25362306a36Sopenharmony_ci * versions are void (ie, don't return a value as such).
25462306a36Sopenharmony_ci */
25562306a36Sopenharmony_ci#define __get_user(x, ptr)						\
25662306a36Sopenharmony_ci({									\
25762306a36Sopenharmony_ci	long __gu_err = 0;						\
25862306a36Sopenharmony_ci	__get_user_err((x), (ptr), __gu_err, TUSER());			\
25962306a36Sopenharmony_ci	__gu_err;							\
26062306a36Sopenharmony_ci})
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci#define __get_user_err(x, ptr, err, __t)				\
26362306a36Sopenharmony_cido {									\
26462306a36Sopenharmony_ci	unsigned long __gu_addr = (unsigned long)(ptr);			\
26562306a36Sopenharmony_ci	unsigned long __gu_val;						\
26662306a36Sopenharmony_ci	unsigned int __ua_flags;					\
26762306a36Sopenharmony_ci	__chk_user_ptr(ptr);						\
26862306a36Sopenharmony_ci	might_fault();							\
26962306a36Sopenharmony_ci	__ua_flags = uaccess_save_and_enable();				\
27062306a36Sopenharmony_ci	switch (sizeof(*(ptr))) {					\
27162306a36Sopenharmony_ci	case 1:	__get_user_asm_byte(__gu_val, __gu_addr, err, __t); break;	\
27262306a36Sopenharmony_ci	case 2:	__get_user_asm_half(__gu_val, __gu_addr, err, __t); break;	\
27362306a36Sopenharmony_ci	case 4:	__get_user_asm_word(__gu_val, __gu_addr, err, __t); break;	\
27462306a36Sopenharmony_ci	default: (__gu_val) = __get_user_bad();				\
27562306a36Sopenharmony_ci	}								\
27662306a36Sopenharmony_ci	uaccess_restore(__ua_flags);					\
27762306a36Sopenharmony_ci	(x) = (__typeof__(*(ptr)))__gu_val;				\
27862306a36Sopenharmony_ci} while (0)
27962306a36Sopenharmony_ci#endif
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci#define __get_user_asm(x, addr, err, instr)			\
28262306a36Sopenharmony_ci	__asm__ __volatile__(					\
28362306a36Sopenharmony_ci	"1:	" instr " %1, [%2], #0\n"			\
28462306a36Sopenharmony_ci	"2:\n"							\
28562306a36Sopenharmony_ci	"	.pushsection .text.fixup,\"ax\"\n"		\
28662306a36Sopenharmony_ci	"	.align	2\n"					\
28762306a36Sopenharmony_ci	"3:	mov	%0, %3\n"				\
28862306a36Sopenharmony_ci	"	mov	%1, #0\n"				\
28962306a36Sopenharmony_ci	"	b	2b\n"					\
29062306a36Sopenharmony_ci	"	.popsection\n"					\
29162306a36Sopenharmony_ci	"	.pushsection __ex_table,\"a\"\n"		\
29262306a36Sopenharmony_ci	"	.align	3\n"					\
29362306a36Sopenharmony_ci	"	.long	1b, 3b\n"				\
29462306a36Sopenharmony_ci	"	.popsection"					\
29562306a36Sopenharmony_ci	: "+r" (err), "=&r" (x)					\
29662306a36Sopenharmony_ci	: "r" (addr), "i" (-EFAULT)				\
29762306a36Sopenharmony_ci	: "cc")
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci#define __get_user_asm_byte(x, addr, err, __t)			\
30062306a36Sopenharmony_ci	__get_user_asm(x, addr, err, "ldrb" __t)
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 6
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci#define __get_user_asm_half(x, addr, err, __t)			\
30562306a36Sopenharmony_ci	__get_user_asm(x, addr, err, "ldrh" __t)
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci#else
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci#ifndef __ARMEB__
31062306a36Sopenharmony_ci#define __get_user_asm_half(x, __gu_addr, err, __t)		\
31162306a36Sopenharmony_ci({								\
31262306a36Sopenharmony_ci	unsigned long __b1, __b2;				\
31362306a36Sopenharmony_ci	__get_user_asm_byte(__b1, __gu_addr, err, __t);		\
31462306a36Sopenharmony_ci	__get_user_asm_byte(__b2, __gu_addr + 1, err, __t);	\
31562306a36Sopenharmony_ci	(x) = __b1 | (__b2 << 8);				\
31662306a36Sopenharmony_ci})
31762306a36Sopenharmony_ci#else
31862306a36Sopenharmony_ci#define __get_user_asm_half(x, __gu_addr, err, __t)		\
31962306a36Sopenharmony_ci({								\
32062306a36Sopenharmony_ci	unsigned long __b1, __b2;				\
32162306a36Sopenharmony_ci	__get_user_asm_byte(__b1, __gu_addr, err, __t);		\
32262306a36Sopenharmony_ci	__get_user_asm_byte(__b2, __gu_addr + 1, err, __t);	\
32362306a36Sopenharmony_ci	(x) = (__b1 << 8) | __b2;				\
32462306a36Sopenharmony_ci})
32562306a36Sopenharmony_ci#endif
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci#endif /* __LINUX_ARM_ARCH__ >= 6 */
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci#define __get_user_asm_word(x, addr, err, __t)			\
33062306a36Sopenharmony_ci	__get_user_asm(x, addr, err, "ldr" __t)
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci#define __put_user_switch(x, ptr, __err, __fn)				\
33362306a36Sopenharmony_ci	do {								\
33462306a36Sopenharmony_ci		const __typeof__(*(ptr)) __user *__pu_ptr = (ptr);	\
33562306a36Sopenharmony_ci		__typeof__(*(ptr)) __pu_val = (x);			\
33662306a36Sopenharmony_ci		unsigned int __ua_flags;				\
33762306a36Sopenharmony_ci		might_fault();						\
33862306a36Sopenharmony_ci		__ua_flags = uaccess_save_and_enable();			\
33962306a36Sopenharmony_ci		switch (sizeof(*(ptr))) {				\
34062306a36Sopenharmony_ci		case 1: __fn(__pu_val, __pu_ptr, __err, 1); break;	\
34162306a36Sopenharmony_ci		case 2:	__fn(__pu_val, __pu_ptr, __err, 2); break;	\
34262306a36Sopenharmony_ci		case 4:	__fn(__pu_val, __pu_ptr, __err, 4); break;	\
34362306a36Sopenharmony_ci		case 8:	__fn(__pu_val, __pu_ptr, __err, 8); break;	\
34462306a36Sopenharmony_ci		default: __err = __put_user_bad(); break;		\
34562306a36Sopenharmony_ci		}							\
34662306a36Sopenharmony_ci		uaccess_restore(__ua_flags);				\
34762306a36Sopenharmony_ci	} while (0)
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci#define put_user(x, ptr)						\
35062306a36Sopenharmony_ci({									\
35162306a36Sopenharmony_ci	int __pu_err = 0;						\
35262306a36Sopenharmony_ci	__put_user_switch((x), (ptr), __pu_err, __put_user_check);	\
35362306a36Sopenharmony_ci	__pu_err;							\
35462306a36Sopenharmony_ci})
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci#ifdef CONFIG_CPU_SPECTRE
35762306a36Sopenharmony_ci/*
35862306a36Sopenharmony_ci * When mitigating Spectre variant 1.1, all accessors need to include
35962306a36Sopenharmony_ci * verification of the address space.
36062306a36Sopenharmony_ci */
36162306a36Sopenharmony_ci#define __put_user(x, ptr) put_user(x, ptr)
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci#else
36462306a36Sopenharmony_ci#define __put_user(x, ptr)						\
36562306a36Sopenharmony_ci({									\
36662306a36Sopenharmony_ci	long __pu_err = 0;						\
36762306a36Sopenharmony_ci	__put_user_switch((x), (ptr), __pu_err, __put_user_nocheck);	\
36862306a36Sopenharmony_ci	__pu_err;							\
36962306a36Sopenharmony_ci})
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci#define __put_user_nocheck(x, __pu_ptr, __err, __size)			\
37262306a36Sopenharmony_ci	do {								\
37362306a36Sopenharmony_ci		unsigned long __pu_addr = (unsigned long)__pu_ptr;	\
37462306a36Sopenharmony_ci		__put_user_nocheck_##__size(x, __pu_addr, __err, TUSER());\
37562306a36Sopenharmony_ci	} while (0)
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci#define __put_user_nocheck_1 __put_user_asm_byte
37862306a36Sopenharmony_ci#define __put_user_nocheck_2 __put_user_asm_half
37962306a36Sopenharmony_ci#define __put_user_nocheck_4 __put_user_asm_word
38062306a36Sopenharmony_ci#define __put_user_nocheck_8 __put_user_asm_dword
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci#endif /* !CONFIG_CPU_SPECTRE */
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci#define __put_user_asm(x, __pu_addr, err, instr)		\
38562306a36Sopenharmony_ci	__asm__ __volatile__(					\
38662306a36Sopenharmony_ci	"1:	" instr " %1, [%2], #0\n"		\
38762306a36Sopenharmony_ci	"2:\n"							\
38862306a36Sopenharmony_ci	"	.pushsection .text.fixup,\"ax\"\n"		\
38962306a36Sopenharmony_ci	"	.align	2\n"					\
39062306a36Sopenharmony_ci	"3:	mov	%0, %3\n"				\
39162306a36Sopenharmony_ci	"	b	2b\n"					\
39262306a36Sopenharmony_ci	"	.popsection\n"					\
39362306a36Sopenharmony_ci	"	.pushsection __ex_table,\"a\"\n"		\
39462306a36Sopenharmony_ci	"	.align	3\n"					\
39562306a36Sopenharmony_ci	"	.long	1b, 3b\n"				\
39662306a36Sopenharmony_ci	"	.popsection"					\
39762306a36Sopenharmony_ci	: "+r" (err)						\
39862306a36Sopenharmony_ci	: "r" (x), "r" (__pu_addr), "i" (-EFAULT)		\
39962306a36Sopenharmony_ci	: "cc")
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci#define __put_user_asm_byte(x, __pu_addr, err, __t)		\
40262306a36Sopenharmony_ci	__put_user_asm(x, __pu_addr, err, "strb" __t)
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 6
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci#define __put_user_asm_half(x, __pu_addr, err, __t)		\
40762306a36Sopenharmony_ci	__put_user_asm(x, __pu_addr, err, "strh" __t)
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci#else
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci#ifndef __ARMEB__
41262306a36Sopenharmony_ci#define __put_user_asm_half(x, __pu_addr, err, __t)		\
41362306a36Sopenharmony_ci({								\
41462306a36Sopenharmony_ci	unsigned long __temp = (__force unsigned long)(x);	\
41562306a36Sopenharmony_ci	__put_user_asm_byte(__temp, __pu_addr, err, __t);	\
41662306a36Sopenharmony_ci	__put_user_asm_byte(__temp >> 8, __pu_addr + 1, err, __t);\
41762306a36Sopenharmony_ci})
41862306a36Sopenharmony_ci#else
41962306a36Sopenharmony_ci#define __put_user_asm_half(x, __pu_addr, err, __t)		\
42062306a36Sopenharmony_ci({								\
42162306a36Sopenharmony_ci	unsigned long __temp = (__force unsigned long)(x);	\
42262306a36Sopenharmony_ci	__put_user_asm_byte(__temp >> 8, __pu_addr, err, __t);	\
42362306a36Sopenharmony_ci	__put_user_asm_byte(__temp, __pu_addr + 1, err, __t);	\
42462306a36Sopenharmony_ci})
42562306a36Sopenharmony_ci#endif
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci#endif /* __LINUX_ARM_ARCH__ >= 6 */
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci#define __put_user_asm_word(x, __pu_addr, err, __t)		\
43062306a36Sopenharmony_ci	__put_user_asm(x, __pu_addr, err, "str" __t)
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci#ifndef __ARMEB__
43362306a36Sopenharmony_ci#define	__reg_oper0	"%R2"
43462306a36Sopenharmony_ci#define	__reg_oper1	"%Q2"
43562306a36Sopenharmony_ci#else
43662306a36Sopenharmony_ci#define	__reg_oper0	"%Q2"
43762306a36Sopenharmony_ci#define	__reg_oper1	"%R2"
43862306a36Sopenharmony_ci#endif
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci#define __put_user_asm_dword(x, __pu_addr, err, __t)		\
44162306a36Sopenharmony_ci	__asm__ __volatile__(					\
44262306a36Sopenharmony_ci ARM(	"1:	str" __t "	" __reg_oper1 ", [%1], #4\n"  ) \
44362306a36Sopenharmony_ci ARM(	"2:	str" __t "	" __reg_oper0 ", [%1]\n"      ) \
44462306a36Sopenharmony_ci THUMB(	"1:	str" __t "	" __reg_oper1 ", [%1]\n"      ) \
44562306a36Sopenharmony_ci THUMB(	"2:	str" __t "	" __reg_oper0 ", [%1, #4]\n"  ) \
44662306a36Sopenharmony_ci	"3:\n"							\
44762306a36Sopenharmony_ci	"	.pushsection .text.fixup,\"ax\"\n"		\
44862306a36Sopenharmony_ci	"	.align	2\n"					\
44962306a36Sopenharmony_ci	"4:	mov	%0, %3\n"				\
45062306a36Sopenharmony_ci	"	b	3b\n"					\
45162306a36Sopenharmony_ci	"	.popsection\n"					\
45262306a36Sopenharmony_ci	"	.pushsection __ex_table,\"a\"\n"		\
45362306a36Sopenharmony_ci	"	.align	3\n"					\
45462306a36Sopenharmony_ci	"	.long	1b, 4b\n"				\
45562306a36Sopenharmony_ci	"	.long	2b, 4b\n"				\
45662306a36Sopenharmony_ci	"	.popsection"					\
45762306a36Sopenharmony_ci	: "+r" (err), "+r" (__pu_addr)				\
45862306a36Sopenharmony_ci	: "r" (x), "i" (-EFAULT)				\
45962306a36Sopenharmony_ci	: "cc")
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci#define __get_kernel_nofault(dst, src, type, err_label)			\
46262306a36Sopenharmony_cido {									\
46362306a36Sopenharmony_ci	const type *__pk_ptr = (src);					\
46462306a36Sopenharmony_ci	unsigned long __src = (unsigned long)(__pk_ptr);		\
46562306a36Sopenharmony_ci	type __val;							\
46662306a36Sopenharmony_ci	int __err = 0;							\
46762306a36Sopenharmony_ci	switch (sizeof(type)) {						\
46862306a36Sopenharmony_ci	case 1:	__get_user_asm_byte(__val, __src, __err, ""); break;	\
46962306a36Sopenharmony_ci	case 2: __get_user_asm_half(__val, __src, __err, ""); break;	\
47062306a36Sopenharmony_ci	case 4: __get_user_asm_word(__val, __src, __err, ""); break;	\
47162306a36Sopenharmony_ci	case 8: {							\
47262306a36Sopenharmony_ci		u32 *__v32 = (u32*)&__val;				\
47362306a36Sopenharmony_ci		__get_user_asm_word(__v32[0], __src, __err, "");	\
47462306a36Sopenharmony_ci		if (__err)						\
47562306a36Sopenharmony_ci			break;						\
47662306a36Sopenharmony_ci		__get_user_asm_word(__v32[1], __src+4, __err, "");	\
47762306a36Sopenharmony_ci		break;							\
47862306a36Sopenharmony_ci	}								\
47962306a36Sopenharmony_ci	default: __err = __get_user_bad(); break;			\
48062306a36Sopenharmony_ci	}								\
48162306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))		\
48262306a36Sopenharmony_ci		put_unaligned(__val, (type *)(dst));			\
48362306a36Sopenharmony_ci	else								\
48462306a36Sopenharmony_ci		*(type *)(dst) = __val; /* aligned by caller */		\
48562306a36Sopenharmony_ci	if (__err)							\
48662306a36Sopenharmony_ci		goto err_label;						\
48762306a36Sopenharmony_ci} while (0)
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci#define __put_kernel_nofault(dst, src, type, err_label)			\
49062306a36Sopenharmony_cido {									\
49162306a36Sopenharmony_ci	const type *__pk_ptr = (dst);					\
49262306a36Sopenharmony_ci	unsigned long __dst = (unsigned long)__pk_ptr;			\
49362306a36Sopenharmony_ci	int __err = 0;							\
49462306a36Sopenharmony_ci	type __val = IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)	\
49562306a36Sopenharmony_ci		     ? get_unaligned((type *)(src))			\
49662306a36Sopenharmony_ci		     : *(type *)(src);	/* aligned by caller */		\
49762306a36Sopenharmony_ci	switch (sizeof(type)) {						\
49862306a36Sopenharmony_ci	case 1: __put_user_asm_byte(__val, __dst, __err, ""); break;	\
49962306a36Sopenharmony_ci	case 2:	__put_user_asm_half(__val, __dst, __err, ""); break;	\
50062306a36Sopenharmony_ci	case 4:	__put_user_asm_word(__val, __dst, __err, ""); break;	\
50162306a36Sopenharmony_ci	case 8:	__put_user_asm_dword(__val, __dst, __err, ""); break;	\
50262306a36Sopenharmony_ci	default: __err = __put_user_bad(); break;			\
50362306a36Sopenharmony_ci	}								\
50462306a36Sopenharmony_ci	if (__err)							\
50562306a36Sopenharmony_ci		goto err_label;						\
50662306a36Sopenharmony_ci} while (0)
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci#ifdef CONFIG_MMU
50962306a36Sopenharmony_ciextern unsigned long __must_check
51062306a36Sopenharmony_ciarm_copy_from_user(void *to, const void __user *from, unsigned long n);
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_cistatic inline unsigned long __must_check
51362306a36Sopenharmony_ciraw_copy_from_user(void *to, const void __user *from, unsigned long n)
51462306a36Sopenharmony_ci{
51562306a36Sopenharmony_ci	unsigned int __ua_flags;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	__ua_flags = uaccess_save_and_enable();
51862306a36Sopenharmony_ci	n = arm_copy_from_user(to, from, n);
51962306a36Sopenharmony_ci	uaccess_restore(__ua_flags);
52062306a36Sopenharmony_ci	return n;
52162306a36Sopenharmony_ci}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ciextern unsigned long __must_check
52462306a36Sopenharmony_ciarm_copy_to_user(void __user *to, const void *from, unsigned long n);
52562306a36Sopenharmony_ciextern unsigned long __must_check
52662306a36Sopenharmony_ci__copy_to_user_std(void __user *to, const void *from, unsigned long n);
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_cistatic inline unsigned long __must_check
52962306a36Sopenharmony_ciraw_copy_to_user(void __user *to, const void *from, unsigned long n)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci#ifndef CONFIG_UACCESS_WITH_MEMCPY
53262306a36Sopenharmony_ci	unsigned int __ua_flags;
53362306a36Sopenharmony_ci	__ua_flags = uaccess_save_and_enable();
53462306a36Sopenharmony_ci	n = arm_copy_to_user(to, from, n);
53562306a36Sopenharmony_ci	uaccess_restore(__ua_flags);
53662306a36Sopenharmony_ci	return n;
53762306a36Sopenharmony_ci#else
53862306a36Sopenharmony_ci	return arm_copy_to_user(to, from, n);
53962306a36Sopenharmony_ci#endif
54062306a36Sopenharmony_ci}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ciextern unsigned long __must_check
54362306a36Sopenharmony_ciarm_clear_user(void __user *addr, unsigned long n);
54462306a36Sopenharmony_ciextern unsigned long __must_check
54562306a36Sopenharmony_ci__clear_user_std(void __user *addr, unsigned long n);
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_cistatic inline unsigned long __must_check
54862306a36Sopenharmony_ci__clear_user(void __user *addr, unsigned long n)
54962306a36Sopenharmony_ci{
55062306a36Sopenharmony_ci	unsigned int __ua_flags = uaccess_save_and_enable();
55162306a36Sopenharmony_ci	n = arm_clear_user(addr, n);
55262306a36Sopenharmony_ci	uaccess_restore(__ua_flags);
55362306a36Sopenharmony_ci	return n;
55462306a36Sopenharmony_ci}
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci#else
55762306a36Sopenharmony_cistatic inline unsigned long
55862306a36Sopenharmony_ciraw_copy_from_user(void *to, const void __user *from, unsigned long n)
55962306a36Sopenharmony_ci{
56062306a36Sopenharmony_ci	memcpy(to, (const void __force *)from, n);
56162306a36Sopenharmony_ci	return 0;
56262306a36Sopenharmony_ci}
56362306a36Sopenharmony_cistatic inline unsigned long
56462306a36Sopenharmony_ciraw_copy_to_user(void __user *to, const void *from, unsigned long n)
56562306a36Sopenharmony_ci{
56662306a36Sopenharmony_ci	memcpy((void __force *)to, from, n);
56762306a36Sopenharmony_ci	return 0;
56862306a36Sopenharmony_ci}
56962306a36Sopenharmony_ci#define __clear_user(addr, n)		(memset((void __force *)addr, 0, n), 0)
57062306a36Sopenharmony_ci#endif
57162306a36Sopenharmony_ci#define INLINE_COPY_TO_USER
57262306a36Sopenharmony_ci#define INLINE_COPY_FROM_USER
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_cistatic inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
57562306a36Sopenharmony_ci{
57662306a36Sopenharmony_ci	if (access_ok(to, n))
57762306a36Sopenharmony_ci		n = __clear_user(to, n);
57862306a36Sopenharmony_ci	return n;
57962306a36Sopenharmony_ci}
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci/* These are from lib/ code, and use __get_user() and friends */
58262306a36Sopenharmony_ciextern long strncpy_from_user(char *dest, const char __user *src, long count);
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ciextern __must_check long strnlen_user(const char __user *str, long n);
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci#endif /* _ASMARM_UACCESS_H */
587