File: /usr/src/linux/include/asm-cris/uaccess.h

1     /* 
2      * Authors:    Bjorn Wesen (bjornw@axis.com)
3      *	       Hans-Peter Nilsson (hp@axis.com)
4      *
5      * $Log: uaccess.h,v $
6      * Revision 1.5  2000/10/25 03:33:21  hp
7      * - Provide implementation for everything else but get_user and put_user;
8      *   copying inline to/from user for constant length 0..16, 20, 24, and
9      *   clearing for 0..4, 8, 12, 16, 20, 24, strncpy_from_user and strnlen_user
10      *   always inline.
11      * - Constraints for destination addr in get_user cannot be memory, only reg.
12      * - Correct labels for PC at expected fault points.
13      * - Nits with assembly code.
14      * - Don't use statement expressions without value; use "do {} while (0)".
15      * - Return correct values from __generic_... functions.
16      *
17      * Revision 1.4  2000/09/12 16:28:25  bjornw
18      * * Removed comments from the get/put user asm code
19      * * Constrains for destination addr in put_user cannot be memory, only reg
20      *
21      * Revision 1.3  2000/09/12 14:30:20  bjornw
22      * MAX_ADDR_USER does not exist anymore
23      *
24      * Revision 1.2  2000/07/13 15:52:48  bjornw
25      * New user-access functions
26      *
27      * Revision 1.1.1.1  2000/07/10 16:32:31  bjornw
28      * CRIS architecture, working draft
29      *
30      *
31      *
32      */
33     
34     /* Asm:s have been tweaked (within the domain of correctness) to give
35        satisfactory results for "gcc version 2.96 20000427 (experimental)".
36     
37        Check regularly...
38     
39        Register r9 is chosen for temporaries, being a call-clobbered register
40        first in line to be used (notably for local blocks), not colliding with
41        parameter registers.  */
42     
43     #ifndef _CRIS_UACCESS_H
44     #define _CRIS_UACCESS_H
45     
46     #ifndef __ASSEMBLY__
47     #include <linux/sched.h>
48     #include <linux/errno.h>
49     #include <asm/processor.h>
50     #include <asm/page.h>
51     
52     #define VERIFY_READ	0
53     #define VERIFY_WRITE	1
54     
55     /*
56      * The fs value determines whether argument validity checking should be
57      * performed or not.  If get_fs() == USER_DS, checking is performed, with
58      * get_fs() == KERNEL_DS, checking is bypassed.
59      *
60      * For historical reasons, these macros are grossly misnamed.
61      */
62     
63     #define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
64     
65     /* addr_limit is the maximum accessible address for the task. we misuse
66      * the KERNEL_DS and USER_DS values to both assign and compare the 
67      * addr_limit values through the equally misnamed get/set_fs macros.
68      * (see above)
69      */
70     
71     #define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
72     #define USER_DS		MAKE_MM_SEG(TASK_SIZE)
73     
74     #define get_ds()	(KERNEL_DS)
75     #define get_fs()	(current->addr_limit)
76     #define set_fs(x)	(current->addr_limit = (x))
77     
78     #define segment_eq(a,b)	((a).seg == (b).seg)
79     
80     #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
81     #define __user_ok(addr,size) (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size)))
82     #define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
83     #define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
84     
85     extern inline int verify_area(int type, const void * addr, unsigned long size)
86     {
87     	return access_ok(type,addr,size) ? 0 : -EFAULT;
88     }
89     
90     
91     /*
92      * The exception table consists of pairs of addresses: the first is the
93      * address of an instruction that is allowed to fault, and the second is
94      * the address at which the program should continue.  No registers are
95      * modified, so it is entirely up to the continuation code to figure out
96      * what to do.
97      *
98      * All the routines below use bits of fixup code that are out of line
99      * with the main instruction path.  This means when everything is well,
100      * we don't even have to jump over them.  Further, they do not intrude
101      * on our cache or tlb entries.
102      */
103     
104     struct exception_table_entry
105     {
106     	unsigned long insn, fixup;
107     };
108     
109     /* Returns 0 if exception not found and fixup otherwise.  */
110     extern unsigned long search_exception_table(unsigned long);
111     
112     
113     /*
114      * These are the main single-value transfer routines.  They automatically
115      * use the right size if we just have the right pointer type.
116      *
117      * This gets kind of ugly. We want to return _two_ values in "get_user()"
118      * and yet we don't want to do any pointers, because that is too much
119      * of a performance impact. Thus we have a few rather ugly macros here,
120      * and hide all the uglyness from the user.
121      *
122      * The "__xxx" versions of the user access functions are versions that
123      * do not verify the address space, that must have been done previously
124      * with a separate "access_ok()" call (this is used when we do multiple
125      * accesses to the same area of user memory).
126      *
127      * As we use the same address space for kernel and user data on
128      * CRIS, we can just do these as direct assignments.  (Of course, the
129      * exception handling means that it's no longer "just"...)
130      */
131     #define get_user(x,ptr) \
132       __get_user_check((x),(ptr),sizeof(*(ptr)))
133     #define put_user(x,ptr) \
134       __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
135     
136     #define __get_user(x,ptr) \
137       __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
138     #define __put_user(x,ptr) \
139       __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
140     
141     /*
142      * The "xxx_ret" versions return constant specified in third argument, if
143      * something bad happens. These macros can be optimized for the
144      * case of just returning from the function xxx_ret is used.
145      */
146     
147     #define put_user_ret(x,ptr,ret) \
148     	do { if (put_user(x,ptr)) return ret; } while (0)
149     
150     #define get_user_ret(x,ptr,ret) \
151     	do { if (get_user(x,ptr)) return ret; } while (0)
152     
153     #define __put_user_ret(x,ptr,ret) \
154     	do { if (__put_user(x,ptr)) return ret; } while (0)
155     
156     #define __get_user_ret(x,ptr,ret) \
157     	do { if (__get_user(x,ptr)) return ret; } while (0)
158     
159     
160     extern long __put_user_bad(void);
161     
162     #define __put_user_nocheck(x,ptr,size)			\
163     ({							\
164     	long __pu_err;					\
165     	__put_user_size((x),(ptr),(size),__pu_err);	\
166     	__pu_err;					\
167     })
168     
169     #define __put_user_check(x,ptr,size)				\
170     ({								\
171     	long __pu_err = -EFAULT;				\
172     	__typeof__(*(ptr)) *__pu_addr = (ptr);			\
173     	if (access_ok(VERIFY_WRITE,__pu_addr,size))		\
174     		__put_user_size((x),__pu_addr,(size),__pu_err);	\
175     	__pu_err;						\
176     })
177     
178     #define __put_user_size(x,ptr,size,retval)			\
179     do {								\
180     	retval = 0;						\
181     	switch (size) {						\
182     	  case 1: __put_user_asm(x,ptr,retval,"move.b"); break;	\
183     	  case 2: __put_user_asm(x,ptr,retval,"move.w"); break;	\
184     	  case 4: __put_user_asm(x,ptr,retval,"move.d"); break;	\
185     	  default: __put_user_bad();				\
186     	}							\
187     } while (0)
188     
189     struct __large_struct { unsigned long buf[100]; };
190     #define __m(x) (*(struct __large_struct *)(x))
191     
192     /*
193      * We don't tell gcc that we are accessing memory, but this is OK
194      * because we do not write to any memory gcc knows about, so there
195      * are no aliasing issues.
196      *
197      * Note that PC at a fault is the address *after* the faulting
198      * instruction.
199      */
200     #define __put_user_asm(x, addr, err, op)			\
201     	__asm__ __volatile__(					\
202     		"	"op" %1,[%2]\n"				\
203     		"2:\n"						\
204     		"	.section .fixup,\"ax\"\n"		\
205     		"3:	move.d %3,%0\n"				\
206     		"	jump 2b\n"				\
207     		"	.previous\n"				\
208     		"	.section __ex_table,\"a\"\n"		\
209     		"	.dword 2b,3b\n"				\
210     		"	.previous\n"				\
211     		: "=r" (err)					\
212     		: "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
213     
214     
215     #define __get_user_nocheck(x,ptr,size)				\
216     ({								\
217     	long __gu_err, __gu_val;				\
218     	__get_user_size(__gu_val,(ptr),(size),__gu_err);	\
219     	(x) = (__typeof__(*(ptr)))__gu_val;			\
220     	__gu_err;						\
221     })
222     
223     #define __get_user_check(x,ptr,size)					\
224     ({									\
225     	long __gu_err = -EFAULT, __gu_val = 0;				\
226     	const __typeof__(*(ptr)) *__gu_addr = (ptr);			\
227     	if (access_ok(VERIFY_READ,__gu_addr,size))			\
228     		__get_user_size(__gu_val,__gu_addr,(size),__gu_err);	\
229     	(x) = (__typeof__(*(ptr)))__gu_val;				\
230     	__gu_err;							\
231     })
232     
233     extern long __get_user_bad(void);
234     
235     #define __get_user_size(x,ptr,size,retval)			\
236     do {								\
237     	retval = 0;						\
238     	switch (size) {						\
239     	  case 1: __get_user_asm(x,ptr,retval,"move.b"); break;	\
240     	  case 2: __get_user_asm(x,ptr,retval,"move.w"); break;	\
241     	  case 4: __get_user_asm(x,ptr,retval,"move.d"); break;	\
242     	  default: (x) = __get_user_bad();			\
243     	}							\
244     } while (0)
245     
246     /* See comment before __put_user_asm.  */
247     
248     #define __get_user_asm(x, addr, err, op)		\
249     	__asm__ __volatile__(				\
250     		"	"op" [%2],%1\n"			\
251     		"2:\n"					\
252     		"	.section .fixup,\"ax\"\n"	\
253     		"3:	move.d %3,%0\n"			\
254     		"	moveq 0,%1\n"			\
255     		"	jump 2b\n"			\
256     		"	.previous\n"			\
257     		"	.section __ex_table,\"a\"\n"	\
258     		"	.dword 2b,3b\n"			\
259     		"	.previous\n"			\
260     		: "=r" (err), "=r" (x)			\
261     		: "r" (addr), "g" (-EFAULT), "0" (err))
262     
263     /* More complex functions.  Most are inline, but some call functions that
264        live in lib/usercopy.c  */
265     
266     extern unsigned long __copy_user(void *to, const void *from, unsigned long n);
267     extern unsigned long __copy_user_zeroing(void *to, const void *from, unsigned long n);
268     extern unsigned long __do_clear_user(void *to, unsigned long n);
269     
270     /*
271      * Copy a null terminated string from userspace.
272      *
273      * Must return:
274      * -EFAULT		for an exception
275      * count		if we hit the buffer limit
276      * bytes copied		if we hit a null byte
277      * (without the null byte)
278      */
279     
280     static inline long         
281     __do_strncpy_from_user(char *dst, const char *src, long count)
282     {
283     	long res;
284     
285     	if (count == 0)
286     		return 0;
287     
288     	/*
289     	 * Currently, in 2.4.0-test9, most ports use a simple byte-copy loop.
290     	 *  So do we.
291     	 *
292     	 *  This code is deduced from:
293     	 *
294     	 *	char tmp2;
295     	 *	long tmp1, tmp3	
296     	 *	tmp1 = count;
297     	 *	while ((*dst++ = (tmp2 = *src++)) != 0
298     	 *	       && --tmp1)
299     	 *	  ;
300     	 *
301     	 *	res = count - tmp1;
302     	 *
303     	 *  with tweaks.
304     	 */
305     
306     	__asm__ __volatile__ (
307     		"	move.d %3,%0\n"
308     		"	move.b [%2+],r9\n"
309     		"1:	beq 2f\n"
310     		"	move.b r9,[%1+]\n"
311     
312     		"	subq 1,%0\n"
313     		"	bne 1b\n"
314     		"	move.b [%2+],r9\n"
315     
316     		"2:	sub.d %3,%0\n"
317     		"	neg.d %0,%0\n"
318     		"3:\n"
319     		"	.section .fixup,\"ax\"\n"
320     		"4:	move.d %7,%0\n"
321     		"	jump 3b\n"
322     
323     		/* There's one address for a fault at the first move, and
324     		   two possible PC values for a fault at the second move,
325     		   being a delay-slot filler.  However, the branch-target
326     		   for the second move is the same as the first address.
327     		   Just so you don't get confused...  */
328     		"	.previous\n"
329     		"	.section __ex_table,\"a\"\n"
330     		"	.dword 1b,4b\n"
331     		"	.dword 2b,4b\n"
332     		"	.previous"
333     		: "=r" (res), "=r" (dst), "=r" (src), "=r" (count)
334     		: "3" (count), "1" (dst), "2" (src), "g" (-EFAULT)
335     		: "r9");
336     
337     	return res;
338     }
339     
340     static inline unsigned long
341     __generic_copy_to_user(void *to, const void *from, unsigned long n)
342     {
343     	if (access_ok(VERIFY_WRITE, to, n))
344     		return __copy_user(to,from,n);
345     	return n;
346     }
347     
348     static inline unsigned long
349     __generic_copy_from_user(void *to, const void *from, unsigned long n)
350     {
351     	if (access_ok(VERIFY_READ, from, n))
352     		return __copy_user_zeroing(to,from,n);
353     	return n;
354     }
355     
356     static inline unsigned long
357     __generic_clear_user(void *to, unsigned long n)
358     {
359     	if (access_ok(VERIFY_WRITE, to, n))
360     		return __do_clear_user(to,n);
361     	return n;
362     }
363     
364     static inline long
365     __strncpy_from_user(char *dst, const char *src, long count)
366     {
367     	return __do_strncpy_from_user(dst, src, count);
368     }
369     
370     static inline long
371     strncpy_from_user(char *dst, const char *src, long count)
372     {
373     	long res = -EFAULT;
374     	if (access_ok(VERIFY_READ, src, 1))
375     		res = __do_strncpy_from_user(dst, src, count);
376     	return res;
377     }
378     
379     /* A few copy asms to build up the more complex ones from.
380     
381        Note again, a post-increment is performed regardless of whether a bus
382        fault occurred in that instruction, and PC for a faulted insn is the
383        address *after* the insn.  */
384     
385     #define __asm_copy_user_cont(to, from, ret, COPY, FIXUP, TENTRY) \
386     	__asm__ __volatile__ (				\
387     			COPY				\
388     		"1:\n"					\
389     		"	.section .fixup,\"ax\"\n"	\
390     			FIXUP				\
391     		"	jump 1b\n"			\
392     		"	.previous\n"			\
393     		"	.section __ex_table,\"a\"\n"	\
394     			TENTRY				\
395     		"	.previous\n"			\
396     		: "=r" (to), "=r" (from), "=r" (ret)	\
397     		: "0" (to), "1" (from), "2" (ret)	\
398     		: "r9", "memory")
399     
400     #define __asm_copy_from_user_1(to, from, ret) \
401     	__asm_copy_user_cont(to, from, ret,	\
402     		"	move.b [%1+],r9\n"	\
403     		"2:	move.b r9,[%0+]\n",	\
404     		"3:	addq 1,%2\n"		\
405     		"	clear.b [%0+]\n",	\
406     		"	.dword 2b,3b\n")
407     
408     #define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
409     	__asm_copy_user_cont(to, from, ret,		\
410     		"	move.w [%1+],r9\n"		\
411     		"2:	move.w r9,[%0+]\n" COPY,	\
412     		"3:	addq 2,%2\n"			\
413     		"	clear.w [%0+]\n" FIXUP,		\
414     		"	.dword 2b,3b\n" TENTRY)
415     
416     #define __asm_copy_from_user_2(to, from, ret) \
417     	__asm_copy_from_user_2x_cont(to, from, ret, "", "", "")
418     
419     #define __asm_copy_from_user_3(to, from, ret)		\
420     	__asm_copy_from_user_2x_cont(to, from, ret,	\
421     		"	move.b [%1+],r9\n"		\
422     		"4:	move.b r9,[%0+]\n",		\
423     		"5:	addq 1,%2\n"			\
424     		"	clear.b [%0+]\n",		\
425     		"	.dword 4b,5b\n")
426     
427     #define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
428     	__asm_copy_user_cont(to, from, ret,		\
429     		"	move.d [%1+],r9\n"		\
430     		"2:	move.d r9,[%0+]\n" COPY,	\
431     		"3:	addq 4,%2\n"			\
432     		"	clear.d [%0+]\n" FIXUP,		\
433     		"	.dword 2b,3b\n" TENTRY)
434     
435     #define __asm_copy_from_user_4(to, from, ret) \
436     	__asm_copy_from_user_4x_cont(to, from, ret, "", "", "")
437     
438     #define __asm_copy_from_user_5(to, from, ret) \
439     	__asm_copy_from_user_4x_cont(to, from, ret,	\
440     		"	move.b [%1+],r9\n"		\
441     		"4:	move.b r9,[%0+]\n",		\
442     		"5:	addq 1,%2\n"			\
443     		"	clear.b [%0+]\n",		\
444     		"	.dword 4b,5b\n")
445     
446     #define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
447     	__asm_copy_from_user_4x_cont(to, from, ret,	\
448     		"	move.w [%1+],r9\n"		\
449     		"4:	move.w r9,[%0+]\n" COPY,	\
450     		"5:	addq 2,%2\n"			\
451     		"	clear.w [%0+]\n" FIXUP,		\
452     		"	.dword 4b,5b\n" TENTRY)
453     
454     #define __asm_copy_from_user_6(to, from, ret) \
455     	__asm_copy_from_user_6x_cont(to, from, ret, "", "", "")
456     
457     #define __asm_copy_from_user_7(to, from, ret) \
458     	__asm_copy_from_user_6x_cont(to, from, ret,	\
459     		"	move.b [%1+],r9\n"		\
460     		"6:	move.b r9,[%0+]\n",		\
461     		"7:	addq 1,%2\n"			\
462     		"	clear.b [%0+]\n",		\
463     		"	.dword 6b,7b\n")
464     
465     #define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
466     	__asm_copy_from_user_4x_cont(to, from, ret,	\
467     		"	move.d [%1+],r9\n"		\
468     		"4:	move.d r9,[%0+]\n" COPY,	\
469     		"5:	addq 4,%2\n"			\
470     		"	clear.d [%0+]\n" FIXUP,		\
471     		"	.dword 4b,5b\n" TENTRY)
472     
473     #define __asm_copy_from_user_8(to, from, ret) \
474     	__asm_copy_from_user_8x_cont(to, from, ret, "", "", "")
475     
476     #define __asm_copy_from_user_9(to, from, ret) \
477     	__asm_copy_from_user_8x_cont(to, from, ret,	\
478     		"	move.b [%1+],r9\n"		\
479     		"6:	move.b r9,[%0+]\n",		\
480     		"7:	addq 1,%2\n"			\
481     		"	clear.b [%0+]\n",		\
482     		"	.dword 6b,7b\n")
483     
484     #define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
485     	__asm_copy_from_user_8x_cont(to, from, ret,	\
486     		"	move.w [%1+],r9\n"		\
487     		"6:	move.w r9,[%0+]\n" COPY,	\
488     		"7:	addq 2,%2\n"			\
489     		"	clear.w [%0+]\n" FIXUP,		\
490     		"	.dword 6b,7b\n" TENTRY)
491     
492     #define __asm_copy_from_user_10(to, from, ret) \
493     	__asm_copy_from_user_10x_cont(to, from, ret, "", "", "")
494     
495     #define __asm_copy_from_user_11(to, from, ret)		\
496     	__asm_copy_from_user_10x_cont(to, from, ret,	\
497     		"	move.b [%1+],r9\n"		\
498     		"8:	move.b r9,[%0+]\n",		\
499     		"9:	addq 1,%2\n"			\
500     		"	clear.b [%0+]\n",		\
501     		"	.dword 8b,9b\n")
502     
503     #define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
504     	__asm_copy_from_user_8x_cont(to, from, ret,	\
505     		"	move.d [%1+],r9\n"		\
506     		"6:	move.d r9,[%0+]\n" COPY,	\
507     		"7:	addq 4,%2\n"			\
508     		"	clear.d [%0+]\n" FIXUP,		\
509     		"	.dword 6b,7b\n" TENTRY)
510     
511     #define __asm_copy_from_user_12(to, from, ret) \
512     	__asm_copy_from_user_12x_cont(to, from, ret, "", "", "")
513     
514     #define __asm_copy_from_user_13(to, from, ret) \
515     	__asm_copy_from_user_12x_cont(to, from, ret,	\
516     		"	move.b [%1+],r9\n"		\
517     		"8:	move.b r9,[%0+]\n",		\
518     		"9:	addq 1,%2\n"			\
519     		"	clear.b [%0+]\n",		\
520     		"	.dword 8b,9b\n")
521     
522     #define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
523     	__asm_copy_from_user_12x_cont(to, from, ret,	\
524     		"	move.w [%1+],r9\n"		\
525     		"8:	move.w r9,[%0+]\n" COPY,	\
526     		"9:	addq 2,%2\n"			\
527     		"	clear.w [%0+]\n" FIXUP,		\
528     		"	.dword 8b,9b\n" TENTRY)
529     
530     #define __asm_copy_from_user_14(to, from, ret) \
531     	__asm_copy_from_user_14x_cont(to, from, ret, "", "", "")
532     
533     #define __asm_copy_from_user_15(to, from, ret) \
534     	__asm_copy_from_user_14x_cont(to, from, ret,	\
535     		"	move.b [%1+],r9\n"		\
536     		"10:	move.b r9,[%0+]\n",		\
537     		"11:	addq 1,%2\n"			\
538     		"	clear.b [%0+]\n",		\
539     		"	.dword 10b,11b\n")
540     
541     #define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
542     	__asm_copy_from_user_12x_cont(to, from, ret,	\
543     		"	move.d [%1+],r9\n"		\
544     		"8:	move.d r9,[%0+]\n" COPY,	\
545     		"9:	addq 4,%2\n"			\
546     		"	clear.d [%0+]\n" FIXUP,		\
547     		"	.dword 8b,9b\n" TENTRY)
548     
549     #define __asm_copy_from_user_16(to, from, ret) \
550     	__asm_copy_from_user_16x_cont(to, from, ret, "", "", "")
551     
552     #define __asm_copy_from_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
553     	__asm_copy_from_user_16x_cont(to, from, ret,	\
554     		"	move.d [%1+],r9\n"		\
555     		"10:	move.d r9,[%0+]\n" COPY,	\
556     		"11:	addq 4,%2\n"			\
557     		"	clear.d [%0+]\n" FIXUP,		\
558     		"	.dword 10b,11b\n" TENTRY)
559     
560     #define __asm_copy_from_user_20(to, from, ret) \
561     	__asm_copy_from_user_20x_cont(to, from, ret, "", "", "")
562     
563     #define __asm_copy_from_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
564     	__asm_copy_from_user_20x_cont(to, from, ret,	\
565     		"	move.d [%1+],r9\n"		\
566     		"12:	move.d r9,[%0+]\n" COPY,	\
567     		"13:	addq 4,%2\n"			\
568     		"	clear.d [%0+]\n" FIXUP,		\
569     		"	.dword 12b,13b\n" TENTRY)
570     
571     #define __asm_copy_from_user_24(to, from, ret) \
572     	__asm_copy_from_user_24x_cont(to, from, ret, "", "", "")
573     
574     /* And now, the to-user ones.  */
575     
576     #define __asm_copy_to_user_1(to, from, ret)	\
577     	__asm_copy_user_cont(to, from, ret,	\
578     		"	move.b [%1+],r9\n"	\
579     		"	move.b r9,[%0+]\n2:\n",	\
580     		"3:	addq 1,%2\n",		\
581     		"	.dword 2b,3b\n")
582     
583     #define __asm_copy_to_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
584     	__asm_copy_user_cont(to, from, ret,		\
585     		"	move.w [%1+],r9\n"		\
586     		"	move.w r9,[%0+]\n2:\n" COPY,	\
587     		"3:	addq 2,%2\n" FIXUP,		\
588     		"	.dword 2b,3b\n" TENTRY)
589     
590     #define __asm_copy_to_user_2(to, from, ret) \
591     	__asm_copy_to_user_2x_cont(to, from, ret, "", "", "")
592     
593     #define __asm_copy_to_user_3(to, from, ret) \
594     	__asm_copy_to_user_2x_cont(to, from, ret,	\
595     		"	move.b [%1+],r9\n"		\
596     		"	move.b r9,[%0+]\n4:\n",		\
597     		"5:	addq 1,%2\n",			\
598     		"	.dword 4b,5b\n")
599     
600     #define __asm_copy_to_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
601     	__asm_copy_user_cont(to, from, ret,		\
602     		"	move.d [%1+],r9\n"		\
603     		"	move.d r9,[%0+]\n2:\n" COPY,	\
604     		"3:	addq 4,%2\n" FIXUP,		\
605     		"	.dword 2b,3b\n" TENTRY)
606     
607     #define __asm_copy_to_user_4(to, from, ret) \
608     	__asm_copy_to_user_4x_cont(to, from, ret, "", "", "")
609     
610     #define __asm_copy_to_user_5(to, from, ret) \
611     	__asm_copy_to_user_4x_cont(to, from, ret,	\
612     		"	move.b [%1+],r9\n"		\
613     		"	move.b r9,[%0+]\n4:\n",		\
614     		"5:	addq 1,%2\n",			\
615     		"	.dword 4b,5b\n")
616     
617     #define __asm_copy_to_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
618     	__asm_copy_to_user_4x_cont(to, from, ret,	\
619     		"	move.w [%1+],r9\n"		\
620     		"	move.w r9,[%0+]\n4:\n" COPY,	\
621     		"5:	addq 2,%2\n" FIXUP,		\
622     		"	.dword 4b,5b\n" TENTRY)
623     
624     #define __asm_copy_to_user_6(to, from, ret) \
625     	__asm_copy_to_user_6x_cont(to, from, ret, "", "", "")
626     
627     #define __asm_copy_to_user_7(to, from, ret) \
628     	__asm_copy_to_user_6x_cont(to, from, ret,	\
629     		"	move.b [%1+],r9\n"		\
630     		"	move.b r9,[%0+]\n6:\n",		\
631     		"7:	addq 1,%2\n",			\
632     		"	.dword 6b,7b\n")
633     
634     #define __asm_copy_to_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
635     	__asm_copy_to_user_4x_cont(to, from, ret,	\
636     		"	move.d [%1+],r9\n"		\
637     		"	move.d r9,[%0+]\n4:\n" COPY,	\
638     		"5:	addq 4,%2\n"  FIXUP,		\
639     		"	.dword 4b,5b\n" TENTRY)
640     
641     #define __asm_copy_to_user_8(to, from, ret) \
642     	__asm_copy_to_user_8x_cont(to, from, ret, "", "", "")
643     
644     #define __asm_copy_to_user_9(to, from, ret) \
645     	__asm_copy_to_user_8x_cont(to, from, ret,	\
646     		"	move.b [%1+],r9\n"		\
647     		"	move.b r9,[%0+]\n6:\n",		\
648     		"7:	addq 1,%2\n",			\
649     		"	.dword 6b,7b\n")
650     
651     #define __asm_copy_to_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
652     	__asm_copy_to_user_8x_cont(to, from, ret,	\
653     		"	move.w [%1+],r9\n"		\
654     		"	move.w r9,[%0+]\n6:\n" COPY,	\
655     		"7:	addq 2,%2\n" FIXUP,		\
656     		"	.dword 6b,7b\n" TENTRY)
657     
658     #define __asm_copy_to_user_10(to, from, ret) \
659     	__asm_copy_to_user_10x_cont(to, from, ret, "", "", "")
660     
661     #define __asm_copy_to_user_11(to, from, ret) \
662     	__asm_copy_to_user_10x_cont(to, from, ret,	\
663     		"	move.b [%1+],r9\n"		\
664     		"	move.b r9,[%0+]\n8:\n",		\
665     		"9:	addq 1,%2\n",			\
666     		"	.dword 8b,9b\n")
667     
668     #define __asm_copy_to_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
669     	__asm_copy_to_user_8x_cont(to, from, ret,	\
670     		"	move.d [%1+],r9\n"		\
671     		"	move.d r9,[%0+]\n6:\n" COPY,	\
672     		"7:	addq 4,%2\n" FIXUP,		\
673     		"	.dword 6b,7b\n" TENTRY)
674     
675     #define __asm_copy_to_user_12(to, from, ret) \
676     	__asm_copy_to_user_12x_cont(to, from, ret, "", "", "")
677     
678     #define __asm_copy_to_user_13(to, from, ret) \
679     	__asm_copy_to_user_12x_cont(to, from, ret,	\
680     		"	move.b [%1+],r9\n"		\
681     		"	move.b r9,[%0+]\n8:\n",		\
682     		"9:	addq 1,%2\n",			\
683     		"	.dword 8b,9b\n")
684     
685     #define __asm_copy_to_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
686     	__asm_copy_to_user_12x_cont(to, from, ret,	\
687     		"	move.w [%1+],r9\n"		\
688     		"	move.w r9,[%0+]\n8:\n" COPY,	\
689     		"9:	addq 2,%2\n" FIXUP,		\
690     		"	.dword 8b,9b\n" TENTRY)
691     
692     #define __asm_copy_to_user_14(to, from, ret)	\
693     	__asm_copy_to_user_14x_cont(to, from, ret, "", "", "")
694     
695     #define __asm_copy_to_user_15(to, from, ret) \
696     	__asm_copy_to_user_14x_cont(to, from, ret,	\
697     		"	move.b [%1+],r9\n"		\
698     		"	move.b r9,[%0+]\n10:\n",		\
699     		"11:	addq 1,%2\n",			\
700     		"	.dword 10b,11b\n")
701     
702     #define __asm_copy_to_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
703     	__asm_copy_to_user_12x_cont(to, from, ret,	\
704     		"	move.d [%1+],r9\n"		\
705     		"	move.d r9,[%0+]\n8:\n" COPY,	\
706     		"9:	addq 4,%2\n" FIXUP,		\
707     		"	.dword 8b,9b\n" TENTRY)
708     
709     #define __asm_copy_to_user_16(to, from, ret) \
710     	__asm_copy_to_user_16x_cont(to, from, ret, "", "", "")
711     
712     #define __asm_copy_to_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
713     	__asm_copy_to_user_16x_cont(to, from, ret,	\
714     		"	move.d [%1+],r9\n"		\
715     		"	move.d r9,[%0+]\n10:\n" COPY,	\
716     		"11:	addq 4,%2\n" FIXUP,		\
717     		"	.dword 10b,11b\n" TENTRY)
718     
719     #define __asm_copy_to_user_20(to, from, ret) \
720     	__asm_copy_to_user_20x_cont(to, from, ret, "", "", "")
721     
722     #define __asm_copy_to_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY)	\
723     	__asm_copy_to_user_20x_cont(to, from, ret,	\
724     		"	move.d [%1+],r9\n"		\
725     		"	move.d r9,[%0+]\n12:\n" COPY,	\
726     		"13:	addq 4,%2\n" FIXUP,		\
727     		"	.dword 12b,13b\n" TENTRY)
728     
729     #define __asm_copy_to_user_24(to, from, ret)	\
730     	__asm_copy_to_user_24x_cont(to, from, ret, "", "", "")
731     
732     /* Define a few clearing asms with exception handlers.  */
733     
734     /* This frame-asm is like the __asm_copy_user_cont one, but has one less
735        input.  */
736     
737     #define __asm_clear(to, ret, CLEAR, FIXUP, TENTRY) \
738     	__asm__ __volatile__ (				\
739     			CLEAR				\
740     		"1:\n"					\
741     		"	.section .fixup,\"ax\"\n"	\
742     			FIXUP				\
743     		"	jump 1b\n"			\
744     		"	.previous\n"			\
745     		"	.section __ex_table,\"a\"\n"	\
746     			TENTRY				\
747     		"	.previous"			\
748     		: "=r" (to), "=r" (ret)			\
749     		: "0" (to), "1" (ret)			\
750     		: "r9", "memory")
751     
752     #define __asm_clear_1(to, ret) \
753     	__asm_clear(to, ret,			\
754     		"	clear.b [%0+]\n2:\n",	\
755     		"3:	addq 1,%1\n",		\
756     		"	.dword 2b,3b\n")
757     
758     #define __asm_clear_2(to, ret) \
759     	__asm_clear(to, ret,			\
760     		"	clear.w [%0+]\n2:\n",	\
761     		"3:	addq 2,%1\n",		\
762     		"	.dword 2b,3b\n")
763     
764     #define __asm_clear_3(to, ret) \
765          __asm_clear(to, ret,			\
766     		 "	clear.w [%0+]\n"	\
767     		 "2:	clear.b [%0+]\n3:\n",	\
768     		 "4:	addq 2,%1\n"		\
769     		 "5:	addq 1,%1\n",		\
770     		 "	.dword 2b,4b\n"		\
771     		 "	.dword 3b,5b\n")
772     
773     #define __asm_clear_4x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
774     	__asm_clear(to, ret,				\
775     		"	clear.d [%0+]\n2:\n" CLEAR,	\
776     		"3:	addq 4,%1\n" FIXUP,		\
777     		"	.dword 2b,3b\n" TENTRY)
778     
779     #define __asm_clear_4(to, ret) \
780     	__asm_clear_4x_cont(to, ret, "", "", "")
781     
782     #define __asm_clear_8x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
783     	__asm_clear_4x_cont(to, ret,			\
784     		"	clear.d [%0+]\n4:\n" CLEAR,	\
785     		"5:	addq 4,%1\n" FIXUP,		\
786     		"	.dword 4b,5b\n" TENTRY)
787     
788     #define __asm_clear_8(to, ret) \
789     	__asm_clear_8x_cont(to, ret, "", "", "")
790     
791     #define __asm_clear_12x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
792     	__asm_clear_8x_cont(to, ret,			\
793     		"	clear.d [%0+]\n6:\n" CLEAR,	\
794     		"7:	addq 4,%1\n" FIXUP,		\
795     		"	.dword 6b,7b\n" TENTRY)
796     
797     #define __asm_clear_12(to, ret) \
798     	__asm_clear_12x_cont(to, ret, "", "", "")
799     
800     #define __asm_clear_16x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
801     	__asm_clear_12x_cont(to, ret,			\
802     		"	clear.d [%0+]\n8:\n" CLEAR,	\
803     		"9:	addq 4,%1\n" FIXUP,		\
804     		"	.dword 8b,9b\n" TENTRY)
805     
806     #define __asm_clear_16(to, ret) \
807     	__asm_clear_16x_cont(to, ret, "", "", "")
808     
809     #define __asm_clear_20x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
810     	__asm_clear_16x_cont(to, ret,			\
811     		"	clear.d [%0+]\n10:\n" CLEAR,	\
812     		"11:	addq 4,%1\n" FIXUP,		\
813     		"	.dword 10b,11b\n" TENTRY)
814     
815     #define __asm_clear_20(to, ret) \
816     	__asm_clear_20x_cont(to, ret, "", "", "")
817     
818     #define __asm_clear_24x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
819     	__asm_clear_20x_cont(to, ret,			\
820     		"	clear.d [%0+]\n12:\n" CLEAR,	\
821     		"13:	addq 4,%1\n" FIXUP,		\
822     		"	.dword 12b,13b\n" TENTRY)
823     
824     #define __asm_clear_24(to, ret) \
825     	__asm_clear_24x_cont(to, ret, "", "", "")
826     
827     /* Note that if these expand awfully if made into switch constructs, so
828        don't do that.  */
829     
830     static inline unsigned long
831     __constant_copy_from_user(void *to, const void *from, unsigned long n)
832     {
833     	unsigned long ret = 0;
834     	if (n == 0)
835     		;
836     	else if (n == 1)
837     		__asm_copy_from_user_1(to, from, ret);
838     	else if (n == 2)
839     		__asm_copy_from_user_2(to, from, ret);
840     	else if (n == 3)
841     		__asm_copy_from_user_3(to, from, ret);
842     	else if (n == 4)
843     		__asm_copy_from_user_4(to, from, ret);
844     	else if (n == 5)
845     		__asm_copy_from_user_5(to, from, ret);
846     	else if (n == 6)
847     		__asm_copy_from_user_6(to, from, ret);
848     	else if (n == 7)
849     		__asm_copy_from_user_7(to, from, ret);
850     	else if (n == 8)
851     		__asm_copy_from_user_8(to, from, ret);
852     	else if (n == 9)
853     		__asm_copy_from_user_9(to, from, ret);
854     	else if (n == 10)
855     		__asm_copy_from_user_10(to, from, ret);
856     	else if (n == 11)
857     		__asm_copy_from_user_11(to, from, ret);
858     	else if (n == 12)
859     		__asm_copy_from_user_12(to, from, ret);
860     	else if (n == 13)
861     		__asm_copy_from_user_13(to, from, ret);
862     	else if (n == 14)
863     		__asm_copy_from_user_14(to, from, ret);
864     	else if (n == 15)
865     		__asm_copy_from_user_15(to, from, ret);
866     	else if (n == 16)
867     		__asm_copy_from_user_16(to, from, ret);
868     	else if (n == 20)
869     		__asm_copy_from_user_20(to, from, ret);
870     	else if (n == 24)
871     		__asm_copy_from_user_24(to, from, ret);
872     	else
873     		ret = __generic_copy_from_user(to, from, n);
874     
875     	return ret;
876     }
877     
878     /* Ditto, don't make a switch out of this.  */
879     
880     static inline unsigned long
881     __constant_copy_to_user(void *to, const void *from, unsigned long n)
882     {
883     	unsigned long ret = 0;
884     	if (n == 0)
885     		;
886     	else if (n == 1)
887     		__asm_copy_to_user_1(to, from, ret);
888     	else if (n == 2)
889     		__asm_copy_to_user_2(to, from, ret);
890     	else if (n == 3)
891     		__asm_copy_to_user_3(to, from, ret);
892     	else if (n == 4)
893     		__asm_copy_to_user_4(to, from, ret);
894     	else if (n == 5)
895     		__asm_copy_to_user_5(to, from, ret);
896     	else if (n == 6)
897     		__asm_copy_to_user_6(to, from, ret);
898     	else if (n == 7)
899     		__asm_copy_to_user_7(to, from, ret);
900     	else if (n == 8)
901     		__asm_copy_to_user_8(to, from, ret);
902     	else if (n == 9)
903     		__asm_copy_to_user_9(to, from, ret);
904     	else if (n == 10)
905     		__asm_copy_to_user_10(to, from, ret);
906     	else if (n == 11)
907     		__asm_copy_to_user_11(to, from, ret);
908     	else if (n == 12)
909     		__asm_copy_to_user_12(to, from, ret);
910     	else if (n == 13)
911     		__asm_copy_to_user_13(to, from, ret);
912     	else if (n == 14)
913     		__asm_copy_to_user_14(to, from, ret);
914     	else if (n == 15)
915     		__asm_copy_to_user_15(to, from, ret);
916     	else if (n == 16)
917     		__asm_copy_to_user_16(to, from, ret);
918     	else if (n == 20)
919     		__asm_copy_to_user_20(to, from, ret);
920     	else if (n == 24)
921     		__asm_copy_to_user_24(to, from, ret);
922     	else
923     		ret = __generic_copy_to_user(to, from, n);
924     
925     	return ret;
926     }
927     
928     /* No switch, please.  */
929     
930     static inline unsigned long
931     __constant_clear_user(void *to, unsigned long n)
932     {
933     	unsigned long ret = 0;
934     	if (n == 0)
935     		;
936     	else if (n == 1)
937     		__asm_clear_1(to, ret);
938     	else if (n == 2)
939     		__asm_clear_2(to, ret);
940     	else if (n == 3)
941     		__asm_clear_3(to, ret);
942     	else if (n == 4)
943     		__asm_clear_4(to, ret);
944     	else if (n == 8)
945     		__asm_clear_8(to, ret);
946     	else if (n == 12)
947     		__asm_clear_12(to, ret);
948     	else if (n == 16)
949     		__asm_clear_16(to, ret);
950     	else if (n == 20)
951     		__asm_clear_20(to, ret);
952     	else if (n == 24)
953     		__asm_clear_24(to, ret);
954     	else
955     		ret = __generic_clear_user(to, n);
956     
957     	return ret;
958     }
959     
960     
961     #define clear_user(to, n)			\
962     (__builtin_constant_p(n) ?			\
963      __constant_clear_user(to, n) :			\
964      __generic_clear_user(to, n))
965     
966     #define copy_from_user(to, from, n)		\
967     (__builtin_constant_p(n) ?			\
968      __constant_copy_from_user(to, from, n) :	\
969      __generic_copy_from_user(to, from, n))
970     
971     #define copy_to_user(to, from, n)		\
972     (__builtin_constant_p(n) ?			\
973      __constant_copy_to_user(to, from, n) :		\
974      __generic_copy_to_user(to, from, n))
975     
976     #define copy_to_user_ret(to,from,n,retval) \
977     	do { if (copy_to_user(to,from,n)) return retval; } while (0)
978     #define copy_from_user_ret(to,from,n,retval) \
979     	do { if (copy_from_user(to,from,n)) return retval; } while (0)
980     
981     /* We let the __ versions of copy_from/to_user inline, because they're often
982      * used in fast paths and have only a small space overhead.
983      */
984     
985     static inline unsigned long
986     __generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
987     {
988     	return __copy_user_zeroing(to,from,n);
989     }
990     
991     static inline unsigned long
992     __generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
993     {
994     	return __copy_user(to,from,n);
995     }
996     
997     static inline unsigned long
998     __generic_clear_user_nocheck(void *to, unsigned long n)
999     {
1000     	return __do_clear_user(to,n);
1001     }
1002     
1003     /* without checking */
1004     
1005     #define __copy_to_user(to,from,n)   __generic_copy_to_user_nocheck((to),(from),(n))
1006     #define __copy_from_user(to,from,n) __generic_copy_from_user_nocheck((to),(from),(n))
1007     #define __clear_user(to,n) __generic_clear_user_nocheck((to),(n))
1008     
1009     /*
1010      * Return the size of a string (including the ending 0)
1011      *
1012      * Return length of string in userspace including terminating 0
1013      * or 0 for error.  Return a value greater than N if too long.
1014      */
1015     
1016     static inline long
1017     strnlen_user(const char *s, long n)
1018     {
1019     	long res, tmp1, tmp2;
1020     
1021     	if (!access_ok(VERIFY_READ, s, 0))
1022     		return 0;
1023     
1024     	/*
1025     	 * This code is deduced from:
1026     	 *
1027     	 *	tmp1 = n;
1028     	 *	while (tmp1-- > 0 && *s++)
1029     	 *	  ;
1030     	 *
1031     	 *	res = n - tmp1;
1032     	 *
1033     	 *  (with tweaks).
1034     	 */
1035     
1036     	__asm__ __volatile__ (
1037     		"	move.d %1,r9\n"
1038     		"0:\n"
1039     		"	ble 1f\n"
1040     		"	subq 1,r9\n"
1041     
1042     		"	test.b [%0+]\n"
1043     		"	bne 0b\n"
1044     		"	test.d r9\n"
1045     		"1:\n"
1046     		"	move.d %1,%0\n"
1047     		"	sub.d r9,%0\n"
1048     		"2:\n"
1049     		"	.section .fixup,\"ax\"\n"
1050     
1051     		"3:	clear.d %0\n"
1052     		"	jump 2b\n"
1053     
1054     		/* There's one address for a fault at the first move, and
1055     		   two possible PC values for a fault at the second move,
1056     		   being a delay-slot filler.  However, the branch-target
1057     		   for the second move is the same as the first address.
1058     		   Just so you don't get confused...  */
1059     		"	.previous\n"
1060     		"	.section __ex_table,\"a\"\n"
1061     		"	.dword 0b,3b\n"
1062     		"	.dword 1b,3b\n"
1063     		"	.previous\n"
1064     		: "=r" (res), "=r" (tmp1)
1065     		: "0" (s), "1" (n)
1066     		: "r9");
1067     
1068     	return res;
1069     }
1070     
1071     #define strlen_user(str)	strnlen_user((str), 0x7ffffffe)
1072     
1073     #endif  /* __ASSEMBLY__ */
1074     
1075     #endif	/* _CRIS_UACCESS_H */
1076