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,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,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 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,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 198109: 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 218109: 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 238109: 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 246