^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <asm/asm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <asm/regdef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <asm/mipsregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/stackframe.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/cacheops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/sibyte/board.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define C0_ERRCTL $26 /* CP0: Error info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define C0_CERR_I $27 /* CP0: Icache error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define C0_CERR_D $27,1 /* CP0: Dcache error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Based on SiByte sample software cache-err/cerr.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * CVS revision 1.8. Only the 'unrecoverable' case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * is changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) .set mips64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) .set noreorder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) .set noat
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * sb1_cerr_vec: code to be copied to the Cache Error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * Exception vector. The code must be pushed out to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * (either by copying to Kseg0 and Kseg1 both, or by flushing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * the L1 and L2) since it is fetched as 0xa0000100.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * NOTE: Be sure this handler is at most 28 instructions long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * since the final 16 bytes of the exception vector memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * (0x170-0x17f) are used to preserve k0, k1, and ra.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) LEAF(except_vec2_sb1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * If this error is recoverable, we need to exit the handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * without having dirtied any registers. To do this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * save/restore k0 and k1 from low memory (Useg is direct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * mapped while ERL=1). Note that we can't save to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * CPU-specific location without ruining a register in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * process. This means we are vulnerable to data corruption
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * whenever the handler is reentered by a second CPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) sd k0,0x170($0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) sd k1,0x178($0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #ifdef CONFIG_SB1_CEX_ALWAYS_FATAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) j handle_vec2_sb1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * M_ERRCTL_RECOVERABLE is bit 31, which makes it easy to tell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * if we can fast-path out of here for a h/w-recovered error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) mfc0 k1,C0_ERRCTL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) bgtz k1,attempt_recovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) sll k0,k1,1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) recovered_dcache:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * Unlock CacheErr-D (which in turn unlocks CacheErr-DPA).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * Ought to log the occurrence of this recovered dcache error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) b recovered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) mtc0 $0,C0_CERR_D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) attempt_recovery:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * k0 has C0_ERRCTL << 1, which puts 'DC' at bit 31. Any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Dcache errors we can recover from will take more extensive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * processing. For now, they are considered "unrecoverable".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * Note that 'DC' becoming set (outside of ERL mode) will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * cause 'IC' to clear; so if there's an Icache error, we'll
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * only find out about it if we recover from this error and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * continue executing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) bltz k0,unrecoverable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) sll k0,1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * k0 has C0_ERRCTL << 2, which puts 'IC' at bit 31. If an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * Icache error isn't indicated, I'm not sure why we got here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * Consider that case "unrecoverable" for now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) bgez k0,unrecoverable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) attempt_icache_recovery:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * External icache errors are due to uncorrectable ECC errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * in the L2 cache or Memory Controller and cannot be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * recovered here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) mfc0 k0,C0_CERR_I /* delay slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) li k1,1 << 26 /* ICACHE_EXTERNAL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) and k1,k0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) bnez k1,unrecoverable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) andi k0,0x1fe0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * Since the error is internal, the 'IDX' field from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * CacheErr-I is valid and we can just invalidate all blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * in that set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) cache Index_Invalidate_I,(0<<13)(k0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) cache Index_Invalidate_I,(1<<13)(k0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) cache Index_Invalidate_I,(2<<13)(k0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) cache Index_Invalidate_I,(3<<13)(k0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* Ought to log this recovered icache error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) recovered:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* Restore the saved registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ld k0,0x170($0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ld k1,0x178($0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) eret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) unrecoverable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* Unrecoverable Icache or Dcache error; log it and/or fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) j handle_vec2_sb1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) END(except_vec2_sb1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) LEAF(handle_vec2_sb1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) mfc0 k0,CP0_CONFIG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) li k1,~CONF_CM_CMASK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) and k0,k0,k1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ori k0,k0,CONF_CM_UNCACHED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) mtc0 k0,CP0_CONFIG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) SSNOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) SSNOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) SSNOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) SSNOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) bnezl $0, 1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) mfc0 k0, CP0_STATUS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) sll k0, k0, 3 # check CU0 (kernel?)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) bltz k0, 2f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* Get a valid Kseg0 stack pointer. Any task's stack pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * will do, although if we ever want to resume execution we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * better not have corrupted any state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) get_saved_sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) move sp, k1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) j sb1_cache_error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) END(handle_vec2_sb1)