David S. Miller | 6eda3a7 | 2008-04-28 00:47:20 -0700 | [diff] [blame] | 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 |
David S. Miller | b4f4372 | 2008-11-23 21:55:29 -0800 | [diff] [blame] | 83 | wrpr %g0, PIL_NORMAL_MAX, %pil |
David S. Miller | 6eda3a7 | 2008-04-28 00:47:20 -0700 | [diff] [blame] | 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 |