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
__put_user_fn(size_t size,void __user * ptr,void * x)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
__get_user_fn(size_t size,const void __user * ptr,void * x)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