^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2001,2002,2003 Broadcom Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <asm/mipsregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <asm/sibyte/sb1250.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <asm/sibyte/sb1250_regs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #if !defined(CONFIG_SIBYTE_BUS_WATCHER) || defined(CONFIG_SIBYTE_BW_TRACE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/sibyte/sb1250_scd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * We'd like to dump the L2_ECC_TAG register on errors, but errata make
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * that unsafe... So for now we don't. (BCM1250/BCM112x erratum SOC-48.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #undef DUMP_L2_ECC_TAG_ON_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* SB1 definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* XXX should come from config1 XXX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define SB1_CACHE_INDEX_MASK 0x1fe0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define CP0_ERRCTL_RECOVERABLE (1 << 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define CP0_ERRCTL_DCACHE (1 << 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define CP0_ERRCTL_ICACHE (1 << 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define CP0_ERRCTL_MULTIBUS (1 << 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define CP0_ERRCTL_MC_TLB (1 << 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define CP0_ERRCTL_MC_TIMEOUT (1 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define CP0_CERRI_TAG_PARITY (1 << 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define CP0_CERRI_DATA_PARITY (1 << 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define CP0_CERRI_EXTERNAL (1 << 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define CP0_CERRI_IDX_VALID(c) (!((c) & CP0_CERRI_EXTERNAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define CP0_CERRI_DATA (CP0_CERRI_DATA_PARITY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define CP0_CERRD_MULTIPLE (1 << 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define CP0_CERRD_TAG_STATE (1 << 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define CP0_CERRD_TAG_ADDRESS (1 << 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define CP0_CERRD_DATA_SBE (1 << 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define CP0_CERRD_DATA_DBE (1 << 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define CP0_CERRD_EXTERNAL (1 << 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define CP0_CERRD_LOAD (1 << 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define CP0_CERRD_STORE (1 << 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define CP0_CERRD_FILLWB (1 << 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define CP0_CERRD_COHERENCY (1 << 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define CP0_CERRD_DUPTAG (1 << 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define CP0_CERRD_DPA_VALID(c) (!((c) & CP0_CERRD_EXTERNAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define CP0_CERRD_IDX_VALID(c) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) (((c) & (CP0_CERRD_LOAD | CP0_CERRD_STORE)) ? (!((c) & CP0_CERRD_EXTERNAL)) : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define CP0_CERRD_CAUSES \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) (CP0_CERRD_LOAD | CP0_CERRD_STORE | CP0_CERRD_FILLWB | CP0_CERRD_COHERENCY | CP0_CERRD_DUPTAG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define CP0_CERRD_TYPES \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) (CP0_CERRD_TAG_STATE | CP0_CERRD_TAG_ADDRESS | CP0_CERRD_DATA_SBE | CP0_CERRD_DATA_DBE | CP0_CERRD_EXTERNAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define CP0_CERRD_DATA (CP0_CERRD_DATA_SBE | CP0_CERRD_DATA_DBE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static uint32_t extract_ic(unsigned short addr, int data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static uint32_t extract_dc(unsigned short addr, int data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static inline void breakout_errctl(unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (val & CP0_ERRCTL_RECOVERABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) printk(" recoverable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (val & CP0_ERRCTL_DCACHE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) printk(" dcache");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (val & CP0_ERRCTL_ICACHE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) printk(" icache");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (val & CP0_ERRCTL_MULTIBUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) printk(" multiple-buserr");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static inline void breakout_cerri(unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (val & CP0_CERRI_TAG_PARITY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) printk(" tag-parity");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (val & CP0_CERRI_DATA_PARITY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) printk(" data-parity");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (val & CP0_CERRI_EXTERNAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) printk(" external");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static inline void breakout_cerrd(unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) switch (val & CP0_CERRD_CAUSES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) case CP0_CERRD_LOAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) printk(" load,");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) case CP0_CERRD_STORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) printk(" store,");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) case CP0_CERRD_FILLWB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) printk(" fill/wb,");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) case CP0_CERRD_COHERENCY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) printk(" coherency,");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) case CP0_CERRD_DUPTAG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) printk(" duptags,");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) printk(" NO CAUSE,");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (!(val & CP0_CERRD_TYPES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) printk(" NO TYPE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (val & CP0_CERRD_MULTIPLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) printk(" multi-err");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (val & CP0_CERRD_TAG_STATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) printk(" tag-state");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (val & CP0_CERRD_TAG_ADDRESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) printk(" tag-address");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (val & CP0_CERRD_DATA_SBE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) printk(" data-SBE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (val & CP0_CERRD_DATA_DBE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) printk(" data-DBE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (val & CP0_CERRD_EXTERNAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) printk(" external");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #ifndef CONFIG_SIBYTE_BUS_WATCHER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static void check_bus_watcher(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) uint32_t status, l2_err, memio_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #ifdef DUMP_L2_ECC_TAG_ON_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) uint64_t l2_tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Destructive read, clears register and interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* Bit 31 is always on, but there's no #define for that */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (status & ~(1UL << 31)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #ifdef DUMP_L2_ECC_TAG_ON_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) l2_tag = in64(IOADDR(A_L2_ECC_TAG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) printk("Bus watcher error counters: %08x %08x\n", l2_err, memio_err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) printk("\nLast recorded signature:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) printk("Request %02x from %d, answered by %d with Dcode %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) (unsigned int)(G_SCD_BERR_TID(status) & 0x3f),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) (int)(G_SCD_BERR_TID(status) >> 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) (int)G_SCD_BERR_RID(status),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) (int)G_SCD_BERR_DCODE(status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #ifdef DUMP_L2_ECC_TAG_ON_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) printk("Last L2 tag w/ bad ECC: %016llx\n", l2_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) printk("Bus watcher indicates no error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) extern void check_bus_watcher(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) asmlinkage void sb1_cache_error(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) uint32_t errctl, cerr_i, cerr_d, dpalo, dpahi, eepc, res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned long long cerr_dpa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #ifdef CONFIG_SIBYTE_BW_TRACE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* Freeze the trace buffer now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) printk("Trace buffer frozen\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) printk("Cache error exception on CPU %x:\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) (read_c0_prid() >> 25) & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) __asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) " .set push\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) " .set mips64\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) " .set noat\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) " mfc0 %0, $26\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) " mfc0 %1, $27\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) " mfc0 %2, $27, 1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) " dmfc0 $1, $27, 3\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) " dsrl32 %3, $1, 0 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) " sll %4, $1, 0 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) " mfc0 %5, $30\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) " .set pop"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) : "=r" (errctl), "=r" (cerr_i), "=r" (cerr_d),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) "=r" (dpahi), "=r" (dpalo), "=r" (eepc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) cerr_dpa = (((uint64_t)dpahi) << 32) | dpalo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) printk(" c0_errorepc == %08x\n", eepc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) printk(" c0_errctl == %08x", errctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) breakout_errctl(errctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (errctl & CP0_ERRCTL_ICACHE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) printk(" c0_cerr_i == %08x", cerr_i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) breakout_cerri(cerr_i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (CP0_CERRI_IDX_VALID(cerr_i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* Check index of EPC, allowing for delay slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (((eepc & SB1_CACHE_INDEX_MASK) != (cerr_i & SB1_CACHE_INDEX_MASK)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ((eepc & SB1_CACHE_INDEX_MASK) != ((cerr_i & SB1_CACHE_INDEX_MASK) - 4)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) printk(" cerr_i idx doesn't match eepc\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) res = extract_ic(cerr_i & SB1_CACHE_INDEX_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) (cerr_i & CP0_CERRI_DATA) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (!(res & cerr_i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) printk("...didn't see indicated icache problem\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (errctl & CP0_ERRCTL_DCACHE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) printk(" c0_cerr_d == %08x", cerr_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) breakout_cerrd(cerr_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (CP0_CERRD_DPA_VALID(cerr_d)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) printk(" c0_cerr_dpa == %010llx\n", cerr_dpa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (!CP0_CERRD_IDX_VALID(cerr_d)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) res = extract_dc(cerr_dpa & SB1_CACHE_INDEX_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) (cerr_d & CP0_CERRD_DATA) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!(res & cerr_d))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) printk("...didn't see indicated dcache problem\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if ((cerr_dpa & SB1_CACHE_INDEX_MASK) != (cerr_d & SB1_CACHE_INDEX_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) printk(" cerr_d idx doesn't match cerr_dpa\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) res = extract_dc(cerr_d & SB1_CACHE_INDEX_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) (cerr_d & CP0_CERRD_DATA) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (!(res & cerr_d))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) printk("...didn't see indicated problem\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) check_bus_watcher();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * Calling panic() when a fatal cache error occurs scrambles the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * state of the system (and the cache), making it difficult to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * investigate after the fact. However, if you just stall the CPU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * the other CPU may keep on running, which is typically very
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * undesirable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) #ifdef CONFIG_SB1_CERR_STALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) while (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) panic("unhandled cache error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* Parity lookup table. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static const uint8_t parity[256] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* Masks to select bits for Hamming parity, mask_72_64[i] for bit[i] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static const uint64_t mask_72_64[8] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 0x0738C808099264FFULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 0x38C808099264FF07ULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 0xC808099264FF0738ULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 0x08099264FF0738C8ULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 0x099264FF0738C808ULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 0x9264FF0738C80809ULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 0x64FF0738C8080992ULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 0xFF0738C808099264ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /* Calculate the parity on a range of bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static char range_parity(uint64_t dword, int max, int min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) char parity = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) dword >>= min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) for (i=max-min; i>=0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (dword & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) parity = !parity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) dword >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return parity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* Calculate the 4-bit even byte-parity for an instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static unsigned char inst_parity(uint32_t word)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) char parity = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) for (j=0; j<4; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) char byte_parity = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) for (i=0; i<8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (word & 0x80000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) byte_parity = !byte_parity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) word <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) parity <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) parity |= byte_parity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return parity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static uint32_t extract_ic(unsigned short addr, int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) unsigned short way;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) int valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) uint32_t taghi, taglolo, taglohi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) unsigned long long taglo, va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) uint64_t tlo_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) uint8_t lru;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) printk("Icache index 0x%04x ", addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) for (way = 0; way < 4; way++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /* Index-load-tag-I */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) __asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) " .set push \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) " .set noreorder \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) " .set mips64 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) " .set noat \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) " cache 4, 0(%3) \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) " mfc0 %0, $29 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) " dmfc0 $1, $28 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) " dsrl32 %1, $1, 0 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) " sll %2, $1, 0 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) " .set pop"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) : "=r" (taghi), "=r" (taglohi), "=r" (taglolo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) : "r" ((way << 13) | addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) taglo = ((unsigned long long)taglohi << 32) | taglolo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (way == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) lru = (taghi >> 14) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) printk("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) ((addr >> 5) & 0x3), /* bank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) ((addr >> 7) & 0x3f), /* index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) (lru & 0x3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ((lru >> 2) & 0x3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) ((lru >> 4) & 0x3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) ((lru >> 6) & 0x3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) va = (taglo & 0xC0000FFFFFFFE000ULL) | addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if ((taglo & (1 << 31)) && (((taglo >> 62) & 0x3) == 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) va |= 0x3FFFF00000000000ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) valid = ((taghi >> 29) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) tlo_tmp = taglo & 0xfff3ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (((taglo >> 10) & 1) ^ range_parity(tlo_tmp, 23, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) printk(" ** bad parity in VTag0/G/ASID\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) res |= CP0_CERRI_TAG_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (((taglo >> 11) & 1) ^ range_parity(taglo, 63, 24)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) printk(" ** bad parity in R/VTag1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) res |= CP0_CERRI_TAG_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (valid ^ ((taghi >> 27) & 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) printk(" ** bad parity for valid bit\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) res |= CP0_CERRI_TAG_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) printk(" %d [VA %016llx] [Vld? %d] raw tags: %08X-%016llX\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) way, va, valid, taghi, taglo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) uint32_t datahi, insta, instb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) uint8_t predecode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) /* (hit all banks and ways) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) for (offset = 0; offset < 4; offset++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* Index-load-data-I */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) __asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) " .set push\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) " .set noreorder\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) " .set mips64\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) " .set noat\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) " cache 6, 0(%3) \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) " mfc0 %0, $29, 1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) " dmfc0 $1, $28, 1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) " dsrl32 %1, $1, 0 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) " sll %2, $1, 0 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) " .set pop \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) : "=r" (datahi), "=r" (insta), "=r" (instb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) : "r" ((way << 13) | addr | (offset << 3)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) predecode = (datahi >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (((datahi >> 16) & 1) != (uint32_t)range_parity(predecode, 7, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) printk(" ** bad parity in predecode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) res |= CP0_CERRI_DATA_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* XXXKW should/could check predecode bits themselves */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (((datahi >> 4) & 0xf) ^ inst_parity(insta)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) printk(" ** bad parity in instruction a\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) res |= CP0_CERRI_DATA_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if ((datahi & 0xf) ^ inst_parity(instb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) printk(" ** bad parity in instruction b\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) res |= CP0_CERRI_DATA_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) printk(" %05X-%08X%08X", datahi, insta, instb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /* Compute the ECC for a data doubleword */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static uint8_t dc_ecc(uint64_t dword)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) uint64_t t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) uint32_t w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) uint8_t p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) p = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) for (i = 7; i >= 0; i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) p <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) t = dword & mask_72_64[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) w = (uint32_t)(t >> 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) w = (uint32_t)(t & 0xFFFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct dc_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static struct dc_state dc_states[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) { 0x00, "INVALID" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) { 0x0f, "COH-SHD" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) { 0x13, "NCO-E-C" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) { 0x19, "NCO-E-D" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) { 0x16, "COH-E-C" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) { 0x1c, "COH-E-D" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) { 0xff, "*ERROR*" }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) #define DC_TAG_VALID(state) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) (((state) == 0x0) || ((state) == 0xf) || ((state) == 0x13) || \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) ((state) == 0x19) || ((state) == 0x16) || ((state) == 0x1c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) static char *dc_state_str(unsigned char state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) struct dc_state *dsc = dc_states;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) while (dsc->val != 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (dsc->val == state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) dsc++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return dsc->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static uint32_t extract_dc(unsigned short addr, int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) int valid, way;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) unsigned char state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) uint32_t taghi, taglolo, taglohi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) unsigned long long taglo, pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) uint8_t ecc, lru;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) printk("Dcache index 0x%04x ", addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) for (way = 0; way < 4; way++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) __asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) " .set push\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) " .set noreorder\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) " .set mips64\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) " .set noat\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) " cache 5, 0(%3)\n\t" /* Index-load-tag-D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) " mfc0 %0, $29, 2\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) " dmfc0 $1, $28, 2\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) " dsrl32 %1, $1, 0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) " sll %2, $1, 0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) " .set pop"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) : "=r" (taghi), "=r" (taglohi), "=r" (taglolo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) : "r" ((way << 13) | addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) taglo = ((unsigned long long)taglohi << 32) | taglolo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) pa = (taglo & 0xFFFFFFE000ULL) | addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (way == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) lru = (taghi >> 14) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) printk("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) ((addr >> 11) & 0x2) | ((addr >> 5) & 1), /* bank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) ((addr >> 6) & 0x3f), /* index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) (lru & 0x3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ((lru >> 2) & 0x3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) ((lru >> 4) & 0x3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) ((lru >> 6) & 0x3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) state = (taghi >> 25) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) valid = DC_TAG_VALID(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) printk(" %d [PA %010llx] [state %s (%02x)] raw tags: %08X-%016llX\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) way, pa, dc_state_str(state), state, taghi, taglo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (((taglo >> 11) & 1) ^ range_parity(taglo, 39, 26)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) printk(" ** bad parity in PTag1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) res |= CP0_CERRD_TAG_ADDRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (((taglo >> 10) & 1) ^ range_parity(taglo, 25, 13)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) printk(" ** bad parity in PTag0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) res |= CP0_CERRD_TAG_ADDRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) res |= CP0_CERRD_TAG_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) uint32_t datalohi, datalolo, datahi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) unsigned long long datalo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) char bad_ecc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) for (offset = 0; offset < 4; offset++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) /* Index-load-data-D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) __asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) " .set push\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) " .set noreorder\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) " .set mips64\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) " .set noat\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) " cache 7, 0(%3)\n\t" /* Index-load-data-D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) " mfc0 %0, $29, 3\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) " dmfc0 $1, $28, 3\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) " dsrl32 %1, $1, 0 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) " sll %2, $1, 0 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) " .set pop"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) : "=r" (datahi), "=r" (datalohi), "=r" (datalolo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) : "r" ((way << 13) | addr | (offset << 3)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) datalo = ((unsigned long long)datalohi << 32) | datalolo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ecc = dc_ecc(datalo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (ecc != datahi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) int bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) bad_ecc |= 1 << (3-offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ecc ^= datahi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) bits = hweight8(ecc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) printk(" %02X-%016llX", datahi, datalo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (bad_ecc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) printk(" dwords w/ bad ECC: %d %d %d %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) !!(bad_ecc & 8), !!(bad_ecc & 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) !!(bad_ecc & 2), !!(bad_ecc & 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }