diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2005-07-28 04:30:20 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2005-07-28 04:30:20 -0400 |
commit | 661299d9d0437a0ff72240f3d60016ac3a361a6e (patch) | |
tree | 765512576314fc3612b503f182b9ae4e60fcf849 /include/asm-cris/arch-v32/uaccess.h | |
parent | 05caac585f8abd6c0113856bc8858e3ef214d8a6 (diff) | |
parent | 41c018b7ecb60b1c2c4d5dee0cd37d32a94c45af (diff) |
Merge with Linus' 2.6 tree
Diffstat (limited to 'include/asm-cris/arch-v32/uaccess.h')
-rw-r--r-- | include/asm-cris/arch-v32/uaccess.h | 748 |
1 files changed, 748 insertions, 0 deletions
diff --git a/include/asm-cris/arch-v32/uaccess.h b/include/asm-cris/arch-v32/uaccess.h new file mode 100644 index 000000000000..055a0bdbe835 --- /dev/null +++ b/include/asm-cris/arch-v32/uaccess.h | |||
@@ -0,0 +1,748 @@ | |||
1 | /* | ||
2 | * Authors: Hans-Peter Nilsson (hp@axis.com) | ||
3 | * | ||
4 | */ | ||
5 | #ifndef _CRIS_ARCH_UACCESS_H | ||
6 | #define _CRIS_ARCH_UACCESS_H | ||
7 | |||
8 | /* | ||
9 | * We don't tell gcc that we are accessing memory, but this is OK | ||
10 | * because we do not write to any memory gcc knows about, so there | ||
11 | * are no aliasing issues. | ||
12 | * | ||
13 | * Note that PC at a fault is the address *at* the faulting | ||
14 | * instruction for CRISv32. | ||
15 | */ | ||
16 | #define __put_user_asm(x, addr, err, op) \ | ||
17 | __asm__ __volatile__( \ | ||
18 | "2: "op" %1,[%2]\n" \ | ||
19 | "4:\n" \ | ||
20 | " .section .fixup,\"ax\"\n" \ | ||
21 | "3: move.d %3,%0\n" \ | ||
22 | " jump 4b\n" \ | ||
23 | " nop\n" \ | ||
24 | " .previous\n" \ | ||
25 | " .section __ex_table,\"a\"\n" \ | ||
26 | " .dword 2b,3b\n" \ | ||
27 | " .previous\n" \ | ||
28 | : "=r" (err) \ | ||
29 | : "r" (x), "r" (addr), "g" (-EFAULT), "0" (err)) | ||
30 | |||
31 | #define __put_user_asm_64(x, addr, err) do { \ | ||
32 | int dummy_for_put_user_asm_64_; \ | ||
33 | __asm__ __volatile__( \ | ||
34 | "2: move.d %M2,[%1+]\n" \ | ||
35 | "4: move.d %H2,[%1]\n" \ | ||
36 | "5:\n" \ | ||
37 | " .section .fixup,\"ax\"\n" \ | ||
38 | "3: move.d %4,%0\n" \ | ||
39 | " jump 5b\n" \ | ||
40 | " .previous\n" \ | ||
41 | " .section __ex_table,\"a\"\n" \ | ||
42 | " .dword 2b,3b\n" \ | ||
43 | " .dword 4b,3b\n" \ | ||
44 | " .previous\n" \ | ||
45 | : "=r" (err), "=b" (dummy_for_put_user_asm_64_) \ | ||
46 | : "r" (x), "1" (addr), "g" (-EFAULT), \ | ||
47 | "0" (err)); \ | ||
48 | } while (0) | ||
49 | |||
50 | /* See comment before __put_user_asm. */ | ||
51 | |||
52 | #define __get_user_asm(x, addr, err, op) \ | ||
53 | __asm__ __volatile__( \ | ||
54 | "2: "op" [%2],%1\n" \ | ||
55 | "4:\n" \ | ||
56 | " .section .fixup,\"ax\"\n" \ | ||
57 | "3: move.d %3,%0\n" \ | ||
58 | " jump 4b\n" \ | ||
59 | " moveq 0,%1\n" \ | ||
60 | " .previous\n" \ | ||
61 | " .section __ex_table,\"a\"\n" \ | ||
62 | " .dword 2b,3b\n" \ | ||
63 | " .previous\n" \ | ||
64 | : "=r" (err), "=r" (x) \ | ||
65 | : "r" (addr), "g" (-EFAULT), "0" (err)) | ||
66 | |||
67 | #define __get_user_asm_64(x, addr, err) do { \ | ||
68 | int dummy_for_get_user_asm_64_; \ | ||
69 | __asm__ __volatile__( \ | ||
70 | "2: move.d [%2+],%M1\n" \ | ||
71 | "4: move.d [%2],%H1\n" \ | ||
72 | "5:\n" \ | ||
73 | " .section .fixup,\"ax\"\n" \ | ||
74 | "3: move.d %4,%0\n" \ | ||
75 | " jump 5b\n" \ | ||
76 | " moveq 0,%1\n" \ | ||
77 | " .previous\n" \ | ||
78 | " .section __ex_table,\"a\"\n" \ | ||
79 | " .dword 2b,3b\n" \ | ||
80 | " .dword 4b,3b\n" \ | ||
81 | " .previous\n" \ | ||
82 | : "=r" (err), "=r" (x), \ | ||
83 | "=b" (dummy_for_get_user_asm_64_) \ | ||
84 | : "2" (addr), "g" (-EFAULT), "0" (err));\ | ||
85 | } while (0) | ||
86 | |||
87 | /* | ||
88 | * Copy a null terminated string from userspace. | ||
89 | * | ||
90 | * Must return: | ||
91 | * -EFAULT for an exception | ||
92 | * count if we hit the buffer limit | ||
93 | * bytes copied if we hit a null byte | ||
94 | * (without the null byte) | ||
95 | */ | ||
96 | extern inline long | ||
97 | __do_strncpy_from_user(char *dst, const char *src, long count) | ||
98 | { | ||
99 | long res; | ||
100 | |||
101 | if (count == 0) | ||
102 | return 0; | ||
103 | |||
104 | /* | ||
105 | * Currently, in 2.4.0-test9, most ports use a simple byte-copy loop. | ||
106 | * So do we. | ||
107 | * | ||
108 | * This code is deduced from: | ||
109 | * | ||
110 | * char tmp2; | ||
111 | * long tmp1, tmp3; | ||
112 | * tmp1 = count; | ||
113 | * while ((*dst++ = (tmp2 = *src++)) != 0 | ||
114 | * && --tmp1) | ||
115 | * ; | ||
116 | * | ||
117 | * res = count - tmp1; | ||
118 | * | ||
119 | * with tweaks. | ||
120 | */ | ||
121 | |||
122 | __asm__ __volatile__ ( | ||
123 | " move.d %3,%0\n" | ||
124 | "5: move.b [%2+],$acr\n" | ||
125 | "1: beq 2f\n" | ||
126 | " move.b $acr,[%1+]\n" | ||
127 | |||
128 | " subq 1,%0\n" | ||
129 | "2: bne 1b\n" | ||
130 | " move.b [%2+],$acr\n" | ||
131 | |||
132 | " sub.d %3,%0\n" | ||
133 | " neg.d %0,%0\n" | ||
134 | "3:\n" | ||
135 | " .section .fixup,\"ax\"\n" | ||
136 | "4: move.d %7,%0\n" | ||
137 | " jump 3b\n" | ||
138 | " nop\n" | ||
139 | |||
140 | /* The address for a fault at the first move is trivial. | ||
141 | The address for a fault at the second move is that of | ||
142 | the preceding branch insn, since the move insn is in | ||
143 | its delay-slot. That address is also a branch | ||
144 | target. Just so you don't get confused... */ | ||
145 | " .previous\n" | ||
146 | " .section __ex_table,\"a\"\n" | ||
147 | " .dword 5b,4b\n" | ||
148 | " .dword 2b,4b\n" | ||
149 | " .previous" | ||
150 | : "=r" (res), "=b" (dst), "=b" (src), "=r" (count) | ||
151 | : "3" (count), "1" (dst), "2" (src), "g" (-EFAULT) | ||
152 | : "acr"); | ||
153 | |||
154 | return res; | ||
155 | } | ||
156 | |||
157 | /* A few copy asms to build up the more complex ones from. | ||
158 | |||
159 | Note again, a post-increment is performed regardless of whether a bus | ||
160 | fault occurred in that instruction, and PC for a faulted insn is the | ||
161 | address for the insn, or for the preceding branch when in a delay-slot. */ | ||
162 | |||
163 | #define __asm_copy_user_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
164 | __asm__ __volatile__ ( \ | ||
165 | COPY \ | ||
166 | "1:\n" \ | ||
167 | " .section .fixup,\"ax\"\n" \ | ||
168 | FIXUP \ | ||
169 | " .previous\n" \ | ||
170 | " .section __ex_table,\"a\"\n" \ | ||
171 | TENTRY \ | ||
172 | " .previous\n" \ | ||
173 | : "=b" (to), "=b" (from), "=r" (ret) \ | ||
174 | : "0" (to), "1" (from), "2" (ret) \ | ||
175 | : "acr", "memory") | ||
176 | |||
177 | #define __asm_copy_from_user_1(to, from, ret) \ | ||
178 | __asm_copy_user_cont(to, from, ret, \ | ||
179 | "2: move.b [%1+],$acr\n" \ | ||
180 | " move.b $acr,[%0+]\n", \ | ||
181 | "3: addq 1,%2\n" \ | ||
182 | " jump 1b\n" \ | ||
183 | " clear.b [%0+]\n", \ | ||
184 | " .dword 2b,3b\n") | ||
185 | |||
186 | #define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
187 | __asm_copy_user_cont(to, from, ret, \ | ||
188 | COPY \ | ||
189 | "2: move.w [%1+],$acr\n" \ | ||
190 | " move.w $acr,[%0+]\n", \ | ||
191 | FIXUP \ | ||
192 | "3: addq 2,%2\n" \ | ||
193 | " jump 1b\n" \ | ||
194 | " clear.w [%0+]\n", \ | ||
195 | TENTRY \ | ||
196 | " .dword 2b,3b\n") | ||
197 | |||
198 | #define __asm_copy_from_user_2(to, from, ret) \ | ||
199 | __asm_copy_from_user_2x_cont(to, from, ret, "", "", "") | ||
200 | |||
201 | #define __asm_copy_from_user_3(to, from, ret) \ | ||
202 | __asm_copy_from_user_2x_cont(to, from, ret, \ | ||
203 | "4: move.b [%1+],$acr\n" \ | ||
204 | " move.b $acr,[%0+]\n", \ | ||
205 | "5: addq 1,%2\n" \ | ||
206 | " clear.b [%0+]\n", \ | ||
207 | " .dword 4b,5b\n") | ||
208 | |||
209 | #define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
210 | __asm_copy_user_cont(to, from, ret, \ | ||
211 | COPY \ | ||
212 | "2: move.d [%1+],$acr\n" \ | ||
213 | " move.d $acr,[%0+]\n", \ | ||
214 | FIXUP \ | ||
215 | "3: addq 4,%2\n" \ | ||
216 | " jump 1b\n" \ | ||
217 | " clear.d [%0+]\n", \ | ||
218 | TENTRY \ | ||
219 | " .dword 2b,3b\n") | ||
220 | |||
221 | #define __asm_copy_from_user_4(to, from, ret) \ | ||
222 | __asm_copy_from_user_4x_cont(to, from, ret, "", "", "") | ||
223 | |||
224 | #define __asm_copy_from_user_5(to, from, ret) \ | ||
225 | __asm_copy_from_user_4x_cont(to, from, ret, \ | ||
226 | "4: move.b [%1+],$acr\n" \ | ||
227 | " move.b $acr,[%0+]\n", \ | ||
228 | "5: addq 1,%2\n" \ | ||
229 | " clear.b [%0+]\n", \ | ||
230 | " .dword 4b,5b\n") | ||
231 | |||
232 | #define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
233 | __asm_copy_from_user_4x_cont(to, from, ret, \ | ||
234 | COPY \ | ||
235 | "4: move.w [%1+],$acr\n" \ | ||
236 | " move.w $acr,[%0+]\n", \ | ||
237 | FIXUP \ | ||
238 | "5: addq 2,%2\n" \ | ||
239 | " clear.w [%0+]\n", \ | ||
240 | TENTRY \ | ||
241 | " .dword 4b,5b\n") | ||
242 | |||
243 | #define __asm_copy_from_user_6(to, from, ret) \ | ||
244 | __asm_copy_from_user_6x_cont(to, from, ret, "", "", "") | ||
245 | |||
246 | #define __asm_copy_from_user_7(to, from, ret) \ | ||
247 | __asm_copy_from_user_6x_cont(to, from, ret, \ | ||
248 | "6: move.b [%1+],$acr\n" \ | ||
249 | " move.b $acr,[%0+]\n", \ | ||
250 | "7: addq 1,%2\n" \ | ||
251 | " clear.b [%0+]\n", \ | ||
252 | " .dword 6b,7b\n") | ||
253 | |||
254 | #define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
255 | __asm_copy_from_user_4x_cont(to, from, ret, \ | ||
256 | COPY \ | ||
257 | "4: move.d [%1+],$acr\n" \ | ||
258 | " move.d $acr,[%0+]\n", \ | ||
259 | FIXUP \ | ||
260 | "5: addq 4,%2\n" \ | ||
261 | " clear.d [%0+]\n", \ | ||
262 | TENTRY \ | ||
263 | " .dword 4b,5b\n") | ||
264 | |||
265 | #define __asm_copy_from_user_8(to, from, ret) \ | ||
266 | __asm_copy_from_user_8x_cont(to, from, ret, "", "", "") | ||
267 | |||
268 | #define __asm_copy_from_user_9(to, from, ret) \ | ||
269 | __asm_copy_from_user_8x_cont(to, from, ret, \ | ||
270 | "6: move.b [%1+],$acr\n" \ | ||
271 | " move.b $acr,[%0+]\n", \ | ||
272 | "7: addq 1,%2\n" \ | ||
273 | " clear.b [%0+]\n", \ | ||
274 | " .dword 6b,7b\n") | ||
275 | |||
276 | #define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
277 | __asm_copy_from_user_8x_cont(to, from, ret, \ | ||
278 | COPY \ | ||
279 | "6: move.w [%1+],$acr\n" \ | ||
280 | " move.w $acr,[%0+]\n", \ | ||
281 | FIXUP \ | ||
282 | "7: addq 2,%2\n" \ | ||
283 | " clear.w [%0+]\n", \ | ||
284 | TENTRY \ | ||
285 | " .dword 6b,7b\n") | ||
286 | |||
287 | #define __asm_copy_from_user_10(to, from, ret) \ | ||
288 | __asm_copy_from_user_10x_cont(to, from, ret, "", "", "") | ||
289 | |||
290 | #define __asm_copy_from_user_11(to, from, ret) \ | ||
291 | __asm_copy_from_user_10x_cont(to, from, ret, \ | ||
292 | "8: move.b [%1+],$acr\n" \ | ||
293 | " move.b $acr,[%0+]\n", \ | ||
294 | "9: addq 1,%2\n" \ | ||
295 | " clear.b [%0+]\n", \ | ||
296 | " .dword 8b,9b\n") | ||
297 | |||
298 | #define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
299 | __asm_copy_from_user_8x_cont(to, from, ret, \ | ||
300 | COPY \ | ||
301 | "6: move.d [%1+],$acr\n" \ | ||
302 | " move.d $acr,[%0+]\n", \ | ||
303 | FIXUP \ | ||
304 | "7: addq 4,%2\n" \ | ||
305 | " clear.d [%0+]\n", \ | ||
306 | TENTRY \ | ||
307 | " .dword 6b,7b\n") | ||
308 | |||
309 | #define __asm_copy_from_user_12(to, from, ret) \ | ||
310 | __asm_copy_from_user_12x_cont(to, from, ret, "", "", "") | ||
311 | |||
312 | #define __asm_copy_from_user_13(to, from, ret) \ | ||
313 | __asm_copy_from_user_12x_cont(to, from, ret, \ | ||
314 | "8: move.b [%1+],$acr\n" \ | ||
315 | " move.b $acr,[%0+]\n", \ | ||
316 | "9: addq 1,%2\n" \ | ||
317 | " clear.b [%0+]\n", \ | ||
318 | " .dword 8b,9b\n") | ||
319 | |||
320 | #define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
321 | __asm_copy_from_user_12x_cont(to, from, ret, \ | ||
322 | COPY \ | ||
323 | "8: move.w [%1+],$acr\n" \ | ||
324 | " move.w $acr,[%0+]\n", \ | ||
325 | FIXUP \ | ||
326 | "9: addq 2,%2\n" \ | ||
327 | " clear.w [%0+]\n", \ | ||
328 | TENTRY \ | ||
329 | " .dword 8b,9b\n") | ||
330 | |||
331 | #define __asm_copy_from_user_14(to, from, ret) \ | ||
332 | __asm_copy_from_user_14x_cont(to, from, ret, "", "", "") | ||
333 | |||
334 | #define __asm_copy_from_user_15(to, from, ret) \ | ||
335 | __asm_copy_from_user_14x_cont(to, from, ret, \ | ||
336 | "10: move.b [%1+],$acr\n" \ | ||
337 | " move.b $acr,[%0+]\n", \ | ||
338 | "11: addq 1,%2\n" \ | ||
339 | " clear.b [%0+]\n", \ | ||
340 | " .dword 10b,11b\n") | ||
341 | |||
342 | #define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
343 | __asm_copy_from_user_12x_cont(to, from, ret, \ | ||
344 | COPY \ | ||
345 | "8: move.d [%1+],$acr\n" \ | ||
346 | " move.d $acr,[%0+]\n", \ | ||
347 | FIXUP \ | ||
348 | "9: addq 4,%2\n" \ | ||
349 | " clear.d [%0+]\n", \ | ||
350 | TENTRY \ | ||
351 | " .dword 8b,9b\n") | ||
352 | |||
353 | #define __asm_copy_from_user_16(to, from, ret) \ | ||
354 | __asm_copy_from_user_16x_cont(to, from, ret, "", "", "") | ||
355 | |||
356 | #define __asm_copy_from_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
357 | __asm_copy_from_user_16x_cont(to, from, ret, \ | ||
358 | COPY \ | ||
359 | "10: move.d [%1+],$acr\n" \ | ||
360 | " move.d $acr,[%0+]\n", \ | ||
361 | FIXUP \ | ||
362 | "11: addq 4,%2\n" \ | ||
363 | " clear.d [%0+]\n", \ | ||
364 | TENTRY \ | ||
365 | " .dword 10b,11b\n") | ||
366 | |||
367 | #define __asm_copy_from_user_20(to, from, ret) \ | ||
368 | __asm_copy_from_user_20x_cont(to, from, ret, "", "", "") | ||
369 | |||
370 | #define __asm_copy_from_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
371 | __asm_copy_from_user_20x_cont(to, from, ret, \ | ||
372 | COPY \ | ||
373 | "12: move.d [%1+],$acr\n" \ | ||
374 | " move.d $acr,[%0+]\n", \ | ||
375 | FIXUP \ | ||
376 | "13: addq 4,%2\n" \ | ||
377 | " clear.d [%0+]\n", \ | ||
378 | TENTRY \ | ||
379 | " .dword 12b,13b\n") | ||
380 | |||
381 | #define __asm_copy_from_user_24(to, from, ret) \ | ||
382 | __asm_copy_from_user_24x_cont(to, from, ret, "", "", "") | ||
383 | |||
384 | /* And now, the to-user ones. */ | ||
385 | |||
386 | #define __asm_copy_to_user_1(to, from, ret) \ | ||
387 | __asm_copy_user_cont(to, from, ret, \ | ||
388 | " move.b [%1+],$acr\n" \ | ||
389 | "2: move.b $acr,[%0+]\n", \ | ||
390 | "3: jump 1b\n" \ | ||
391 | " addq 1,%2\n", \ | ||
392 | " .dword 2b,3b\n") | ||
393 | |||
394 | #define __asm_copy_to_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
395 | __asm_copy_user_cont(to, from, ret, \ | ||
396 | COPY \ | ||
397 | " move.w [%1+],$acr\n" \ | ||
398 | "2: move.w $acr,[%0+]\n", \ | ||
399 | FIXUP \ | ||
400 | "3: jump 1b\n" \ | ||
401 | " addq 2,%2\n", \ | ||
402 | TENTRY \ | ||
403 | " .dword 2b,3b\n") | ||
404 | |||
405 | #define __asm_copy_to_user_2(to, from, ret) \ | ||
406 | __asm_copy_to_user_2x_cont(to, from, ret, "", "", "") | ||
407 | |||
408 | #define __asm_copy_to_user_3(to, from, ret) \ | ||
409 | __asm_copy_to_user_2x_cont(to, from, ret, \ | ||
410 | " move.b [%1+],$acr\n" \ | ||
411 | "4: move.b $acr,[%0+]\n", \ | ||
412 | "5: addq 1,%2\n", \ | ||
413 | " .dword 4b,5b\n") | ||
414 | |||
415 | #define __asm_copy_to_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
416 | __asm_copy_user_cont(to, from, ret, \ | ||
417 | COPY \ | ||
418 | " move.d [%1+],$acr\n" \ | ||
419 | "2: move.d $acr,[%0+]\n", \ | ||
420 | FIXUP \ | ||
421 | "3: jump 1b\n" \ | ||
422 | " addq 4,%2\n", \ | ||
423 | TENTRY \ | ||
424 | " .dword 2b,3b\n") | ||
425 | |||
426 | #define __asm_copy_to_user_4(to, from, ret) \ | ||
427 | __asm_copy_to_user_4x_cont(to, from, ret, "", "", "") | ||
428 | |||
429 | #define __asm_copy_to_user_5(to, from, ret) \ | ||
430 | __asm_copy_to_user_4x_cont(to, from, ret, \ | ||
431 | " move.b [%1+],$acr\n" \ | ||
432 | "4: move.b $acr,[%0+]\n", \ | ||
433 | "5: addq 1,%2\n", \ | ||
434 | " .dword 4b,5b\n") | ||
435 | |||
436 | #define __asm_copy_to_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
437 | __asm_copy_to_user_4x_cont(to, from, ret, \ | ||
438 | COPY \ | ||
439 | " move.w [%1+],$acr\n" \ | ||
440 | "4: move.w $acr,[%0+]\n", \ | ||
441 | FIXUP \ | ||
442 | "5: addq 2,%2\n", \ | ||
443 | TENTRY \ | ||
444 | " .dword 4b,5b\n") | ||
445 | |||
446 | #define __asm_copy_to_user_6(to, from, ret) \ | ||
447 | __asm_copy_to_user_6x_cont(to, from, ret, "", "", "") | ||
448 | |||
449 | #define __asm_copy_to_user_7(to, from, ret) \ | ||
450 | __asm_copy_to_user_6x_cont(to, from, ret, \ | ||
451 | " move.b [%1+],$acr\n" \ | ||
452 | "6: move.b $acr,[%0+]\n", \ | ||
453 | "7: addq 1,%2\n", \ | ||
454 | " .dword 6b,7b\n") | ||
455 | |||
456 | #define __asm_copy_to_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
457 | __asm_copy_to_user_4x_cont(to, from, ret, \ | ||
458 | COPY \ | ||
459 | " move.d [%1+],$acr\n" \ | ||
460 | "4: move.d $acr,[%0+]\n", \ | ||
461 | FIXUP \ | ||
462 | "5: addq 4,%2\n", \ | ||
463 | TENTRY \ | ||
464 | " .dword 4b,5b\n") | ||
465 | |||
466 | #define __asm_copy_to_user_8(to, from, ret) \ | ||
467 | __asm_copy_to_user_8x_cont(to, from, ret, "", "", "") | ||
468 | |||
469 | #define __asm_copy_to_user_9(to, from, ret) \ | ||
470 | __asm_copy_to_user_8x_cont(to, from, ret, \ | ||
471 | " move.b [%1+],$acr\n" \ | ||
472 | "6: move.b $acr,[%0+]\n", \ | ||
473 | "7: addq 1,%2\n", \ | ||
474 | " .dword 6b,7b\n") | ||
475 | |||
476 | #define __asm_copy_to_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
477 | __asm_copy_to_user_8x_cont(to, from, ret, \ | ||
478 | COPY \ | ||
479 | " move.w [%1+],$acr\n" \ | ||
480 | "6: move.w $acr,[%0+]\n", \ | ||
481 | FIXUP \ | ||
482 | "7: addq 2,%2\n", \ | ||
483 | TENTRY \ | ||
484 | " .dword 6b,7b\n") | ||
485 | |||
486 | #define __asm_copy_to_user_10(to, from, ret) \ | ||
487 | __asm_copy_to_user_10x_cont(to, from, ret, "", "", "") | ||
488 | |||
489 | #define __asm_copy_to_user_11(to, from, ret) \ | ||
490 | __asm_copy_to_user_10x_cont(to, from, ret, \ | ||
491 | " move.b [%1+],$acr\n" \ | ||
492 | "8: move.b $acr,[%0+]\n", \ | ||
493 | "9: addq 1,%2\n", \ | ||
494 | " .dword 8b,9b\n") | ||
495 | |||
496 | #define __asm_copy_to_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
497 | __asm_copy_to_user_8x_cont(to, from, ret, \ | ||
498 | COPY \ | ||
499 | " move.d [%1+],$acr\n" \ | ||
500 | "6: move.d $acr,[%0+]\n", \ | ||
501 | FIXUP \ | ||
502 | "7: addq 4,%2\n", \ | ||
503 | TENTRY \ | ||
504 | " .dword 6b,7b\n") | ||
505 | |||
506 | #define __asm_copy_to_user_12(to, from, ret) \ | ||
507 | __asm_copy_to_user_12x_cont(to, from, ret, "", "", "") | ||
508 | |||
509 | #define __asm_copy_to_user_13(to, from, ret) \ | ||
510 | __asm_copy_to_user_12x_cont(to, from, ret, \ | ||
511 | " move.b [%1+],$acr\n" \ | ||
512 | "8: move.b $acr,[%0+]\n", \ | ||
513 | "9: addq 1,%2\n", \ | ||
514 | " .dword 8b,9b\n") | ||
515 | |||
516 | #define __asm_copy_to_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
517 | __asm_copy_to_user_12x_cont(to, from, ret, \ | ||
518 | COPY \ | ||
519 | " move.w [%1+],$acr\n" \ | ||
520 | "8: move.w $acr,[%0+]\n", \ | ||
521 | FIXUP \ | ||
522 | "9: addq 2,%2\n", \ | ||
523 | TENTRY \ | ||
524 | " .dword 8b,9b\n") | ||
525 | |||
526 | #define __asm_copy_to_user_14(to, from, ret) \ | ||
527 | __asm_copy_to_user_14x_cont(to, from, ret, "", "", "") | ||
528 | |||
529 | #define __asm_copy_to_user_15(to, from, ret) \ | ||
530 | __asm_copy_to_user_14x_cont(to, from, ret, \ | ||
531 | " move.b [%1+],$acr\n" \ | ||
532 | "10: move.b $acr,[%0+]\n", \ | ||
533 | "11: addq 1,%2\n", \ | ||
534 | " .dword 10b,11b\n") | ||
535 | |||
536 | #define __asm_copy_to_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
537 | __asm_copy_to_user_12x_cont(to, from, ret, \ | ||
538 | COPY \ | ||
539 | " move.d [%1+],$acr\n" \ | ||
540 | "8: move.d $acr,[%0+]\n", \ | ||
541 | FIXUP \ | ||
542 | "9: addq 4,%2\n", \ | ||
543 | TENTRY \ | ||
544 | " .dword 8b,9b\n") | ||
545 | |||
546 | #define __asm_copy_to_user_16(to, from, ret) \ | ||
547 | __asm_copy_to_user_16x_cont(to, from, ret, "", "", "") | ||
548 | |||
549 | #define __asm_copy_to_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
550 | __asm_copy_to_user_16x_cont(to, from, ret, \ | ||
551 | COPY \ | ||
552 | " move.d [%1+],$acr\n" \ | ||
553 | "10: move.d $acr,[%0+]\n", \ | ||
554 | FIXUP \ | ||
555 | "11: addq 4,%2\n", \ | ||
556 | TENTRY \ | ||
557 | " .dword 10b,11b\n") | ||
558 | |||
559 | #define __asm_copy_to_user_20(to, from, ret) \ | ||
560 | __asm_copy_to_user_20x_cont(to, from, ret, "", "", "") | ||
561 | |||
562 | #define __asm_copy_to_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \ | ||
563 | __asm_copy_to_user_20x_cont(to, from, ret, \ | ||
564 | COPY \ | ||
565 | " move.d [%1+],$acr\n" \ | ||
566 | "12: move.d $acr,[%0+]\n", \ | ||
567 | FIXUP \ | ||
568 | "13: addq 4,%2\n", \ | ||
569 | TENTRY \ | ||
570 | " .dword 12b,13b\n") | ||
571 | |||
572 | #define __asm_copy_to_user_24(to, from, ret) \ | ||
573 | __asm_copy_to_user_24x_cont(to, from, ret, "", "", "") | ||
574 | |||
575 | /* Define a few clearing asms with exception handlers. */ | ||
576 | |||
577 | /* This frame-asm is like the __asm_copy_user_cont one, but has one less | ||
578 | input. */ | ||
579 | |||
580 | #define __asm_clear(to, ret, CLEAR, FIXUP, TENTRY) \ | ||
581 | __asm__ __volatile__ ( \ | ||
582 | CLEAR \ | ||
583 | "1:\n" \ | ||
584 | " .section .fixup,\"ax\"\n" \ | ||
585 | FIXUP \ | ||
586 | " .previous\n" \ | ||
587 | " .section __ex_table,\"a\"\n" \ | ||
588 | TENTRY \ | ||
589 | " .previous" \ | ||
590 | : "=b" (to), "=r" (ret) \ | ||
591 | : "0" (to), "1" (ret) \ | ||
592 | : "memory") | ||
593 | |||
594 | #define __asm_clear_1(to, ret) \ | ||
595 | __asm_clear(to, ret, \ | ||
596 | "2: clear.b [%0+]\n", \ | ||
597 | "3: jump 1b\n" \ | ||
598 | " addq 1,%1\n", \ | ||
599 | " .dword 2b,3b\n") | ||
600 | |||
601 | #define __asm_clear_2(to, ret) \ | ||
602 | __asm_clear(to, ret, \ | ||
603 | "2: clear.w [%0+]\n", \ | ||
604 | "3: jump 1b\n" \ | ||
605 | " addq 2,%1\n", \ | ||
606 | " .dword 2b,3b\n") | ||
607 | |||
608 | #define __asm_clear_3(to, ret) \ | ||
609 | __asm_clear(to, ret, \ | ||
610 | "2: clear.w [%0+]\n" \ | ||
611 | "3: clear.b [%0+]\n", \ | ||
612 | "4: addq 2,%1\n" \ | ||
613 | "5: jump 1b\n" \ | ||
614 | " addq 1,%1\n", \ | ||
615 | " .dword 2b,4b\n" \ | ||
616 | " .dword 3b,5b\n") | ||
617 | |||
618 | #define __asm_clear_4x_cont(to, ret, CLEAR, FIXUP, TENTRY) \ | ||
619 | __asm_clear(to, ret, \ | ||
620 | CLEAR \ | ||
621 | "2: clear.d [%0+]\n", \ | ||
622 | FIXUP \ | ||
623 | "3: jump 1b\n" \ | ||
624 | " addq 4,%1\n", \ | ||
625 | TENTRY \ | ||
626 | " .dword 2b,3b\n") | ||
627 | |||
628 | #define __asm_clear_4(to, ret) \ | ||
629 | __asm_clear_4x_cont(to, ret, "", "", "") | ||
630 | |||
631 | #define __asm_clear_8x_cont(to, ret, CLEAR, FIXUP, TENTRY) \ | ||
632 | __asm_clear_4x_cont(to, ret, \ | ||
633 | CLEAR \ | ||
634 | "4: clear.d [%0+]\n", \ | ||
635 | FIXUP \ | ||
636 | "5: addq 4,%1\n", \ | ||
637 | TENTRY \ | ||
638 | " .dword 4b,5b\n") | ||
639 | |||
640 | #define __asm_clear_8(to, ret) \ | ||
641 | __asm_clear_8x_cont(to, ret, "", "", "") | ||
642 | |||
643 | #define __asm_clear_12x_cont(to, ret, CLEAR, FIXUP, TENTRY) \ | ||
644 | __asm_clear_8x_cont(to, ret, \ | ||
645 | CLEAR \ | ||
646 | "6: clear.d [%0+]\n", \ | ||
647 | FIXUP \ | ||
648 | "7: addq 4,%1\n", \ | ||
649 | TENTRY \ | ||
650 | " .dword 6b,7b\n") | ||
651 | |||
652 | #define __asm_clear_12(to, ret) \ | ||
653 | __asm_clear_12x_cont(to, ret, "", "", "") | ||
654 | |||
655 | #define __asm_clear_16x_cont(to, ret, CLEAR, FIXUP, TENTRY) \ | ||
656 | __asm_clear_12x_cont(to, ret, \ | ||
657 | CLEAR \ | ||
658 | "8: clear.d [%0+]\n", \ | ||
659 | FIXUP \ | ||
660 | "9: addq 4,%1\n", \ | ||
661 | TENTRY \ | ||
662 | " .dword 8b,9b\n") | ||
663 | |||
664 | #define __asm_clear_16(to, ret) \ | ||
665 | __asm_clear_16x_cont(to, ret, "", "", "") | ||
666 | |||
667 | #define __asm_clear_20x_cont(to, ret, CLEAR, FIXUP, TENTRY) \ | ||
668 | __asm_clear_16x_cont(to, ret, \ | ||
669 | CLEAR \ | ||
670 | "10: clear.d [%0+]\n", \ | ||
671 | FIXUP \ | ||
672 | "11: addq 4,%1\n", \ | ||
673 | TENTRY \ | ||
674 | " .dword 10b,11b\n") | ||
675 | |||
676 | #define __asm_clear_20(to, ret) \ | ||
677 | __asm_clear_20x_cont(to, ret, "", "", "") | ||
678 | |||
679 | #define __asm_clear_24x_cont(to, ret, CLEAR, FIXUP, TENTRY) \ | ||
680 | __asm_clear_20x_cont(to, ret, \ | ||
681 | CLEAR \ | ||
682 | "12: clear.d [%0+]\n", \ | ||
683 | FIXUP \ | ||
684 | "13: addq 4,%1\n", \ | ||
685 | TENTRY \ | ||
686 | " .dword 12b,13b\n") | ||
687 | |||
688 | #define __asm_clear_24(to, ret) \ | ||
689 | __asm_clear_24x_cont(to, ret, "", "", "") | ||
690 | |||
691 | /* | ||
692 | * Return the size of a string (including the ending 0) | ||
693 | * | ||
694 | * Return length of string in userspace including terminating 0 | ||
695 | * or 0 for error. Return a value greater than N if too long. | ||
696 | */ | ||
697 | |||
698 | extern inline long | ||
699 | strnlen_user(const char *s, long n) | ||
700 | { | ||
701 | long res, tmp1; | ||
702 | |||
703 | if (!access_ok(VERIFY_READ, s, 0)) | ||
704 | return 0; | ||
705 | |||
706 | /* | ||
707 | * This code is deduced from: | ||
708 | * | ||
709 | * tmp1 = n; | ||
710 | * while (tmp1-- > 0 && *s++) | ||
711 | * ; | ||
712 | * | ||
713 | * res = n - tmp1; | ||
714 | * | ||
715 | * (with tweaks). | ||
716 | */ | ||
717 | |||
718 | __asm__ __volatile__ ( | ||
719 | " move.d %1,$acr\n" | ||
720 | " cmpq 0,$acr\n" | ||
721 | "0:\n" | ||
722 | " ble 1f\n" | ||
723 | " subq 1,$acr\n" | ||
724 | |||
725 | "4: test.b [%0+]\n" | ||
726 | " bne 0b\n" | ||
727 | " cmpq 0,$acr\n" | ||
728 | "1:\n" | ||
729 | " move.d %1,%0\n" | ||
730 | " sub.d $acr,%0\n" | ||
731 | "2:\n" | ||
732 | " .section .fixup,\"ax\"\n" | ||
733 | |||
734 | "3: jump 2b\n" | ||
735 | " clear.d %0\n" | ||
736 | |||
737 | " .previous\n" | ||
738 | " .section __ex_table,\"a\"\n" | ||
739 | " .dword 4b,3b\n" | ||
740 | " .previous\n" | ||
741 | : "=r" (res), "=r" (tmp1) | ||
742 | : "0" (s), "1" (n) | ||
743 | : "acr"); | ||
744 | |||
745 | return res; | ||
746 | } | ||
747 | |||
748 | #endif | ||