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 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 */ 521: 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 621: 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 741: /* 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 84 wrpr %g0, PIL_NORMAL_MAX, %pil 85 86 ba,pt %xcc, etraptl1 87 rd %pc, %g7 88 89 ba,a,pt %xcc, 2f 90 nop 91 921: ba,pt %xcc, etrap_irq 93 rd %pc, %g7 94 952: 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 104 ba,a,pt %xcc, rtrap 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 1751: sethi %hi(109f), %g7 176 ba,pt %xcc, etraptl1 177109: 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,a,pt %xcc, rtrap 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 197109: 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 202 ba,a,pt %xcc, rtrap 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 216109: 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 221 ba,a,pt %xcc, rtrap 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 235109: 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 240 ba,a,pt %xcc, rtrap 241 .size __spitfire_insn_access_exception,.-__spitfire_insn_access_exception 242