root/arch/sparc/kernel/spiterrs.S

/* [<][>][^][v][top][bottom][index][help] */
   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          */
  52 1:      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 
  62 1:      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 
  74 1:      /* 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 
  92 1:      ba,pt           %xcc, etrap_irq
  93          rd             %pc, %g7
  94 
  95 2:
  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
 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,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
 197 109:     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
 216 109:     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
 235 109:     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

/* [<][>][^][v][top][bottom][index][help] */