aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/entry.S
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2005-08-29 15:45:11 -0400
committerDavid S. Miller <davem@davemloft.net>2005-08-29 15:45:11 -0400
commit6c52a96e6cacb35403b85c3b42db0faf26f3ed85 (patch)
tree07ebe2ce68511ffb75575603b0c58bf00c78f8c7 /arch/sparc64/kernel/entry.S
parentbde4e4ee9f90142d550e2684dec2c8df302f5f8e (diff)
[SPARC64]: Revamp Spitfire error trap handling.
Current uncorrectable error handling was poor enough that the processor could just loop taking the same trap over and over again. Fix things up so that we at least get a log message and perhaps even some register state. In the process, much consolidation became possible, particularly with the correctable error handler. Prefix assembler and C function names with "spitfire" to indicate that these are for Ultra-I/II/IIi/IIe only. More work is needed to make these routines robust and featureful to the level of the Ultra-III error handlers. Signed-off-by: David S. Miller <davem@davemloft.net>
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