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