• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/cris/arch-v10/lib/
1/*
2 * User address space access functions.
3 * The non-inlined parts of asm-cris/uaccess.h are here.
4 *
5 * Copyright (C) 2000, Axis Communications AB.
6 *
7 * Written by Hans-Peter Nilsson.
8 * Pieces used from memcpy, originally by Kenny Ranerup long time ago.
9 */
10
11#include <asm/uaccess.h>
12
13/* Asm:s have been tweaked (within the domain of correctness) to give
14   satisfactory results for "gcc version 2.96 20000427 (experimental)".
15
16   Check regularly...
17
18   Note that the PC saved at a bus-fault is the address *after* the
19   faulting instruction, which means the branch-target for instructions in
20   delay-slots for taken branches.  Note also that the postincrement in
21   the instruction is performed regardless of bus-fault; the register is
22   seen updated in fault handlers.
23
24   Oh, and on the code formatting issue, to whomever feels like "fixing
25   it" to Conformity: I'm too "lazy", but why don't you go ahead and "fix"
26   string.c too.  I just don't think too many people will hack this file
27   for the code format to be an issue.  */
28
29
30/* Copy to userspace.  This is based on the memcpy used for
31   kernel-to-kernel copying; see "string.c".  */
32
33unsigned long
34__copy_user (void __user *pdst, const void *psrc, unsigned long pn)
35{
36
37  register char *dst __asm__ ("r13") = pdst;
38  register const char *src __asm__ ("r11") = psrc;
39  register int n __asm__ ("r12") = pn;
40  register int retn __asm__ ("r10") = 0;
41
42
43  /* When src is aligned but not dst, this makes a few extra needless
44     cycles.  I believe it would take as many to check that the
45     re-alignment was unnecessary.  */
46  if (((unsigned long) dst & 3) != 0
47      /* Don't align if we wouldn't copy more than a few bytes; so we
48	 don't have to check further for overflows.  */
49      && n >= 3)
50  {
51    if ((unsigned long) dst & 1)
52    {
53      __asm_copy_to_user_1 (dst, src, retn);
54      n--;
55    }
56
57    if ((unsigned long) dst & 2)
58    {
59      __asm_copy_to_user_2 (dst, src, retn);
60      n -= 2;
61    }
62  }
63
64  /* Decide which copying method to use. */
65  if (n >= 44*2)		/* Break even between movem and
66				   move16 is at 38.7*2, but modulo 44. */
67  {
68    /* For large copies we use 'movem'.  */
69
70    /* It is not optimal to tell the compiler about clobbering any
71       registers; that will move the saving/restoring of those registers
72       to the function prologue/epilogue, and make non-movem sizes
73       suboptimal.
74
75       This method is not foolproof; it assumes that the "asm reg"
76       declarations at the beginning of the function really are used
77       here (beware: they may be moved to temporary registers).
78       This way, we do not have to save/move the registers around into
79       temporaries; we can safely use them straight away.
80
81       If you want to check that the allocation was right; then
82       check the equalities in the first comment.  It should say
83       "r13=r13, r11=r11, r12=r12".  */
84    __asm__ volatile ("\
85	.ifnc %0%1%2%3,$r13$r11$r12$r10					\n\
86	.err								\n\
87	.endif								\n\
88									\n\
89	;; Save the registers we'll use in the movem process		\n\
90	;; on the stack.						\n\
91	subq	11*4,$sp						\n\
92	movem	$r10,[$sp]						\n\
93									\n\
94	;; Now we've got this:						\n\
95	;; r11 - src							\n\
96	;; r13 - dst							\n\
97	;; r12 - n							\n\
98									\n\
99	;; Update n for the first loop					\n\
100	subq	44,$r12							\n\
101									\n\
102; Since the noted PC of a faulting instruction in a delay-slot of a taken \n\
103; branch, is that of the branch target, we actually point at the from-movem \n\
104; for this case.  There is no ambiguity here; if there was a fault in that \n\
105; instruction (meaning a kernel oops), the faulted PC would be the address \n\
106; after *that* movem.							\n\
107									\n\
1080:									\n\
109	movem	[$r11+],$r10						\n\
110	subq   44,$r12							\n\
111	bge	0b							\n\
112	movem	$r10,[$r13+]						\n\
1131:									\n\
114	addq   44,$r12  ;; compensate for last loop underflowing n	\n\
115									\n\
116	;; Restore registers from stack					\n\
117	movem [$sp+],$r10						\n\
1182:									\n\
119	.section .fixup,\"ax\"						\n\
120									\n\
121; To provide a correct count in r10 of bytes that failed to be copied,	\n\
122; we jump back into the loop if the loop-branch was taken.  There is no	\n\
123; performance penalty for sany use; the program will segfault soon enough.\n\
124									\n\
1253:									\n\
126	move.d [$sp],$r10						\n\
127	addq 44,$r10							\n\
128	move.d $r10,[$sp]						\n\
129	jump 0b								\n\
1304:									\n\
131	movem [$sp+],$r10						\n\
132	addq 44,$r10							\n\
133	addq 44,$r12							\n\
134	jump 2b								\n\
135									\n\
136	.previous							\n\
137	.section __ex_table,\"a\"					\n\
138	.dword 0b,3b							\n\
139	.dword 1b,4b							\n\
140	.previous"
141
142     /* Outputs */ : "=r" (dst), "=r" (src), "=r" (n), "=r" (retn)
143     /* Inputs */ : "0" (dst), "1" (src), "2" (n), "3" (retn));
144
145  }
146
147  /* Either we directly start copying, using dword copying in a loop, or
148     we copy as much as possible with 'movem' and then the last block (<44
149     bytes) is copied here.  This will work since 'movem' will have
150     updated SRC, DST and N.  */
151
152  while (n >= 16)
153  {
154    __asm_copy_to_user_16 (dst, src, retn);
155    n -= 16;
156  }
157
158  while (n >= 4)
159  {
160    __asm_copy_to_user_4 (dst, src, retn);
161    n -= 4;
162  }
163
164  switch (n)
165  {
166    case 0:
167      break;
168    case 1:
169      __asm_copy_to_user_1 (dst, src, retn);
170      break;
171    case 2:
172      __asm_copy_to_user_2 (dst, src, retn);
173      break;
174    case 3:
175      __asm_copy_to_user_3 (dst, src, retn);
176      break;
177  }
178
179  return retn;
180}
181
182/* Copy from user to kernel, zeroing the bytes that were inaccessible in
183   userland.  The return-value is the number of bytes that were
184   inaccessible.  */
185
186unsigned long
187__copy_user_zeroing(void *pdst, const void __user *psrc, unsigned long pn)
188{
189
190  register char *dst __asm__ ("r13") = pdst;
191  register const char *src __asm__ ("r11") = psrc;
192  register int n __asm__ ("r12") = pn;
193  register int retn __asm__ ("r10") = 0;
194
195  /* The best reason to align src is that we then know that a read-fault
196     was for aligned bytes; there's no 1..3 remaining good bytes to
197     pickle.  */
198  if (((unsigned long) src & 3) != 0)
199  {
200    if (((unsigned long) src & 1) && n != 0)
201    {
202      __asm_copy_from_user_1 (dst, src, retn);
203      n--;
204    }
205
206    if (((unsigned long) src & 2) && n >= 2)
207    {
208      __asm_copy_from_user_2 (dst, src, retn);
209      n -= 2;
210    }
211
212    /* We only need one check after the unalignment-adjustments, because
213       if both adjustments were done, either both or neither reference
214       had an exception.  */
215    if (retn != 0)
216      goto copy_exception_bytes;
217  }
218
219  /* Decide which copying method to use. */
220  if (n >= 44*2)
221  {
222    /* For large copies we use 'movem' */
223
224    /* It is not optimal to tell the compiler about clobbering any
225       registers; that will move the saving/restoring of those registers
226       to the function prologue/epilogue, and make non-movem sizes
227       suboptimal.
228
229       This method is not foolproof; it assumes that the "asm reg"
230       declarations at the beginning of the function really are used
231       here (beware: they may be moved to temporary registers).
232       This way, we do not have to save/move the registers around into
233       temporaries; we can safely use them straight away.
234
235       If you want to check that the allocation was right; then
236       check the equalities in the first comment.  It should say
237       "r13=r13, r11=r11, r12=r12" */
238    __asm__ volatile ("\n\
239	.ifnc %0%1%2%3,$r13$r11$r12$r10					\n\
240	.err								\n\
241	.endif								\n\
242									\n\
243	;; Save the registers we'll use in the movem process		\n\
244	;; on the stack.						\n\
245	subq	11*4,$sp						\n\
246	movem	$r10,[$sp]						\n\
247									\n\
248	;; Now we've got this:						\n\
249	;; r11 - src							\n\
250	;; r13 - dst							\n\
251	;; r12 - n							\n\
252									\n\
253	;; Update n for the first loop					\n\
254	subq	44,$r12							\n\
2550:									\n\
256	movem	[$r11+],$r10						\n\
2571:									\n\
258	subq   44,$r12							\n\
259	bge	0b							\n\
260	movem	$r10,[$r13+]						\n\
261									\n\
262	addq   44,$r12  ;; compensate for last loop underflowing n	\n\
263									\n\
264	;; Restore registers from stack					\n\
265	movem [$sp+],$r10						\n\
2664:									\n\
267	.section .fixup,\"ax\"						\n\
268									\n\
269;; Do not jump back into the loop if we fail.  For some uses, we get a	\n\
270;; page fault somewhere on the line.  Without checking for page limits,	\n\
271;; we don't know where, but we need to copy accurately and keep an	\n\
272;; accurate count; not just clear the whole line.  To do that, we fall	\n\
273;; down in the code below, proceeding with smaller amounts.  It should	\n\
274;; be kept in mind that we have to cater to code like what at one time	\n\
275;; was in fs/super.c:							\n\
276;;  i = size - copy_from_user((void *)page, data, size);		\n\
277;; which would cause repeated faults while clearing the remainder of	\n\
278;; the SIZE bytes at PAGE after the first fault.			\n\
279;; A caveat here is that we must not fall through from a failing page	\n\
280;; to a valid page.							\n\
281									\n\
2823:									\n\
283	movem  [$sp+],$r10						\n\
284	addq	44,$r12 ;; Get back count before faulting point.	\n\
285	subq	44,$r11 ;; Get back pointer to faulting movem-line.	\n\
286	jump	4b	;; Fall through, pretending the fault didn't happen.\n\
287									\n\
288	.previous							\n\
289	.section __ex_table,\"a\"					\n\
290	.dword 1b,3b							\n\
291	.previous"
292
293     /* Outputs */ : "=r" (dst), "=r" (src), "=r" (n), "=r" (retn)
294     /* Inputs */ : "0" (dst), "1" (src), "2" (n), "3" (retn));
295
296  }
297
298  /* Either we directly start copying here, using dword copying in a loop,
299     or we copy as much as possible with 'movem' and then the last block
300     (<44 bytes) is copied here.  This will work since 'movem' will have
301     updated src, dst and n.  (Except with failing src.)
302
303     Since we want to keep src accurate, we can't use
304     __asm_copy_from_user_N with N != (1, 2, 4); it updates dst and
305     retn, but not src (by design; it's value is ignored elsewhere).  */
306
307  while (n >= 4)
308  {
309    __asm_copy_from_user_4 (dst, src, retn);
310    n -= 4;
311
312    if (retn)
313      goto copy_exception_bytes;
314  }
315
316  /* If we get here, there were no memory read faults.  */
317  switch (n)
318  {
319    /* These copies are at least "naturally aligned" (so we don't have
320       to check each byte), due to the src alignment code before the
321       movem loop.  The *_3 case *will* get the correct count for retn.  */
322    case 0:
323      /* This case deliberately left in (if you have doubts check the
324	 generated assembly code).  */
325      break;
326    case 1:
327      __asm_copy_from_user_1 (dst, src, retn);
328      break;
329    case 2:
330      __asm_copy_from_user_2 (dst, src, retn);
331      break;
332    case 3:
333      __asm_copy_from_user_3 (dst, src, retn);
334      break;
335  }
336
337  /* If we get here, retn correctly reflects the number of failing
338     bytes.  */
339  return retn;
340
341copy_exception_bytes:
342  /* We already have "retn" bytes cleared, and need to clear the
343     remaining "n" bytes.  A non-optimized simple byte-for-byte in-line
344     memset is preferred here, since this isn't speed-critical code and
345     we'd rather have this a leaf-function than calling memset.  */
346  {
347    char *endp;
348    for (endp = dst + n; dst < endp; dst++)
349      *dst = 0;
350  }
351
352  return retn + n;
353}
354
355/* Zero userspace.  */
356
357unsigned long
358__do_clear_user (void __user *pto, unsigned long pn)
359{
360
361  register char *dst __asm__ ("r13") = pto;
362  register int n __asm__ ("r12") = pn;
363  register int retn __asm__ ("r10") = 0;
364
365
366  if (((unsigned long) dst & 3) != 0
367     /* Don't align if we wouldn't copy more than a few bytes.  */
368      && n >= 3)
369  {
370    if ((unsigned long) dst & 1)
371    {
372      __asm_clear_1 (dst, retn);
373      n--;
374    }
375
376    if ((unsigned long) dst & 2)
377    {
378      __asm_clear_2 (dst, retn);
379      n -= 2;
380    }
381  }
382
383  if (n >= (1*48))
384  {
385    /* For large clears we use 'movem' */
386
387    /* It is not optimal to tell the compiler about clobbering any
388       call-saved registers; that will move the saving/restoring of
389       those registers to the function prologue/epilogue, and make
390       non-movem sizes suboptimal.
391
392       This method is not foolproof; it assumes that the "asm reg"
393       declarations at the beginning of the function really are used
394       here (beware: they may be moved to temporary registers).
395       This way, we do not have to save/move the registers around into
396       temporaries; we can safely use them straight away.
397
398      If you want to check that the allocation was right; then
399      check the equalities in the first comment.  It should say
400      something like "r13=r13, r11=r11, r12=r12". */
401    __asm__ volatile ("\n\
402	.ifnc %0%1%2,$r13$r12$r10					\n\
403	.err								\n\
404	.endif								\n\
405									\n\
406	;; Save the registers we'll clobber in the movem process	\n\
407	;; on the stack.  Don't mention them to gcc, it will only be	\n\
408	;; upset.							\n\
409	subq	11*4,$sp						\n\
410	movem	$r10,[$sp]						\n\
411									\n\
412	clear.d $r0							\n\
413	clear.d $r1							\n\
414	clear.d $r2							\n\
415	clear.d $r3							\n\
416	clear.d $r4							\n\
417	clear.d $r5							\n\
418	clear.d $r6							\n\
419	clear.d $r7							\n\
420	clear.d $r8							\n\
421	clear.d $r9							\n\
422	clear.d $r10							\n\
423	clear.d $r11							\n\
424									\n\
425	;; Now we've got this:						\n\
426	;; r13 - dst							\n\
427	;; r12 - n							\n\
428									\n\
429	;; Update n for the first loop					\n\
430	subq	12*4,$r12						\n\
4310:									\n\
432	subq   12*4,$r12						\n\
433	bge	0b							\n\
434	movem	$r11,[$r13+]						\n\
4351:									\n\
436	addq   12*4,$r12        ;; compensate for last loop underflowing n\n\
437									\n\
438	;; Restore registers from stack					\n\
439	movem [$sp+],$r10						\n\
4402:									\n\
441	.section .fixup,\"ax\"						\n\
4423:									\n\
443	move.d [$sp],$r10						\n\
444	addq 12*4,$r10							\n\
445	move.d $r10,[$sp]						\n\
446	clear.d $r10							\n\
447	jump 0b								\n\
448									\n\
4494:									\n\
450	movem [$sp+],$r10						\n\
451	addq 12*4,$r10							\n\
452	addq 12*4,$r12							\n\
453	jump 2b								\n\
454									\n\
455	.previous							\n\
456	.section __ex_table,\"a\"					\n\
457	.dword 0b,3b							\n\
458	.dword 1b,4b							\n\
459	.previous"
460
461     /* Outputs */ : "=r" (dst), "=r" (n), "=r" (retn)
462     /* Inputs */ : "0" (dst), "1" (n), "2" (retn)
463     /* Clobber */ : "r11");
464  }
465
466  while (n >= 16)
467  {
468    __asm_clear_16 (dst, retn);
469    n -= 16;
470  }
471
472  while (n >= 4)
473  {
474    __asm_clear_4 (dst, retn);
475    n -= 4;
476  }
477
478  switch (n)
479  {
480    case 0:
481      break;
482    case 1:
483      __asm_clear_1 (dst, retn);
484      break;
485    case 2:
486      __asm_clear_2 (dst, retn);
487      break;
488    case 3:
489      __asm_clear_3 (dst, retn);
490      break;
491  }
492
493  return retn;
494}
495