ia64/xen-unstable

view xen/arch/x86/x86_64/usercopy.c @ 5281:71124f0ea5d4

bitkeeper revision 1.1645 (429f63fb6JW1K1LYjnjnswN1KOd0Jg)

Merge firebug.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
into firebug.cl.cam.ac.uk:/local/scratch/cl349/xen-unstable.bk
author cl349@firebug.cl.cam.ac.uk
date Thu Jun 02 19:54:35 2005 +0000 (2005-06-02)
parents c62ee1a8ba98 fbb832f71d22
children
line source
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 */
9 #include <xen/config.h>
10 #include <xen/lib.h>
11 #include <asm/uaccess.h>
13 /*
14 * Zero Userspace
15 */
17 unsigned long __clear_user(void *addr, unsigned long size)
18 {
19 long __d0;
20 /* no memory constraint because it doesn't change any memory gcc knows
21 about */
22 asm volatile(
23 " testq %[size8],%[size8]\n"
24 " jz 4f\n"
25 "0: movq %[zero],(%[dst])\n"
26 " addq %[eight],%[dst]\n"
27 " decl %%ecx ; jnz 0b\n"
28 "4: movq %[size1],%%rcx\n"
29 " testl %%ecx,%%ecx\n"
30 " jz 2f\n"
31 "1: movb %b[zero],(%[dst])\n"
32 " incq %[dst]\n"
33 " decl %%ecx ; jnz 1b\n"
34 "2:\n"
35 ".section .fixup,\"ax\"\n"
36 "3: lea 0(%[size1],%[size8],8),%[size8]\n"
37 " jmp 2b\n"
38 ".previous\n"
39 ".section __ex_table,\"a\"\n"
40 " .align 8\n"
41 " .quad 0b,3b\n"
42 " .quad 1b,2b\n"
43 ".previous"
44 : [size8] "=c"(size), [dst] "=&D" (__d0)
45 : [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr),
46 [zero] "r" (0UL), [eight] "r" (8UL));
47 return size;
48 }
50 unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned n)
51 {
52 unsigned long __d0, __d1, __d2, __n = n;
53 __asm__ __volatile__(
54 " cmpq $15,%0\n"
55 " jbe 1f\n"
56 " mov %1,%0\n"
57 " neg %0\n"
58 " and $7,%0\n"
59 " sub %0,%3\n"
60 "4: rep; movsb\n" /* make 'to' address aligned */
61 " mov %3,%0\n"
62 " shr $3,%0\n"
63 " and $7,%3\n"
64 " .align 2,0x90\n"
65 "0: rep; movsq\n" /* as many quadwords as possible... */
66 " mov %3,%0\n"
67 "1: rep; movsb\n" /* ...remainder copied as bytes */
68 "2:\n"
69 ".section .fixup,\"ax\"\n"
70 "5: add %3,%0\n"
71 " jmp 2b\n"
72 "3: lea 0(%3,%0,8),%0\n"
73 " jmp 2b\n"
74 ".previous\n"
75 ".section __ex_table,\"a\"\n"
76 " .align 8\n"
77 " .quad 4b,5b\n"
78 " .quad 0b,3b\n"
79 " .quad 1b,2b\n"
80 ".previous"
81 : "=&c"(__n), "=&D" (__d0), "=&S" (__d1), "=r"(__d2)
82 : "3"(__n), "0"(__n), "1"(to), "2"(from)
83 : "memory");
84 return (unsigned)__n;
85 }
87 unsigned long
88 __copy_from_user_ll(void *to, const void __user *from, unsigned n)
89 {
90 unsigned long __d0, __d1, __d2, __n = n;
91 __asm__ __volatile__(
92 " cmp $15,%0\n"
93 " jbe 1f\n"
94 " mov %1,%0\n"
95 " neg %0\n"
96 " and $7,%0\n"
97 " sub %0,%3\n"
98 "4: rep; movsb\n" /* make 'to' address aligned */
99 " mov %3,%0\n"
100 " shr $3,%0\n"
101 " and $7,%3\n"
102 " .align 2,0x90\n"
103 "0: rep; movsq\n" /* as many quadwords as possible... */
104 " mov %3,%0\n"
105 "1: rep; movsb\n" /* ...remainder copied as bytes */
106 "2:\n"
107 ".section .fixup,\"ax\"\n"
108 "5: add %3,%0\n"
109 " jmp 6f\n"
110 "3: lea 0(%3,%0,8),%0\n"
111 "6: push %0\n"
112 " push %%rax\n"
113 " xor %%rax,%%rax\n"
114 " rep; stosb\n"
115 " pop %%rax\n"
116 " pop %0\n"
117 " jmp 2b\n"
118 ".previous\n"
119 ".section __ex_table,\"a\"\n"
120 " .align 8\n"
121 " .quad 4b,5b\n"
122 " .quad 0b,3b\n"
123 " .quad 1b,6b\n"
124 ".previous"
125 : "=&c"(__n), "=&D" (__d0), "=&S" (__d1), "=r"(__d2)
126 : "3"(__n), "0"(__n), "1"(to), "2"(from)
127 : "memory");
128 return (unsigned)__n;
129 }
131 unsigned long clear_user(void *to, unsigned long n)
132 {
133 if (access_ok(to, n))
134 return __clear_user(to, n);
135 return n;
136 }
138 /**
139 * copy_to_user: - Copy a block of data into user space.
140 * @to: Destination address, in user space.
141 * @from: Source address, in kernel space.
142 * @n: Number of bytes to copy.
143 *
144 * Context: User context only. This function may sleep.
145 *
146 * Copy data from kernel space to user space.
147 *
148 * Returns number of bytes that could not be copied.
149 * On success, this will be zero.
150 */
151 unsigned long
152 copy_to_user(void __user *to, const void *from, unsigned n)
153 {
154 if (access_ok(to, n))
155 n = __copy_to_user(to, from, n);
156 return n;
157 }
159 /**
160 * copy_from_user: - Copy a block of data from user space.
161 * @to: Destination address, in kernel space.
162 * @from: Source address, in user space.
163 * @n: Number of bytes to copy.
164 *
165 * Context: User context only. This function may sleep.
166 *
167 * Copy data from user space to kernel space.
168 *
169 * Returns number of bytes that could not be copied.
170 * On success, this will be zero.
171 *
172 * If some data could not be copied, this function will pad the copied
173 * data to the requested size using zero bytes.
174 */
175 unsigned long
176 copy_from_user(void *to, const void __user *from, unsigned n)
177 {
178 if (access_ok(from, n))
179 n = __copy_from_user(to, from, n);
180 else
181 memset(to, 0, n);
182 return n;
183 }