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