xref: /linux/arch/csky/include/asm/uaccess.h (revision 41e0d49104dbff888ef6446ea46842fde66c0a76)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 
3 #ifndef __ASM_CSKY_UACCESS_H
4 #define __ASM_CSKY_UACCESS_H
5 
6 /*
7  * __put_user_fn
8  */
9 extern int __put_user_bad(void);
10 
11 #define __put_user_asm_b(x, ptr, err)			\
12 do {							\
13 	int errcode;					\
14 	__asm__ __volatile__(				\
15 	"1:     stb   %1, (%2,0)	\n"		\
16 	"       br    3f		\n"		\
17 	"2:     mov   %0, %3		\n"		\
18 	"       br    3f		\n"		\
19 	".section __ex_table, \"a\"	\n"		\
20 	".align   2			\n"		\
21 	".long    1b,2b			\n"		\
22 	".previous			\n"		\
23 	"3:				\n"		\
24 	: "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode)	\
25 	: "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT)	\
26 	: "memory");					\
27 } while (0)
28 
29 #define __put_user_asm_h(x, ptr, err)			\
30 do {							\
31 	int errcode;					\
32 	__asm__ __volatile__(				\
33 	"1:     sth   %1, (%2,0)	\n"		\
34 	"       br    3f		\n"		\
35 	"2:     mov   %0, %3		\n"		\
36 	"       br    3f		\n"		\
37 	".section __ex_table, \"a\"	\n"		\
38 	".align   2			\n"		\
39 	".long    1b,2b			\n"		\
40 	".previous			\n"		\
41 	"3:				\n"		\
42 	: "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode)	\
43 	: "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT)	\
44 	: "memory");					\
45 } while (0)
46 
47 #define __put_user_asm_w(x, ptr, err)			\
48 do {							\
49 	int errcode;					\
50 	__asm__ __volatile__(				\
51 	"1:     stw   %1, (%2,0)	\n"		\
52 	"       br    3f		\n"		\
53 	"2:     mov   %0, %3		\n"		\
54 	"       br    3f		\n"		\
55 	".section __ex_table,\"a\"	\n"		\
56 	".align   2			\n"		\
57 	".long    1b, 2b		\n"		\
58 	".previous			\n"		\
59 	"3:				\n"		\
60 	: "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode)	\
61 	: "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT)	\
62 	: "memory");					\
63 } while (0)
64 
65 #define __put_user_asm_64(x, ptr, err)			\
66 do {							\
67 	int tmp;					\
68 	int errcode;					\
69 							\
70 	__asm__ __volatile__(				\
71 	"     ldw     %3, (%1, 0)     \n"		\
72 	"1:   stw     %3, (%2, 0)     \n"		\
73 	"     ldw     %3, (%1, 4)     \n"		\
74 	"2:   stw     %3, (%2, 4)     \n"		\
75 	"     br      4f              \n"		\
76 	"3:   mov     %0, %4          \n"		\
77 	"     br      4f              \n"		\
78 	".section __ex_table, \"a\"   \n"		\
79 	".align   2                   \n"		\
80 	".long    1b, 3b              \n"		\
81 	".long    2b, 3b              \n"		\
82 	".previous                    \n"		\
83 	"4:                           \n"		\
84 	: "=r"(err), "=r"(x), "=r"(ptr),		\
85 	  "=r"(tmp), "=r"(errcode)			\
86 	: "0"(err), "1"(x), "2"(ptr), "3"(0),		\
87 	  "4"(-EFAULT)					\
88 	: "memory");					\
89 } while (0)
90 
91 static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
92 {
93 	int retval = 0;
94 	u32 tmp;
95 
96 	switch (size) {
97 	case 1:
98 		tmp = *(u8 *)x;
99 		__put_user_asm_b(tmp, ptr, retval);
100 		break;
101 	case 2:
102 		tmp = *(u16 *)x;
103 		__put_user_asm_h(tmp, ptr, retval);
104 		break;
105 	case 4:
106 		tmp = *(u32 *)x;
107 		__put_user_asm_w(tmp, ptr, retval);
108 		break;
109 	case 8:
110 		__put_user_asm_64(x, (u64 *)ptr, retval);
111 		break;
112 	}
113 
114 	return retval;
115 }
116 #define __put_user_fn __put_user_fn
117 
118 /*
119  * __get_user_fn
120  */
121 extern int __get_user_bad(void);
122 
123 #define __get_user_asm_common(x, ptr, ins, err)		\
124 do {							\
125 	int errcode;					\
126 	__asm__ __volatile__(				\
127 	"1:   " ins " %1, (%4, 0)	\n"		\
128 	"       br    3f		\n"		\
129 	"2:     mov   %0, %2		\n"		\
130 	"       movi  %1, 0		\n"		\
131 	"       br    3f		\n"		\
132 	".section __ex_table,\"a\"      \n"		\
133 	".align   2			\n"		\
134 	".long    1b, 2b		\n"		\
135 	".previous			\n"		\
136 	"3:				\n" 		\
137 	: "=r"(err), "=r"(x), "=r"(errcode)		\
138 	: "0"(0), "r"(ptr), "2"(-EFAULT)		\
139 	: "memory");					\
140 } while (0)
141 
142 #define __get_user_asm_64(x, ptr, err)			\
143 do {							\
144 	int tmp;					\
145 	int errcode;					\
146 							\
147 	__asm__ __volatile__(				\
148 	"1:   ldw     %3, (%2, 0)     \n"		\
149 	"     stw     %3, (%1, 0)     \n"		\
150 	"2:   ldw     %3, (%2, 4)     \n"		\
151 	"     stw     %3, (%1, 4)     \n"		\
152 	"     br      4f              \n"		\
153 	"3:   mov     %0, %4          \n"		\
154 	"     br      4f              \n"		\
155 	".section __ex_table, \"a\"   \n"		\
156 	".align   2                   \n"		\
157 	".long    1b, 3b              \n"		\
158 	".long    2b, 3b              \n"		\
159 	".previous                    \n"		\
160 	"4:                           \n"		\
161 	: "=r"(err), "=r"(x), "=r"(ptr),		\
162 	  "=r"(tmp), "=r"(errcode)			\
163 	: "0"(err), "1"(x), "2"(ptr), "3"(0),		\
164 	  "4"(-EFAULT)					\
165 	: "memory");					\
166 } while (0)
167 
168 static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
169 {
170 	int retval;
171 	u32 tmp;
172 
173 	switch (size) {
174 	case 1:
175 		__get_user_asm_common(tmp, ptr, "ldb", retval);
176 		*(u8 *)x = (u8)tmp;
177 		break;
178 	case 2:
179 		__get_user_asm_common(tmp, ptr, "ldh", retval);
180 		*(u16 *)x = (u16)tmp;
181 		break;
182 	case 4:
183 		__get_user_asm_common(tmp, ptr, "ldw", retval);
184 		*(u32 *)x = (u32)tmp;
185 		break;
186 	case 8:
187 		__get_user_asm_64(x, ptr, retval);
188 		break;
189 	}
190 
191 	return retval;
192 }
193 #define __get_user_fn __get_user_fn
194 
195 unsigned long raw_copy_from_user(void *to, const void *from, unsigned long n);
196 unsigned long raw_copy_to_user(void *to, const void *from, unsigned long n);
197 
198 unsigned long __clear_user(void __user *to, unsigned long n);
199 #define __clear_user __clear_user
200 
201 #include <asm-generic/uaccess.h>
202 
203 #endif /* __ASM_CSKY_UACCESS_H */
204