]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
6eda3a75 DM |
2 | /* We need to carefully read the error status, ACK the errors, |
3 | * prevent recursive traps, and pass the information on to C | |
4 | * code for logging. | |
5 | * | |
6 | * We pass the AFAR in as-is, and we encode the status | |
7 | * information as described in asm-sparc64/sfafsr.h | |
8 | */ | |
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. | |
13 | */ | |
14 | stxa %g0, [%g0] ASI_ESTATE_ERROR_EN | |
15 | membar #Sync | |
16 | ||
17 | mov UDBE_UE, %g1 | |
18 | ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR | |
19 | ||
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. | |
23 | */ | |
24 | __spitfire_cee_trap_continue: | |
25 | ldxa [%g0] ASI_AFAR, %g5 ! Get AFAR | |
26 | ||
27 | rdpr %tt, %g3 | |
28 | and %g3, 0x1ff, %g3 ! Paranoia | |
29 | sllx %g3, SFSTAT_TRAP_TYPE_SHIFT, %g3 | |
30 | or %g4, %g3, %g4 | |
31 | rdpr %tl, %g3 | |
32 | cmp %g3, 1 | |
33 | mov 1, %g3 | |
34 | bleu %xcc, 1f | |
35 | sllx %g3, SFSTAT_TL_GT_ONE_SHIFT, %g3 | |
36 | ||
37 | or %g4, %g3, %g4 | |
38 | ||
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. | |
43 | * | |
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. | |
51 | */ | |
52 | 1: ldxa [%g0] ASI_UDBH_ERROR_R, %g3 | |
53 | and %g3, 0x3ff, %g7 ! Paranoia | |
54 | sllx %g7, SFSTAT_UDBH_SHIFT, %g7 | |
55 | or %g4, %g7, %g4 | |
56 | andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE | |
57 | be,pn %xcc, 1f | |
58 | nop | |
59 | stxa %g3, [%g0] ASI_UDB_ERROR_W | |
60 | membar #Sync | |
61 | ||
62 | 1: mov 0x18, %g3 | |
63 | ldxa [%g3] ASI_UDBL_ERROR_R, %g3 | |
64 | and %g3, 0x3ff, %g7 ! Paranoia | |
65 | sllx %g7, SFSTAT_UDBL_SHIFT, %g7 | |
66 | or %g4, %g7, %g4 | |
67 | andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE | |
68 | be,pn %xcc, 1f | |
69 | nop | |
70 | mov 0x18, %g7 | |
71 | stxa %g3, [%g7] ASI_UDB_ERROR_W | |
72 | membar #Sync | |
73 | ||
74 | 1: /* Ok, now that we've latched the error state, clear the | |
75 | * sticky bits in the AFSR. | |
76 | */ | |
77 | stxa %g4, [%g0] ASI_AFSR | |
78 | membar #Sync | |
79 | ||
80 | rdpr %tl, %g2 | |
81 | cmp %g2, 1 | |
82 | rdpr %pil, %g2 | |
83 | bleu,pt %xcc, 1f | |
b4f4372f | 84 | wrpr %g0, PIL_NORMAL_MAX, %pil |
6eda3a75 DM |
85 | |
86 | ba,pt %xcc, etraptl1 | |
87 | rd %pc, %g7 | |
88 | ||
49fa5230 | 89 | ba,a,pt %xcc, 2f |
0ae2d26f | 90 | nop |
6eda3a75 DM |
91 | |
92 | 1: ba,pt %xcc, etrap_irq | |
93 | rd %pc, %g7 | |
94 | ||
95 | 2: | |
96 | #ifdef CONFIG_TRACE_IRQFLAGS | |
97 | call trace_hardirqs_off | |
98 | nop | |
99 | #endif | |
100 | mov %l4, %o1 | |
101 | mov %l5, %o2 | |
102 | call spitfire_access_error | |
103 | add %sp, PTREGS_OFF, %o0 | |
49fa5230 | 104 | ba,a,pt %xcc, rtrap |
6eda3a75 DM |
105 | .size __spitfire_access_error,.-__spitfire_access_error |
106 | ||
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. | |
110 | * | |
111 | * Disrupting errors are either: | |
112 | * 1) single-bit ECC errors during UDB reads to system | |
113 | * memory | |
114 | * 2) data parity errors during write-back events | |
115 | * | |
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. | |
119 | * | |
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 | |
123 | * return. | |
124 | * | |
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. | |
132 | */ | |
133 | .type __spitfire_cee_trap,#function | |
134 | __spitfire_cee_trap: | |
135 | ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR | |
136 | mov 1, %g3 | |
137 | sllx %g3, SFAFSR_UE_SHIFT, %g3 | |
138 | andcc %g4, %g3, %g0 ! Check for UE | |
139 | bne,pn %xcc, __spitfire_access_error | |
140 | nop | |
141 | ||
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. | |
146 | */ | |
147 | ldxa [%g0] ASI_ESTATE_ERROR_EN, %g3 | |
148 | andn %g3, ESTATE_ERR_CE, %g3 | |
149 | stxa %g3, [%g0] ASI_ESTATE_ERROR_EN | |
150 | membar #Sync | |
151 | ||
152 | /* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */ | |
153 | ba,pt %xcc, __spitfire_cee_trap_continue | |
154 | mov UDBE_CE, %g1 | |
155 | .size __spitfire_cee_trap,.-__spitfire_cee_trap | |
156 | ||
157 | .type __spitfire_data_access_exception_tl1,#function | |
158 | __spitfire_data_access_exception_tl1: | |
159 | rdpr %pstate, %g4 | |
160 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate | |
161 | mov TLB_SFSR, %g3 | |
162 | mov DMMU_SFAR, %g5 | |
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 | |
166 | membar #Sync | |
167 | rdpr %tt, %g3 | |
168 | cmp %g3, 0x80 ! first win spill/fill trap | |
169 | blu,pn %xcc, 1f | |
170 | cmp %g3, 0xff ! last win spill/fill trap | |
171 | bgu,pn %xcc, 1f | |
172 | nop | |
173 | ba,pt %xcc, winfix_dax | |
174 | rdpr %tpc, %g3 | |
175 | 1: sethi %hi(109f), %g7 | |
176 | ba,pt %xcc, etraptl1 | |
177 | 109: or %g7, %lo(109b), %g7 | |
178 | mov %l4, %o1 | |
179 | mov %l5, %o2 | |
180 | call spitfire_data_access_exception_tl1 | |
181 | add %sp, PTREGS_OFF, %o0 | |
49fa5230 | 182 | ba,a,pt %xcc, rtrap |
6eda3a75 DM |
183 | .size __spitfire_data_access_exception_tl1,.-__spitfire_data_access_exception_tl1 |
184 | ||
185 | .type __spitfire_data_access_exception,#function | |
186 | __spitfire_data_access_exception: | |
187 | rdpr %pstate, %g4 | |
188 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate | |
189 | mov TLB_SFSR, %g3 | |
190 | mov DMMU_SFAR, %g5 | |
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 | |
194 | membar #Sync | |
195 | sethi %hi(109f), %g7 | |
196 | ba,pt %xcc, etrap | |
197 | 109: or %g7, %lo(109b), %g7 | |
198 | mov %l4, %o1 | |
199 | mov %l5, %o2 | |
200 | call spitfire_data_access_exception | |
201 | add %sp, PTREGS_OFF, %o0 | |
49fa5230 | 202 | ba,a,pt %xcc, rtrap |
6eda3a75 DM |
203 | .size __spitfire_data_access_exception,.-__spitfire_data_access_exception |
204 | ||
205 | .type __spitfire_insn_access_exception_tl1,#function | |
206 | __spitfire_insn_access_exception_tl1: | |
207 | rdpr %pstate, %g4 | |
208 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate | |
209 | mov TLB_SFSR, %g3 | |
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 | |
213 | membar #Sync | |
214 | sethi %hi(109f), %g7 | |
215 | ba,pt %xcc, etraptl1 | |
216 | 109: or %g7, %lo(109b), %g7 | |
217 | mov %l4, %o1 | |
218 | mov %l5, %o2 | |
219 | call spitfire_insn_access_exception_tl1 | |
220 | add %sp, PTREGS_OFF, %o0 | |
49fa5230 | 221 | ba,a,pt %xcc, rtrap |
6eda3a75 DM |
222 | .size __spitfire_insn_access_exception_tl1,.-__spitfire_insn_access_exception_tl1 |
223 | ||
224 | .type __spitfire_insn_access_exception,#function | |
225 | __spitfire_insn_access_exception: | |
226 | rdpr %pstate, %g4 | |
227 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate | |
228 | mov TLB_SFSR, %g3 | |
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 | |
232 | membar #Sync | |
233 | sethi %hi(109f), %g7 | |
234 | ba,pt %xcc, etrap | |
235 | 109: or %g7, %lo(109b), %g7 | |
236 | mov %l4, %o1 | |
237 | mov %l5, %o2 | |
238 | call spitfire_insn_access_exception | |
239 | add %sp, PTREGS_OFF, %o0 | |
49fa5230 | 240 | ba,a,pt %xcc, rtrap |
6eda3a75 | 241 | .size __spitfire_insn_access_exception,.-__spitfire_insn_access_exception |