162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __M68K_UACCESS_H
362306a36Sopenharmony_ci#define __M68K_UACCESS_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#ifdef CONFIG_MMU
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci/*
862306a36Sopenharmony_ci * User space memory access functions
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci#include <linux/compiler.h>
1162306a36Sopenharmony_ci#include <linux/types.h>
1262306a36Sopenharmony_ci#include <asm/extable.h>
1362306a36Sopenharmony_ci#include <asm-generic/access_ok.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/*
1662306a36Sopenharmony_ci * Not all varients of the 68k family support the notion of address spaces.
1762306a36Sopenharmony_ci * The traditional 680x0 parts do, and they use the sfc/dfc registers and
1862306a36Sopenharmony_ci * the "moves" instruction to access user space from kernel space. Other
1962306a36Sopenharmony_ci * family members like ColdFire don't support this, and only have a single
2062306a36Sopenharmony_ci * address space, and use the usual "move" instruction for user space access.
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * Outside of this difference the user space access functions are the same.
2362306a36Sopenharmony_ci * So lets keep the code simple and just define in what we need to use.
2462306a36Sopenharmony_ci */
2562306a36Sopenharmony_ci#ifdef CONFIG_CPU_HAS_ADDRESS_SPACES
2662306a36Sopenharmony_ci#define	MOVES	"moves"
2762306a36Sopenharmony_ci#else
2862306a36Sopenharmony_ci#define	MOVES	"move"
2962306a36Sopenharmony_ci#endif
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define __put_user_asm(inst, res, x, ptr, bwl, reg, err) \
3262306a36Sopenharmony_ciasm volatile ("\n"					\
3362306a36Sopenharmony_ci	"1:	"inst"."#bwl"	%2,%1\n"		\
3462306a36Sopenharmony_ci	"2:\n"						\
3562306a36Sopenharmony_ci	"	.section .fixup,\"ax\"\n"		\
3662306a36Sopenharmony_ci	"	.even\n"				\
3762306a36Sopenharmony_ci	"10:	moveq.l	%3,%0\n"			\
3862306a36Sopenharmony_ci	"	jra 2b\n"				\
3962306a36Sopenharmony_ci	"	.previous\n"				\
4062306a36Sopenharmony_ci	"\n"						\
4162306a36Sopenharmony_ci	"	.section __ex_table,\"a\"\n"		\
4262306a36Sopenharmony_ci	"	.align	4\n"				\
4362306a36Sopenharmony_ci	"	.long	1b,10b\n"			\
4462306a36Sopenharmony_ci	"	.long	2b,10b\n"			\
4562306a36Sopenharmony_ci	"	.previous"				\
4662306a36Sopenharmony_ci	: "+d" (res), "=m" (*(ptr))			\
4762306a36Sopenharmony_ci	: #reg (x), "i" (err))
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define __put_user_asm8(inst, res, x, ptr)			\
5062306a36Sopenharmony_cido {								\
5162306a36Sopenharmony_ci	const void *__pu_ptr = (const void __force *)(ptr);	\
5262306a36Sopenharmony_ci								\
5362306a36Sopenharmony_ci	asm volatile ("\n"					\
5462306a36Sopenharmony_ci		"1:	"inst".l %2,(%1)+\n"			\
5562306a36Sopenharmony_ci		"2:	"inst".l %R2,(%1)\n"			\
5662306a36Sopenharmony_ci		"3:\n"						\
5762306a36Sopenharmony_ci		"	.section .fixup,\"ax\"\n"		\
5862306a36Sopenharmony_ci		"	.even\n"				\
5962306a36Sopenharmony_ci		"10:	movel %3,%0\n"				\
6062306a36Sopenharmony_ci		"	jra 3b\n"				\
6162306a36Sopenharmony_ci		"	.previous\n"				\
6262306a36Sopenharmony_ci		"\n"						\
6362306a36Sopenharmony_ci		"	.section __ex_table,\"a\"\n"		\
6462306a36Sopenharmony_ci		"	.align 4\n"				\
6562306a36Sopenharmony_ci		"	.long 1b,10b\n"				\
6662306a36Sopenharmony_ci		"	.long 2b,10b\n"				\
6762306a36Sopenharmony_ci		"	.long 3b,10b\n"				\
6862306a36Sopenharmony_ci		"	.previous"				\
6962306a36Sopenharmony_ci		: "+d" (res), "+a" (__pu_ptr)			\
7062306a36Sopenharmony_ci		: "r" (x), "i" (-EFAULT)			\
7162306a36Sopenharmony_ci		: "memory");					\
7262306a36Sopenharmony_ci} while (0)
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci/*
7562306a36Sopenharmony_ci * These are the main single-value transfer routines.  They automatically
7662306a36Sopenharmony_ci * use the right size if we just have the right pointer type.
7762306a36Sopenharmony_ci */
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci#define __put_user(x, ptr)						\
8062306a36Sopenharmony_ci({									\
8162306a36Sopenharmony_ci	typeof(*(ptr)) __pu_val = (x);					\
8262306a36Sopenharmony_ci	int __pu_err = 0;						\
8362306a36Sopenharmony_ci	__chk_user_ptr(ptr);						\
8462306a36Sopenharmony_ci	switch (sizeof (*(ptr))) {					\
8562306a36Sopenharmony_ci	case 1:								\
8662306a36Sopenharmony_ci		__put_user_asm(MOVES, __pu_err, __pu_val, ptr, b, d, -EFAULT); \
8762306a36Sopenharmony_ci		break;							\
8862306a36Sopenharmony_ci	case 2:								\
8962306a36Sopenharmony_ci		__put_user_asm(MOVES, __pu_err, __pu_val, ptr, w, r, -EFAULT); \
9062306a36Sopenharmony_ci		break;							\
9162306a36Sopenharmony_ci	case 4:								\
9262306a36Sopenharmony_ci		__put_user_asm(MOVES, __pu_err, __pu_val, ptr, l, r, -EFAULT); \
9362306a36Sopenharmony_ci		break;							\
9462306a36Sopenharmony_ci	case 8:								\
9562306a36Sopenharmony_ci		__put_user_asm8(MOVES, __pu_err, __pu_val, ptr);	\
9662306a36Sopenharmony_ci		break;							\
9762306a36Sopenharmony_ci	default:							\
9862306a36Sopenharmony_ci		BUILD_BUG();						\
9962306a36Sopenharmony_ci	}								\
10062306a36Sopenharmony_ci	__pu_err;							\
10162306a36Sopenharmony_ci})
10262306a36Sopenharmony_ci#define put_user(x, ptr)	__put_user(x, ptr)
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci#define __get_user_asm(inst, res, x, ptr, type, bwl, reg, err) ({	\
10662306a36Sopenharmony_ci	type __gu_val;							\
10762306a36Sopenharmony_ci	asm volatile ("\n"						\
10862306a36Sopenharmony_ci		"1:	"inst"."#bwl"	%2,%1\n"			\
10962306a36Sopenharmony_ci		"2:\n"							\
11062306a36Sopenharmony_ci		"	.section .fixup,\"ax\"\n"			\
11162306a36Sopenharmony_ci		"	.even\n"					\
11262306a36Sopenharmony_ci		"10:	move.l	%3,%0\n"				\
11362306a36Sopenharmony_ci		"	sub.l	%1,%1\n"				\
11462306a36Sopenharmony_ci		"	jra	2b\n"					\
11562306a36Sopenharmony_ci		"	.previous\n"					\
11662306a36Sopenharmony_ci		"\n"							\
11762306a36Sopenharmony_ci		"	.section __ex_table,\"a\"\n"			\
11862306a36Sopenharmony_ci		"	.align	4\n"					\
11962306a36Sopenharmony_ci		"	.long	1b,10b\n"				\
12062306a36Sopenharmony_ci		"	.previous"					\
12162306a36Sopenharmony_ci		: "+d" (res), "=&" #reg (__gu_val)			\
12262306a36Sopenharmony_ci		: "m" (*(ptr)), "i" (err));				\
12362306a36Sopenharmony_ci	(x) = (__force typeof(*(ptr)))(__force unsigned long)__gu_val;	\
12462306a36Sopenharmony_ci})
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci#define __get_user_asm8(inst, res, x, ptr) 				\
12762306a36Sopenharmony_cido {									\
12862306a36Sopenharmony_ci	const void *__gu_ptr = (const void __force *)(ptr);		\
12962306a36Sopenharmony_ci	union {								\
13062306a36Sopenharmony_ci		u64 l;							\
13162306a36Sopenharmony_ci		__typeof__(*(ptr)) t;					\
13262306a36Sopenharmony_ci	} __gu_val;							\
13362306a36Sopenharmony_ci									\
13462306a36Sopenharmony_ci	asm volatile ("\n"						\
13562306a36Sopenharmony_ci		"1:	"inst".l (%2)+,%1\n"				\
13662306a36Sopenharmony_ci		"2:	"inst".l (%2),%R1\n"				\
13762306a36Sopenharmony_ci		"3:\n"							\
13862306a36Sopenharmony_ci		"	.section .fixup,\"ax\"\n"			\
13962306a36Sopenharmony_ci		"	.even\n"					\
14062306a36Sopenharmony_ci		"10:	move.l	%3,%0\n"				\
14162306a36Sopenharmony_ci		"	sub.l	%1,%1\n"				\
14262306a36Sopenharmony_ci		"	sub.l	%R1,%R1\n"				\
14362306a36Sopenharmony_ci		"	jra	3b\n"					\
14462306a36Sopenharmony_ci		"	.previous\n"					\
14562306a36Sopenharmony_ci		"\n"							\
14662306a36Sopenharmony_ci		"	.section __ex_table,\"a\"\n"			\
14762306a36Sopenharmony_ci		"	.align	4\n"					\
14862306a36Sopenharmony_ci		"	.long	1b,10b\n"				\
14962306a36Sopenharmony_ci		"	.long	2b,10b\n"				\
15062306a36Sopenharmony_ci		"	.previous"					\
15162306a36Sopenharmony_ci		: "+d" (res), "=&r" (__gu_val.l),			\
15262306a36Sopenharmony_ci		  "+a" (__gu_ptr)					\
15362306a36Sopenharmony_ci		: "i" (-EFAULT)						\
15462306a36Sopenharmony_ci		: "memory");						\
15562306a36Sopenharmony_ci	(x) = __gu_val.t;						\
15662306a36Sopenharmony_ci} while (0)
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci#define __get_user(x, ptr)						\
15962306a36Sopenharmony_ci({									\
16062306a36Sopenharmony_ci	int __gu_err = 0;						\
16162306a36Sopenharmony_ci	__chk_user_ptr(ptr);						\
16262306a36Sopenharmony_ci	switch (sizeof(*(ptr))) {					\
16362306a36Sopenharmony_ci	case 1:								\
16462306a36Sopenharmony_ci		__get_user_asm(MOVES, __gu_err, x, ptr, u8, b, d, -EFAULT); \
16562306a36Sopenharmony_ci		break;							\
16662306a36Sopenharmony_ci	case 2:								\
16762306a36Sopenharmony_ci		__get_user_asm(MOVES, __gu_err, x, ptr, u16, w, r, -EFAULT); \
16862306a36Sopenharmony_ci		break;							\
16962306a36Sopenharmony_ci	case 4:								\
17062306a36Sopenharmony_ci		__get_user_asm(MOVES, __gu_err, x, ptr, u32, l, r, -EFAULT); \
17162306a36Sopenharmony_ci		break;							\
17262306a36Sopenharmony_ci	case 8:								\
17362306a36Sopenharmony_ci		__get_user_asm8(MOVES, __gu_err, x, ptr);		\
17462306a36Sopenharmony_ci		break;							\
17562306a36Sopenharmony_ci	default:							\
17662306a36Sopenharmony_ci		BUILD_BUG();						\
17762306a36Sopenharmony_ci	}								\
17862306a36Sopenharmony_ci	__gu_err;							\
17962306a36Sopenharmony_ci})
18062306a36Sopenharmony_ci#define get_user(x, ptr) __get_user(x, ptr)
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ciunsigned long __generic_copy_from_user(void *to, const void __user *from, unsigned long n);
18362306a36Sopenharmony_ciunsigned long __generic_copy_to_user(void __user *to, const void *from, unsigned long n);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci#define __suffix0
18662306a36Sopenharmony_ci#define __suffix1 b
18762306a36Sopenharmony_ci#define __suffix2 w
18862306a36Sopenharmony_ci#define __suffix4 l
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci#define ____constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, s1, s2, s3)\
19162306a36Sopenharmony_ci	asm volatile ("\n"						\
19262306a36Sopenharmony_ci		"1:	"MOVES"."#s1"	(%2)+,%3\n"			\
19362306a36Sopenharmony_ci		"	move."#s1"	%3,(%1)+\n"			\
19462306a36Sopenharmony_ci		"	.ifnc	\""#s2"\",\"\"\n"			\
19562306a36Sopenharmony_ci		"2:	"MOVES"."#s2"	(%2)+,%3\n"			\
19662306a36Sopenharmony_ci		"	move."#s2"	%3,(%1)+\n"			\
19762306a36Sopenharmony_ci		"	.ifnc	\""#s3"\",\"\"\n"			\
19862306a36Sopenharmony_ci		"3:	"MOVES"."#s3"	(%2)+,%3\n"			\
19962306a36Sopenharmony_ci		"	move."#s3"	%3,(%1)+\n"			\
20062306a36Sopenharmony_ci		"	.endif\n"					\
20162306a36Sopenharmony_ci		"	.endif\n"					\
20262306a36Sopenharmony_ci		"4:\n"							\
20362306a36Sopenharmony_ci		"	.section __ex_table,\"a\"\n"			\
20462306a36Sopenharmony_ci		"	.align	4\n"					\
20562306a36Sopenharmony_ci		"	.long	1b,10f\n"				\
20662306a36Sopenharmony_ci		"	.ifnc	\""#s2"\",\"\"\n"			\
20762306a36Sopenharmony_ci		"	.long	2b,20f\n"				\
20862306a36Sopenharmony_ci		"	.ifnc	\""#s3"\",\"\"\n"			\
20962306a36Sopenharmony_ci		"	.long	3b,30f\n"				\
21062306a36Sopenharmony_ci		"	.endif\n"					\
21162306a36Sopenharmony_ci		"	.endif\n"					\
21262306a36Sopenharmony_ci		"	.previous\n"					\
21362306a36Sopenharmony_ci		"\n"							\
21462306a36Sopenharmony_ci		"	.section .fixup,\"ax\"\n"			\
21562306a36Sopenharmony_ci		"	.even\n"					\
21662306a36Sopenharmony_ci		"10:	addq.l #"#n1",%0\n"				\
21762306a36Sopenharmony_ci		"	.ifnc	\""#s2"\",\"\"\n"			\
21862306a36Sopenharmony_ci		"20:	addq.l #"#n2",%0\n"				\
21962306a36Sopenharmony_ci		"	.ifnc	\""#s3"\",\"\"\n"			\
22062306a36Sopenharmony_ci		"30:	addq.l #"#n3",%0\n"				\
22162306a36Sopenharmony_ci		"	.endif\n"					\
22262306a36Sopenharmony_ci		"	.endif\n"					\
22362306a36Sopenharmony_ci		"	jra	4b\n"					\
22462306a36Sopenharmony_ci		"	.previous\n"					\
22562306a36Sopenharmony_ci		: "+d" (res), "+&a" (to), "+a" (from), "=&d" (tmp)	\
22662306a36Sopenharmony_ci		: : "memory")
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci#define ___constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, s1, s2, s3)\
22962306a36Sopenharmony_ci	____constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, s1, s2, s3)
23062306a36Sopenharmony_ci#define __constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3)	\
23162306a36Sopenharmony_ci	___constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3,  \
23262306a36Sopenharmony_ci					__suffix##n1, __suffix##n2, __suffix##n3)
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cistatic __always_inline unsigned long
23562306a36Sopenharmony_ci__constant_copy_from_user(void *to, const void __user *from, unsigned long n)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	unsigned long res = 0, tmp;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	switch (n) {
24062306a36Sopenharmony_ci	case 1:
24162306a36Sopenharmony_ci		__constant_copy_from_user_asm(res, to, from, tmp, 1, 0, 0);
24262306a36Sopenharmony_ci		break;
24362306a36Sopenharmony_ci	case 2:
24462306a36Sopenharmony_ci		__constant_copy_from_user_asm(res, to, from, tmp, 2, 0, 0);
24562306a36Sopenharmony_ci		break;
24662306a36Sopenharmony_ci	case 3:
24762306a36Sopenharmony_ci		__constant_copy_from_user_asm(res, to, from, tmp, 2, 1, 0);
24862306a36Sopenharmony_ci		break;
24962306a36Sopenharmony_ci	case 4:
25062306a36Sopenharmony_ci		__constant_copy_from_user_asm(res, to, from, tmp, 4, 0, 0);
25162306a36Sopenharmony_ci		break;
25262306a36Sopenharmony_ci	case 5:
25362306a36Sopenharmony_ci		__constant_copy_from_user_asm(res, to, from, tmp, 4, 1, 0);
25462306a36Sopenharmony_ci		break;
25562306a36Sopenharmony_ci	case 6:
25662306a36Sopenharmony_ci		__constant_copy_from_user_asm(res, to, from, tmp, 4, 2, 0);
25762306a36Sopenharmony_ci		break;
25862306a36Sopenharmony_ci	case 7:
25962306a36Sopenharmony_ci		__constant_copy_from_user_asm(res, to, from, tmp, 4, 2, 1);
26062306a36Sopenharmony_ci		break;
26162306a36Sopenharmony_ci	case 8:
26262306a36Sopenharmony_ci		__constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 0);
26362306a36Sopenharmony_ci		break;
26462306a36Sopenharmony_ci	case 9:
26562306a36Sopenharmony_ci		__constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 1);
26662306a36Sopenharmony_ci		break;
26762306a36Sopenharmony_ci	case 10:
26862306a36Sopenharmony_ci		__constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 2);
26962306a36Sopenharmony_ci		break;
27062306a36Sopenharmony_ci	case 12:
27162306a36Sopenharmony_ci		__constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 4);
27262306a36Sopenharmony_ci		break;
27362306a36Sopenharmony_ci	default:
27462306a36Sopenharmony_ci		/* we limit the inlined version to 3 moves */
27562306a36Sopenharmony_ci		return __generic_copy_from_user(to, from, n);
27662306a36Sopenharmony_ci	}
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	return res;
27962306a36Sopenharmony_ci}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci#define __constant_copy_to_user_asm(res, to, from, tmp, n, s1, s2, s3)	\
28262306a36Sopenharmony_ci	asm volatile ("\n"						\
28362306a36Sopenharmony_ci		"	move."#s1"	(%2)+,%3\n"			\
28462306a36Sopenharmony_ci		"11:	"MOVES"."#s1"	%3,(%1)+\n"			\
28562306a36Sopenharmony_ci		"12:	move."#s2"	(%2)+,%3\n"			\
28662306a36Sopenharmony_ci		"21:	"MOVES"."#s2"	%3,(%1)+\n"			\
28762306a36Sopenharmony_ci		"22:\n"							\
28862306a36Sopenharmony_ci		"	.ifnc	\""#s3"\",\"\"\n"			\
28962306a36Sopenharmony_ci		"	move."#s3"	(%2)+,%3\n"			\
29062306a36Sopenharmony_ci		"31:	"MOVES"."#s3"	%3,(%1)+\n"			\
29162306a36Sopenharmony_ci		"32:\n"							\
29262306a36Sopenharmony_ci		"	.endif\n"					\
29362306a36Sopenharmony_ci		"4:\n"							\
29462306a36Sopenharmony_ci		"\n"							\
29562306a36Sopenharmony_ci		"	.section __ex_table,\"a\"\n"			\
29662306a36Sopenharmony_ci		"	.align	4\n"					\
29762306a36Sopenharmony_ci		"	.long	11b,5f\n"				\
29862306a36Sopenharmony_ci		"	.long	12b,5f\n"				\
29962306a36Sopenharmony_ci		"	.long	21b,5f\n"				\
30062306a36Sopenharmony_ci		"	.long	22b,5f\n"				\
30162306a36Sopenharmony_ci		"	.ifnc	\""#s3"\",\"\"\n"			\
30262306a36Sopenharmony_ci		"	.long	31b,5f\n"				\
30362306a36Sopenharmony_ci		"	.long	32b,5f\n"				\
30462306a36Sopenharmony_ci		"	.endif\n"					\
30562306a36Sopenharmony_ci		"	.previous\n"					\
30662306a36Sopenharmony_ci		"\n"							\
30762306a36Sopenharmony_ci		"	.section .fixup,\"ax\"\n"			\
30862306a36Sopenharmony_ci		"	.even\n"					\
30962306a36Sopenharmony_ci		"5:	moveq.l	#"#n",%0\n"				\
31062306a36Sopenharmony_ci		"	jra	4b\n"					\
31162306a36Sopenharmony_ci		"	.previous\n"					\
31262306a36Sopenharmony_ci		: "+d" (res), "+a" (to), "+a" (from), "=&d" (tmp)	\
31362306a36Sopenharmony_ci		: : "memory")
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistatic __always_inline unsigned long
31662306a36Sopenharmony_ci__constant_copy_to_user(void __user *to, const void *from, unsigned long n)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	unsigned long res = 0, tmp;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	switch (n) {
32162306a36Sopenharmony_ci	case 1:
32262306a36Sopenharmony_ci		__put_user_asm(MOVES, res, *(u8 *)from, (u8 __user *)to,
32362306a36Sopenharmony_ci				b, d, 1);
32462306a36Sopenharmony_ci		break;
32562306a36Sopenharmony_ci	case 2:
32662306a36Sopenharmony_ci		__put_user_asm(MOVES, res, *(u16 *)from, (u16 __user *)to,
32762306a36Sopenharmony_ci				w, r, 2);
32862306a36Sopenharmony_ci		break;
32962306a36Sopenharmony_ci	case 3:
33062306a36Sopenharmony_ci		__constant_copy_to_user_asm(res, to, from, tmp, 3, w, b,);
33162306a36Sopenharmony_ci		break;
33262306a36Sopenharmony_ci	case 4:
33362306a36Sopenharmony_ci		__put_user_asm(MOVES, res, *(u32 *)from, (u32 __user *)to,
33462306a36Sopenharmony_ci				l, r, 4);
33562306a36Sopenharmony_ci		break;
33662306a36Sopenharmony_ci	case 5:
33762306a36Sopenharmony_ci		__constant_copy_to_user_asm(res, to, from, tmp, 5, l, b,);
33862306a36Sopenharmony_ci		break;
33962306a36Sopenharmony_ci	case 6:
34062306a36Sopenharmony_ci		__constant_copy_to_user_asm(res, to, from, tmp, 6, l, w,);
34162306a36Sopenharmony_ci		break;
34262306a36Sopenharmony_ci	case 7:
34362306a36Sopenharmony_ci		__constant_copy_to_user_asm(res, to, from, tmp, 7, l, w, b);
34462306a36Sopenharmony_ci		break;
34562306a36Sopenharmony_ci	case 8:
34662306a36Sopenharmony_ci		__constant_copy_to_user_asm(res, to, from, tmp, 8, l, l,);
34762306a36Sopenharmony_ci		break;
34862306a36Sopenharmony_ci	case 9:
34962306a36Sopenharmony_ci		__constant_copy_to_user_asm(res, to, from, tmp, 9, l, l, b);
35062306a36Sopenharmony_ci		break;
35162306a36Sopenharmony_ci	case 10:
35262306a36Sopenharmony_ci		__constant_copy_to_user_asm(res, to, from, tmp, 10, l, l, w);
35362306a36Sopenharmony_ci		break;
35462306a36Sopenharmony_ci	case 12:
35562306a36Sopenharmony_ci		__constant_copy_to_user_asm(res, to, from, tmp, 12, l, l, l);
35662306a36Sopenharmony_ci		break;
35762306a36Sopenharmony_ci	default:
35862306a36Sopenharmony_ci		/* limit the inlined version to 3 moves */
35962306a36Sopenharmony_ci		return __generic_copy_to_user(to, from, n);
36062306a36Sopenharmony_ci	}
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	return res;
36362306a36Sopenharmony_ci}
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_cistatic inline unsigned long
36662306a36Sopenharmony_ciraw_copy_from_user(void *to, const void __user *from, unsigned long n)
36762306a36Sopenharmony_ci{
36862306a36Sopenharmony_ci	if (__builtin_constant_p(n))
36962306a36Sopenharmony_ci		return __constant_copy_from_user(to, from, n);
37062306a36Sopenharmony_ci	return __generic_copy_from_user(to, from, n);
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic inline unsigned long
37462306a36Sopenharmony_ciraw_copy_to_user(void __user *to, const void *from, unsigned long n)
37562306a36Sopenharmony_ci{
37662306a36Sopenharmony_ci	if (__builtin_constant_p(n))
37762306a36Sopenharmony_ci		return __constant_copy_to_user(to, from, n);
37862306a36Sopenharmony_ci	return __generic_copy_to_user(to, from, n);
37962306a36Sopenharmony_ci}
38062306a36Sopenharmony_ci#define INLINE_COPY_FROM_USER
38162306a36Sopenharmony_ci#define INLINE_COPY_TO_USER
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci#define __get_kernel_nofault(dst, src, type, err_label)			\
38462306a36Sopenharmony_cido {									\
38562306a36Sopenharmony_ci	type *__gk_dst = (type *)(dst);					\
38662306a36Sopenharmony_ci	type *__gk_src = (type *)(src);					\
38762306a36Sopenharmony_ci	int __gk_err = 0;						\
38862306a36Sopenharmony_ci									\
38962306a36Sopenharmony_ci	switch (sizeof(type)) {						\
39062306a36Sopenharmony_ci	case 1:								\
39162306a36Sopenharmony_ci		__get_user_asm("move", __gk_err, *__gk_dst, __gk_src,	\
39262306a36Sopenharmony_ci				u8, b, d, -EFAULT);			\
39362306a36Sopenharmony_ci		break;							\
39462306a36Sopenharmony_ci	case 2:								\
39562306a36Sopenharmony_ci		__get_user_asm("move", __gk_err, *__gk_dst, __gk_src,	\
39662306a36Sopenharmony_ci				u16, w, r, -EFAULT);			\
39762306a36Sopenharmony_ci		break;							\
39862306a36Sopenharmony_ci	case 4:								\
39962306a36Sopenharmony_ci		__get_user_asm("move", __gk_err, *__gk_dst, __gk_src,	\
40062306a36Sopenharmony_ci				u32, l, r, -EFAULT);			\
40162306a36Sopenharmony_ci		break;							\
40262306a36Sopenharmony_ci	case 8:								\
40362306a36Sopenharmony_ci		__get_user_asm8("move", __gk_err, *__gk_dst, __gk_src);	\
40462306a36Sopenharmony_ci		break;							\
40562306a36Sopenharmony_ci	default:							\
40662306a36Sopenharmony_ci		BUILD_BUG();						\
40762306a36Sopenharmony_ci	}								\
40862306a36Sopenharmony_ci	if (unlikely(__gk_err))						\
40962306a36Sopenharmony_ci		goto err_label;						\
41062306a36Sopenharmony_ci} while (0)
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci#define __put_kernel_nofault(dst, src, type, err_label)			\
41362306a36Sopenharmony_cido {									\
41462306a36Sopenharmony_ci	type __pk_src = *(type *)(src);					\
41562306a36Sopenharmony_ci	type *__pk_dst = (type *)(dst);					\
41662306a36Sopenharmony_ci	int __pk_err = 0;						\
41762306a36Sopenharmony_ci									\
41862306a36Sopenharmony_ci	switch (sizeof(type)) {						\
41962306a36Sopenharmony_ci	case 1:								\
42062306a36Sopenharmony_ci		__put_user_asm("move", __pk_err, __pk_src, __pk_dst,	\
42162306a36Sopenharmony_ci				b, d, -EFAULT);				\
42262306a36Sopenharmony_ci		break;							\
42362306a36Sopenharmony_ci	case 2:								\
42462306a36Sopenharmony_ci		__put_user_asm("move", __pk_err, __pk_src, __pk_dst,	\
42562306a36Sopenharmony_ci				w, r, -EFAULT);				\
42662306a36Sopenharmony_ci		break;							\
42762306a36Sopenharmony_ci	case 4:								\
42862306a36Sopenharmony_ci		__put_user_asm("move", __pk_err, __pk_src, __pk_dst,	\
42962306a36Sopenharmony_ci				l, r, -EFAULT);				\
43062306a36Sopenharmony_ci		break;							\
43162306a36Sopenharmony_ci	case 8:								\
43262306a36Sopenharmony_ci		__put_user_asm8("move", __pk_err, __pk_src, __pk_dst);	\
43362306a36Sopenharmony_ci		break;							\
43462306a36Sopenharmony_ci	default:							\
43562306a36Sopenharmony_ci		BUILD_BUG();						\
43662306a36Sopenharmony_ci	}								\
43762306a36Sopenharmony_ci	if (unlikely(__pk_err))						\
43862306a36Sopenharmony_ci		goto err_label;						\
43962306a36Sopenharmony_ci} while (0)
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ciextern long strncpy_from_user(char *dst, const char __user *src, long count);
44262306a36Sopenharmony_ciextern __must_check long strnlen_user(const char __user *str, long n);
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ciunsigned long __clear_user(void __user *to, unsigned long n);
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci#define clear_user	__clear_user
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci#else /* !CONFIG_MMU */
44962306a36Sopenharmony_ci#include <asm-generic/uaccess.h>
45062306a36Sopenharmony_ci#endif
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci#endif /* _M68K_UACCESS_H */
453