Committer: Michael Beasley <mike@snafu.setup>
[mikesnafu-overlay.git] / arch / mn10300 / lib / usercopy.c
bloba75b203059c1b358434f616ae7b3a7243cb65d33
1 /* MN10300 Userspace accessor functions
3 * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public Licence
9 * as published by the Free Software Foundation; either version
10 * 2 of the Licence, or (at your option) any later version.
12 #include <asm/uaccess.h>
14 unsigned long
15 __generic_copy_to_user(void *to, const void *from, unsigned long n)
17 if (access_ok(VERIFY_WRITE, to, n))
18 __copy_user(to, from, n);
19 return n;
22 unsigned long
23 __generic_copy_from_user(void *to, const void *from, unsigned long n)
25 if (access_ok(VERIFY_READ, from, n))
26 __copy_user_zeroing(to, from, n);
27 return n;
31 * Copy a null terminated string from userspace.
33 #define __do_strncpy_from_user(dst, src, count, res) \
34 do { \
35 int w; \
36 asm volatile( \
37 " mov %1,%0\n" \
38 " cmp 0,%1\n" \
39 " beq 2f\n" \
40 "0:\n" \
41 " movbu (%5),%2\n" \
42 "1:\n" \
43 " movbu %2,(%6)\n" \
44 " inc %5\n" \
45 " inc %6\n" \
46 " cmp 0,%2\n" \
47 " beq 2f\n" \
48 " add -1,%1\n" \
49 " bne 0b\n" \
50 "2:\n" \
51 " sub %1,%0\n" \
52 "3:\n" \
53 " .section .fixup,\"ax\"\n" \
54 "4:\n" \
55 " mov %3,%0\n" \
56 " jmp 3b\n" \
57 " .previous\n" \
58 " .section __ex_table,\"a\"\n" \
59 " .balign 4\n" \
60 " .long 0b,4b\n" \
61 " .long 1b,4b\n" \
62 " .previous" \
63 :"=&r"(res), "=r"(count), "=&r"(w) \
64 :"i"(-EFAULT), "1"(count), "a"(src), "a"(dst) \
65 :"memory"); \
66 } while (0)
68 long
69 __strncpy_from_user(char *dst, const char *src, long count)
71 long res;
72 __do_strncpy_from_user(dst, src, count, res);
73 return res;
76 long
77 strncpy_from_user(char *dst, const char *src, long count)
79 long res = -EFAULT;
80 if (access_ok(VERIFY_READ, src, 1))
81 __do_strncpy_from_user(dst, src, count, res);
82 return res;
87 * Clear a userspace memory
89 #define __do_clear_user(addr, size) \
90 do { \
91 int w; \
92 asm volatile( \
93 " cmp 0,%0\n" \
94 " beq 1f\n" \
95 " clr %1\n" \
96 "0: movbu %1,(%3,%2)\n" \
97 " inc %3\n" \
98 " cmp %0,%3\n" \
99 " bne 0b\n" \
100 "1:\n" \
101 " sub %3,%0\n" \
102 "2:\n" \
103 ".section .fixup,\"ax\"\n" \
104 "3: jmp 2b\n" \
105 ".previous\n" \
106 ".section __ex_table,\"a\"\n" \
107 " .balign 4\n" \
108 " .long 0b,3b\n" \
109 ".previous\n" \
110 : "+r"(size), "=&r"(w) \
111 : "a"(addr), "d"(0) \
112 : "memory"); \
113 } while (0)
115 unsigned long
116 __clear_user(void *to, unsigned long n)
118 __do_clear_user(to, n);
119 return n;
122 unsigned long
123 clear_user(void *to, unsigned long n)
125 if (access_ok(VERIFY_WRITE, to, n))
126 __do_clear_user(to, n);
127 return n;
131 * Return the size of a string (including the ending 0)
133 * Return 0 on exception, a value greater than N if too long
135 long strnlen_user(const char *s, long n)
137 unsigned long res, w;
139 if (!__addr_ok(s))
140 return 0;
142 if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg)
143 n = current_thread_info()->addr_limit.seg - (u_long)s;
145 asm volatile(
146 "0: cmp %4,%0\n"
147 " beq 2f\n"
148 "1: movbu (%0,%3),%1\n"
149 " inc %0\n"
150 " cmp 0,%1\n"
151 " beq 3f\n"
152 " bra 0b\n"
153 "2: clr %0\n"
154 "3:\n"
155 ".section .fixup,\"ax\"\n"
156 "4: jmp 2b\n"
157 ".previous\n"
158 ".section __ex_table,\"a\"\n"
159 " .balign 4\n"
160 " .long 1b,4b\n"
161 ".previous\n"
162 :"=d"(res), "=&r"(w)
163 :"0"(0), "a"(s), "r"(n)
164 :"memory");
165 return res;