2 * User address space access functions.
3 * The non inlined parts of asm-m32r/uaccess.h are here.
5 * Copyright 1997 Andi Kleen <ak@muc.de>
6 * Copyright 1997 Linus Torvalds
7 * Copyright 2001, 2002, 2004 Hirokazu Takata
9 #include <linux/config.h>
10 #include <linux/prefetch.h>
11 #include <linux/string.h>
12 #include <linux/thread_info.h>
13 #include <asm/uaccess.h>
16 __generic_copy_to_user(void *to
, const void *from
, unsigned long n
)
19 if (access_ok(VERIFY_WRITE
, to
, n
))
20 __copy_user(to
,from
,n
);
25 __generic_copy_from_user(void *to
, const void *from
, unsigned long n
)
28 if (access_ok(VERIFY_READ
, from
, n
))
29 __copy_user_zeroing(to
,from
,n
);
37 * Copy a null terminated string from userspace.
40 #ifdef CONFIG_ISA_DUAL_ISSUE
42 #define __do_strncpy_from_user(dst,src,count,res) \
44 int __d0, __d1, __d2; \
45 __asm__ __volatile__( \
48 "0: ldb r14, @%3 || addi %3, #1\n" \
49 " stb r14, @%4 || addi %4, #1\n" \
57 ".section .fixup,\"ax\"\n" \
59 "3: seth r14, #high(2b)\n" \
60 " or3 r14, r14, #low(2b)\n" \
61 " jmp r14 || ldi %0, #%5\n" \
63 ".section __ex_table,\"a\"\n" \
67 : "=r"(res), "=r"(count), "=&r" (__d0), "=&r" (__d1), \
69 : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), \
71 : "r14", "cbit", "memory"); \
74 #else /* not CONFIG_ISA_DUAL_ISSUE */
76 #define __do_strncpy_from_user(dst,src,count,res) \
78 int __d0, __d1, __d2; \
79 __asm__ __volatile__( \
93 ".section .fixup,\"ax\"\n" \
96 " seth r14, #high(2b)\n" \
97 " or3 r14, r14, #low(2b)\n" \
100 ".section __ex_table,\"a\"\n" \
104 : "=r"(res), "=r"(count), "=&r" (__d0), "=&r" (__d1), \
106 : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), \
108 : "r14", "cbit", "memory"); \
111 #endif /* CONFIG_ISA_DUAL_ISSUE */
114 __strncpy_from_user(char *dst
, const char *src
, long count
)
117 __do_strncpy_from_user(dst
, src
, count
, res
);
122 strncpy_from_user(char *dst
, const char *src
, long count
)
125 if (access_ok(VERIFY_READ
, src
, 1))
126 __do_strncpy_from_user(dst
, src
, count
, res
);
135 #ifdef CONFIG_ISA_DUAL_ISSUE
137 #define __do_clear_user(addr,size) \
140 __asm__ __volatile__( \
142 " and3 r14, %0, #3\n" \
144 " and3 r14, %1, #3\n" \
146 " and3 %1, %1, #3\n" \
150 "0: ; word clear \n" \
151 " st %6, @+%0 || addi %2, #-1\n" \
155 "2: ; byte clear \n" \
156 " stb %6, @%0 || addi %1, #-1\n" \
161 ".section .fixup,\"ax\"\n" \
164 " seth r14, #high(9b)\n" \
165 " or3 r14, r14, #low(9b)\n" \
166 " jmp r14 || add %1, %2\n" \
168 ".section __ex_table,\"a\"\n" \
173 : "=&r"(__dst), "=&r"(size), "=&r"(__c) \
174 : "0"(addr), "1"(size), "2"(size / 4), "r"(0) \
175 : "r14", "cbit", "memory"); \
178 #else /* not CONFIG_ISA_DUAL_ISSUE */
180 #define __do_clear_user(addr,size) \
183 __asm__ __volatile__( \
185 " and3 r14, %0, #3\n" \
187 " and3 r14, %1, #3\n" \
189 " and3 %1, %1, #3\n" \
193 "0: st %6, @+%0 ; word clear \n" \
198 "2: stb %6, @%0 ; byte clear \n" \
204 ".section .fixup,\"ax\"\n" \
208 " seth r14, #high(9b)\n" \
209 " or3 r14, r14, #low(9b)\n" \
212 ".section __ex_table,\"a\"\n" \
217 : "=&r"(__dst), "=&r"(size), "=&r"(__c) \
218 : "0"(addr), "1"(size), "2"(size / 4), "r"(0) \
219 : "r14", "cbit", "memory"); \
222 #endif /* not CONFIG_ISA_DUAL_ISSUE */
225 clear_user(void *to
, unsigned long n
)
227 if (access_ok(VERIFY_WRITE
, to
, n
))
228 __do_clear_user(to
, n
);
233 __clear_user(void *to
, unsigned long n
)
235 __do_clear_user(to
, n
);
240 * Return the size of a string (including the ending 0)
242 * Return 0 on exception, a value greater than N if too long
245 #ifdef CONFIG_ISA_DUAL_ISSUE
247 long strnlen_user(const char *s
, long n
)
249 unsigned long mask
= -__addr_ok(s
);
252 __asm__
__volatile__(
253 " and %0, %5 || mv r1, %1\n"
254 " beqz %0, strnlen_exit\n"
256 " bnez r0, strnlen_byte_loop\n"
258 " bc strnlen_byte_loop\n"
259 "strnlen_word_loop:\n"
262 " bc strnlen_last_bytes_fixup\n"
264 " beqz %0, strnlen_exit\n"
265 " bgtz %0, strnlen_word_loop\n"
266 "strnlen_last_bytes:\n"
268 "strnlen_last_bytes_fixup:\n"
270 "strnlen_byte_loop:\n"
271 "1: ldb r0, @%1 || addi %0, #-1\n"
272 " beqz r0, strnlen_exit\n"
274 " bnez %0, strnlen_byte_loop\n"
280 ".section .fixup,\"ax\"\n"
284 "5: seth r1, #high(9b)\n"
285 " or3 r1, r1, #low(9b)\n"
286 " jmp r1 || ldi %0, #0\n"
288 ".section __ex_table,\"a\"\n"
293 : "=&r" (res
), "=r" (s
)
294 : "0" (n
), "1" (s
), "r" (n
& 3), "r" (mask
), "r"(0x01010101)
295 : "r0", "r1", "cbit");
297 /* NOTE: strnlen_user() algorism:
300 * for (p = s; n-- && *p != '\0'; ++p)
306 /* NOTE: If a null char. exists, return 0.
307 * if ((x - 0x01010101) & ~x & 0x80808080)\n"
314 #else /* not CONFIG_ISA_DUAL_ISSUE */
316 long strnlen_user(const char *s
, long n
)
318 unsigned long mask
= -__addr_ok(s
);
321 __asm__
__volatile__(
324 " beqz %0, strnlen_exit\n"
326 " bnez r0, strnlen_byte_loop\n"
328 " bc strnlen_byte_loop\n"
330 "strnlen_word_loop:\n"
336 " bnez r2, strnlen_last_bytes_fixup\n"
338 " beqz %0, strnlen_exit\n"
339 " bgtz %0, strnlen_word_loop\n"
340 "strnlen_last_bytes:\n"
342 "strnlen_last_bytes_fixup:\n"
344 "strnlen_byte_loop:\n"
347 " beqz r0, strnlen_exit\n"
349 " bnez %0, strnlen_byte_loop\n"
355 ".section .fixup,\"ax\"\n"
360 " seth r1, #high(9b)\n"
361 " or3 r1, r1, #low(9b)\n"
364 ".section __ex_table,\"a\"\n"
369 : "=&r" (res
), "=r" (s
)
370 : "0" (n
), "1" (s
), "r" (n
& 3), "r" (mask
), "r"(0x01010101)
371 : "r0", "r1", "r2", "r3", "cbit");
373 /* NOTE: strnlen_user() algorism:
376 * for (p = s; n-- && *p != '\0'; ++p)
382 /* NOTE: If a null char. exists, return 0.
383 * if ((x - 0x01010101) & ~x & 0x80808080)\n"
390 #endif /* CONFIG_ISA_DUAL_ISSUE */