diff options
Diffstat (limited to 'arch/sparc64/kernel/entry.S')
-rw-r--r-- | arch/sparc64/kernel/entry.S | 602 |
1 files changed, 354 insertions, 248 deletions
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 88332f00094a..3e0badb820c5 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/visasm.h> | 21 | #include <asm/visasm.h> |
22 | #include <asm/estate.h> | 22 | #include <asm/estate.h> |
23 | #include <asm/auxio.h> | 23 | #include <asm/auxio.h> |
24 | #include <asm/sfafsr.h> | ||
24 | 25 | ||
25 | #define curptr g6 | 26 | #define curptr g6 |
26 | 27 | ||
@@ -690,14 +691,159 @@ netbsd_syscall: | |||
690 | retl | 691 | retl |
691 | nop | 692 | nop |
692 | 693 | ||
693 | /* These next few routines must be sure to clear the | 694 | /* We need to carefully read the error status, ACK |
694 | * SFSR FaultValid bit so that the fast tlb data protection | 695 | * the errors, prevent recursive traps, and pass the |
695 | * handler does not flush the wrong context and lock up the | 696 | * information on to C code for logging. |
696 | * box. | 697 | * |
698 | * We pass the AFAR in as-is, and we encode the status | ||
699 | * information as described in asm-sparc64/sfafsr.h | ||
700 | */ | ||
701 | .globl __spitfire_access_error | ||
702 | __spitfire_access_error: | ||
703 | /* Disable ESTATE error reporting so that we do not | ||
704 | * take recursive traps and RED state the processor. | ||
705 | */ | ||
706 | stxa %g0, [%g0] ASI_ESTATE_ERROR_EN | ||
707 | membar #Sync | ||
708 | |||
709 | mov UDBE_UE, %g1 | ||
710 | ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR | ||
711 | |||
712 | /* __spitfire_cee_trap branches here with AFSR in %g4 and | ||
713 | * UDBE_CE in %g1. It only clears ESTATE_ERR_CE in the | ||
714 | * ESTATE Error Enable register. | ||
715 | */ | ||
716 | __spitfire_cee_trap_continue: | ||
717 | ldxa [%g0] ASI_AFAR, %g5 ! Get AFAR | ||
718 | |||
719 | rdpr %tt, %g3 | ||
720 | and %g3, 0x1ff, %g3 ! Paranoia | ||
721 | sllx %g3, SFSTAT_TRAP_TYPE_SHIFT, %g3 | ||
722 | or %g4, %g3, %g4 | ||
723 | rdpr %tl, %g3 | ||
724 | cmp %g3, 1 | ||
725 | mov 1, %g3 | ||
726 | bleu %xcc, 1f | ||
727 | sllx %g3, SFSTAT_TL_GT_ONE_SHIFT, %g3 | ||
728 | |||
729 | or %g4, %g3, %g4 | ||
730 | |||
731 | /* Read in the UDB error register state, clearing the | ||
732 | * sticky error bits as-needed. We only clear them if | ||
733 | * the UE bit is set. Likewise, __spitfire_cee_trap | ||
734 | * below will only do so if the CE bit is set. | ||
735 | * | ||
736 | * NOTE: UltraSparc-I/II have high and low UDB error | ||
737 | * registers, corresponding to the two UDB units | ||
738 | * present on those chips. UltraSparc-IIi only | ||
739 | * has a single UDB, called "SDB" in the manual. | ||
740 | * For IIi the upper UDB register always reads | ||
741 | * as zero so for our purposes things will just | ||
742 | * work with the checks below. | ||
697 | */ | 743 | */ |
698 | .globl __do_data_access_exception | 744 | 1: ldxa [%g0] ASI_UDBH_ERROR_R, %g3 |
699 | .globl __do_data_access_exception_tl1 | 745 | and %g3, 0x3ff, %g7 ! Paranoia |
700 | __do_data_access_exception_tl1: | 746 | sllx %g7, SFSTAT_UDBH_SHIFT, %g7 |
747 | or %g4, %g7, %g4 | ||
748 | andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE | ||
749 | be,pn %xcc, 1f | ||
750 | nop | ||
751 | stxa %g3, [%g0] ASI_UDB_ERROR_W | ||
752 | membar #Sync | ||
753 | |||
754 | 1: mov 0x18, %g3 | ||
755 | ldxa [%g3] ASI_UDBL_ERROR_R, %g3 | ||
756 | and %g3, 0x3ff, %g7 ! Paranoia | ||
757 | sllx %g7, SFSTAT_UDBL_SHIFT, %g7 | ||
758 | or %g4, %g7, %g4 | ||
759 | andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE | ||
760 | be,pn %xcc, 1f | ||
761 | nop | ||
762 | mov 0x18, %g7 | ||
763 | stxa %g3, [%g7] ASI_UDB_ERROR_W | ||
764 | membar #Sync | ||
765 | |||
766 | 1: /* Ok, now that we've latched the error state, | ||
767 | * clear the sticky bits in the AFSR. | ||
768 | */ | ||
769 | stxa %g4, [%g0] ASI_AFSR | ||
770 | membar #Sync | ||
771 | |||
772 | rdpr %tl, %g2 | ||
773 | cmp %g2, 1 | ||
774 | rdpr %pil, %g2 | ||
775 | bleu,pt %xcc, 1f | ||
776 | wrpr %g0, 15, %pil | ||
777 | |||
778 | ba,pt %xcc, etraptl1 | ||
779 | rd %pc, %g7 | ||
780 | |||
781 | ba,pt %xcc, 2f | ||
782 | nop | ||
783 | |||
784 | 1: ba,pt %xcc, etrap_irq | ||
785 | rd %pc, %g7 | ||
786 | |||
787 | 2: mov %l4, %o1 | ||
788 | mov %l5, %o2 | ||
789 | call spitfire_access_error | ||
790 | add %sp, PTREGS_OFF, %o0 | ||
791 | ba,pt %xcc, rtrap | ||
792 | clr %l6 | ||
793 | |||
794 | /* This is the trap handler entry point for ECC correctable | ||
795 | * errors. They are corrected, but we listen for the trap | ||
796 | * so that the event can be logged. | ||
797 | * | ||
798 | * Disrupting errors are either: | ||
799 | * 1) single-bit ECC errors during UDB reads to system | ||
800 | * memory | ||
801 | * 2) data parity errors during write-back events | ||
802 | * | ||
803 | * As far as I can make out from the manual, the CEE trap | ||
804 | * is only for correctable errors during memory read | ||
805 | * accesses by the front-end of the processor. | ||
806 | * | ||
807 | * The code below is only for trap level 1 CEE events, | ||
808 | * as it is the only situation where we can safely record | ||
809 | * and log. For trap level >1 we just clear the CE bit | ||
810 | * in the AFSR and return. | ||
811 | * | ||
812 | * This is just like __spiftire_access_error above, but it | ||
813 | * specifically handles correctable errors. If an | ||
814 | * uncorrectable error is indicated in the AFSR we | ||
815 | * will branch directly above to __spitfire_access_error | ||
816 | * to handle it instead. Uncorrectable therefore takes | ||
817 | * priority over correctable, and the error logging | ||
818 | * C code will notice this case by inspecting the | ||
819 | * trap type. | ||
820 | */ | ||
821 | .globl __spitfire_cee_trap | ||
822 | __spitfire_cee_trap: | ||
823 | ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR | ||
824 | mov 1, %g3 | ||
825 | sllx %g3, SFAFSR_UE_SHIFT, %g3 | ||
826 | andcc %g4, %g3, %g0 ! Check for UE | ||
827 | bne,pn %xcc, __spitfire_access_error | ||
828 | nop | ||
829 | |||
830 | /* Ok, in this case we only have a correctable error. | ||
831 | * Indicate we only wish to capture that state in register | ||
832 | * %g1, and we only disable CE error reporting unlike UE | ||
833 | * handling which disables all errors. | ||
834 | */ | ||
835 | ldxa [%g0] ASI_ESTATE_ERROR_EN, %g3 | ||
836 | andn %g3, ESTATE_ERR_CE, %g3 | ||
837 | stxa %g3, [%g0] ASI_ESTATE_ERROR_EN | ||
838 | membar #Sync | ||
839 | |||
840 | /* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */ | ||
841 | ba,pt %xcc, __spitfire_cee_trap_continue | ||
842 | mov UDBE_CE, %g1 | ||
843 | |||
844 | .globl __spitfire_data_access_exception | ||
845 | .globl __spitfire_data_access_exception_tl1 | ||
846 | __spitfire_data_access_exception_tl1: | ||
701 | rdpr %pstate, %g4 | 847 | rdpr %pstate, %g4 |
702 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate | 848 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate |
703 | mov TLB_SFSR, %g3 | 849 | mov TLB_SFSR, %g3 |
@@ -706,9 +852,25 @@ __do_data_access_exception_tl1: | |||
706 | ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR | 852 | ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR |
707 | stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit | 853 | stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit |
708 | membar #Sync | 854 | membar #Sync |
855 | rdpr %tt, %g3 | ||
856 | cmp %g3, 0x80 ! first win spill/fill trap | ||
857 | blu,pn %xcc, 1f | ||
858 | cmp %g3, 0xff ! last win spill/fill trap | ||
859 | bgu,pn %xcc, 1f | ||
860 | nop | ||
709 | ba,pt %xcc, winfix_dax | 861 | ba,pt %xcc, winfix_dax |
710 | rdpr %tpc, %g3 | 862 | rdpr %tpc, %g3 |
711 | __do_data_access_exception: | 863 | 1: sethi %hi(109f), %g7 |
864 | ba,pt %xcc, etraptl1 | ||
865 | 109: or %g7, %lo(109b), %g7 | ||
866 | mov %l4, %o1 | ||
867 | mov %l5, %o2 | ||
868 | call spitfire_data_access_exception_tl1 | ||
869 | add %sp, PTREGS_OFF, %o0 | ||
870 | ba,pt %xcc, rtrap | ||
871 | clr %l6 | ||
872 | |||
873 | __spitfire_data_access_exception: | ||
712 | rdpr %pstate, %g4 | 874 | rdpr %pstate, %g4 |
713 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate | 875 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate |
714 | mov TLB_SFSR, %g3 | 876 | mov TLB_SFSR, %g3 |
@@ -722,20 +884,19 @@ __do_data_access_exception: | |||
722 | 109: or %g7, %lo(109b), %g7 | 884 | 109: or %g7, %lo(109b), %g7 |
723 | mov %l4, %o1 | 885 | mov %l4, %o1 |
724 | mov %l5, %o2 | 886 | mov %l5, %o2 |
725 | call data_access_exception | 887 | call spitfire_data_access_exception |
726 | add %sp, PTREGS_OFF, %o0 | 888 | add %sp, PTREGS_OFF, %o0 |
727 | ba,pt %xcc, rtrap | 889 | ba,pt %xcc, rtrap |
728 | clr %l6 | 890 | clr %l6 |
729 | 891 | ||
730 | .globl __do_instruction_access_exception | 892 | .globl __spitfire_insn_access_exception |
731 | .globl __do_instruction_access_exception_tl1 | 893 | .globl __spitfire_insn_access_exception_tl1 |
732 | __do_instruction_access_exception_tl1: | 894 | __spitfire_insn_access_exception_tl1: |
733 | rdpr %pstate, %g4 | 895 | rdpr %pstate, %g4 |
734 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate | 896 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate |
735 | mov TLB_SFSR, %g3 | 897 | mov TLB_SFSR, %g3 |
736 | mov DMMU_SFAR, %g5 | 898 | ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR |
737 | ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR | 899 | rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC |
738 | ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR | ||
739 | stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit | 900 | stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit |
740 | membar #Sync | 901 | membar #Sync |
741 | sethi %hi(109f), %g7 | 902 | sethi %hi(109f), %g7 |
@@ -743,18 +904,17 @@ __do_instruction_access_exception_tl1: | |||
743 | 109: or %g7, %lo(109b), %g7 | 904 | 109: or %g7, %lo(109b), %g7 |
744 | mov %l4, %o1 | 905 | mov %l4, %o1 |
745 | mov %l5, %o2 | 906 | mov %l5, %o2 |
746 | call instruction_access_exception_tl1 | 907 | call spitfire_insn_access_exception_tl1 |
747 | add %sp, PTREGS_OFF, %o0 | 908 | add %sp, PTREGS_OFF, %o0 |
748 | ba,pt %xcc, rtrap | 909 | ba,pt %xcc, rtrap |
749 | clr %l6 | 910 | clr %l6 |
750 | 911 | ||
751 | __do_instruction_access_exception: | 912 | __spitfire_insn_access_exception: |
752 | rdpr %pstate, %g4 | 913 | rdpr %pstate, %g4 |
753 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate | 914 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate |
754 | mov TLB_SFSR, %g3 | 915 | mov TLB_SFSR, %g3 |
755 | mov DMMU_SFAR, %g5 | 916 | ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR |
756 | ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR | 917 | rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC |
757 | ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR | ||
758 | stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit | 918 | stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit |
759 | membar #Sync | 919 | membar #Sync |
760 | sethi %hi(109f), %g7 | 920 | sethi %hi(109f), %g7 |
@@ -762,235 +922,11 @@ __do_instruction_access_exception: | |||
762 | 109: or %g7, %lo(109b), %g7 | 922 | 109: or %g7, %lo(109b), %g7 |
763 | mov %l4, %o1 | 923 | mov %l4, %o1 |
764 | mov %l5, %o2 | 924 | mov %l5, %o2 |
765 | call instruction_access_exception | 925 | call spitfire_insn_access_exception |
766 | add %sp, PTREGS_OFF, %o0 | 926 | add %sp, PTREGS_OFF, %o0 |
767 | ba,pt %xcc, rtrap | 927 | ba,pt %xcc, rtrap |
768 | clr %l6 | 928 | clr %l6 |
769 | 929 | ||
770 | /* This is the trap handler entry point for ECC correctable | ||
771 | * errors. They are corrected, but we listen for the trap | ||
772 | * so that the event can be logged. | ||
773 | * | ||
774 | * Disrupting errors are either: | ||
775 | * 1) single-bit ECC errors during UDB reads to system | ||
776 | * memory | ||
777 | * 2) data parity errors during write-back events | ||
778 | * | ||
779 | * As far as I can make out from the manual, the CEE trap | ||
780 | * is only for correctable errors during memory read | ||
781 | * accesses by the front-end of the processor. | ||
782 | * | ||
783 | * The code below is only for trap level 1 CEE events, | ||
784 | * as it is the only situation where we can safely record | ||
785 | * and log. For trap level >1 we just clear the CE bit | ||
786 | * in the AFSR and return. | ||
787 | */ | ||
788 | |||
789 | /* Our trap handling infrastructure allows us to preserve | ||
790 | * two 64-bit values during etrap for arguments to | ||
791 | * subsequent C code. Therefore we encode the information | ||
792 | * as follows: | ||
793 | * | ||
794 | * value 1) Full 64-bits of AFAR | ||
795 | * value 2) Low 33-bits of AFSR, then bits 33-->42 | ||
796 | * are UDBL error status and bits 43-->52 | ||
797 | * are UDBH error status | ||
798 | */ | ||
799 | .align 64 | ||
800 | .globl cee_trap | ||
801 | cee_trap: | ||
802 | ldxa [%g0] ASI_AFSR, %g1 ! Read AFSR | ||
803 | ldxa [%g0] ASI_AFAR, %g2 ! Read AFAR | ||
804 | sllx %g1, 31, %g1 ! Clear reserved bits | ||
805 | srlx %g1, 31, %g1 ! in AFSR | ||
806 | |||
807 | /* NOTE: UltraSparc-I/II have high and low UDB error | ||
808 | * registers, corresponding to the two UDB units | ||
809 | * present on those chips. UltraSparc-IIi only | ||
810 | * has a single UDB, called "SDB" in the manual. | ||
811 | * For IIi the upper UDB register always reads | ||
812 | * as zero so for our purposes things will just | ||
813 | * work with the checks below. | ||
814 | */ | ||
815 | ldxa [%g0] ASI_UDBL_ERROR_R, %g3 ! Read UDB-Low error status | ||
816 | andcc %g3, (1 << 8), %g4 ! Check CE bit | ||
817 | sllx %g3, (64 - 10), %g3 ! Clear reserved bits | ||
818 | srlx %g3, (64 - 10), %g3 ! in UDB-Low error status | ||
819 | |||
820 | sllx %g3, (33 + 0), %g3 ! Shift up to encoding area | ||
821 | or %g1, %g3, %g1 ! Or it in | ||
822 | be,pn %xcc, 1f ! Branch if CE bit was clear | ||
823 | nop | ||
824 | stxa %g4, [%g0] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBL | ||
825 | membar #Sync ! Synchronize ASI stores | ||
826 | 1: mov 0x18, %g5 ! Addr of UDB-High error status | ||
827 | ldxa [%g5] ASI_UDBH_ERROR_R, %g3 ! Read it | ||
828 | |||
829 | andcc %g3, (1 << 8), %g4 ! Check CE bit | ||
830 | sllx %g3, (64 - 10), %g3 ! Clear reserved bits | ||
831 | srlx %g3, (64 - 10), %g3 ! in UDB-High error status | ||
832 | sllx %g3, (33 + 10), %g3 ! Shift up to encoding area | ||
833 | or %g1, %g3, %g1 ! Or it in | ||
834 | be,pn %xcc, 1f ! Branch if CE bit was clear | ||
835 | nop | ||
836 | nop | ||
837 | |||
838 | stxa %g4, [%g5] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBH | ||
839 | membar #Sync ! Synchronize ASI stores | ||
840 | 1: mov 1, %g5 ! AFSR CE bit is | ||
841 | sllx %g5, 20, %g5 ! bit 20 | ||
842 | stxa %g5, [%g0] ASI_AFSR ! Clear CE sticky bit in AFSR | ||
843 | membar #Sync ! Synchronize ASI stores | ||
844 | sllx %g2, (64 - 41), %g2 ! Clear reserved bits | ||
845 | srlx %g2, (64 - 41), %g2 ! in latched AFAR | ||
846 | |||
847 | andn %g2, 0x0f, %g2 ! Finish resv bit clearing | ||
848 | mov %g1, %g4 ! Move AFSR+UDB* into save reg | ||
849 | mov %g2, %g5 ! Move AFAR into save reg | ||
850 | rdpr %pil, %g2 | ||
851 | wrpr %g0, 15, %pil | ||
852 | ba,pt %xcc, etrap_irq | ||
853 | rd %pc, %g7 | ||
854 | mov %l4, %o0 | ||
855 | |||
856 | mov %l5, %o1 | ||
857 | call cee_log | ||
858 | add %sp, PTREGS_OFF, %o2 | ||
859 | ba,a,pt %xcc, rtrap_irq | ||
860 | |||
861 | /* Capture I/D/E-cache state into per-cpu error scoreboard. | ||
862 | * | ||
863 | * %g1: (TL>=0) ? 1 : 0 | ||
864 | * %g2: scratch | ||
865 | * %g3: scratch | ||
866 | * %g4: AFSR | ||
867 | * %g5: AFAR | ||
868 | * %g6: current thread ptr | ||
869 | * %g7: scratch | ||
870 | */ | ||
871 | #define CHEETAH_LOG_ERROR \ | ||
872 | /* Put "TL1" software bit into AFSR. */ \ | ||
873 | and %g1, 0x1, %g1; \ | ||
874 | sllx %g1, 63, %g2; \ | ||
875 | or %g4, %g2, %g4; \ | ||
876 | /* Get log entry pointer for this cpu at this trap level. */ \ | ||
877 | BRANCH_IF_JALAPENO(g2,g3,50f) \ | ||
878 | ldxa [%g0] ASI_SAFARI_CONFIG, %g2; \ | ||
879 | srlx %g2, 17, %g2; \ | ||
880 | ba,pt %xcc, 60f; \ | ||
881 | and %g2, 0x3ff, %g2; \ | ||
882 | 50: ldxa [%g0] ASI_JBUS_CONFIG, %g2; \ | ||
883 | srlx %g2, 17, %g2; \ | ||
884 | and %g2, 0x1f, %g2; \ | ||
885 | 60: sllx %g2, 9, %g2; \ | ||
886 | sethi %hi(cheetah_error_log), %g3; \ | ||
887 | ldx [%g3 + %lo(cheetah_error_log)], %g3; \ | ||
888 | brz,pn %g3, 80f; \ | ||
889 | nop; \ | ||
890 | add %g3, %g2, %g3; \ | ||
891 | sllx %g1, 8, %g1; \ | ||
892 | add %g3, %g1, %g1; \ | ||
893 | /* %g1 holds pointer to the top of the logging scoreboard */ \ | ||
894 | ldx [%g1 + 0x0], %g7; \ | ||
895 | cmp %g7, -1; \ | ||
896 | bne,pn %xcc, 80f; \ | ||
897 | nop; \ | ||
898 | stx %g4, [%g1 + 0x0]; \ | ||
899 | stx %g5, [%g1 + 0x8]; \ | ||
900 | add %g1, 0x10, %g1; \ | ||
901 | /* %g1 now points to D-cache logging area */ \ | ||
902 | set 0x3ff8, %g2; /* DC_addr mask */ \ | ||
903 | and %g5, %g2, %g2; /* DC_addr bits of AFAR */ \ | ||
904 | srlx %g5, 12, %g3; \ | ||
905 | or %g3, 1, %g3; /* PHYS tag + valid */ \ | ||
906 | 10: ldxa [%g2] ASI_DCACHE_TAG, %g7; \ | ||
907 | cmp %g3, %g7; /* TAG match? */ \ | ||
908 | bne,pt %xcc, 13f; \ | ||
909 | nop; \ | ||
910 | /* Yep, what we want, capture state. */ \ | ||
911 | stx %g2, [%g1 + 0x20]; \ | ||
912 | stx %g7, [%g1 + 0x28]; \ | ||
913 | /* A membar Sync is required before and after utag access. */ \ | ||
914 | membar #Sync; \ | ||
915 | ldxa [%g2] ASI_DCACHE_UTAG, %g7; \ | ||
916 | membar #Sync; \ | ||
917 | stx %g7, [%g1 + 0x30]; \ | ||
918 | ldxa [%g2] ASI_DCACHE_SNOOP_TAG, %g7; \ | ||
919 | stx %g7, [%g1 + 0x38]; \ | ||
920 | clr %g3; \ | ||
921 | 12: ldxa [%g2 + %g3] ASI_DCACHE_DATA, %g7; \ | ||
922 | stx %g7, [%g1]; \ | ||
923 | add %g3, (1 << 5), %g3; \ | ||
924 | cmp %g3, (4 << 5); \ | ||
925 | bl,pt %xcc, 12b; \ | ||
926 | add %g1, 0x8, %g1; \ | ||
927 | ba,pt %xcc, 20f; \ | ||
928 | add %g1, 0x20, %g1; \ | ||
929 | 13: sethi %hi(1 << 14), %g7; \ | ||
930 | add %g2, %g7, %g2; \ | ||
931 | srlx %g2, 14, %g7; \ | ||
932 | cmp %g7, 4; \ | ||
933 | bl,pt %xcc, 10b; \ | ||
934 | nop; \ | ||
935 | add %g1, 0x40, %g1; \ | ||
936 | 20: /* %g1 now points to I-cache logging area */ \ | ||
937 | set 0x1fe0, %g2; /* IC_addr mask */ \ | ||
938 | and %g5, %g2, %g2; /* IC_addr bits of AFAR */ \ | ||
939 | sllx %g2, 1, %g2; /* IC_addr[13:6]==VA[12:5] */ \ | ||
940 | srlx %g5, (13 - 8), %g3; /* Make PTAG */ \ | ||
941 | andn %g3, 0xff, %g3; /* Mask off undefined bits */ \ | ||
942 | 21: ldxa [%g2] ASI_IC_TAG, %g7; \ | ||
943 | andn %g7, 0xff, %g7; \ | ||
944 | cmp %g3, %g7; \ | ||
945 | bne,pt %xcc, 23f; \ | ||
946 | nop; \ | ||
947 | /* Yep, what we want, capture state. */ \ | ||
948 | stx %g2, [%g1 + 0x40]; \ | ||
949 | stx %g7, [%g1 + 0x48]; \ | ||
950 | add %g2, (1 << 3), %g2; \ | ||
951 | ldxa [%g2] ASI_IC_TAG, %g7; \ | ||
952 | add %g2, (1 << 3), %g2; \ | ||
953 | stx %g7, [%g1 + 0x50]; \ | ||
954 | ldxa [%g2] ASI_IC_TAG, %g7; \ | ||
955 | add %g2, (1 << 3), %g2; \ | ||
956 | stx %g7, [%g1 + 0x60]; \ | ||
957 | ldxa [%g2] ASI_IC_TAG, %g7; \ | ||
958 | stx %g7, [%g1 + 0x68]; \ | ||
959 | sub %g2, (3 << 3), %g2; \ | ||
960 | ldxa [%g2] ASI_IC_STAG, %g7; \ | ||
961 | stx %g7, [%g1 + 0x58]; \ | ||
962 | clr %g3; \ | ||
963 | srlx %g2, 2, %g2; \ | ||
964 | 22: ldxa [%g2 + %g3] ASI_IC_INSTR, %g7; \ | ||
965 | stx %g7, [%g1]; \ | ||
966 | add %g3, (1 << 3), %g3; \ | ||
967 | cmp %g3, (8 << 3); \ | ||
968 | bl,pt %xcc, 22b; \ | ||
969 | add %g1, 0x8, %g1; \ | ||
970 | ba,pt %xcc, 30f; \ | ||
971 | add %g1, 0x30, %g1; \ | ||
972 | 23: sethi %hi(1 << 14), %g7; \ | ||
973 | add %g2, %g7, %g2; \ | ||
974 | srlx %g2, 14, %g7; \ | ||
975 | cmp %g7, 4; \ | ||
976 | bl,pt %xcc, 21b; \ | ||
977 | nop; \ | ||
978 | add %g1, 0x70, %g1; \ | ||
979 | 30: /* %g1 now points to E-cache logging area */ \ | ||
980 | andn %g5, (32 - 1), %g2; /* E-cache subblock */ \ | ||
981 | stx %g2, [%g1 + 0x20]; \ | ||
982 | ldxa [%g2] ASI_EC_TAG_DATA, %g7; \ | ||
983 | stx %g7, [%g1 + 0x28]; \ | ||
984 | ldxa [%g2] ASI_EC_R, %g0; \ | ||
985 | clr %g3; \ | ||
986 | 31: ldxa [%g3] ASI_EC_DATA, %g7; \ | ||
987 | stx %g7, [%g1 + %g3]; \ | ||
988 | add %g3, 0x8, %g3; \ | ||
989 | cmp %g3, 0x20; \ | ||
990 | bl,pt %xcc, 31b; \ | ||
991 | nop; \ | ||
992 | 80: /* DONE */ | ||
993 | |||
994 | /* These get patched into the trap table at boot time | 930 | /* These get patched into the trap table at boot time |
995 | * once we know we have a cheetah processor. | 931 | * once we know we have a cheetah processor. |
996 | */ | 932 | */ |
@@ -1227,6 +1163,170 @@ dcpe_icpe_tl1_common: | |||
1227 | membar #Sync | 1163 | membar #Sync |
1228 | retry | 1164 | retry |
1229 | 1165 | ||
1166 | /* Capture I/D/E-cache state into per-cpu error scoreboard. | ||
1167 | * | ||
1168 | * %g1: (TL>=0) ? 1 : 0 | ||
1169 | * %g2: scratch | ||
1170 | * %g3: scratch | ||
1171 | * %g4: AFSR | ||
1172 | * %g5: AFAR | ||
1173 | * %g6: current thread ptr | ||
1174 | * %g7: scratch | ||
1175 | */ | ||
1176 | __cheetah_log_error: | ||
1177 | /* Put "TL1" software bit into AFSR. */ | ||
1178 | and %g1, 0x1, %g1 | ||
1179 | sllx %g1, 63, %g2 | ||
1180 | or %g4, %g2, %g4 | ||
1181 | |||
1182 | /* Get log entry pointer for this cpu at this trap level. */ | ||
1183 | BRANCH_IF_JALAPENO(g2,g3,50f) | ||
1184 | ldxa [%g0] ASI_SAFARI_CONFIG, %g2 | ||
1185 | srlx %g2, 17, %g2 | ||
1186 | ba,pt %xcc, 60f | ||
1187 | and %g2, 0x3ff, %g2 | ||
1188 | |||
1189 | 50: ldxa [%g0] ASI_JBUS_CONFIG, %g2 | ||
1190 | srlx %g2, 17, %g2 | ||
1191 | and %g2, 0x1f, %g2 | ||
1192 | |||
1193 | 60: sllx %g2, 9, %g2 | ||
1194 | sethi %hi(cheetah_error_log), %g3 | ||
1195 | ldx [%g3 + %lo(cheetah_error_log)], %g3 | ||
1196 | brz,pn %g3, 80f | ||
1197 | nop | ||
1198 | |||
1199 | add %g3, %g2, %g3 | ||
1200 | sllx %g1, 8, %g1 | ||
1201 | add %g3, %g1, %g1 | ||
1202 | |||
1203 | /* %g1 holds pointer to the top of the logging scoreboard */ | ||
1204 | ldx [%g1 + 0x0], %g7 | ||
1205 | cmp %g7, -1 | ||
1206 | bne,pn %xcc, 80f | ||
1207 | nop | ||
1208 | |||
1209 | stx %g4, [%g1 + 0x0] | ||
1210 | stx %g5, [%g1 + 0x8] | ||
1211 | add %g1, 0x10, %g1 | ||
1212 | |||
1213 | /* %g1 now points to D-cache logging area */ | ||
1214 | set 0x3ff8, %g2 /* DC_addr mask */ | ||
1215 | and %g5, %g2, %g2 /* DC_addr bits of AFAR */ | ||
1216 | srlx %g5, 12, %g3 | ||
1217 | or %g3, 1, %g3 /* PHYS tag + valid */ | ||
1218 | |||
1219 | 10: ldxa [%g2] ASI_DCACHE_TAG, %g7 | ||
1220 | cmp %g3, %g7 /* TAG match? */ | ||
1221 | bne,pt %xcc, 13f | ||
1222 | nop | ||
1223 | |||
1224 | /* Yep, what we want, capture state. */ | ||
1225 | stx %g2, [%g1 + 0x20] | ||
1226 | stx %g7, [%g1 + 0x28] | ||
1227 | |||
1228 | /* A membar Sync is required before and after utag access. */ | ||
1229 | membar #Sync | ||
1230 | ldxa [%g2] ASI_DCACHE_UTAG, %g7 | ||
1231 | membar #Sync | ||
1232 | stx %g7, [%g1 + 0x30] | ||
1233 | ldxa [%g2] ASI_DCACHE_SNOOP_TAG, %g7 | ||
1234 | stx %g7, [%g1 + 0x38] | ||
1235 | clr %g3 | ||
1236 | |||
1237 | 12: ldxa [%g2 + %g3] ASI_DCACHE_DATA, %g7 | ||
1238 | stx %g7, [%g1] | ||
1239 | add %g3, (1 << 5), %g3 | ||
1240 | cmp %g3, (4 << 5) | ||
1241 | bl,pt %xcc, 12b | ||
1242 | add %g1, 0x8, %g1 | ||
1243 | |||
1244 | ba,pt %xcc, 20f | ||
1245 | add %g1, 0x20, %g1 | ||
1246 | |||
1247 | 13: sethi %hi(1 << 14), %g7 | ||
1248 | add %g2, %g7, %g2 | ||
1249 | srlx %g2, 14, %g7 | ||
1250 | cmp %g7, 4 | ||
1251 | bl,pt %xcc, 10b | ||
1252 | nop | ||
1253 | |||
1254 | add %g1, 0x40, %g1 | ||
1255 | |||
1256 | /* %g1 now points to I-cache logging area */ | ||
1257 | 20: set 0x1fe0, %g2 /* IC_addr mask */ | ||
1258 | and %g5, %g2, %g2 /* IC_addr bits of AFAR */ | ||
1259 | sllx %g2, 1, %g2 /* IC_addr[13:6]==VA[12:5] */ | ||
1260 | srlx %g5, (13 - 8), %g3 /* Make PTAG */ | ||
1261 | andn %g3, 0xff, %g3 /* Mask off undefined bits */ | ||
1262 | |||
1263 | 21: ldxa [%g2] ASI_IC_TAG, %g7 | ||
1264 | andn %g7, 0xff, %g7 | ||
1265 | cmp %g3, %g7 | ||
1266 | bne,pt %xcc, 23f | ||
1267 | nop | ||
1268 | |||
1269 | /* Yep, what we want, capture state. */ | ||
1270 | stx %g2, [%g1 + 0x40] | ||
1271 | stx %g7, [%g1 + 0x48] | ||
1272 | add %g2, (1 << 3), %g2 | ||
1273 | ldxa [%g2] ASI_IC_TAG, %g7 | ||
1274 | add %g2, (1 << 3), %g2 | ||
1275 | stx %g7, [%g1 + 0x50] | ||
1276 | ldxa [%g2] ASI_IC_TAG, %g7 | ||
1277 | add %g2, (1 << 3), %g2 | ||
1278 | stx %g7, [%g1 + 0x60] | ||
1279 | ldxa [%g2] ASI_IC_TAG, %g7 | ||
1280 | stx %g7, [%g1 + 0x68] | ||
1281 | sub %g2, (3 << 3), %g2 | ||
1282 | ldxa [%g2] ASI_IC_STAG, %g7 | ||
1283 | stx %g7, [%g1 + 0x58] | ||
1284 | clr %g3 | ||
1285 | srlx %g2, 2, %g2 | ||
1286 | |||
1287 | 22: ldxa [%g2 + %g3] ASI_IC_INSTR, %g7 | ||
1288 | stx %g7, [%g1] | ||
1289 | add %g3, (1 << 3), %g3 | ||
1290 | cmp %g3, (8 << 3) | ||
1291 | bl,pt %xcc, 22b | ||
1292 | add %g1, 0x8, %g1 | ||
1293 | |||
1294 | ba,pt %xcc, 30f | ||
1295 | add %g1, 0x30, %g1 | ||
1296 | |||
1297 | 23: sethi %hi(1 << 14), %g7 | ||
1298 | add %g2, %g7, %g2 | ||
1299 | srlx %g2, 14, %g7 | ||
1300 | cmp %g7, 4 | ||
1301 | bl,pt %xcc, 21b | ||
1302 | nop | ||
1303 | |||
1304 | add %g1, 0x70, %g1 | ||
1305 | |||
1306 | /* %g1 now points to E-cache logging area */ | ||
1307 | 30: andn %g5, (32 - 1), %g2 | ||
1308 | stx %g2, [%g1 + 0x20] | ||
1309 | ldxa [%g2] ASI_EC_TAG_DATA, %g7 | ||
1310 | stx %g7, [%g1 + 0x28] | ||
1311 | ldxa [%g2] ASI_EC_R, %g0 | ||
1312 | clr %g3 | ||
1313 | |||
1314 | 31: ldxa [%g3] ASI_EC_DATA, %g7 | ||
1315 | stx %g7, [%g1 + %g3] | ||
1316 | add %g3, 0x8, %g3 | ||
1317 | cmp %g3, 0x20 | ||
1318 | |||
1319 | bl,pt %xcc, 31b | ||
1320 | nop | ||
1321 | 80: | ||
1322 | rdpr %tt, %g2 | ||
1323 | cmp %g2, 0x70 | ||
1324 | be c_fast_ecc | ||
1325 | cmp %g2, 0x63 | ||
1326 | be c_cee | ||
1327 | nop | ||
1328 | ba,pt %xcc, c_deferred | ||
1329 | |||
1230 | /* Cheetah FECC trap handling, we get here from tl{0,1}_fecc | 1330 | /* Cheetah FECC trap handling, we get here from tl{0,1}_fecc |
1231 | * in the trap table. That code has done a memory barrier | 1331 | * in the trap table. That code has done a memory barrier |
1232 | * and has disabled both the I-cache and D-cache in the DCU | 1332 | * and has disabled both the I-cache and D-cache in the DCU |
@@ -1252,8 +1352,10 @@ cheetah_fast_ecc: | |||
1252 | stxa %g4, [%g0] ASI_AFSR | 1352 | stxa %g4, [%g0] ASI_AFSR |
1253 | membar #Sync | 1353 | membar #Sync |
1254 | 1354 | ||
1255 | CHEETAH_LOG_ERROR | 1355 | ba,pt %xcc, __cheetah_log_error |
1356 | nop | ||
1256 | 1357 | ||
1358 | c_fast_ecc: | ||
1257 | rdpr %pil, %g2 | 1359 | rdpr %pil, %g2 |
1258 | wrpr %g0, 15, %pil | 1360 | wrpr %g0, 15, %pil |
1259 | ba,pt %xcc, etrap_irq | 1361 | ba,pt %xcc, etrap_irq |
@@ -1278,8 +1380,10 @@ cheetah_cee: | |||
1278 | stxa %g4, [%g0] ASI_AFSR | 1380 | stxa %g4, [%g0] ASI_AFSR |
1279 | membar #Sync | 1381 | membar #Sync |
1280 | 1382 | ||
1281 | CHEETAH_LOG_ERROR | 1383 | ba,pt %xcc, __cheetah_log_error |
1384 | nop | ||
1282 | 1385 | ||
1386 | c_cee: | ||
1283 | rdpr %pil, %g2 | 1387 | rdpr %pil, %g2 |
1284 | wrpr %g0, 15, %pil | 1388 | wrpr %g0, 15, %pil |
1285 | ba,pt %xcc, etrap_irq | 1389 | ba,pt %xcc, etrap_irq |
@@ -1304,8 +1408,10 @@ cheetah_deferred_trap: | |||
1304 | stxa %g4, [%g0] ASI_AFSR | 1408 | stxa %g4, [%g0] ASI_AFSR |
1305 | membar #Sync | 1409 | membar #Sync |
1306 | 1410 | ||
1307 | CHEETAH_LOG_ERROR | 1411 | ba,pt %xcc, __cheetah_log_error |
1412 | nop | ||
1308 | 1413 | ||
1414 | c_deferred: | ||
1309 | rdpr %pil, %g2 | 1415 | rdpr %pil, %g2 |
1310 | wrpr %g0, 15, %pil | 1416 | wrpr %g0, 15, %pil |
1311 | ba,pt %xcc, etrap_irq | 1417 | ba,pt %xcc, etrap_irq |