diff options
Diffstat (limited to 'arch/m68k')
-rw-r--r-- | arch/m68k/lib/Makefile | 4 | ||||
-rw-r--r-- | arch/m68k/lib/uaccess.c | 222 |
2 files changed, 224 insertions, 2 deletions
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile index ebe51a513817..6bbf19f96007 100644 --- a/arch/m68k/lib/Makefile +++ b/arch/m68k/lib/Makefile | |||
@@ -4,5 +4,5 @@ | |||
4 | 4 | ||
5 | EXTRA_AFLAGS := -traditional | 5 | EXTRA_AFLAGS := -traditional |
6 | 6 | ||
7 | lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ | 7 | lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ |
8 | checksum.o string.o semaphore.o | 8 | checksum.o string.o semaphore.o uaccess.o |
diff --git a/arch/m68k/lib/uaccess.c b/arch/m68k/lib/uaccess.c new file mode 100644 index 000000000000..1bc188c0d983 --- /dev/null +++ b/arch/m68k/lib/uaccess.c | |||
@@ -0,0 +1,222 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file COPYING in the main directory of this archive | ||
4 | * for more details. | ||
5 | */ | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <asm/uaccess.h> | ||
9 | |||
10 | unsigned long __generic_copy_from_user(void *to, const void __user *from, | ||
11 | unsigned long n) | ||
12 | { | ||
13 | unsigned long tmp, res; | ||
14 | |||
15 | asm volatile ("\n" | ||
16 | " tst.l %0\n" | ||
17 | " jeq 2f\n" | ||
18 | "1: moves.l (%1)+,%3\n" | ||
19 | " move.l %3,(%2)+\n" | ||
20 | " subq.l #1,%0\n" | ||
21 | " jne 1b\n" | ||
22 | "2: btst #1,%5\n" | ||
23 | " jeq 4f\n" | ||
24 | "3: moves.w (%1)+,%3\n" | ||
25 | " move.w %3,(%2)+\n" | ||
26 | "4: btst #0,%5\n" | ||
27 | " jeq 6f\n" | ||
28 | "5: moves.b (%1)+,%3\n" | ||
29 | " move.b %3,(%2)+\n" | ||
30 | "6:\n" | ||
31 | " .section .fixup,\"ax\"\n" | ||
32 | " .even\n" | ||
33 | "10: move.l %0,%3\n" | ||
34 | "7: clr.l (%2)+\n" | ||
35 | " subq.l #1,%3\n" | ||
36 | " jne 7b\n" | ||
37 | " lsl.l #2,%0\n" | ||
38 | " btst #1,%5\n" | ||
39 | " jeq 8f\n" | ||
40 | "30: clr.w (%2)+\n" | ||
41 | " addq.l #2,%0\n" | ||
42 | "8: btst #0,%5\n" | ||
43 | " jeq 6b\n" | ||
44 | "50: clr.b (%2)+\n" | ||
45 | " addq.l #1,%0\n" | ||
46 | " jra 6b\n" | ||
47 | " .previous\n" | ||
48 | "\n" | ||
49 | " .section __ex_table,\"a\"\n" | ||
50 | " .align 4\n" | ||
51 | " .long 1b,10b\n" | ||
52 | " .long 3b,30b\n" | ||
53 | " .long 5b,50b\n" | ||
54 | " .previous" | ||
55 | : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp) | ||
56 | : "0" (n / 4), "d" (n & 3)); | ||
57 | |||
58 | return res; | ||
59 | } | ||
60 | EXPORT_SYMBOL(__generic_copy_from_user); | ||
61 | |||
62 | unsigned long __generic_copy_to_user(void __user *to, const void *from, | ||
63 | unsigned long n) | ||
64 | { | ||
65 | unsigned long tmp, res; | ||
66 | |||
67 | asm volatile ("\n" | ||
68 | " tst.l %0\n" | ||
69 | " jeq 4f\n" | ||
70 | "1: move.l (%1)+,%3\n" | ||
71 | "2: moves.l %3,(%2)+\n" | ||
72 | "3: subq.l #1,%0\n" | ||
73 | " jne 1b\n" | ||
74 | "4: btst #1,%5\n" | ||
75 | " jeq 6f\n" | ||
76 | " move.w (%1)+,%3\n" | ||
77 | "5: moves.w %3,(%2)+\n" | ||
78 | "6: btst #0,%5\n" | ||
79 | " jeq 8f\n" | ||
80 | " move.b (%1)+,%3\n" | ||
81 | "7: moves.b %3,(%2)+\n" | ||
82 | "8:\n" | ||
83 | " .section .fixup,\"ax\"\n" | ||
84 | " .even\n" | ||
85 | "20: lsl.l #2,%0\n" | ||
86 | "50: add.l %5,%0\n" | ||
87 | " jra 7b\n" | ||
88 | " .previous\n" | ||
89 | "\n" | ||
90 | " .section __ex_table,\"a\"\n" | ||
91 | " .align 4\n" | ||
92 | " .long 2b,20b\n" | ||
93 | " .long 3b,20b\n" | ||
94 | " .long 5b,50b\n" | ||
95 | " .long 6b,50b\n" | ||
96 | " .long 7b,50b\n" | ||
97 | " .long 8b,50b\n" | ||
98 | " .previous" | ||
99 | : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp) | ||
100 | : "0" (n / 4), "d" (n & 3)); | ||
101 | |||
102 | return res; | ||
103 | } | ||
104 | EXPORT_SYMBOL(__generic_copy_to_user); | ||
105 | |||
106 | /* | ||
107 | * Copy a null terminated string from userspace. | ||
108 | */ | ||
109 | long strncpy_from_user(char *dst, const char __user *src, long count) | ||
110 | { | ||
111 | long res; | ||
112 | char c; | ||
113 | |||
114 | if (count <= 0) | ||
115 | return count; | ||
116 | |||
117 | asm volatile ("\n" | ||
118 | "1: moves.b (%2)+,%4\n" | ||
119 | " move.b %4,(%1)+\n" | ||
120 | " jeq 2f\n" | ||
121 | " subq.l #1,%3\n" | ||
122 | " jne 1b\n" | ||
123 | "2: sub.l %3,%0\n" | ||
124 | "3:\n" | ||
125 | " .section .fixup,\"ax\"\n" | ||
126 | " .even\n" | ||
127 | "10: move.l %5,%0\n" | ||
128 | " jra 3b\n" | ||
129 | " .previous\n" | ||
130 | "\n" | ||
131 | " .section __ex_table,\"a\"\n" | ||
132 | " .align 4\n" | ||
133 | " .long 1b,10b\n" | ||
134 | " .previous" | ||
135 | : "=d" (res), "+a" (dst), "+a" (src), "+r" (count), "=&d" (c) | ||
136 | : "i" (-EFAULT), "0" (count)); | ||
137 | |||
138 | return res; | ||
139 | } | ||
140 | EXPORT_SYMBOL(strncpy_from_user); | ||
141 | |||
142 | /* | ||
143 | * Return the size of a string (including the ending 0) | ||
144 | * | ||
145 | * Return 0 on exception, a value greater than N if too long | ||
146 | */ | ||
147 | long strnlen_user(const char __user *src, long n) | ||
148 | { | ||
149 | char c; | ||
150 | long res; | ||
151 | |||
152 | asm volatile ("\n" | ||
153 | "1: subq.l #1,%1\n" | ||
154 | " jmi 3f\n" | ||
155 | "2: moves.b (%0)+,%2\n" | ||
156 | " tst.b %2\n" | ||
157 | " jne 1b\n" | ||
158 | " jra 4f\n" | ||
159 | "\n" | ||
160 | "3: addq.l #1,%0\n" | ||
161 | "4: sub.l %4,%0\n" | ||
162 | "5:\n" | ||
163 | " .section .fixup,\"ax\"\n" | ||
164 | " .even\n" | ||
165 | "20: sub.l %0,%0\n" | ||
166 | " jra 5b\n" | ||
167 | " .previous\n" | ||
168 | "\n" | ||
169 | " .section __ex_table,\"a\"\n" | ||
170 | " .align 4\n" | ||
171 | " .long 2b,20b\n" | ||
172 | " .previous\n" | ||
173 | : "=&a" (res), "+d" (n), "=&d" (c) | ||
174 | : "0" (src), "r" (src)); | ||
175 | |||
176 | return res; | ||
177 | } | ||
178 | EXPORT_SYMBOL(strnlen_user); | ||
179 | |||
180 | /* | ||
181 | * Zero Userspace | ||
182 | */ | ||
183 | |||
184 | unsigned long clear_user(void __user *to, unsigned long n) | ||
185 | { | ||
186 | unsigned long res; | ||
187 | |||
188 | asm volatile ("\n" | ||
189 | " tst.l %0\n" | ||
190 | " jeq 3f\n" | ||
191 | "1: moves.l %2,(%1)+\n" | ||
192 | "2: subq.l #1,%0\n" | ||
193 | " jne 1b\n" | ||
194 | "3: btst #1,%4\n" | ||
195 | " jeq 5f\n" | ||
196 | "4: moves.w %2,(%1)+\n" | ||
197 | "5: btst #0,%4\n" | ||
198 | " jeq 7f\n" | ||
199 | "6: moves.b %2,(%1)\n" | ||
200 | "7:\n" | ||
201 | " .section .fixup,\"ax\"\n" | ||
202 | " .even\n" | ||
203 | "10: lsl.l #2,%0\n" | ||
204 | "40: add.l %4,%0\n" | ||
205 | " jra 7b\n" | ||
206 | " .previous\n" | ||
207 | "\n" | ||
208 | " .section __ex_table,\"a\"\n" | ||
209 | " .align 4\n" | ||
210 | " .long 1b,10b\n" | ||
211 | " .long 2b,10b\n" | ||
212 | " .long 4b,40b\n" | ||
213 | " .long 5b,40b\n" | ||
214 | " .long 6b,40b\n" | ||
215 | " .long 7b,40b\n" | ||
216 | " .previous" | ||
217 | : "=d" (res), "+a" (to) | ||
218 | : "r" (0), "0" (n / 4), "d" (n & 3)); | ||
219 | |||
220 | return res; | ||
221 | } | ||
222 | EXPORT_SYMBOL(clear_user); | ||