Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios.git] / kitten / arch / x86_64 / lib / usercopy.c
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 #include <arch/uaccess.h>
9
10 /*
11  * Copy a null terminated string from userspace.
12  */
13
14 #define __do_strncpy_from_user(dst,src,count,res)                          \
15 do {                                                                       \
16         long __d0, __d1, __d2;                                             \
17         __asm__ __volatile__(                                              \
18                 "       testq %1,%1\n"                                     \
19                 "       jz 2f\n"                                           \
20                 "0:     lodsb\n"                                           \
21                 "       stosb\n"                                           \
22                 "       testb %%al,%%al\n"                                 \
23                 "       jz 1f\n"                                           \
24                 "       decq %1\n"                                         \
25                 "       jnz 0b\n"                                          \
26                 "1:     subq %1,%0\n"                                      \
27                 "2:\n"                                                     \
28                 ".section .fixup,\"ax\"\n"                                 \
29                 "3:     movq %5,%0\n"                                      \
30                 "       jmp 2b\n"                                          \
31                 ".previous\n"                                              \
32                 ".section __ex_table,\"a\"\n"                              \
33                 "       .align 8\n"                                        \
34                 "       .quad 0b,3b\n"                                     \
35                 ".previous"                                                \
36                 : "=r"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1),      \
37                   "=&D" (__d2)                                             \
38                 : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
39                 : "memory");                                               \
40 } while (0)
41
42 long
43 __strncpy_from_user(char *dst, const char __user *src, long count)
44 {
45         long res;
46         __do_strncpy_from_user(dst, src, count, res);
47         return res;
48 }
49
50 long
51 strncpy_from_user(char *dst, const char __user *src, long count)
52 {
53         long res = -EFAULT;
54         if (access_ok(VERIFY_READ, src, 1))
55                 return __strncpy_from_user(dst, src, count);
56         return res;
57 }
58
59 /*
60  * Zero Userspace
61  */
62
63 unsigned long __clear_user(void __user *addr, unsigned long size)
64 {
65         long __d0;
66         /* no memory constraint because it doesn't change any memory gcc knows
67            about */
68         asm volatile(
69                 "       testq  %[size8],%[size8]\n"
70                 "       jz     4f\n"
71                 "0:     movq %[zero],(%[dst])\n"
72                 "       addq   %[eight],%[dst]\n"
73                 "       decl %%ecx ; jnz   0b\n"
74                 "4:     movq  %[size1],%%rcx\n"
75                 "       testl %%ecx,%%ecx\n"
76                 "       jz     2f\n"
77                 "1:     movb   %b[zero],(%[dst])\n"
78                 "       incq   %[dst]\n"
79                 "       decl %%ecx ; jnz  1b\n"
80                 "2:\n"
81                 ".section .fixup,\"ax\"\n"
82                 "3:     lea 0(%[size1],%[size8],8),%[size8]\n"
83                 "       jmp 2b\n"
84                 ".previous\n"
85                 ".section __ex_table,\"a\"\n"
86                 "       .align 8\n"
87                 "       .quad 0b,3b\n"
88                 "       .quad 1b,2b\n"
89                 ".previous"
90                 : [size8] "=c"(size), [dst] "=&D" (__d0)
91                 : [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr),
92                   [zero] "r" (0UL), [eight] "r" (8UL));
93         return size;
94 }
95
96 unsigned long clear_user(void __user *to, unsigned long n)
97 {
98         if (access_ok(VERIFY_WRITE, to, n))
99                 return __clear_user(to, n);
100         return n;
101 }
102
103 /*
104  * Return the size of a string (including the ending 0)
105  *
106  * Return 0 on exception, a value greater than N if too long
107  */
108
109 long __strnlen_user(const char __user *s, long n)
110 {
111         long res = 0;
112         char c;
113
114         while (1) {
115                 if (res>n)
116                         return n+1;
117                 if (__get_user(c, s))
118                         return 0;
119                 if (!c)
120                         return res+1;
121                 res++;
122                 s++;
123         }
124 }
125
126 long strnlen_user(const char __user *s, long n)
127 {
128         if (!access_ok(VERIFY_READ, s, n))
129                 return 0;
130         return __strnlen_user(s, n);
131 }
132
133 long strlen_user(const char __user *s)
134 {
135         long res = 0;
136         char c;
137
138         for (;;) {
139                 if (get_user(c, s))
140                         return 0;
141                 if (!c)
142                         return res+1;
143                 res++;
144                 s++;
145         }
146 }
147
148 unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len)
149 {
150         if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) { 
151                 return copy_user_generic((__force void *)to, (__force void *)from, len);
152         } 
153         return len;             
154 }
155