blob: 130b8f28610a4b07f376a6b981e1644fc2a4e114 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/arm26/lib/uaccess-user.S
3 *
4 * Copyright (C) 1995, 1996,1997,1998 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Routines to block copy data to/from user memory
11 * These are highly optimised both for the 4k page size
12 * and for various alignments.
13 */
14#include <linux/linkage.h>
15#include <asm/assembler.h>
16#include <asm/errno.h>
17#include <asm/page.h>
18
19 .text
20
21//FIXME - surely this can be done in C not asm, removing the problem of keeping C and asm in sync? (this is a struct uaccess_t)
22 .globl uaccess_user
23uaccess_user:
24 .word uaccess_user_put_byte
25 .word uaccess_user_get_byte
26 .word uaccess_user_put_half
27 .word uaccess_user_get_half
28 .word uaccess_user_put_word
29 .word uaccess_user_get_word
30 .word uaccess_user_put_dword
31 .word uaccess_user_copy_from_user
32 .word uaccess_user_copy_to_user
33 .word uaccess_user_clear_user
34 .word uaccess_user_strncpy_from_user
35 .word uaccess_user_strnlen_user
36
37
38@ In : r0 = x, r1 = addr, r2 = error
39@ Out: r2 = error
40uaccess_user_put_byte:
41 stmfd sp!, {lr}
42USER( strbt r0, [r1])
43 ldmfd sp!, {pc}^
44
45@ In : r0 = x, r1 = addr, r2 = error
46@ Out: r2 = error
47uaccess_user_put_half:
48 stmfd sp!, {lr}
49USER( strbt r0, [r1], #1)
50 mov r0, r0, lsr #8
51USER( strbt r0, [r1])
52 ldmfd sp!, {pc}^
53
54@ In : r0 = x, r1 = addr, r2 = error
55@ Out: r2 = error
56uaccess_user_put_word:
57 stmfd sp!, {lr}
58USER( strt r0, [r1])
59 ldmfd sp!, {pc}^
60
61@ In : r0 = x, r1 = addr, r2 = error
62@ Out: r2 = error
63uaccess_user_put_dword:
64 stmfd sp!, {lr}
65USER( strt r0, [r1], #4)
66USER( strt r0, [r1], #0)
67 ldmfd sp!, {pc}^
68
699001: mov r2, #-EFAULT
70 ldmfd sp!, {pc}^
71
72
73@ In : r0 = addr, r1 = error
74@ Out: r0 = x, r1 = error
75uaccess_user_get_byte:
76 stmfd sp!, {lr}
77USER( ldrbt r0, [r0])
78 ldmfd sp!, {pc}^
79
80@ In : r0 = addr, r1 = error
81@ Out: r0 = x, r1 = error
82uaccess_user_get_half:
83 stmfd sp!, {lr}
84USER( ldrt r0, [r0])
85 mov r0, r0, lsl #16
86 mov r0, r0, lsr #16
87 ldmfd sp!, {pc}^
88
89@ In : r0 = addr, r1 = error
90@ Out: r0 = x, r1 = error
91uaccess_user_get_word:
92 stmfd sp!, {lr}
93USER( ldrt r0, [r0])
94 ldmfd sp!, {pc}^
95
969001: mov r1, #-EFAULT
97 ldmfd sp!, {pc}^
98
99/* Prototype: int uaccess_user_copy_to_user(void *to, const char *from, size_t n)
100 * Purpose : copy a block to user memory from kernel memory
101 * Params : to - user memory
102 * : from - kernel memory
103 * : n - number of bytes to copy
104 * Returns : Number of bytes NOT copied.
105 */
106
107.c2u_dest_not_aligned:
108 rsb ip, ip, #4
109 cmp ip, #2
110 ldrb r3, [r1], #1
111USER( strbt r3, [r0], #1) @ May fault
112 ldrgeb r3, [r1], #1
113USER( strgebt r3, [r0], #1) @ May fault
114 ldrgtb r3, [r1], #1
115USER( strgtbt r3, [r0], #1) @ May fault
116 sub r2, r2, ip
117 b .c2u_dest_aligned
118
119ENTRY(uaccess_user_copy_to_user)
120 stmfd sp!, {r2, r4 - r7, lr}
121 cmp r2, #4
122 blt .c2u_not_enough
123 ands ip, r0, #3
124 bne .c2u_dest_not_aligned
125.c2u_dest_aligned:
126
127 ands ip, r1, #3
128 bne .c2u_src_not_aligned
129/*
130 * Seeing as there has to be at least 8 bytes to copy, we can
131 * copy one word, and force a user-mode page fault...
132 */
133
134.c2u_0fupi: subs r2, r2, #4
135 addmi ip, r2, #4
136 bmi .c2u_0nowords
137 ldr r3, [r1], #4
138USER( strt r3, [r0], #4) @ May fault
139 mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
140 rsb ip, ip, #0
141 movs ip, ip, lsr #32 - PAGE_SHIFT
142 beq .c2u_0fupi
143/*
144 * ip = max no. of bytes to copy before needing another "strt" insn
145 */
146 cmp r2, ip
147 movlt ip, r2
148 sub r2, r2, ip
149 subs ip, ip, #32
150 blt .c2u_0rem8lp
151
152.c2u_0cpy8lp: ldmia r1!, {r3 - r6}
153 stmia r0!, {r3 - r6} @ Shouldnt fault
154 ldmia r1!, {r3 - r6}
155 stmia r0!, {r3 - r6} @ Shouldnt fault
156 subs ip, ip, #32
157 bpl .c2u_0cpy8lp
158.c2u_0rem8lp: cmn ip, #16
159 ldmgeia r1!, {r3 - r6}
160 stmgeia r0!, {r3 - r6} @ Shouldnt fault
161 tst ip, #8
162 ldmneia r1!, {r3 - r4}
163 stmneia r0!, {r3 - r4} @ Shouldnt fault
164 tst ip, #4
165 ldrne r3, [r1], #4
166 strnet r3, [r0], #4 @ Shouldnt fault
167 ands ip, ip, #3
168 beq .c2u_0fupi
169.c2u_0nowords: teq ip, #0
170 beq .c2u_finished
171.c2u_nowords: cmp ip, #2
172 ldrb r3, [r1], #1
173USER( strbt r3, [r0], #1) @ May fault
174 ldrgeb r3, [r1], #1
175USER( strgebt r3, [r0], #1) @ May fault
176 ldrgtb r3, [r1], #1
177USER( strgtbt r3, [r0], #1) @ May fault
178 b .c2u_finished
179
180.c2u_not_enough:
181 movs ip, r2
182 bne .c2u_nowords
183.c2u_finished: mov r0, #0
184 LOADREGS(fd,sp!,{r2, r4 - r7, pc})
185
186.c2u_src_not_aligned:
187 bic r1, r1, #3
188 ldr r7, [r1], #4
189 cmp ip, #2
190 bgt .c2u_3fupi
191 beq .c2u_2fupi
192.c2u_1fupi: subs r2, r2, #4
193 addmi ip, r2, #4
194 bmi .c2u_1nowords
195 mov r3, r7, pull #8
196 ldr r7, [r1], #4
197 orr r3, r3, r7, push #24
198USER( strt r3, [r0], #4) @ May fault
199 mov ip, r0, lsl #32 - PAGE_SHIFT
200 rsb ip, ip, #0
201 movs ip, ip, lsr #32 - PAGE_SHIFT
202 beq .c2u_1fupi
203 cmp r2, ip
204 movlt ip, r2
205 sub r2, r2, ip
206 subs ip, ip, #16
207 blt .c2u_1rem8lp
208
209.c2u_1cpy8lp: mov r3, r7, pull #8
210 ldmia r1!, {r4 - r7}
211 orr r3, r3, r4, push #24
212 mov r4, r4, pull #8
213 orr r4, r4, r5, push #24
214 mov r5, r5, pull #8
215 orr r5, r5, r6, push #24
216 mov r6, r6, pull #8
217 orr r6, r6, r7, push #24
218 stmia r0!, {r3 - r6} @ Shouldnt fault
219 subs ip, ip, #16
220 bpl .c2u_1cpy8lp
221.c2u_1rem8lp: tst ip, #8
222 movne r3, r7, pull #8
223 ldmneia r1!, {r4, r7}
224 orrne r3, r3, r4, push #24
225 movne r4, r4, pull #8
226 orrne r4, r4, r7, push #24
227 stmneia r0!, {r3 - r4} @ Shouldnt fault
228 tst ip, #4
229 movne r3, r7, pull #8
230 ldrne r7, [r1], #4
231 orrne r3, r3, r7, push #24
232 strnet r3, [r0], #4 @ Shouldnt fault
233 ands ip, ip, #3
234 beq .c2u_1fupi
235.c2u_1nowords: mov r3, r7, lsr #byte(1)
236 teq ip, #0
237 beq .c2u_finished
238 cmp ip, #2
239USER( strbt r3, [r0], #1) @ May fault
240 movge r3, r7, lsr #byte(2)
241USER( strgebt r3, [r0], #1) @ May fault
242 movgt r3, r7, lsr #byte(3)
243USER( strgtbt r3, [r0], #1) @ May fault
244 b .c2u_finished
245
246.c2u_2fupi: subs r2, r2, #4
247 addmi ip, r2, #4
248 bmi .c2u_2nowords
249 mov r3, r7, pull #16
250 ldr r7, [r1], #4
251 orr r3, r3, r7, push #16
252USER( strt r3, [r0], #4) @ May fault
253 mov ip, r0, lsl #32 - PAGE_SHIFT
254 rsb ip, ip, #0
255 movs ip, ip, lsr #32 - PAGE_SHIFT
256 beq .c2u_2fupi
257 cmp r2, ip
258 movlt ip, r2
259 sub r2, r2, ip
260 subs ip, ip, #16
261 blt .c2u_2rem8lp
262
263.c2u_2cpy8lp: mov r3, r7, pull #16
264 ldmia r1!, {r4 - r7}
265 orr r3, r3, r4, push #16
266 mov r4, r4, pull #16
267 orr r4, r4, r5, push #16
268 mov r5, r5, pull #16
269 orr r5, r5, r6, push #16
270 mov r6, r6, pull #16
271 orr r6, r6, r7, push #16
272 stmia r0!, {r3 - r6} @ Shouldnt fault
273 subs ip, ip, #16
274 bpl .c2u_2cpy8lp
275.c2u_2rem8lp: tst ip, #8
276 movne r3, r7, pull #16
277 ldmneia r1!, {r4, r7}
278 orrne r3, r3, r4, push #16
279 movne r4, r4, pull #16
280 orrne r4, r4, r7, push #16
281 stmneia r0!, {r3 - r4} @ Shouldnt fault
282 tst ip, #4
283 movne r3, r7, pull #16
284 ldrne r7, [r1], #4
285 orrne r3, r3, r7, push #16
286 strnet r3, [r0], #4 @ Shouldnt fault
287 ands ip, ip, #3
288 beq .c2u_2fupi
289.c2u_2nowords: mov r3, r7, lsr #byte(2)
290 teq ip, #0
291 beq .c2u_finished
292 cmp ip, #2
293USER( strbt r3, [r0], #1) @ May fault
294 movge r3, r7, lsr #byte(3)
295USER( strgebt r3, [r0], #1) @ May fault
296 ldrgtb r3, [r1], #0
297USER( strgtbt r3, [r0], #1) @ May fault
298 b .c2u_finished
299
300.c2u_3fupi: subs r2, r2, #4
301 addmi ip, r2, #4
302 bmi .c2u_3nowords
303 mov r3, r7, pull #24
304 ldr r7, [r1], #4
305 orr r3, r3, r7, push #8
306USER( strt r3, [r0], #4) @ May fault
307 mov ip, r0, lsl #32 - PAGE_SHIFT
308 rsb ip, ip, #0
309 movs ip, ip, lsr #32 - PAGE_SHIFT
310 beq .c2u_3fupi
311 cmp r2, ip
312 movlt ip, r2
313 sub r2, r2, ip
314 subs ip, ip, #16
315 blt .c2u_3rem8lp
316
317.c2u_3cpy8lp: mov r3, r7, pull #24
318 ldmia r1!, {r4 - r7}
319 orr r3, r3, r4, push #8
320 mov r4, r4, pull #24
321 orr r4, r4, r5, push #8
322 mov r5, r5, pull #24
323 orr r5, r5, r6, push #8
324 mov r6, r6, pull #24
325 orr r6, r6, r7, push #8
326 stmia r0!, {r3 - r6} @ Shouldnt fault
327 subs ip, ip, #16
328 bpl .c2u_3cpy8lp
329.c2u_3rem8lp: tst ip, #8
330 movne r3, r7, pull #24
331 ldmneia r1!, {r4, r7}
332 orrne r3, r3, r4, push #8
333 movne r4, r4, pull #24
334 orrne r4, r4, r7, push #8
335 stmneia r0!, {r3 - r4} @ Shouldnt fault
336 tst ip, #4
337 movne r3, r7, pull #24
338 ldrne r7, [r1], #4
339 orrne r3, r3, r7, push #8
340 strnet r3, [r0], #4 @ Shouldnt fault
341 ands ip, ip, #3
342 beq .c2u_3fupi
343.c2u_3nowords: mov r3, r7, lsr #byte(3)
344 teq ip, #0
345 beq .c2u_finished
346 cmp ip, #2
347USER( strbt r3, [r0], #1) @ May fault
348 ldrgeb r3, [r1], #1
349USER( strgebt r3, [r0], #1) @ May fault
350 ldrgtb r3, [r1], #0
351USER( strgtbt r3, [r0], #1) @ May fault
352 b .c2u_finished
353
354 .section .fixup,"ax"
355 .align 0
3569001: LOADREGS(fd,sp!, {r0, r4 - r7, pc})
357 .previous
358
359/* Prototype: unsigned long uaccess_user_copy_from_user(void *to,const void *from,unsigned long n);
360 * Purpose : copy a block from user memory to kernel memory
361 * Params : to - kernel memory
362 * : from - user memory
363 * : n - number of bytes to copy
364 * Returns : Number of bytes NOT copied.
365 */
366.cfu_dest_not_aligned:
367 rsb ip, ip, #4
368 cmp ip, #2
369USER( ldrbt r3, [r1], #1) @ May fault
370 strb r3, [r0], #1
371USER( ldrgebt r3, [r1], #1) @ May fault
372 strgeb r3, [r0], #1
373USER( ldrgtbt r3, [r1], #1) @ May fault
374 strgtb r3, [r0], #1
375 sub r2, r2, ip
376 b .cfu_dest_aligned
377
378ENTRY(uaccess_user_copy_from_user)
379 stmfd sp!, {r0, r2, r4 - r7, lr}
380 cmp r2, #4
381 blt .cfu_not_enough
382 ands ip, r0, #3
383 bne .cfu_dest_not_aligned
384.cfu_dest_aligned:
385 ands ip, r1, #3
386 bne .cfu_src_not_aligned
387/*
388 * Seeing as there has to be at least 8 bytes to copy, we can
389 * copy one word, and force a user-mode page fault...
390 */
391
392.cfu_0fupi: subs r2, r2, #4
393 addmi ip, r2, #4
394 bmi .cfu_0nowords
395USER( ldrt r3, [r1], #4)
396 str r3, [r0], #4
397 mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
398 rsb ip, ip, #0
399 movs ip, ip, lsr #32 - PAGE_SHIFT
400 beq .cfu_0fupi
401/*
402 * ip = max no. of bytes to copy before needing another "strt" insn
403 */
404 cmp r2, ip
405 movlt ip, r2
406 sub r2, r2, ip
407 subs ip, ip, #32
408 blt .cfu_0rem8lp
409
410.cfu_0cpy8lp: ldmia r1!, {r3 - r6} @ Shouldnt fault
411 stmia r0!, {r3 - r6}
412 ldmia r1!, {r3 - r6} @ Shouldnt fault
413 stmia r0!, {r3 - r6}
414 subs ip, ip, #32
415 bpl .cfu_0cpy8lp
416.cfu_0rem8lp: cmn ip, #16
417 ldmgeia r1!, {r3 - r6} @ Shouldnt fault
418 stmgeia r0!, {r3 - r6}
419 tst ip, #8
420 ldmneia r1!, {r3 - r4} @ Shouldnt fault
421 stmneia r0!, {r3 - r4}
422 tst ip, #4
423 ldrnet r3, [r1], #4 @ Shouldnt fault
424 strne r3, [r0], #4
425 ands ip, ip, #3
426 beq .cfu_0fupi
427.cfu_0nowords: teq ip, #0
428 beq .cfu_finished
429.cfu_nowords: cmp ip, #2
430USER( ldrbt r3, [r1], #1) @ May fault
431 strb r3, [r0], #1
432USER( ldrgebt r3, [r1], #1) @ May fault
433 strgeb r3, [r0], #1
434USER( ldrgtbt r3, [r1], #1) @ May fault
435 strgtb r3, [r0], #1
436 b .cfu_finished
437
438.cfu_not_enough:
439 movs ip, r2
440 bne .cfu_nowords
441.cfu_finished: mov r0, #0
442 add sp, sp, #8
443 LOADREGS(fd,sp!,{r4 - r7, pc})
444
445.cfu_src_not_aligned:
446 bic r1, r1, #3
447USER( ldrt r7, [r1], #4) @ May fault
448 cmp ip, #2
449 bgt .cfu_3fupi
450 beq .cfu_2fupi
451.cfu_1fupi: subs r2, r2, #4
452 addmi ip, r2, #4
453 bmi .cfu_1nowords
454 mov r3, r7, pull #8
455USER( ldrt r7, [r1], #4) @ May fault
456 orr r3, r3, r7, push #24
457 str r3, [r0], #4
458 mov ip, r1, lsl #32 - PAGE_SHIFT
459 rsb ip, ip, #0
460 movs ip, ip, lsr #32 - PAGE_SHIFT
461 beq .cfu_1fupi
462 cmp r2, ip
463 movlt ip, r2
464 sub r2, r2, ip
465 subs ip, ip, #16
466 blt .cfu_1rem8lp
467
468.cfu_1cpy8lp: mov r3, r7, pull #8
469 ldmia r1!, {r4 - r7} @ Shouldnt fault
470 orr r3, r3, r4, push #24
471 mov r4, r4, pull #8
472 orr r4, r4, r5, push #24
473 mov r5, r5, pull #8
474 orr r5, r5, r6, push #24
475 mov r6, r6, pull #8
476 orr r6, r6, r7, push #24
477 stmia r0!, {r3 - r6}
478 subs ip, ip, #16
479 bpl .cfu_1cpy8lp
480.cfu_1rem8lp: tst ip, #8
481 movne r3, r7, pull #8
482 ldmneia r1!, {r4, r7} @ Shouldnt fault
483 orrne r3, r3, r4, push #24
484 movne r4, r4, pull #8
485 orrne r4, r4, r7, push #24
486 stmneia r0!, {r3 - r4}
487 tst ip, #4
488 movne r3, r7, pull #8
489USER( ldrnet r7, [r1], #4) @ May fault
490 orrne r3, r3, r7, push #24
491 strne r3, [r0], #4
492 ands ip, ip, #3
493 beq .cfu_1fupi
494.cfu_1nowords: mov r3, r7, lsr #byte(1)
495 teq ip, #0
496 beq .cfu_finished
497 cmp ip, #2
498 strb r3, [r0], #1
499 movge r3, r7, lsr #byte(2)
500 strgeb r3, [r0], #1
501 movgt r3, r7, lsr #byte(3)
502 strgtb r3, [r0], #1
503 b .cfu_finished
504
505.cfu_2fupi: subs r2, r2, #4
506 addmi ip, r2, #4
507 bmi .cfu_2nowords
508 mov r3, r7, pull #16
509USER( ldrt r7, [r1], #4) @ May fault
510 orr r3, r3, r7, push #16
511 str r3, [r0], #4
512 mov ip, r1, lsl #32 - PAGE_SHIFT
513 rsb ip, ip, #0
514 movs ip, ip, lsr #32 - PAGE_SHIFT
515 beq .cfu_2fupi
516 cmp r2, ip
517 movlt ip, r2
518 sub r2, r2, ip
519 subs ip, ip, #16
520 blt .cfu_2rem8lp
521
522.cfu_2cpy8lp: mov r3, r7, pull #16
523 ldmia r1!, {r4 - r7} @ Shouldnt fault
524 orr r3, r3, r4, push #16
525 mov r4, r4, pull #16
526 orr r4, r4, r5, push #16
527 mov r5, r5, pull #16
528 orr r5, r5, r6, push #16
529 mov r6, r6, pull #16
530 orr r6, r6, r7, push #16
531 stmia r0!, {r3 - r6}
532 subs ip, ip, #16
533 bpl .cfu_2cpy8lp
534.cfu_2rem8lp: tst ip, #8
535 movne r3, r7, pull #16
536 ldmneia r1!, {r4, r7} @ Shouldnt fault
537 orrne r3, r3, r4, push #16
538 movne r4, r4, pull #16
539 orrne r4, r4, r7, push #16
540 stmneia r0!, {r3 - r4}
541 tst ip, #4
542 movne r3, r7, pull #16
543USER( ldrnet r7, [r1], #4) @ May fault
544 orrne r3, r3, r7, push #16
545 strne r3, [r0], #4
546 ands ip, ip, #3
547 beq .cfu_2fupi
548.cfu_2nowords: mov r3, r7, lsr #byte(2)
549 teq ip, #0
550 beq .cfu_finished
551 cmp ip, #2
552 strb r3, [r0], #1
553 movge r3, r7, lsr #byte(3)
554 strgeb r3, [r0], #1
555USER( ldrgtbt r3, [r1], #0) @ May fault
556 strgtb r3, [r0], #1
557 b .cfu_finished
558
559.cfu_3fupi: subs r2, r2, #4
560 addmi ip, r2, #4
561 bmi .cfu_3nowords
562 mov r3, r7, pull #24
563USER( ldrt r7, [r1], #4) @ May fault
564 orr r3, r3, r7, push #8
565 str r3, [r0], #4
566 mov ip, r1, lsl #32 - PAGE_SHIFT
567 rsb ip, ip, #0
568 movs ip, ip, lsr #32 - PAGE_SHIFT
569 beq .cfu_3fupi
570 cmp r2, ip
571 movlt ip, r2
572 sub r2, r2, ip
573 subs ip, ip, #16
574 blt .cfu_3rem8lp
575
576.cfu_3cpy8lp: mov r3, r7, pull #24
577 ldmia r1!, {r4 - r7} @ Shouldnt fault
578 orr r3, r3, r4, push #8
579 mov r4, r4, pull #24
580 orr r4, r4, r5, push #8
581 mov r5, r5, pull #24
582 orr r5, r5, r6, push #8
583 mov r6, r6, pull #24
584 orr r6, r6, r7, push #8
585 stmia r0!, {r3 - r6}
586 subs ip, ip, #16
587 bpl .cfu_3cpy8lp
588.cfu_3rem8lp: tst ip, #8
589 movne r3, r7, pull #24
590 ldmneia r1!, {r4, r7} @ Shouldnt fault
591 orrne r3, r3, r4, push #8
592 movne r4, r4, pull #24
593 orrne r4, r4, r7, push #8
594 stmneia r0!, {r3 - r4}
595 tst ip, #4
596 movne r3, r7, pull #24
597USER( ldrnet r7, [r1], #4) @ May fault
598 orrne r3, r3, r7, push #8
599 strne r3, [r0], #4
600 ands ip, ip, #3
601 beq .cfu_3fupi
602.cfu_3nowords: mov r3, r7, lsr #byte(3)
603 teq ip, #0
604 beq .cfu_finished
605 cmp ip, #2
606 strb r3, [r0], #1
607USER( ldrgebt r3, [r1], #1) @ May fault
608 strgeb r3, [r0], #1
609USER( ldrgtbt r3, [r1], #1) @ May fault
610 strgtb r3, [r0], #1
611 b .cfu_finished
612
613 .section .fixup,"ax"
614 .align 0
615 /*
616 * We took an exception. r0 contains a pointer to
617 * the byte not copied.
618 */
6199001: ldr r2, [sp], #4 @ void *to
620 sub r2, r0, r2 @ bytes copied
621 ldr r1, [sp], #4 @ unsigned long count
622 subs r4, r1, r2 @ bytes left to copy
623 movne r1, r4
624 blne __memzero
625 mov r0, r4
626 LOADREGS(fd,sp!, {r4 - r7, pc})
627 .previous
628
629/* Prototype: int uaccess_user_clear_user(void *addr, size_t sz)
630 * Purpose : clear some user memory
631 * Params : addr - user memory address to clear
632 * : sz - number of bytes to clear
633 * Returns : number of bytes NOT cleared
634 */
635ENTRY(uaccess_user_clear_user)
636 stmfd sp!, {r1, lr}
637 mov r2, #0
638 cmp r1, #4
639 blt 2f
640 ands ip, r0, #3
641 beq 1f
642 cmp ip, #2
643USER( strbt r2, [r0], #1)
644USER( strlebt r2, [r0], #1)
645USER( strltbt r2, [r0], #1)
646 rsb ip, ip, #4
647 sub r1, r1, ip @ 7 6 5 4 3 2 1
6481: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7
649USER( strplt r2, [r0], #4)
650USER( strplt r2, [r0], #4)
651 bpl 1b
652 adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
653USER( strplt r2, [r0], #4)
6542: tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
655USER( strnebt r2, [r0], #1)
656USER( strnebt r2, [r0], #1)
657 tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
658USER( strnebt r2, [r0], #1)
659 mov r0, #0
660 LOADREGS(fd,sp!, {r1, pc})
661
662 .section .fixup,"ax"
663 .align 0
6649001: LOADREGS(fd,sp!, {r0, pc})
665 .previous
666
667/*
668 * Copy a string from user space to kernel space.
669 * r0 = dst, r1 = src, r2 = byte length
670 * returns the number of characters copied (strlen of copied string),
671 * -EFAULT on exception, or "len" if we fill the whole buffer
672 */
673ENTRY(uaccess_user_strncpy_from_user)
674 save_lr
675 mov ip, r1
6761: subs r2, r2, #1
677USER( ldrplbt r3, [r1], #1)
678 bmi 2f
679 strb r3, [r0], #1
680 teq r3, #0
681 bne 1b
682 sub r1, r1, #1 @ take NUL character out of count
6832: sub r0, r1, ip
684 restore_pc
685
686 .section .fixup,"ax"
687 .align 0
6889001: mov r3, #0
689 strb r3, [r0, #0] @ null terminate
690 mov r0, #-EFAULT
691 restore_pc
692 .previous
693
694/* Prototype: unsigned long uaccess_user_strnlen_user(const char *str, long n)
695 * Purpose : get length of a string in user memory
696 * Params : str - address of string in user memory
697 * Returns : length of string *including terminator*
698 * or zero on exception, or n + 1 if too long
699 */
700ENTRY(uaccess_user_strnlen_user)
701 save_lr
702 mov r2, r0
7031:
704USER( ldrbt r3, [r0], #1)
705 teq r3, #0
706 beq 2f
707 subs r1, r1, #1
708 bne 1b
709 add r0, r0, #1
7102: sub r0, r0, r2
711 restore_pc
712
713 .section .fixup,"ax"
714 .align 0
7159001: mov r0, #0
716 restore_pc
717 .previous
718