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