Commit | Line | Data |
---|---|---|
6eda3a75 DM |
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 | */ | |
51 | 1: 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 | ||
61 | 1: 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 | ||
73 | 1: /* 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 | |
b4f4372f | 83 | wrpr %g0, PIL_NORMAL_MAX, %pil |
6eda3a75 DM |
84 | |
85 | ba,pt %xcc, etraptl1 | |
86 | rd %pc, %g7 | |
87 | ||
88 | ba,pt %xcc, 2f | |
89 | nop | |
90 | ||
91 | 1: ba,pt %xcc, etrap_irq | |
92 | rd %pc, %g7 | |
93 | ||
94 | 2: | |
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,pt %xcc, rtrap | |
104 | nop | |
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 | |
182 | ba,pt %xcc, rtrap | |
183 | nop | |
184 | .size __spitfire_data_access_exception_tl1,.-__spitfire_data_access_exception_tl1 | |
185 | ||
186 | .type __spitfire_data_access_exception,#function | |
187 | __spitfire_data_access_exception: | |
188 | rdpr %pstate, %g4 | |
189 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate | |
190 | mov TLB_SFSR, %g3 | |
191 | mov DMMU_SFAR, %g5 | |
192 | ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR | |
193 | ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR | |
194 | stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit | |
195 | membar #Sync | |
196 | sethi %hi(109f), %g7 | |
197 | ba,pt %xcc, etrap | |
198 | 109: or %g7, %lo(109b), %g7 | |
199 | mov %l4, %o1 | |
200 | mov %l5, %o2 | |
201 | call spitfire_data_access_exception | |
202 | add %sp, PTREGS_OFF, %o0 | |
203 | ba,pt %xcc, rtrap | |
204 | nop | |
205 | .size __spitfire_data_access_exception,.-__spitfire_data_access_exception | |
206 | ||
207 | .type __spitfire_insn_access_exception_tl1,#function | |
208 | __spitfire_insn_access_exception_tl1: | |
209 | rdpr %pstate, %g4 | |
210 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate | |
211 | mov TLB_SFSR, %g3 | |
212 | ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR | |
213 | rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC | |
214 | stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit | |
215 | membar #Sync | |
216 | sethi %hi(109f), %g7 | |
217 | ba,pt %xcc, etraptl1 | |
218 | 109: or %g7, %lo(109b), %g7 | |
219 | mov %l4, %o1 | |
220 | mov %l5, %o2 | |
221 | call spitfire_insn_access_exception_tl1 | |
222 | add %sp, PTREGS_OFF, %o0 | |
223 | ba,pt %xcc, rtrap | |
224 | nop | |
225 | .size __spitfire_insn_access_exception_tl1,.-__spitfire_insn_access_exception_tl1 | |
226 | ||
227 | .type __spitfire_insn_access_exception,#function | |
228 | __spitfire_insn_access_exception: | |
229 | rdpr %pstate, %g4 | |
230 | wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate | |
231 | mov TLB_SFSR, %g3 | |
232 | ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR | |
233 | rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC | |
234 | stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit | |
235 | membar #Sync | |
236 | sethi %hi(109f), %g7 | |
237 | ba,pt %xcc, etrap | |
238 | 109: or %g7, %lo(109b), %g7 | |
239 | mov %l4, %o1 | |
240 | mov %l5, %o2 | |
241 | call spitfire_insn_access_exception | |
242 | add %sp, PTREGS_OFF, %o0 | |
243 | ba,pt %xcc, rtrap | |
244 | nop | |
245 | .size __spitfire_insn_access_exception,.-__spitfire_insn_access_exception |