Import 2.1.116pre2
[davej-history.git] / arch / i386 / lib / usercopy.c
blob8901882db7a4770a1a44d8a261391880a945c22a
1 /*
2 * User address space access functions.
3 * The non inlined parts of asm-i386/uaccess.h are here.
5 * Copyright 1997 Andi Kleen <ak@muc.de>
6 * Copyright 1997 Linus Torvalds
7 */
8 #include <asm/uaccess.h>
10 inline unsigned long
11 __generic_copy_to_user(void *to, const void *from, unsigned long n)
13 if ((unsigned long) to < TASK_SIZE)
14 __check_locks(1);
15 if (access_ok(VERIFY_WRITE, to, n))
16 __copy_user(to,from,n);
17 return n;
20 inline unsigned long
21 __generic_copy_from_user(void *to, const void *from, unsigned long n)
23 if ((unsigned long) from < TASK_SIZE)
24 __check_locks(1);
25 if (access_ok(VERIFY_READ, from, n))
26 __copy_user(to,from,n);
27 return n;
32 * Copy a null terminated string from userspace.
35 #define __do_strncpy_from_user(dst,src,count,res) \
36 __asm__ __volatile__( \
37 " testl %1,%1\n" \
38 " jz 2f\n" \
39 "0: lodsb\n" \
40 " stosb\n" \
41 " testb %%al,%%al\n" \
42 " jz 1f\n" \
43 " decl %1\n" \
44 " jnz 0b\n" \
45 "1: subl %1,%0\n" \
46 "2:\n" \
47 ".section .fixup,\"ax\"\n" \
48 "3: movl %2,%0\n" \
49 " jmp 2b\n" \
50 ".previous\n" \
51 ".section __ex_table,\"a\"\n" \
52 " .align 4\n" \
53 " .long 0b,3b\n" \
54 ".previous" \
55 : "=d"(res), "=c"(count) \
56 : "i"(-EFAULT), "0"(count), "1"(count), "S"(src), "D"(dst) \
57 : "si", "di", "ax", "memory")
59 long
60 __strncpy_from_user(char *dst, const char *src, long count)
62 long res;
63 __check_locks(1);
64 __do_strncpy_from_user(dst, src, count, res);
65 return res;
68 long
69 strncpy_from_user(char *dst, const char *src, long count)
71 long res = -EFAULT;
72 __check_locks(1);
73 if (access_ok(VERIFY_READ, src, 1))
74 __do_strncpy_from_user(dst, src, count, res);
75 return res;
80 * Zero Userspace
83 #define __do_clear_user(addr,size) \
84 __asm__ __volatile__( \
85 "0: rep; stosl\n" \
86 " movl %1,%0\n" \
87 "1: rep; stosb\n" \
88 "2:\n" \
89 ".section .fixup,\"ax\"\n" \
90 "3: lea 0(%1,%0,4),%0\n" \
91 " jmp 2b\n" \
92 ".previous\n" \
93 ".section __ex_table,\"a\"\n" \
94 " .align 4\n" \
95 " .long 0b,3b\n" \
96 " .long 1b,2b\n" \
97 ".previous" \
98 : "=&c"(size) \
99 : "r"(size & 3), "0"(size / 4), "D"(addr), "a"(0) \
100 : "di")
102 unsigned long
103 clear_user(void *to, unsigned long n)
105 __check_locks(1);
106 if (access_ok(VERIFY_WRITE, to, n))
107 __do_clear_user(to, n);
108 return n;
111 unsigned long
112 __clear_user(void *to, unsigned long n)
114 __check_locks(1);
115 __do_clear_user(to, n);
116 return n;
120 * Return the size of a string (including the ending 0)
122 * Return 0 for error
125 long strlen_user(const char *s)
127 unsigned long res;
129 __check_locks(1);
130 __asm__ __volatile__(
131 "0: repne; scasb\n"
132 " notl %0\n"
133 "1:\n"
134 ".section .fixup,\"ax\"\n"
135 "2: xorl %0,%0\n"
136 " jmp 1b\n"
137 ".previous\n"
138 ".section __ex_table,\"a\"\n"
139 " .align 4\n"
140 " .long 0b,2b\n"
141 ".previous"
142 :"=c" (res), "=D" (s)
143 :"1" (s), "a" (0), "0" (-__addr_ok(s)));
144 return res & -__addr_ok(s);