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