aboutsummaryrefslogtreecommitdiff
path: root/arch/sparc/kernel/spiterrs.S
diff options
context:
space:
mode:
authorSam Ravnborg <sam@ravnborg.org>2008-12-03 03:11:52 -0800
committerDavid S. Miller <davem@davemloft.net>2008-12-04 09:17:21 -0800
commita88b5ba8bd8ac18aad65ee6c6a254e2e74876db3 (patch)
treeeb3d0ffaf53c3f7ec6083752c2097cecd1cb892a /arch/sparc/kernel/spiterrs.S
parentd670bd4f803c8b646acd20f3ba21e65458293faf (diff)
sparc,sparc64: unify kernel/
o Move all files from sparc64/kernel/ to sparc/kernel - rename as appropriate o Update sparc/Makefile to the changes o Update sparc/kernel/Makefile to include the sparc64 files NOTE: This commit changes link order on sparc64! Link order had to change for either of sparc32 and sparc64. And assuming sparc64 see more testing than sparc32 change link order on sparc64 where issues will be caught faster. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/spiterrs.S')
-rw-r--r--arch/sparc/kernel/spiterrs.S245
1 files changed, 245 insertions, 0 deletions
diff --git a/arch/sparc/kernel/spiterrs.S b/arch/sparc/kernel/spiterrs.S
new file mode 100644
index 00000000000..c357e40ffd0
--- /dev/null
+++ b/arch/sparc/kernel/spiterrs.S
@@ -0,0 +1,245 @@
+ /* We need to carefully read the error status, ACK the errors,
+ * prevent recursive traps, and pass the information on to C
+ * code for logging.
+ *
+ * We pass the AFAR in as-is, and we encode the status
+ * information as described in asm-sparc64/sfafsr.h
+ */
+ .type __spitfire_access_error,#function
+__spitfire_access_error:
+ /* Disable ESTATE error reporting so that we do not take
+ * recursive traps and RED state the processor.
+ */
+ stxa %g0, [%g0] ASI_ESTATE_ERROR_EN
+ membar #Sync
+
+ mov UDBE_UE, %g1
+ ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
+
+ /* __spitfire_cee_trap branches here with AFSR in %g4 and
+ * UDBE_CE in %g1. It only clears ESTATE_ERR_CE in the ESTATE
+ * Error Enable register.
+ */
+__spitfire_cee_trap_continue:
+ ldxa [%g0] ASI_AFAR, %g5 ! Get AFAR
+
+ rdpr %tt, %g3
+ and %g3, 0x1ff, %g3 ! Paranoia
+ sllx %g3, SFSTAT_TRAP_TYPE_SHIFT, %g3
+ or %g4, %g3, %g4
+ rdpr %tl, %g3
+ cmp %g3, 1
+ mov 1, %g3
+ bleu %xcc, 1f
+ sllx %g3, SFSTAT_TL_GT_ONE_SHIFT, %g3
+
+ or %g4, %g3, %g4
+
+ /* Read in the UDB error register state, clearing the sticky
+ * error bits as-needed. We only clear them if the UE bit is
+ * set. Likewise, __spitfire_cee_trap below will only do so
+ * if the CE bit is set.
+ *
+ * NOTE: UltraSparc-I/II have high and low UDB error
+ * registers, corresponding to the two UDB units
+ * present on those chips. UltraSparc-IIi only
+ * has a single UDB, called "SDB" in the manual.
+ * For IIi the upper UDB register always reads
+ * as zero so for our purposes things will just
+ * work with the checks below.
+ */
+1: ldxa [%g0] ASI_UDBH_ERROR_R, %g3
+ and %g3, 0x3ff, %g7 ! Paranoia
+ sllx %g7, SFSTAT_UDBH_SHIFT, %g7
+ or %g4, %g7, %g4
+ andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
+ be,pn %xcc, 1f
+ nop
+ stxa %g3, [%g0] ASI_UDB_ERROR_W
+ membar #Sync
+
+1: mov 0x18, %g3
+ ldxa [%g3] ASI_UDBL_ERROR_R, %g3
+ and %g3, 0x3ff, %g7 ! Paranoia
+ sllx %g7, SFSTAT_UDBL_SHIFT, %g7
+ or %g4, %g7, %g4
+ andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
+ be,pn %xcc, 1f
+ nop
+ mov 0x18, %g7
+ stxa %g3, [%g7] ASI_UDB_ERROR_W
+ membar #Sync
+
+1: /* Ok, now that we've latched the error state, clear the
+ * sticky bits in the AFSR.
+ */
+ stxa %g4, [%g0] ASI_AFSR
+ membar #Sync
+
+ rdpr %tl, %g2
+ cmp %g2, 1
+ rdpr %pil, %g2
+ bleu,pt %xcc, 1f
+ wrpr %g0, PIL_NORMAL_MAX, %pil
+
+ ba,pt %xcc, etraptl1
+ rd %pc, %g7
+
+ ba,pt %xcc, 2f
+ nop
+
+1: ba,pt %xcc, etrap_irq
+ rd %pc, %g7
+
+2:
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call trace_hardirqs_off
+ nop
+#endif
+ mov %l4, %o1
+ mov %l5, %o2
+ call spitfire_access_error
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+ nop
+ .size __spitfire_access_error,.-__spitfire_access_error
+
+ /* This is the trap handler entry point for ECC correctable
+ * errors. They are corrected, but we listen for the trap so
+ * that the event can be logged.
+ *
+ * Disrupting errors are either:
+ * 1) single-bit ECC errors during UDB reads to system
+ * memory
+ * 2) data parity errors during write-back events
+ *
+ * As far as I can make out from the manual, the CEE trap is
+ * only for correctable errors during memory read accesses by
+ * the front-end of the processor.
+ *
+ * The code below is only for trap level 1 CEE events, as it
+ * is the only situation where we can safely record and log.
+ * For trap level >1 we just clear the CE bit in the AFSR and
+ * return.
+ *
+ * This is just like __spiftire_access_error above, but it
+ * specifically handles correctable errors. If an
+ * uncorrectable error is indicated in the AFSR we will branch
+ * directly above to __spitfire_access_error to handle it
+ * instead. Uncorrectable therefore takes priority over
+ * correctable, and the error logging C code will notice this
+ * case by inspecting the trap type.
+ */
+ .type __spitfire_cee_trap,#function
+__spitfire_cee_trap:
+ ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
+ mov 1, %g3
+ sllx %g3, SFAFSR_UE_SHIFT, %g3
+ andcc %g4, %g3, %g0 ! Check for UE
+ bne,pn %xcc, __spitfire_access_error
+ nop
+
+ /* Ok, in this case we only have a correctable error.
+ * Indicate we only wish to capture that state in register
+ * %g1, and we only disable CE error reporting unlike UE
+ * handling which disables all errors.
+ */
+ ldxa [%g0] ASI_ESTATE_ERROR_EN, %g3
+ andn %g3, ESTATE_ERR_CE, %g3
+ stxa %g3, [%g0] ASI_ESTATE_ERROR_EN
+ membar #Sync
+
+ /* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */
+ ba,pt %xcc, __spitfire_cee_trap_continue
+ mov UDBE_CE, %g1
+ .size __spitfire_cee_trap,.-__spitfire_cee_trap
+
+ .type __spitfire_data_access_exception_tl1,#function
+__spitfire_data_access_exception_tl1:
+ rdpr %pstate, %g4
+ wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
+ mov TLB_SFSR, %g3
+ mov DMMU_SFAR, %g5
+ ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
+ ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
+ stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
+ membar #Sync
+ rdpr %tt, %g3
+ cmp %g3, 0x80 ! first win spill/fill trap
+ blu,pn %xcc, 1f
+ cmp %g3, 0xff ! last win spill/fill trap
+ bgu,pn %xcc, 1f
+ nop
+ ba,pt %xcc, winfix_dax
+ rdpr %tpc, %g3
+1: sethi %hi(109f), %g7
+ ba,pt %xcc, etraptl1
+109: or %g7, %lo(109b), %g7
+ mov %l4, %o1
+ mov %l5, %o2
+ call spitfire_data_access_exception_tl1
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+ nop
+ .size __spitfire_data_access_exception_tl1,.-__spitfire_data_access_exception_tl1
+
+ .type __spitfire_data_access_exception,#function
+__spitfire_data_access_exception:
+ rdpr %pstate, %g4
+ wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
+ mov TLB_SFSR, %g3
+ mov DMMU_SFAR, %g5
+ ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
+ ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
+ stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
+ membar #Sync
+ sethi %hi(109f), %g7
+ ba,pt %xcc, etrap
+109: or %g7, %lo(109b), %g7
+ mov %l4, %o1
+ mov %l5, %o2
+ call spitfire_data_access_exception
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+ nop
+ .size __spitfire_data_access_exception,.-__spitfire_data_access_exception
+
+ .type __spitfire_insn_access_exception_tl1,#function
+__spitfire_insn_access_exception_tl1:
+ rdpr %pstate, %g4
+ wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
+ mov TLB_SFSR, %g3
+ ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
+ rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
+ stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
+ membar #Sync
+ sethi %hi(109f), %g7
+ ba,pt %xcc, etraptl1
+109: or %g7, %lo(109b), %g7
+ mov %l4, %o1
+ mov %l5, %o2
+ call spitfire_insn_access_exception_tl1
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+ nop
+ .size __spitfire_insn_access_exception_tl1,.-__spitfire_insn_access_exception_tl1
+
+ .type __spitfire_insn_access_exception,#function
+__spitfire_insn_access_exception:
+ rdpr %pstate, %g4
+ wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
+ mov TLB_SFSR, %g3
+ ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
+ rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
+ stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
+ membar #Sync
+ sethi %hi(109f), %g7
+ ba,pt %xcc, etrap
+109: or %g7, %lo(109b), %g7
+ mov %l4, %o1
+ mov %l5, %o2
+ call spitfire_insn_access_exception
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+ nop
+ .size __spitfire_insn_access_exception,.-__spitfire_insn_access_exception