Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.12 718 lines 18 kB view raw
1/* 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