linux/arch/sparc/kernel/spiterrs.S
<<
>>
Prefs
   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