blob: 2ffd87b0a7694894547e5672655339c3062af058 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001#ifndef __M68K_UACCESS_H
2#define __M68K_UACCESS_H
3
4/*
5 * User space memory access functions
6 */
7#include <linux/errno.h>
8#include <linux/sched.h>
9#include <asm/segment.h>
10
11#define VERIFY_READ 0
12#define VERIFY_WRITE 1
13
14/* We let the MMU do all checking */
15#define access_ok(type,addr,size) 1
16
Linus Torvalds1da177e2005-04-16 15:20:36 -070017/*
18 * The exception table consists of pairs of addresses: the first is the
19 * address of an instruction that is allowed to fault, and the second is
20 * the address at which the program should continue. No registers are
21 * modified, so it is entirely up to the continuation code to figure out
22 * what to do.
23 *
24 * All the routines below use bits of fixup code that are out of line
25 * with the main instruction path. This means when everything is well,
26 * we don't even have to jump over them. Further, they do not intrude
27 * on our cache or tlb entries.
28 */
29
30struct exception_table_entry
31{
32 unsigned long insn, fixup;
33};
34
35
36/*
37 * These are the main single-value transfer routines. They automatically
38 * use the right size if we just have the right pointer type.
39 */
40
41#define put_user(x, ptr) \
42({ \
43 int __pu_err; \
44 typeof(*(ptr)) __pu_val = (x); \
Al Viro11c40f82006-01-12 01:06:24 -080045 __chk_user_ptr(ptr); \
Linus Torvalds1da177e2005-04-16 15:20:36 -070046 switch (sizeof (*(ptr))) { \
47 case 1: \
48 __put_user_asm(__pu_err, __pu_val, ptr, b); \
49 break; \
50 case 2: \
51 __put_user_asm(__pu_err, __pu_val, ptr, w); \
52 break; \
53 case 4: \
54 __put_user_asm(__pu_err, __pu_val, ptr, l); \
55 break; \
56 case 8: \
57 __pu_err = __constant_copy_to_user(ptr, &__pu_val, 8); \
58 break; \
59 default: \
60 __pu_err = __put_user_bad(); \
61 break; \
62 } \
63 __pu_err; \
64})
65#define __put_user(x, ptr) put_user(x, ptr)
66
67extern int __put_user_bad(void);
68
69/*
70 * Tell gcc we read from memory instead of writing: this is because
71 * we do not write to any memory gcc knows about, so there are no
72 * aliasing issues.
73 */
74#define __put_user_asm(err,x,ptr,bwl) \
75__asm__ __volatile__ \
76 ("21:moves" #bwl " %2,%1\n" \
77 "1:\n" \
78 ".section .fixup,\"ax\"\n" \
79 " .even\n" \
80 "2: movel %3,%0\n" \
81 " jra 1b\n" \
82 ".previous\n" \
83 ".section __ex_table,\"a\"\n" \
84 " .align 4\n" \
85 " .long 21b,2b\n" \
86 " .long 1b,2b\n" \
87 ".previous" \
88 : "=d"(err) \
89 : "m"(*(ptr)), "r"(x), "i"(-EFAULT), "0"(0))
90
91#define get_user(x, ptr) \
92({ \
93 int __gu_err; \
94 typeof(*(ptr)) __gu_val; \
Al Viro11c40f82006-01-12 01:06:24 -080095 __chk_user_ptr(ptr); \
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 switch (sizeof(*(ptr))) { \
97 case 1: \
98 __get_user_asm(__gu_err, __gu_val, ptr, b, "=d"); \
99 break; \
100 case 2: \
101 __get_user_asm(__gu_err, __gu_val, ptr, w, "=r"); \
102 break; \
103 case 4: \
104 __get_user_asm(__gu_err, __gu_val, ptr, l, "=r"); \
105 break; \
106 case 8: \
107 __gu_err = __constant_copy_from_user(&__gu_val, ptr, 8); \
108 break; \
109 default: \
Al Viro11c40f82006-01-12 01:06:24 -0800110 __gu_val = (typeof(*(ptr)))0; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 __gu_err = __get_user_bad(); \
112 break; \
113 } \
114 (x) = __gu_val; \
115 __gu_err; \
116})
117#define __get_user(x, ptr) get_user(x, ptr)
118
119extern int __get_user_bad(void);
120
121#define __get_user_asm(err,x,ptr,bwl,reg) \
122__asm__ __volatile__ \
123 ("1: moves" #bwl " %2,%1\n" \
124 "2:\n" \
125 ".section .fixup,\"ax\"\n" \
126 " .even\n" \
127 "3: movel %3,%0\n" \
128 " sub" #bwl " %1,%1\n" \
129 " jra 2b\n" \
130 ".previous\n" \
131 ".section __ex_table,\"a\"\n" \
132 " .align 4\n" \
133 " .long 1b,3b\n" \
134 ".previous" \
135 : "=d"(err), reg(x) \
136 : "m"(*(ptr)), "i" (-EFAULT), "0"(0))
137
138static inline unsigned long
Al Viro11c40f82006-01-12 01:06:24 -0800139__generic_copy_from_user(void *to, const void __user *from, unsigned long n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140{
141 unsigned long tmp;
142 __asm__ __volatile__
143 (" tstl %2\n"
144 " jeq 2f\n"
145 "1: movesl (%1)+,%3\n"
146 " movel %3,(%0)+\n"
147 " subql #1,%2\n"
148 " jne 1b\n"
149 "2: movel %4,%2\n"
150 " bclr #1,%2\n"
151 " jeq 4f\n"
152 "3: movesw (%1)+,%3\n"
153 " movew %3,(%0)+\n"
154 "4: bclr #0,%2\n"
155 " jeq 6f\n"
156 "5: movesb (%1)+,%3\n"
157 " moveb %3,(%0)+\n"
158 "6:\n"
159 ".section .fixup,\"ax\"\n"
160 " .even\n"
161 "7: movel %2,%%d0\n"
162 "71:clrl (%0)+\n"
163 " subql #1,%%d0\n"
164 " jne 71b\n"
165 " lsll #2,%2\n"
166 " addl %4,%2\n"
167 " btst #1,%4\n"
168 " jne 81f\n"
169 " btst #0,%4\n"
170 " jne 91f\n"
171 " jra 6b\n"
172 "8: addql #2,%2\n"
173 "81:clrw (%0)+\n"
174 " btst #0,%4\n"
175 " jne 91f\n"
176 " jra 6b\n"
177 "9: addql #1,%2\n"
178 "91:clrb (%0)+\n"
179 " jra 6b\n"
180 ".previous\n"
181 ".section __ex_table,\"a\"\n"
182 " .align 4\n"
183 " .long 1b,7b\n"
184 " .long 3b,8b\n"
185 " .long 5b,9b\n"
186 ".previous"
187 : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
188 : "d"(n & 3), "0"(to), "1"(from), "2"(n/4)
189 : "d0", "memory");
190 return n;
191}
192
193static inline unsigned long
Al Viro11c40f82006-01-12 01:06:24 -0800194__generic_copy_to_user(void __user *to, const void *from, unsigned long n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195{
196 unsigned long tmp;
197 __asm__ __volatile__
198 (" tstl %2\n"
199 " jeq 3f\n"
200 "1: movel (%1)+,%3\n"
201 "22:movesl %3,(%0)+\n"
202 "2: subql #1,%2\n"
203 " jne 1b\n"
204 "3: movel %4,%2\n"
205 " bclr #1,%2\n"
206 " jeq 4f\n"
207 " movew (%1)+,%3\n"
208 "24:movesw %3,(%0)+\n"
209 "4: bclr #0,%2\n"
210 " jeq 5f\n"
211 " moveb (%1)+,%3\n"
212 "25:movesb %3,(%0)+\n"
213 "5:\n"
214 ".section .fixup,\"ax\"\n"
215 " .even\n"
216 "60:addql #1,%2\n"
217 "6: lsll #2,%2\n"
218 " addl %4,%2\n"
219 " jra 5b\n"
220 "7: addql #2,%2\n"
221 " jra 5b\n"
222 "8: addql #1,%2\n"
223 " jra 5b\n"
224 ".previous\n"
225 ".section __ex_table,\"a\"\n"
226 " .align 4\n"
227 " .long 1b,60b\n"
228 " .long 22b,6b\n"
229 " .long 2b,6b\n"
230 " .long 24b,7b\n"
231 " .long 3b,60b\n"
232 " .long 4b,7b\n"
233 " .long 25b,8b\n"
234 " .long 5b,8b\n"
235 ".previous"
236 : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
237 : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4)
238 : "memory");
239 return n;
240}
241
242#define __copy_from_user_big(to, from, n, fixup, copy) \
243 __asm__ __volatile__ \
244 ("10: movesl (%1)+,%%d0\n" \
245 " movel %%d0,(%0)+\n" \
246 " subql #1,%2\n" \
247 " jne 10b\n" \
248 ".section .fixup,\"ax\"\n" \
249 " .even\n" \
250 "11: movel %2,%%d0\n" \
251 "13: clrl (%0)+\n" \
252 " subql #1,%%d0\n" \
253 " jne 13b\n" \
254 " lsll #2,%2\n" \
255 fixup "\n" \
256 " jra 12f\n" \
257 ".previous\n" \
258 ".section __ex_table,\"a\"\n" \
259 " .align 4\n" \
260 " .long 10b,11b\n" \
261 ".previous\n" \
262 copy "\n" \
263 "12:" \
264 : "=a"(to), "=a"(from), "=d"(n) \
265 : "0"(to), "1"(from), "2"(n/4) \
266 : "d0", "memory")
267
268static inline unsigned long
Al Viro11c40f82006-01-12 01:06:24 -0800269__constant_copy_from_user(void *to, const void __user *from, unsigned long n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270{
271 switch (n) {
272 case 0:
273 break;
274 case 1:
275 __asm__ __volatile__
276 ("1: movesb (%1)+,%%d0\n"
277 " moveb %%d0,(%0)+\n"
278 "2:\n"
279 ".section .fixup,\"ax\"\n"
280 " .even\n"
281 "3: addql #1,%2\n"
282 " clrb (%0)+\n"
283 " jra 2b\n"
284 ".previous\n"
285 ".section __ex_table,\"a\"\n"
286 " .align 4\n"
287 " .long 1b,3b\n"
288 ".previous"
289 : "=a"(to), "=a"(from), "=d"(n)
290 : "0"(to), "1"(from), "2"(0)
291 : "d0", "memory");
292 break;
293 case 2:
294 __asm__ __volatile__
295 ("1: movesw (%1)+,%%d0\n"
296 " movew %%d0,(%0)+\n"
297 "2:\n"
298 ".section .fixup,\"ax\"\n"
299 " .even\n"
300 "3: addql #2,%2\n"
301 " clrw (%0)+\n"
302 " jra 2b\n"
303 ".previous\n"
304 ".section __ex_table,\"a\"\n"
305 " .align 4\n"
306 " .long 1b,3b\n"
307 ".previous"
308 : "=a"(to), "=a"(from), "=d"(n)
309 : "0"(to), "1"(from), "2"(0)
310 : "d0", "memory");
311 break;
312 case 3:
313 __asm__ __volatile__
314 ("1: movesw (%1)+,%%d0\n"
315 " movew %%d0,(%0)+\n"
316 "2: movesb (%1)+,%%d0\n"
317 " moveb %%d0,(%0)+\n"
318 "3:"
319 ".section .fixup,\"ax\"\n"
320 " .even\n"
321 "4: addql #2,%2\n"
322 " clrw (%0)+\n"
323 "5: addql #1,%2\n"
324 " clrb (%0)+\n"
325 " jra 3b\n"
326 ".previous\n"
327 ".section __ex_table,\"a\"\n"
328 " .align 4\n"
329 " .long 1b,4b\n"
330 " .long 2b,5b\n"
331 ".previous"
332 : "=a"(to), "=a"(from), "=d"(n)
333 : "0"(to), "1"(from), "2"(0)
334 : "d0", "memory");
335 break;
336 case 4:
337 __asm__ __volatile__
338 ("1: movesl (%1)+,%%d0\n"
339 " movel %%d0,(%0)+\n"
340 "2:"
341 ".section .fixup,\"ax\"\n"
342 " .even\n"
343 "3: addql #4,%2\n"
344 " clrl (%0)+\n"
345 " jra 2b\n"
346 ".previous\n"
347 ".section __ex_table,\"a\"\n"
348 " .align 4\n"
349 " .long 1b,3b\n"
350 ".previous"
351 : "=a"(to), "=a"(from), "=d"(n)
352 : "0"(to), "1"(from), "2"(0)
353 : "d0", "memory");
354 break;
355 case 8:
356 __asm__ __volatile__
357 ("1: movesl (%1)+,%%d0\n"
358 " movel %%d0,(%0)+\n"
359 "2: movesl (%1)+,%%d0\n"
360 " movel %%d0,(%0)+\n"
361 "3:"
362 ".section .fixup,\"ax\"\n"
363 " .even\n"
364 "4: addql #4,%2\n"
365 " clrl (%0)+\n"
366 "5: addql #4,%2\n"
367 " clrl (%0)+\n"
368 " jra 3b\n"
369 ".previous\n"
370 ".section __ex_table,\"a\"\n"
371 " .align 4\n"
372 " .long 1b,4b\n"
373 " .long 2b,5b\n"
374 ".previous"
375 : "=a"(to), "=a"(from), "=d"(n)
376 : "0"(to), "1"(from), "2"(0)
377 : "d0", "memory");
378 break;
379 case 12:
380 __asm__ __volatile__
381 ("1: movesl (%1)+,%%d0\n"
382 " movel %%d0,(%0)+\n"
383 "2: movesl (%1)+,%%d0\n"
384 " movel %%d0,(%0)+\n"
385 "3: movesl (%1)+,%%d0\n"
386 " movel %%d0,(%0)+\n"
387 "4:"
388 ".section .fixup,\"ax\"\n"
389 " .even\n"
390 "5: addql #4,%2\n"
391 " clrl (%0)+\n"
392 "6: addql #4,%2\n"
393 " clrl (%0)+\n"
394 "7: addql #4,%2\n"
395 " clrl (%0)+\n"
396 " jra 4b\n"
397 ".previous\n"
398 ".section __ex_table,\"a\"\n"
399 " .align 4\n"
400 " .long 1b,5b\n"
401 " .long 2b,6b\n"
402 " .long 3b,7b\n"
403 ".previous"
404 : "=a"(to), "=a"(from), "=d"(n)
405 : "0"(to), "1"(from), "2"(0)
406 : "d0", "memory");
407 break;
408 case 16:
409 __asm__ __volatile__
410 ("1: movesl (%1)+,%%d0\n"
411 " movel %%d0,(%0)+\n"
412 "2: movesl (%1)+,%%d0\n"
413 " movel %%d0,(%0)+\n"
414 "3: movesl (%1)+,%%d0\n"
415 " movel %%d0,(%0)+\n"
416 "4: movesl (%1)+,%%d0\n"
417 " movel %%d0,(%0)+\n"
418 "5:"
419 ".section .fixup,\"ax\"\n"
420 " .even\n"
421 "6: addql #4,%2\n"
422 " clrl (%0)+\n"
423 "7: addql #4,%2\n"
424 " clrl (%0)+\n"
425 "8: addql #4,%2\n"
426 " clrl (%0)+\n"
427 "9: addql #4,%2\n"
428 " clrl (%0)+\n"
429 " jra 5b\n"
430 ".previous\n"
431 ".section __ex_table,\"a\"\n"
432 " .align 4\n"
433 " .long 1b,6b\n"
434 " .long 2b,7b\n"
435 " .long 3b,8b\n"
436 " .long 4b,9b\n"
437 ".previous"
438 : "=a"(to), "=a"(from), "=d"(n)
439 : "0"(to), "1"(from), "2"(0)
440 : "d0", "memory");
441 break;
442 default:
443 switch (n & 3) {
444 case 0:
445 __copy_from_user_big(to, from, n, "", "");
446 break;
447 case 1:
448 __copy_from_user_big(to, from, n,
449 /* fixup */
450 "1: addql #1,%2\n"
451 " clrb (%0)+",
452 /* copy */
453 "2: movesb (%1)+,%%d0\n"
454 " moveb %%d0,(%0)+\n"
455 ".section __ex_table,\"a\"\n"
456 " .long 2b,1b\n"
457 ".previous");
458 break;
459 case 2:
460 __copy_from_user_big(to, from, n,
461 /* fixup */
462 "1: addql #2,%2\n"
463 " clrw (%0)+",
464 /* copy */
465 "2: movesw (%1)+,%%d0\n"
466 " movew %%d0,(%0)+\n"
467 ".section __ex_table,\"a\"\n"
468 " .long 2b,1b\n"
469 ".previous");
470 break;
471 case 3:
472 __copy_from_user_big(to, from, n,
473 /* fixup */
474 "1: addql #2,%2\n"
475 " clrw (%0)+\n"
476 "2: addql #1,%2\n"
477 " clrb (%0)+",
478 /* copy */
479 "3: movesw (%1)+,%%d0\n"
480 " movew %%d0,(%0)+\n"
481 "4: movesb (%1)+,%%d0\n"
482 " moveb %%d0,(%0)+\n"
483 ".section __ex_table,\"a\"\n"
484 " .long 3b,1b\n"
485 " .long 4b,2b\n"
486 ".previous");
487 break;
488 }
489 break;
490 }
491 return n;
492}
493
494#define __copy_to_user_big(to, from, n, fixup, copy) \
495 __asm__ __volatile__ \
496 ("10: movel (%1)+,%%d0\n" \
497 "31: movesl %%d0,(%0)+\n" \
498 "11: subql #1,%2\n" \
499 " jne 10b\n" \
500 "41:\n" \
501 ".section .fixup,\"ax\"\n" \
502 " .even\n" \
503 "22: addql #1,%2\n" \
504 "12: lsll #2,%2\n" \
505 fixup "\n" \
506 " jra 13f\n" \
507 ".previous\n" \
508 ".section __ex_table,\"a\"\n" \
509 " .align 4\n" \
510 " .long 10b,22b\n" \
511 " .long 31b,12b\n" \
512 " .long 11b,12b\n" \
513 " .long 41b,22b\n" \
514 ".previous\n" \
515 copy "\n" \
516 "13:" \
517 : "=a"(to), "=a"(from), "=d"(n) \
518 : "0"(to), "1"(from), "2"(n/4) \
519 : "d0", "memory")
520
521#define __copy_to_user_inatomic __copy_to_user
522#define __copy_from_user_inatomic __copy_from_user
523
524static inline unsigned long
Al Viro11c40f82006-01-12 01:06:24 -0800525__constant_copy_to_user(void __user *to, const void *from, unsigned long n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526{
527 switch (n) {
528 case 0:
529 break;
530 case 1:
531 __asm__ __volatile__
532 (" moveb (%1)+,%%d0\n"
533 "21:movesb %%d0,(%0)+\n"
534 "1:\n"
535 ".section .fixup,\"ax\"\n"
536 " .even\n"
537 "2: addql #1,%2\n"
538 " jra 1b\n"
539 ".previous\n"
540 ".section __ex_table,\"a\"\n"
541 " .align 4\n "
542 " .long 21b,2b\n"
543 " .long 1b,2b\n"
544 ".previous"
545 : "=a"(to), "=a"(from), "=d"(n)
546 : "0"(to), "1"(from), "2"(0)
547 : "d0", "memory");
548 break;
549 case 2:
550 __asm__ __volatile__
551 (" movew (%1)+,%%d0\n"
552 "21:movesw %%d0,(%0)+\n"
553 "1:\n"
554 ".section .fixup,\"ax\"\n"
555 " .even\n"
556 "2: addql #2,%2\n"
557 " jra 1b\n"
558 ".previous\n"
559 ".section __ex_table,\"a\"\n"
560 " .align 4\n"
561 " .long 21b,2b\n"
562 " .long 1b,2b\n"
563 ".previous"
564 : "=a"(to), "=a"(from), "=d"(n)
565 : "0"(to), "1"(from), "2"(0)
566 : "d0", "memory");
567 break;
568 case 3:
569 __asm__ __volatile__
570 (" movew (%1)+,%%d0\n"
571 "21:movesw %%d0,(%0)+\n"
572 "1: moveb (%1)+,%%d0\n"
573 "22:movesb %%d0,(%0)+\n"
574 "2:\n"
575 ".section .fixup,\"ax\"\n"
576 " .even\n"
577 "3: addql #2,%2\n"
578 "4: addql #1,%2\n"
579 " jra 2b\n"
580 ".previous\n"
581 ".section __ex_table,\"a\"\n"
582 " .align 4\n"
583 " .long 21b,3b\n"
584 " .long 1b,3b\n"
585 " .long 22b,4b\n"
586 " .long 2b,4b\n"
587 ".previous"
588 : "=a"(to), "=a"(from), "=d"(n)
589 : "0"(to), "1"(from), "2"(0)
590 : "d0", "memory");
591 break;
592 case 4:
593 __asm__ __volatile__
594 (" movel (%1)+,%%d0\n"
595 "21:movesl %%d0,(%0)+\n"
596 "1:\n"
597 ".section .fixup,\"ax\"\n"
598 " .even\n"
599 "2: addql #4,%2\n"
600 " jra 1b\n"
601 ".previous\n"
602 ".section __ex_table,\"a\"\n"
603 " .align 4\n"
604 " .long 21b,2b\n"
605 " .long 1b,2b\n"
606 ".previous"
607 : "=a"(to), "=a"(from), "=d"(n)
608 : "0"(to), "1"(from), "2"(0)
609 : "d0", "memory");
610 break;
611 case 8:
612 __asm__ __volatile__
613 (" movel (%1)+,%%d0\n"
614 "21:movesl %%d0,(%0)+\n"
615 "1: movel (%1)+,%%d0\n"
616 "22:movesl %%d0,(%0)+\n"
617 "2:\n"
618 ".section .fixup,\"ax\"\n"
619 " .even\n"
620 "3: addql #4,%2\n"
621 "4: addql #4,%2\n"
622 " jra 2b\n"
623 ".previous\n"
624 ".section __ex_table,\"a\"\n"
625 " .align 4\n"
626 " .long 21b,3b\n"
627 " .long 1b,3b\n"
628 " .long 22b,4b\n"
629 " .long 2b,4b\n"
630 ".previous"
631 : "=a"(to), "=a"(from), "=d"(n)
632 : "0"(to), "1"(from), "2"(0)
633 : "d0", "memory");
634 break;
635 case 12:
636 __asm__ __volatile__
637 (" movel (%1)+,%%d0\n"
638 "21:movesl %%d0,(%0)+\n"
639 "1: movel (%1)+,%%d0\n"
640 "22:movesl %%d0,(%0)+\n"
641 "2: movel (%1)+,%%d0\n"
642 "23:movesl %%d0,(%0)+\n"
643 "3:\n"
644 ".section .fixup,\"ax\"\n"
645 " .even\n"
646 "4: addql #4,%2\n"
647 "5: addql #4,%2\n"
648 "6: addql #4,%2\n"
649 " jra 3b\n"
650 ".previous\n"
651 ".section __ex_table,\"a\"\n"
652 " .align 4\n"
653 " .long 21b,4b\n"
654 " .long 1b,4b\n"
655 " .long 22b,5b\n"
656 " .long 2b,5b\n"
657 " .long 23b,6b\n"
658 " .long 3b,6b\n"
659 ".previous"
660 : "=a"(to), "=a"(from), "=d"(n)
661 : "0"(to), "1"(from), "2"(0)
662 : "d0", "memory");
663 break;
664 case 16:
665 __asm__ __volatile__
666 (" movel (%1)+,%%d0\n"
667 "21:movesl %%d0,(%0)+\n"
668 "1: movel (%1)+,%%d0\n"
669 "22:movesl %%d0,(%0)+\n"
670 "2: movel (%1)+,%%d0\n"
671 "23:movesl %%d0,(%0)+\n"
672 "3: movel (%1)+,%%d0\n"
673 "24:movesl %%d0,(%0)+\n"
674 "4:"
675 ".section .fixup,\"ax\"\n"
676 " .even\n"
677 "5: addql #4,%2\n"
678 "6: addql #4,%2\n"
679 "7: addql #4,%2\n"
680 "8: addql #4,%2\n"
681 " jra 4b\n"
682 ".previous\n"
683 ".section __ex_table,\"a\"\n"
684 " .align 4\n"
685 " .long 21b,5b\n"
686 " .long 1b,5b\n"
687 " .long 22b,6b\n"
688 " .long 2b,6b\n"
689 " .long 23b,7b\n"
690 " .long 3b,7b\n"
691 " .long 24b,8b\n"
692 " .long 4b,8b\n"
693 ".previous"
694 : "=a"(to), "=a"(from), "=d"(n)
695 : "0"(to), "1"(from), "2"(0)
696 : "d0", "memory");
697 break;
698 default:
699 switch (n & 3) {
700 case 0:
701 __copy_to_user_big(to, from, n, "", "");
702 break;
703 case 1:
704 __copy_to_user_big(to, from, n,
705 /* fixup */
706 "1: addql #1,%2",
707 /* copy */
708 " moveb (%1)+,%%d0\n"
709 "22:movesb %%d0,(%0)+\n"
710 "2:"
711 ".section __ex_table,\"a\"\n"
712 " .long 22b,1b\n"
713 " .long 2b,1b\n"
714 ".previous");
715 break;
716 case 2:
717 __copy_to_user_big(to, from, n,
718 /* fixup */
719 "1: addql #2,%2",
720 /* copy */
721 " movew (%1)+,%%d0\n"
722 "22:movesw %%d0,(%0)+\n"
723 "2:"
724 ".section __ex_table,\"a\"\n"
725 " .long 22b,1b\n"
726 " .long 2b,1b\n"
727 ".previous");
728 break;
729 case 3:
730 __copy_to_user_big(to, from, n,
731 /* fixup */
732 "1: addql #2,%2\n"
733 "2: addql #1,%2",
734 /* copy */
735 " movew (%1)+,%%d0\n"
736 "23:movesw %%d0,(%0)+\n"
737 "3: moveb (%1)+,%%d0\n"
738 "24:movesb %%d0,(%0)+\n"
739 "4:"
740 ".section __ex_table,\"a\"\n"
741 " .long 23b,1b\n"
742 " .long 3b,1b\n"
743 " .long 24b,2b\n"
744 " .long 4b,2b\n"
745 ".previous");
746 break;
747 }
748 break;
749 }
750 return n;
751}
752
753#define copy_from_user(to, from, n) \
754(__builtin_constant_p(n) ? \
755 __constant_copy_from_user(to, from, n) : \
756 __generic_copy_from_user(to, from, n))
757
758#define copy_to_user(to, from, n) \
759(__builtin_constant_p(n) ? \
760 __constant_copy_to_user(to, from, n) : \
761 __generic_copy_to_user(to, from, n))
762
763#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
764#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
765
766/*
767 * Copy a null terminated string from userspace.
768 */
769
770static inline long
Al Viro11c40f82006-01-12 01:06:24 -0800771strncpy_from_user(char *dst, const char __user *src, long count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772{
773 long res;
774 if (count == 0) return count;
775 __asm__ __volatile__
776 ("1: movesb (%2)+,%%d0\n"
777 "12:moveb %%d0,(%1)+\n"
778 " jeq 2f\n"
779 " subql #1,%3\n"
780 " jne 1b\n"
781 "2: subl %3,%0\n"
782 "3:\n"
783 ".section .fixup,\"ax\"\n"
784 " .even\n"
785 "4: movel %4,%0\n"
786 " jra 3b\n"
787 ".previous\n"
788 ".section __ex_table,\"a\"\n"
789 " .align 4\n"
790 " .long 1b,4b\n"
791 " .long 12b,4b\n"
792 ".previous"
793 : "=d"(res), "=a"(dst), "=a"(src), "=d"(count)
794 : "i"(-EFAULT), "0"(count), "1"(dst), "2"(src), "3"(count)
795 : "d0", "memory");
796 return res;
797}
798
799/*
800 * Return the size of a string (including the ending 0)
801 *
802 * Return 0 on exception, a value greater than N if too long
803 */
Al Viro11c40f82006-01-12 01:06:24 -0800804static inline long strnlen_user(const char __user *src, long n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805{
806 long res;
807
Al Viro35efbca2006-01-12 01:06:34 -0800808 res = -(unsigned long)src;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 __asm__ __volatile__
810 ("1:\n"
811 " tstl %2\n"
812 " jeq 3f\n"
813 "2: movesb (%1)+,%%d0\n"
814 "22:\n"
815 " subql #1,%2\n"
816 " tstb %%d0\n"
817 " jne 1b\n"
818 " jra 4f\n"
819 "3:\n"
820 " addql #1,%0\n"
821 "4:\n"
822 " addl %1,%0\n"
823 "5:\n"
824 ".section .fixup,\"ax\"\n"
825 " .even\n"
826 "6: moveq %3,%0\n"
827 " jra 5b\n"
828 ".previous\n"
829 ".section __ex_table,\"a\"\n"
830 " .align 4\n"
831 " .long 2b,6b\n"
832 " .long 22b,6b\n"
833 ".previous"
834 : "=d"(res), "=a"(src), "=d"(n)
835 : "i"(0), "0"(res), "1"(src), "2"(n)
836 : "d0");
837 return res;
838}
839
840#define strlen_user(str) strnlen_user(str, 32767)
841
842/*
843 * Zero Userspace
844 */
845
846static inline unsigned long
Al Viro11c40f82006-01-12 01:06:24 -0800847clear_user(void __user *to, unsigned long n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848{
849 __asm__ __volatile__
850 (" tstl %1\n"
851 " jeq 3f\n"
852 "1: movesl %3,(%0)+\n"
853 "2: subql #1,%1\n"
854 " jne 1b\n"
855 "3: movel %2,%1\n"
856 " bclr #1,%1\n"
857 " jeq 4f\n"
858 "24:movesw %3,(%0)+\n"
859 "4: bclr #0,%1\n"
860 " jeq 5f\n"
861 "25:movesb %3,(%0)+\n"
862 "5:\n"
863 ".section .fixup,\"ax\"\n"
864 " .even\n"
865 "61:addql #1,%1\n"
866 "6: lsll #2,%1\n"
867 " addl %2,%1\n"
868 " jra 5b\n"
869 "7: addql #2,%1\n"
870 " jra 5b\n"
871 "8: addql #1,%1\n"
872 " jra 5b\n"
873 ".previous\n"
874 ".section __ex_table,\"a\"\n"
875 " .align 4\n"
876 " .long 1b,61b\n"
877 " .long 2b,6b\n"
878 " .long 3b,61b\n"
879 " .long 24b,7b\n"
880 " .long 4b,7b\n"
881 " .long 25b,8b\n"
882 " .long 5b,8b\n"
883 ".previous"
884 : "=a"(to), "=d"(n)
885 : "r"(n & 3), "r"(0), "0"(to), "1"(n/4));
886 return n;
887}
888
889#endif /* _M68K_UACCESS_H */