Back to home page

LXR

 
 

    


0001 /*
0002  * Copyright (C) 2001,2002,2003 Broadcom Corporation
0003  *
0004  * This program is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU General Public License
0006  * as published by the Free Software Foundation; either version 2
0007  * of the License, or (at your option) any later version.
0008  *
0009  * This program is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  * GNU General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU General Public License
0015  * along with this program; if not, write to the Free Software
0016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
0017  */
0018 
0019 #include <asm/asm.h>
0020 #include <asm/regdef.h>
0021 #include <asm/mipsregs.h>
0022 #include <asm/stackframe.h>
0023 #include <asm/cacheops.h>
0024 #include <asm/sibyte/board.h>
0025 
0026 #define C0_ERRCTL     $26         /* CP0: Error info */
0027 #define C0_CERR_I     $27         /* CP0: Icache error */
0028 #define C0_CERR_D     $27,1       /* CP0: Dcache error */
0029 
0030     /*
0031      * Based on SiByte sample software cache-err/cerr.S
0032      * CVS revision 1.8.  Only the 'unrecoverable' case
0033      * is changed.
0034      */
0035 
0036     .set    mips64
0037     .set    noreorder
0038     .set    noat
0039 
0040     /*
0041      * sb1_cerr_vec: code to be copied to the Cache Error
0042      * Exception vector.  The code must be pushed out to memory
0043      * (either by copying to Kseg0 and Kseg1 both, or by flushing
0044      * the L1 and L2) since it is fetched as 0xa0000100.
0045      *
0046      * NOTE: Be sure this handler is at most 28 instructions long
0047      * since the final 16 bytes of the exception vector memory
0048      * (0x170-0x17f) are used to preserve k0, k1, and ra.
0049      */
0050 
0051 LEAF(except_vec2_sb1)
0052     /*
0053      * If this error is recoverable, we need to exit the handler
0054      * without having dirtied any registers.  To do this,
0055      * save/restore k0 and k1 from low memory (Useg is direct
0056      * mapped while ERL=1). Note that we can't save to a
0057      * CPU-specific location without ruining a register in the
0058      * process.  This means we are vulnerable to data corruption
0059      * whenever the handler is reentered by a second CPU.
0060      */
0061     sd  k0,0x170($0)
0062     sd  k1,0x178($0)
0063 
0064 #ifdef CONFIG_SB1_CEX_ALWAYS_FATAL
0065     j   handle_vec2_sb1
0066      nop
0067 #else
0068     /*
0069      * M_ERRCTL_RECOVERABLE is bit 31, which makes it easy to tell
0070      * if we can fast-path out of here for a h/w-recovered error.
0071      */
0072     mfc0    k1,C0_ERRCTL
0073     bgtz    k1,attempt_recovery
0074      sll    k0,k1,1
0075 
0076 recovered_dcache:
0077     /*
0078      * Unlock CacheErr-D (which in turn unlocks CacheErr-DPA).
0079      * Ought to log the occurrence of this recovered dcache error.
0080      */
0081     b   recovered
0082      mtc0   $0,C0_CERR_D
0083 
0084 attempt_recovery:
0085     /*
0086      * k0 has C0_ERRCTL << 1, which puts 'DC' at bit 31.  Any
0087      * Dcache errors we can recover from will take more extensive
0088      * processing.  For now, they are considered "unrecoverable".
0089      * Note that 'DC' becoming set (outside of ERL mode) will
0090      * cause 'IC' to clear; so if there's an Icache error, we'll
0091      * only find out about it if we recover from this error and
0092      * continue executing.
0093      */
0094     bltz    k0,unrecoverable
0095      sll    k0,1
0096 
0097     /*
0098      * k0 has C0_ERRCTL << 2, which puts 'IC' at bit 31.  If an
0099      * Icache error isn't indicated, I'm not sure why we got here.
0100      * Consider that case "unrecoverable" for now.
0101      */
0102     bgez    k0,unrecoverable
0103 
0104 attempt_icache_recovery:
0105     /*
0106      * External icache errors are due to uncorrectable ECC errors
0107      * in the L2 cache or Memory Controller and cannot be
0108      * recovered here.
0109      */
0110      mfc0   k0,C0_CERR_I        /* delay slot */
0111     li  k1,1 << 26      /* ICACHE_EXTERNAL */
0112     and k1,k0
0113     bnez    k1,unrecoverable
0114      andi   k0,0x1fe0
0115 
0116     /*
0117      * Since the error is internal, the 'IDX' field from
0118      * CacheErr-I is valid and we can just invalidate all blocks
0119      * in that set.
0120      */
0121     cache   Index_Invalidate_I,(0<<13)(k0)
0122     cache   Index_Invalidate_I,(1<<13)(k0)
0123     cache   Index_Invalidate_I,(2<<13)(k0)
0124     cache   Index_Invalidate_I,(3<<13)(k0)
0125 
0126     /* Ought to log this recovered icache error */
0127 
0128 recovered:
0129     /* Restore the saved registers */
0130     ld  k0,0x170($0)
0131     ld  k1,0x178($0)
0132     eret
0133 
0134 unrecoverable:
0135     /* Unrecoverable Icache or Dcache error; log it and/or fail */
0136     j   handle_vec2_sb1
0137      nop
0138 #endif
0139 
0140 END(except_vec2_sb1)
0141 
0142     LEAF(handle_vec2_sb1)
0143     mfc0    k0,CP0_CONFIG
0144     li  k1,~CONF_CM_CMASK
0145     and k0,k0,k1
0146     ori k0,k0,CONF_CM_UNCACHED
0147     mtc0    k0,CP0_CONFIG
0148 
0149     SSNOP
0150     SSNOP
0151     SSNOP
0152     SSNOP
0153     bnezl   $0, 1f
0154 1:
0155     mfc0    k0, CP0_STATUS
0156     sll k0, k0, 3           # check CU0 (kernel?)
0157     bltz    k0, 2f
0158      nop
0159 
0160     /* Get a valid Kseg0 stack pointer.  Any task's stack pointer
0161      * will do, although if we ever want to resume execution we
0162      * better not have corrupted any state. */
0163     get_saved_sp
0164     move    sp, k1
0165 
0166 2:
0167     j   sb1_cache_error
0168      nop
0169 
0170     END(handle_vec2_sb1)