xref: /openbmc/linux/arch/sh/include/asm/uaccess_32.h (revision b2441318)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2f15cbe6fSPaul Mundt /*
3f15cbe6fSPaul Mundt  * User space memory access functions
4f15cbe6fSPaul Mundt  *
5f15cbe6fSPaul Mundt  * Copyright (C) 1999, 2002  Niibe Yutaka
6f15cbe6fSPaul Mundt  * Copyright (C) 2003 - 2008  Paul Mundt
7f15cbe6fSPaul Mundt  *
8f15cbe6fSPaul Mundt  *  Based on:
9f15cbe6fSPaul Mundt  *     MIPS implementation version 1.15 by
10f15cbe6fSPaul Mundt  *              Copyright (C) 1996, 1997, 1998 by Ralf Baechle
11f15cbe6fSPaul Mundt  *     and i386 version.
12f15cbe6fSPaul Mundt  */
13f15cbe6fSPaul Mundt #ifndef __ASM_SH_UACCESS_32_H
14f15cbe6fSPaul Mundt #define __ASM_SH_UACCESS_32_H
15f15cbe6fSPaul Mundt 
16f15cbe6fSPaul Mundt #define __get_user_size(x,ptr,size,retval)			\
17f15cbe6fSPaul Mundt do {								\
18f15cbe6fSPaul Mundt 	retval = 0;						\
19f15cbe6fSPaul Mundt 	switch (size) {						\
20f15cbe6fSPaul Mundt 	case 1:							\
21f15cbe6fSPaul Mundt 		__get_user_asm(x, ptr, retval, "b");		\
22f15cbe6fSPaul Mundt 		break;						\
23f15cbe6fSPaul Mundt 	case 2:							\
24f15cbe6fSPaul Mundt 		__get_user_asm(x, ptr, retval, "w");		\
25f15cbe6fSPaul Mundt 		break;						\
26f15cbe6fSPaul Mundt 	case 4:							\
27f15cbe6fSPaul Mundt 		__get_user_asm(x, ptr, retval, "l");		\
28f15cbe6fSPaul Mundt 		break;						\
29f15cbe6fSPaul Mundt 	default:						\
30f15cbe6fSPaul Mundt 		__get_user_unknown();				\
31f15cbe6fSPaul Mundt 		break;						\
32f15cbe6fSPaul Mundt 	}							\
33f15cbe6fSPaul Mundt } while (0)
34f15cbe6fSPaul Mundt 
35f15cbe6fSPaul Mundt #ifdef CONFIG_MMU
36f15cbe6fSPaul Mundt #define __get_user_asm(x, addr, err, insn) \
37f15cbe6fSPaul Mundt ({ \
38f15cbe6fSPaul Mundt __asm__ __volatile__( \
39f15cbe6fSPaul Mundt 	"1:\n\t" \
40f15cbe6fSPaul Mundt 	"mov." insn "	%2, %1\n\t" \
41f15cbe6fSPaul Mundt 	"2:\n" \
42f15cbe6fSPaul Mundt 	".section	.fixup,\"ax\"\n" \
43f15cbe6fSPaul Mundt 	"3:\n\t" \
44f15cbe6fSPaul Mundt 	"mov	#0, %1\n\t" \
45f15cbe6fSPaul Mundt 	"mov.l	4f, %0\n\t" \
46f15cbe6fSPaul Mundt 	"jmp	@%0\n\t" \
47f15cbe6fSPaul Mundt 	" mov	%3, %0\n\t" \
48f15cbe6fSPaul Mundt 	".balign	4\n" \
49f15cbe6fSPaul Mundt 	"4:	.long	2b\n\t" \
50f15cbe6fSPaul Mundt 	".previous\n" \
51f15cbe6fSPaul Mundt 	".section	__ex_table,\"a\"\n\t" \
52f15cbe6fSPaul Mundt 	".long	1b, 3b\n\t" \
53f15cbe6fSPaul Mundt 	".previous" \
54f15cbe6fSPaul Mundt 	:"=&r" (err), "=&r" (x) \
55f15cbe6fSPaul Mundt 	:"m" (__m(addr)), "i" (-EFAULT), "0" (err)); })
56f15cbe6fSPaul Mundt #else
57f15cbe6fSPaul Mundt #define __get_user_asm(x, addr, err, insn)		\
58f15cbe6fSPaul Mundt do {							\
59f15cbe6fSPaul Mundt 	__asm__ __volatile__ (				\
60f15cbe6fSPaul Mundt 		"mov." insn "	%1, %0\n\t"		\
61f15cbe6fSPaul Mundt 		: "=&r" (x)				\
62f15cbe6fSPaul Mundt 		: "m" (__m(addr))			\
63f15cbe6fSPaul Mundt 	);						\
64f15cbe6fSPaul Mundt } while (0)
65f15cbe6fSPaul Mundt #endif /* CONFIG_MMU */
66f15cbe6fSPaul Mundt 
67f15cbe6fSPaul Mundt extern void __get_user_unknown(void);
68f15cbe6fSPaul Mundt 
69f15cbe6fSPaul Mundt #define __put_user_size(x,ptr,size,retval)		\
70f15cbe6fSPaul Mundt do {							\
71f15cbe6fSPaul Mundt 	retval = 0;					\
72f15cbe6fSPaul Mundt 	switch (size) {					\
73f15cbe6fSPaul Mundt 	case 1:						\
74f15cbe6fSPaul Mundt 		__put_user_asm(x, ptr, retval, "b");	\
75f15cbe6fSPaul Mundt 		break;					\
76f15cbe6fSPaul Mundt 	case 2:						\
77f15cbe6fSPaul Mundt 		__put_user_asm(x, ptr, retval, "w");	\
78f15cbe6fSPaul Mundt 		break;					\
79f15cbe6fSPaul Mundt 	case 4:						\
806de9c648SOGAWA Hirofumi 		__put_user_asm(x, ptr, retval, "l");	\
81f15cbe6fSPaul Mundt 		break;					\
82f15cbe6fSPaul Mundt 	case 8:						\
83f15cbe6fSPaul Mundt 		__put_user_u64(x, ptr, retval);		\
84f15cbe6fSPaul Mundt 		break;					\
85f15cbe6fSPaul Mundt 	default:					\
86f15cbe6fSPaul Mundt 		__put_user_unknown();			\
87f15cbe6fSPaul Mundt 	}						\
88f15cbe6fSPaul Mundt } while (0)
89f15cbe6fSPaul Mundt 
90f15cbe6fSPaul Mundt #ifdef CONFIG_MMU
91f15cbe6fSPaul Mundt #define __put_user_asm(x, addr, err, insn)			\
92f15cbe6fSPaul Mundt do {								\
93f15cbe6fSPaul Mundt 	__asm__ __volatile__ (					\
94f15cbe6fSPaul Mundt 		"1:\n\t"					\
95f15cbe6fSPaul Mundt 		"mov." insn "	%1, %2\n\t"			\
96f15cbe6fSPaul Mundt 		"2:\n"						\
97f15cbe6fSPaul Mundt 		".section	.fixup,\"ax\"\n"		\
98f15cbe6fSPaul Mundt 		"3:\n\t"					\
99f15cbe6fSPaul Mundt 		"mov.l	4f, %0\n\t"				\
100f15cbe6fSPaul Mundt 		"jmp	@%0\n\t"				\
101f15cbe6fSPaul Mundt 		" mov	%3, %0\n\t"				\
102f15cbe6fSPaul Mundt 		".balign	4\n"				\
103f15cbe6fSPaul Mundt 		"4:	.long	2b\n\t"				\
104f15cbe6fSPaul Mundt 		".previous\n"					\
105f15cbe6fSPaul Mundt 		".section	__ex_table,\"a\"\n\t"		\
106f15cbe6fSPaul Mundt 		".long	1b, 3b\n\t"				\
107f15cbe6fSPaul Mundt 		".previous"					\
108f15cbe6fSPaul Mundt 		: "=&r" (err)					\
109f15cbe6fSPaul Mundt 		: "r" (x), "m" (__m(addr)), "i" (-EFAULT),	\
110f15cbe6fSPaul Mundt 		  "0" (err)					\
111f15cbe6fSPaul Mundt 		: "memory"					\
112f15cbe6fSPaul Mundt 	);							\
113f15cbe6fSPaul Mundt } while (0)
114f15cbe6fSPaul Mundt #else
115f15cbe6fSPaul Mundt #define __put_user_asm(x, addr, err, insn)		\
116f15cbe6fSPaul Mundt do {							\
117f15cbe6fSPaul Mundt 	__asm__ __volatile__ (				\
118f15cbe6fSPaul Mundt 		"mov." insn "	%0, %1\n\t"		\
119f15cbe6fSPaul Mundt 		: /* no outputs */			\
120f15cbe6fSPaul Mundt 		: "r" (x), "m" (__m(addr))		\
121f15cbe6fSPaul Mundt 		: "memory"				\
122f15cbe6fSPaul Mundt 	);						\
123f15cbe6fSPaul Mundt } while (0)
124f15cbe6fSPaul Mundt #endif /* CONFIG_MMU */
125f15cbe6fSPaul Mundt 
126f15cbe6fSPaul Mundt #if defined(CONFIG_CPU_LITTLE_ENDIAN)
127f15cbe6fSPaul Mundt #define __put_user_u64(val,addr,retval) \
128f15cbe6fSPaul Mundt ({ \
129f15cbe6fSPaul Mundt __asm__ __volatile__( \
130f15cbe6fSPaul Mundt 	"1:\n\t" \
131f15cbe6fSPaul Mundt 	"mov.l	%R1,%2\n\t" \
132f15cbe6fSPaul Mundt 	"mov.l	%S1,%T2\n\t" \
133f15cbe6fSPaul Mundt 	"2:\n" \
134f15cbe6fSPaul Mundt 	".section	.fixup,\"ax\"\n" \
135f15cbe6fSPaul Mundt 	"3:\n\t" \
136f15cbe6fSPaul Mundt 	"mov.l	4f,%0\n\t" \
137f15cbe6fSPaul Mundt 	"jmp	@%0\n\t" \
138f15cbe6fSPaul Mundt 	" mov	%3,%0\n\t" \
139f15cbe6fSPaul Mundt 	".balign	4\n" \
140f15cbe6fSPaul Mundt 	"4:	.long	2b\n\t" \
141f15cbe6fSPaul Mundt 	".previous\n" \
142f15cbe6fSPaul Mundt 	".section	__ex_table,\"a\"\n\t" \
143f15cbe6fSPaul Mundt 	".long	1b, 3b\n\t" \
144f15cbe6fSPaul Mundt 	".previous" \
145f15cbe6fSPaul Mundt 	: "=r" (retval) \
146f15cbe6fSPaul Mundt 	: "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \
147f15cbe6fSPaul Mundt         : "memory"); })
148f15cbe6fSPaul Mundt #else
149f15cbe6fSPaul Mundt #define __put_user_u64(val,addr,retval) \
150f15cbe6fSPaul Mundt ({ \
151f15cbe6fSPaul Mundt __asm__ __volatile__( \
152f15cbe6fSPaul Mundt 	"1:\n\t" \
153f15cbe6fSPaul Mundt 	"mov.l	%S1,%2\n\t" \
154f15cbe6fSPaul Mundt 	"mov.l	%R1,%T2\n\t" \
155f15cbe6fSPaul Mundt 	"2:\n" \
156f15cbe6fSPaul Mundt 	".section	.fixup,\"ax\"\n" \
157f15cbe6fSPaul Mundt 	"3:\n\t" \
158f15cbe6fSPaul Mundt 	"mov.l	4f,%0\n\t" \
159f15cbe6fSPaul Mundt 	"jmp	@%0\n\t" \
160f15cbe6fSPaul Mundt 	" mov	%3,%0\n\t" \
161f15cbe6fSPaul Mundt 	".balign	4\n" \
162f15cbe6fSPaul Mundt 	"4:	.long	2b\n\t" \
163f15cbe6fSPaul Mundt 	".previous\n" \
164f15cbe6fSPaul Mundt 	".section	__ex_table,\"a\"\n\t" \
165f15cbe6fSPaul Mundt 	".long	1b, 3b\n\t" \
166f15cbe6fSPaul Mundt 	".previous" \
167f15cbe6fSPaul Mundt 	: "=r" (retval) \
168f15cbe6fSPaul Mundt 	: "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \
169f15cbe6fSPaul Mundt         : "memory"); })
170f15cbe6fSPaul Mundt #endif
171f15cbe6fSPaul Mundt 
172f15cbe6fSPaul Mundt extern void __put_user_unknown(void);
173f15cbe6fSPaul Mundt 
174f15cbe6fSPaul Mundt #endif /* __ASM_SH_UACCESS_32_H */
175