18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * User space memory access functions
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 1999, 2002  Niibe Yutaka
68c2ecf20Sopenharmony_ci * Copyright (C) 2003 - 2008  Paul Mundt
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci *  Based on:
98c2ecf20Sopenharmony_ci *     MIPS implementation version 1.15 by
108c2ecf20Sopenharmony_ci *              Copyright (C) 1996, 1997, 1998 by Ralf Baechle
118c2ecf20Sopenharmony_ci *     and i386 version.
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci#ifndef __ASM_SH_UACCESS_32_H
148c2ecf20Sopenharmony_ci#define __ASM_SH_UACCESS_32_H
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#define __get_user_size(x,ptr,size,retval)			\
178c2ecf20Sopenharmony_cido {								\
188c2ecf20Sopenharmony_ci	retval = 0;						\
198c2ecf20Sopenharmony_ci	switch (size) {						\
208c2ecf20Sopenharmony_ci	case 1:							\
218c2ecf20Sopenharmony_ci		__get_user_asm(x, ptr, retval, "b");		\
228c2ecf20Sopenharmony_ci		break;						\
238c2ecf20Sopenharmony_ci	case 2:							\
248c2ecf20Sopenharmony_ci		__get_user_asm(x, ptr, retval, "w");		\
258c2ecf20Sopenharmony_ci		break;						\
268c2ecf20Sopenharmony_ci	case 4:							\
278c2ecf20Sopenharmony_ci		__get_user_asm(x, ptr, retval, "l");		\
288c2ecf20Sopenharmony_ci		break;						\
298c2ecf20Sopenharmony_ci	case 8:							\
308c2ecf20Sopenharmony_ci		__get_user_u64(x, ptr, retval);			\
318c2ecf20Sopenharmony_ci		break;						\
328c2ecf20Sopenharmony_ci	default:						\
338c2ecf20Sopenharmony_ci		__get_user_unknown();				\
348c2ecf20Sopenharmony_ci		break;						\
358c2ecf20Sopenharmony_ci	}							\
368c2ecf20Sopenharmony_ci} while (0)
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#ifdef CONFIG_MMU
398c2ecf20Sopenharmony_ci#define __get_user_asm(x, addr, err, insn) \
408c2ecf20Sopenharmony_ci({ \
418c2ecf20Sopenharmony_ci__asm__ __volatile__( \
428c2ecf20Sopenharmony_ci	"1:\n\t" \
438c2ecf20Sopenharmony_ci	"mov." insn "	%2, %1\n\t" \
448c2ecf20Sopenharmony_ci	"2:\n" \
458c2ecf20Sopenharmony_ci	".section	.fixup,\"ax\"\n" \
468c2ecf20Sopenharmony_ci	"3:\n\t" \
478c2ecf20Sopenharmony_ci	"mov	#0, %1\n\t" \
488c2ecf20Sopenharmony_ci	"mov.l	4f, %0\n\t" \
498c2ecf20Sopenharmony_ci	"jmp	@%0\n\t" \
508c2ecf20Sopenharmony_ci	" mov	%3, %0\n\t" \
518c2ecf20Sopenharmony_ci	".balign	4\n" \
528c2ecf20Sopenharmony_ci	"4:	.long	2b\n\t" \
538c2ecf20Sopenharmony_ci	".previous\n" \
548c2ecf20Sopenharmony_ci	".section	__ex_table,\"a\"\n\t" \
558c2ecf20Sopenharmony_ci	".long	1b, 3b\n\t" \
568c2ecf20Sopenharmony_ci	".previous" \
578c2ecf20Sopenharmony_ci	:"=&r" (err), "=&r" (x) \
588c2ecf20Sopenharmony_ci	:"m" (__m(addr)), "i" (-EFAULT), "0" (err)); })
598c2ecf20Sopenharmony_ci#else
608c2ecf20Sopenharmony_ci#define __get_user_asm(x, addr, err, insn)		\
618c2ecf20Sopenharmony_cido {							\
628c2ecf20Sopenharmony_ci	__asm__ __volatile__ (				\
638c2ecf20Sopenharmony_ci		"mov." insn "	%1, %0\n\t"		\
648c2ecf20Sopenharmony_ci		: "=&r" (x)				\
658c2ecf20Sopenharmony_ci		: "m" (__m(addr))			\
668c2ecf20Sopenharmony_ci	);						\
678c2ecf20Sopenharmony_ci} while (0)
688c2ecf20Sopenharmony_ci#endif /* CONFIG_MMU */
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ciextern void __get_user_unknown(void);
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci#if defined(CONFIG_CPU_LITTLE_ENDIAN)
738c2ecf20Sopenharmony_ci#define __get_user_u64(x, addr, err) \
748c2ecf20Sopenharmony_ci({ \
758c2ecf20Sopenharmony_ci__asm__ __volatile__( \
768c2ecf20Sopenharmony_ci	"1:\n\t" \
778c2ecf20Sopenharmony_ci	"mov.l	%2,%R1\n\t" \
788c2ecf20Sopenharmony_ci	"mov.l	%T2,%S1\n\t" \
798c2ecf20Sopenharmony_ci	"2:\n" \
808c2ecf20Sopenharmony_ci	".section	.fixup,\"ax\"\n" \
818c2ecf20Sopenharmony_ci	"3:\n\t" \
828c2ecf20Sopenharmony_ci	"mov  #0,%R1\n\t"   \
838c2ecf20Sopenharmony_ci	"mov  #0,%S1\n\t"   \
848c2ecf20Sopenharmony_ci	"mov.l	4f, %0\n\t" \
858c2ecf20Sopenharmony_ci	"jmp	@%0\n\t" \
868c2ecf20Sopenharmony_ci	" mov	%3, %0\n\t" \
878c2ecf20Sopenharmony_ci	".balign	4\n" \
888c2ecf20Sopenharmony_ci	"4:	.long	2b\n\t" \
898c2ecf20Sopenharmony_ci	".previous\n" \
908c2ecf20Sopenharmony_ci	".section	__ex_table,\"a\"\n\t" \
918c2ecf20Sopenharmony_ci	".long	1b, 3b\n\t" \
928c2ecf20Sopenharmony_ci	".long	1b + 2, 3b\n\t" \
938c2ecf20Sopenharmony_ci	".previous" \
948c2ecf20Sopenharmony_ci	:"=&r" (err), "=&r" (x) \
958c2ecf20Sopenharmony_ci	:"m" (__m(addr)), "i" (-EFAULT), "0" (err)); })
968c2ecf20Sopenharmony_ci#else
978c2ecf20Sopenharmony_ci#define __get_user_u64(x, addr, err) \
988c2ecf20Sopenharmony_ci({ \
998c2ecf20Sopenharmony_ci__asm__ __volatile__( \
1008c2ecf20Sopenharmony_ci	"1:\n\t" \
1018c2ecf20Sopenharmony_ci	"mov.l	%2,%S1\n\t" \
1028c2ecf20Sopenharmony_ci	"mov.l	%T2,%R1\n\t" \
1038c2ecf20Sopenharmony_ci	"2:\n" \
1048c2ecf20Sopenharmony_ci	".section	.fixup,\"ax\"\n" \
1058c2ecf20Sopenharmony_ci	"3:\n\t" \
1068c2ecf20Sopenharmony_ci	"mov  #0,%S1\n\t"   \
1078c2ecf20Sopenharmony_ci	"mov  #0,%R1\n\t"   \
1088c2ecf20Sopenharmony_ci	"mov.l	4f, %0\n\t" \
1098c2ecf20Sopenharmony_ci	"jmp	@%0\n\t" \
1108c2ecf20Sopenharmony_ci	" mov	%3, %0\n\t" \
1118c2ecf20Sopenharmony_ci	".balign	4\n" \
1128c2ecf20Sopenharmony_ci	"4:	.long	2b\n\t" \
1138c2ecf20Sopenharmony_ci	".previous\n" \
1148c2ecf20Sopenharmony_ci	".section	__ex_table,\"a\"\n\t" \
1158c2ecf20Sopenharmony_ci	".long	1b, 3b\n\t" \
1168c2ecf20Sopenharmony_ci	".long	1b + 2, 3b\n\t" \
1178c2ecf20Sopenharmony_ci	".previous" \
1188c2ecf20Sopenharmony_ci	:"=&r" (err), "=&r" (x) \
1198c2ecf20Sopenharmony_ci	:"m" (__m(addr)), "i" (-EFAULT), "0" (err)); })
1208c2ecf20Sopenharmony_ci#endif
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci#define __put_user_size(x,ptr,size,retval)		\
1238c2ecf20Sopenharmony_cido {							\
1248c2ecf20Sopenharmony_ci	retval = 0;					\
1258c2ecf20Sopenharmony_ci	switch (size) {					\
1268c2ecf20Sopenharmony_ci	case 1:						\
1278c2ecf20Sopenharmony_ci		__put_user_asm(x, ptr, retval, "b");	\
1288c2ecf20Sopenharmony_ci		break;					\
1298c2ecf20Sopenharmony_ci	case 2:						\
1308c2ecf20Sopenharmony_ci		__put_user_asm(x, ptr, retval, "w");	\
1318c2ecf20Sopenharmony_ci		break;					\
1328c2ecf20Sopenharmony_ci	case 4:						\
1338c2ecf20Sopenharmony_ci		__put_user_asm(x, ptr, retval, "l");	\
1348c2ecf20Sopenharmony_ci		break;					\
1358c2ecf20Sopenharmony_ci	case 8:						\
1368c2ecf20Sopenharmony_ci		__put_user_u64(x, ptr, retval);		\
1378c2ecf20Sopenharmony_ci		break;					\
1388c2ecf20Sopenharmony_ci	default:					\
1398c2ecf20Sopenharmony_ci		__put_user_unknown();			\
1408c2ecf20Sopenharmony_ci	}						\
1418c2ecf20Sopenharmony_ci} while (0)
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci#ifdef CONFIG_MMU
1448c2ecf20Sopenharmony_ci#define __put_user_asm(x, addr, err, insn)			\
1458c2ecf20Sopenharmony_cido {								\
1468c2ecf20Sopenharmony_ci	__asm__ __volatile__ (					\
1478c2ecf20Sopenharmony_ci		"1:\n\t"					\
1488c2ecf20Sopenharmony_ci		"mov." insn "	%1, %2\n\t"			\
1498c2ecf20Sopenharmony_ci		"2:\n"						\
1508c2ecf20Sopenharmony_ci		".section	.fixup,\"ax\"\n"		\
1518c2ecf20Sopenharmony_ci		"3:\n\t"					\
1528c2ecf20Sopenharmony_ci		"mov.l	4f, %0\n\t"				\
1538c2ecf20Sopenharmony_ci		"jmp	@%0\n\t"				\
1548c2ecf20Sopenharmony_ci		" mov	%3, %0\n\t"				\
1558c2ecf20Sopenharmony_ci		".balign	4\n"				\
1568c2ecf20Sopenharmony_ci		"4:	.long	2b\n\t"				\
1578c2ecf20Sopenharmony_ci		".previous\n"					\
1588c2ecf20Sopenharmony_ci		".section	__ex_table,\"a\"\n\t"		\
1598c2ecf20Sopenharmony_ci		".long	1b, 3b\n\t"				\
1608c2ecf20Sopenharmony_ci		".previous"					\
1618c2ecf20Sopenharmony_ci		: "=&r" (err)					\
1628c2ecf20Sopenharmony_ci		: "r" (x), "m" (__m(addr)), "i" (-EFAULT),	\
1638c2ecf20Sopenharmony_ci		  "0" (err)					\
1648c2ecf20Sopenharmony_ci		: "memory"					\
1658c2ecf20Sopenharmony_ci	);							\
1668c2ecf20Sopenharmony_ci} while (0)
1678c2ecf20Sopenharmony_ci#else
1688c2ecf20Sopenharmony_ci#define __put_user_asm(x, addr, err, insn)		\
1698c2ecf20Sopenharmony_cido {							\
1708c2ecf20Sopenharmony_ci	__asm__ __volatile__ (				\
1718c2ecf20Sopenharmony_ci		"mov." insn "	%0, %1\n\t"		\
1728c2ecf20Sopenharmony_ci		: /* no outputs */			\
1738c2ecf20Sopenharmony_ci		: "r" (x), "m" (__m(addr))		\
1748c2ecf20Sopenharmony_ci		: "memory"				\
1758c2ecf20Sopenharmony_ci	);						\
1768c2ecf20Sopenharmony_ci} while (0)
1778c2ecf20Sopenharmony_ci#endif /* CONFIG_MMU */
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci#if defined(CONFIG_CPU_LITTLE_ENDIAN)
1808c2ecf20Sopenharmony_ci#define __put_user_u64(val,addr,retval) \
1818c2ecf20Sopenharmony_ci({ \
1828c2ecf20Sopenharmony_ci__asm__ __volatile__( \
1838c2ecf20Sopenharmony_ci	"1:\n\t" \
1848c2ecf20Sopenharmony_ci	"mov.l	%R1,%2\n\t" \
1858c2ecf20Sopenharmony_ci	"mov.l	%S1,%T2\n\t" \
1868c2ecf20Sopenharmony_ci	"2:\n" \
1878c2ecf20Sopenharmony_ci	".section	.fixup,\"ax\"\n" \
1888c2ecf20Sopenharmony_ci	"3:\n\t" \
1898c2ecf20Sopenharmony_ci	"mov.l	4f,%0\n\t" \
1908c2ecf20Sopenharmony_ci	"jmp	@%0\n\t" \
1918c2ecf20Sopenharmony_ci	" mov	%3,%0\n\t" \
1928c2ecf20Sopenharmony_ci	".balign	4\n" \
1938c2ecf20Sopenharmony_ci	"4:	.long	2b\n\t" \
1948c2ecf20Sopenharmony_ci	".previous\n" \
1958c2ecf20Sopenharmony_ci	".section	__ex_table,\"a\"\n\t" \
1968c2ecf20Sopenharmony_ci	".long	1b, 3b\n\t" \
1978c2ecf20Sopenharmony_ci	".previous" \
1988c2ecf20Sopenharmony_ci	: "=r" (retval) \
1998c2ecf20Sopenharmony_ci	: "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \
2008c2ecf20Sopenharmony_ci        : "memory"); })
2018c2ecf20Sopenharmony_ci#else
2028c2ecf20Sopenharmony_ci#define __put_user_u64(val,addr,retval) \
2038c2ecf20Sopenharmony_ci({ \
2048c2ecf20Sopenharmony_ci__asm__ __volatile__( \
2058c2ecf20Sopenharmony_ci	"1:\n\t" \
2068c2ecf20Sopenharmony_ci	"mov.l	%S1,%2\n\t" \
2078c2ecf20Sopenharmony_ci	"mov.l	%R1,%T2\n\t" \
2088c2ecf20Sopenharmony_ci	"2:\n" \
2098c2ecf20Sopenharmony_ci	".section	.fixup,\"ax\"\n" \
2108c2ecf20Sopenharmony_ci	"3:\n\t" \
2118c2ecf20Sopenharmony_ci	"mov.l	4f,%0\n\t" \
2128c2ecf20Sopenharmony_ci	"jmp	@%0\n\t" \
2138c2ecf20Sopenharmony_ci	" mov	%3,%0\n\t" \
2148c2ecf20Sopenharmony_ci	".balign	4\n" \
2158c2ecf20Sopenharmony_ci	"4:	.long	2b\n\t" \
2168c2ecf20Sopenharmony_ci	".previous\n" \
2178c2ecf20Sopenharmony_ci	".section	__ex_table,\"a\"\n\t" \
2188c2ecf20Sopenharmony_ci	".long	1b, 3b\n\t" \
2198c2ecf20Sopenharmony_ci	".previous" \
2208c2ecf20Sopenharmony_ci	: "=r" (retval) \
2218c2ecf20Sopenharmony_ci	: "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \
2228c2ecf20Sopenharmony_ci        : "memory"); })
2238c2ecf20Sopenharmony_ci#endif
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ciextern void __put_user_unknown(void);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci#endif /* __ASM_SH_UACCESS_32_H */
228