Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
usercopy.c
Go to the documentation of this file.
1 /*
2  * User address space access functions.
3  * The non inlined parts of asm-m32r/uaccess.h are here.
4  *
5  * Copyright 1997 Andi Kleen <[email protected]>
6  * Copyright 1997 Linus Torvalds
7  * Copyright 2001, 2002, 2004 Hirokazu Takata
8  */
9 #include <linux/prefetch.h>
10 #include <linux/string.h>
11 #include <linux/thread_info.h>
12 #include <asm/uaccess.h>
13 
14 unsigned long
15 __generic_copy_to_user(void __user *to, const void *from, unsigned long n)
16 {
17  prefetch(from);
18  if (access_ok(VERIFY_WRITE, to, n))
19  __copy_user(to,from,n);
20  return n;
21 }
22 
23 unsigned long
24 __generic_copy_from_user(void *to, const void __user *from, unsigned long n)
25 {
26  prefetchw(to);
27  if (access_ok(VERIFY_READ, from, n))
28  __copy_user_zeroing(to,from,n);
29  else
30  memset(to, 0, n);
31  return n;
32 }
33 
34 
35 /*
36  * Copy a null terminated string from userspace.
37  */
38 
39 #ifdef CONFIG_ISA_DUAL_ISSUE
40 
41 #define __do_strncpy_from_user(dst,src,count,res) \
42 do { \
43  int __d0, __d1, __d2; \
44  __asm__ __volatile__( \
45  " beqz %1, 2f\n" \
46  " .fillinsn\n" \
47  "0: ldb r14, @%3 || addi %3, #1\n" \
48  " stb r14, @%4 || addi %4, #1\n" \
49  " beqz r14, 1f\n" \
50  " addi %1, #-1\n" \
51  " bnez %1, 0b\n" \
52  " .fillinsn\n" \
53  "1: sub %0, %1\n" \
54  " .fillinsn\n" \
55  "2:\n" \
56  ".section .fixup,\"ax\"\n" \
57  " .balign 4\n" \
58  "3: seth r14, #high(2b)\n" \
59  " or3 r14, r14, #low(2b)\n" \
60  " jmp r14 || ldi %0, #%5\n" \
61  ".previous\n" \
62  ".section __ex_table,\"a\"\n" \
63  " .balign 4\n" \
64  " .long 0b,3b\n" \
65  ".previous" \
66  : "=&r"(res), "=&r"(count), "=&r" (__d0), "=&r" (__d1), \
67  "=&r" (__d2) \
68  : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), \
69  "4"(dst) \
70  : "r14", "cbit", "memory"); \
71 } while (0)
72 
73 #else /* not CONFIG_ISA_DUAL_ISSUE */
74 
75 #define __do_strncpy_from_user(dst,src,count,res) \
76 do { \
77  int __d0, __d1, __d2; \
78  __asm__ __volatile__( \
79  " beqz %1, 2f\n" \
80  " .fillinsn\n" \
81  "0: ldb r14, @%3\n" \
82  " stb r14, @%4\n" \
83  " addi %3, #1\n" \
84  " addi %4, #1\n" \
85  " beqz r14, 1f\n" \
86  " addi %1, #-1\n" \
87  " bnez %1, 0b\n" \
88  " .fillinsn\n" \
89  "1: sub %0, %1\n" \
90  " .fillinsn\n" \
91  "2:\n" \
92  ".section .fixup,\"ax\"\n" \
93  " .balign 4\n" \
94  "3: ldi %0, #%5\n" \
95  " seth r14, #high(2b)\n" \
96  " or3 r14, r14, #low(2b)\n" \
97  " jmp r14\n" \
98  ".previous\n" \
99  ".section __ex_table,\"a\"\n" \
100  " .balign 4\n" \
101  " .long 0b,3b\n" \
102  ".previous" \
103  : "=&r"(res), "=&r"(count), "=&r" (__d0), "=&r" (__d1), \
104  "=&r" (__d2) \
105  : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), \
106  "4"(dst) \
107  : "r14", "cbit", "memory"); \
108 } while (0)
109 
110 #endif /* CONFIG_ISA_DUAL_ISSUE */
111 
112 long
113 __strncpy_from_user(char *dst, const char __user *src, long count)
114 {
115  long res;
116  __do_strncpy_from_user(dst, src, count, res);
117  return res;
118 }
119 
120 long
121 strncpy_from_user(char *dst, const char __user *src, long count)
122 {
123  long res = -EFAULT;
124  if (access_ok(VERIFY_READ, src, 1))
125  __do_strncpy_from_user(dst, src, count, res);
126  return res;
127 }
128 
129 
130 /*
131  * Zero Userspace
132  */
133 
134 #ifdef CONFIG_ISA_DUAL_ISSUE
135 
136 #define __do_clear_user(addr,size) \
137 do { \
138  int __dst, __c; \
139  __asm__ __volatile__( \
140  " beqz %1, 9f\n" \
141  " and3 r14, %0, #3\n" \
142  " bnez r14, 2f\n" \
143  " and3 r14, %1, #3\n" \
144  " bnez r14, 2f\n" \
145  " and3 %1, %1, #3\n" \
146  " beqz %2, 2f\n" \
147  " addi %0, #-4\n" \
148  " .fillinsn\n" \
149  "0: ; word clear \n" \
150  " st %6, @+%0 || addi %2, #-1\n" \
151  " bnez %2, 0b\n" \
152  " beqz %1, 9f\n" \
153  " .fillinsn\n" \
154  "2: ; byte clear \n" \
155  " stb %6, @%0 || addi %1, #-1\n" \
156  " addi %0, #1\n" \
157  " bnez %1, 2b\n" \
158  " .fillinsn\n" \
159  "9:\n" \
160  ".section .fixup,\"ax\"\n" \
161  " .balign 4\n" \
162  "4: slli %2, #2\n" \
163  " seth r14, #high(9b)\n" \
164  " or3 r14, r14, #low(9b)\n" \
165  " jmp r14 || add %1, %2\n" \
166  ".previous\n" \
167  ".section __ex_table,\"a\"\n" \
168  " .balign 4\n" \
169  " .long 0b,4b\n" \
170  " .long 2b,9b\n" \
171  ".previous\n" \
172  : "=&r"(__dst), "=&r"(size), "=&r"(__c) \
173  : "0"(addr), "1"(size), "2"(size / 4), "r"(0) \
174  : "r14", "cbit", "memory"); \
175 } while (0)
176 
177 #else /* not CONFIG_ISA_DUAL_ISSUE */
178 
179 #define __do_clear_user(addr,size) \
180 do { \
181  int __dst, __c; \
182  __asm__ __volatile__( \
183  " beqz %1, 9f\n" \
184  " and3 r14, %0, #3\n" \
185  " bnez r14, 2f\n" \
186  " and3 r14, %1, #3\n" \
187  " bnez r14, 2f\n" \
188  " and3 %1, %1, #3\n" \
189  " beqz %2, 2f\n" \
190  " addi %0, #-4\n" \
191  " .fillinsn\n" \
192  "0: st %6, @+%0 ; word clear \n" \
193  " addi %2, #-1\n" \
194  " bnez %2, 0b\n" \
195  " beqz %1, 9f\n" \
196  " .fillinsn\n" \
197  "2: stb %6, @%0 ; byte clear \n" \
198  " addi %1, #-1\n" \
199  " addi %0, #1\n" \
200  " bnez %1, 2b\n" \
201  " .fillinsn\n" \
202  "9:\n" \
203  ".section .fixup,\"ax\"\n" \
204  " .balign 4\n" \
205  "4: slli %2, #2\n" \
206  " add %1, %2\n" \
207  " seth r14, #high(9b)\n" \
208  " or3 r14, r14, #low(9b)\n" \
209  " jmp r14\n" \
210  ".previous\n" \
211  ".section __ex_table,\"a\"\n" \
212  " .balign 4\n" \
213  " .long 0b,4b\n" \
214  " .long 2b,9b\n" \
215  ".previous\n" \
216  : "=&r"(__dst), "=&r"(size), "=&r"(__c) \
217  : "0"(addr), "1"(size), "2"(size / 4), "r"(0) \
218  : "r14", "cbit", "memory"); \
219 } while (0)
220 
221 #endif /* not CONFIG_ISA_DUAL_ISSUE */
222 
223 unsigned long
224 clear_user(void __user *to, unsigned long n)
225 {
226  if (access_ok(VERIFY_WRITE, to, n))
227  __do_clear_user(to, n);
228  return n;
229 }
230 
231 unsigned long
232 __clear_user(void __user *to, unsigned long n)
233 {
234  __do_clear_user(to, n);
235  return n;
236 }
237 
238 /*
239  * Return the size of a string (including the ending 0)
240  *
241  * Return 0 on exception, a value greater than N if too long
242  */
243 
244 #ifdef CONFIG_ISA_DUAL_ISSUE
245 
246 long strnlen_user(const char __user *s, long n)
247 {
248  unsigned long mask = -__addr_ok(s);
249  unsigned long res;
250 
251  __asm__ __volatile__(
252  " and %0, %5 || mv r1, %1\n"
253  " beqz %0, strnlen_exit\n"
254  " and3 r0, %1, #3\n"
255  " bnez r0, strnlen_byte_loop\n"
256  " cmpui %0, #4\n"
257  " bc strnlen_byte_loop\n"
258  "strnlen_word_loop:\n"
259  "0: ld r0, @%1+\n"
260  " pcmpbz r0\n"
261  " bc strnlen_last_bytes_fixup\n"
262  " addi %0, #-4\n"
263  " beqz %0, strnlen_exit\n"
264  " bgtz %0, strnlen_word_loop\n"
265  "strnlen_last_bytes:\n"
266  " mv %0, %4\n"
267  "strnlen_last_bytes_fixup:\n"
268  " addi %1, #-4\n"
269  "strnlen_byte_loop:\n"
270  "1: ldb r0, @%1 || addi %0, #-1\n"
271  " beqz r0, strnlen_exit\n"
272  " addi %1, #1\n"
273  " bnez %0, strnlen_byte_loop\n"
274  "strnlen_exit:\n"
275  " sub %1, r1\n"
276  " add3 %0, %1, #1\n"
277  " .fillinsn\n"
278  "9:\n"
279  ".section .fixup,\"ax\"\n"
280  " .balign 4\n"
281  "4: addi %1, #-4\n"
282  " .fillinsn\n"
283  "5: seth r1, #high(9b)\n"
284  " or3 r1, r1, #low(9b)\n"
285  " jmp r1 || ldi %0, #0\n"
286  ".previous\n"
287  ".section __ex_table,\"a\"\n"
288  " .balign 4\n"
289  " .long 0b,4b\n"
290  " .long 1b,5b\n"
291  ".previous"
292  : "=&r" (res), "=r" (s)
293  : "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
294  : "r0", "r1", "cbit");
295 
296  /* NOTE: strnlen_user() algorithm:
297  * {
298  * char *p;
299  * for (p = s; n-- && *p != '\0'; ++p)
300  * ;
301  * return p - s + 1;
302  * }
303  */
304 
305  /* NOTE: If a null char. exists, return 0.
306  * if ((x - 0x01010101) & ~x & 0x80808080)\n"
307  * return 0;\n"
308  */
309 
310  return res & mask;
311 }
312 
313 #else /* not CONFIG_ISA_DUAL_ISSUE */
314 
315 long strnlen_user(const char __user *s, long n)
316 {
317  unsigned long mask = -__addr_ok(s);
318  unsigned long res;
319 
320  __asm__ __volatile__(
321  " and %0, %5\n"
322  " mv r1, %1\n"
323  " beqz %0, strnlen_exit\n"
324  " and3 r0, %1, #3\n"
325  " bnez r0, strnlen_byte_loop\n"
326  " cmpui %0, #4\n"
327  " bc strnlen_byte_loop\n"
328  " sll3 r3, %6, #7\n"
329  "strnlen_word_loop:\n"
330  "0: ld r0, @%1+\n"
331  " not r2, r0\n"
332  " sub r0, %6\n"
333  " and r2, r3\n"
334  " and r2, r0\n"
335  " bnez r2, strnlen_last_bytes_fixup\n"
336  " addi %0, #-4\n"
337  " beqz %0, strnlen_exit\n"
338  " bgtz %0, strnlen_word_loop\n"
339  "strnlen_last_bytes:\n"
340  " mv %0, %4\n"
341  "strnlen_last_bytes_fixup:\n"
342  " addi %1, #-4\n"
343  "strnlen_byte_loop:\n"
344  "1: ldb r0, @%1\n"
345  " addi %0, #-1\n"
346  " beqz r0, strnlen_exit\n"
347  " addi %1, #1\n"
348  " bnez %0, strnlen_byte_loop\n"
349  "strnlen_exit:\n"
350  " sub %1, r1\n"
351  " add3 %0, %1, #1\n"
352  " .fillinsn\n"
353  "9:\n"
354  ".section .fixup,\"ax\"\n"
355  " .balign 4\n"
356  "4: addi %1, #-4\n"
357  " .fillinsn\n"
358  "5: ldi %0, #0\n"
359  " seth r1, #high(9b)\n"
360  " or3 r1, r1, #low(9b)\n"
361  " jmp r1\n"
362  ".previous\n"
363  ".section __ex_table,\"a\"\n"
364  " .balign 4\n"
365  " .long 0b,4b\n"
366  " .long 1b,5b\n"
367  ".previous"
368  : "=&r" (res), "=r" (s)
369  : "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
370  : "r0", "r1", "r2", "r3", "cbit");
371 
372  /* NOTE: strnlen_user() algorithm:
373  * {
374  * char *p;
375  * for (p = s; n-- && *p != '\0'; ++p)
376  * ;
377  * return p - s + 1;
378  * }
379  */
380 
381  /* NOTE: If a null char. exists, return 0.
382  * if ((x - 0x01010101) & ~x & 0x80808080)\n"
383  * return 0;\n"
384  */
385 
386  return res & mask;
387 }
388 
389 #endif /* CONFIG_ISA_DUAL_ISSUE */
390