diff options
Diffstat (limited to 'arch/mips/lib/csum_partial.S')
-rw-r--r-- | arch/mips/lib/csum_partial.S | 282 |
1 files changed, 174 insertions, 108 deletions
diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index a6adffbb4e5f..2e4825e48388 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S | |||
@@ -8,6 +8,7 @@ | |||
8 | * Copyright (C) 1998, 1999 Ralf Baechle | 8 | * Copyright (C) 1998, 1999 Ralf Baechle |
9 | * Copyright (C) 1999 Silicon Graphics, Inc. | 9 | * Copyright (C) 1999 Silicon Graphics, Inc. |
10 | * Copyright (C) 2007 Maciej W. Rozycki | 10 | * Copyright (C) 2007 Maciej W. Rozycki |
11 | * Copyright (C) 2014 Imagination Technologies Ltd. | ||
11 | */ | 12 | */ |
12 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
13 | #include <asm/asm.h> | 14 | #include <asm/asm.h> |
@@ -296,7 +297,7 @@ LEAF(csum_partial) | |||
296 | * checksum and copy routines based on memcpy.S | 297 | * checksum and copy routines based on memcpy.S |
297 | * | 298 | * |
298 | * csum_partial_copy_nocheck(src, dst, len, sum) | 299 | * csum_partial_copy_nocheck(src, dst, len, sum) |
299 | * __csum_partial_copy_user(src, dst, len, sum, errp) | 300 | * __csum_partial_copy_kernel(src, dst, len, sum, errp) |
300 | * | 301 | * |
301 | * See "Spec" in memcpy.S for details. Unlike __copy_user, all | 302 | * See "Spec" in memcpy.S for details. Unlike __copy_user, all |
302 | * function in this file use the standard calling convention. | 303 | * function in this file use the standard calling convention. |
@@ -327,20 +328,58 @@ LEAF(csum_partial) | |||
327 | * These handlers do not need to overwrite any data. | 328 | * These handlers do not need to overwrite any data. |
328 | */ | 329 | */ |
329 | 330 | ||
330 | #define EXC(inst_reg,addr,handler) \ | 331 | /* Instruction type */ |
331 | 9: inst_reg, addr; \ | 332 | #define LD_INSN 1 |
332 | .section __ex_table,"a"; \ | 333 | #define ST_INSN 2 |
333 | PTR 9b, handler; \ | 334 | #define LEGACY_MODE 1 |
334 | .previous | 335 | #define EVA_MODE 2 |
336 | #define USEROP 1 | ||
337 | #define KERNELOP 2 | ||
338 | |||
339 | /* | ||
340 | * Wrapper to add an entry in the exception table | ||
341 | * in case the insn causes a memory exception. | ||
342 | * Arguments: | ||
343 | * insn : Load/store instruction | ||
344 | * type : Instruction type | ||
345 | * reg : Register | ||
346 | * addr : Address | ||
347 | * handler : Exception handler | ||
348 | */ | ||
349 | #define EXC(insn, type, reg, addr, handler) \ | ||
350 | .if \mode == LEGACY_MODE; \ | ||
351 | 9: insn reg, addr; \ | ||
352 | .section __ex_table,"a"; \ | ||
353 | PTR 9b, handler; \ | ||
354 | .previous; \ | ||
355 | /* This is enabled in EVA mode */ \ | ||
356 | .else; \ | ||
357 | /* If loading from user or storing to user */ \ | ||
358 | .if ((\from == USEROP) && (type == LD_INSN)) || \ | ||
359 | ((\to == USEROP) && (type == ST_INSN)); \ | ||
360 | 9: __BUILD_EVA_INSN(insn##e, reg, addr); \ | ||
361 | .section __ex_table,"a"; \ | ||
362 | PTR 9b, handler; \ | ||
363 | .previous; \ | ||
364 | .else; \ | ||
365 | /* EVA without exception */ \ | ||
366 | insn reg, addr; \ | ||
367 | .endif; \ | ||
368 | .endif | ||
369 | |||
370 | #undef LOAD | ||
335 | 371 | ||
336 | #ifdef USE_DOUBLE | 372 | #ifdef USE_DOUBLE |
337 | 373 | ||
338 | #define LOAD ld | 374 | #define LOADK ld /* No exception */ |
339 | #define LOADL ldl | 375 | #define LOAD(reg, addr, handler) EXC(ld, LD_INSN, reg, addr, handler) |
340 | #define LOADR ldr | 376 | #define LOADBU(reg, addr, handler) EXC(lbu, LD_INSN, reg, addr, handler) |
341 | #define STOREL sdl | 377 | #define LOADL(reg, addr, handler) EXC(ldl, LD_INSN, reg, addr, handler) |
342 | #define STORER sdr | 378 | #define LOADR(reg, addr, handler) EXC(ldr, LD_INSN, reg, addr, handler) |
343 | #define STORE sd | 379 | #define STOREB(reg, addr, handler) EXC(sb, ST_INSN, reg, addr, handler) |
380 | #define STOREL(reg, addr, handler) EXC(sdl, ST_INSN, reg, addr, handler) | ||
381 | #define STORER(reg, addr, handler) EXC(sdr, ST_INSN, reg, addr, handler) | ||
382 | #define STORE(reg, addr, handler) EXC(sd, ST_INSN, reg, addr, handler) | ||
344 | #define ADD daddu | 383 | #define ADD daddu |
345 | #define SUB dsubu | 384 | #define SUB dsubu |
346 | #define SRL dsrl | 385 | #define SRL dsrl |
@@ -352,12 +391,15 @@ LEAF(csum_partial) | |||
352 | 391 | ||
353 | #else | 392 | #else |
354 | 393 | ||
355 | #define LOAD lw | 394 | #define LOADK lw /* No exception */ |
356 | #define LOADL lwl | 395 | #define LOAD(reg, addr, handler) EXC(lw, LD_INSN, reg, addr, handler) |
357 | #define LOADR lwr | 396 | #define LOADBU(reg, addr, handler) EXC(lbu, LD_INSN, reg, addr, handler) |
358 | #define STOREL swl | 397 | #define LOADL(reg, addr, handler) EXC(lwl, LD_INSN, reg, addr, handler) |
359 | #define STORER swr | 398 | #define LOADR(reg, addr, handler) EXC(lwr, LD_INSN, reg, addr, handler) |
360 | #define STORE sw | 399 | #define STOREB(reg, addr, handler) EXC(sb, ST_INSN, reg, addr, handler) |
400 | #define STOREL(reg, addr, handler) EXC(swl, ST_INSN, reg, addr, handler) | ||
401 | #define STORER(reg, addr, handler) EXC(swr, ST_INSN, reg, addr, handler) | ||
402 | #define STORE(reg, addr, handler) EXC(sw, ST_INSN, reg, addr, handler) | ||
361 | #define ADD addu | 403 | #define ADD addu |
362 | #define SUB subu | 404 | #define SUB subu |
363 | #define SRL srl | 405 | #define SRL srl |
@@ -396,14 +438,20 @@ LEAF(csum_partial) | |||
396 | .set at=v1 | 438 | .set at=v1 |
397 | #endif | 439 | #endif |
398 | 440 | ||
399 | LEAF(__csum_partial_copy_user) | 441 | .macro __BUILD_CSUM_PARTIAL_COPY_USER mode, from, to, __nocheck |
442 | |||
400 | PTR_ADDU AT, src, len /* See (1) above. */ | 443 | PTR_ADDU AT, src, len /* See (1) above. */ |
444 | /* initialize __nocheck if this the first time we execute this | ||
445 | * macro | ||
446 | */ | ||
401 | #ifdef CONFIG_64BIT | 447 | #ifdef CONFIG_64BIT |
402 | move errptr, a4 | 448 | move errptr, a4 |
403 | #else | 449 | #else |
404 | lw errptr, 16(sp) | 450 | lw errptr, 16(sp) |
405 | #endif | 451 | #endif |
406 | FEXPORT(csum_partial_copy_nocheck) | 452 | .if \__nocheck == 1 |
453 | FEXPORT(csum_partial_copy_nocheck) | ||
454 | .endif | ||
407 | move sum, zero | 455 | move sum, zero |
408 | move odd, zero | 456 | move odd, zero |
409 | /* | 457 | /* |
@@ -419,48 +467,48 @@ FEXPORT(csum_partial_copy_nocheck) | |||
419 | */ | 467 | */ |
420 | sltu t2, len, NBYTES | 468 | sltu t2, len, NBYTES |
421 | and t1, dst, ADDRMASK | 469 | and t1, dst, ADDRMASK |
422 | bnez t2, .Lcopy_bytes_checklen | 470 | bnez t2, .Lcopy_bytes_checklen\@ |
423 | and t0, src, ADDRMASK | 471 | and t0, src, ADDRMASK |
424 | andi odd, dst, 0x1 /* odd buffer? */ | 472 | andi odd, dst, 0x1 /* odd buffer? */ |
425 | bnez t1, .Ldst_unaligned | 473 | bnez t1, .Ldst_unaligned\@ |
426 | nop | 474 | nop |
427 | bnez t0, .Lsrc_unaligned_dst_aligned | 475 | bnez t0, .Lsrc_unaligned_dst_aligned\@ |
428 | /* | 476 | /* |
429 | * use delay slot for fall-through | 477 | * use delay slot for fall-through |
430 | * src and dst are aligned; need to compute rem | 478 | * src and dst are aligned; need to compute rem |
431 | */ | 479 | */ |
432 | .Lboth_aligned: | 480 | .Lboth_aligned\@: |
433 | SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter | 481 | SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter |
434 | beqz t0, .Lcleanup_both_aligned # len < 8*NBYTES | 482 | beqz t0, .Lcleanup_both_aligned\@ # len < 8*NBYTES |
435 | nop | 483 | nop |
436 | SUB len, 8*NBYTES # subtract here for bgez loop | 484 | SUB len, 8*NBYTES # subtract here for bgez loop |
437 | .align 4 | 485 | .align 4 |
438 | 1: | 486 | 1: |
439 | EXC( LOAD t0, UNIT(0)(src), .Ll_exc) | 487 | LOAD(t0, UNIT(0)(src), .Ll_exc\@) |
440 | EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy) | 488 | LOAD(t1, UNIT(1)(src), .Ll_exc_copy\@) |
441 | EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy) | 489 | LOAD(t2, UNIT(2)(src), .Ll_exc_copy\@) |
442 | EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy) | 490 | LOAD(t3, UNIT(3)(src), .Ll_exc_copy\@) |
443 | EXC( LOAD t4, UNIT(4)(src), .Ll_exc_copy) | 491 | LOAD(t4, UNIT(4)(src), .Ll_exc_copy\@) |
444 | EXC( LOAD t5, UNIT(5)(src), .Ll_exc_copy) | 492 | LOAD(t5, UNIT(5)(src), .Ll_exc_copy\@) |
445 | EXC( LOAD t6, UNIT(6)(src), .Ll_exc_copy) | 493 | LOAD(t6, UNIT(6)(src), .Ll_exc_copy\@) |
446 | EXC( LOAD t7, UNIT(7)(src), .Ll_exc_copy) | 494 | LOAD(t7, UNIT(7)(src), .Ll_exc_copy\@) |
447 | SUB len, len, 8*NBYTES | 495 | SUB len, len, 8*NBYTES |
448 | ADD src, src, 8*NBYTES | 496 | ADD src, src, 8*NBYTES |
449 | EXC( STORE t0, UNIT(0)(dst), .Ls_exc) | 497 | STORE(t0, UNIT(0)(dst), .Ls_exc\@) |
450 | ADDC(sum, t0) | 498 | ADDC(sum, t0) |
451 | EXC( STORE t1, UNIT(1)(dst), .Ls_exc) | 499 | STORE(t1, UNIT(1)(dst), .Ls_exc\@) |
452 | ADDC(sum, t1) | 500 | ADDC(sum, t1) |
453 | EXC( STORE t2, UNIT(2)(dst), .Ls_exc) | 501 | STORE(t2, UNIT(2)(dst), .Ls_exc\@) |
454 | ADDC(sum, t2) | 502 | ADDC(sum, t2) |
455 | EXC( STORE t3, UNIT(3)(dst), .Ls_exc) | 503 | STORE(t3, UNIT(3)(dst), .Ls_exc\@) |
456 | ADDC(sum, t3) | 504 | ADDC(sum, t3) |
457 | EXC( STORE t4, UNIT(4)(dst), .Ls_exc) | 505 | STORE(t4, UNIT(4)(dst), .Ls_exc\@) |
458 | ADDC(sum, t4) | 506 | ADDC(sum, t4) |
459 | EXC( STORE t5, UNIT(5)(dst), .Ls_exc) | 507 | STORE(t5, UNIT(5)(dst), .Ls_exc\@) |
460 | ADDC(sum, t5) | 508 | ADDC(sum, t5) |
461 | EXC( STORE t6, UNIT(6)(dst), .Ls_exc) | 509 | STORE(t6, UNIT(6)(dst), .Ls_exc\@) |
462 | ADDC(sum, t6) | 510 | ADDC(sum, t6) |
463 | EXC( STORE t7, UNIT(7)(dst), .Ls_exc) | 511 | STORE(t7, UNIT(7)(dst), .Ls_exc\@) |
464 | ADDC(sum, t7) | 512 | ADDC(sum, t7) |
465 | .set reorder /* DADDI_WAR */ | 513 | .set reorder /* DADDI_WAR */ |
466 | ADD dst, dst, 8*NBYTES | 514 | ADD dst, dst, 8*NBYTES |
@@ -471,44 +519,44 @@ EXC( STORE t7, UNIT(7)(dst), .Ls_exc) | |||
471 | /* | 519 | /* |
472 | * len == the number of bytes left to copy < 8*NBYTES | 520 | * len == the number of bytes left to copy < 8*NBYTES |
473 | */ | 521 | */ |
474 | .Lcleanup_both_aligned: | 522 | .Lcleanup_both_aligned\@: |
475 | #define rem t7 | 523 | #define rem t7 |
476 | beqz len, .Ldone | 524 | beqz len, .Ldone\@ |
477 | sltu t0, len, 4*NBYTES | 525 | sltu t0, len, 4*NBYTES |
478 | bnez t0, .Lless_than_4units | 526 | bnez t0, .Lless_than_4units\@ |
479 | and rem, len, (NBYTES-1) # rem = len % NBYTES | 527 | and rem, len, (NBYTES-1) # rem = len % NBYTES |
480 | /* | 528 | /* |
481 | * len >= 4*NBYTES | 529 | * len >= 4*NBYTES |
482 | */ | 530 | */ |
483 | EXC( LOAD t0, UNIT(0)(src), .Ll_exc) | 531 | LOAD(t0, UNIT(0)(src), .Ll_exc\@) |
484 | EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy) | 532 | LOAD(t1, UNIT(1)(src), .Ll_exc_copy\@) |
485 | EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy) | 533 | LOAD(t2, UNIT(2)(src), .Ll_exc_copy\@) |
486 | EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy) | 534 | LOAD(t3, UNIT(3)(src), .Ll_exc_copy\@) |
487 | SUB len, len, 4*NBYTES | 535 | SUB len, len, 4*NBYTES |
488 | ADD src, src, 4*NBYTES | 536 | ADD src, src, 4*NBYTES |
489 | EXC( STORE t0, UNIT(0)(dst), .Ls_exc) | 537 | STORE(t0, UNIT(0)(dst), .Ls_exc\@) |
490 | ADDC(sum, t0) | 538 | ADDC(sum, t0) |
491 | EXC( STORE t1, UNIT(1)(dst), .Ls_exc) | 539 | STORE(t1, UNIT(1)(dst), .Ls_exc\@) |
492 | ADDC(sum, t1) | 540 | ADDC(sum, t1) |
493 | EXC( STORE t2, UNIT(2)(dst), .Ls_exc) | 541 | STORE(t2, UNIT(2)(dst), .Ls_exc\@) |
494 | ADDC(sum, t2) | 542 | ADDC(sum, t2) |
495 | EXC( STORE t3, UNIT(3)(dst), .Ls_exc) | 543 | STORE(t3, UNIT(3)(dst), .Ls_exc\@) |
496 | ADDC(sum, t3) | 544 | ADDC(sum, t3) |
497 | .set reorder /* DADDI_WAR */ | 545 | .set reorder /* DADDI_WAR */ |
498 | ADD dst, dst, 4*NBYTES | 546 | ADD dst, dst, 4*NBYTES |
499 | beqz len, .Ldone | 547 | beqz len, .Ldone\@ |
500 | .set noreorder | 548 | .set noreorder |
501 | .Lless_than_4units: | 549 | .Lless_than_4units\@: |
502 | /* | 550 | /* |
503 | * rem = len % NBYTES | 551 | * rem = len % NBYTES |
504 | */ | 552 | */ |
505 | beq rem, len, .Lcopy_bytes | 553 | beq rem, len, .Lcopy_bytes\@ |
506 | nop | 554 | nop |
507 | 1: | 555 | 1: |
508 | EXC( LOAD t0, 0(src), .Ll_exc) | 556 | LOAD(t0, 0(src), .Ll_exc\@) |
509 | ADD src, src, NBYTES | 557 | ADD src, src, NBYTES |
510 | SUB len, len, NBYTES | 558 | SUB len, len, NBYTES |
511 | EXC( STORE t0, 0(dst), .Ls_exc) | 559 | STORE(t0, 0(dst), .Ls_exc\@) |
512 | ADDC(sum, t0) | 560 | ADDC(sum, t0) |
513 | .set reorder /* DADDI_WAR */ | 561 | .set reorder /* DADDI_WAR */ |
514 | ADD dst, dst, NBYTES | 562 | ADD dst, dst, NBYTES |
@@ -527,20 +575,20 @@ EXC( STORE t0, 0(dst), .Ls_exc) | |||
527 | * more instruction-level parallelism. | 575 | * more instruction-level parallelism. |
528 | */ | 576 | */ |
529 | #define bits t2 | 577 | #define bits t2 |
530 | beqz len, .Ldone | 578 | beqz len, .Ldone\@ |
531 | ADD t1, dst, len # t1 is just past last byte of dst | 579 | ADD t1, dst, len # t1 is just past last byte of dst |
532 | li bits, 8*NBYTES | 580 | li bits, 8*NBYTES |
533 | SLL rem, len, 3 # rem = number of bits to keep | 581 | SLL rem, len, 3 # rem = number of bits to keep |
534 | EXC( LOAD t0, 0(src), .Ll_exc) | 582 | LOAD(t0, 0(src), .Ll_exc\@) |
535 | SUB bits, bits, rem # bits = number of bits to discard | 583 | SUB bits, bits, rem # bits = number of bits to discard |
536 | SHIFT_DISCARD t0, t0, bits | 584 | SHIFT_DISCARD t0, t0, bits |
537 | EXC( STREST t0, -1(t1), .Ls_exc) | 585 | STREST(t0, -1(t1), .Ls_exc\@) |
538 | SHIFT_DISCARD_REVERT t0, t0, bits | 586 | SHIFT_DISCARD_REVERT t0, t0, bits |
539 | .set reorder | 587 | .set reorder |
540 | ADDC(sum, t0) | 588 | ADDC(sum, t0) |
541 | b .Ldone | 589 | b .Ldone\@ |
542 | .set noreorder | 590 | .set noreorder |
543 | .Ldst_unaligned: | 591 | .Ldst_unaligned\@: |
544 | /* | 592 | /* |
545 | * dst is unaligned | 593 | * dst is unaligned |
546 | * t0 = src & ADDRMASK | 594 | * t0 = src & ADDRMASK |
@@ -551,25 +599,25 @@ EXC( STREST t0, -1(t1), .Ls_exc) | |||
551 | * Set match = (src and dst have same alignment) | 599 | * Set match = (src and dst have same alignment) |
552 | */ | 600 | */ |
553 | #define match rem | 601 | #define match rem |
554 | EXC( LDFIRST t3, FIRST(0)(src), .Ll_exc) | 602 | LDFIRST(t3, FIRST(0)(src), .Ll_exc\@) |
555 | ADD t2, zero, NBYTES | 603 | ADD t2, zero, NBYTES |
556 | EXC( LDREST t3, REST(0)(src), .Ll_exc_copy) | 604 | LDREST(t3, REST(0)(src), .Ll_exc_copy\@) |
557 | SUB t2, t2, t1 # t2 = number of bytes copied | 605 | SUB t2, t2, t1 # t2 = number of bytes copied |
558 | xor match, t0, t1 | 606 | xor match, t0, t1 |
559 | EXC( STFIRST t3, FIRST(0)(dst), .Ls_exc) | 607 | STFIRST(t3, FIRST(0)(dst), .Ls_exc\@) |
560 | SLL t4, t1, 3 # t4 = number of bits to discard | 608 | SLL t4, t1, 3 # t4 = number of bits to discard |
561 | SHIFT_DISCARD t3, t3, t4 | 609 | SHIFT_DISCARD t3, t3, t4 |
562 | /* no SHIFT_DISCARD_REVERT to handle odd buffer properly */ | 610 | /* no SHIFT_DISCARD_REVERT to handle odd buffer properly */ |
563 | ADDC(sum, t3) | 611 | ADDC(sum, t3) |
564 | beq len, t2, .Ldone | 612 | beq len, t2, .Ldone\@ |
565 | SUB len, len, t2 | 613 | SUB len, len, t2 |
566 | ADD dst, dst, t2 | 614 | ADD dst, dst, t2 |
567 | beqz match, .Lboth_aligned | 615 | beqz match, .Lboth_aligned\@ |
568 | ADD src, src, t2 | 616 | ADD src, src, t2 |
569 | 617 | ||
570 | .Lsrc_unaligned_dst_aligned: | 618 | .Lsrc_unaligned_dst_aligned\@: |
571 | SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter | 619 | SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter |
572 | beqz t0, .Lcleanup_src_unaligned | 620 | beqz t0, .Lcleanup_src_unaligned\@ |
573 | and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES | 621 | and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES |
574 | 1: | 622 | 1: |
575 | /* | 623 | /* |
@@ -578,53 +626,53 @@ EXC( STFIRST t3, FIRST(0)(dst), .Ls_exc) | |||
578 | * It's OK to load FIRST(N+1) before REST(N) because the two addresses | 626 | * It's OK to load FIRST(N+1) before REST(N) because the two addresses |
579 | * are to the same unit (unless src is aligned, but it's not). | 627 | * are to the same unit (unless src is aligned, but it's not). |
580 | */ | 628 | */ |
581 | EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc) | 629 | LDFIRST(t0, FIRST(0)(src), .Ll_exc\@) |
582 | EXC( LDFIRST t1, FIRST(1)(src), .Ll_exc_copy) | 630 | LDFIRST(t1, FIRST(1)(src), .Ll_exc_copy\@) |
583 | SUB len, len, 4*NBYTES | 631 | SUB len, len, 4*NBYTES |
584 | EXC( LDREST t0, REST(0)(src), .Ll_exc_copy) | 632 | LDREST(t0, REST(0)(src), .Ll_exc_copy\@) |
585 | EXC( LDREST t1, REST(1)(src), .Ll_exc_copy) | 633 | LDREST(t1, REST(1)(src), .Ll_exc_copy\@) |
586 | EXC( LDFIRST t2, FIRST(2)(src), .Ll_exc_copy) | 634 | LDFIRST(t2, FIRST(2)(src), .Ll_exc_copy\@) |
587 | EXC( LDFIRST t3, FIRST(3)(src), .Ll_exc_copy) | 635 | LDFIRST(t3, FIRST(3)(src), .Ll_exc_copy\@) |
588 | EXC( LDREST t2, REST(2)(src), .Ll_exc_copy) | 636 | LDREST(t2, REST(2)(src), .Ll_exc_copy\@) |
589 | EXC( LDREST t3, REST(3)(src), .Ll_exc_copy) | 637 | LDREST(t3, REST(3)(src), .Ll_exc_copy\@) |
590 | ADD src, src, 4*NBYTES | 638 | ADD src, src, 4*NBYTES |
591 | #ifdef CONFIG_CPU_SB1 | 639 | #ifdef CONFIG_CPU_SB1 |
592 | nop # improves slotting | 640 | nop # improves slotting |
593 | #endif | 641 | #endif |
594 | EXC( STORE t0, UNIT(0)(dst), .Ls_exc) | 642 | STORE(t0, UNIT(0)(dst), .Ls_exc\@) |
595 | ADDC(sum, t0) | 643 | ADDC(sum, t0) |
596 | EXC( STORE t1, UNIT(1)(dst), .Ls_exc) | 644 | STORE(t1, UNIT(1)(dst), .Ls_exc\@) |
597 | ADDC(sum, t1) | 645 | ADDC(sum, t1) |
598 | EXC( STORE t2, UNIT(2)(dst), .Ls_exc) | 646 | STORE(t2, UNIT(2)(dst), .Ls_exc\@) |
599 | ADDC(sum, t2) | 647 | ADDC(sum, t2) |
600 | EXC( STORE t3, UNIT(3)(dst), .Ls_exc) | 648 | STORE(t3, UNIT(3)(dst), .Ls_exc\@) |
601 | ADDC(sum, t3) | 649 | ADDC(sum, t3) |
602 | .set reorder /* DADDI_WAR */ | 650 | .set reorder /* DADDI_WAR */ |
603 | ADD dst, dst, 4*NBYTES | 651 | ADD dst, dst, 4*NBYTES |
604 | bne len, rem, 1b | 652 | bne len, rem, 1b |
605 | .set noreorder | 653 | .set noreorder |
606 | 654 | ||
607 | .Lcleanup_src_unaligned: | 655 | .Lcleanup_src_unaligned\@: |
608 | beqz len, .Ldone | 656 | beqz len, .Ldone\@ |
609 | and rem, len, NBYTES-1 # rem = len % NBYTES | 657 | and rem, len, NBYTES-1 # rem = len % NBYTES |
610 | beq rem, len, .Lcopy_bytes | 658 | beq rem, len, .Lcopy_bytes\@ |
611 | nop | 659 | nop |
612 | 1: | 660 | 1: |
613 | EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc) | 661 | LDFIRST(t0, FIRST(0)(src), .Ll_exc\@) |
614 | EXC( LDREST t0, REST(0)(src), .Ll_exc_copy) | 662 | LDREST(t0, REST(0)(src), .Ll_exc_copy\@) |
615 | ADD src, src, NBYTES | 663 | ADD src, src, NBYTES |
616 | SUB len, len, NBYTES | 664 | SUB len, len, NBYTES |
617 | EXC( STORE t0, 0(dst), .Ls_exc) | 665 | STORE(t0, 0(dst), .Ls_exc\@) |
618 | ADDC(sum, t0) | 666 | ADDC(sum, t0) |
619 | .set reorder /* DADDI_WAR */ | 667 | .set reorder /* DADDI_WAR */ |
620 | ADD dst, dst, NBYTES | 668 | ADD dst, dst, NBYTES |
621 | bne len, rem, 1b | 669 | bne len, rem, 1b |
622 | .set noreorder | 670 | .set noreorder |
623 | 671 | ||
624 | .Lcopy_bytes_checklen: | 672 | .Lcopy_bytes_checklen\@: |
625 | beqz len, .Ldone | 673 | beqz len, .Ldone\@ |
626 | nop | 674 | nop |
627 | .Lcopy_bytes: | 675 | .Lcopy_bytes\@: |
628 | /* 0 < len < NBYTES */ | 676 | /* 0 < len < NBYTES */ |
629 | #ifdef CONFIG_CPU_LITTLE_ENDIAN | 677 | #ifdef CONFIG_CPU_LITTLE_ENDIAN |
630 | #define SHIFT_START 0 | 678 | #define SHIFT_START 0 |
@@ -637,12 +685,12 @@ EXC( STORE t0, 0(dst), .Ls_exc) | |||
637 | li t3, SHIFT_START # shift | 685 | li t3, SHIFT_START # shift |
638 | /* use .Ll_exc_copy here to return correct sum on fault */ | 686 | /* use .Ll_exc_copy here to return correct sum on fault */ |
639 | #define COPY_BYTE(N) \ | 687 | #define COPY_BYTE(N) \ |
640 | EXC( lbu t0, N(src), .Ll_exc_copy); \ | 688 | LOADBU(t0, N(src), .Ll_exc_copy\@); \ |
641 | SUB len, len, 1; \ | 689 | SUB len, len, 1; \ |
642 | EXC( sb t0, N(dst), .Ls_exc); \ | 690 | STOREB(t0, N(dst), .Ls_exc\@); \ |
643 | SLLV t0, t0, t3; \ | 691 | SLLV t0, t0, t3; \ |
644 | addu t3, SHIFT_INC; \ | 692 | addu t3, SHIFT_INC; \ |
645 | beqz len, .Lcopy_bytes_done; \ | 693 | beqz len, .Lcopy_bytes_done\@; \ |
646 | or t2, t0 | 694 | or t2, t0 |
647 | 695 | ||
648 | COPY_BYTE(0) | 696 | COPY_BYTE(0) |
@@ -653,14 +701,14 @@ EXC( sb t0, N(dst), .Ls_exc); \ | |||
653 | COPY_BYTE(4) | 701 | COPY_BYTE(4) |
654 | COPY_BYTE(5) | 702 | COPY_BYTE(5) |
655 | #endif | 703 | #endif |
656 | EXC( lbu t0, NBYTES-2(src), .Ll_exc_copy) | 704 | LOADBU(t0, NBYTES-2(src), .Ll_exc_copy\@) |
657 | SUB len, len, 1 | 705 | SUB len, len, 1 |
658 | EXC( sb t0, NBYTES-2(dst), .Ls_exc) | 706 | STOREB(t0, NBYTES-2(dst), .Ls_exc\@) |
659 | SLLV t0, t0, t3 | 707 | SLLV t0, t0, t3 |
660 | or t2, t0 | 708 | or t2, t0 |
661 | .Lcopy_bytes_done: | 709 | .Lcopy_bytes_done\@: |
662 | ADDC(sum, t2) | 710 | ADDC(sum, t2) |
663 | .Ldone: | 711 | .Ldone\@: |
664 | /* fold checksum */ | 712 | /* fold checksum */ |
665 | #ifdef USE_DOUBLE | 713 | #ifdef USE_DOUBLE |
666 | dsll32 v1, sum, 0 | 714 | dsll32 v1, sum, 0 |
@@ -689,7 +737,7 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc) | |||
689 | jr ra | 737 | jr ra |
690 | .set noreorder | 738 | .set noreorder |
691 | 739 | ||
692 | .Ll_exc_copy: | 740 | .Ll_exc_copy\@: |
693 | /* | 741 | /* |
694 | * Copy bytes from src until faulting load address (or until a | 742 | * Copy bytes from src until faulting load address (or until a |
695 | * lb faults) | 743 | * lb faults) |
@@ -700,11 +748,11 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc) | |||
700 | * | 748 | * |
701 | * Assumes src < THREAD_BUADDR($28) | 749 | * Assumes src < THREAD_BUADDR($28) |
702 | */ | 750 | */ |
703 | LOAD t0, TI_TASK($28) | 751 | LOADK t0, TI_TASK($28) |
704 | li t2, SHIFT_START | 752 | li t2, SHIFT_START |
705 | LOAD t0, THREAD_BUADDR(t0) | 753 | LOADK t0, THREAD_BUADDR(t0) |
706 | 1: | 754 | 1: |
707 | EXC( lbu t1, 0(src), .Ll_exc) | 755 | LOADBU(t1, 0(src), .Ll_exc\@) |
708 | ADD src, src, 1 | 756 | ADD src, src, 1 |
709 | sb t1, 0(dst) # can't fault -- we're copy_from_user | 757 | sb t1, 0(dst) # can't fault -- we're copy_from_user |
710 | SLLV t1, t1, t2 | 758 | SLLV t1, t1, t2 |
@@ -714,10 +762,10 @@ EXC( lbu t1, 0(src), .Ll_exc) | |||
714 | ADD dst, dst, 1 | 762 | ADD dst, dst, 1 |
715 | bne src, t0, 1b | 763 | bne src, t0, 1b |
716 | .set noreorder | 764 | .set noreorder |
717 | .Ll_exc: | 765 | .Ll_exc\@: |
718 | LOAD t0, TI_TASK($28) | 766 | LOADK t0, TI_TASK($28) |
719 | nop | 767 | nop |
720 | LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address | 768 | LOADK t0, THREAD_BUADDR(t0) # t0 is just past last good address |
721 | nop | 769 | nop |
722 | SUB len, AT, t0 # len number of uncopied bytes | 770 | SUB len, AT, t0 # len number of uncopied bytes |
723 | /* | 771 | /* |
@@ -733,7 +781,7 @@ EXC( lbu t1, 0(src), .Ll_exc) | |||
733 | */ | 781 | */ |
734 | .set reorder /* DADDI_WAR */ | 782 | .set reorder /* DADDI_WAR */ |
735 | SUB src, len, 1 | 783 | SUB src, len, 1 |
736 | beqz len, .Ldone | 784 | beqz len, .Ldone\@ |
737 | .set noreorder | 785 | .set noreorder |
738 | 1: sb zero, 0(dst) | 786 | 1: sb zero, 0(dst) |
739 | ADD dst, dst, 1 | 787 | ADD dst, dst, 1 |
@@ -748,13 +796,31 @@ EXC( lbu t1, 0(src), .Ll_exc) | |||
748 | SUB src, src, v1 | 796 | SUB src, src, v1 |
749 | #endif | 797 | #endif |
750 | li v1, -EFAULT | 798 | li v1, -EFAULT |
751 | b .Ldone | 799 | b .Ldone\@ |
752 | sw v1, (errptr) | 800 | sw v1, (errptr) |
753 | 801 | ||
754 | .Ls_exc: | 802 | .Ls_exc\@: |
755 | li v0, -1 /* invalid checksum */ | 803 | li v0, -1 /* invalid checksum */ |
756 | li v1, -EFAULT | 804 | li v1, -EFAULT |
757 | jr ra | 805 | jr ra |
758 | sw v1, (errptr) | 806 | sw v1, (errptr) |
759 | .set pop | 807 | .set pop |
760 | END(__csum_partial_copy_user) | 808 | .endm |
809 | |||
810 | LEAF(__csum_partial_copy_kernel) | ||
811 | #ifndef CONFIG_EVA | ||
812 | FEXPORT(__csum_partial_copy_to_user) | ||
813 | FEXPORT(__csum_partial_copy_from_user) | ||
814 | #endif | ||
815 | __BUILD_CSUM_PARTIAL_COPY_USER LEGACY_MODE USEROP USEROP 1 | ||
816 | END(__csum_partial_copy_kernel) | ||
817 | |||
818 | #ifdef CONFIG_EVA | ||
819 | LEAF(__csum_partial_copy_to_user) | ||
820 | __BUILD_CSUM_PARTIAL_COPY_USER EVA_MODE KERNELOP USEROP 0 | ||
821 | END(__csum_partial_copy_to_user) | ||
822 | |||
823 | LEAF(__csum_partial_copy_from_user) | ||
824 | __BUILD_CSUM_PARTIAL_COPY_USER EVA_MODE USEROP KERNELOP 0 | ||
825 | END(__csum_partial_copy_from_user) | ||
826 | #endif | ||