aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/entry.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/entry.S')
-rw-r--r--arch/sparc64/kernel/entry.S266
1 files changed, 163 insertions, 103 deletions
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 214cd0ebe832..cecdc0a7521f 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,9 +691,159 @@ netbsd_syscall:
690 retl 691 retl
691 nop 692 nop
692 693
693 .globl __do_data_access_exception 694 /* We need to carefully read the error status, ACK
694 .globl __do_data_access_exception_tl1 695 * the errors, prevent recursive traps, and pass the
695__do_data_access_exception_tl1: 696 * information on to C code for logging.
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.
743 */
7441: ldxa [%g0] ASI_UDBH_ERROR_R, %g3
745 and %g3, 0x3ff, %g7 ! Paranoia
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
7541: 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
7661: /* 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
7841: ba,pt %xcc, etrap_irq
785 rd %pc, %g7
786
7872: 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:
696 rdpr %pstate, %g4 847 rdpr %pstate, %g4
697 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate 848 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
698 mov TLB_SFSR, %g3 849 mov TLB_SFSR, %g3
@@ -714,12 +865,12 @@ __do_data_access_exception_tl1:
714109: or %g7, %lo(109b), %g7 865109: or %g7, %lo(109b), %g7
715 mov %l4, %o1 866 mov %l4, %o1
716 mov %l5, %o2 867 mov %l5, %o2
717 call data_access_exception_tl1 868 call spitfire_data_access_exception_tl1
718 add %sp, PTREGS_OFF, %o0 869 add %sp, PTREGS_OFF, %o0
719 ba,pt %xcc, rtrap 870 ba,pt %xcc, rtrap
720 clr %l6 871 clr %l6
721 872
722__do_data_access_exception: 873__spitfire_data_access_exception:
723 rdpr %pstate, %g4 874 rdpr %pstate, %g4
724 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate 875 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
725 mov TLB_SFSR, %g3 876 mov TLB_SFSR, %g3
@@ -733,14 +884,14 @@ __do_data_access_exception:
733109: or %g7, %lo(109b), %g7 884109: or %g7, %lo(109b), %g7
734 mov %l4, %o1 885 mov %l4, %o1
735 mov %l5, %o2 886 mov %l5, %o2
736 call data_access_exception 887 call spitfire_data_access_exception
737 add %sp, PTREGS_OFF, %o0 888 add %sp, PTREGS_OFF, %o0
738 ba,pt %xcc, rtrap 889 ba,pt %xcc, rtrap
739 clr %l6 890 clr %l6
740 891
741 .globl __do_instruction_access_exception 892 .globl __spitfire_insn_access_exception
742 .globl __do_instruction_access_exception_tl1 893 .globl __spitfire_insn_access_exception_tl1
743__do_instruction_access_exception_tl1: 894__spitfire_insn_access_exception_tl1:
744 rdpr %pstate, %g4 895 rdpr %pstate, %g4
745 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate 896 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
746 mov TLB_SFSR, %g3 897 mov TLB_SFSR, %g3
@@ -753,12 +904,12 @@ __do_instruction_access_exception_tl1:
753109: or %g7, %lo(109b), %g7 904109: or %g7, %lo(109b), %g7
754 mov %l4, %o1 905 mov %l4, %o1
755 mov %l5, %o2 906 mov %l5, %o2
756 call instruction_access_exception_tl1 907 call spitfire_insn_access_exception_tl1
757 add %sp, PTREGS_OFF, %o0 908 add %sp, PTREGS_OFF, %o0
758 ba,pt %xcc, rtrap 909 ba,pt %xcc, rtrap
759 clr %l6 910 clr %l6
760 911
761__do_instruction_access_exception: 912__spitfire_insn_access_exception:
762 rdpr %pstate, %g4 913 rdpr %pstate, %g4
763 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate 914 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
764 mov TLB_SFSR, %g3 915 mov TLB_SFSR, %g3
@@ -771,102 +922,11 @@ __do_instruction_access_exception:
771109: or %g7, %lo(109b), %g7 922109: or %g7, %lo(109b), %g7
772 mov %l4, %o1 923 mov %l4, %o1
773 mov %l5, %o2 924 mov %l5, %o2
774 call instruction_access_exception 925 call spitfire_insn_access_exception
775 add %sp, PTREGS_OFF, %o0 926 add %sp, PTREGS_OFF, %o0
776 ba,pt %xcc, rtrap 927 ba,pt %xcc, rtrap
777 clr %l6 928 clr %l6
778 929
779 /* This is the trap handler entry point for ECC correctable
780 * errors. They are corrected, but we listen for the trap
781 * so that the event can be logged.
782 *
783 * Disrupting errors are either:
784 * 1) single-bit ECC errors during UDB reads to system
785 * memory
786 * 2) data parity errors during write-back events
787 *
788 * As far as I can make out from the manual, the CEE trap
789 * is only for correctable errors during memory read
790 * accesses by the front-end of the processor.
791 *
792 * The code below is only for trap level 1 CEE events,
793 * as it is the only situation where we can safely record
794 * and log. For trap level >1 we just clear the CE bit
795 * in the AFSR and return.
796 */
797
798 /* Our trap handling infrastructure allows us to preserve
799 * two 64-bit values during etrap for arguments to
800 * subsequent C code. Therefore we encode the information
801 * as follows:
802 *
803 * value 1) Full 64-bits of AFAR
804 * value 2) Low 33-bits of AFSR, then bits 33-->42
805 * are UDBL error status and bits 43-->52
806 * are UDBH error status
807 */
808 .align 64
809 .globl cee_trap
810cee_trap:
811 ldxa [%g0] ASI_AFSR, %g1 ! Read AFSR
812 ldxa [%g0] ASI_AFAR, %g2 ! Read AFAR
813 sllx %g1, 31, %g1 ! Clear reserved bits
814 srlx %g1, 31, %g1 ! in AFSR
815
816 /* NOTE: UltraSparc-I/II have high and low UDB error
817 * registers, corresponding to the two UDB units
818 * present on those chips. UltraSparc-IIi only
819 * has a single UDB, called "SDB" in the manual.
820 * For IIi the upper UDB register always reads
821 * as zero so for our purposes things will just
822 * work with the checks below.
823 */
824 ldxa [%g0] ASI_UDBL_ERROR_R, %g3 ! Read UDB-Low error status
825 andcc %g3, (1 << 8), %g4 ! Check CE bit
826 sllx %g3, (64 - 10), %g3 ! Clear reserved bits
827 srlx %g3, (64 - 10), %g3 ! in UDB-Low error status
828
829 sllx %g3, (33 + 0), %g3 ! Shift up to encoding area
830 or %g1, %g3, %g1 ! Or it in
831 be,pn %xcc, 1f ! Branch if CE bit was clear
832 nop
833 stxa %g4, [%g0] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBL
834 membar #Sync ! Synchronize ASI stores
8351: mov 0x18, %g5 ! Addr of UDB-High error status
836 ldxa [%g5] ASI_UDBH_ERROR_R, %g3 ! Read it
837
838 andcc %g3, (1 << 8), %g4 ! Check CE bit
839 sllx %g3, (64 - 10), %g3 ! Clear reserved bits
840 srlx %g3, (64 - 10), %g3 ! in UDB-High error status
841 sllx %g3, (33 + 10), %g3 ! Shift up to encoding area
842 or %g1, %g3, %g1 ! Or it in
843 be,pn %xcc, 1f ! Branch if CE bit was clear
844 nop
845 nop
846
847 stxa %g4, [%g5] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBH
848 membar #Sync ! Synchronize ASI stores
8491: mov 1, %g5 ! AFSR CE bit is
850 sllx %g5, 20, %g5 ! bit 20
851 stxa %g5, [%g0] ASI_AFSR ! Clear CE sticky bit in AFSR
852 membar #Sync ! Synchronize ASI stores
853 sllx %g2, (64 - 41), %g2 ! Clear reserved bits
854 srlx %g2, (64 - 41), %g2 ! in latched AFAR
855
856 andn %g2, 0x0f, %g2 ! Finish resv bit clearing
857 mov %g1, %g4 ! Move AFSR+UDB* into save reg
858 mov %g2, %g5 ! Move AFAR into save reg
859 rdpr %pil, %g2
860 wrpr %g0, 15, %pil
861 ba,pt %xcc, etrap_irq
862 rd %pc, %g7
863 mov %l4, %o0
864
865 mov %l5, %o1
866 call cee_log
867 add %sp, PTREGS_OFF, %o2
868 ba,a,pt %xcc, rtrap_irq
869
870 /* Capture I/D/E-cache state into per-cpu error scoreboard. 930 /* Capture I/D/E-cache state into per-cpu error scoreboard.
871 * 931 *
872 * %g1: (TL>=0) ? 1 : 0 932 * %g1: (TL>=0) ? 1 : 0