16330Sjc25722 /*
26330Sjc25722 * CDDL HEADER START
36330Sjc25722 *
46330Sjc25722 * The contents of this file are subject to the terms of the
56330Sjc25722 * Common Development and Distribution License (the "License").
66330Sjc25722 * You may not use this file except in compliance with the License.
76330Sjc25722 *
86330Sjc25722 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96330Sjc25722 * or http://www.opensolaris.org/os/licensing.
106330Sjc25722 * See the License for the specific language governing permissions
116330Sjc25722 * and limitations under the License.
126330Sjc25722 *
136330Sjc25722 * When distributing Covered Code, include this CDDL HEADER in each
146330Sjc25722 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156330Sjc25722 * If applicable, add the following below this CDDL HEADER, with the
166330Sjc25722 * fields enclosed by brackets "[]" replaced with your own identifying
176330Sjc25722 * information: Portions Copyright [yyyy] [name of copyright owner]
186330Sjc25722 *
196330Sjc25722 * CDDL HEADER END
206330Sjc25722 */
216330Sjc25722 /*
22*10784Ssinanallur.balasubramanian@sun.com * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
236330Sjc25722 * Use is subject to license terms.
246330Sjc25722 */
256330Sjc25722
266330Sjc25722
276330Sjc25722 /*
286330Sjc25722 * Support routines for managing per-Lxcache state.
296330Sjc25722 */
306330Sjc25722
316330Sjc25722 #include <sys/types.h>
326330Sjc25722 #include <errno.h>
336330Sjc25722 #include <strings.h>
346330Sjc25722 #include <sys/stat.h>
356330Sjc25722 #include <fcntl.h>
366330Sjc25722 #include <unistd.h>
376330Sjc25722 #include <stropts.h>
386330Sjc25722 #include <fm/fmd_api.h>
396330Sjc25722 #include <sys/fm/protocol.h>
406330Sjc25722 #include <sys/fm/cpu/UltraSPARC-III.h>
416330Sjc25722 #include <sys/cpuvar.h>
426330Sjc25722 #include <cmd_Lxcache.h>
436330Sjc25722 #include <cmd_mem.h>
446330Sjc25722 #include <cmd_cpu.h>
456330Sjc25722 #include <cmd_state.h>
466330Sjc25722 #include <cmd.h>
476330Sjc25722 #define _KERNEL
486330Sjc25722 #include <sys/cheetahregs.h>
496330Sjc25722 #include <sys/mem_cache.h>
506330Sjc25722 #undef _KERNEL
516330Sjc25722 #include <sys/errclassify.h>
526330Sjc25722 #include <sys/fm/io/sun4upci.h>
536330Sjc25722
546330Sjc25722 #include <fmd_adm.h>
556330Sjc25722 #include <fmd_adm_impl.h>
566330Sjc25722 #include <fmd_rpc_adm.h>
576330Sjc25722
586330Sjc25722 #define PN_CACHE_ERRORS (CMD_ERRCL_UCC | CMD_ERRCL_WDC | \
596330Sjc25722 CMD_ERRCL_CPC | CMD_ERRCL_EDC | \
606330Sjc25722 CMD_ERRCL_L3_UCC | CMD_ERRCL_L3_CPC |\
616330Sjc25722 CMD_ERRCL_L3_WDC | CMD_ERRCL_L3_EDC)
626330Sjc25722
636330Sjc25722 /* Note that these are the same for panther L2 and L3 (see prm) */
646330Sjc25722
656330Sjc25722 #define LX_INDEX_MASK PN_L2_INDEX_MASK
666330Sjc25722 #define LX_INDEX_SHIFT 6
676330Sjc25722 #define PN_ECSTATE_NA 5
68*10784Ssinanallur.balasubramanian@sun.com #define PN_ECSTATE_INV 0
696330Sjc25722
70*10784Ssinanallur.balasubramanian@sun.com #define PN_L3_INDEX_MASK PN_L3_TAG_RD_MASK
716330Sjc25722
72*10784Ssinanallur.balasubramanian@sun.com static const errdata_t l3errdata =
736330Sjc25722 { &cmd.cmd_l3data_serd, "l3cachedata", CMD_PTR_LxCACHE_CASE };
74*10784Ssinanallur.balasubramanian@sun.com static const errdata_t l2errdata =
756330Sjc25722 { &cmd.cmd_l2data_serd, "l2cachedata", CMD_PTR_LxCACHE_CASE };
766330Sjc25722
77*10784Ssinanallur.balasubramanian@sun.com /* Macro for putting 64-bit onto stack as two 32-bit ints */
78*10784Ssinanallur.balasubramanian@sun.com #define PRTF_64_TO_32(x) (uint32_t)((x)>>32), (uint32_t)(x)
796330Sjc25722
806330Sjc25722 #define LX_PA_MASK2_32BIT_CORRECT 16
816330Sjc25722 #define LX_PA_MASK3_32BIT_CORRECT 24
826330Sjc25722 #define LX_PA_MASK2 0x7fffff8
836330Sjc25722 #define LX_PA_MASK3 0x7ffff8
846330Sjc25722
856330Sjc25722
866330Sjc25722 #define MAX_RETRIES_FOR_ECC_MATCH 3
876330Sjc25722 #define PN_TAG_ECC_MASK 0x7fc0
886330Sjc25722 #define PN_L2_PTAG_SHIFT 19
896330Sjc25722 #define PN_L3_PTAG_SHIFT 24
906330Sjc25722 #define L2_PTAG_MASK 0xffffff
916330Sjc25722 #define L3_PTAG_MASK 0xfffff
926330Sjc25722 #define BIT_MASK 0x7f
936330Sjc25722 #define MSB_BIT 0x8000
94*10784Ssinanallur.balasubramanian@sun.com #define SET_MSB_BIT 0x8000
95*10784Ssinanallur.balasubramanian@sun.com #define CLEAR_MSB_BIT 0x7fff
96*10784Ssinanallur.balasubramanian@sun.com #define PN_LX_TAG_ECC_START_BIT 6
97*10784Ssinanallur.balasubramanian@sun.com #define PN_LX_TAG_ECC_END_BIT 14
98*10784Ssinanallur.balasubramanian@sun.com #define PN_LX_STATE_END_BIT 2
99*10784Ssinanallur.balasubramanian@sun.com #define PN_LX_NUM_OF_BITS_IN_ECC 9
1006330Sjc25722
1016330Sjc25722 #define LX_NWAYS 4
1026330Sjc25722
1036330Sjc25722 int test_mode = 0; /* should be 0 in production version. */
104*10784Ssinanallur.balasubramanian@sun.com #define FM_EREPORT_RECHECK_OF_TAGS "recheck_tags"
105*10784Ssinanallur.balasubramanian@sun.com #define RETRIES_TO_BE_DONE_WHEN_SYND_IS_ZERO 3
106*10784Ssinanallur.balasubramanian@sun.com uint32_t cmd_Lxcache_recheck_tags_delay
107*10784Ssinanallur.balasubramanian@sun.com [RETRIES_TO_BE_DONE_WHEN_SYND_IS_ZERO + 1] = {0, 1, 2, 4};
1086330Sjc25722
1096330Sjc25722 /*
1106330Sjc25722 * e (for ecctable) maps single bit positions (0-127, or 0-0x7F) to the
1116330Sjc25722 * corresponding ECC syndromes for an error in that position.
1126330Sjc25722 */
1136330Sjc25722 int e[] = {
1146330Sjc25722 /* From Table P-4, JPS1 US-III Supplement */
1156330Sjc25722 /* 0 1 2 3 4 5 6 7 */
1166330Sjc25722 /* 00 */ 0x03B, 0x127, 0x067, 0x097, 0x10F, 0x08F, 0x04F, 0x02C,
1176330Sjc25722 /* 08 */ 0x147, 0x0C7, 0x02F, 0x01C, 0x117, 0x032, 0x08A, 0x04A,
1186330Sjc25722 /* 10 */ 0x01F, 0x086, 0x046, 0x026, 0x09B, 0x08C, 0x0C1, 0x0A1,
1196330Sjc25722 /* 18 */ 0x01A, 0x016, 0x061, 0x091, 0x052, 0x00E, 0x109, 0x029,
1206330Sjc25722 /* 20 */ 0x02A, 0x019, 0x105, 0x085, 0x045, 0x025, 0x015, 0x103,
1216330Sjc25722 /* 28 */ 0x031, 0x00D, 0x083, 0x043, 0x051, 0x089, 0x023, 0x007,
1226330Sjc25722 /* 30 */ 0x0B9, 0x049, 0x013, 0x0A7, 0x057, 0x00B, 0x07A, 0x187,
1236330Sjc25722 /* 38 */ 0x0F8, 0x11B, 0x079, 0x034, 0x178, 0x1D8, 0x05B, 0x04C,
1246330Sjc25722 /* 40 */ 0x064, 0x1B4, 0x037, 0x03D, 0x058, 0x13C, 0x1B1, 0x03E,
1256330Sjc25722 /* 48 */ 0x1C3, 0x0BC, 0x1A0, 0x1D4, 0x1CA, 0x190, 0x124, 0x13A,
1266330Sjc25722 /* 50 */ 0x1C0, 0x188, 0x122, 0x114, 0x184, 0x182, 0x160, 0x118,
1276330Sjc25722 /* 58 */ 0x181, 0x150, 0x148, 0x144, 0x142, 0x141, 0x130, 0x0A8,
1286330Sjc25722 /* 60 */ 0x128, 0x121, 0x0E0, 0x094, 0x112, 0x10C, 0x0D0, 0x0B0,
1296330Sjc25722 /* 68 */ 0x10A, 0x106, 0x062, 0x1B2, 0x0C8, 0x0C4, 0x0C2, 0x1F0,
1306330Sjc25722 /* 70 */ 0x0A4, 0x0A2, 0x098, 0x1D1, 0x070, 0x1E8, 0x1C6, 0x1C5,
1316330Sjc25722 /* 78 */ 0x068, 0x1E4, 0x1E2, 0x1E1, 0x1D2, 0x1CC, 0x1C9, 0x1B8,
1326330Sjc25722 /* Now we have the check bits */
1336330Sjc25722 /* C0 C1 C2 C3 C4 C5 C6 C7 C8 */
1346330Sjc25722 0x001, 0x002, 0x004, 0x008, 0x010, 0x020, 0x040, 0x080, 0x100,
1356330Sjc25722 };
1366330Sjc25722
1376330Sjc25722 #define NBITS (sizeof (e)/sizeof (e[0]))
1386330Sjc25722 #define NDATABITS (128)
1396330Sjc25722 /*
1406330Sjc25722 * This table is used to determine which bit(s) is(are) bad when an ECC
1416330Sjc25722 * error occurs. The array is indexed by an 9-bit syndrome. The entries
1426330Sjc25722 * of this array have the following semantics:
1436330Sjc25722 *
1446330Sjc25722 * 00-127 The number of the bad bit, when only one bit is bad.
1456330Sjc25722 * 128 ECC bit C0 is bad.
1466330Sjc25722 * 129 ECC bit C1 is bad.
1476330Sjc25722 * 130 ECC bit C2 is bad.
1486330Sjc25722 * 131 ECC bit C3 is bad.
1496330Sjc25722 * 132 ECC bit C4 is bad.
1506330Sjc25722 * 133 ECC bit C5 is bad.
1516330Sjc25722 * 134 ECC bit C6 is bad.
1526330Sjc25722 * 135 ECC bit C7 is bad.
1536330Sjc25722 * 136 ECC bit C8 is bad.
1546330Sjc25722 * 137-143 reserved for Mtag Data and ECC.
1556330Sjc25722 * 144(M2) Two bits are bad within a nibble.
1566330Sjc25722 * 145(M3) Three bits are bad within a nibble.
1576330Sjc25722 * 146(M3) Four bits are bad within a nibble.
1586330Sjc25722 * 147(M) Multiple bits (5 or more) are bad.
1596330Sjc25722 * 148 NO bits are bad.
1606330Sjc25722 * Based on "Cheetah Programmer's Reference Manual" rev 1.1, Tables 11-4,11-5.
1616330Sjc25722 */
1626330Sjc25722
1636330Sjc25722 #define C0 128
1646330Sjc25722 #define C1 129
1656330Sjc25722 #define C2 130
1666330Sjc25722 #define C3 131
1676330Sjc25722 #define C4 132
1686330Sjc25722 #define C5 133
1696330Sjc25722 #define C6 134
1706330Sjc25722 #define C7 135
1716330Sjc25722 #define C8 136
1726330Sjc25722 #define MT0 137 /* Mtag Data bit 0 */
1736330Sjc25722 #define MT1 138
1746330Sjc25722 #define MT2 139
1756330Sjc25722 #define MTC0 140 /* Mtag Check bit 0 */
1766330Sjc25722 #define MTC1 141
1776330Sjc25722 #define MTC2 142
1786330Sjc25722 #define MTC3 143
1796330Sjc25722 #define M2 144
1806330Sjc25722 #define M3 145
1816330Sjc25722 #define M4 146
1826330Sjc25722 #define M 147
1836330Sjc25722 #define NA 148
1846330Sjc25722 #if defined(JALAPENO) || defined(SERRANO)
1856330Sjc25722 #define S003 149 /* Syndrome 0x003 => likely from CPU/EDU:ST/FRU/BP */
1866330Sjc25722 #define S003MEM 150 /* Syndrome 0x003 => likely from WDU/WBP */
1876330Sjc25722 #define SLAST S003MEM /* last special syndrome */
1886330Sjc25722 #else /* JALAPENO || SERRANO */
1896330Sjc25722 #define S003 149 /* Syndrome 0x003 => likely from EDU:ST */
1906330Sjc25722 #define S071 150 /* Syndrome 0x071 => likely from WDU/CPU */
1916330Sjc25722 #define S11C 151 /* Syndrome 0x11c => likely from BERR/DBERR */
1926330Sjc25722 #define SLAST S11C /* last special syndrome */
1936330Sjc25722 #endif /* JALAPENO || SERRANO */
1946330Sjc25722 #if defined(JALAPENO) || defined(SERRANO)
1956330Sjc25722 #define BPAR0 152 /* syndrom 152 through 167 for bus parity */
1966330Sjc25722 #define BPAR15 167
1976330Sjc25722 #endif /* JALAPENO || SERRANO */
1986330Sjc25722
1996330Sjc25722 static uint8_t ecc_syndrome_tab[] =
2006330Sjc25722 {
2016330Sjc25722 NA, C0, C1, S003, C2, M2, M3, 47, C3, M2, M2, 53, M2, 41, 29, M,
2026330Sjc25722 C4, M, M, 50, M2, 38, 25, M2, M2, 33, 24, M2, 11, M, M2, 16,
2036330Sjc25722 C5, M, M, 46, M2, 37, 19, M2, M, 31, 32, M, 7, M2, M2, 10,
2046330Sjc25722 M2, 40, 13, M2, 59, M, M2, 66, M, M2, M2, 0, M2, 67, 71, M,
2056330Sjc25722 C6, M, M, 43, M, 36, 18, M, M2, 49, 15, M, 63, M2, M2, 6,
2066330Sjc25722 M2, 44, 28, M2, M, M2, M2, 52, 68, M2, M2, 62, M2, M3, M3, M4,
2076330Sjc25722 M2, 26, 106, M2, 64, M, M2, 2, 120, M, M2, M3, M, M3, M3, M4,
2086330Sjc25722 #if defined(JALAPENO) || defined(SERRANO)
2096330Sjc25722 116, M2, M2, M3, M2, M3, M, M4, M2, 58, 54, M2, M, M4, M4, M3,
2106330Sjc25722 #else /* JALAPENO || SERRANO */
2116330Sjc25722 116, S071, M2, M3, M2, M3, M, M4, M2, 58, 54, M2, M, M4, M4, M3,
2126330Sjc25722 #endif /* JALAPENO || SERRANO */
2136330Sjc25722 C7, M2, M, 42, M, 35, 17, M2, M, 45, 14, M2, 21, M2, M2, 5,
2146330Sjc25722 M, 27, M, M, 99, M, M, 3, 114, M2, M2, 20, M2, M3, M3, M,
2156330Sjc25722 M2, 23, 113, M2, 112, M2, M, 51, 95, M, M2, M3, M2, M3, M3, M2,
2166330Sjc25722 103, M, M2, M3, M2, M3, M3, M4, M2, 48, M, M, 73, M2, M, M3,
2176330Sjc25722 M2, 22, 110, M2, 109, M2, M, 9, 108, M2, M, M3, M2, M3, M3, M,
2186330Sjc25722 102, M2, M, M, M2, M3, M3, M, M2, M3, M3, M2, M, M4, M, M3,
2196330Sjc25722 98, M, M2, M3, M2, M, M3, M4, M2, M3, M3, M4, M3, M, M, M,
2206330Sjc25722 M2, M3, M3, M, M3, M, M, M, 56, M4, M, M3, M4, M, M, M,
2216330Sjc25722 C8, M, M2, 39, M, 34, 105, M2, M, 30, 104, M, 101, M, M, 4,
2226330Sjc25722 #if defined(JALAPENO) || defined(SERRANO)
2236330Sjc25722 M, M, 100, M, 83, M, M2, 12, 87, M, M, 57, M2, M, M3, M,
2246330Sjc25722 #else /* JALAPENO || SERRANO */
2256330Sjc25722 M, M, 100, M, 83, M, M2, 12, 87, M, M, 57, S11C, M, M3, M,
2266330Sjc25722 #endif /* JALAPENO || SERRANO */
2276330Sjc25722 M2, 97, 82, M2, 78, M2, M2, 1, 96, M, M, M, M, M, M3, M2,
2286330Sjc25722 94, M, M2, M3, M2, M, M3, M, M2, M, 79, M, 69, M, M4, M,
2296330Sjc25722 M2, 93, 92, M, 91, M, M2, 8, 90, M2, M2, M, M, M, M, M4,
2306330Sjc25722 89, M, M, M3, M2, M3, M3, M, M, M, M3, M2, M3, M2, M, M3,
2316330Sjc25722 86, M, M2, M3, M2, M, M3, M, M2, M, M3, M, M3, M, M, M3,
2326330Sjc25722 M, M, M3, M2, M3, M2, M4, M, 60, M, M2, M3, M4, M, M, M2,
2336330Sjc25722 M2, 88, 85, M2, 84, M, M2, 55, 81, M2, M2, M3, M2, M3, M3, M4,
2346330Sjc25722 77, M, M, M, M2, M3, M, M, M2, M3, M3, M4, M3, M2, M, M,
2356330Sjc25722 74, M, M2, M3, M, M, M3, M, M, M, M3, M, M3, M, M4, M3,
2366330Sjc25722 M2, 70, 107, M4, 65, M2, M2, M, 127, M, M, M, M2, M3, M3, M,
2376330Sjc25722 80, M2, M2, 72, M, 119, 118, M, M2, 126, 76, M, 125, M, M4, M3,
2386330Sjc25722 M2, 115, 124, M, 75, M, M, M3, 61, M, M4, M, M4, M, M, M,
2396330Sjc25722 M, 123, 122, M4, 121, M4, M, M3, 117, M2, M2, M3, M4, M3, M, M,
2406330Sjc25722 111, M, M, M, M4, M3, M3, M, M, M, M3, M, M3, M2, M, M
2416330Sjc25722 };
2426330Sjc25722
2436330Sjc25722 #define ESYND_TBL_SIZE (sizeof (ecc_syndrome_tab) / sizeof (uint8_t))
2446330Sjc25722
245*10784Ssinanallur.balasubramanian@sun.com int8_t L2TAG_bit_to_way_map[128] = {
2466330Sjc25722 /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */
2476330Sjc25722 /* 1 */ 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 0, 0, 0, 0,
2486330Sjc25722 /* 2 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2496330Sjc25722 /* 3 */ 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
250*10784Ssinanallur.balasubramanian@sun.com /* 4 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1,
251*10784Ssinanallur.balasubramanian@sun.com /* 5 */-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1,
2526330Sjc25722 /* 6 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2536330Sjc25722 /* 7 */ 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
254*10784Ssinanallur.balasubramanian@sun.com /* 8 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1, -1, -1, -1,
2556330Sjc25722 };
2566330Sjc25722
2576330Sjc25722 uint8_t L2TAG_bit_to_way_bit[128] = {
2586330Sjc25722 /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */
2596330Sjc25722 /* 1 */ 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 19, 20, 21, 22,
2606330Sjc25722 /* 2 */23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
2616330Sjc25722 /* 3 */39, 40, 41, 42, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
2626330Sjc25722 /* 4 */31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, C0, C0, C0, C0,
2636330Sjc25722 /* 5 */C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, 19, 20, 21, 22,
2646330Sjc25722 /* 6 */23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
2656330Sjc25722 /* 7 */39, 40, 41, 42, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
2666330Sjc25722 /* 8 */31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, C0, C0, C0, C0,
2676330Sjc25722 };
2686330Sjc25722
269*10784Ssinanallur.balasubramanian@sun.com int8_t L3TAG_bit_to_way_map[128] = {
2706330Sjc25722 /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */
2716330Sjc25722 /* 1 */ 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3,
2726330Sjc25722 /* 2 */ 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3,
273*10784Ssinanallur.balasubramanian@sun.com /* 3 */ 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, -1, -1,
274*10784Ssinanallur.balasubramanian@sun.com /* 4 */-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2756330Sjc25722 /* 5 */ 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2,
2766330Sjc25722 /* 6 */ 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2,
277*10784Ssinanallur.balasubramanian@sun.com /* 7 */ 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, -1, -1,
278*10784Ssinanallur.balasubramanian@sun.com /* 8 */-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2796330Sjc25722 };
2806330Sjc25722
2816330Sjc25722 uint8_t L3TAG_bit_to_way_bit[128] = {
2826330Sjc25722 /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */
2836330Sjc25722 /* 1 */ 0, 0, 1, 1, 2, 2, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28,
2846330Sjc25722 /* 2 */29, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36,
2856330Sjc25722 /* 3 */37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, C0, C0,
2866330Sjc25722 /* 4 */C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0,
2876330Sjc25722 /* 5 */ 0, 0, 1, 1, 2, 2, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28,
2886330Sjc25722 /* 6 */29, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36,
2896330Sjc25722 /* 7 */37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, C0, C0,
2906330Sjc25722 /* 8 */C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0,
2916330Sjc25722 };
2926330Sjc25722
2936330Sjc25722 uint16_t
calcecc(uint64_t chi,uint64_t clo)2946330Sjc25722 calcecc(uint64_t chi, uint64_t clo)
2956330Sjc25722 {
2966330Sjc25722 int i;
2976330Sjc25722 uint64_t syndrome = 0;
2986330Sjc25722
2996330Sjc25722 for (i = 0; i < (NDATABITS/2); i++) {
3006330Sjc25722 syndrome ^= ((chi & 1) ? e[(NDATABITS/2) + i] : 0) ^
3016330Sjc25722 ((clo & 1) ? e[i] : 0);
3026330Sjc25722 chi >>= 1;
3036330Sjc25722 clo >>= 1;
3046330Sjc25722 }
3056330Sjc25722 return (uint16_t)(syndrome);
3066330Sjc25722 }
3076330Sjc25722
308*10784Ssinanallur.balasubramanian@sun.com uint64_t
calcsynd(uint64_t chi,uint64_t clo,uint64_t ecc)309*10784Ssinanallur.balasubramanian@sun.com calcsynd(uint64_t chi, uint64_t clo, uint64_t ecc)
310*10784Ssinanallur.balasubramanian@sun.com {
311*10784Ssinanallur.balasubramanian@sun.com return (calcecc(chi, clo) ^ ecc);
312*10784Ssinanallur.balasubramanian@sun.com }
313*10784Ssinanallur.balasubramanian@sun.com
3146330Sjc25722 static uint8_t
tag_bit_to_way_bit(cmd_ptrsubtype_t pstype,int16_t tag_bit)315*10784Ssinanallur.balasubramanian@sun.com tag_bit_to_way_bit(cmd_ptrsubtype_t pstype, int16_t tag_bit)
3166330Sjc25722 {
317*10784Ssinanallur.balasubramanian@sun.com uint8_t way_bit = C0;
3186330Sjc25722
3196330Sjc25722 switch (pstype) {
3206330Sjc25722 case CMD_PTR_CPU_L2TAG:
3216330Sjc25722 way_bit = L2TAG_bit_to_way_bit[tag_bit];
3226330Sjc25722 break;
3236330Sjc25722 case CMD_PTR_CPU_L3TAG:
3246330Sjc25722 way_bit = L3TAG_bit_to_way_bit[tag_bit];
3256330Sjc25722 break;
3266330Sjc25722 }
3276330Sjc25722 return (way_bit);
3286330Sjc25722 }
3296330Sjc25722
330*10784Ssinanallur.balasubramanian@sun.com static int8_t
bit_to_way(cmd_ptrsubtype_t pstype,uint32_t bit)3316330Sjc25722 bit_to_way(cmd_ptrsubtype_t pstype, uint32_t bit)
3326330Sjc25722 {
333*10784Ssinanallur.balasubramanian@sun.com int8_t way = -1;
3346330Sjc25722
3356330Sjc25722 switch (pstype) {
3366330Sjc25722 case CMD_PTR_CPU_L2TAG:
3376330Sjc25722 way = L2TAG_bit_to_way_map[bit & BIT_MASK];
3386330Sjc25722 break;
3396330Sjc25722 case CMD_PTR_CPU_L3TAG:
3406330Sjc25722 way = L3TAG_bit_to_way_map[bit & BIT_MASK];
3416330Sjc25722 break;
3426330Sjc25722 }
3436330Sjc25722 return (way);
3446330Sjc25722 }
3456330Sjc25722
346*10784Ssinanallur.balasubramanian@sun.com static int32_t
get_index(cmd_ptrsubtype_t pstype,uint64_t tag_afar)3476330Sjc25722 get_index(cmd_ptrsubtype_t pstype, uint64_t tag_afar)
3486330Sjc25722 {
349*10784Ssinanallur.balasubramanian@sun.com int32_t index = -1;
3506330Sjc25722
3516330Sjc25722 switch (pstype) {
3526330Sjc25722 case CMD_PTR_CPU_L2TAG:
353*10784Ssinanallur.balasubramanian@sun.com index = (int32_t)((tag_afar & PN_L2_INDEX_MASK)
3546330Sjc25722 >> PN_CACHE_LINE_SHIFT);
3556330Sjc25722 break;
3566330Sjc25722 case CMD_PTR_CPU_L3TAG:
357*10784Ssinanallur.balasubramanian@sun.com index = (int32_t)((tag_afar & PN_L3_TAG_RD_MASK)
3586330Sjc25722 >> PN_CACHE_LINE_SHIFT);
3596330Sjc25722 break;
3606330Sjc25722 }
3616330Sjc25722 return (index);
3626330Sjc25722 }
3636330Sjc25722
364*10784Ssinanallur.balasubramanian@sun.com static int
get_retired_ways(uint64_t * tag_data)365*10784Ssinanallur.balasubramanian@sun.com get_retired_ways(uint64_t *tag_data)
366*10784Ssinanallur.balasubramanian@sun.com {
367*10784Ssinanallur.balasubramanian@sun.com int i, retired_ways;
368*10784Ssinanallur.balasubramanian@sun.com
369*10784Ssinanallur.balasubramanian@sun.com retired_ways = 0;
370*10784Ssinanallur.balasubramanian@sun.com for (i = 0; i < PN_CACHE_NWAYS; i++) {
371*10784Ssinanallur.balasubramanian@sun.com if ((tag_data[i] & CH_ECSTATE_MASK) ==
372*10784Ssinanallur.balasubramanian@sun.com PN_ECSTATE_NA)
373*10784Ssinanallur.balasubramanian@sun.com retired_ways++;
374*10784Ssinanallur.balasubramanian@sun.com }
375*10784Ssinanallur.balasubramanian@sun.com return (retired_ways);
376*10784Ssinanallur.balasubramanian@sun.com }
377*10784Ssinanallur.balasubramanian@sun.com
3786330Sjc25722 static cmd_evdisp_t
extract_data_from_ereport_payload(fmd_hdl_t * hdl,nvlist_t * nvl,cmd_cpu_t * cpu,cmd_ptrsubtype_t pstype,uint64_t * afarp,uint64_t * tag_data,const char * fltnm)3796330Sjc25722 extract_data_from_ereport_payload(fmd_hdl_t *hdl, nvlist_t *nvl,
3806330Sjc25722 cmd_cpu_t *cpu,
3816330Sjc25722 cmd_ptrsubtype_t pstype,
3826330Sjc25722 uint64_t *afarp, uint64_t *tag_data,
3836330Sjc25722 const char *fltnm)
3846330Sjc25722 {
3856330Sjc25722 ch_ec_data_t *ec_data;
3866330Sjc25722 char *payload_namep;
387*10784Ssinanallur.balasubramanian@sun.com int tag_afar_status;
3886330Sjc25722 uint64_t tag_afar;
3896330Sjc25722 int i;
3906330Sjc25722 uint_t sz;
391*10784Ssinanallur.balasubramanian@sun.com int32_t index;
392*10784Ssinanallur.balasubramanian@sun.com int32_t recheck_of_tags;
3936330Sjc25722
394*10784Ssinanallur.balasubramanian@sun.com tag_afar_status = cmd_afar_valid(hdl, nvl, 0, &tag_afar);
395*10784Ssinanallur.balasubramanian@sun.com if (tag_afar_status == -1) {
3966330Sjc25722 fmd_hdl_debug(hdl,
397*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id = %d Invalid afar status in nvlist\n",
3986330Sjc25722 fltnm, cpu->cpu_cpuid);
3996330Sjc25722 return (CMD_EVD_BAD);
4006330Sjc25722 }
4016330Sjc25722 *afarp = tag_afar;
4026330Sjc25722 index = get_index(pstype, tag_afar);
4036330Sjc25722 switch (pstype) {
4046330Sjc25722 case CMD_PTR_CPU_L2TAG:
4056330Sjc25722 payload_namep = FM_EREPORT_PAYLOAD_NAME_L2_DATA;
4066330Sjc25722 break;
4076330Sjc25722 case CMD_PTR_CPU_L3TAG:
4086330Sjc25722 payload_namep = FM_EREPORT_PAYLOAD_NAME_L3_DATA;
4096330Sjc25722 break;
410*10784Ssinanallur.balasubramanian@sun.com default:
411*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
4126330Sjc25722 }
413*10784Ssinanallur.balasubramanian@sun.com if (nvlist_lookup_int32(nvl, FM_EREPORT_RECHECK_OF_TAGS,
414*10784Ssinanallur.balasubramanian@sun.com &recheck_of_tags) != 0)
415*10784Ssinanallur.balasubramanian@sun.com recheck_of_tags = 0;
416*10784Ssinanallur.balasubramanian@sun.com if ((recheck_of_tags) || (test_mode))
417*10784Ssinanallur.balasubramanian@sun.com return (get_tagdata(cpu, pstype, index, tag_data));
418*10784Ssinanallur.balasubramanian@sun.com if (nvlist_lookup_uint64_array(nvl, payload_namep,
419*10784Ssinanallur.balasubramanian@sun.com (uint64_t **)&ec_data, &sz) != 0) {
420*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
421*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id = %d index = %d could not find %s"
422*10784Ssinanallur.balasubramanian@sun.com " in nvlist\n",
423*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index, payload_namep);
424*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
425*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id = %d Reading tag data through"
426*10784Ssinanallur.balasubramanian@sun.com " mem_cache driver.\n",
427*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid);
4286330Sjc25722 return (get_tagdata(cpu, pstype, index,
4296330Sjc25722 tag_data));
4306330Sjc25722 }
4316330Sjc25722 for (i = 0; i < PN_CACHE_NWAYS; i++) {
4326330Sjc25722 tag_data[i] = ec_data[i].ec_tag;
4336330Sjc25722 }
4346330Sjc25722 return (CMD_EVD_OK);
4356330Sjc25722 }
4366330Sjc25722
4376330Sjc25722 static void
print_ecc(fmd_hdl_t * hdl,cmd_cpu_t * cpu,const char * fltnm,uint64_t * tag_data)4386330Sjc25722 print_ecc(fmd_hdl_t *hdl, cmd_cpu_t *cpu, const char *fltnm, uint64_t *tag_data)
4396330Sjc25722 {
4406330Sjc25722 int i;
4416330Sjc25722 uint16_t tag_ecc[PN_CACHE_NWAYS];
4426330Sjc25722
4436330Sjc25722 for (i = 0; i < PN_CACHE_NWAYS; i++) {
444*10784Ssinanallur.balasubramanian@sun.com tag_ecc[i] =
445*10784Ssinanallur.balasubramanian@sun.com ((tag_data[i] & PN_TAG_ECC_MASK)
446*10784Ssinanallur.balasubramanian@sun.com >> PN_LX_TAG_ECC_START_BIT);
4476330Sjc25722 }
4486330Sjc25722 fmd_hdl_debug(hdl,
449*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id = %d ecc[0] = 0x%03x ecc[1] = 0x%03x"
450*10784Ssinanallur.balasubramanian@sun.com " ecc[2] = 0x%03x ecc[3] = 0x%03x\n",
4516330Sjc25722 fltnm, cpu->cpu_cpuid, tag_ecc[0], tag_ecc[1], tag_ecc[2],
4526330Sjc25722 tag_ecc[3]);
4536330Sjc25722
4546330Sjc25722 }
4556330Sjc25722
4566330Sjc25722 static int
matching_ecc(uint64_t * tag_data)4576330Sjc25722 matching_ecc(uint64_t *tag_data)
4586330Sjc25722 {
4596330Sjc25722 int i;
4606330Sjc25722 uint16_t tag_ecc[PN_CACHE_NWAYS];
4616330Sjc25722
4626330Sjc25722 for (i = 0; i < PN_CACHE_NWAYS; i++) {
463*10784Ssinanallur.balasubramanian@sun.com tag_ecc[i] =
464*10784Ssinanallur.balasubramanian@sun.com ((tag_data[i] & PN_TAG_ECC_MASK)
465*10784Ssinanallur.balasubramanian@sun.com >> PN_LX_TAG_ECC_START_BIT);
4666330Sjc25722 if (tag_ecc[i] != tag_ecc[0]) {
4676330Sjc25722 return (1);
4686330Sjc25722 }
4696330Sjc25722 }
4706330Sjc25722 return (0);
4716330Sjc25722 }
4726330Sjc25722
4736330Sjc25722 static void
gen_data_for_ecc(uint64_t * tag_data,uint64_t * data_for_ecc_gen,cmd_ptrsubtype_t pstype)4746330Sjc25722 gen_data_for_ecc(uint64_t *tag_data, uint64_t *data_for_ecc_gen,
4756330Sjc25722 cmd_ptrsubtype_t pstype)
4766330Sjc25722 {
4776330Sjc25722 uint64_t ptag[PN_CACHE_NWAYS];
4786330Sjc25722 uint8_t state[PN_CACHE_NWAYS];
4796330Sjc25722 int i;
4806330Sjc25722 uint16_t tag_ecc[PN_CACHE_NWAYS];
4816330Sjc25722 uint8_t bit_position;
4826330Sjc25722
4836330Sjc25722 for (i = 0; i < PN_CACHE_NWAYS; i++) {
4846330Sjc25722 state[i] = tag_data[i] & CH_ECSTATE_MASK;
485*10784Ssinanallur.balasubramanian@sun.com tag_ecc[i] =
486*10784Ssinanallur.balasubramanian@sun.com ((tag_data[i] & PN_TAG_ECC_MASK)
487*10784Ssinanallur.balasubramanian@sun.com >> PN_LX_TAG_ECC_START_BIT);
4886330Sjc25722 switch (pstype) {
4896330Sjc25722 case CMD_PTR_CPU_L2TAG:
4906330Sjc25722 ptag[i] = (tag_data[i] >> PN_L2_PTAG_SHIFT) &
4916330Sjc25722 L2_PTAG_MASK;
4926330Sjc25722 break;
4936330Sjc25722 case CMD_PTR_CPU_L3TAG:
4946330Sjc25722 ptag[i] = (tag_data[i] >> PN_L3_PTAG_SHIFT) &
4956330Sjc25722 L3_PTAG_MASK;
4966330Sjc25722 break;
4976330Sjc25722 }
4986330Sjc25722 }
4996330Sjc25722 /*
5006330Sjc25722 * We now assemble the 128 bit data swizzling the Physical tags
5016330Sjc25722 * and states we obtained for all the 4 ways.
5026330Sjc25722 */
5036330Sjc25722 data_for_ecc_gen[0] = 0; /* high order 64 bits */
5046330Sjc25722 data_for_ecc_gen[1] = 0; /* low order 64 bits */
5056330Sjc25722 switch (pstype) {
5066330Sjc25722 case CMD_PTR_CPU_L2TAG:
5076330Sjc25722 data_for_ecc_gen[1] = state[0]; /* way 0 state */
5086330Sjc25722 data_for_ecc_gen[1] |=
5096330Sjc25722 (state[1] << 3); /* way 1 state */
5106330Sjc25722 data_for_ecc_gen[1] |=
5116330Sjc25722 (state[2] << 6); /* way 2 state */
5126330Sjc25722 data_for_ecc_gen[1] |=
5136330Sjc25722 (state[3] << 9); /* way 3 state */
5146330Sjc25722 data_for_ecc_gen[1] |= (ptag[0] << 12); /* way 0 ptag */
5156330Sjc25722 data_for_ecc_gen[1] |= (ptag[2] << 36); /* way 2 ptag */
5166330Sjc25722 /* bits 63:60 of low order 64 bits are 0s */
5176330Sjc25722
5186330Sjc25722 /*
5196330Sjc25722 * We now start with hig order 64 bits.
5206330Sjc25722 * the low 12 bits are 0s
5216330Sjc25722 */
5226330Sjc25722 data_for_ecc_gen[0] |= (ptag[1] << 12); /* way 1 ptag */
5236330Sjc25722 data_for_ecc_gen[0] |= (ptag[3] << 36); /* way 3 ptag */
5246330Sjc25722 break;
5256330Sjc25722 case CMD_PTR_CPU_L3TAG:
5266330Sjc25722 bit_position = 0;
5276330Sjc25722 /*
5286330Sjc25722 * Swizzle state bits for way 1 and way 3
5296330Sjc25722 */
5306330Sjc25722 for (i = 0; i < 3; i++) {
5316330Sjc25722 data_for_ecc_gen[1] |=
5326330Sjc25722 (((state[1] >> i) & 1) << bit_position);
5336330Sjc25722 bit_position++;
5346330Sjc25722 data_for_ecc_gen[1] |=
5356330Sjc25722 (((state[3] >> i) & 1) << bit_position);
5366330Sjc25722 bit_position++;
5376330Sjc25722 }
5386330Sjc25722 /*
5396330Sjc25722 * Swizzle physical tag bits for way 1 and way 3
5406330Sjc25722 */
5416330Sjc25722 for (i = 0; i < 20; i++) {
5426330Sjc25722 data_for_ecc_gen[1] |=
5436330Sjc25722 (((ptag[1] >> i) & 1) << bit_position);
5446330Sjc25722 bit_position++;
5456330Sjc25722 data_for_ecc_gen[1] |=
5466330Sjc25722 (((ptag[3] >> i) & 1) << bit_position);
5476330Sjc25722 bit_position++;
5486330Sjc25722 }
5496330Sjc25722 /*
5506330Sjc25722 * start the high order 64 bits.
5516330Sjc25722 */
5526330Sjc25722 bit_position = 0;
5536330Sjc25722 /*
5546330Sjc25722 * Swizzle state bits for way 0 and way 2
5556330Sjc25722 */
5566330Sjc25722 for (i = 0; i < 3; i++) {
5576330Sjc25722 data_for_ecc_gen[0] |=
5586330Sjc25722 (((state[0] >> i) & 1) << bit_position);
5596330Sjc25722 bit_position++;
5606330Sjc25722 data_for_ecc_gen[0] |=
5616330Sjc25722 (((state[2] >> i) & 1) << bit_position);
5626330Sjc25722 bit_position++;
5636330Sjc25722 }
5646330Sjc25722 /*
5656330Sjc25722 * Swizzle physical tag bits for way 0 and way 2
5666330Sjc25722 */
5676330Sjc25722 for (i = 0; i < 20; i++) {
5686330Sjc25722 data_for_ecc_gen[0] |=
5696330Sjc25722 (((ptag[0] >> i) & 1) << bit_position);
5706330Sjc25722 bit_position++;
5716330Sjc25722 data_for_ecc_gen[0] |=
5726330Sjc25722 (((ptag[2] >> i) & 1) << bit_position);
5736330Sjc25722 bit_position++;
5746330Sjc25722 }
5756330Sjc25722 break;
5766330Sjc25722 }
5776330Sjc25722 }
5786330Sjc25722
5796330Sjc25722 static uint16_t
compute_syndrome(uint64_t * tag_data,cmd_ptrsubtype_t pstype)5806330Sjc25722 compute_syndrome(uint64_t *tag_data, cmd_ptrsubtype_t pstype)
5816330Sjc25722 {
5826330Sjc25722 uint64_t tag_synd;
5836330Sjc25722 uint64_t data_for_ecc_gen[2];
5846330Sjc25722 uint16_t tag_ecc;
5856330Sjc25722
5866330Sjc25722 gen_data_for_ecc(tag_data, data_for_ecc_gen, pstype);
587*10784Ssinanallur.balasubramanian@sun.com tag_ecc = ((tag_data[0] & PN_TAG_ECC_MASK) >> PN_LX_TAG_ECC_START_BIT);
5886330Sjc25722 tag_synd = calcsynd(data_for_ecc_gen[0], data_for_ecc_gen[1],
5896330Sjc25722 (uint64_t)tag_ecc);
5906330Sjc25722 return (tag_synd);
5916330Sjc25722 }
5926330Sjc25722
593*10784Ssinanallur.balasubramanian@sun.com static int16_t
find_bit_stickiness(uint64_t * tag_data,int8_t way,int16_t bit)594*10784Ssinanallur.balasubramanian@sun.com find_bit_stickiness(uint64_t *tag_data, int8_t way, int16_t bit)
595*10784Ssinanallur.balasubramanian@sun.com {
596*10784Ssinanallur.balasubramanian@sun.com int16_t sticky_bit;
597*10784Ssinanallur.balasubramanian@sun.com
598*10784Ssinanallur.balasubramanian@sun.com sticky_bit = bit;
599*10784Ssinanallur.balasubramanian@sun.com if ((tag_data[way] & ((uint64_t)1 << bit)) != 0)
600*10784Ssinanallur.balasubramanian@sun.com sticky_bit |= MSB_BIT;
601*10784Ssinanallur.balasubramanian@sun.com return (sticky_bit);
602*10784Ssinanallur.balasubramanian@sun.com }
603*10784Ssinanallur.balasubramanian@sun.com
604*10784Ssinanallur.balasubramanian@sun.com static cmd_Lxcache_t *
cmd_create_and_destroy_Lxcache(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_Lxcache_t * Lxcache)605*10784Ssinanallur.balasubramanian@sun.com cmd_create_and_destroy_Lxcache(fmd_hdl_t *hdl, cmd_cpu_t *cpu,
606*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *Lxcache)
607*10784Ssinanallur.balasubramanian@sun.com {
608*10784Ssinanallur.balasubramanian@sun.com const char *fltnm;
609*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *new_Lxcache;
610*10784Ssinanallur.balasubramanian@sun.com
611*10784Ssinanallur.balasubramanian@sun.com fltnm = cmd_type_to_str(Lxcache->Lxcache_type);
612*10784Ssinanallur.balasubramanian@sun.com
613*10784Ssinanallur.balasubramanian@sun.com /*
614*10784Ssinanallur.balasubramanian@sun.com * We first create a new Lxcache and add the event ep
615*10784Ssinanallur.balasubramanian@sun.com * that is in Lxcache to the new case we create.
616*10784Ssinanallur.balasubramanian@sun.com * we then destroy the Lxcache that has the event ep in its SERD engine.
617*10784Ssinanallur.balasubramanian@sun.com */
618*10784Ssinanallur.balasubramanian@sun.com new_Lxcache = cmd_Lxcache_create(hdl, Lxcache->xr, cpu,
619*10784Ssinanallur.balasubramanian@sun.com cpu->cpu_asru_nvl,
620*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_type,
621*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_index, Lxcache->Lxcache_way, Lxcache->Lxcache_bit);
622*10784Ssinanallur.balasubramanian@sun.com if (new_Lxcache == NULL) {
623*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
624*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d:Failed to create a Lxcache for"
625*10784Ssinanallur.balasubramanian@sun.com " index %d way %d bit %d\n",
626*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, Lxcache->Lxcache_index,
627*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_way, Lxcache->Lxcache_bit);
628*10784Ssinanallur.balasubramanian@sun.com return (NULL);
629*10784Ssinanallur.balasubramanian@sun.com }
630*10784Ssinanallur.balasubramanian@sun.com (void) cmd_create_case_for_Lxcache(hdl, cpu, new_Lxcache);
631*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy(hdl, cpu, Lxcache);
632*10784Ssinanallur.balasubramanian@sun.com return (new_Lxcache);
633*10784Ssinanallur.balasubramanian@sun.com }
634*10784Ssinanallur.balasubramanian@sun.com
635*10784Ssinanallur.balasubramanian@sun.com int
cmd_Lxcache_retire_as_reason(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_Lxcache_t * Lxcache,const char * fltnm,int32_t reason)636*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_retire_as_reason(fmd_hdl_t *hdl, cmd_cpu_t *cpu,
637*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *Lxcache, const char *fltnm, int32_t reason)
6386330Sjc25722 {
639*10784Ssinanallur.balasubramanian@sun.com boolean_t ret;
640*10784Ssinanallur.balasubramanian@sun.com uint_t certainty;
641*10784Ssinanallur.balasubramanian@sun.com
642*10784Ssinanallur.balasubramanian@sun.com if (reason == CMD_LXSUSPECT_0_TAG) {
643*10784Ssinanallur.balasubramanian@sun.com /*
644*10784Ssinanallur.balasubramanian@sun.com * clear MSB bit to retire as SUSPECT_0_TAG
645*10784Ssinanallur.balasubramanian@sun.com * We need to update the Lxcache asru to reflect
646*10784Ssinanallur.balasubramanian@sun.com * the change in bit value.
647*10784Ssinanallur.balasubramanian@sun.com */
648*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_bit &= CLEAR_MSB_BIT;
649*10784Ssinanallur.balasubramanian@sun.com errno = nvlist_add_uint16(
650*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_asru_nvl,
651*10784Ssinanallur.balasubramanian@sun.com FM_FMRI_CPU_CACHE_BIT,
652*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_bit);
653*10784Ssinanallur.balasubramanian@sun.com if (errno) {
654*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
655*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d: failed to update",
656*10784Ssinanallur.balasubramanian@sun.com " CACHE_BIT in asru.\n",
657*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid);
658*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
659*10784Ssinanallur.balasubramanian@sun.com }
660*10784Ssinanallur.balasubramanian@sun.com }
661*10784Ssinanallur.balasubramanian@sun.com if (reason == CMD_LXCONVICTED)
662*10784Ssinanallur.balasubramanian@sun.com certainty = HUNDRED_PERCENT;
663*10784Ssinanallur.balasubramanian@sun.com else
664*10784Ssinanallur.balasubramanian@sun.com certainty = SUSPECT_PERCENT;
665*10784Ssinanallur.balasubramanian@sun.com ret = cmd_Lxcache_retire(hdl, cpu, Lxcache, fltnm, certainty);
666*10784Ssinanallur.balasubramanian@sun.com if (reason == CMD_LXSUSPECT_0_TAG)
667*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_bit |= SET_MSB_BIT;
668*10784Ssinanallur.balasubramanian@sun.com if (ret == B_FALSE)
669*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
670*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_reason = reason;
671*10784Ssinanallur.balasubramanian@sun.com /*
672*10784Ssinanallur.balasubramanian@sun.com * Update the persistence storage of
673*10784Ssinanallur.balasubramanian@sun.com * Lxcache.
674*10784Ssinanallur.balasubramanian@sun.com */
675*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
676*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d:reason = %s flags = %s\n",
677*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid,
678*10784Ssinanallur.balasubramanian@sun.com cmd_reason_to_str(Lxcache->Lxcache_reason),
679*10784Ssinanallur.balasubramanian@sun.com cmd_flags_to_str(Lxcache->Lxcache_flags));
680*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_write(hdl, Lxcache);
681*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK);
682*10784Ssinanallur.balasubramanian@sun.com }
683*10784Ssinanallur.balasubramanian@sun.com
684*10784Ssinanallur.balasubramanian@sun.com int
retire_lowest_retirable_way_as_suspect(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_Lxcache_t * anonymous_Lxcache,const char * fltnm)685*10784Ssinanallur.balasubramanian@sun.com retire_lowest_retirable_way_as_suspect(fmd_hdl_t *hdl, cmd_cpu_t *cpu,
686*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *anonymous_Lxcache, const char *fltnm)
687*10784Ssinanallur.balasubramanian@sun.com {
688*10784Ssinanallur.balasubramanian@sun.com /*
689*10784Ssinanallur.balasubramanian@sun.com * This routine is called only when handling anonymous TAG or DATA
690*10784Ssinanallur.balasubramanian@sun.com * errors. When we exit this routine we would have destroyed the
691*10784Ssinanallur.balasubramanian@sun.com * anonymous_Lxcache structure that was passed to us and created
692*10784Ssinanallur.balasubramanian@sun.com * a new Lxcache if we were successful in determining a way to retire.
693*10784Ssinanallur.balasubramanian@sun.com */
694*10784Ssinanallur.balasubramanian@sun.com int8_t lowest_retirable_way, ways_retired;
695*10784Ssinanallur.balasubramanian@sun.com int32_t reason;
696*10784Ssinanallur.balasubramanian@sun.com cmd_ptrsubtype_t type;
697*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *new_Lxcache;
6986330Sjc25722
699*10784Ssinanallur.balasubramanian@sun.com ways_retired = get_index_retired_ways(cpu,
700*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache->Lxcache_type,
701*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache->Lxcache_index);
702*10784Ssinanallur.balasubramanian@sun.com if (ways_retired == -1) {
703*10784Ssinanallur.balasubramanian@sun.com /*
704*10784Ssinanallur.balasubramanian@sun.com * Couldn't determine how many ways have been retired at this
705*10784Ssinanallur.balasubramanian@sun.com * index. Destroy the anonymous_Lxcache and return failure.
706*10784Ssinanallur.balasubramanian@sun.com */
707*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy(hdl, cpu, anonymous_Lxcache);
708*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
709*10784Ssinanallur.balasubramanian@sun.com }
710*10784Ssinanallur.balasubramanian@sun.com /*
711*10784Ssinanallur.balasubramanian@sun.com * Before retiring a way check if we have already
712*10784Ssinanallur.balasubramanian@sun.com * retired 3 ways for this index.
713*10784Ssinanallur.balasubramanian@sun.com * For TAG errors we will not perform this check because
714*10784Ssinanallur.balasubramanian@sun.com * we could reretire cachlines retired for DATA errors.
715*10784Ssinanallur.balasubramanian@sun.com * The get_lowest_retirable_way() will ensure that we do
716*10784Ssinanallur.balasubramanian@sun.com * not end up retiring all 4 ways.
717*10784Ssinanallur.balasubramanian@sun.com */
718*10784Ssinanallur.balasubramanian@sun.com if (!IS_TAG(anonymous_Lxcache->Lxcache_type)) {
719*10784Ssinanallur.balasubramanian@sun.com if (ways_retired >= 3) {
720*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
721*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu %d: num of ways retired for index %d"
722*10784Ssinanallur.balasubramanian@sun.com " is %d will fault the CPU\n",
723*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid,
724*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache->Lxcache_index, ways_retired);
725*10784Ssinanallur.balasubramanian@sun.com type = anonymous_Lxcache->Lxcache_type;
726*10784Ssinanallur.balasubramanian@sun.com /*
727*10784Ssinanallur.balasubramanian@sun.com * destroy the anonymous_Lxcache
728*10784Ssinanallur.balasubramanian@sun.com */
729*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy(hdl, cpu, anonymous_Lxcache);
730*10784Ssinanallur.balasubramanian@sun.com cmd_fault_the_cpu(hdl, cpu, type, fltnm);
731*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK);
732*10784Ssinanallur.balasubramanian@sun.com }
733*10784Ssinanallur.balasubramanian@sun.com }
734*10784Ssinanallur.balasubramanian@sun.com /*
735*10784Ssinanallur.balasubramanian@sun.com * No ways have been retired as "SUSPECT" for this bit.
736*10784Ssinanallur.balasubramanian@sun.com * We need to retire the lowest unretired way as suspect.
737*10784Ssinanallur.balasubramanian@sun.com */
738*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
739*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id %d Checking for the lowest retirable"
740*10784Ssinanallur.balasubramanian@sun.com " way at index %d\n",
741*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, anonymous_Lxcache->Lxcache_index);
742*10784Ssinanallur.balasubramanian@sun.com lowest_retirable_way = cmd_Lxcache_get_lowest_retirable_way(cpu,
743*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache->Lxcache_index, anonymous_Lxcache->Lxcache_type);
744*10784Ssinanallur.balasubramanian@sun.com if (lowest_retirable_way != -1) {
745*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
746*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id %d lowest retirable way is %d\n",
747*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, lowest_retirable_way);
748*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache->Lxcache_way = lowest_retirable_way;
749*10784Ssinanallur.balasubramanian@sun.com new_Lxcache = cmd_create_and_destroy_Lxcache(hdl, cpu,
750*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache);
751*10784Ssinanallur.balasubramanian@sun.com if ((new_Lxcache == NULL) ||
752*10784Ssinanallur.balasubramanian@sun.com (new_Lxcache->Lxcache_case.cc_cp == NULL)) {
753*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
754*10784Ssinanallur.balasubramanian@sun.com }
755*10784Ssinanallur.balasubramanian@sun.com if (IS_TAG(new_Lxcache->Lxcache_type))
756*10784Ssinanallur.balasubramanian@sun.com reason = CMD_LXSUSPECT_0_TAG;
757*10784Ssinanallur.balasubramanian@sun.com else
758*10784Ssinanallur.balasubramanian@sun.com reason = CMD_LXSUSPECT_DATA;
759*10784Ssinanallur.balasubramanian@sun.com return (cmd_Lxcache_retire_as_reason(hdl, cpu, new_Lxcache,
760*10784Ssinanallur.balasubramanian@sun.com fltnm, reason));
761*10784Ssinanallur.balasubramanian@sun.com } else {
762*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
763*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d we are unable to determine which"
764*10784Ssinanallur.balasubramanian@sun.com " way is faulty at cache index %d."
765*10784Ssinanallur.balasubramanian@sun.com " Will retire the CPU.\nRecommended-Action:"
766*10784Ssinanallur.balasubramanian@sun.com " Service action required\n",
767*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, anonymous_Lxcache->Lxcache_index);
768*10784Ssinanallur.balasubramanian@sun.com type = anonymous_Lxcache->Lxcache_type;
769*10784Ssinanallur.balasubramanian@sun.com /*
770*10784Ssinanallur.balasubramanian@sun.com * destroy the anonymous_Lxcache
771*10784Ssinanallur.balasubramanian@sun.com */
772*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy(hdl, cpu, anonymous_Lxcache);
773*10784Ssinanallur.balasubramanian@sun.com cmd_fault_the_cpu(hdl, cpu, type, fltnm);
774*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK);
7756330Sjc25722 }
776*10784Ssinanallur.balasubramanian@sun.com }
777*10784Ssinanallur.balasubramanian@sun.com
778*10784Ssinanallur.balasubramanian@sun.com int
unretire_suspect_and_retire_next_retirable_way(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_Lxcache_t * suspect_Lxcache,cmd_Lxcache_t * anonymous_Lxcache,const char * fltnm)779*10784Ssinanallur.balasubramanian@sun.com unretire_suspect_and_retire_next_retirable_way(fmd_hdl_t *hdl, cmd_cpu_t *cpu,
780*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *suspect_Lxcache, cmd_Lxcache_t *anonymous_Lxcache,
781*10784Ssinanallur.balasubramanian@sun.com const char *fltnm)
782*10784Ssinanallur.balasubramanian@sun.com {
783*10784Ssinanallur.balasubramanian@sun.com int8_t retired_way, next_retirable_way;
784*10784Ssinanallur.balasubramanian@sun.com int32_t retired_index;
785*10784Ssinanallur.balasubramanian@sun.com cmd_ptrsubtype_t retired_type;
786*10784Ssinanallur.balasubramanian@sun.com int32_t reason;
787*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *new_Lxcache;
788*10784Ssinanallur.balasubramanian@sun.com
789*10784Ssinanallur.balasubramanian@sun.com /*
790*10784Ssinanallur.balasubramanian@sun.com * This routine is called only when handling anonymous TAG or DATA
791*10784Ssinanallur.balasubramanian@sun.com * errors. When we exit this routine we would have destroyed the
792*10784Ssinanallur.balasubramanian@sun.com * anonymous_Lxcache structure that was passed to us.
793*10784Ssinanallur.balasubramanian@sun.com */
794*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
795*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d found index %d way %d"
796*10784Ssinanallur.balasubramanian@sun.com " bit %d retired as %s. Will unretire this now.\n",
797*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, suspect_Lxcache->Lxcache_index,
798*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_way, suspect_Lxcache->Lxcache_bit,
799*10784Ssinanallur.balasubramanian@sun.com cmd_reason_to_str(suspect_Lxcache->Lxcache_reason));
800*10784Ssinanallur.balasubramanian@sun.com /*
801*10784Ssinanallur.balasubramanian@sun.com * Save the way because we will destroy the
802*10784Ssinanallur.balasubramanian@sun.com * suspect_Lxcache after we successfully unretire it.
803*10784Ssinanallur.balasubramanian@sun.com */
804*10784Ssinanallur.balasubramanian@sun.com retired_way = suspect_Lxcache->Lxcache_way;
805*10784Ssinanallur.balasubramanian@sun.com retired_index = suspect_Lxcache->Lxcache_index;
806*10784Ssinanallur.balasubramanian@sun.com retired_type = suspect_Lxcache->Lxcache_type;
807*10784Ssinanallur.balasubramanian@sun.com /*
808*10784Ssinanallur.balasubramanian@sun.com * unretire the retired_way.
809*10784Ssinanallur.balasubramanian@sun.com */
810*10784Ssinanallur.balasubramanian@sun.com if (cmd_Lxcache_unretire(hdl, cpu, suspect_Lxcache,
811*10784Ssinanallur.balasubramanian@sun.com fltnm)
812*10784Ssinanallur.balasubramanian@sun.com == B_TRUE) {
813*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_reason =
814*10784Ssinanallur.balasubramanian@sun.com CMD_LXFUNCTIONING;
815*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
816*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d index %d way %d"
817*10784Ssinanallur.balasubramanian@sun.com " successfully unretired. Will"
818*10784Ssinanallur.balasubramanian@sun.com " destroy this Lxcache now.\n",
819*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, suspect_Lxcache->Lxcache_index,
820*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_way);
821*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy(hdl, cpu, suspect_Lxcache);
822*10784Ssinanallur.balasubramanian@sun.com } else {
823*10784Ssinanallur.balasubramanian@sun.com /*
824*10784Ssinanallur.balasubramanian@sun.com * destroy the anonymous_Lxcache
825*10784Ssinanallur.balasubramanian@sun.com */
826*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy(hdl, cpu, anonymous_Lxcache);
827*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
828*10784Ssinanallur.balasubramanian@sun.com }
829*10784Ssinanallur.balasubramanian@sun.com /*
830*10784Ssinanallur.balasubramanian@sun.com * retire the next retirable way
831*10784Ssinanallur.balasubramanian@sun.com */
832*10784Ssinanallur.balasubramanian@sun.com next_retirable_way = cmd_Lxcache_get_next_retirable_way(cpu,
833*10784Ssinanallur.balasubramanian@sun.com retired_index,
834*10784Ssinanallur.balasubramanian@sun.com retired_type, retired_way);
835*10784Ssinanallur.balasubramanian@sun.com if (next_retirable_way == -1) {
836*10784Ssinanallur.balasubramanian@sun.com /*
837*10784Ssinanallur.balasubramanian@sun.com * There is no retirable way that is next to the
838*10784Ssinanallur.balasubramanian@sun.com * one we just retired. We need to offline the
839*10784Ssinanallur.balasubramanian@sun.com * CPU since we are unable to determine which
840*10784Ssinanallur.balasubramanian@sun.com * way is reporting the errors.
841*10784Ssinanallur.balasubramanian@sun.com */
842*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
843*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d we are unable to determine"
844*10784Ssinanallur.balasubramanian@sun.com " which way is faulty at cache index %d."
845*10784Ssinanallur.balasubramanian@sun.com " It is likely that we have a leaky bit"
846*10784Ssinanallur.balasubramanian@sun.com " that gets corrected.\n Will retire"
847*10784Ssinanallur.balasubramanian@sun.com " the CPU.\nRecommended-Action: Service"
848*10784Ssinanallur.balasubramanian@sun.com " action required\n",
849*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, retired_index);
850*10784Ssinanallur.balasubramanian@sun.com /*
851*10784Ssinanallur.balasubramanian@sun.com * destroy the anonymous_Lxcache
852*10784Ssinanallur.balasubramanian@sun.com */
853*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy(hdl, cpu, anonymous_Lxcache);
854*10784Ssinanallur.balasubramanian@sun.com cmd_fault_the_cpu(hdl, cpu, retired_type, fltnm);
855*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK);
856*10784Ssinanallur.balasubramanian@sun.com } else {
857*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
858*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d found way %d at index %d to"
859*10784Ssinanallur.balasubramanian@sun.com " retire as SUSPECT_0/SUSPECT_DATA\n",
860*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, next_retirable_way, retired_index);
861*10784Ssinanallur.balasubramanian@sun.com /*
862*10784Ssinanallur.balasubramanian@sun.com * We need to create a new Lxcache struture.
863*10784Ssinanallur.balasubramanian@sun.com * The existing Lxcache is for anonymous way.
864*10784Ssinanallur.balasubramanian@sun.com */
865*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache->Lxcache_way = next_retirable_way;
866*10784Ssinanallur.balasubramanian@sun.com new_Lxcache = cmd_create_and_destroy_Lxcache(hdl,
867*10784Ssinanallur.balasubramanian@sun.com cpu, anonymous_Lxcache);
868*10784Ssinanallur.balasubramanian@sun.com if ((new_Lxcache == NULL) ||
869*10784Ssinanallur.balasubramanian@sun.com (new_Lxcache->Lxcache_case.cc_cp == NULL)) {
870*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
871*10784Ssinanallur.balasubramanian@sun.com }
872*10784Ssinanallur.balasubramanian@sun.com if (IS_TAG(new_Lxcache->Lxcache_type))
873*10784Ssinanallur.balasubramanian@sun.com reason = CMD_LXSUSPECT_0_TAG;
874*10784Ssinanallur.balasubramanian@sun.com else
875*10784Ssinanallur.balasubramanian@sun.com reason = CMD_LXSUSPECT_DATA;
876*10784Ssinanallur.balasubramanian@sun.com return (cmd_Lxcache_retire_as_reason(hdl, cpu, new_Lxcache,
877*10784Ssinanallur.balasubramanian@sun.com fltnm, reason));
878*10784Ssinanallur.balasubramanian@sun.com }
879*10784Ssinanallur.balasubramanian@sun.com }
880*10784Ssinanallur.balasubramanian@sun.com
881*10784Ssinanallur.balasubramanian@sun.com void
find_and_destroy_anonymous_Lxcache(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_ptrsubtype_t pstype,int32_t index)882*10784Ssinanallur.balasubramanian@sun.com find_and_destroy_anonymous_Lxcache(fmd_hdl_t *hdl, cmd_cpu_t *cpu,
883*10784Ssinanallur.balasubramanian@sun.com cmd_ptrsubtype_t pstype, int32_t index)
884*10784Ssinanallur.balasubramanian@sun.com {
885*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *anonymous_Lxcache;
886*10784Ssinanallur.balasubramanian@sun.com const char *fltnm;
887*10784Ssinanallur.balasubramanian@sun.com
888*10784Ssinanallur.balasubramanian@sun.com fltnm = cmd_type_to_str(pstype);
889*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache =
890*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_lookup_by_type_index_way_bit(cpu,
891*10784Ssinanallur.balasubramanian@sun.com pstype, index, -1, -1);
892*10784Ssinanallur.balasubramanian@sun.com if (anonymous_Lxcache != NULL) {
893*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
894*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id = %d index = %d We are destroying the"
895*10784Ssinanallur.balasubramanian@sun.com " anonymous Lxcache now.\n",
896*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index);
897*10784Ssinanallur.balasubramanian@sun.com /*
898*10784Ssinanallur.balasubramanian@sun.com * Free the resources allocated to handle
899*10784Ssinanallur.balasubramanian@sun.com * recheck_of_tags. Delete the Lxcache.
900*10784Ssinanallur.balasubramanian@sun.com */
901*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy(hdl, cpu,
902*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache);
903*10784Ssinanallur.balasubramanian@sun.com }
904*10784Ssinanallur.balasubramanian@sun.com }
905*10784Ssinanallur.balasubramanian@sun.com
906*10784Ssinanallur.balasubramanian@sun.com void
cmd_Lxcache_anonymous_tag_error_timeout(fmd_hdl_t * hdl,id_t id)907*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_anonymous_tag_error_timeout(fmd_hdl_t *hdl, id_t id)
908*10784Ssinanallur.balasubramanian@sun.com {
909*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *Lxcache;
910*10784Ssinanallur.balasubramanian@sun.com const char *class;
911*10784Ssinanallur.balasubramanian@sun.com
912*10784Ssinanallur.balasubramanian@sun.com
913*10784Ssinanallur.balasubramanian@sun.com /*
914*10784Ssinanallur.balasubramanian@sun.com * We search thru the entire Lxcache structures to find
915*10784Ssinanallur.balasubramanian@sun.com * a matching id.
916*10784Ssinanallur.balasubramanian@sun.com */
917*10784Ssinanallur.balasubramanian@sun.com Lxcache = cmd_Lxcache_lookup_by_timeout_id(id);
918*10784Ssinanallur.balasubramanian@sun.com if (Lxcache == NULL) {
919*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
920*10784Ssinanallur.balasubramanian@sun.com "Could not find Lxcache for timeout_id 0x%x\n", id);
921*10784Ssinanallur.balasubramanian@sun.com return;
922*10784Ssinanallur.balasubramanian@sun.com }
923*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
924*10784Ssinanallur.balasubramanian@sun.com "\n%s:anonymous_tag_error_timeout:index = %d\n",
925*10784Ssinanallur.balasubramanian@sun.com cmd_type_to_str(Lxcache->Lxcache_type),
926*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_index);
927*10784Ssinanallur.balasubramanian@sun.com /*
928*10784Ssinanallur.balasubramanian@sun.com * Set timeout_id to -1 to indicate that we have processed the
929*10784Ssinanallur.balasubramanian@sun.com * timeout.
930*10784Ssinanallur.balasubramanian@sun.com */
931*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_timeout_id = -1;
932*10784Ssinanallur.balasubramanian@sun.com switch (Lxcache->Lxcache_type) {
933*10784Ssinanallur.balasubramanian@sun.com case CMD_PTR_CPU_L2TAG:
934*10784Ssinanallur.balasubramanian@sun.com class = "ereport.cpu.ultraSPARC-IVplus.thce";
935*10784Ssinanallur.balasubramanian@sun.com (void) cmd_txce(hdl, Lxcache->Lxcache_ep,
936*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_nvl,
937*10784Ssinanallur.balasubramanian@sun.com class, Lxcache->Lxcache_clcode);
938*10784Ssinanallur.balasubramanian@sun.com break;
939*10784Ssinanallur.balasubramanian@sun.com case CMD_PTR_CPU_L3TAG:
940*10784Ssinanallur.balasubramanian@sun.com class = "ereport.cpu.ultraSPARC-IVplus.l3-thce";
941*10784Ssinanallur.balasubramanian@sun.com (void) cmd_l3_thce(hdl, Lxcache->Lxcache_ep,
942*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_nvl,
943*10784Ssinanallur.balasubramanian@sun.com class, Lxcache->Lxcache_clcode);
944*10784Ssinanallur.balasubramanian@sun.com break;
945*10784Ssinanallur.balasubramanian@sun.com default:
946*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
947*10784Ssinanallur.balasubramanian@sun.com "Unexpected pstype 0x%x found in"
948*10784Ssinanallur.balasubramanian@sun.com " anonymous_tag_error_timeout: index = %d\n",
949*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_type,
950*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_index);
951*10784Ssinanallur.balasubramanian@sun.com return;
952*10784Ssinanallur.balasubramanian@sun.com }
9536330Sjc25722 }
9546330Sjc25722
9556330Sjc25722 cmd_evdisp_t
cmd_us4plus_tag_err(fmd_hdl_t * hdl,fmd_event_t * ep,nvlist_t * nvl,cmd_cpu_t * cpu,cmd_ptrsubtype_t pstype,const char * serdn,const char * serdt,const char * fltnm,cmd_errcl_t clcode)9566330Sjc25722 cmd_us4plus_tag_err(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
957*10784Ssinanallur.balasubramanian@sun.com cmd_cpu_t *cpu, cmd_ptrsubtype_t pstype,
958*10784Ssinanallur.balasubramanian@sun.com const char *serdn, const char *serdt,
959*10784Ssinanallur.balasubramanian@sun.com const char *fltnm, cmd_errcl_t clcode)
9606330Sjc25722 {
9616330Sjc25722 uint64_t tag_afar;
962*10784Ssinanallur.balasubramanian@sun.com int32_t index;
963*10784Ssinanallur.balasubramanian@sun.com int8_t way;
964*10784Ssinanallur.balasubramanian@sun.com int16_t tag_bit, bit, sticky_bit;
965*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *Lxcache, *suspect_Lxcache, *retired_Lxcache;
966*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *anonymous_Lxcache;
9676330Sjc25722 uint64_t tag_synd;
9686330Sjc25722 uint64_t tag_data[PN_CACHE_NWAYS];
969*10784Ssinanallur.balasubramanian@sun.com uint8_t state;
9706330Sjc25722 int ways_retired, ret;
971*10784Ssinanallur.balasubramanian@sun.com int retries_for_ecc_match;
972*10784Ssinanallur.balasubramanian@sun.com int32_t recheck_of_tags;
973*10784Ssinanallur.balasubramanian@sun.com int way_already_retired = 0;
9746330Sjc25722
9756330Sjc25722 /*
9766330Sjc25722 * We now extract physical tags and states
9776330Sjc25722 * and also look for matching ECC on all 4 ways.
9786330Sjc25722 */
9796330Sjc25722 ret = extract_data_from_ereport_payload(hdl, nvl, cpu, pstype,
9806330Sjc25722 &tag_afar, tag_data, fltnm);
9816330Sjc25722 if (ret != 0)
9826330Sjc25722 return (ret);
9836330Sjc25722 index = get_index(pstype, tag_afar);
9846330Sjc25722 retries_for_ecc_match = 0;
9856330Sjc25722 while (matching_ecc(tag_data) != 0) {
9866330Sjc25722 if (retries_for_ecc_match >= MAX_RETRIES_FOR_ECC_MATCH)
9876330Sjc25722 return (CMD_EVD_BAD);
9886330Sjc25722 print_ecc(hdl, cpu, fltnm, tag_data);
9896330Sjc25722 fmd_hdl_debug(hdl,
990*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id = %d index = %d ECCs don't match.\n"
9916330Sjc25722 "Reading tag info again.\n",
9926330Sjc25722 fltnm, cpu->cpu_cpuid, index);
9936330Sjc25722 (void) get_tagdata(cpu, pstype, index, tag_data);
9946330Sjc25722 retries_for_ecc_match++;
9956330Sjc25722 }
996*10784Ssinanallur.balasubramanian@sun.com ways_retired = get_retired_ways(tag_data);
997*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
998*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d: found %d ways retired at the index %d\n",
999*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, ways_retired, index);
10006330Sjc25722 tag_synd = compute_syndrome(tag_data, pstype);
1001*10784Ssinanallur.balasubramanian@sun.com ret = nvlist_lookup_int32(nvl, FM_EREPORT_RECHECK_OF_TAGS,
1002*10784Ssinanallur.balasubramanian@sun.com &recheck_of_tags);
1003*10784Ssinanallur.balasubramanian@sun.com if (ret != CMD_EVD_OK) {
1004*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1005*10784Ssinanallur.balasubramanian@sun.com "ret value = %d for nvlist_lookup of recheck_of_tags\n",
1006*10784Ssinanallur.balasubramanian@sun.com ret);
1007*10784Ssinanallur.balasubramanian@sun.com recheck_of_tags = 0;
1008*10784Ssinanallur.balasubramanian@sun.com }
10096330Sjc25722 if (tag_synd == 0) {
10106330Sjc25722 /*
10116330Sjc25722 * The bit has been corrected by writeback, we will
1012*10784Ssinanallur.balasubramanian@sun.com * first check if we are processing the re-check of tags
1013*10784Ssinanallur.balasubramanian@sun.com * that we scheduled thru the timeout call.
1014*10784Ssinanallur.balasubramanian@sun.com * if so we will exit if we reached the max retries.
1015*10784Ssinanallur.balasubramanian@sun.com * Else we start a timeout and exit.
1016*10784Ssinanallur.balasubramanian@sun.com * We will create a Lxcache structure for this index with way
1017*10784Ssinanallur.balasubramanian@sun.com * as -1 and bit as -1. We will also keep a count of
1018*10784Ssinanallur.balasubramanian@sun.com * attempts we made to check the tag data at this index.
1019*10784Ssinanallur.balasubramanian@sun.com *
10206330Sjc25722 */
1021*10784Ssinanallur.balasubramanian@sun.com way = -1;
1022*10784Ssinanallur.balasubramanian@sun.com bit = -1;
1023*10784Ssinanallur.balasubramanian@sun.com Lxcache = cmd_Lxcache_lookup_by_type_index_way_bit(cpu, pstype,
1024*10784Ssinanallur.balasubramanian@sun.com index, way, bit);
1025*10784Ssinanallur.balasubramanian@sun.com if (recheck_of_tags) {
1026*10784Ssinanallur.balasubramanian@sun.com /*
1027*10784Ssinanallur.balasubramanian@sun.com * We are processing the re-read of tags scheduled by
1028*10784Ssinanallur.balasubramanian@sun.com * timeout. Exit if retry limit has been
1029*10784Ssinanallur.balasubramanian@sun.com * reached. Else start another timeout.
1030*10784Ssinanallur.balasubramanian@sun.com */
1031*10784Ssinanallur.balasubramanian@sun.com if (Lxcache == NULL) {
1032*10784Ssinanallur.balasubramanian@sun.com /*
1033*10784Ssinanallur.balasubramanian@sun.com * This shouldn't happen.
1034*10784Ssinanallur.balasubramanian@sun.com */
1035*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1036*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id = %d failed to lookup"
1037*10784Ssinanallur.balasubramanian@sun.com " index = %d way %d bit %d\n",
1038*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index, way, bit);
1039*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
1040*10784Ssinanallur.balasubramanian@sun.com }
1041*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1042*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id = %d index = %d syndrome"
1043*10784Ssinanallur.balasubramanian@sun.com " computed is 0 in attempt #%d.\n",
1044*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index,
1045*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_retry_count);
1046*10784Ssinanallur.balasubramanian@sun.com if (Lxcache->Lxcache_retry_count >=
1047*10784Ssinanallur.balasubramanian@sun.com RETRIES_TO_BE_DONE_WHEN_SYND_IS_ZERO) {
1048*10784Ssinanallur.balasubramanian@sun.com /*
1049*10784Ssinanallur.balasubramanian@sun.com * We free only the nvl list here.
1050*10784Ssinanallur.balasubramanian@sun.com * anonymous SERD engine will be freed
1051*10784Ssinanallur.balasubramanian@sun.com * when the Lxcache gets destroyed.
1052*10784Ssinanallur.balasubramanian@sun.com * We need the anonymous SERD engine still
1053*10784Ssinanallur.balasubramanian@sun.com * because it has the event ep.
1054*10784Ssinanallur.balasubramanian@sun.com * reset or destroy of SERD engine frees the
1055*10784Ssinanallur.balasubramanian@sun.com * event ep.
1056*10784Ssinanallur.balasubramanian@sun.com */
1057*10784Ssinanallur.balasubramanian@sun.com if (Lxcache->Lxcache_nvl != NULL) {
1058*10784Ssinanallur.balasubramanian@sun.com nvlist_free(Lxcache->Lxcache_nvl);
1059*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_nvl = NULL;
1060*10784Ssinanallur.balasubramanian@sun.com }
1061*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1062*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d Max retry count reached. Giving up.\n",
1063*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid);
1064*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_timeout_id = -1;
1065*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_retry_count = 0;
1066*10784Ssinanallur.balasubramanian@sun.com goto process_after_finding_way_bit;
1067*10784Ssinanallur.balasubramanian@sun.com } else {
1068*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_retry_count++;
1069*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_timeout_id =
1070*10784Ssinanallur.balasubramanian@sun.com fmd_timer_install(hdl,
1071*10784Ssinanallur.balasubramanian@sun.com (void *)CMD_TIMERTYPE_ANONYMOUS_TAG_ERROR,
1072*10784Ssinanallur.balasubramanian@sun.com NULL,
1073*10784Ssinanallur.balasubramanian@sun.com (cmd_Lxcache_recheck_tags_delay[
1074*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_retry_count] * NANOSEC));
1075*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK);
1076*10784Ssinanallur.balasubramanian@sun.com }
1077*10784Ssinanallur.balasubramanian@sun.com }
1078*10784Ssinanallur.balasubramanian@sun.com /*
1079*10784Ssinanallur.balasubramanian@sun.com * Check if we already have a Lxcache structure
1080*10784Ssinanallur.balasubramanian@sun.com * with anonymous way and bit created.
1081*10784Ssinanallur.balasubramanian@sun.com */
1082*10784Ssinanallur.balasubramanian@sun.com if (Lxcache == NULL) {
1083*10784Ssinanallur.balasubramanian@sun.com Lxcache = cmd_Lxcache_create(hdl, 0, cpu,
1084*10784Ssinanallur.balasubramanian@sun.com cpu->cpu_asru_nvl, pstype, index, way, bit);
1085*10784Ssinanallur.balasubramanian@sun.com if (Lxcache == NULL) {
1086*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1087*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d Failed to create Lxcache"
1088*10784Ssinanallur.balasubramanian@sun.com " for index=%d\n",
1089*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index);
1090*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
1091*10784Ssinanallur.balasubramanian@sun.com }
1092*10784Ssinanallur.balasubramanian@sun.com }
1093*10784Ssinanallur.balasubramanian@sun.com if (Lxcache->Lxcache_timeout_id != -1) {
1094*10784Ssinanallur.balasubramanian@sun.com /*
1095*10784Ssinanallur.balasubramanian@sun.com * We have another syndrome = 0 condition while we are
1096*10784Ssinanallur.balasubramanian@sun.com * still in the process of retrying for the previous
1097*10784Ssinanallur.balasubramanian@sun.com * condition.
1098*10784Ssinanallur.balasubramanian@sun.com */
1099*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1100*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id = %d index = %d We have another"
1101*10784Ssinanallur.balasubramanian@sun.com " syndrome = 0 condition while we have already"
1102*10784Ssinanallur.balasubramanian@sun.com " scheduled a timeout. We will ignore this"
1103*10784Ssinanallur.balasubramanian@sun.com " event.\n",
1104*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index);
1105*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK);
1106*10784Ssinanallur.balasubramanian@sun.com }
11076330Sjc25722 fmd_hdl_debug(hdl,
1108*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id = %d index = %d syndrome computed is 0."
11096330Sjc25722 "Looks like the bit got corrected."
11106330Sjc25722 " Will check later to see if it is OK.\n",
11116330Sjc25722 fltnm, cpu->cpu_cpuid, index);
1112*10784Ssinanallur.balasubramanian@sun.com /*
1113*10784Ssinanallur.balasubramanian@sun.com * We need to store the following arguments passed to
1114*10784Ssinanallur.balasubramanian@sun.com * this function(tag_error_handler) so that we can
1115*10784Ssinanallur.balasubramanian@sun.com * invoke this function from timeout routine.
1116*10784Ssinanallur.balasubramanian@sun.com *
1117*10784Ssinanallur.balasubramanian@sun.com * nvl, ep, clcode
1118*10784Ssinanallur.balasubramanian@sun.com */
1119*10784Ssinanallur.balasubramanian@sun.com if (Lxcache->Lxcache_nvl == NULL) {
1120*10784Ssinanallur.balasubramanian@sun.com if (nvlist_dup(nvl, &Lxcache->Lxcache_nvl, 0) != 0) {
1121*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1122*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d Failed to duplicate nvl"
1123*10784Ssinanallur.balasubramanian@sun.com " for index=%d\n",
1124*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index);
1125*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
1126*10784Ssinanallur.balasubramanian@sun.com }
1127*10784Ssinanallur.balasubramanian@sun.com if (nvlist_add_int32(Lxcache->Lxcache_nvl,
1128*10784Ssinanallur.balasubramanian@sun.com FM_EREPORT_RECHECK_OF_TAGS, 1) != 0) {
1129*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1130*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d Failed to add"
1131*10784Ssinanallur.balasubramanian@sun.com " RECHECK_OF_TAGS in nvl for index=%d\n",
1132*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index);
1133*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
1134*10784Ssinanallur.balasubramanian@sun.com }
1135*10784Ssinanallur.balasubramanian@sun.com }
11366330Sjc25722 /*
1137*10784Ssinanallur.balasubramanian@sun.com * We are called with CMP_CPU_LEVEL_CORE masked out
1138*10784Ssinanallur.balasubramanian@sun.com * from cmd_txce(), cmd_l3_thce() routines.
1139*10784Ssinanallur.balasubramanian@sun.com * We need to set CMD_CPU_LEVEL_CORE because we want to handle
1140*10784Ssinanallur.balasubramanian@sun.com * both the cores on the Chip as one single cpu_id.
11416330Sjc25722 */
1142*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_clcode = (clcode | CMD_CPU_LEVEL_CORE);
1143*10784Ssinanallur.balasubramanian@sun.com if (Lxcache->Lxcache_ep == NULL) {
1144*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_ep = ep;
1145*10784Ssinanallur.balasubramanian@sun.com /*
1146*10784Ssinanallur.balasubramanian@sun.com * we need to preserve the event ep so that it does
1147*10784Ssinanallur.balasubramanian@sun.com * not get destroyed when we return from this call.
1148*10784Ssinanallur.balasubramanian@sun.com * We do that by adding the event ep to the SERD engine.
1149*10784Ssinanallur.balasubramanian@sun.com * The SERD engine we create is different from the one
1150*10784Ssinanallur.balasubramanian@sun.com * we create when we handle the actual event at label
1151*10784Ssinanallur.balasubramanian@sun.com * process_after_finding_way_bit.
1152*10784Ssinanallur.balasubramanian@sun.com */
1153*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_serdnm =
1154*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_anonymous_serdnm_create(hdl,
1155*10784Ssinanallur.balasubramanian@sun.com cpu->cpu_cpuid, pstype, index,
1156*10784Ssinanallur.balasubramanian@sun.com way, bit);
1157*10784Ssinanallur.balasubramanian@sun.com if (!fmd_serd_exists(hdl, Lxcache->Lxcache_serdnm)) {
1158*10784Ssinanallur.balasubramanian@sun.com fmd_serd_create(hdl, Lxcache->Lxcache_serdnm,
1159*10784Ssinanallur.balasubramanian@sun.com fmd_prop_get_int32(hdl, serdn),
1160*10784Ssinanallur.balasubramanian@sun.com fmd_prop_get_int64(hdl, serdt));
1161*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1162*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id %d: created a SERD engine"
1163*10784Ssinanallur.balasubramanian@sun.com " %s\n",
1164*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid,
1165*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_serdnm);
1166*10784Ssinanallur.balasubramanian@sun.com }
1167*10784Ssinanallur.balasubramanian@sun.com (void) fmd_serd_record(hdl,
1168*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_serdnm,
1169*10784Ssinanallur.balasubramanian@sun.com ep);
1170*10784Ssinanallur.balasubramanian@sun.com }
1171*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_retry_count++;
1172*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_timeout_id =
1173*10784Ssinanallur.balasubramanian@sun.com fmd_timer_install(hdl,
1174*10784Ssinanallur.balasubramanian@sun.com (void *)CMD_TIMERTYPE_ANONYMOUS_TAG_ERROR, NULL,
1175*10784Ssinanallur.balasubramanian@sun.com (cmd_Lxcache_recheck_tags_delay[
1176*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_retry_count] * NANOSEC));
1177*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK);
1178*10784Ssinanallur.balasubramanian@sun.com
11796330Sjc25722 } else {
1180*10784Ssinanallur.balasubramanian@sun.com /*
1181*10784Ssinanallur.balasubramanian@sun.com * tag_synd != 0
1182*10784Ssinanallur.balasubramanian@sun.com * determine way and bit
1183*10784Ssinanallur.balasubramanian@sun.com */
1184*10784Ssinanallur.balasubramanian@sun.com tag_bit = ecc_syndrome_tab[tag_synd & 0x1ff];
1185*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1186*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id = %d index = %d tag_bit %03d is faulty.\n",
1187*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index, tag_bit);
1188*10784Ssinanallur.balasubramanian@sun.com if ((tag_bit > C8)) {
1189*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "%s: cpu_id = %d"
1190*10784Ssinanallur.balasubramanian@sun.com " Unexpected MTAG or Multiple bit error detected\n",
1191*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid);
1192*10784Ssinanallur.balasubramanian@sun.com find_and_destroy_anonymous_Lxcache(hdl, cpu, pstype,
1193*10784Ssinanallur.balasubramanian@sun.com index);
11946330Sjc25722 return (CMD_EVD_BAD);
11956330Sjc25722 }
1196*10784Ssinanallur.balasubramanian@sun.com if ((tag_bit >= C0) && (tag_bit <= C8)) {
1197*10784Ssinanallur.balasubramanian@sun.com /*
1198*10784Ssinanallur.balasubramanian@sun.com * ECC bit is corrupted.
1199*10784Ssinanallur.balasubramanian@sun.com * Need to offline the CPU
1200*10784Ssinanallur.balasubramanian@sun.com */
1201*10784Ssinanallur.balasubramanian@sun.com bit = (tag_bit - C0) + PN_LX_TAG_ECC_START_BIT;
1202*10784Ssinanallur.balasubramanian@sun.com way = 0;
1203*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1204*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id = %d ECC bit is faulty.\n",
1205*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid);
1206*10784Ssinanallur.balasubramanian@sun.com } else {
1207*10784Ssinanallur.balasubramanian@sun.com bit = tag_bit_to_way_bit(pstype, tag_bit);
1208*10784Ssinanallur.balasubramanian@sun.com way = bit_to_way(pstype, tag_bit);
1209*10784Ssinanallur.balasubramanian@sun.com if (way < 0) {
1210*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1211*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id = %d %d bit indicted is a"
1212*10784Ssinanallur.balasubramanian@sun.com " meta bit !!\n",
1213*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, bit);
1214*10784Ssinanallur.balasubramanian@sun.com find_and_destroy_anonymous_Lxcache(hdl, cpu,
1215*10784Ssinanallur.balasubramanian@sun.com pstype,
1216*10784Ssinanallur.balasubramanian@sun.com index);
1217*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
1218*10784Ssinanallur.balasubramanian@sun.com }
1219*10784Ssinanallur.balasubramanian@sun.com }
1220*10784Ssinanallur.balasubramanian@sun.com } /* end of tag_synd != 0 */
1221*10784Ssinanallur.balasubramanian@sun.com process_after_finding_way_bit:
1222*10784Ssinanallur.balasubramanian@sun.com if ((Lxcache = cmd_Lxcache_lookup_by_type_index_way_bit(cpu, pstype,
1223*10784Ssinanallur.balasubramanian@sun.com index, way,
12246330Sjc25722 bit)) != NULL &&
12256330Sjc25722 Lxcache->Lxcache_case.cc_cp != NULL &&
12266330Sjc25722 fmd_case_solved(hdl, Lxcache->Lxcache_case.cc_cp)) {
12276330Sjc25722 fmd_hdl_debug(hdl,
1228*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu %d: the case for %s is already solved.\n",
12296330Sjc25722 fltnm, cpu->cpu_cpuid, Lxcache->Lxcache_bufname);
1230*10784Ssinanallur.balasubramanian@sun.com find_and_destroy_anonymous_Lxcache(hdl, cpu, pstype, index);
12316330Sjc25722 return (CMD_EVD_REDUND);
12326330Sjc25722 }
12336330Sjc25722
12346330Sjc25722 if (Lxcache == NULL)
12356330Sjc25722 Lxcache = cmd_Lxcache_create(hdl, 0, cpu, cpu->cpu_asru_nvl,
12366330Sjc25722 pstype, index, way, bit);
1237*10784Ssinanallur.balasubramanian@sun.com if (Lxcache == NULL) {
12386330Sjc25722 fmd_hdl_debug(hdl,
1239*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu %d: Failed to create Lxcache for index %d",
1240*10784Ssinanallur.balasubramanian@sun.com " way %d bit %d\n",
12416330Sjc25722 fltnm, cpu->cpu_cpuid, index, way, bit);
1242*10784Ssinanallur.balasubramanian@sun.com find_and_destroy_anonymous_Lxcache(hdl, cpu, pstype, index);
1243*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
1244*10784Ssinanallur.balasubramanian@sun.com }
1245*10784Ssinanallur.balasubramanian@sun.com if (cmd_create_case_for_Lxcache(hdl, cpu, Lxcache) == B_FALSE) {
1246*10784Ssinanallur.balasubramanian@sun.com find_and_destroy_anonymous_Lxcache(hdl, cpu, pstype, index);
1247*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
12486330Sjc25722 }
12496330Sjc25722 if (Lxcache->Lxcache_case.cc_serdnm == NULL) {
12506330Sjc25722 Lxcache->Lxcache_case.cc_serdnm = cmd_Lxcache_serdnm_create(hdl,
12516330Sjc25722 cpu->cpu_cpuid, pstype, index,
12526330Sjc25722 way, bit);
1253*10784Ssinanallur.balasubramanian@sun.com if (!fmd_serd_exists(hdl, Lxcache->Lxcache_case.cc_serdnm)) {
1254*10784Ssinanallur.balasubramanian@sun.com fmd_serd_create(hdl, Lxcache->Lxcache_case.cc_serdnm,
1255*10784Ssinanallur.balasubramanian@sun.com fmd_prop_get_int32(hdl, serdn),
1256*10784Ssinanallur.balasubramanian@sun.com fmd_prop_get_int64(hdl, serdt));
1257*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1258*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id %d: created a SERD engine %s\n",
1259*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid,
1260*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_case.cc_serdnm);
1261*10784Ssinanallur.balasubramanian@sun.com }
12626330Sjc25722 }
12636330Sjc25722 fmd_hdl_debug(hdl,
1264*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d: Checking if the SERD engine %s has fired.\n",
12656330Sjc25722 fltnm, cpu->cpu_cpuid, Lxcache->Lxcache_case.cc_serdnm);
12666330Sjc25722
1267*10784Ssinanallur.balasubramanian@sun.com (void) fmd_serd_record(hdl, Lxcache->Lxcache_case.cc_serdnm, ep);
1268*10784Ssinanallur.balasubramanian@sun.com if (way >= 0) {
1269*10784Ssinanallur.balasubramanian@sun.com /*
1270*10784Ssinanallur.balasubramanian@sun.com * Now that we have recorded the event ep we can do the
1271*10784Ssinanallur.balasubramanian@sun.com * necessary cleanup of resources allocated for recheck of tags.
1272*10784Ssinanallur.balasubramanian@sun.com */
1273*10784Ssinanallur.balasubramanian@sun.com find_and_destroy_anonymous_Lxcache(hdl, cpu, pstype, index);
1274*10784Ssinanallur.balasubramanian@sun.com }
1275*10784Ssinanallur.balasubramanian@sun.com if (fmd_serd_fired(hdl, Lxcache->Lxcache_case.cc_serdnm) ==
12766330Sjc25722 FMD_B_FALSE)
1277*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK);
12786330Sjc25722
1279*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "\n%s: cpu_id = %d creating fault %s\n",
12806330Sjc25722 fltnm, cpu->cpu_cpuid, Lxcache->Lxcache_case.cc_serdnm);
12816330Sjc25722 fmd_case_add_serd(hdl, Lxcache->Lxcache_case.cc_cp,
12826330Sjc25722 Lxcache->Lxcache_case.cc_serdnm);
12836330Sjc25722 fmd_serd_reset(hdl, Lxcache->Lxcache_case.cc_serdnm);
1284*10784Ssinanallur.balasubramanian@sun.com if (way == -1) {
1285*10784Ssinanallur.balasubramanian@sun.com /*
1286*10784Ssinanallur.balasubramanian@sun.com * The assignment below is to make the code easier to maintain.
1287*10784Ssinanallur.balasubramanian@sun.com * We need to destroy the anonymous_Lxcache after we have
1288*10784Ssinanallur.balasubramanian@sun.com * identifed a way to retire. If we cannot detrmine a way to
1289*10784Ssinanallur.balasubramanian@sun.com * retire we will destrory the anonymous_Lxcache and fault the
1290*10784Ssinanallur.balasubramanian@sun.com * cpu.
1291*10784Ssinanallur.balasubramanian@sun.com */
1292*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache = Lxcache;
1293*10784Ssinanallur.balasubramanian@sun.com /*
1294*10784Ssinanallur.balasubramanian@sun.com * Anonymous TAG way retirement.
1295*10784Ssinanallur.balasubramanian@sun.com * - if a way at this index has already been retired as
1296*10784Ssinanallur.balasubramanian@sun.com * "suspect-1", unretire that way, and retire the next
1297*10784Ssinanallur.balasubramanian@sun.com * unretired way as "suspect-0", using a pattern of all zeros
1298*10784Ssinanallur.balasubramanian@sun.com * for the PA bits.
1299*10784Ssinanallur.balasubramanian@sun.com * - if a way at this index has already been retired as
1300*10784Ssinanallur.balasubramanian@sun.com * "suspect-0", re-retire that way as "suspect-1", using a
1301*10784Ssinanallur.balasubramanian@sun.com * pattern of all ones for the PA bits.
1302*10784Ssinanallur.balasubramanian@sun.com * - if no ways have been retired as "suspect" for this index,
1303*10784Ssinanallur.balasubramanian@sun.com * retire the lowest unretired way as "suspect-0" for this
1304*10784Ssinanallur.balasubramanian@sun.com * bit, using a pattern of all zeros for the PA bits.
1305*10784Ssinanallur.balasubramanian@sun.com * - if there is no next retirable way, fault the CPU.
1306*10784Ssinanallur.balasubramanian@sun.com */
1307*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache = cmd_Lxcache_lookup_by_type_index_bit_reason(
1308*10784Ssinanallur.balasubramanian@sun.com cpu, pstype, index, bit, CMD_LXSUSPECT_1_TAG);
1309*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache->Lxcache_ep = ep;
1310*10784Ssinanallur.balasubramanian@sun.com if (suspect_Lxcache) {
1311*10784Ssinanallur.balasubramanian@sun.com ret = unretire_suspect_and_retire_next_retirable_way(
1312*10784Ssinanallur.balasubramanian@sun.com hdl, cpu, suspect_Lxcache, anonymous_Lxcache,
1313*10784Ssinanallur.balasubramanian@sun.com fltnm);
1314*10784Ssinanallur.balasubramanian@sun.com return (ret);
1315*10784Ssinanallur.balasubramanian@sun.com } /* end SUSPECT_1_TAG */
1316*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache = cmd_Lxcache_lookup_by_type_index_bit_reason(
1317*10784Ssinanallur.balasubramanian@sun.com cpu, pstype, index, bit, CMD_LXSUSPECT_0_TAG);
1318*10784Ssinanallur.balasubramanian@sun.com if (suspect_Lxcache) {
1319*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1320*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d found index %d way %d"
1321*10784Ssinanallur.balasubramanian@sun.com " bit %d retired as SUSPECT_0_TAG. Will"
1322*10784Ssinanallur.balasubramanian@sun.com " re-retire this now as SUSPECT_1_TAG.\n",
1323*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index,
1324*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_way, bit);
1325*10784Ssinanallur.balasubramanian@sun.com /*
1326*10784Ssinanallur.balasubramanian@sun.com * destroy the anonymous_Lxcache
1327*10784Ssinanallur.balasubramanian@sun.com */
1328*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy(hdl, cpu, anonymous_Lxcache);
1329*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_ep = ep;
1330*10784Ssinanallur.balasubramanian@sun.com /*
1331*10784Ssinanallur.balasubramanian@sun.com * We need to update the FM_FMRI_CPU_CACHE_BIT entry
1332*10784Ssinanallur.balasubramanian@sun.com * in the Lxcache_asru_nvl. This entry was last updated
1333*10784Ssinanallur.balasubramanian@sun.com * when the cacheline was retired as SUSPECT_0.
1334*10784Ssinanallur.balasubramanian@sun.com * Therefore the MSB of FM_FMRI_CPU_CACHE_BIT entry
1335*10784Ssinanallur.balasubramanian@sun.com * value will be reset. To retire cacheline as
1336*10784Ssinanallur.balasubramanian@sun.com * SUSPECT_1 the MSB has to be set.
1337*10784Ssinanallur.balasubramanian@sun.com */
1338*10784Ssinanallur.balasubramanian@sun.com errno = nvlist_add_uint16(
1339*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_asru_nvl,
1340*10784Ssinanallur.balasubramanian@sun.com FM_FMRI_CPU_CACHE_BIT,
1341*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_bit);
1342*10784Ssinanallur.balasubramanian@sun.com if (errno) {
1343*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1344*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d: failed to update",
1345*10784Ssinanallur.balasubramanian@sun.com " CACHE_BIT in asru.\n",
1346*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid);
1347*10784Ssinanallur.balasubramanian@sun.com }
1348*10784Ssinanallur.balasubramanian@sun.com return (cmd_Lxcache_retire_as_reason(hdl, cpu,
1349*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache, fltnm, CMD_LXSUSPECT_1_TAG));
1350*10784Ssinanallur.balasubramanian@sun.com } /* end of SUSPECT_0_TAG */
1351*10784Ssinanallur.balasubramanian@sun.com /*
1352*10784Ssinanallur.balasubramanian@sun.com * No ways have been retired as "SUSPECT_x" for this bit.
1353*10784Ssinanallur.balasubramanian@sun.com * We need to retire the lowest unretired way as suspect.
1354*10784Ssinanallur.balasubramanian@sun.com */
1355*10784Ssinanallur.balasubramanian@sun.com ret = retire_lowest_retirable_way_as_suspect(hdl, cpu,
1356*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache,
1357*10784Ssinanallur.balasubramanian@sun.com fltnm);
1358*10784Ssinanallur.balasubramanian@sun.com return (ret);
1359*10784Ssinanallur.balasubramanian@sun.com } /* End of Anonymous TAG retirement */
1360*10784Ssinanallur.balasubramanian@sun.com /*
1361*10784Ssinanallur.balasubramanian@sun.com * Identified bit and way has fired.
1362*10784Ssinanallur.balasubramanian@sun.com * - Destroy any anonymous SERD engine at that index.
1363*10784Ssinanallur.balasubramanian@sun.com * - If the bad bit is an ECC bit, fault the CPU.
1364*10784Ssinanallur.balasubramanian@sun.com * - If the way was already convicted due to tag errors, fault the CPU.
1365*10784Ssinanallur.balasubramanian@sun.com * - If the bad bit is a state bit, then:
1366*10784Ssinanallur.balasubramanian@sun.com * - if the stable value of the bad bit will hold the NA encoding,
1367*10784Ssinanallur.balasubramanian@sun.com * retire the containing way as "convicted".
1368*10784Ssinanallur.balasubramanian@sun.com * - if the stable value of the bad bit will not hold the NA
1369*10784Ssinanallur.balasubramanian@sun.com * encoding, fault the CPU.
1370*10784Ssinanallur.balasubramanian@sun.com */
1371*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy_anonymous_serd_engines(hdl, cpu, pstype, index, -1);
13726330Sjc25722 sticky_bit = find_bit_stickiness(tag_data, way, bit);
1373*10784Ssinanallur.balasubramanian@sun.com if ((bit >= PN_LX_TAG_ECC_START_BIT) &&
1374*10784Ssinanallur.balasubramanian@sun.com (bit <= PN_LX_TAG_ECC_END_BIT)) {
1375*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1376*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d Bad ECC bit %d at cache index %d way %d"
1377*10784Ssinanallur.balasubramanian@sun.com " detected. Will offline the CPU.\n",
1378*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, bit, index, way);
13796330Sjc25722 cmd_fault_the_cpu(hdl, cpu, pstype, fltnm);
13806330Sjc25722 return (CMD_EVD_OK);
13816330Sjc25722 }
13826330Sjc25722 /*
13836330Sjc25722 * Check if a STATE bit is faulty.
13846330Sjc25722 * If so we need to ensure that we will be able to
13856330Sjc25722 * make the way NA, else fault the CPU.
13866330Sjc25722 */
1387*10784Ssinanallur.balasubramanian@sun.com if (bit <= PN_LX_STATE_END_BIT) {
13886330Sjc25722 fmd_hdl_debug(hdl,
13896330Sjc25722 "%s cpu_id = %d: STATE bit %d is faulty.\n",
13906330Sjc25722 fltnm, cpu->cpu_cpuid, bit);
13916330Sjc25722 /*
13926330Sjc25722 * If the stable value of bit will hold the NA encoding
13936330Sjc25722 * retire the containing way Else fault the cpu.
13946330Sjc25722 */
1395*10784Ssinanallur.balasubramanian@sun.com state = tag_data[way] & CH_ECSTATE_MASK;
1396*10784Ssinanallur.balasubramanian@sun.com if ((state & (1 << bit)) != (PN_ECSTATE_NA & (1 << bit))) {
13976330Sjc25722 /*
1398*10784Ssinanallur.balasubramanian@sun.com * The stable value of the bad bit will not hold the
1399*10784Ssinanallur.balasubramanian@sun.com * NA encoding. will fault the CPU.
14006330Sjc25722 */
1401*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1402*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d STATE bit %d is faulty at"
1403*10784Ssinanallur.balasubramanian@sun.com " cache index %d way %d. STATE = 0x%x\n"
1404*10784Ssinanallur.balasubramanian@sun.com " The bad bit will not hold the encoding we need"
1405*10784Ssinanallur.balasubramanian@sun.com " to mark the cacheline as retired, so will offline"
1406*10784Ssinanallur.balasubramanian@sun.com " the CPU.\n",
1407*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, bit, index, way, state);
14086330Sjc25722 cmd_fault_the_cpu(hdl, cpu, pstype, fltnm);
14096330Sjc25722 return (CMD_EVD_OK);
14106330Sjc25722 }
14116330Sjc25722 }
14126330Sjc25722 /*
1413*10784Ssinanallur.balasubramanian@sun.com * Check if we are getting fault on a way that is already retired.
1414*10784Ssinanallur.balasubramanian@sun.com * if the way was already convicted due to tag errors, fault the CPU.
1415*10784Ssinanallur.balasubramanian@sun.com * Note that the way could have previously been retired due to
1416*10784Ssinanallur.balasubramanian@sun.com * data errors. This is okay; we just re-retire it due to tag errors,
1417*10784Ssinanallur.balasubramanian@sun.com * so that we can write the offending tag bit to a stable value.
14186330Sjc25722 */
1419*10784Ssinanallur.balasubramanian@sun.com if ((tag_data[way] & CH_ECSTATE_MASK) == PN_ECSTATE_NA) {
1420*10784Ssinanallur.balasubramanian@sun.com /*
1421*10784Ssinanallur.balasubramanian@sun.com * Looking for CONVICTED TAG fault first.
1422*10784Ssinanallur.balasubramanian@sun.com * If found retire the CPU.
1423*10784Ssinanallur.balasubramanian@sun.com */
1424*10784Ssinanallur.balasubramanian@sun.com retired_Lxcache = cmd_Lxcache_lookup_by_type_index_way_reason(
1425*10784Ssinanallur.balasubramanian@sun.com cpu, pstype, index, way, CMD_LXCONVICTED);
1426*10784Ssinanallur.balasubramanian@sun.com if (retired_Lxcache) {
1427*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1428*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu %d: The cache index %d way %d previously"
1429*10784Ssinanallur.balasubramanian@sun.com " retired for %s fault at bit %d is reporting"
1430*10784Ssinanallur.balasubramanian@sun.com " fault. Will fault the CPU\n",
1431*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index, way,
1432*10784Ssinanallur.balasubramanian@sun.com cmd_type_to_str(
1433*10784Ssinanallur.balasubramanian@sun.com retired_Lxcache->Lxcache_type),
1434*10784Ssinanallur.balasubramanian@sun.com retired_Lxcache->Lxcache_bit);
1435*10784Ssinanallur.balasubramanian@sun.com cmd_fault_the_cpu(hdl, cpu, pstype, fltnm);
1436*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK);
1437*10784Ssinanallur.balasubramanian@sun.com }
1438*10784Ssinanallur.balasubramanian@sun.com way_already_retired = 1;
14396330Sjc25722 }
14406330Sjc25722 /*
1441*10784Ssinanallur.balasubramanian@sun.com * If any way(Including the current way) at this index is retired as
1442*10784Ssinanallur.balasubramanian@sun.com * "suspect" due to tag errors, unretire it. (If that suspect way
1443*10784Ssinanallur.balasubramanian@sun.com * really was bad, it will start producing errors again and will
1444*10784Ssinanallur.balasubramanian@sun.com * eventually be retired again.)
14456330Sjc25722 */
1446*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache = cmd_Lxcache_lookup_by_type_index_bit_reason(
1447*10784Ssinanallur.balasubramanian@sun.com cpu, pstype, index, -1,
1448*10784Ssinanallur.balasubramanian@sun.com (CMD_LXSUSPECT_0_TAG | CMD_LXSUSPECT_1_TAG));
1449*10784Ssinanallur.balasubramanian@sun.com if (suspect_Lxcache) {
14506330Sjc25722 fmd_hdl_debug(hdl,
1451*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d found index %d way %d"
1452*10784Ssinanallur.balasubramanian@sun.com " bit %d retired as SUSPECT_x. Will"
1453*10784Ssinanallur.balasubramanian@sun.com " unretire this now.\n",
1454*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index,
1455*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_way, -1);
1456*10784Ssinanallur.balasubramanian@sun.com /*
1457*10784Ssinanallur.balasubramanian@sun.com * unretire the suspect_x retired_way.
1458*10784Ssinanallur.balasubramanian@sun.com */
1459*10784Ssinanallur.balasubramanian@sun.com if (cmd_Lxcache_unretire(hdl, cpu, suspect_Lxcache, fltnm)
1460*10784Ssinanallur.balasubramanian@sun.com == B_TRUE) {
1461*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_reason =
1462*10784Ssinanallur.balasubramanian@sun.com CMD_LXFUNCTIONING;
1463*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1464*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d index %d way %d"
1465*10784Ssinanallur.balasubramanian@sun.com " successfully unretired. Will"
1466*10784Ssinanallur.balasubramanian@sun.com " destroy this Lxcache now.\n",
1467*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index,
1468*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_way);
1469*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy(hdl, cpu, suspect_Lxcache);
1470*10784Ssinanallur.balasubramanian@sun.com } else {
1471*10784Ssinanallur.balasubramanian@sun.com /*
1472*10784Ssinanallur.balasubramanian@sun.com * We are unable to unretire the previously retired
1473*10784Ssinanallur.balasubramanian@sun.com * SUSPECT way at the fault index.
1474*10784Ssinanallur.balasubramanian@sun.com * If the previously retired way is same as the way
1475*10784Ssinanallur.balasubramanian@sun.com * we are attempting to retire then return failure.
1476*10784Ssinanallur.balasubramanian@sun.com */
1477*10784Ssinanallur.balasubramanian@sun.com if (suspect_Lxcache->Lxcache_way ==
1478*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_way)
1479*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
1480*10784Ssinanallur.balasubramanian@sun.com }
14816330Sjc25722 }
1482*10784Ssinanallur.balasubramanian@sun.com ways_retired = get_index_retired_ways(cpu, pstype, index);
1483*10784Ssinanallur.balasubramanian@sun.com if (ways_retired == -1)
1484*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
1485*10784Ssinanallur.balasubramanian@sun.com /*
1486*10784Ssinanallur.balasubramanian@sun.com * Before retiring a way check if we have already
1487*10784Ssinanallur.balasubramanian@sun.com * retired 3 ways for this index.
1488*10784Ssinanallur.balasubramanian@sun.com * If the way was already retired due to DATA error or
1489*10784Ssinanallur.balasubramanian@sun.com * SUSPECT_X TAG error then we skip the check.
1490*10784Ssinanallur.balasubramanian@sun.com */
1491*10784Ssinanallur.balasubramanian@sun.com if (!way_already_retired) {
1492*10784Ssinanallur.balasubramanian@sun.com if (ways_retired >= 3) {
1493*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1494*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu %d: num of ways retired for index %d"
1495*10784Ssinanallur.balasubramanian@sun.com " is %d will fault the CPU\n",
1496*10784Ssinanallur.balasubramanian@sun.com fltnm, cpu->cpu_cpuid, index, ways_retired);
1497*10784Ssinanallur.balasubramanian@sun.com cmd_fault_the_cpu(hdl, cpu, pstype, fltnm);
1498*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK);
1499*10784Ssinanallur.balasubramanian@sun.com }
1500*10784Ssinanallur.balasubramanian@sun.com }
15016330Sjc25722 fmd_hdl_debug(hdl,
1502*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu %d: num of ways retired for index %d is %d\n",
15036330Sjc25722 fltnm, cpu->cpu_cpuid, index, ways_retired);
15046330Sjc25722 if ((errno = nvlist_add_uint16(Lxcache->Lxcache_asru_nvl,
15056330Sjc25722 FM_FMRI_CPU_CACHE_BIT,
15066330Sjc25722 sticky_bit)) != 0 ||
15076330Sjc25722 (errno = fmd_nvl_fmri_expand(hdl, Lxcache->Lxcache_asru_nvl)) != 0)
15086330Sjc25722 fmd_hdl_abort(hdl, "failed to build Lxcache fmri");
1509*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_ep = ep;
1510*10784Ssinanallur.balasubramanian@sun.com return (cmd_Lxcache_retire_as_reason(hdl, cpu, Lxcache, fltnm,
1511*10784Ssinanallur.balasubramanian@sun.com CMD_LXCONVICTED));
15126330Sjc25722 }
15136330Sjc25722
1514*10784Ssinanallur.balasubramanian@sun.com static boolean_t
pn_there_is_a_matching_synd(fmd_hdl_t * hdl,cmd_xr_t * xr)1515*10784Ssinanallur.balasubramanian@sun.com pn_there_is_a_matching_synd(fmd_hdl_t *hdl, cmd_xr_t *xr)
15166330Sjc25722 {
1517*10784Ssinanallur.balasubramanian@sun.com int ec_data_idx, i;
1518*10784Ssinanallur.balasubramanian@sun.com int8_t way;
1519*10784Ssinanallur.balasubramanian@sun.com uint64_t ec_tag, data_hi, data_lo;
1520*10784Ssinanallur.balasubramanian@sun.com int ecc, calc_synd;
1521*10784Ssinanallur.balasubramanian@sun.com ec_data_elm_t *ecdptr = NULL;
1522*10784Ssinanallur.balasubramanian@sun.com uint8_t state;
1523*10784Ssinanallur.balasubramanian@sun.com ch_ec_data_t *ecp;
15246330Sjc25722
1525*10784Ssinanallur.balasubramanian@sun.com ecp = (ch_ec_data_t *)(xr->xr_cache_data);
1526*10784Ssinanallur.balasubramanian@sun.com for (way = 0; way < xr->xr_num_ways; way++, ecp++) {
1527*10784Ssinanallur.balasubramanian@sun.com ec_tag = ecp->ec_tag;
1528*10784Ssinanallur.balasubramanian@sun.com /*
1529*10784Ssinanallur.balasubramanian@sun.com * skip Retired and Invalid ways
1530*10784Ssinanallur.balasubramanian@sun.com */
1531*10784Ssinanallur.balasubramanian@sun.com state = ec_tag & CH_ECSTATE_MASK;
1532*10784Ssinanallur.balasubramanian@sun.com if ((state == PN_ECSTATE_NA) ||
1533*10784Ssinanallur.balasubramanian@sun.com (state == CH_ECSTATE_INV))
1534*10784Ssinanallur.balasubramanian@sun.com continue;
1535*10784Ssinanallur.balasubramanian@sun.com /*
1536*10784Ssinanallur.balasubramanian@sun.com * Each 16 bytes of data are protected by 9-bit ECC field.
1537*10784Ssinanallur.balasubramanian@sun.com */
1538*10784Ssinanallur.balasubramanian@sun.com
1539*10784Ssinanallur.balasubramanian@sun.com for (i = 0; i < (CH_ECACHE_SUBBLK_SIZE/16); i++) {
1540*10784Ssinanallur.balasubramanian@sun.com ec_data_idx = (i/2);
1541*10784Ssinanallur.balasubramanian@sun.com
1542*10784Ssinanallur.balasubramanian@sun.com ecdptr = &ecp->ec_data[ec_data_idx];
1543*10784Ssinanallur.balasubramanian@sun.com if ((i & 1) == 0) {
1544*10784Ssinanallur.balasubramanian@sun.com ecc = (ecdptr->ec_eccd >> 9) & 0x1ff;
1545*10784Ssinanallur.balasubramanian@sun.com data_hi = ecdptr->ec_d8[0];
1546*10784Ssinanallur.balasubramanian@sun.com data_lo = ecdptr->ec_d8[1];
1547*10784Ssinanallur.balasubramanian@sun.com } else {
1548*10784Ssinanallur.balasubramanian@sun.com ecc = ecdptr->ec_eccd & 0x1ff;
1549*10784Ssinanallur.balasubramanian@sun.com data_hi = ecdptr->ec_d8[2];
1550*10784Ssinanallur.balasubramanian@sun.com data_lo = ecdptr->ec_d8[3];
15516330Sjc25722 }
1552*10784Ssinanallur.balasubramanian@sun.com
1553*10784Ssinanallur.balasubramanian@sun.com calc_synd = calcsynd(data_hi, data_lo, ecc);
1554*10784Ssinanallur.balasubramanian@sun.com if ((calc_synd != 0) &&
1555*10784Ssinanallur.balasubramanian@sun.com (xr->xr_synd == calc_synd)) {
1556*10784Ssinanallur.balasubramanian@sun.com if (xr->xr_num_ways == 1) {
1557*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1558*10784Ssinanallur.balasubramanian@sun.com "\ncomputed syndrome matches with the reported syndrome"
1559*10784Ssinanallur.balasubramanian@sun.com " 0x%x index = %d way = %d\n",
1560*10784Ssinanallur.balasubramanian@sun.com xr->xr_synd, xr->xr_error_index,
1561*10784Ssinanallur.balasubramanian@sun.com xr->xr_error_way);
15626330Sjc25722 } else {
1563*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1564*10784Ssinanallur.balasubramanian@sun.com "\ncomputed syndrome matches with"
1565*10784Ssinanallur.balasubramanian@sun.com " the reported syndrome"
1566*10784Ssinanallur.balasubramanian@sun.com " 0x%x index = %d way = %d\n",
1567*10784Ssinanallur.balasubramanian@sun.com xr->xr_synd, xr->xr_error_index,
1568*10784Ssinanallur.balasubramanian@sun.com way);
1569*10784Ssinanallur.balasubramanian@sun.com xr->xr_error_way = way;
15706330Sjc25722 }
1571*10784Ssinanallur.balasubramanian@sun.com return (B_TRUE);
1572*10784Ssinanallur.balasubramanian@sun.com }
15736330Sjc25722 }
15746330Sjc25722 }
1575*10784Ssinanallur.balasubramanian@sun.com return (B_FALSE);
15766330Sjc25722 }
15776330Sjc25722
1578*10784Ssinanallur.balasubramanian@sun.com /* add to cheetahregs.h */
1579*10784Ssinanallur.balasubramanian@sun.com #define CH_ECSTATE_NA 5
15806330Sjc25722
1581*10784Ssinanallur.balasubramanian@sun.com static int32_t
pn_extract_index(int32_t type,uint64_t afar)1582*10784Ssinanallur.balasubramanian@sun.com pn_extract_index(int32_t type, uint64_t afar)
15836330Sjc25722 {
1584*10784Ssinanallur.balasubramanian@sun.com int32_t index = -1;
15856330Sjc25722
1586*10784Ssinanallur.balasubramanian@sun.com switch (type) {
1587*10784Ssinanallur.balasubramanian@sun.com case CMD_PTR_CPU_L2DATA:
1588*10784Ssinanallur.balasubramanian@sun.com index = (int32_t)((afar & PN_L2_INDEX_MASK)
1589*10784Ssinanallur.balasubramanian@sun.com >> PN_CACHE_LINE_SHIFT);
1590*10784Ssinanallur.balasubramanian@sun.com break;
1591*10784Ssinanallur.balasubramanian@sun.com case CMD_PTR_CPU_L3DATA:
1592*10784Ssinanallur.balasubramanian@sun.com index = (int32_t)((afar & PN_L3_INDEX_MASK)
1593*10784Ssinanallur.balasubramanian@sun.com >> PN_CACHE_LINE_SHIFT);
1594*10784Ssinanallur.balasubramanian@sun.com break;
15956330Sjc25722 }
1596*10784Ssinanallur.balasubramanian@sun.com return (index);
15976330Sjc25722 }
15986330Sjc25722
15996330Sjc25722 /*
16006330Sjc25722 * cmd_cache_ce_panther
16016330Sjc25722 *
16026330Sjc25722 * This routine handles L2 and L3 cachedata errors for the Panther.
16036330Sjc25722 * It's called when the train processing for L2 and L3 correctable
16046330Sjc25722 * data errors are about to issue a fault.
16056330Sjc25722 *
16066330Sjc25722 * This routine retrieves payload information gathered during the XR
16076330Sjc25722 * processing and generates a unique SERD engine and cache data
16086330Sjc25722 * associated with the CPU if one does not exist.
16096330Sjc25722 * If the SERD fires for the given engine it will initiate a cache
16106330Sjc25722 * line fault if the way is not anonomyous.
16116330Sjc25722 * If the way is anonomyous, it will attempt to choose a way for the
16126330Sjc25722 * given index to fault. If the maximum for the index has not been
16136330Sjc25722 * reached, it will attempt to unretire a different way previously retired
16146330Sjc25722 * under suspicion for the index prior to faulting
16156330Sjc25722 * the selected way.
16166330Sjc25722 * The routine will also fault the CPU if the maximum number of
16176330Sjc25722 * retired ways for the CPU has been exceeded based on the category.
16186330Sjc25722 */
16196330Sjc25722 /*ARGSUSED*/
16206330Sjc25722 int
cmd_cache_ce_panther(fmd_hdl_t * hdl,fmd_event_t * ep,cmd_xr_t * xr)16216330Sjc25722 cmd_cache_ce_panther(fmd_hdl_t *hdl, fmd_event_t *ep, cmd_xr_t *xr)
16226330Sjc25722 {
1623*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *suspect_Lxcache, *Lxcache, *anonymous_Lxcache;
16246330Sjc25722 cmd_cpu_t *cpu = xr->xr_cpu;
16256330Sjc25722 cmd_case_t *cpu_cc;
16266330Sjc25722 cmd_ptrsubtype_t type;
16276330Sjc25722 const errdata_t *cache_ed;
1628*10784Ssinanallur.balasubramanian@sun.com uint16_t offset;
1629*10784Ssinanallur.balasubramanian@sun.com int16_t bit;
1630*10784Ssinanallur.balasubramanian@sun.com int ways_retired;
1631*10784Ssinanallur.balasubramanian@sun.com int ret;
16326330Sjc25722
16336330Sjc25722 /*
1634*10784Ssinanallur.balasubramanian@sun.com * The caller of this routine cmd_xxc_hdlr() expects us to
1635*10784Ssinanallur.balasubramanian@sun.com * return CMD_EVD_OK for success and CMD_EVD_BAD for failures.
16366330Sjc25722 * If this is not a Panther or one of the Panther specific
16376330Sjc25722 * errors that we handle here, then exit
16386330Sjc25722 */
16396330Sjc25722
1640*10784Ssinanallur.balasubramanian@sun.com if (cpu->cpu_pers.cpup_type != CPU_ULTRASPARC_IVplus)
1641*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
16426330Sjc25722
16436330Sjc25722 if (!(xr->xr_clcode & (int)PN_CACHE_ERRORS))
1644*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
16456330Sjc25722
16466330Sjc25722
16476330Sjc25722 /* Set up Cache specific structs */
16486330Sjc25722
16496330Sjc25722 if (CMD_ERRCL_ISL2XXCU(xr->xr_clcode)) {
16506330Sjc25722 type = CMD_PTR_CPU_L2DATA;
16516330Sjc25722 cpu_cc = &cpu->cpu_l2data;
1652*10784Ssinanallur.balasubramanian@sun.com cache_ed = &l2errdata;
16536330Sjc25722 } else {
16546330Sjc25722 type = CMD_PTR_CPU_L3DATA;
16556330Sjc25722 cpu_cc = &cpu->cpu_l3data;
1656*10784Ssinanallur.balasubramanian@sun.com cache_ed = &l3errdata;
16576330Sjc25722 }
16586330Sjc25722
16596330Sjc25722 /* Ensure that our case is not solved */
16606330Sjc25722
16616330Sjc25722 if (cpu->cpu_faulting || (cpu_cc->cc_cp != NULL &&
16626330Sjc25722 fmd_case_solved(hdl, cpu_cc->cc_cp)))
1663*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK);
16646330Sjc25722
1665*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "Processing Panther %s Error\n",
16666330Sjc25722 cache_ed->ed_fltnm);
16676330Sjc25722
16686330Sjc25722 /* L3 errors arrive as mem scheme errors - convert to CPU */
16696330Sjc25722 if (type == CMD_PTR_CPU_L3DATA) {
16706330Sjc25722 cmd_fmri_init(hdl, &xr->xr_rsrc,
16716330Sjc25722 xr->xr_detector_nvlist, "%s_rsrc",
16726330Sjc25722 fmd_case_uuid(hdl, xr->xr_case));
16736330Sjc25722 }
1674*10784Ssinanallur.balasubramanian@sun.com bit = (uint8_t)ecc_syndrome_tab[xr->xr_synd];
1675*10784Ssinanallur.balasubramanian@sun.com offset = (uint16_t)xr->xr_afar & 0x3f;
1676*10784Ssinanallur.balasubramanian@sun.com if (bit > C8) {
1677*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "xxC/LDxC dropped due to syndrome\n");
1678*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
1679*10784Ssinanallur.balasubramanian@sun.com }
1680*10784Ssinanallur.balasubramanian@sun.com if (bit < C0) {
1681*10784Ssinanallur.balasubramanian@sun.com /*
1682*10784Ssinanallur.balasubramanian@sun.com * Data bit. Set bit in the range 0-511
1683*10784Ssinanallur.balasubramanian@sun.com */
1684*10784Ssinanallur.balasubramanian@sun.com bit += ((3 - (offset/16)) * 128);
1685*10784Ssinanallur.balasubramanian@sun.com } else {
1686*10784Ssinanallur.balasubramanian@sun.com /*
1687*10784Ssinanallur.balasubramanian@sun.com * ECC bit. Set bit in the range 512-547
1688*10784Ssinanallur.balasubramanian@sun.com */
1689*10784Ssinanallur.balasubramanian@sun.com bit -= C0;
1690*10784Ssinanallur.balasubramanian@sun.com bit += 512 + ((3 - (offset/16)) * PN_LX_NUM_OF_BITS_IN_ECC);
16916330Sjc25722 }
1692*10784Ssinanallur.balasubramanian@sun.com xr->xr_error_index = pn_extract_index(type, xr->xr_afar);
1693*10784Ssinanallur.balasubramanian@sun.com if (xr->xr_error_index == 0xffffffff) {
1694*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "xxC/LDxC dropped due to index\n");
1695*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
1696*10784Ssinanallur.balasubramanian@sun.com }
1697*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "cpu_id: %d, syndrome: 0x%x, afar: 0x%llx\n",
1698*10784Ssinanallur.balasubramanian@sun.com xr->xr_cpuid, xr->xr_synd, xr->xr_afar);
1699*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "index: 0x%x(%d) bit: %d\n",
1700*10784Ssinanallur.balasubramanian@sun.com xr->xr_error_index, xr->xr_error_index, bit);
1701*10784Ssinanallur.balasubramanian@sun.com /*
1702*10784Ssinanallur.balasubramanian@sun.com * The payload information for the DATA errors are assembled
1703*10784Ssinanallur.balasubramanian@sun.com * after first looking for a valid line that matches the fault AFAR.
1704*10784Ssinanallur.balasubramanian@sun.com * If no match is found all 4 ways are logged and xr_num_ways
1705*10784Ssinanallur.balasubramanian@sun.com * will be 4. If a matching way is found only that entry is logged
1706*10784Ssinanallur.balasubramanian@sun.com * and xr_num_ways is set as 1.
1707*10784Ssinanallur.balasubramanian@sun.com * The xr_error_way is set as -1 when xr_num_ways is 4, else
1708*10784Ssinanallur.balasubramanian@sun.com * xr_error_way is set to the matching way.
1709*10784Ssinanallur.balasubramanian@sun.com * what we do below is to force the xr_error_way to -1 for WDC/CPC
1710*10784Ssinanallur.balasubramanian@sun.com * errors.
1711*10784Ssinanallur.balasubramanian@sun.com * For UCC and EDC errors the xr_error_way will be set correctly.
1712*10784Ssinanallur.balasubramanian@sun.com */
17136330Sjc25722
1714*10784Ssinanallur.balasubramanian@sun.com switch (xr->xr_clcode) {
1715*10784Ssinanallur.balasubramanian@sun.com case CMD_ERRCL_WDC:
1716*10784Ssinanallur.balasubramanian@sun.com case CMD_ERRCL_L3_WDC:
1717*10784Ssinanallur.balasubramanian@sun.com /*
1718*10784Ssinanallur.balasubramanian@sun.com * WDC is a disrupting trap, and invalidates and
1719*10784Ssinanallur.balasubramanian@sun.com * overwrites the problematic way. Any match is due to
1720*10784Ssinanallur.balasubramanian@sun.com * a refetch of the AFAR, which could have been to any
1721*10784Ssinanallur.balasubramanian@sun.com * way. So these are treated as "anonymous".
1722*10784Ssinanallur.balasubramanian@sun.com */
1723*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "WDC fault detected\n");
1724*10784Ssinanallur.balasubramanian@sun.com xr->xr_error_way = (uint32_t)CMD_ANON_WAY;
1725*10784Ssinanallur.balasubramanian@sun.com break;
1726*10784Ssinanallur.balasubramanian@sun.com case CMD_ERRCL_CPC:
1727*10784Ssinanallur.balasubramanian@sun.com case CMD_ERRCL_L3_CPC:
1728*10784Ssinanallur.balasubramanian@sun.com /*
1729*10784Ssinanallur.balasubramanian@sun.com * CPC is a disrupting trap, but since it happens due to
1730*10784Ssinanallur.balasubramanian@sun.com * a snoop, the problematic way could become invalid,
1731*10784Ssinanallur.balasubramanian@sun.com * overwritten by a different cache line, and then the
1732*10784Ssinanallur.balasubramanian@sun.com * AFAR accessed and pulled into a different way,
1733*10784Ssinanallur.balasubramanian@sun.com * causing a false positive match. So it's best to not
1734*10784Ssinanallur.balasubramanian@sun.com * look for a matching way and just ascribe these to
1735*10784Ssinanallur.balasubramanian@sun.com * the "anonymous" way.
1736*10784Ssinanallur.balasubramanian@sun.com */
1737*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "CPC fault detected\n");
1738*10784Ssinanallur.balasubramanian@sun.com xr->xr_error_way = (uint32_t)CMD_ANON_WAY;
1739*10784Ssinanallur.balasubramanian@sun.com break;
1740*10784Ssinanallur.balasubramanian@sun.com case CMD_ERRCL_UCC:
1741*10784Ssinanallur.balasubramanian@sun.com case CMD_ERRCL_L3_UCC:
1742*10784Ssinanallur.balasubramanian@sun.com /*
1743*10784Ssinanallur.balasubramanian@sun.com * UCC is a precise trap, so, absent activity from the
1744*10784Ssinanallur.balasubramanian@sun.com * other core, the tag address values read by the TL=1
1745*10784Ssinanallur.balasubramanian@sun.com * trap handler are likely to be the same as those at
1746*10784Ssinanallur.balasubramanian@sun.com * the time of the trap.
1747*10784Ssinanallur.balasubramanian@sun.com * (A snoop from another CPU might cause a change in
1748*10784Ssinanallur.balasubramanian@sun.com * state from valid to invalid, but the tag address
1749*10784Ssinanallur.balasubramanian@sun.com * won't change.) If we find a matching valid tag,
1750*10784Ssinanallur.balasubramanian@sun.com * that identifies the way.
1751*10784Ssinanallur.balasubramanian@sun.com */
1752*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "UCC fault detected\n");
1753*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "# of ways collected are %d\n",
1754*10784Ssinanallur.balasubramanian@sun.com xr->xr_num_ways);
1755*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1756*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d: error way = %d\n",
1757*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm, cpu->cpu_cpuid,
1758*10784Ssinanallur.balasubramanian@sun.com xr->xr_error_way);
1759*10784Ssinanallur.balasubramanian@sun.com break;
1760*10784Ssinanallur.balasubramanian@sun.com case CMD_ERRCL_EDC:
1761*10784Ssinanallur.balasubramanian@sun.com case CMD_ERRCL_L3_EDC:
1762*10784Ssinanallur.balasubramanian@sun.com /*
1763*10784Ssinanallur.balasubramanian@sun.com * EDC is a disrupting trap, but again if a matching
1764*10784Ssinanallur.balasubramanian@sun.com * valid way is found, it is likely to be the correct
1765*10784Ssinanallur.balasubramanian@sun.com * way.
1766*10784Ssinanallur.balasubramanian@sun.com */
1767*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "EDC fault detected\n");
1768*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "# of ways collected are %d\n",
1769*10784Ssinanallur.balasubramanian@sun.com xr->xr_num_ways);
1770*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1771*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d: error way = %d\n",
1772*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm, cpu->cpu_cpuid,
1773*10784Ssinanallur.balasubramanian@sun.com xr->xr_error_way);
1774*10784Ssinanallur.balasubramanian@sun.com break;
1775*10784Ssinanallur.balasubramanian@sun.com default:
1776*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "Unexpected fault detected\n");
1777*10784Ssinanallur.balasubramanian@sun.com xr->xr_error_way = (uint32_t)CMD_ANON_WAY;
17786330Sjc25722 }
1779*10784Ssinanallur.balasubramanian@sun.com if ((type == CMD_PTR_CPU_L2DATA) &&
1780*10784Ssinanallur.balasubramanian@sun.com (xr->xr_cache_data != NULL) &&
1781*10784Ssinanallur.balasubramanian@sun.com (!pn_there_is_a_matching_synd(hdl, xr))) {
1782*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "No matching syndrome\n");
17836330Sjc25722 }
1784*10784Ssinanallur.balasubramanian@sun.com Lxcache = cmd_Lxcache_lookup_by_type_index_way_bit(xr->xr_cpu, type,
17856330Sjc25722 xr->xr_error_index, xr->xr_error_way, bit);
17866330Sjc25722
1787*10784Ssinanallur.balasubramanian@sun.com if (Lxcache == NULL) {
17886330Sjc25722 fmd_hdl_debug(hdl,
1789*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu %d: creating a case for index %d way %d"
1790*10784Ssinanallur.balasubramanian@sun.com " bit %d\n",
17916330Sjc25722 cache_ed->ed_fltnm, xr->xr_cpuid,
17926330Sjc25722 xr->xr_error_index, xr->xr_error_way, bit);
1793*10784Ssinanallur.balasubramanian@sun.com Lxcache = cmd_Lxcache_create(hdl, xr, xr->xr_cpu,
17946330Sjc25722 xr->xr_cpu->cpu_asru_nvl,
17956330Sjc25722 type, xr->xr_error_index,
17966330Sjc25722 xr->xr_error_way, bit);
1797*10784Ssinanallur.balasubramanian@sun.com if (Lxcache == NULL) {
1798*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1799*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d:Failed to create a Lxcache for"
1800*10784Ssinanallur.balasubramanian@sun.com " index %d way %d bit %d\n",
1801*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm, cpu->cpu_cpuid,
1802*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_index,
1803*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_way, Lxcache->Lxcache_bit);
1804*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
1805*10784Ssinanallur.balasubramanian@sun.com }
1806*10784Ssinanallur.balasubramanian@sun.com }
1807*10784Ssinanallur.balasubramanian@sun.com if (cmd_create_case_for_Lxcache(hdl, cpu, Lxcache) == B_FALSE)
1808*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
1809*10784Ssinanallur.balasubramanian@sun.com if (Lxcache->Lxcache_case.cc_serdnm == NULL) {
1810*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_case.cc_serdnm =
18116330Sjc25722 cmd_Lxcache_serdnm_create(hdl, xr->xr_cpuid,
18126330Sjc25722 type, xr->xr_error_index, xr->xr_error_way, bit);
18136330Sjc25722
18146330Sjc25722 if (!fmd_serd_exists(hdl,
1815*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_case.cc_serdnm)) {
18166330Sjc25722 fmd_serd_create(hdl,
1817*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_case.cc_serdnm,
18186330Sjc25722 cache_ed->ed_serd->cs_n,
18196330Sjc25722 cache_ed->ed_serd->cs_t);
1820*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1821*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu_id %d: created a SERD engine %s\n",
1822*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm, cpu->cpu_cpuid,
1823*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_case.cc_serdnm);
18246330Sjc25722 }
18256330Sjc25722 }
18266330Sjc25722 /* Ensure that our case is not solved */
1827*10784Ssinanallur.balasubramanian@sun.com if ((Lxcache->Lxcache_case.cc_cp != NULL) &&
1828*10784Ssinanallur.balasubramanian@sun.com fmd_case_solved(hdl, Lxcache->Lxcache_case.cc_cp)) {
1829*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1830*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu %d: the case for %s is already solved.\n",
1831*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm, cpu->cpu_cpuid,
1832*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_bufname);
1833*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_REDUND);
18346330Sjc25722 }
18356330Sjc25722
1836*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1837*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d: checking if SERD engine %s has fired.\n",
1838*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm, xr->xr_cpuid, Lxcache->Lxcache_case.cc_serdnm);
18396330Sjc25722
1840*10784Ssinanallur.balasubramanian@sun.com if (fmd_serd_record(hdl, Lxcache->Lxcache_case.cc_serdnm, ep)
1841*10784Ssinanallur.balasubramanian@sun.com == FMD_B_FALSE)
1842*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK); /* serd engine hasn't fired yet */
18436330Sjc25722
1844*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "\n%s: cpu_id = %d creating fault %s\n",
1845*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm, cpu->cpu_cpuid,
1846*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_case.cc_serdnm);
1847*10784Ssinanallur.balasubramanian@sun.com fmd_case_add_serd(hdl, Lxcache->Lxcache_case.cc_cp,
1848*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_case.cc_serdnm);
1849*10784Ssinanallur.balasubramanian@sun.com fmd_serd_reset(hdl, Lxcache->Lxcache_case.cc_serdnm);
1850*10784Ssinanallur.balasubramanian@sun.com /*
1851*10784Ssinanallur.balasubramanian@sun.com * Find out if there is a way at the fault index/bit that was retired
1852*10784Ssinanallur.balasubramanian@sun.com * as suspect. We need this information for both anonymous way and
1853*10784Ssinanallur.balasubramanian@sun.com * identified way handling. We store this info in suspect_Lxcache.
1854*10784Ssinanallur.balasubramanian@sun.com */
1855*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1856*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d checking if there is a way at"
1857*10784Ssinanallur.balasubramanian@sun.com " index %d retired as suspect due to bit %d\n",
1858*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm, cpu->cpu_cpuid,
1859*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_index, Lxcache->Lxcache_bit);
1860*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache = cmd_Lxcache_lookup_by_type_index_bit_reason(
1861*10784Ssinanallur.balasubramanian@sun.com cpu, type, Lxcache->Lxcache_index, Lxcache->Lxcache_bit,
1862*10784Ssinanallur.balasubramanian@sun.com CMD_LXSUSPECT_DATA);
1863*10784Ssinanallur.balasubramanian@sun.com if (xr->xr_error_way != (uint32_t)CMD_ANON_WAY) {
1864*10784Ssinanallur.balasubramanian@sun.com /*
1865*10784Ssinanallur.balasubramanian@sun.com * IDENTIFIED WAY DATA error handling.
1866*10784Ssinanallur.balasubramanian@sun.com *
1867*10784Ssinanallur.balasubramanian@sun.com * If there is a way at that index retired as suspect due
1868*10784Ssinanallur.balasubramanian@sun.com * to that bit, unretire it.
1869*10784Ssinanallur.balasubramanian@sun.com * retire the identified way, and mark the way as "convicted"
1870*10784Ssinanallur.balasubramanian@sun.com * for this bit. Destroy any anonymous SERD engine named by
1871*10784Ssinanallur.balasubramanian@sun.com * that index and bit.
1872*10784Ssinanallur.balasubramanian@sun.com */
1873*10784Ssinanallur.balasubramanian@sun.com if (suspect_Lxcache != NULL) {
18746330Sjc25722 fmd_hdl_debug(hdl,
1875*10784Ssinanallur.balasubramanian@sun.com "\n%s:cpu_id %d found index %d way %d"
1876*10784Ssinanallur.balasubramanian@sun.com " bit %d retired on suspicion. Will"
1877*10784Ssinanallur.balasubramanian@sun.com " unretire this now.\n",
1878*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm, cpu->cpu_cpuid,
1879*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_index,
1880*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_way,
1881*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_bit);
1882*10784Ssinanallur.balasubramanian@sun.com /*
1883*10784Ssinanallur.balasubramanian@sun.com * unretire the retired_way.
1884*10784Ssinanallur.balasubramanian@sun.com */
1885*10784Ssinanallur.balasubramanian@sun.com if (cmd_Lxcache_unretire(hdl, cpu, suspect_Lxcache,
1886*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm) == B_TRUE) {
1887*10784Ssinanallur.balasubramanian@sun.com suspect_Lxcache->Lxcache_reason =
1888*10784Ssinanallur.balasubramanian@sun.com CMD_LXFUNCTIONING;
1889*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy(hdl, cpu, suspect_Lxcache);
18906330Sjc25722 }
18916330Sjc25722 /*
1892*10784Ssinanallur.balasubramanian@sun.com * We proceed to retire the identified way even if
1893*10784Ssinanallur.balasubramanian@sun.com * we are unable to unretire the suspect way.
1894*10784Ssinanallur.balasubramanian@sun.com * We will not end up retiring all 4 ways because
1895*10784Ssinanallur.balasubramanian@sun.com * we check the actual number of ways retired
1896*10784Ssinanallur.balasubramanian@sun.com * at this index by reading the info from processor
1897*10784Ssinanallur.balasubramanian@sun.com * directly. The call to get_index_retired_ways() does
1898*10784Ssinanallur.balasubramanian@sun.com * that.
18996330Sjc25722 */
1900*10784Ssinanallur.balasubramanian@sun.com }
1901*10784Ssinanallur.balasubramanian@sun.com /*
1902*10784Ssinanallur.balasubramanian@sun.com * Before retiring a way check if we have already
1903*10784Ssinanallur.balasubramanian@sun.com * retired 3 ways for this index.
1904*10784Ssinanallur.balasubramanian@sun.com */
1905*10784Ssinanallur.balasubramanian@sun.com ways_retired = get_index_retired_ways(cpu, type,
1906*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_index);
1907*10784Ssinanallur.balasubramanian@sun.com if (ways_retired == -1) {
1908*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1909*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu %d: We are unable to determine how many"
1910*10784Ssinanallur.balasubramanian@sun.com " ways are retired at this index. We will not be"
1911*10784Ssinanallur.balasubramanian@sun.com " retiring the identified cacheline at index %d"
1912*10784Ssinanallur.balasubramanian@sun.com " way %d\n",
1913*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm, cpu->cpu_cpuid,
1914*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_index, Lxcache->Lxcache_way);
1915*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_BAD);
1916*10784Ssinanallur.balasubramanian@sun.com }
1917*10784Ssinanallur.balasubramanian@sun.com if (ways_retired >= 3) {
1918*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1919*10784Ssinanallur.balasubramanian@sun.com "\n%s: cpu %d: num of ways retired for index %d"
1920*10784Ssinanallur.balasubramanian@sun.com " is %d. Will fault the CPU\n",
1921*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm, cpu->cpu_cpuid,
1922*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_index, ways_retired);
1923*10784Ssinanallur.balasubramanian@sun.com cmd_fault_the_cpu(hdl, cpu, type, cache_ed->ed_fltnm);
1924*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK);
19256330Sjc25722 }
1926*10784Ssinanallur.balasubramanian@sun.com /*
1927*10784Ssinanallur.balasubramanian@sun.com * retire the cache line
1928*10784Ssinanallur.balasubramanian@sun.com */
1929*10784Ssinanallur.balasubramanian@sun.com ret = cmd_Lxcache_retire_as_reason(hdl, cpu, Lxcache,
1930*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm, CMD_LXCONVICTED);
1931*10784Ssinanallur.balasubramanian@sun.com if (ret != CMD_EVD_OK)
1932*10784Ssinanallur.balasubramanian@sun.com return (ret);
1933*10784Ssinanallur.balasubramanian@sun.com /*
1934*10784Ssinanallur.balasubramanian@sun.com * anonymous serd engines for DATA faults will have valid bit
1935*10784Ssinanallur.balasubramanian@sun.com * but way as -1.
1936*10784Ssinanallur.balasubramanian@sun.com */
1937*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy_anonymous_serd_engines(hdl, cpu, type,
1938*10784Ssinanallur.balasubramanian@sun.com Lxcache->Lxcache_index,
1939*10784Ssinanallur.balasubramanian@sun.com bit);
1940*10784Ssinanallur.balasubramanian@sun.com return (CMD_EVD_OK);
1941*10784Ssinanallur.balasubramanian@sun.com } /* end of IDENTIFIED WAY error handling */
19426330Sjc25722 /*
1943*10784Ssinanallur.balasubramanian@sun.com * ANONYMOUS WAY DATA error handling.
1944*10784Ssinanallur.balasubramanian@sun.com *
1945*10784Ssinanallur.balasubramanian@sun.com * - if a way at this index has already been retired as "suspect"
1946*10784Ssinanallur.balasubramanian@sun.com * for this bit, unretire that way, and retire the next retirable
1947*10784Ssinanallur.balasubramanian@sun.com * way as "suspect" for this bit.
1948*10784Ssinanallur.balasubramanian@sun.com * - if no ways have been retired as "suspect" for this bit,
1949*10784Ssinanallur.balasubramanian@sun.com * retire the lowest unretired way as "suspect" for this bit.
1950*10784Ssinanallur.balasubramanian@sun.com * - if there is no next retirable way, fault the CPU.
19516330Sjc25722 */
1952*10784Ssinanallur.balasubramanian@sun.com /*
1953*10784Ssinanallur.balasubramanian@sun.com * The assignment below is to make the code easier to maintain.
1954*10784Ssinanallur.balasubramanian@sun.com * We need to destroy the anonymous_Lxcache after we have
1955*10784Ssinanallur.balasubramanian@sun.com * identifed a way to retire. If we cannot detrmine a way to
1956*10784Ssinanallur.balasubramanian@sun.com * retire we will destrory the anonymous_Lxcache and fault the cpu.
1957*10784Ssinanallur.balasubramanian@sun.com */
1958*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache = Lxcache;
1959*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache->Lxcache_ep = ep;
1960*10784Ssinanallur.balasubramanian@sun.com if (suspect_Lxcache != NULL) {
1961*10784Ssinanallur.balasubramanian@sun.com ret = unretire_suspect_and_retire_next_retirable_way(hdl,
1962*10784Ssinanallur.balasubramanian@sun.com cpu, suspect_Lxcache, anonymous_Lxcache,
1963*10784Ssinanallur.balasubramanian@sun.com cache_ed->ed_fltnm);
1964*10784Ssinanallur.balasubramanian@sun.com } else {
1965*10784Ssinanallur.balasubramanian@sun.com ret = retire_lowest_retirable_way_as_suspect(hdl, cpu,
1966*10784Ssinanallur.balasubramanian@sun.com anonymous_Lxcache, cache_ed->ed_fltnm);
19676330Sjc25722 }
1968*10784Ssinanallur.balasubramanian@sun.com return (ret);
19696330Sjc25722 }
19706330Sjc25722
19716330Sjc25722 /* ARGSUSED */
19726330Sjc25722 int
cmd_xr_pn_cache_fill(fmd_hdl_t * hdl,nvlist_t * nvl,cmd_xr_t * xr,cmd_cpu_t * cpu,cmd_errcl_t clcode)19736330Sjc25722 cmd_xr_pn_cache_fill(fmd_hdl_t *hdl, nvlist_t *nvl, cmd_xr_t *xr,
19746330Sjc25722 cmd_cpu_t *cpu, cmd_errcl_t clcode)
19756330Sjc25722 {
19766330Sjc25722 struct ch_ec_data *data_ptr;
1977*10784Ssinanallur.balasubramanian@sun.com uint64_t *cache_data = NULL;
19786330Sjc25722 uint_t sz;
19796330Sjc25722
19806330Sjc25722 if (cpu->cpu_pers.cpup_type != CPU_ULTRASPARC_IVplus)
19816330Sjc25722 return (0);
19826330Sjc25722
19836330Sjc25722 if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR,
1984*10784Ssinanallur.balasubramanian@sun.com &xr->xr_detector_nvlist) != 0) {
1985*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl, "look up for FM_EREPORT_DETECTOR failed\n");
19866330Sjc25722 return (-1);
1987*10784Ssinanallur.balasubramanian@sun.com }
19886330Sjc25722 if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_NAME_AFSR,
1989*10784Ssinanallur.balasubramanian@sun.com &xr->xr_afsr) != 0) {
1990*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
1991*10784Ssinanallur.balasubramanian@sun.com "look up for FM_EREPORT_PAYLOAD_NAME_AFSR failed\n");
19926330Sjc25722 return (-1);
1993*10784Ssinanallur.balasubramanian@sun.com }
19946330Sjc25722
19956330Sjc25722 /* check clcode for l2/l3 first */
19966330Sjc25722 if (CMD_ERRCL_ISL3XXCU(clcode)) {
19976330Sjc25722 if (nvlist_lookup_uint8(nvl, FM_EREPORT_PAYLOAD_NAME_L3_WAYS,
1998*10784Ssinanallur.balasubramanian@sun.com &xr->xr_num_ways) != 0) {
1999*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
2000*10784Ssinanallur.balasubramanian@sun.com "look up for FM_EREPORT_PAYLOAD_NAME_L3_WAYS failed\n");
20016330Sjc25722 return (-1);
2002*10784Ssinanallur.balasubramanian@sun.com }
20036330Sjc25722
20046330Sjc25722 if (nvlist_lookup_uint64_array(nvl,
20056330Sjc25722 FM_EREPORT_PAYLOAD_NAME_L3_DATA, (uint64_t **)&cache_data,
2006*10784Ssinanallur.balasubramanian@sun.com &sz) != 0) {
2007*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
2008*10784Ssinanallur.balasubramanian@sun.com "look up for FM_EREPORT_PAYLOAD_NAME_L3_DATA failed\n");
2009*10784Ssinanallur.balasubramanian@sun.com }
20106330Sjc25722 } else {
20116330Sjc25722 if (nvlist_lookup_uint8(nvl, FM_EREPORT_PAYLOAD_NAME_L2_WAYS,
2012*10784Ssinanallur.balasubramanian@sun.com &xr->xr_num_ways) != 0) {
2013*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
2014*10784Ssinanallur.balasubramanian@sun.com "look up for FM_EREPORT_PAYLOAD_NAME_L2_WAYS failed\n");
20156330Sjc25722 return (-1);
2016*10784Ssinanallur.balasubramanian@sun.com }
20176330Sjc25722
20186330Sjc25722 if (nvlist_lookup_uint64_array(nvl,
20196330Sjc25722 FM_EREPORT_PAYLOAD_NAME_L2_DATA, (uint64_t **)&cache_data,
2020*10784Ssinanallur.balasubramanian@sun.com &sz) != 0) {
2021*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
2022*10784Ssinanallur.balasubramanian@sun.com "look up for FM_EREPORT_PAYLOAD_NAME_L2_DATA failed\n");
2023*10784Ssinanallur.balasubramanian@sun.com }
20246330Sjc25722 }
2025*10784Ssinanallur.balasubramanian@sun.com if (xr->xr_num_ways > PN_CACHE_NWAYS) {
2026*10784Ssinanallur.balasubramanian@sun.com fmd_hdl_debug(hdl,
2027*10784Ssinanallur.balasubramanian@sun.com "xr_num_ways > PN_CACHE_WAYS\n");
20286330Sjc25722 return (-1);
2029*10784Ssinanallur.balasubramanian@sun.com }
20306330Sjc25722
20316330Sjc25722 xr->xr_cache_data = cache_data;
20326330Sjc25722 data_ptr = (struct ch_ec_data *)cache_data;
2033*10784Ssinanallur.balasubramanian@sun.com if (cache_data == NULL) {
2034*10784Ssinanallur.balasubramanian@sun.com xr->xr_error_way = (uint32_t)CMD_ANON_WAY;
2035*10784Ssinanallur.balasubramanian@sun.com return (0);
20366330Sjc25722 }
2037*10784Ssinanallur.balasubramanian@sun.com
2038*10784Ssinanallur.balasubramanian@sun.com /*
2039*10784Ssinanallur.balasubramanian@sun.com * Our error handler checks for a matching valid way
2040*10784Ssinanallur.balasubramanian@sun.com * If there is a match, there is only 1 data set, the set
2041*10784Ssinanallur.balasubramanian@sun.com * associated with the cache-line/way that was "valid"
2042*10784Ssinanallur.balasubramanian@sun.com * Otherwise, it stores all of the ways
2043*10784Ssinanallur.balasubramanian@sun.com */
2044*10784Ssinanallur.balasubramanian@sun.com xr->xr_error_tag = data_ptr[0].ec_tag;
2045*10784Ssinanallur.balasubramanian@sun.com xr->xr_error_way = (uint32_t)data_ptr[0].ec_way;
2046*10784Ssinanallur.balasubramanian@sun.com
20476330Sjc25722 /* If there is more than 1 way structure, set way to Anonymous */
20486330Sjc25722 if (xr->xr_num_ways > 1)
20496330Sjc25722 xr->xr_error_way = (uint32_t)CMD_ANON_WAY;
20506330Sjc25722
20516330Sjc25722 return (0);
20526330Sjc25722 }
2053