xref: /linux/arch/sparc/kernel/spiterrs.S (revision e58e871becec2d3b04ed91c0c16fe8deac9c9dfa)
1	/* We need to carefully read the error status, ACK the errors,
2	 * prevent recursive traps, and pass the information on to C
3	 * code for logging.
4	 *
5	 * We pass the AFAR in as-is, and we encode the status
6	 * information as described in asm-sparc64/sfafsr.h
7	 */
8	.type		__spitfire_access_error,#function
9__spitfire_access_error:
10	/* Disable ESTATE error reporting so that we do not take
11	 * recursive traps and RED state the processor.
12	 */
13	stxa		%g0, [%g0] ASI_ESTATE_ERROR_EN
14	membar		#Sync
15
16	mov		UDBE_UE, %g1
17	ldxa		[%g0] ASI_AFSR, %g4	! Get AFSR
18
19	/* __spitfire_cee_trap branches here with AFSR in %g4 and
20	 * UDBE_CE in %g1.  It only clears ESTATE_ERR_CE in the ESTATE
21	 * Error Enable register.
22	 */
23__spitfire_cee_trap_continue:
24	ldxa		[%g0] ASI_AFAR, %g5	! Get AFAR
25
26	rdpr		%tt, %g3
27	and		%g3, 0x1ff, %g3		! Paranoia
28	sllx		%g3, SFSTAT_TRAP_TYPE_SHIFT, %g3
29	or		%g4, %g3, %g4
30	rdpr		%tl, %g3
31	cmp		%g3, 1
32	mov		1, %g3
33	bleu		%xcc, 1f
34	 sllx		%g3, SFSTAT_TL_GT_ONE_SHIFT, %g3
35
36	or		%g4, %g3, %g4
37
38	/* Read in the UDB error register state, clearing the sticky
39	 * error bits as-needed.  We only clear them if the UE bit is
40	 * set.  Likewise, __spitfire_cee_trap below will only do so
41	 * if the CE bit is set.
42	 *
43	 * NOTE: UltraSparc-I/II have high and low UDB error
44	 *       registers, corresponding to the two UDB units
45	 *       present on those chips.  UltraSparc-IIi only
46	 *       has a single UDB, called "SDB" in the manual.
47	 *       For IIi the upper UDB register always reads
48	 *       as zero so for our purposes things will just
49	 *       work with the checks below.
50	 */
511:	ldxa		[%g0] ASI_UDBH_ERROR_R, %g3
52	and		%g3, 0x3ff, %g7		! Paranoia
53	sllx		%g7, SFSTAT_UDBH_SHIFT, %g7
54	or		%g4, %g7, %g4
55	andcc		%g3, %g1, %g3		! UDBE_UE or UDBE_CE
56	be,pn		%xcc, 1f
57	 nop
58	stxa		%g3, [%g0] ASI_UDB_ERROR_W
59	membar		#Sync
60
611:	mov		0x18, %g3
62	ldxa		[%g3] ASI_UDBL_ERROR_R, %g3
63	and		%g3, 0x3ff, %g7		! Paranoia
64	sllx		%g7, SFSTAT_UDBL_SHIFT, %g7
65	or		%g4, %g7, %g4
66	andcc		%g3, %g1, %g3		! UDBE_UE or UDBE_CE
67	be,pn		%xcc, 1f
68	 nop
69	mov		0x18, %g7
70	stxa		%g3, [%g7] ASI_UDB_ERROR_W
71	membar		#Sync
72
731:	/* Ok, now that we've latched the error state, clear the
74	 * sticky bits in the AFSR.
75	 */
76	stxa		%g4, [%g0] ASI_AFSR
77	membar		#Sync
78
79	rdpr		%tl, %g2
80	cmp		%g2, 1
81	rdpr		%pil, %g2
82	bleu,pt		%xcc, 1f
83	 wrpr		%g0, PIL_NORMAL_MAX, %pil
84
85	ba,pt		%xcc, etraptl1
86	 rd		%pc, %g7
87
88	ba,a,pt		%xcc, 2f
89	 nop
90
911:	ba,pt		%xcc, etrap_irq
92	 rd		%pc, %g7
93
942:
95#ifdef CONFIG_TRACE_IRQFLAGS
96	call	trace_hardirqs_off
97	 nop
98#endif
99	mov		%l4, %o1
100	mov		%l5, %o2
101	call		spitfire_access_error
102	 add		%sp, PTREGS_OFF, %o0
103	ba,a,pt		%xcc, rtrap
104	.size		__spitfire_access_error,.-__spitfire_access_error
105
106	/* This is the trap handler entry point for ECC correctable
107	 * errors.  They are corrected, but we listen for the trap so
108	 * that the event can be logged.
109	 *
110	 * Disrupting errors are either:
111	 * 1) single-bit ECC errors during UDB reads to system
112	 *    memory
113	 * 2) data parity errors during write-back events
114	 *
115	 * As far as I can make out from the manual, the CEE trap is
116	 * only for correctable errors during memory read accesses by
117	 * the front-end of the processor.
118	 *
119	 * The code below is only for trap level 1 CEE events, as it
120	 * is the only situation where we can safely record and log.
121	 * For trap level >1 we just clear the CE bit in the AFSR and
122	 * return.
123	 *
124	 * This is just like __spiftire_access_error above, but it
125	 * specifically handles correctable errors.  If an
126	 * uncorrectable error is indicated in the AFSR we will branch
127	 * directly above to __spitfire_access_error to handle it
128	 * instead.  Uncorrectable therefore takes priority over
129	 * correctable, and the error logging C code will notice this
130	 * case by inspecting the trap type.
131	 */
132	.type		__spitfire_cee_trap,#function
133__spitfire_cee_trap:
134	ldxa		[%g0] ASI_AFSR, %g4	! Get AFSR
135	mov		1, %g3
136	sllx		%g3, SFAFSR_UE_SHIFT, %g3
137	andcc		%g4, %g3, %g0		! Check for UE
138	bne,pn		%xcc, __spitfire_access_error
139	 nop
140
141	/* Ok, in this case we only have a correctable error.
142	 * Indicate we only wish to capture that state in register
143	 * %g1, and we only disable CE error reporting unlike UE
144	 * handling which disables all errors.
145	 */
146	ldxa		[%g0] ASI_ESTATE_ERROR_EN, %g3
147	andn		%g3, ESTATE_ERR_CE, %g3
148	stxa		%g3, [%g0] ASI_ESTATE_ERROR_EN
149	membar		#Sync
150
151	/* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */
152	ba,pt		%xcc, __spitfire_cee_trap_continue
153	 mov		UDBE_CE, %g1
154	.size		__spitfire_cee_trap,.-__spitfire_cee_trap
155
156	.type		__spitfire_data_access_exception_tl1,#function
157__spitfire_data_access_exception_tl1:
158	rdpr		%pstate, %g4
159	wrpr		%g4, PSTATE_MG|PSTATE_AG, %pstate
160	mov		TLB_SFSR, %g3
161	mov		DMMU_SFAR, %g5
162	ldxa		[%g3] ASI_DMMU, %g4	! Get SFSR
163	ldxa		[%g5] ASI_DMMU, %g5	! Get SFAR
164	stxa		%g0, [%g3] ASI_DMMU	! Clear SFSR.FaultValid bit
165	membar		#Sync
166	rdpr		%tt, %g3
167	cmp		%g3, 0x80		! first win spill/fill trap
168	blu,pn		%xcc, 1f
169	 cmp		%g3, 0xff		! last win spill/fill trap
170	bgu,pn		%xcc, 1f
171	 nop
172	ba,pt		%xcc, winfix_dax
173	 rdpr		%tpc, %g3
1741:	sethi		%hi(109f), %g7
175	ba,pt		%xcc, etraptl1
176109:	 or		%g7, %lo(109b), %g7
177	mov		%l4, %o1
178	mov		%l5, %o2
179	call		spitfire_data_access_exception_tl1
180	 add		%sp, PTREGS_OFF, %o0
181	ba,a,pt		%xcc, rtrap
182	.size		__spitfire_data_access_exception_tl1,.-__spitfire_data_access_exception_tl1
183
184	.type		__spitfire_data_access_exception,#function
185__spitfire_data_access_exception:
186	rdpr		%pstate, %g4
187	wrpr		%g4, PSTATE_MG|PSTATE_AG, %pstate
188	mov		TLB_SFSR, %g3
189	mov		DMMU_SFAR, %g5
190	ldxa		[%g3] ASI_DMMU, %g4	! Get SFSR
191	ldxa		[%g5] ASI_DMMU, %g5	! Get SFAR
192	stxa		%g0, [%g3] ASI_DMMU	! Clear SFSR.FaultValid bit
193	membar		#Sync
194	sethi		%hi(109f), %g7
195	ba,pt		%xcc, etrap
196109:	 or		%g7, %lo(109b), %g7
197	mov		%l4, %o1
198	mov		%l5, %o2
199	call		spitfire_data_access_exception
200	 add		%sp, PTREGS_OFF, %o0
201	ba,a,pt		%xcc, rtrap
202	.size		__spitfire_data_access_exception,.-__spitfire_data_access_exception
203
204	.type		__spitfire_insn_access_exception_tl1,#function
205__spitfire_insn_access_exception_tl1:
206	rdpr		%pstate, %g4
207	wrpr		%g4, PSTATE_MG|PSTATE_AG, %pstate
208	mov		TLB_SFSR, %g3
209	ldxa		[%g3] ASI_IMMU, %g4	! Get SFSR
210	rdpr		%tpc, %g5		! IMMU has no SFAR, use TPC
211	stxa		%g0, [%g3] ASI_IMMU	! Clear FaultValid bit
212	membar		#Sync
213	sethi		%hi(109f), %g7
214	ba,pt		%xcc, etraptl1
215109:	 or		%g7, %lo(109b), %g7
216	mov		%l4, %o1
217	mov		%l5, %o2
218	call		spitfire_insn_access_exception_tl1
219	 add		%sp, PTREGS_OFF, %o0
220	ba,a,pt		%xcc, rtrap
221	.size		__spitfire_insn_access_exception_tl1,.-__spitfire_insn_access_exception_tl1
222
223	.type		__spitfire_insn_access_exception,#function
224__spitfire_insn_access_exception:
225	rdpr		%pstate, %g4
226	wrpr		%g4, PSTATE_MG|PSTATE_AG, %pstate
227	mov		TLB_SFSR, %g3
228	ldxa		[%g3] ASI_IMMU, %g4	! Get SFSR
229	rdpr		%tpc, %g5		! IMMU has no SFAR, use TPC
230	stxa		%g0, [%g3] ASI_IMMU	! Clear FaultValid bit
231	membar		#Sync
232	sethi		%hi(109f), %g7
233	ba,pt		%xcc, etrap
234109:	 or		%g7, %lo(109b), %g7
235	mov		%l4, %o1
236	mov		%l5, %o2
237	call		spitfire_insn_access_exception
238	 add		%sp, PTREGS_OFF, %o0
239	ba,a,pt		%xcc, rtrap
240	.size		__spitfire_insn_access_exception,.-__spitfire_insn_access_exception
241