Import 2.1.118
[davej-history.git] / arch / i386 / lib / usercopy.c
blobd5b052c20f3cab7e460faeed2a1e7321ceb281be
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 unsigned long
11 __generic_copy_to_user(void *to, const void *from, unsigned long n)
13 if (access_ok(VERIFY_WRITE, to, n))
14 __copy_user(to,from,n);
15 return n;
18 unsigned long
19 __generic_copy_from_user(void *to, const void *from, unsigned long n)
21 if (access_ok(VERIFY_READ, from, n))
22 __copy_user_zeroing(to,from,n);
23 return n;
28 * Copy a null terminated string from userspace.
31 #define __do_strncpy_from_user(dst,src,count,res) \
32 __asm__ __volatile__( \
33 " testl %1,%1\n" \
34 " jz 2f\n" \
35 "0: lodsb\n" \
36 " stosb\n" \
37 " testb %%al,%%al\n" \
38 " jz 1f\n" \
39 " decl %1\n" \
40 " jnz 0b\n" \
41 "1: subl %1,%0\n" \
42 "2:\n" \
43 ".section .fixup,\"ax\"\n" \
44 "3: movl %2,%0\n" \
45 " jmp 2b\n" \
46 ".previous\n" \
47 ".section __ex_table,\"a\"\n" \
48 " .align 4\n" \
49 " .long 0b,3b\n" \
50 ".previous" \
51 : "=d"(res), "=c"(count) \
52 : "i"(-EFAULT), "0"(count), "1"(count), "S"(src), "D"(dst) \
53 : "si", "di", "ax", "memory")
55 long
56 __strncpy_from_user(char *dst, const char *src, long count)
58 long res;
59 __do_strncpy_from_user(dst, src, count, res);
60 return res;
63 long
64 strncpy_from_user(char *dst, const char *src, long count)
66 long res = -EFAULT;
67 if (access_ok(VERIFY_READ, src, 1))
68 __do_strncpy_from_user(dst, src, count, res);
69 return res;
74 * Zero Userspace
77 #define __do_clear_user(addr,size) \
78 __asm__ __volatile__( \
79 "0: rep; stosl\n" \
80 " movl %1,%0\n" \
81 "1: rep; stosb\n" \
82 "2:\n" \
83 ".section .fixup,\"ax\"\n" \
84 "3: lea 0(%1,%0,4),%0\n" \
85 " jmp 2b\n" \
86 ".previous\n" \
87 ".section __ex_table,\"a\"\n" \
88 " .align 4\n" \
89 " .long 0b,3b\n" \
90 " .long 1b,2b\n" \
91 ".previous" \
92 : "=&c"(size) \
93 : "r"(size & 3), "0"(size / 4), "D"(addr), "a"(0) \
94 : "di")
96 unsigned long
97 clear_user(void *to, unsigned long n)
99 if (access_ok(VERIFY_WRITE, to, n))
100 __do_clear_user(to, n);
101 return n;
104 unsigned long
105 __clear_user(void *to, unsigned long n)
107 __do_clear_user(to, n);
108 return n;
112 * Return the size of a string (including the ending 0)
114 * Return 0 for error
117 long strlen_user(const char *s)
119 unsigned long res;
121 __asm__ __volatile__(
122 "0: repne; scasb\n"
123 " notl %0\n"
124 "1:\n"
125 ".section .fixup,\"ax\"\n"
126 "2: xorl %0,%0\n"
127 " jmp 1b\n"
128 ".previous\n"
129 ".section __ex_table,\"a\"\n"
130 " .align 4\n"
131 " .long 0b,2b\n"
132 ".previous"
133 :"=c" (res), "=D" (s)
134 :"1" (s), "a" (0), "0" (-__addr_ok(s)));
135 return res & -__addr_ok(s);