1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* We need to carefully read the error status, ACK the errors,
3 * prevent recursive traps, and pass the information on to C
6 * We pass the AFAR in as-is, and we encode the status
7 * information as described in asm-sparc64/sfafsr.h
9 .type __spitfire_access_error,#function
10 __spitfire_access_error:
11 /* Disable ESTATE error reporting so that we do not take
12 * recursive traps and RED state the processor.
14 stxa %g0, [%g0] ASI_ESTATE_ERROR_EN
18 ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
20 /* __spitfire_cee_trap branches here with AFSR in %g4 and
21 * UDBE_CE in %g1. It only clears ESTATE_ERR_CE in the ESTATE
22 * Error Enable register.
24 __spitfire_cee_trap_continue:
25 ldxa [%g0] ASI_AFAR, %g5 ! Get AFAR
28 and %g3, 0x1ff, %g3 ! Paranoia
29 sllx %g3, SFSTAT_TRAP_TYPE_SHIFT, %g3
35 sllx %g3, SFSTAT_TL_GT_ONE_SHIFT, %g3
39 /* Read in the UDB error register state, clearing the sticky
40 * error bits as-needed. We only clear them if the UE bit is
41 * set. Likewise, __spitfire_cee_trap below will only do so
42 * if the CE bit is set.
44 * NOTE: UltraSparc-I/II have high and low UDB error
45 * registers, corresponding to the two UDB units
46 * present on those chips. UltraSparc-IIi only
47 * has a single UDB, called "SDB" in the manual.
48 * For IIi the upper UDB register always reads
49 * as zero so for our purposes things will just
50 * work with the checks below.
52 1: ldxa [%g0] ASI_UDBH_ERROR_R, %g3
53 and %g3, 0x3ff, %g7 ! Paranoia
54 sllx %g7, SFSTAT_UDBH_SHIFT, %g7
56 andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
59 stxa %g3, [%g0] ASI_UDB_ERROR_W
63 ldxa [%g3] ASI_UDBL_ERROR_R, %g3
64 and %g3, 0x3ff, %g7 ! Paranoia
65 sllx %g7, SFSTAT_UDBL_SHIFT, %g7
67 andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
71 stxa %g3, [%g7] ASI_UDB_ERROR_W
74 1: /* Ok, now that we've latched the error state, clear the
75 * sticky bits in the AFSR.
77 stxa %g4, [%g0] ASI_AFSR
84 wrpr %g0, PIL_NORMAL_MAX, %pil
92 1: ba,pt %xcc, etrap_irq
96 #ifdef CONFIG_TRACE_IRQFLAGS
97 call trace_hardirqs_off
102 call spitfire_access_error
103 add %sp, PTREGS_OFF, %o0
105 .size __spitfire_access_error,.-__spitfire_access_error
107 /* This is the trap handler entry point for ECC correctable
108 * errors. They are corrected, but we listen for the trap so
109 * that the event can be logged.
111 * Disrupting errors are either:
112 * 1) single-bit ECC errors during UDB reads to system
114 * 2) data parity errors during write-back events
116 * As far as I can make out from the manual, the CEE trap is
117 * only for correctable errors during memory read accesses by
118 * the front-end of the processor.
120 * The code below is only for trap level 1 CEE events, as it
121 * is the only situation where we can safely record and log.
122 * For trap level >1 we just clear the CE bit in the AFSR and
125 * This is just like __spiftire_access_error above, but it
126 * specifically handles correctable errors. If an
127 * uncorrectable error is indicated in the AFSR we will branch
128 * directly above to __spitfire_access_error to handle it
129 * instead. Uncorrectable therefore takes priority over
130 * correctable, and the error logging C code will notice this
131 * case by inspecting the trap type.
133 .type __spitfire_cee_trap,#function
135 ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
137 sllx %g3, SFAFSR_UE_SHIFT, %g3
138 andcc %g4, %g3, %g0 ! Check for UE
139 bne,pn %xcc, __spitfire_access_error
142 /* Ok, in this case we only have a correctable error.
143 * Indicate we only wish to capture that state in register
144 * %g1, and we only disable CE error reporting unlike UE
145 * handling which disables all errors.
147 ldxa [%g0] ASI_ESTATE_ERROR_EN, %g3
148 andn %g3, ESTATE_ERR_CE, %g3
149 stxa %g3, [%g0] ASI_ESTATE_ERROR_EN
152 /* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */
153 ba,pt %xcc, __spitfire_cee_trap_continue
155 .size __spitfire_cee_trap,.-__spitfire_cee_trap
157 .type __spitfire_data_access_exception_tl1,#function
158 __spitfire_data_access_exception_tl1:
160 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
163 ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
164 ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
165 stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
168 cmp %g3, 0x80 ! first win spill/fill trap
170 cmp %g3, 0xff ! last win spill/fill trap
173 ba,pt %xcc, winfix_dax
175 1: sethi %hi(109f), %g7
177 109: or %g7, %lo(109b), %g7
180 call spitfire_data_access_exception_tl1
181 add %sp, PTREGS_OFF, %o0
183 .size __spitfire_data_access_exception_tl1,.-__spitfire_data_access_exception_tl1
185 .type __spitfire_data_access_exception,#function
186 __spitfire_data_access_exception:
188 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
191 ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
192 ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
193 stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
197 109: or %g7, %lo(109b), %g7
200 call spitfire_data_access_exception
201 add %sp, PTREGS_OFF, %o0
203 .size __spitfire_data_access_exception,.-__spitfire_data_access_exception
205 .type __spitfire_insn_access_exception_tl1,#function
206 __spitfire_insn_access_exception_tl1:
208 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
210 ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
211 rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
212 stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
216 109: or %g7, %lo(109b), %g7
219 call spitfire_insn_access_exception_tl1
220 add %sp, PTREGS_OFF, %o0
222 .size __spitfire_insn_access_exception_tl1,.-__spitfire_insn_access_exception_tl1
224 .type __spitfire_insn_access_exception,#function
225 __spitfire_insn_access_exception:
227 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
229 ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
230 rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
231 stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
235 109: or %g7, %lo(109b), %g7
238 call spitfire_insn_access_exception
239 add %sp, PTREGS_OFF, %o0
241 .size __spitfire_insn_access_exception,.-__spitfire_insn_access_exception