• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Authors:    Bjorn Wesen (bjornw@axis.com)
3  *	       Hans-Peter Nilsson (hp@axis.com)
4  *
5  */
6 #ifndef _CRIS_ARCH_UACCESS_H
7 #define _CRIS_ARCH_UACCESS_H
8 
9 /*
10  * We don't tell gcc that we are accessing memory, but this is OK
11  * because we do not write to any memory gcc knows about, so there
12  * are no aliasing issues.
13  *
14  * Note that PC at a fault is the address *after* the faulting
15  * instruction.
16  */
17 #define __put_user_asm(x, addr, err, op)			\
18 	__asm__ __volatile__(					\
19 		"	"op" %1,[%2]\n"				\
20 		"2:\n"						\
21 		"	.section .fixup,\"ax\"\n"		\
22 		"3:	move.d %3,%0\n"				\
23 		"	jump 2b\n"				\
24 		"	.previous\n"				\
25 		"	.section __ex_table,\"a\"\n"		\
26 		"	.dword 2b,3b\n"				\
27 		"	.previous\n"				\
28 		: "=r" (err)					\
29 		: "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
30 
31 #define __put_user_asm_64(x, addr, err)				\
32 	__asm__ __volatile__(					\
33 		"	move.d %M1,[%2]\n"			\
34 		"2:	move.d %H1,[%2+4]\n"			\
35 		"4:\n"						\
36 		"	.section .fixup,\"ax\"\n"		\
37 		"3:	move.d %3,%0\n"				\
38 		"	jump 4b\n"				\
39 		"	.previous\n"				\
40 		"	.section __ex_table,\"a\"\n"		\
41 		"	.dword 2b,3b\n"				\
42 		"	.dword 4b,3b\n"				\
43 		"	.previous\n"				\
44 		: "=r" (err)					\
45 		: "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
46 
47 /* See comment before __put_user_asm.  */
48 
49 #define __get_user_asm(x, addr, err, op)		\
50 	__asm__ __volatile__(				\
51 		"	"op" [%2],%1\n"			\
52 		"2:\n"					\
53 		"	.section .fixup,\"ax\"\n"	\
54 		"3:	move.d %3,%0\n"			\
55 		"	moveq 0,%1\n"			\
56 		"	jump 2b\n"			\
57 		"	.previous\n"			\
58 		"	.section __ex_table,\"a\"\n"	\
59 		"	.dword 2b,3b\n"			\
60 		"	.previous\n"			\
61 		: "=r" (err), "=r" (x)			\
62 		: "r" (addr), "g" (-EFAULT), "0" (err))
63 
64 #define __get_user_asm_64(x, addr, err)			\
65 	__asm__ __volatile__(				\
66 		"	move.d [%2],%M1\n"		\
67 		"2:	move.d [%2+4],%H1\n"		\
68 		"4:\n"					\
69 		"	.section .fixup,\"ax\"\n"	\
70 		"3:	move.d %3,%0\n"			\
71 		"	moveq 0,%1\n"			\
72 		"	jump 4b\n"			\
73 		"	.previous\n"			\
74 		"	.section __ex_table,\"a\"\n"	\
75 		"	.dword 2b,3b\n"			\
76 		"	.dword 4b,3b\n"			\
77 		"	.previous\n"			\
78 		: "=r" (err), "=r" (x)			\
79 		: "r" (addr), "g" (-EFAULT), "0" (err))
80 
81 /*
82  * Copy a null terminated string from userspace.
83  *
84  * Must return:
85  * -EFAULT		for an exception
86  * count		if we hit the buffer limit
87  * bytes copied		if we hit a null byte
88  * (without the null byte)
89  */
90 static inline long
__do_strncpy_from_user(char * dst,const char * src,long count)91 __do_strncpy_from_user(char *dst, const char *src, long count)
92 {
93 	long res;
94 
95 	if (count == 0)
96 		return 0;
97 
98 	/*
99 	 * Currently, in 2.4.0-test9, most ports use a simple byte-copy loop.
100 	 *  So do we.
101 	 *
102 	 *  This code is deduced from:
103 	 *
104 	 *	char tmp2;
105 	 *	long tmp1, tmp3
106 	 *	tmp1 = count;
107 	 *	while ((*dst++ = (tmp2 = *src++)) != 0
108 	 *	       && --tmp1)
109 	 *	  ;
110 	 *
111 	 *	res = count - tmp1;
112 	 *
113 	 *  with tweaks.
114 	 */
115 
116 	__asm__ __volatile__ (
117 		"	move.d %3,%0\n"
118 		"	move.b [%2+],$r9\n"
119 		"1:	beq 2f\n"
120 		"	move.b $r9,[%1+]\n"
121 
122 		"	subq 1,%0\n"
123 		"	bne 1b\n"
124 		"	move.b [%2+],$r9\n"
125 
126 		"2:	sub.d %3,%0\n"
127 		"	neg.d %0,%0\n"
128 		"3:\n"
129 		"	.section .fixup,\"ax\"\n"
130 		"4:	move.d %7,%0\n"
131 		"	jump 3b\n"
132 
133 		/* There's one address for a fault at the first move, and
134 		   two possible PC values for a fault at the second move,
135 		   being a delay-slot filler.  However, the branch-target
136 		   for the second move is the same as the first address.
137 		   Just so you don't get confused...  */
138 		"	.previous\n"
139 		"	.section __ex_table,\"a\"\n"
140 		"	.dword 1b,4b\n"
141 		"	.dword 2b,4b\n"
142 		"	.previous"
143 		: "=r" (res), "=r" (dst), "=r" (src), "=r" (count)
144 		: "3" (count), "1" (dst), "2" (src), "g" (-EFAULT)
145 		: "r9");
146 
147 	return res;
148 }
149 
150 /* A few copy asms to build up the more complex ones from.
151 
152    Note again, a post-increment is performed regardless of whether a bus
153    fault occurred in that instruction, and PC for a faulted insn is the
154    address *after* the insn.  */
155 
156 #define __asm_copy_user_cont(to, from, ret, COPY, FIXUP, TENTRY) \
157 	__asm__ __volatile__ (				\
158 			COPY				\
159 		"1:\n"					\
160 		"	.section .fixup,\"ax\"\n"	\
161 			FIXUP				\
162 		"	jump 1b\n"			\
163 		"	.previous\n"			\
164 		"	.section __ex_table,\"a\"\n"	\
165 			TENTRY				\
166 		"	.previous\n"			\
167 		: "=r" (to), "=r" (from), "=r" (ret)	\
168 		: "0" (to), "1" (from), "2" (ret)	\
169 		: "r9", "memory")
170 
171 #define __asm_copy_from_user_1(to, from, ret) \
172 	__asm_copy_user_cont(to, from, ret,	\
173 		"	move.b [%1+],$r9\n"	\
174 		"2:	move.b $r9,[%0+]\n",	\
175 		"3:	addq 1,%2\n"		\
176 		"	clear.b [%0+]\n",	\
177 		"	.dword 2b,3b\n")
178 
179 #define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
180 	__asm_copy_user_cont(to, from, ret,		\
181 		"	move.w [%1+],$r9\n"		\
182 		"2:	move.w $r9,[%0+]\n" COPY,	\
183 		"3:	addq 2,%2\n"			\
184 		"	clear.w [%0+]\n" FIXUP,		\
185 		"	.dword 2b,3b\n" TENTRY)
186 
187 #define __asm_copy_from_user_2(to, from, ret) \
188 	__asm_copy_from_user_2x_cont(to, from, ret, "", "", "")
189 
190 #define __asm_copy_from_user_3(to, from, ret)		\
191 	__asm_copy_from_user_2x_cont(to, from, ret,	\
192 		"	move.b [%1+],$r9\n"		\
193 		"4:	move.b $r9,[%0+]\n",		\
194 		"5:	addq 1,%2\n"			\
195 		"	clear.b [%0+]\n",		\
196 		"	.dword 4b,5b\n")
197 
198 #define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
199 	__asm_copy_user_cont(to, from, ret,		\
200 		"	move.d [%1+],$r9\n"		\
201 		"2:	move.d $r9,[%0+]\n" COPY,	\
202 		"3:	addq 4,%2\n"			\
203 		"	clear.d [%0+]\n" FIXUP,		\
204 		"	.dword 2b,3b\n" TENTRY)
205 
206 #define __asm_copy_from_user_4(to, from, ret) \
207 	__asm_copy_from_user_4x_cont(to, from, ret, "", "", "")
208 
209 #define __asm_copy_from_user_5(to, from, ret) \
210 	__asm_copy_from_user_4x_cont(to, from, ret,	\
211 		"	move.b [%1+],$r9\n"		\
212 		"4:	move.b $r9,[%0+]\n",		\
213 		"5:	addq 1,%2\n"			\
214 		"	clear.b [%0+]\n",		\
215 		"	.dword 4b,5b\n")
216 
217 #define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
218 	__asm_copy_from_user_4x_cont(to, from, ret,	\
219 		"	move.w [%1+],$r9\n"		\
220 		"4:	move.w $r9,[%0+]\n" COPY,	\
221 		"5:	addq 2,%2\n"			\
222 		"	clear.w [%0+]\n" FIXUP,		\
223 		"	.dword 4b,5b\n" TENTRY)
224 
225 #define __asm_copy_from_user_6(to, from, ret) \
226 	__asm_copy_from_user_6x_cont(to, from, ret, "", "", "")
227 
228 #define __asm_copy_from_user_7(to, from, ret) \
229 	__asm_copy_from_user_6x_cont(to, from, ret,	\
230 		"	move.b [%1+],$r9\n"		\
231 		"6:	move.b $r9,[%0+]\n",		\
232 		"7:	addq 1,%2\n"			\
233 		"	clear.b [%0+]\n",		\
234 		"	.dword 6b,7b\n")
235 
236 #define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
237 	__asm_copy_from_user_4x_cont(to, from, ret,	\
238 		"	move.d [%1+],$r9\n"		\
239 		"4:	move.d $r9,[%0+]\n" COPY,	\
240 		"5:	addq 4,%2\n"			\
241 		"	clear.d [%0+]\n" FIXUP,		\
242 		"	.dword 4b,5b\n" TENTRY)
243 
244 #define __asm_copy_from_user_8(to, from, ret) \
245 	__asm_copy_from_user_8x_cont(to, from, ret, "", "", "")
246 
247 #define __asm_copy_from_user_9(to, from, ret) \
248 	__asm_copy_from_user_8x_cont(to, from, ret,	\
249 		"	move.b [%1+],$r9\n"		\
250 		"6:	move.b $r9,[%0+]\n",		\
251 		"7:	addq 1,%2\n"			\
252 		"	clear.b [%0+]\n",		\
253 		"	.dword 6b,7b\n")
254 
255 #define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
256 	__asm_copy_from_user_8x_cont(to, from, ret,	\
257 		"	move.w [%1+],$r9\n"		\
258 		"6:	move.w $r9,[%0+]\n" COPY,	\
259 		"7:	addq 2,%2\n"			\
260 		"	clear.w [%0+]\n" FIXUP,		\
261 		"	.dword 6b,7b\n" TENTRY)
262 
263 #define __asm_copy_from_user_10(to, from, ret) \
264 	__asm_copy_from_user_10x_cont(to, from, ret, "", "", "")
265 
266 #define __asm_copy_from_user_11(to, from, ret)		\
267 	__asm_copy_from_user_10x_cont(to, from, ret,	\
268 		"	move.b [%1+],$r9\n"		\
269 		"8:	move.b $r9,[%0+]\n",		\
270 		"9:	addq 1,%2\n"			\
271 		"	clear.b [%0+]\n",		\
272 		"	.dword 8b,9b\n")
273 
274 #define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
275 	__asm_copy_from_user_8x_cont(to, from, ret,	\
276 		"	move.d [%1+],$r9\n"		\
277 		"6:	move.d $r9,[%0+]\n" COPY,	\
278 		"7:	addq 4,%2\n"			\
279 		"	clear.d [%0+]\n" FIXUP,		\
280 		"	.dword 6b,7b\n" TENTRY)
281 
282 #define __asm_copy_from_user_12(to, from, ret) \
283 	__asm_copy_from_user_12x_cont(to, from, ret, "", "", "")
284 
285 #define __asm_copy_from_user_13(to, from, ret) \
286 	__asm_copy_from_user_12x_cont(to, from, ret,	\
287 		"	move.b [%1+],$r9\n"		\
288 		"8:	move.b $r9,[%0+]\n",		\
289 		"9:	addq 1,%2\n"			\
290 		"	clear.b [%0+]\n",		\
291 		"	.dword 8b,9b\n")
292 
293 #define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
294 	__asm_copy_from_user_12x_cont(to, from, ret,	\
295 		"	move.w [%1+],$r9\n"		\
296 		"8:	move.w $r9,[%0+]\n" COPY,	\
297 		"9:	addq 2,%2\n"			\
298 		"	clear.w [%0+]\n" FIXUP,		\
299 		"	.dword 8b,9b\n" TENTRY)
300 
301 #define __asm_copy_from_user_14(to, from, ret) \
302 	__asm_copy_from_user_14x_cont(to, from, ret, "", "", "")
303 
304 #define __asm_copy_from_user_15(to, from, ret) \
305 	__asm_copy_from_user_14x_cont(to, from, ret,	\
306 		"	move.b [%1+],$r9\n"		\
307 		"10:	move.b $r9,[%0+]\n",		\
308 		"11:	addq 1,%2\n"			\
309 		"	clear.b [%0+]\n",		\
310 		"	.dword 10b,11b\n")
311 
312 #define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
313 	__asm_copy_from_user_12x_cont(to, from, ret,	\
314 		"	move.d [%1+],$r9\n"		\
315 		"8:	move.d $r9,[%0+]\n" COPY,	\
316 		"9:	addq 4,%2\n"			\
317 		"	clear.d [%0+]\n" FIXUP,		\
318 		"	.dword 8b,9b\n" TENTRY)
319 
320 #define __asm_copy_from_user_16(to, from, ret) \
321 	__asm_copy_from_user_16x_cont(to, from, ret, "", "", "")
322 
323 #define __asm_copy_from_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
324 	__asm_copy_from_user_16x_cont(to, from, ret,	\
325 		"	move.d [%1+],$r9\n"		\
326 		"10:	move.d $r9,[%0+]\n" COPY,	\
327 		"11:	addq 4,%2\n"			\
328 		"	clear.d [%0+]\n" FIXUP,		\
329 		"	.dword 10b,11b\n" TENTRY)
330 
331 #define __asm_copy_from_user_20(to, from, ret) \
332 	__asm_copy_from_user_20x_cont(to, from, ret, "", "", "")
333 
334 #define __asm_copy_from_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
335 	__asm_copy_from_user_20x_cont(to, from, ret,	\
336 		"	move.d [%1+],$r9\n"		\
337 		"12:	move.d $r9,[%0+]\n" COPY,	\
338 		"13:	addq 4,%2\n"			\
339 		"	clear.d [%0+]\n" FIXUP,		\
340 		"	.dword 12b,13b\n" TENTRY)
341 
342 #define __asm_copy_from_user_24(to, from, ret) \
343 	__asm_copy_from_user_24x_cont(to, from, ret, "", "", "")
344 
345 /* And now, the to-user ones.  */
346 
347 #define __asm_copy_to_user_1(to, from, ret)	\
348 	__asm_copy_user_cont(to, from, ret,	\
349 		"	move.b [%1+],$r9\n"	\
350 		"	move.b $r9,[%0+]\n2:\n",	\
351 		"3:	addq 1,%2\n",		\
352 		"	.dword 2b,3b\n")
353 
354 #define __asm_copy_to_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
355 	__asm_copy_user_cont(to, from, ret,		\
356 		"	move.w [%1+],$r9\n"		\
357 		"	move.w $r9,[%0+]\n2:\n" COPY,	\
358 		"3:	addq 2,%2\n" FIXUP,		\
359 		"	.dword 2b,3b\n" TENTRY)
360 
361 #define __asm_copy_to_user_2(to, from, ret) \
362 	__asm_copy_to_user_2x_cont(to, from, ret, "", "", "")
363 
364 #define __asm_copy_to_user_3(to, from, ret) \
365 	__asm_copy_to_user_2x_cont(to, from, ret,	\
366 		"	move.b [%1+],$r9\n"		\
367 		"	move.b $r9,[%0+]\n4:\n",		\
368 		"5:	addq 1,%2\n",			\
369 		"	.dword 4b,5b\n")
370 
371 #define __asm_copy_to_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
372 	__asm_copy_user_cont(to, from, ret,		\
373 		"	move.d [%1+],$r9\n"		\
374 		"	move.d $r9,[%0+]\n2:\n" COPY,	\
375 		"3:	addq 4,%2\n" FIXUP,		\
376 		"	.dword 2b,3b\n" TENTRY)
377 
378 #define __asm_copy_to_user_4(to, from, ret) \
379 	__asm_copy_to_user_4x_cont(to, from, ret, "", "", "")
380 
381 #define __asm_copy_to_user_5(to, from, ret) \
382 	__asm_copy_to_user_4x_cont(to, from, ret,	\
383 		"	move.b [%1+],$r9\n"		\
384 		"	move.b $r9,[%0+]\n4:\n",		\
385 		"5:	addq 1,%2\n",			\
386 		"	.dword 4b,5b\n")
387 
388 #define __asm_copy_to_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
389 	__asm_copy_to_user_4x_cont(to, from, ret,	\
390 		"	move.w [%1+],$r9\n"		\
391 		"	move.w $r9,[%0+]\n4:\n" COPY,	\
392 		"5:	addq 2,%2\n" FIXUP,		\
393 		"	.dword 4b,5b\n" TENTRY)
394 
395 #define __asm_copy_to_user_6(to, from, ret) \
396 	__asm_copy_to_user_6x_cont(to, from, ret, "", "", "")
397 
398 #define __asm_copy_to_user_7(to, from, ret) \
399 	__asm_copy_to_user_6x_cont(to, from, ret,	\
400 		"	move.b [%1+],$r9\n"		\
401 		"	move.b $r9,[%0+]\n6:\n",		\
402 		"7:	addq 1,%2\n",			\
403 		"	.dword 6b,7b\n")
404 
405 #define __asm_copy_to_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
406 	__asm_copy_to_user_4x_cont(to, from, ret,	\
407 		"	move.d [%1+],$r9\n"		\
408 		"	move.d $r9,[%0+]\n4:\n" COPY,	\
409 		"5:	addq 4,%2\n"  FIXUP,		\
410 		"	.dword 4b,5b\n" TENTRY)
411 
412 #define __asm_copy_to_user_8(to, from, ret) \
413 	__asm_copy_to_user_8x_cont(to, from, ret, "", "", "")
414 
415 #define __asm_copy_to_user_9(to, from, ret) \
416 	__asm_copy_to_user_8x_cont(to, from, ret,	\
417 		"	move.b [%1+],$r9\n"		\
418 		"	move.b $r9,[%0+]\n6:\n",		\
419 		"7:	addq 1,%2\n",			\
420 		"	.dword 6b,7b\n")
421 
422 #define __asm_copy_to_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
423 	__asm_copy_to_user_8x_cont(to, from, ret,	\
424 		"	move.w [%1+],$r9\n"		\
425 		"	move.w $r9,[%0+]\n6:\n" COPY,	\
426 		"7:	addq 2,%2\n" FIXUP,		\
427 		"	.dword 6b,7b\n" TENTRY)
428 
429 #define __asm_copy_to_user_10(to, from, ret) \
430 	__asm_copy_to_user_10x_cont(to, from, ret, "", "", "")
431 
432 #define __asm_copy_to_user_11(to, from, ret) \
433 	__asm_copy_to_user_10x_cont(to, from, ret,	\
434 		"	move.b [%1+],$r9\n"		\
435 		"	move.b $r9,[%0+]\n8:\n",		\
436 		"9:	addq 1,%2\n",			\
437 		"	.dword 8b,9b\n")
438 
439 #define __asm_copy_to_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
440 	__asm_copy_to_user_8x_cont(to, from, ret,	\
441 		"	move.d [%1+],$r9\n"		\
442 		"	move.d $r9,[%0+]\n6:\n" COPY,	\
443 		"7:	addq 4,%2\n" FIXUP,		\
444 		"	.dword 6b,7b\n" TENTRY)
445 
446 #define __asm_copy_to_user_12(to, from, ret) \
447 	__asm_copy_to_user_12x_cont(to, from, ret, "", "", "")
448 
449 #define __asm_copy_to_user_13(to, from, ret) \
450 	__asm_copy_to_user_12x_cont(to, from, ret,	\
451 		"	move.b [%1+],$r9\n"		\
452 		"	move.b $r9,[%0+]\n8:\n",		\
453 		"9:	addq 1,%2\n",			\
454 		"	.dword 8b,9b\n")
455 
456 #define __asm_copy_to_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
457 	__asm_copy_to_user_12x_cont(to, from, ret,	\
458 		"	move.w [%1+],$r9\n"		\
459 		"	move.w $r9,[%0+]\n8:\n" COPY,	\
460 		"9:	addq 2,%2\n" FIXUP,		\
461 		"	.dword 8b,9b\n" TENTRY)
462 
463 #define __asm_copy_to_user_14(to, from, ret)	\
464 	__asm_copy_to_user_14x_cont(to, from, ret, "", "", "")
465 
466 #define __asm_copy_to_user_15(to, from, ret) \
467 	__asm_copy_to_user_14x_cont(to, from, ret,	\
468 		"	move.b [%1+],$r9\n"		\
469 		"	move.b $r9,[%0+]\n10:\n",		\
470 		"11:	addq 1,%2\n",			\
471 		"	.dword 10b,11b\n")
472 
473 #define __asm_copy_to_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
474 	__asm_copy_to_user_12x_cont(to, from, ret,	\
475 		"	move.d [%1+],$r9\n"		\
476 		"	move.d $r9,[%0+]\n8:\n" COPY,	\
477 		"9:	addq 4,%2\n" FIXUP,		\
478 		"	.dword 8b,9b\n" TENTRY)
479 
480 #define __asm_copy_to_user_16(to, from, ret) \
481 	__asm_copy_to_user_16x_cont(to, from, ret, "", "", "")
482 
483 #define __asm_copy_to_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
484 	__asm_copy_to_user_16x_cont(to, from, ret,	\
485 		"	move.d [%1+],$r9\n"		\
486 		"	move.d $r9,[%0+]\n10:\n" COPY,	\
487 		"11:	addq 4,%2\n" FIXUP,		\
488 		"	.dword 10b,11b\n" TENTRY)
489 
490 #define __asm_copy_to_user_20(to, from, ret) \
491 	__asm_copy_to_user_20x_cont(to, from, ret, "", "", "")
492 
493 #define __asm_copy_to_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY)	\
494 	__asm_copy_to_user_20x_cont(to, from, ret,	\
495 		"	move.d [%1+],$r9\n"		\
496 		"	move.d $r9,[%0+]\n12:\n" COPY,	\
497 		"13:	addq 4,%2\n" FIXUP,		\
498 		"	.dword 12b,13b\n" TENTRY)
499 
500 #define __asm_copy_to_user_24(to, from, ret)	\
501 	__asm_copy_to_user_24x_cont(to, from, ret, "", "", "")
502 
503 /* Define a few clearing asms with exception handlers.  */
504 
505 /* This frame-asm is like the __asm_copy_user_cont one, but has one less
506    input.  */
507 
508 #define __asm_clear(to, ret, CLEAR, FIXUP, TENTRY) \
509 	__asm__ __volatile__ (				\
510 			CLEAR				\
511 		"1:\n"					\
512 		"	.section .fixup,\"ax\"\n"	\
513 			FIXUP				\
514 		"	jump 1b\n"			\
515 		"	.previous\n"			\
516 		"	.section __ex_table,\"a\"\n"	\
517 			TENTRY				\
518 		"	.previous"			\
519 		: "=r" (to), "=r" (ret)			\
520 		: "0" (to), "1" (ret)			\
521 		: "memory")
522 
523 #define __asm_clear_1(to, ret) \
524 	__asm_clear(to, ret,			\
525 		"	clear.b [%0+]\n2:\n",	\
526 		"3:	addq 1,%1\n",		\
527 		"	.dword 2b,3b\n")
528 
529 #define __asm_clear_2(to, ret) \
530 	__asm_clear(to, ret,			\
531 		"	clear.w [%0+]\n2:\n",	\
532 		"3:	addq 2,%1\n",		\
533 		"	.dword 2b,3b\n")
534 
535 #define __asm_clear_3(to, ret) \
536      __asm_clear(to, ret,			\
537 		 "	clear.w [%0+]\n"	\
538 		 "2:	clear.b [%0+]\n3:\n",	\
539 		 "4:	addq 2,%1\n"		\
540 		 "5:	addq 1,%1\n",		\
541 		 "	.dword 2b,4b\n"		\
542 		 "	.dword 3b,5b\n")
543 
544 #define __asm_clear_4x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
545 	__asm_clear(to, ret,				\
546 		"	clear.d [%0+]\n2:\n" CLEAR,	\
547 		"3:	addq 4,%1\n" FIXUP,		\
548 		"	.dword 2b,3b\n" TENTRY)
549 
550 #define __asm_clear_4(to, ret) \
551 	__asm_clear_4x_cont(to, ret, "", "", "")
552 
553 #define __asm_clear_8x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
554 	__asm_clear_4x_cont(to, ret,			\
555 		"	clear.d [%0+]\n4:\n" CLEAR,	\
556 		"5:	addq 4,%1\n" FIXUP,		\
557 		"	.dword 4b,5b\n" TENTRY)
558 
559 #define __asm_clear_8(to, ret) \
560 	__asm_clear_8x_cont(to, ret, "", "", "")
561 
562 #define __asm_clear_12x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
563 	__asm_clear_8x_cont(to, ret,			\
564 		"	clear.d [%0+]\n6:\n" CLEAR,	\
565 		"7:	addq 4,%1\n" FIXUP,		\
566 		"	.dword 6b,7b\n" TENTRY)
567 
568 #define __asm_clear_12(to, ret) \
569 	__asm_clear_12x_cont(to, ret, "", "", "")
570 
571 #define __asm_clear_16x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
572 	__asm_clear_12x_cont(to, ret,			\
573 		"	clear.d [%0+]\n8:\n" CLEAR,	\
574 		"9:	addq 4,%1\n" FIXUP,		\
575 		"	.dword 8b,9b\n" TENTRY)
576 
577 #define __asm_clear_16(to, ret) \
578 	__asm_clear_16x_cont(to, ret, "", "", "")
579 
580 #define __asm_clear_20x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
581 	__asm_clear_16x_cont(to, ret,			\
582 		"	clear.d [%0+]\n10:\n" CLEAR,	\
583 		"11:	addq 4,%1\n" FIXUP,		\
584 		"	.dword 10b,11b\n" TENTRY)
585 
586 #define __asm_clear_20(to, ret) \
587 	__asm_clear_20x_cont(to, ret, "", "", "")
588 
589 #define __asm_clear_24x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
590 	__asm_clear_20x_cont(to, ret,			\
591 		"	clear.d [%0+]\n12:\n" CLEAR,	\
592 		"13:	addq 4,%1\n" FIXUP,		\
593 		"	.dword 12b,13b\n" TENTRY)
594 
595 #define __asm_clear_24(to, ret) \
596 	__asm_clear_24x_cont(to, ret, "", "", "")
597 
598 /*
599  * Return the size of a string (including the ending 0)
600  *
601  * Return length of string in userspace including terminating 0
602  * or 0 for error.  Return a value greater than N if too long.
603  */
604 
605 static inline long
strnlen_user(const char * s,long n)606 strnlen_user(const char *s, long n)
607 {
608 	long res, tmp1;
609 
610 	if (!access_ok(VERIFY_READ, s, 0))
611 		return 0;
612 
613 	/*
614 	 * This code is deduced from:
615 	 *
616 	 *	tmp1 = n;
617 	 *	while (tmp1-- > 0 && *s++)
618 	 *	  ;
619 	 *
620 	 *	res = n - tmp1;
621 	 *
622 	 *  (with tweaks).
623 	 */
624 
625 	__asm__ __volatile__ (
626 		"	move.d %1,$r9\n"
627 		"0:\n"
628 		"	ble 1f\n"
629 		"	subq 1,$r9\n"
630 
631 		"	test.b [%0+]\n"
632 		"	bne 0b\n"
633 		"	test.d $r9\n"
634 		"1:\n"
635 		"	move.d %1,%0\n"
636 		"	sub.d $r9,%0\n"
637 		"2:\n"
638 		"	.section .fixup,\"ax\"\n"
639 
640 		"3:	clear.d %0\n"
641 		"	jump 2b\n"
642 
643 		/* There's one address for a fault at the first move, and
644 		   two possible PC values for a fault at the second move,
645 		   being a delay-slot filler.  However, the branch-target
646 		   for the second move is the same as the first address.
647 		   Just so you don't get confused...  */
648 		"	.previous\n"
649 		"	.section __ex_table,\"a\"\n"
650 		"	.dword 0b,3b\n"
651 		"	.dword 1b,3b\n"
652 		"	.previous\n"
653 		: "=r" (res), "=r" (tmp1)
654 		: "0" (s), "1" (n)
655 		: "r9");
656 
657 	return res;
658 }
659 
660 #endif
661