aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/branch.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/branch.c')
-rw-r--r--arch/mips/kernel/branch.c288
1 files changed, 250 insertions, 38 deletions
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 4d7d99d601cc..c2e0f45ddf6c 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -16,6 +16,7 @@
16#include <asm/fpu.h> 16#include <asm/fpu.h>
17#include <asm/fpu_emulator.h> 17#include <asm/fpu_emulator.h>
18#include <asm/inst.h> 18#include <asm/inst.h>
19#include <asm/mips-r2-to-r6-emul.h>
19#include <asm/ptrace.h> 20#include <asm/ptrace.h>
20#include <asm/uaccess.h> 21#include <asm/uaccess.h>
21 22
@@ -399,11 +400,21 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs)
399 * @returns: -EFAULT on error and forces SIGBUS, and on success 400 * @returns: -EFAULT on error and forces SIGBUS, and on success
400 * returns 0 or BRANCH_LIKELY_TAKEN as appropriate after 401 * returns 0 or BRANCH_LIKELY_TAKEN as appropriate after
401 * evaluating the branch. 402 * evaluating the branch.
403 *
404 * MIPS R6 Compact branches and forbidden slots:
405 * Compact branches do not throw exceptions because they do
406 * not have delay slots. The forbidden slot instruction ($PC+4)
407 * is only executed if the branch was not taken. Otherwise the
408 * forbidden slot is skipped entirely. This means that the
409 * only possible reason to be here because of a MIPS R6 compact
410 * branch instruction is that the forbidden slot has thrown one.
411 * In that case the branch was not taken, so the EPC can be safely
412 * set to EPC + 8.
402 */ 413 */
403int __compute_return_epc_for_insn(struct pt_regs *regs, 414int __compute_return_epc_for_insn(struct pt_regs *regs,
404 union mips_instruction insn) 415 union mips_instruction insn)
405{ 416{
406 unsigned int bit, fcr31, dspcontrol; 417 unsigned int bit, fcr31, dspcontrol, reg;
407 long epc = regs->cp0_epc; 418 long epc = regs->cp0_epc;
408 int ret = 0; 419 int ret = 0;
409 420
@@ -417,6 +428,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
417 regs->regs[insn.r_format.rd] = epc + 8; 428 regs->regs[insn.r_format.rd] = epc + 8;
418 /* Fall through */ 429 /* Fall through */
419 case jr_op: 430 case jr_op:
431 if (NO_R6EMU && insn.r_format.func == jr_op)
432 goto sigill_r6;
420 regs->cp0_epc = regs->regs[insn.r_format.rs]; 433 regs->cp0_epc = regs->regs[insn.r_format.rs];
421 break; 434 break;
422 } 435 }
@@ -429,8 +442,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
429 */ 442 */
430 case bcond_op: 443 case bcond_op:
431 switch (insn.i_format.rt) { 444 switch (insn.i_format.rt) {
432 case bltz_op:
433 case bltzl_op: 445 case bltzl_op:
446 if (NO_R6EMU)
447 goto sigill_r6;
448 case bltz_op:
434 if ((long)regs->regs[insn.i_format.rs] < 0) { 449 if ((long)regs->regs[insn.i_format.rs] < 0) {
435 epc = epc + 4 + (insn.i_format.simmediate << 2); 450 epc = epc + 4 + (insn.i_format.simmediate << 2);
436 if (insn.i_format.rt == bltzl_op) 451 if (insn.i_format.rt == bltzl_op)
@@ -440,8 +455,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
440 regs->cp0_epc = epc; 455 regs->cp0_epc = epc;
441 break; 456 break;
442 457
443 case bgez_op:
444 case bgezl_op: 458 case bgezl_op:
459 if (NO_R6EMU)
460 goto sigill_r6;
461 case bgez_op:
445 if ((long)regs->regs[insn.i_format.rs] >= 0) { 462 if ((long)regs->regs[insn.i_format.rs] >= 0) {
446 epc = epc + 4 + (insn.i_format.simmediate << 2); 463 epc = epc + 4 + (insn.i_format.simmediate << 2);
447 if (insn.i_format.rt == bgezl_op) 464 if (insn.i_format.rt == bgezl_op)
@@ -453,7 +470,29 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
453 470
454 case bltzal_op: 471 case bltzal_op:
455 case bltzall_op: 472 case bltzall_op:
473 if (NO_R6EMU && (insn.i_format.rs ||
474 insn.i_format.rt == bltzall_op)) {
475 ret = -SIGILL;
476 break;
477 }
456 regs->regs[31] = epc + 8; 478 regs->regs[31] = epc + 8;
479 /*
480 * OK we are here either because we hit a NAL
481 * instruction or because we are emulating an
482 * old bltzal{,l} one. Lets figure out what the
483 * case really is.
484 */
485 if (!insn.i_format.rs) {
486 /*
487 * NAL or BLTZAL with rs == 0
488 * Doesn't matter if we are R6 or not. The
489 * result is the same
490 */
491 regs->cp0_epc += 4 +
492 (insn.i_format.simmediate << 2);
493 break;
494 }
495 /* Now do the real thing for non-R6 BLTZAL{,L} */
457 if ((long)regs->regs[insn.i_format.rs] < 0) { 496 if ((long)regs->regs[insn.i_format.rs] < 0) {
458 epc = epc + 4 + (insn.i_format.simmediate << 2); 497 epc = epc + 4 + (insn.i_format.simmediate << 2);
459 if (insn.i_format.rt == bltzall_op) 498 if (insn.i_format.rt == bltzall_op)
@@ -465,7 +504,29 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
465 504
466 case bgezal_op: 505 case bgezal_op:
467 case bgezall_op: 506 case bgezall_op:
507 if (NO_R6EMU && (insn.i_format.rs ||
508 insn.i_format.rt == bgezall_op)) {
509 ret = -SIGILL;
510 break;
511 }
468 regs->regs[31] = epc + 8; 512 regs->regs[31] = epc + 8;
513 /*
514 * OK we are here either because we hit a BAL
515 * instruction or because we are emulating an
516 * old bgezal{,l} one. Lets figure out what the
517 * case really is.
518 */
519 if (!insn.i_format.rs) {
520 /*
521 * BAL or BGEZAL with rs == 0
522 * Doesn't matter if we are R6 or not. The
523 * result is the same
524 */
525 regs->cp0_epc += 4 +
526 (insn.i_format.simmediate << 2);
527 break;
528 }
529 /* Now do the real thing for non-R6 BGEZAL{,L} */
469 if ((long)regs->regs[insn.i_format.rs] >= 0) { 530 if ((long)regs->regs[insn.i_format.rs] >= 0) {
470 epc = epc + 4 + (insn.i_format.simmediate << 2); 531 epc = epc + 4 + (insn.i_format.simmediate << 2);
471 if (insn.i_format.rt == bgezall_op) 532 if (insn.i_format.rt == bgezall_op)
@@ -477,7 +538,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
477 538
478 case bposge32_op: 539 case bposge32_op:
479 if (!cpu_has_dsp) 540 if (!cpu_has_dsp)
480 goto sigill; 541 goto sigill_dsp;
481 542
482 dspcontrol = rddsp(0x01); 543 dspcontrol = rddsp(0x01);
483 544
@@ -508,8 +569,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
508 /* 569 /*
509 * These are conditional and in i_format. 570 * These are conditional and in i_format.
510 */ 571 */
511 case beq_op:
512 case beql_op: 572 case beql_op:
573 if (NO_R6EMU)
574 goto sigill_r6;
575 case beq_op:
513 if (regs->regs[insn.i_format.rs] == 576 if (regs->regs[insn.i_format.rs] ==
514 regs->regs[insn.i_format.rt]) { 577 regs->regs[insn.i_format.rt]) {
515 epc = epc + 4 + (insn.i_format.simmediate << 2); 578 epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -520,8 +583,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
520 regs->cp0_epc = epc; 583 regs->cp0_epc = epc;
521 break; 584 break;
522 585
523 case bne_op:
524 case bnel_op: 586 case bnel_op:
587 if (NO_R6EMU)
588 goto sigill_r6;
589 case bne_op:
525 if (regs->regs[insn.i_format.rs] != 590 if (regs->regs[insn.i_format.rs] !=
526 regs->regs[insn.i_format.rt]) { 591 regs->regs[insn.i_format.rt]) {
527 epc = epc + 4 + (insn.i_format.simmediate << 2); 592 epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -532,8 +597,31 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
532 regs->cp0_epc = epc; 597 regs->cp0_epc = epc;
533 break; 598 break;
534 599
535 case blez_op: /* not really i_format */ 600 case blezl_op: /* not really i_format */
536 case blezl_op: 601 if (NO_R6EMU)
602 goto sigill_r6;
603 case blez_op:
604 /*
605 * Compact branches for R6 for the
606 * blez and blezl opcodes.
607 * BLEZ | rs = 0 | rt != 0 == BLEZALC
608 * BLEZ | rs = rt != 0 == BGEZALC
609 * BLEZ | rs != 0 | rt != 0 == BGEUC
610 * BLEZL | rs = 0 | rt != 0 == BLEZC
611 * BLEZL | rs = rt != 0 == BGEZC
612 * BLEZL | rs != 0 | rt != 0 == BGEC
613 *
614 * For real BLEZ{,L}, rt is always 0.
615 */
616
617 if (cpu_has_mips_r6 && insn.i_format.rt) {
618 if ((insn.i_format.opcode == blez_op) &&
619 ((!insn.i_format.rs && insn.i_format.rt) ||
620 (insn.i_format.rs == insn.i_format.rt)))
621 regs->regs[31] = epc + 4;
622 regs->cp0_epc += 8;
623 break;
624 }
537 /* rt field assumed to be zero */ 625 /* rt field assumed to be zero */
538 if ((long)regs->regs[insn.i_format.rs] <= 0) { 626 if ((long)regs->regs[insn.i_format.rs] <= 0) {
539 epc = epc + 4 + (insn.i_format.simmediate << 2); 627 epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -544,8 +632,32 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
544 regs->cp0_epc = epc; 632 regs->cp0_epc = epc;
545 break; 633 break;
546 634
547 case bgtz_op:
548 case bgtzl_op: 635 case bgtzl_op:
636 if (NO_R6EMU)
637 goto sigill_r6;
638 case bgtz_op:
639 /*
640 * Compact branches for R6 for the
641 * bgtz and bgtzl opcodes.
642 * BGTZ | rs = 0 | rt != 0 == BGTZALC
643 * BGTZ | rs = rt != 0 == BLTZALC
644 * BGTZ | rs != 0 | rt != 0 == BLTUC
645 * BGTZL | rs = 0 | rt != 0 == BGTZC
646 * BGTZL | rs = rt != 0 == BLTZC
647 * BGTZL | rs != 0 | rt != 0 == BLTC
648 *
649 * *ZALC varint for BGTZ &&& rt != 0
650 * For real GTZ{,L}, rt is always 0.
651 */
652 if (cpu_has_mips_r6 && insn.i_format.rt) {
653 if ((insn.i_format.opcode == blez_op) &&
654 ((!insn.i_format.rs && insn.i_format.rt) ||
655 (insn.i_format.rs == insn.i_format.rt)))
656 regs->regs[31] = epc + 4;
657 regs->cp0_epc += 8;
658 break;
659 }
660
549 /* rt field assumed to be zero */ 661 /* rt field assumed to be zero */
550 if ((long)regs->regs[insn.i_format.rs] > 0) { 662 if ((long)regs->regs[insn.i_format.rs] > 0) {
551 epc = epc + 4 + (insn.i_format.simmediate << 2); 663 epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -560,40 +672,83 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
560 * And now the FPA/cp1 branch instructions. 672 * And now the FPA/cp1 branch instructions.
561 */ 673 */
562 case cop1_op: 674 case cop1_op:
563 preempt_disable(); 675 if (cpu_has_mips_r6 &&
564 if (is_fpu_owner()) 676 ((insn.i_format.rs == bc1eqz_op) ||
565 fcr31 = read_32bit_cp1_register(CP1_STATUS); 677 (insn.i_format.rs == bc1nez_op))) {
566 else 678 if (!used_math()) { /* First time FPU user */
567 fcr31 = current->thread.fpu.fcr31; 679 ret = init_fpu();
568 preempt_enable(); 680 if (ret && NO_R6EMU) {
569 681 ret = -ret;
570 bit = (insn.i_format.rt >> 2); 682 break;
571 bit += (bit != 0); 683 }
572 bit += 23; 684 ret = 0;
573 switch (insn.i_format.rt & 3) { 685 set_used_math();
574 case 0: /* bc1f */ 686 }
575 case 2: /* bc1fl */ 687 lose_fpu(1); /* Save FPU state for the emulator. */
576 if (~fcr31 & (1 << bit)) { 688 reg = insn.i_format.rt;
577 epc = epc + 4 + (insn.i_format.simmediate << 2); 689 bit = 0;
578 if (insn.i_format.rt == 2) 690 switch (insn.i_format.rs) {
579 ret = BRANCH_LIKELY_TAKEN; 691 case bc1eqz_op:
580 } else 692 /* Test bit 0 */
693 if (get_fpr32(&current->thread.fpu.fpr[reg], 0)
694 & 0x1)
695 bit = 1;
696 break;
697 case bc1nez_op:
698 /* Test bit 0 */
699 if (!(get_fpr32(&current->thread.fpu.fpr[reg], 0)
700 & 0x1))
701 bit = 1;
702 break;
703 }
704 own_fpu(1);
705 if (bit)
706 epc = epc + 4 +
707 (insn.i_format.simmediate << 2);
708 else
581 epc += 8; 709 epc += 8;
582 regs->cp0_epc = epc; 710 regs->cp0_epc = epc;
711
583 break; 712 break;
713 } else {
584 714
585 case 1: /* bc1t */ 715 preempt_disable();
586 case 3: /* bc1tl */ 716 if (is_fpu_owner())
587 if (fcr31 & (1 << bit)) { 717 fcr31 = read_32bit_cp1_register(CP1_STATUS);
588 epc = epc + 4 + (insn.i_format.simmediate << 2); 718 else
589 if (insn.i_format.rt == 3) 719 fcr31 = current->thread.fpu.fcr31;
590 ret = BRANCH_LIKELY_TAKEN; 720 preempt_enable();
591 } else 721
592 epc += 8; 722 bit = (insn.i_format.rt >> 2);
593 regs->cp0_epc = epc; 723 bit += (bit != 0);
724 bit += 23;
725 switch (insn.i_format.rt & 3) {
726 case 0: /* bc1f */
727 case 2: /* bc1fl */
728 if (~fcr31 & (1 << bit)) {
729 epc = epc + 4 +
730 (insn.i_format.simmediate << 2);
731 if (insn.i_format.rt == 2)
732 ret = BRANCH_LIKELY_TAKEN;
733 } else
734 epc += 8;
735 regs->cp0_epc = epc;
736 break;
737
738 case 1: /* bc1t */
739 case 3: /* bc1tl */
740 if (fcr31 & (1 << bit)) {
741 epc = epc + 4 +
742 (insn.i_format.simmediate << 2);
743 if (insn.i_format.rt == 3)
744 ret = BRANCH_LIKELY_TAKEN;
745 } else
746 epc += 8;
747 regs->cp0_epc = epc;
748 break;
749 }
594 break; 750 break;
595 } 751 }
596 break;
597#ifdef CONFIG_CPU_CAVIUM_OCTEON 752#ifdef CONFIG_CPU_CAVIUM_OCTEON
598 case lwc2_op: /* This is bbit0 on Octeon */ 753 case lwc2_op: /* This is bbit0 on Octeon */
599 if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) 754 if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
@@ -626,15 +781,72 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
626 epc += 8; 781 epc += 8;
627 regs->cp0_epc = epc; 782 regs->cp0_epc = epc;
628 break; 783 break;
784#else
785 case bc6_op:
786 /* Only valid for MIPS R6 */
787 if (!cpu_has_mips_r6) {
788 ret = -SIGILL;
789 break;
790 }
791 regs->cp0_epc += 8;
792 break;
793 case balc6_op:
794 if (!cpu_has_mips_r6) {
795 ret = -SIGILL;
796 break;
797 }
798 /* Compact branch: BALC */
799 regs->regs[31] = epc + 4;
800 epc += 4 + (insn.i_format.simmediate << 2);
801 regs->cp0_epc = epc;
802 break;
803 case beqzcjic_op:
804 if (!cpu_has_mips_r6) {
805 ret = -SIGILL;
806 break;
807 }
808 /* Compact branch: BEQZC || JIC */
809 regs->cp0_epc += 8;
810 break;
811 case bnezcjialc_op:
812 if (!cpu_has_mips_r6) {
813 ret = -SIGILL;
814 break;
815 }
816 /* Compact branch: BNEZC || JIALC */
817 if (insn.i_format.rs)
818 regs->regs[31] = epc + 4;
819 regs->cp0_epc += 8;
820 break;
629#endif 821#endif
822 case cbcond0_op:
823 case cbcond1_op:
824 /* Only valid for MIPS R6 */
825 if (!cpu_has_mips_r6) {
826 ret = -SIGILL;
827 break;
828 }
829 /*
830 * Compact branches:
831 * bovc, beqc, beqzalc, bnvc, bnec, bnezlac
832 */
833 if (insn.i_format.rt && !insn.i_format.rs)
834 regs->regs[31] = epc + 4;
835 regs->cp0_epc += 8;
836 break;
630 } 837 }
631 838
632 return ret; 839 return ret;
633 840
634sigill: 841sigill_dsp:
635 printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm); 842 printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm);
636 force_sig(SIGBUS, current); 843 force_sig(SIGBUS, current);
637 return -EFAULT; 844 return -EFAULT;
845sigill_r6:
846 pr_info("%s: R2 branch but r2-to-r6 emulator is not preset - sending SIGILL.\n",
847 current->comm);
848 force_sig(SIGILL, current);
849 return -EFAULT;
638} 850}
639EXPORT_SYMBOL_GPL(__compute_return_epc_for_insn); 851EXPORT_SYMBOL_GPL(__compute_return_epc_for_insn);
640 852