1 /*
2 * User address space access functions.
3 *
4 * Copyright 1997 Andi Kleen <ak@muc.de>
5 * Copyright 1997 Linus Torvalds
6 * Copyright 2002 Andi Kleen <ak@suse.de>
7 */
8
9 #include <xen/lib.h>
10 #include <xen/sched.h>
11 #include <asm/uaccess.h>
12
__copy_to_user_ll(void __user * to,const void * from,unsigned n)13 unsigned __copy_to_user_ll(void __user *to, const void *from, unsigned n)
14 {
15 unsigned dummy;
16
17 stac();
18 asm volatile (
19 " cmp $"STR(2*BYTES_PER_LONG-1)", %[cnt]\n"
20 " jbe 1f\n"
21 " mov %k[to], %[cnt]\n"
22 " neg %[cnt]\n"
23 " and $"STR(BYTES_PER_LONG-1)", %[cnt]\n"
24 " sub %[cnt], %[aux]\n"
25 "4: rep movsb\n" /* make 'to' address aligned */
26 " mov %[aux], %[cnt]\n"
27 " shr $"STR(LONG_BYTEORDER)", %[cnt]\n"
28 " and $"STR(BYTES_PER_LONG-1)", %[aux]\n"
29 " .align 2,0x90\n"
30 "0: rep movs"__OS"\n" /* as many words as possible... */
31 " mov %[aux],%[cnt]\n"
32 "1: rep movsb\n" /* ...remainder copied as bytes */
33 "2:\n"
34 ".section .fixup,\"ax\"\n"
35 "5: add %[aux], %[cnt]\n"
36 " jmp 2b\n"
37 "3: lea (%q[aux], %q[cnt], "STR(BYTES_PER_LONG)"), %[cnt]\n"
38 " jmp 2b\n"
39 ".previous\n"
40 _ASM_EXTABLE(4b, 5b)
41 _ASM_EXTABLE(0b, 3b)
42 _ASM_EXTABLE(1b, 2b)
43 : [cnt] "+c" (n), [to] "+D" (to), [from] "+S" (from),
44 [aux] "=&r" (dummy)
45 : "[aux]" (n)
46 : "memory" );
47 clac();
48
49 return n;
50 }
51
__copy_from_user_ll(void * to,const void __user * from,unsigned n)52 unsigned __copy_from_user_ll(void *to, const void __user *from, unsigned n)
53 {
54 unsigned dummy;
55
56 stac();
57 asm volatile (
58 " cmp $"STR(2*BYTES_PER_LONG-1)", %[cnt]\n"
59 " jbe 1f\n"
60 " mov %k[to], %[cnt]\n"
61 " neg %[cnt]\n"
62 " and $"STR(BYTES_PER_LONG-1)", %[cnt]\n"
63 " sub %[cnt], %[aux]\n"
64 "4: rep movsb\n" /* make 'to' address aligned */
65 " mov %[aux],%[cnt]\n"
66 " shr $"STR(LONG_BYTEORDER)", %[cnt]\n"
67 " and $"STR(BYTES_PER_LONG-1)", %[aux]\n"
68 " .align 2,0x90\n"
69 "0: rep movs"__OS"\n" /* as many words as possible... */
70 " mov %[aux], %[cnt]\n"
71 "1: rep movsb\n" /* ...remainder copied as bytes */
72 "2:\n"
73 ".section .fixup,\"ax\"\n"
74 "5: add %[aux], %[cnt]\n"
75 " jmp 6f\n"
76 "3: lea (%q[aux], %q[cnt], "STR(BYTES_PER_LONG)"), %[cnt]\n"
77 "6: mov %[cnt], %k[from]\n"
78 " xchg %%eax, %[aux]\n"
79 " xor %%eax, %%eax\n"
80 " rep stosb\n"
81 " xchg %[aux], %%eax\n"
82 " mov %k[from], %[cnt]\n"
83 " jmp 2b\n"
84 ".previous\n"
85 _ASM_EXTABLE(4b, 5b)
86 _ASM_EXTABLE(0b, 3b)
87 _ASM_EXTABLE(1b, 6b)
88 : [cnt] "+c" (n), [to] "+D" (to), [from] "+S" (from),
89 [aux] "=&r" (dummy)
90 : "[aux]" (n)
91 : "memory" );
92 clac();
93
94 return n;
95 }
96
97 /**
98 * copy_to_user: - Copy a block of data into user space.
99 * @to: Destination address, in user space.
100 * @from: Source address, in kernel space.
101 * @n: Number of bytes to copy.
102 *
103 * Context: User context only. This function may sleep.
104 *
105 * Copy data from kernel space to user space.
106 *
107 * Returns number of bytes that could not be copied.
108 * On success, this will be zero.
109 */
copy_to_user(void __user * to,const void * from,unsigned n)110 unsigned copy_to_user(void __user *to, const void *from, unsigned n)
111 {
112 if ( access_ok(to, n) )
113 n = __copy_to_user(to, from, n);
114 return n;
115 }
116
117 /**
118 * clear_user: - Zero a block of memory in user space.
119 * @to: Destination address, in user space.
120 * @n: Number of bytes to zero.
121 *
122 * Zero a block of memory in user space.
123 *
124 * Returns number of bytes that could not be cleared.
125 * On success, this will be zero.
126 */
clear_user(void __user * to,unsigned n)127 unsigned clear_user(void __user *to, unsigned n)
128 {
129 if ( access_ok(to, n) )
130 {
131 stac();
132 asm volatile (
133 "0: rep stos"__OS"\n"
134 " mov %[bytes], %[cnt]\n"
135 "1: rep stosb\n"
136 "2:\n"
137 ".section .fixup,\"ax\"\n"
138 "3: lea (%q[bytes], %q[longs], "STR(BYTES_PER_LONG)"), %[cnt]\n"
139 " jmp 2b\n"
140 ".previous\n"
141 _ASM_EXTABLE(0b,3b)
142 _ASM_EXTABLE(1b,2b)
143 : [cnt] "=&c" (n), [to] "+D" (to)
144 : [bytes] "r" (n & (BYTES_PER_LONG - 1)),
145 [longs] "0" (n / BYTES_PER_LONG), "a" (0) );
146 clac();
147 }
148
149 return n;
150 }
151
152 /**
153 * copy_from_user: - Copy a block of data from user space.
154 * @to: Destination address, in kernel space.
155 * @from: Source address, in user space.
156 * @n: Number of bytes to copy.
157 *
158 * Context: User context only. This function may sleep.
159 *
160 * Copy data from user space to kernel space.
161 *
162 * Returns number of bytes that could not be copied.
163 * On success, this will be zero.
164 *
165 * If some data could not be copied, this function will pad the copied
166 * data to the requested size using zero bytes.
167 */
copy_from_user(void * to,const void __user * from,unsigned n)168 unsigned copy_from_user(void *to, const void __user *from, unsigned n)
169 {
170 if ( access_ok(from, n) )
171 n = __copy_from_user(to, from, n);
172 else
173 memset(to, 0, n);
174 return n;
175 }
176
177 /*
178 * Local variables:
179 * mode: C
180 * c-file-style: "BSD"
181 * c-basic-offset: 4
182 * tab-width: 4
183 * indent-tabs-mode: nil
184 * End:
185 */
186