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 
26*10784Ssinanallur.balasubramanian@sun.com 
276330Sjc25722 /*
286330Sjc25722  * Support routines for managing per-Lxcache state.
296330Sjc25722  */
306330Sjc25722 
316330Sjc25722 #include <cmd_Lxcache.h>
326330Sjc25722 #include <cmd_mem.h>
336330Sjc25722 #include <cmd_cpu.h>
346330Sjc25722 #include <cmd.h>
356330Sjc25722 #include <errno.h>
366330Sjc25722 #include <fcntl.h>
376330Sjc25722 #include <unistd.h>
386330Sjc25722 #include <stdio.h>
396330Sjc25722 #include <strings.h>
406330Sjc25722 #include <fm/fmd_api.h>
416330Sjc25722 #include <sys/fm/protocol.h>
426330Sjc25722 #include <sys/cheetahregs.h>
436330Sjc25722 #include <sys/mem_cache.h>
446330Sjc25722 
456330Sjc25722 #define	PN_ECSTATE_NA	5
466330Sjc25722 /*
476330Sjc25722  * These values are our threshold values for SERDing CPU's based on the
486330Sjc25722  * the # of times we have retired a cache line for each category.
496330Sjc25722  */
506330Sjc25722 
516330Sjc25722 #define	CMD_CPU_SERD_AGG_1  	64
526330Sjc25722 #define	CMD_CPU_SERD_AGG_2	64
536330Sjc25722 
54*10784Ssinanallur.balasubramanian@sun.com static int8_t cmd_lowest_way[16] = {
55*10784Ssinanallur.balasubramanian@sun.com /*	0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */
56*10784Ssinanallur.balasubramanian@sun.com 	-1,  0,  1,  0,  2,  0,  1,  0,  3,  0,  1,  0,  2,  0,  1,  0};
57*10784Ssinanallur.balasubramanian@sun.com static int cmd_num_of_bits[16] = {
58*10784Ssinanallur.balasubramanian@sun.com /*	0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */
59*10784Ssinanallur.balasubramanian@sun.com 	0,  1,  1,  2,  1,  2,  2,  3,  1,  2,  2,  3,  2,  3,  3,  4};
60*10784Ssinanallur.balasubramanian@sun.com 
61*10784Ssinanallur.balasubramanian@sun.com 
62*10784Ssinanallur.balasubramanian@sun.com void
cmd_Lxcache_write(fmd_hdl_t * hdl,cmd_Lxcache_t * Lxcache)63*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_write(fmd_hdl_t *hdl, cmd_Lxcache_t *Lxcache)
646330Sjc25722 {
656330Sjc25722 	fmd_buf_write(hdl, NULL, Lxcache->Lxcache_bufname, Lxcache,
666330Sjc25722 	    sizeof (cmd_Lxcache_pers_t));
676330Sjc25722 }
686330Sjc25722 
69*10784Ssinanallur.balasubramanian@sun.com const char *
cmd_type_to_str(cmd_ptrsubtype_t pstype)707256Sjc25722 cmd_type_to_str(cmd_ptrsubtype_t pstype)
717256Sjc25722 {
727256Sjc25722 	switch (pstype) {
737256Sjc25722 		case CMD_PTR_CPU_L2DATA:
747256Sjc25722 			return ("l2data");
757256Sjc25722 			break;
767256Sjc25722 		case CMD_PTR_CPU_L3DATA:
777256Sjc25722 			return ("l3data");
787256Sjc25722 			break;
797256Sjc25722 		case CMD_PTR_CPU_L2TAG:
807256Sjc25722 			return ("l2tag");
817256Sjc25722 			break;
827256Sjc25722 		case CMD_PTR_CPU_L3TAG:
837256Sjc25722 			return ("l3tag");
847256Sjc25722 			break;
857256Sjc25722 		default:
867256Sjc25722 			return ("unknown");
877256Sjc25722 			break;
887256Sjc25722 	}
897256Sjc25722 }
90*10784Ssinanallur.balasubramanian@sun.com 
91*10784Ssinanallur.balasubramanian@sun.com const char *
cmd_flags_to_str(int flags)92*10784Ssinanallur.balasubramanian@sun.com cmd_flags_to_str(int flags)
93*10784Ssinanallur.balasubramanian@sun.com {
94*10784Ssinanallur.balasubramanian@sun.com 	switch (flags) {
95*10784Ssinanallur.balasubramanian@sun.com 		case CMD_LxCACHE_F_ACTIVE:
96*10784Ssinanallur.balasubramanian@sun.com 			return ("ACTIVE");
97*10784Ssinanallur.balasubramanian@sun.com 		case CMD_LxCACHE_F_FAULTING:
98*10784Ssinanallur.balasubramanian@sun.com 			return ("FAULTING");
99*10784Ssinanallur.balasubramanian@sun.com 		case CMD_LxCACHE_F_RETIRED:
100*10784Ssinanallur.balasubramanian@sun.com 			return ("RETIRED");
101*10784Ssinanallur.balasubramanian@sun.com 		case CMD_LxCACHE_F_UNRETIRED:
102*10784Ssinanallur.balasubramanian@sun.com 			return ("UNRETIRED");
103*10784Ssinanallur.balasubramanian@sun.com 		case CMD_LxCACHE_F_RERETIRED:
104*10784Ssinanallur.balasubramanian@sun.com 			return ("RERETIRED");
105*10784Ssinanallur.balasubramanian@sun.com 		default:
106*10784Ssinanallur.balasubramanian@sun.com 			return ("Unknown_flags");
107*10784Ssinanallur.balasubramanian@sun.com 	}
108*10784Ssinanallur.balasubramanian@sun.com }
109*10784Ssinanallur.balasubramanian@sun.com 
110*10784Ssinanallur.balasubramanian@sun.com const char *
cmd_reason_to_str(int reason)111*10784Ssinanallur.balasubramanian@sun.com cmd_reason_to_str(int reason)
112*10784Ssinanallur.balasubramanian@sun.com {
113*10784Ssinanallur.balasubramanian@sun.com 	switch (reason) {
114*10784Ssinanallur.balasubramanian@sun.com 		case CMD_LXSUSPECT_DATA:
115*10784Ssinanallur.balasubramanian@sun.com 			return ("SUSPECT_DATA");
116*10784Ssinanallur.balasubramanian@sun.com 		case CMD_LXSUSPECT_0_TAG:
117*10784Ssinanallur.balasubramanian@sun.com 			return ("SUSPECT_0_TAG");
118*10784Ssinanallur.balasubramanian@sun.com 		case CMD_LXSUSPECT_1_TAG:
119*10784Ssinanallur.balasubramanian@sun.com 			return ("SUSPECT_1_TAG");
120*10784Ssinanallur.balasubramanian@sun.com 		case CMD_LXCONVICTED:
121*10784Ssinanallur.balasubramanian@sun.com 			return ("CONVICTED");
122*10784Ssinanallur.balasubramanian@sun.com 		case CMD_LXFUNCTIONING:
123*10784Ssinanallur.balasubramanian@sun.com 			return ("FUNCTIONING");
124*10784Ssinanallur.balasubramanian@sun.com 		default:
125*10784Ssinanallur.balasubramanian@sun.com 			return ("Unknown_reason");
126*10784Ssinanallur.balasubramanian@sun.com 	}
127*10784Ssinanallur.balasubramanian@sun.com }
128*10784Ssinanallur.balasubramanian@sun.com 
129*10784Ssinanallur.balasubramanian@sun.com static void
cmd_pretty_print_Lxcache(fmd_hdl_t * hdl,cmd_Lxcache_t * Lxcache)130*10784Ssinanallur.balasubramanian@sun.com cmd_pretty_print_Lxcache(fmd_hdl_t *hdl, cmd_Lxcache_t *Lxcache)
131*10784Ssinanallur.balasubramanian@sun.com {
132*10784Ssinanallur.balasubramanian@sun.com 	fmd_hdl_debug(hdl,
133*10784Ssinanallur.balasubramanian@sun.com 	    "\n"
134*10784Ssinanallur.balasubramanian@sun.com 	    "	cpu	= %s\n"
135*10784Ssinanallur.balasubramanian@sun.com 	    "	type	= %s\n"
136*10784Ssinanallur.balasubramanian@sun.com 	    "	index	= %d\n"
137*10784Ssinanallur.balasubramanian@sun.com 	    "	way	= %d\n"
138*10784Ssinanallur.balasubramanian@sun.com 	    "	bit	= %d\n"
139*10784Ssinanallur.balasubramanian@sun.com 	    "	reason	= %s\n"
140*10784Ssinanallur.balasubramanian@sun.com 	    "	flags	= %s\n",
141*10784Ssinanallur.balasubramanian@sun.com 	    Lxcache->Lxcache_cpu_bufname,
142*10784Ssinanallur.balasubramanian@sun.com 	    cmd_type_to_str(Lxcache->Lxcache_type),
143*10784Ssinanallur.balasubramanian@sun.com 	    Lxcache->Lxcache_index,
144*10784Ssinanallur.balasubramanian@sun.com 	    Lxcache->Lxcache_way,
145*10784Ssinanallur.balasubramanian@sun.com 	    Lxcache->Lxcache_bit,
146*10784Ssinanallur.balasubramanian@sun.com 	    cmd_reason_to_str(Lxcache->Lxcache_reason),
147*10784Ssinanallur.balasubramanian@sun.com 	    cmd_flags_to_str(Lxcache->Lxcache_flags));
148*10784Ssinanallur.balasubramanian@sun.com }
149*10784Ssinanallur.balasubramanian@sun.com 
1506330Sjc25722 void
cmd_Lxcache_free(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_Lxcache_t * Lxcache,int destroy)1516330Sjc25722 cmd_Lxcache_free(fmd_hdl_t *hdl, cmd_cpu_t *cpu, cmd_Lxcache_t *Lxcache,
1526330Sjc25722     int destroy)
1536330Sjc25722 {
1546330Sjc25722 	cmd_case_t *cc = &Lxcache->Lxcache_case;
1556330Sjc25722 
1566330Sjc25722 	fmd_hdl_debug(hdl, "Entering cmd_Lxcache_free for %s destroy = %d\n",
1576330Sjc25722 	    Lxcache->Lxcache_bufname, destroy);
1586330Sjc25722 
1596330Sjc25722 	if (cc->cc_cp != NULL)
1606330Sjc25722 		cmd_case_fini(hdl, cc->cc_cp, destroy);
1616330Sjc25722 	if (cc->cc_serdnm != NULL) {
1626330Sjc25722 		if (fmd_serd_exists(hdl, cc->cc_serdnm) && destroy) {
1636330Sjc25722 			fmd_serd_destroy(hdl, cc->cc_serdnm);
1646330Sjc25722 			fmd_hdl_strfree(hdl, cc->cc_serdnm);
1656330Sjc25722 			cc->cc_serdnm = NULL;
1666330Sjc25722 		}
1676330Sjc25722 	}
168*10784Ssinanallur.balasubramanian@sun.com 	if (Lxcache->Lxcache_nvl) {
169*10784Ssinanallur.balasubramanian@sun.com 		nvlist_free(Lxcache->Lxcache_nvl);
170*10784Ssinanallur.balasubramanian@sun.com 		Lxcache->Lxcache_nvl = NULL;
171*10784Ssinanallur.balasubramanian@sun.com 	}
172*10784Ssinanallur.balasubramanian@sun.com 	/*
173*10784Ssinanallur.balasubramanian@sun.com 	 * Clean up the SERD engine created to handle recheck of TAGS.
174*10784Ssinanallur.balasubramanian@sun.com 	 * This SERD engine was created to save the event pointer.
175*10784Ssinanallur.balasubramanian@sun.com 	 */
176*10784Ssinanallur.balasubramanian@sun.com 	if (Lxcache->Lxcache_serdnm != NULL) {
177*10784Ssinanallur.balasubramanian@sun.com 		if (fmd_serd_exists(hdl, Lxcache->Lxcache_serdnm) && destroy) {
178*10784Ssinanallur.balasubramanian@sun.com 			fmd_serd_destroy(hdl, Lxcache->Lxcache_serdnm);
179*10784Ssinanallur.balasubramanian@sun.com 			fmd_hdl_strfree(hdl, Lxcache->Lxcache_serdnm);
180*10784Ssinanallur.balasubramanian@sun.com 			Lxcache->Lxcache_serdnm = NULL;
181*10784Ssinanallur.balasubramanian@sun.com 		}
182*10784Ssinanallur.balasubramanian@sun.com 	}
183*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_timeout_id = -1;
184*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_ep = NULL;
185*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_retry_count = 0;
1866330Sjc25722 	if (destroy)
1876330Sjc25722 		fmd_buf_destroy(hdl, NULL, Lxcache->Lxcache_bufname);
1886330Sjc25722 	cmd_fmri_fini(hdl, &Lxcache->Lxcache_asru, destroy);
1896330Sjc25722 	cmd_list_delete(&cpu->cpu_Lxcaches, Lxcache);
1906330Sjc25722 	fmd_hdl_free(hdl, Lxcache, sizeof (cmd_Lxcache_t));
1916330Sjc25722 }
1926330Sjc25722 
1936330Sjc25722 void
cmd_Lxcache_destroy(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_Lxcache_t * Lxcache)1946330Sjc25722 cmd_Lxcache_destroy(fmd_hdl_t *hdl, cmd_cpu_t *cpu, cmd_Lxcache_t *Lxcache)
1956330Sjc25722 {
1966330Sjc25722 	cmd_Lxcache_free(hdl, cpu, Lxcache, FMD_B_TRUE);
1976330Sjc25722 }
1986330Sjc25722 
199*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *
cmd_Lxcache_lookup_by_type_index_way_bit(cmd_cpu_t * cpu,cmd_ptrsubtype_t pstype,int32_t index,int8_t way,int16_t bit)200*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_lookup_by_type_index_way_bit(cmd_cpu_t *cpu,
201*10784Ssinanallur.balasubramanian@sun.com     cmd_ptrsubtype_t pstype, int32_t index, int8_t way, int16_t bit)
2026330Sjc25722 {
2036330Sjc25722 	cmd_Lxcache_t *Lxcache;
2046330Sjc25722 
2056330Sjc25722 	for (Lxcache = cmd_list_next(&cpu->cpu_Lxcaches); Lxcache != NULL;
2066330Sjc25722 	    Lxcache = cmd_list_next(Lxcache)) {
2076330Sjc25722 		if ((Lxcache->Lxcache_type == pstype) &&
208*10784Ssinanallur.balasubramanian@sun.com 		    (Lxcache->Lxcache_index == (uint32_t)index) &&
209*10784Ssinanallur.balasubramanian@sun.com 		    (Lxcache->Lxcache_way == (uint32_t)way) &&
210*10784Ssinanallur.balasubramanian@sun.com 		    (Lxcache->Lxcache_bit == (uint16_t)bit))
2116330Sjc25722 			return (Lxcache);
2126330Sjc25722 	}
2136330Sjc25722 
2146330Sjc25722 	return (NULL);
2156330Sjc25722 }
2166330Sjc25722 
2176330Sjc25722 cmd_Lxcache_t *
cmd_Lxcache_create(fmd_hdl_t * hdl,cmd_xr_t * xr,cmd_cpu_t * cpu,nvlist_t * modasru,cmd_ptrsubtype_t pstype,int32_t index,int8_t way,int16_t bit)2186330Sjc25722 cmd_Lxcache_create(fmd_hdl_t *hdl, cmd_xr_t *xr, cmd_cpu_t *cpu,
219*10784Ssinanallur.balasubramanian@sun.com     nvlist_t *modasru, cmd_ptrsubtype_t pstype, int32_t index,
220*10784Ssinanallur.balasubramanian@sun.com     int8_t way, int16_t bit)
2216330Sjc25722 {
2226330Sjc25722 	cmd_Lxcache_t *Lxcache;
2236330Sjc25722 	nvlist_t *asru;
2246330Sjc25722 	const char	*pstype_name;
2256330Sjc25722 	uint8_t	fmri_Lxcache_type;
2266330Sjc25722 
227*10784Ssinanallur.balasubramanian@sun.com 	pstype_name = cmd_type_to_str(pstype);
2286330Sjc25722 	fmd_hdl_debug(hdl,
229*10784Ssinanallur.balasubramanian@sun.com 	    "\n%s:cpu_id %d:Creating new Lxcache for index=%d way=%d bit=%d\n",
230*10784Ssinanallur.balasubramanian@sun.com 	    pstype_name, cpu->cpu_cpuid, index, way, bit);
2316330Sjc25722 
2326330Sjc25722 	CMD_CPU_STAT_BUMP(cpu, Lxcache_creat);
2336330Sjc25722 
2346330Sjc25722 	Lxcache = fmd_hdl_zalloc(hdl, sizeof (cmd_Lxcache_t), FMD_SLEEP);
2356330Sjc25722 	(void) strncpy(Lxcache->Lxcache_cpu_bufname,
2366330Sjc25722 	    cpu->cpu_bufname, CMD_BUFNMLEN);
2376330Sjc25722 	Lxcache->Lxcache_nodetype = CMD_NT_LxCACHE;
2386330Sjc25722 	Lxcache->Lxcache_version = CMD_LxCACHE_VERSION;
2396330Sjc25722 	Lxcache->Lxcache_type = pstype;
240*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_index = (uint32_t)index;
241*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_way = (uint32_t)way;
242*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_bit = (uint16_t)bit;
2436330Sjc25722 	Lxcache->Lxcache_reason = CMD_LXFUNCTIONING;
244*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_flags = CMD_LxCACHE_F_ACTIVE;
245*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_timeout_id = -1;
246*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_retry_count = 0;
247*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_nvl = NULL;
248*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_ep = NULL;
249*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_serdnm = NULL;
250*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_clcode = 0;
2516330Sjc25722 	Lxcache->xr = xr;
252*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_retired_fmri[0] = '\0';
2536330Sjc25722 	switch (pstype) {
2546330Sjc25722 		case CMD_PTR_CPU_L2DATA:
2556330Sjc25722 			fmri_Lxcache_type = FM_FMRI_CPU_CACHE_TYPE_L2;
2566330Sjc25722 			break;
2576330Sjc25722 		case CMD_PTR_CPU_L3DATA:
2586330Sjc25722 			fmri_Lxcache_type = FM_FMRI_CPU_CACHE_TYPE_L3;
2596330Sjc25722 			break;
2606330Sjc25722 		case CMD_PTR_CPU_L2TAG:
2616330Sjc25722 			fmri_Lxcache_type = FM_FMRI_CPU_CACHE_TYPE_L2;
2626330Sjc25722 			break;
2636330Sjc25722 		case CMD_PTR_CPU_L3TAG:
2646330Sjc25722 			fmri_Lxcache_type = FM_FMRI_CPU_CACHE_TYPE_L3;
2656330Sjc25722 			break;
2666330Sjc25722 		default:
2676330Sjc25722 			break;
2686330Sjc25722 	}
2696330Sjc25722 
2706330Sjc25722 	cmd_bufname(Lxcache->Lxcache_bufname, sizeof (Lxcache->Lxcache_bufname),
271*10784Ssinanallur.balasubramanian@sun.com 	    "Lxcache_%s_%d_%d_%d_%d", pstype_name, cpu->cpu_cpuid,
2726330Sjc25722 	    index, way, bit);
273*10784Ssinanallur.balasubramanian@sun.com 	fmd_hdl_debug(hdl,
274*10784Ssinanallur.balasubramanian@sun.com 	    "\n%s:cpu_id %d: new Lxcache name is %s\n",
275*10784Ssinanallur.balasubramanian@sun.com 	    pstype_name, cpu->cpu_cpuid, Lxcache->Lxcache_bufname);
2766330Sjc25722 	if ((errno = nvlist_dup(modasru, &asru, 0)) != 0 ||
2776330Sjc25722 	    (errno = nvlist_add_uint32(asru, FM_FMRI_CPU_CACHE_INDEX,
2786330Sjc25722 	    index)) != 0 ||
2796330Sjc25722 	    (errno = nvlist_add_uint32(asru, FM_FMRI_CPU_CACHE_WAY,
280*10784Ssinanallur.balasubramanian@sun.com 	    (uint32_t)way)) != 0 ||
2816330Sjc25722 	    (errno = nvlist_add_uint16(asru, FM_FMRI_CPU_CACHE_BIT,
2826330Sjc25722 	    bit)) != 0 ||
2836330Sjc25722 	    (errno = nvlist_add_uint8(asru, FM_FMRI_CPU_CACHE_TYPE,
2846330Sjc25722 	    fmri_Lxcache_type)) != 0 ||
2856330Sjc25722 	    (errno = fmd_nvl_fmri_expand(hdl, asru)) != 0)
2866330Sjc25722 		fmd_hdl_abort(hdl, "failed to build Lxcache fmri");
287*10784Ssinanallur.balasubramanian@sun.com 	asru->nvl_nvflag |= NV_UNIQUE_NAME_TYPE;
2886330Sjc25722 
2896330Sjc25722 	cmd_fmri_init(hdl, &Lxcache->Lxcache_asru, asru,
290*10784Ssinanallur.balasubramanian@sun.com 	    "%s_asru_%d_%d_%d", pstype_name, index, way, bit);
2916330Sjc25722 
2926330Sjc25722 	nvlist_free(asru);
2936330Sjc25722 
2946330Sjc25722 	cmd_list_append(&cpu->cpu_Lxcaches, Lxcache);
295*10784Ssinanallur.balasubramanian@sun.com 	cmd_Lxcache_write(hdl, Lxcache);
2966330Sjc25722 
2976330Sjc25722 	return (Lxcache);
2986330Sjc25722 }
2996330Sjc25722 
3006330Sjc25722 cmd_Lxcache_t *
cmd_Lxcache_lookup_by_index_way(cmd_cpu_t * cpu,cmd_ptrsubtype_t pstype,int32_t index,int8_t way)3016330Sjc25722 cmd_Lxcache_lookup_by_index_way(cmd_cpu_t *cpu, cmd_ptrsubtype_t pstype,
302*10784Ssinanallur.balasubramanian@sun.com     int32_t index, int8_t way)
3036330Sjc25722 {
3046330Sjc25722 	cmd_Lxcache_t *cache;
3056330Sjc25722 
3066330Sjc25722 	for (cache = cmd_list_next(&cpu->cpu_Lxcaches); cache != NULL;
3076330Sjc25722 	    cache = cmd_list_next(cache)) {
308*10784Ssinanallur.balasubramanian@sun.com 	if ((cache->Lxcache_index == (uint32_t)index) &&
309*10784Ssinanallur.balasubramanian@sun.com 	    (cache->Lxcache_way == (uint32_t)way) &&
3106330Sjc25722 	    (cache->Lxcache_type == pstype)) {
3116330Sjc25722 		return (cache);
3126330Sjc25722 		}
3136330Sjc25722 	}
3146330Sjc25722 
3156330Sjc25722 	return (NULL);
3166330Sjc25722 }
3176330Sjc25722 
3186330Sjc25722 static cmd_Lxcache_t *
Lxcache_wrapv1(fmd_hdl_t * hdl,cmd_Lxcache_pers_t * pers,size_t psz)3196330Sjc25722 Lxcache_wrapv1(fmd_hdl_t *hdl, cmd_Lxcache_pers_t *pers, size_t psz)
3206330Sjc25722 {
3216330Sjc25722 	cmd_Lxcache_t *Lxcache;
3226330Sjc25722 
3236330Sjc25722 	if (psz != sizeof (cmd_Lxcache_pers_t)) {
3246330Sjc25722 		fmd_hdl_abort(hdl, "size of state doesn't match size of "
3256330Sjc25722 		    "version 1 state (%u bytes).\n",
3266330Sjc25722 		    sizeof (cmd_Lxcache_pers_t));
3276330Sjc25722 	}
3286330Sjc25722 
3296330Sjc25722 	Lxcache = fmd_hdl_zalloc(hdl, sizeof (cmd_Lxcache_t), FMD_SLEEP);
3306330Sjc25722 	bcopy(pers, Lxcache, sizeof (cmd_Lxcache_pers_t));
3316330Sjc25722 	fmd_hdl_free(hdl, pers, psz);
3326330Sjc25722 	return (Lxcache);
3336330Sjc25722 }
3346330Sjc25722 
3356330Sjc25722 void *
cmd_Lxcache_restore(fmd_hdl_t * hdl,fmd_case_t * cp,cmd_case_ptr_t * ptr)3366330Sjc25722 cmd_Lxcache_restore(fmd_hdl_t *hdl, fmd_case_t *cp, cmd_case_ptr_t *ptr)
3376330Sjc25722 {
3386330Sjc25722 	cmd_Lxcache_t *Lxcache;
3396330Sjc25722 	cmd_Lxcache_t *recovered_Lxcache;
3406330Sjc25722 	cmd_cpu_t	*cpu;
3416330Sjc25722 	size_t		Lxcachesz;
3426330Sjc25722 	char		*serdnm;
3436330Sjc25722 
3446330Sjc25722 	/*
3456330Sjc25722 	 * We need to first extract the cpu name by reading directly
3466330Sjc25722 	 * from fmd buffers in order to begin our search for Lxcache in
3476330Sjc25722 	 * the appropriate cpu list.
348*10784Ssinanallur.balasubramanian@sun.com 	 * After we identify the cpu list using buf name we look
3496330Sjc25722 	 * in cpu list for our Lxcache states.
3506330Sjc25722 	 */
3516330Sjc25722 	fmd_hdl_debug(hdl, "restoring Lxcache from %s\n", ptr->ptr_name);
3526330Sjc25722 
3536330Sjc25722 	if ((Lxcachesz = fmd_buf_size(hdl, NULL, ptr->ptr_name)) == 0) {
3546330Sjc25722 		fmd_hdl_abort(hdl, "Lxcache referenced by case %s does "
3556330Sjc25722 		    "not exist in saved state\n",
3566330Sjc25722 		    fmd_case_uuid(hdl, cp));
3576330Sjc25722 	} else if (Lxcachesz != sizeof (cmd_Lxcache_pers_t)) {
3586330Sjc25722 		fmd_hdl_abort(hdl, "Lxcache buffer referenced by case %s "
3596330Sjc25722 		    "is %d bytes. Expected size is %d bytes\n",
3606330Sjc25722 		    fmd_case_uuid(hdl, cp), Lxcachesz,
3616330Sjc25722 		    sizeof (cmd_Lxcache_pers_t));
3626330Sjc25722 	}
3636330Sjc25722 
3646330Sjc25722 	if ((Lxcache = cmd_buf_read(hdl, NULL, ptr->ptr_name,
3656330Sjc25722 	    Lxcachesz)) == NULL) {
3666330Sjc25722 		fmd_hdl_abort(hdl, "failed to read Lxcache buf %s",
3676330Sjc25722 		    ptr->ptr_name);
3686330Sjc25722 	}
369*10784Ssinanallur.balasubramanian@sun.com 	cmd_pretty_print_Lxcache(hdl, Lxcache);
3706330Sjc25722 
3716330Sjc25722 	fmd_hdl_debug(hdl, "found %d in version field\n",
3726330Sjc25722 	    Lxcache->Lxcache_version);
3736330Sjc25722 	cpu = cmd_restore_cpu_only(hdl, cp, Lxcache->Lxcache_cpu_bufname);
374*10784Ssinanallur.balasubramanian@sun.com 	if (cpu == NULL) {
375*10784Ssinanallur.balasubramanian@sun.com 		fmd_hdl_debug(hdl,
376*10784Ssinanallur.balasubramanian@sun.com 		    "\nCould not restore cpu %s\n",
377*10784Ssinanallur.balasubramanian@sun.com 		    Lxcache->Lxcache_cpu_bufname);
3787429SMary.Beale@Sun.COM 		return (NULL);
379*10784Ssinanallur.balasubramanian@sun.com 	}
3806330Sjc25722 	recovered_Lxcache = Lxcache;	/* save the recovered Lxcache */
3816330Sjc25722 
3826330Sjc25722 	for (Lxcache = cmd_list_next(&cpu->cpu_Lxcaches); Lxcache != NULL;
3836330Sjc25722 	    Lxcache = cmd_list_next(Lxcache)) {
3846330Sjc25722 		if (strcmp(Lxcache->Lxcache_bufname, ptr->ptr_name) == 0)
3856330Sjc25722 			break;
3866330Sjc25722 	}
3876330Sjc25722 
3886330Sjc25722 	if (Lxcache == NULL) {
3896330Sjc25722 
3906330Sjc25722 		switch (recovered_Lxcache->Lxcache_version) {
3916330Sjc25722 			case CMD_LxCACHE_VERSION_1:
3926330Sjc25722 				Lxcache = Lxcache_wrapv1(hdl,
3936330Sjc25722 				    (cmd_Lxcache_pers_t *)recovered_Lxcache,
3946330Sjc25722 				    Lxcachesz);
3956330Sjc25722 				break;
3966330Sjc25722 			default:
3976330Sjc25722 				fmd_hdl_abort(hdl, "unknown version (found %d) "
3986330Sjc25722 				"for Lxcache state referenced by case %s.\n",
3996330Sjc25722 				    recovered_Lxcache->Lxcache_version,
4006330Sjc25722 				    fmd_case_uuid(hdl, cp));
4016330Sjc25722 			break;
4026330Sjc25722 		}
4036330Sjc25722 
4046330Sjc25722 		cmd_fmri_restore(hdl, &Lxcache->Lxcache_asru);
405*10784Ssinanallur.balasubramanian@sun.com 		/*
406*10784Ssinanallur.balasubramanian@sun.com 		 * We need to cleanup the information associated with
407*10784Ssinanallur.balasubramanian@sun.com 		 * the timeout routine because these are not checkpointed
408*10784Ssinanallur.balasubramanian@sun.com 		 * and cannot be retored.
409*10784Ssinanallur.balasubramanian@sun.com 		 */
410*10784Ssinanallur.balasubramanian@sun.com 		Lxcache->Lxcache_timeout_id = -1;
411*10784Ssinanallur.balasubramanian@sun.com 		Lxcache->Lxcache_retry_count = 0;
412*10784Ssinanallur.balasubramanian@sun.com 		Lxcache->Lxcache_nvl = NULL;
413*10784Ssinanallur.balasubramanian@sun.com 		Lxcache->Lxcache_ep = NULL;
414*10784Ssinanallur.balasubramanian@sun.com 		Lxcache->Lxcache_serdnm = NULL;
4156330Sjc25722 
4166330Sjc25722 		cmd_list_append(&cpu->cpu_Lxcaches, Lxcache);
4176330Sjc25722 	}
4186330Sjc25722 	serdnm = cmd_Lxcache_serdnm_create(hdl, cpu->cpu_cpuid,
4196330Sjc25722 	    Lxcache->Lxcache_type, Lxcache->Lxcache_index,
4206330Sjc25722 	    Lxcache->Lxcache_way, Lxcache->Lxcache_bit);
4216330Sjc25722 	fmd_hdl_debug(hdl,
4226330Sjc25722 	    "cpu_id %d: serdname for the case is %s\n",
4236330Sjc25722 	    cpu->cpu_cpuid, serdnm);
4246330Sjc25722 	fmd_hdl_debug(hdl,
4256330Sjc25722 	    "cpu_id %d: restoring the case for index %d way %d bit %d\n",
4266330Sjc25722 	    cpu->cpu_cpuid, Lxcache->Lxcache_index,
4276330Sjc25722 	    Lxcache->Lxcache_way, Lxcache->Lxcache_bit);
4286330Sjc25722 	cmd_case_restore(hdl, &Lxcache->Lxcache_case, cp, serdnm);
4296330Sjc25722 
4306330Sjc25722 	return (Lxcache);
4316330Sjc25722 }
4326330Sjc25722 
4336330Sjc25722 /*ARGSUSED*/
4346330Sjc25722 void
cmd_Lxcache_validate(fmd_hdl_t * hdl,cmd_cpu_t * cpu)4356330Sjc25722 cmd_Lxcache_validate(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
4366330Sjc25722 {
4376330Sjc25722 	cmd_Lxcache_t *Lxcache, *next;
4386330Sjc25722 
4396330Sjc25722 	for (Lxcache = cmd_list_next(&cpu->cpu_Lxcaches);
4406330Sjc25722 	    Lxcache != NULL; Lxcache = next) {
4416330Sjc25722 		next = cmd_list_next(Lxcache);
4426330Sjc25722 
4436330Sjc25722 		if (fmd_nvl_fmri_unusable(hdl, Lxcache->Lxcache_asru_nvl)) {
4446330Sjc25722 			cmd_Lxcache_destroy(hdl, cpu, Lxcache);
4456330Sjc25722 		}
4466330Sjc25722 	}
4476330Sjc25722 }
4486330Sjc25722 
4496330Sjc25722 void
cmd_Lxcache_dirty(fmd_hdl_t * hdl,cmd_Lxcache_t * Lxcache)4506330Sjc25722 cmd_Lxcache_dirty(fmd_hdl_t *hdl, cmd_Lxcache_t *Lxcache)
4516330Sjc25722 {
4526330Sjc25722 	if (fmd_buf_size(hdl, NULL, Lxcache->Lxcache_bufname) !=
4536330Sjc25722 	    sizeof (cmd_Lxcache_pers_t))
4546330Sjc25722 		fmd_buf_destroy(hdl, NULL, Lxcache->Lxcache_bufname);
4556330Sjc25722 
4566330Sjc25722 	/* No need to rewrite the FMRIs in the Lxcache - they don't change */
4576330Sjc25722 	fmd_buf_write(hdl, NULL,
4586330Sjc25722 	    Lxcache->Lxcache_bufname, &Lxcache->Lxcache_pers,
4596330Sjc25722 	    sizeof (cmd_Lxcache_pers_t));
4606330Sjc25722 }
4616330Sjc25722 
4626330Sjc25722 void
cmd_Lxcache_fini(fmd_hdl_t * hdl,cmd_cpu_t * cpu)4636330Sjc25722 cmd_Lxcache_fini(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
4646330Sjc25722 {
4656330Sjc25722 	cmd_Lxcache_t *Lxcache;
4666330Sjc25722 
4676330Sjc25722 	while ((Lxcache = cmd_list_next(&cpu->cpu_Lxcaches)) != NULL)
4686330Sjc25722 		cmd_Lxcache_free(hdl, cpu, Lxcache, FMD_B_FALSE);
4696330Sjc25722 }
470*10784Ssinanallur.balasubramanian@sun.com 
4716330Sjc25722 char *
cmd_Lxcache_serdnm_create(fmd_hdl_t * hdl,uint32_t cpu_id,cmd_ptrsubtype_t pstype,int32_t index,int8_t way,int16_t bit)4726330Sjc25722 cmd_Lxcache_serdnm_create(fmd_hdl_t *hdl, uint32_t cpu_id,
4736330Sjc25722 			    cmd_ptrsubtype_t pstype,
474*10784Ssinanallur.balasubramanian@sun.com 			    int32_t index, int8_t way, int16_t bit)
4756330Sjc25722 {
476*10784Ssinanallur.balasubramanian@sun.com 	const char *fmt = "cpu_%d:%s_%d_%d_%d_serd";
4776330Sjc25722 	const char *serdbase;
4786330Sjc25722 	size_t sz;
4796330Sjc25722 	char	*nm;
4806330Sjc25722 
481*10784Ssinanallur.balasubramanian@sun.com 	serdbase = cmd_type_to_str(pstype);
482*10784Ssinanallur.balasubramanian@sun.com 	sz = (snprintf(NULL, 0, fmt, cpu_id, serdbase, index, way, bit) + 1);
483*10784Ssinanallur.balasubramanian@sun.com 	nm = fmd_hdl_alloc(hdl, sz, FMD_SLEEP);
484*10784Ssinanallur.balasubramanian@sun.com 	(void) snprintf(nm, sz, fmt, cpu_id, serdbase, index, way, bit);
485*10784Ssinanallur.balasubramanian@sun.com 	return (nm);
486*10784Ssinanallur.balasubramanian@sun.com }
487*10784Ssinanallur.balasubramanian@sun.com 
488*10784Ssinanallur.balasubramanian@sun.com char *
cmd_Lxcache_anonymous_serdnm_create(fmd_hdl_t * hdl,uint32_t cpu_id,cmd_ptrsubtype_t pstype,int32_t index,int8_t way,int16_t bit)489*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_anonymous_serdnm_create(fmd_hdl_t *hdl, uint32_t cpu_id,
490*10784Ssinanallur.balasubramanian@sun.com 			    cmd_ptrsubtype_t pstype,
491*10784Ssinanallur.balasubramanian@sun.com 			    int32_t index, int8_t way, int16_t bit)
492*10784Ssinanallur.balasubramanian@sun.com {
493*10784Ssinanallur.balasubramanian@sun.com 	const char *fmt = "cpu_%d:%s_%d_%d_%d_anonymous_serd";
494*10784Ssinanallur.balasubramanian@sun.com 	const char *serdbase;
495*10784Ssinanallur.balasubramanian@sun.com 	size_t sz;
496*10784Ssinanallur.balasubramanian@sun.com 	char	*nm;
497*10784Ssinanallur.balasubramanian@sun.com 
498*10784Ssinanallur.balasubramanian@sun.com 	serdbase = cmd_type_to_str(pstype);
4996330Sjc25722 	sz = (snprintf(NULL, 0, fmt, cpu_id, serdbase, index, way, bit) + 1);
5006330Sjc25722 	nm = fmd_hdl_alloc(hdl, sz, FMD_SLEEP);
5016330Sjc25722 	(void) snprintf(nm, sz, fmt, cpu_id, serdbase, index, way, bit);
5026330Sjc25722 	return (nm);
5036330Sjc25722 }
5046330Sjc25722 
5056330Sjc25722 /*
5066330Sjc25722  * Count the number of SERD type 2 ways retired for a given cpu
5076330Sjc25722  * These are defined to be L3 Cache data retirements
5086330Sjc25722  */
5096330Sjc25722 
5106330Sjc25722 uint32_t
cmd_Lx_index_count_type2_ways(cmd_cpu_t * cpu)5116330Sjc25722 cmd_Lx_index_count_type2_ways(cmd_cpu_t *cpu)
5126330Sjc25722 {
5136330Sjc25722 	cmd_Lxcache_t *cache = NULL;
5146330Sjc25722 	uint32_t ret_count = 0;
5156330Sjc25722 
5166330Sjc25722 	for (cache = cmd_list_next(&cpu->cpu_Lxcaches); cache != NULL;
5176330Sjc25722 	    cache = cmd_list_next(cache)) {
518*10784Ssinanallur.balasubramanian@sun.com 		if ((cache->Lxcache_flags & CMD_LxCACHE_F_RETIRED) &&
5196330Sjc25722 		    (cache->Lxcache_type == CMD_PTR_CPU_L3DATA)) {
5206330Sjc25722 			ret_count++;
5216330Sjc25722 		}
5226330Sjc25722 	}
5236330Sjc25722 	return (ret_count);
5246330Sjc25722 }
5256330Sjc25722 /*
5266330Sjc25722  * Count the number of SERD type 1 ways retired for a given cpu
5276330Sjc25722  * These are defined to be L2 Data, tag and L3 Tag retirements
5286330Sjc25722  */
5296330Sjc25722 
5306330Sjc25722 uint32_t
cmd_Lx_index_count_type1_ways(cmd_cpu_t * cpu)5316330Sjc25722 cmd_Lx_index_count_type1_ways(cmd_cpu_t *cpu)
5326330Sjc25722 {
5336330Sjc25722 	cmd_Lxcache_t *cache = NULL;
5346330Sjc25722 	uint32_t ret_count = 0;
5356330Sjc25722 
5366330Sjc25722 	for (cache = cmd_list_next(&cpu->cpu_Lxcaches); cache != NULL;
5376330Sjc25722 	    cache = cmd_list_next(cache)) {
538*10784Ssinanallur.balasubramanian@sun.com 		if ((cache->Lxcache_flags & CMD_LxCACHE_F_RETIRED) &&
5396330Sjc25722 		    ((cache->Lxcache_type == CMD_PTR_CPU_L2DATA) ||
540*10784Ssinanallur.balasubramanian@sun.com 		    IS_TAG(cache->Lxcache_type))) {
5416330Sjc25722 			ret_count++;
5426330Sjc25722 		}
5436330Sjc25722 	}
5446330Sjc25722 	return (ret_count);
5456330Sjc25722 }
5466330Sjc25722 
5476330Sjc25722 void
cmd_fault_the_cpu(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_ptrsubtype_t pstype,const char * fltnm)5486330Sjc25722 cmd_fault_the_cpu(fmd_hdl_t *hdl, cmd_cpu_t *cpu, cmd_ptrsubtype_t pstype,
5496330Sjc25722     const char *fltnm)
5506330Sjc25722 {
5516330Sjc25722 	fmd_case_t	*cp;
5526330Sjc25722 	const char 	*uuid;
5536330Sjc25722 
5546330Sjc25722 	cp = cmd_case_create(hdl, &cpu->cpu_header, pstype,
5556330Sjc25722 	    &uuid);
556*10784Ssinanallur.balasubramanian@sun.com 	fmd_hdl_debug(hdl,
557*10784Ssinanallur.balasubramanian@sun.com 	    "\n%s:cpu_id %d Created case %s to retire CPU\n",
558*10784Ssinanallur.balasubramanian@sun.com 	    fltnm, cpu->cpu_cpuid);
5596330Sjc25722 
5606330Sjc25722 	if ((errno = fmd_nvl_fmri_expand(hdl, cpu->cpu_asru_nvl)) != 0)
5616330Sjc25722 		fmd_hdl_abort(hdl, "failed to build CPU fmri");
5626330Sjc25722 
563*10784Ssinanallur.balasubramanian@sun.com 	cmd_cpu_create_faultlist(hdl, cp, cpu, fltnm, NULL, HUNDRED_PERCENT);
5646330Sjc25722 	fmd_case_solve(hdl, cp);
5656330Sjc25722 }
566*10784Ssinanallur.balasubramanian@sun.com 
567*10784Ssinanallur.balasubramanian@sun.com void
cmd_retire_cpu_if_limits_exceeded(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_ptrsubtype_t pstype,const char * fltnm)568*10784Ssinanallur.balasubramanian@sun.com cmd_retire_cpu_if_limits_exceeded(fmd_hdl_t *hdl, cmd_cpu_t *cpu,
569*10784Ssinanallur.balasubramanian@sun.com     cmd_ptrsubtype_t pstype, const char *fltnm)
570*10784Ssinanallur.balasubramanian@sun.com {
571*10784Ssinanallur.balasubramanian@sun.com 	int cpu_retired_1, cpu_retired_2;
572*10784Ssinanallur.balasubramanian@sun.com 
573*10784Ssinanallur.balasubramanian@sun.com 	/* Retrieve the number of retired ways for each category */
574*10784Ssinanallur.balasubramanian@sun.com 
575*10784Ssinanallur.balasubramanian@sun.com 	cpu_retired_1 = cmd_Lx_index_count_type1_ways(cpu);
576*10784Ssinanallur.balasubramanian@sun.com 	cpu_retired_2 = cmd_Lx_index_count_type2_ways(cpu);
577*10784Ssinanallur.balasubramanian@sun.com 	fmd_hdl_debug(hdl,
578*10784Ssinanallur.balasubramanian@sun.com 	    "\n%s:CPU %d retired Type 1 way count is: %d\n",
579*10784Ssinanallur.balasubramanian@sun.com 	    fltnm, cpu->cpu_cpuid, cpu_retired_1);
580*10784Ssinanallur.balasubramanian@sun.com 	fmd_hdl_debug(hdl, "\n%s:CPU %d retired Type 2 way count is: %d\n",
581*10784Ssinanallur.balasubramanian@sun.com 	    fltnm, cpu->cpu_cpuid, cpu_retired_2);
582*10784Ssinanallur.balasubramanian@sun.com 
583*10784Ssinanallur.balasubramanian@sun.com 	if (((cpu_retired_1 > CMD_CPU_SERD_AGG_1) ||
584*10784Ssinanallur.balasubramanian@sun.com 	    (cpu_retired_2 > CMD_CPU_SERD_AGG_2)) &&
585*10784Ssinanallur.balasubramanian@sun.com 	    (cpu->cpu_faulting != FMD_B_TRUE)) {
586*10784Ssinanallur.balasubramanian@sun.com 		cmd_fault_the_cpu(hdl, cpu, pstype, fltnm);
587*10784Ssinanallur.balasubramanian@sun.com 	}
588*10784Ssinanallur.balasubramanian@sun.com }
589*10784Ssinanallur.balasubramanian@sun.com 
5906330Sjc25722 void
cmd_Lxcache_fault(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_Lxcache_t * Lxcache,const char * fltnm,nvlist_t * rsrc,uint_t cert)5916330Sjc25722 cmd_Lxcache_fault(fmd_hdl_t *hdl, cmd_cpu_t *cpu, cmd_Lxcache_t *Lxcache,
592*10784Ssinanallur.balasubramanian@sun.com 	const char *fltnm, nvlist_t *rsrc, uint_t cert)
5936330Sjc25722 {
594*10784Ssinanallur.balasubramanian@sun.com 	char fltmsg[64];
5956330Sjc25722 	nvlist_t *flt;
5966330Sjc25722 
597*10784Ssinanallur.balasubramanian@sun.com 	(void) snprintf(fltmsg, sizeof (fltmsg), "fault.cpu.%s.%s-line",
598*10784Ssinanallur.balasubramanian@sun.com 	    cmd_cpu_type2name(hdl, cpu->cpu_type), fltnm);
599*10784Ssinanallur.balasubramanian@sun.com 	fmd_hdl_debug(hdl,
600*10784Ssinanallur.balasubramanian@sun.com 	    "\n%s:cpu_id %d: fltmsg = %s\n",
601*10784Ssinanallur.balasubramanian@sun.com 	    fltnm, cpu->cpu_cpuid, fltmsg);
6026330Sjc25722 	if (Lxcache->Lxcache_flags & CMD_LxCACHE_F_FAULTING) {
6036330Sjc25722 		return;
6046330Sjc25722 	}
6056330Sjc25722 	Lxcache->Lxcache_flags |= CMD_LxCACHE_F_FAULTING;
606*10784Ssinanallur.balasubramanian@sun.com 	flt = fmd_nvl_create_fault(hdl, fltmsg, cert,
6076330Sjc25722 	    Lxcache->Lxcache_asru.fmri_nvl, cpu->cpu_fru_nvl, rsrc);
6086330Sjc25722 	if (nvlist_add_boolean_value(flt, FM_SUSPECT_MESSAGE, B_FALSE) != 0)
6096330Sjc25722 		fmd_hdl_abort(hdl, "failed to add no-message member to fault");
6106330Sjc25722 
611*10784Ssinanallur.balasubramanian@sun.com 	fmd_hdl_debug(hdl,
612*10784Ssinanallur.balasubramanian@sun.com 	    "\n%s:cpu_id %d: adding suspect list to case %s\n",
613*10784Ssinanallur.balasubramanian@sun.com 	    fltnm, cpu->cpu_cpuid,
614*10784Ssinanallur.balasubramanian@sun.com 	    fmd_case_uuid(hdl, Lxcache->Lxcache_case.cc_cp));
6156330Sjc25722 	fmd_case_add_suspect(hdl, Lxcache->Lxcache_case.cc_cp, flt);
6166330Sjc25722 	fmd_case_solve(hdl, Lxcache->Lxcache_case.cc_cp);
6177256Sjc25722 	if (Lxcache->Lxcache_retired_fmri[0] == 0) {
6187256Sjc25722 		if (cmd_fmri_nvl2str(hdl, Lxcache->Lxcache_asru.fmri_nvl,
6197256Sjc25722 		    Lxcache->Lxcache_retired_fmri,
6207256Sjc25722 		    sizeof (Lxcache->Lxcache_retired_fmri)) == -1)
621*10784Ssinanallur.balasubramanian@sun.com 			fmd_hdl_debug(hdl,
622*10784Ssinanallur.balasubramanian@sun.com 			    "\n%s:cpu_id %d: Failed to save the"
623*10784Ssinanallur.balasubramanian@sun.com 			    " retired fmri string\n",
624*10784Ssinanallur.balasubramanian@sun.com 			    fltnm, cpu->cpu_cpuid);
6257256Sjc25722 		else
6267256Sjc25722 			fmd_hdl_debug(hdl,
6277256Sjc25722 			    "\n%s:cpu_id %d:Saved the retired fmri string %s\n",
6287256Sjc25722 			    fltnm, cpu->cpu_cpuid,
6297256Sjc25722 			    Lxcache->Lxcache_retired_fmri);
6307256Sjc25722 	}
631*10784Ssinanallur.balasubramanian@sun.com 	Lxcache->Lxcache_flags &= ~(CMD_LxCACHE_F_FAULTING);
6326330Sjc25722 
633*10784Ssinanallur.balasubramanian@sun.com }
6346330Sjc25722 
6356330Sjc25722 void
cmd_Lxcache_close(fmd_hdl_t * hdl,void * arg)6366330Sjc25722 cmd_Lxcache_close(fmd_hdl_t *hdl, void *arg)
6376330Sjc25722 {
6386330Sjc25722 	cmd_cpu_t *cpu;
6396330Sjc25722 	cmd_Lxcache_t *Lxcache;
6406330Sjc25722 	cmd_case_t *cc;
6416330Sjc25722 
6426330Sjc25722 	Lxcache = (cmd_Lxcache_t *)arg;
643*10784Ssinanallur.balasubramanian@sun.com 	fmd_hdl_debug(hdl, "cmd_Lxcache_close called  for %s\n",
6446330Sjc25722 	    Lxcache->Lxcache_bufname);
6456330Sjc25722 	cc = &Lxcache->Lxcache_case;
6466330Sjc25722 
6476330Sjc25722 	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL;
6486330Sjc25722 	    cpu = cmd_list_next(cpu)) {
6496330Sjc25722 		if (strcmp(cpu->cpu_bufname,
6506330Sjc25722 		    Lxcache->Lxcache_cpu_bufname) == 0)
6516330Sjc25722 			break;
6526330Sjc25722 	}
6536330Sjc25722 	if (cpu == NULL)
6546330Sjc25722 		fmd_hdl_abort(hdl, "failed to find the cpu %s for %s\n",
6556330Sjc25722 		    Lxcache->Lxcache_cpu_bufname,
6566330Sjc25722 		    Lxcache->Lxcache_bufname);
6576330Sjc25722 	/*
6586330Sjc25722 	 * We will destroy the case and serd engine.
6596330Sjc25722 	 * The rest will be destroyed when we retire the CPU
6606330Sjc25722 	 * until then we keep the Lxcache strutures alive.
6616330Sjc25722 	 */
6626330Sjc25722 	if (cc->cc_cp != NULL) {
6636330Sjc25722 		cmd_case_fini(hdl, cc->cc_cp, FMD_B_TRUE);
6646330Sjc25722 		cc->cc_cp = NULL;
6656330Sjc25722 	}
6666330Sjc25722 	if (cc->cc_serdnm != NULL) {
6676330Sjc25722 		if (fmd_serd_exists(hdl, cc->cc_serdnm))
6686330Sjc25722 			fmd_serd_destroy(hdl, cc->cc_serdnm);
6696330Sjc25722 		fmd_hdl_strfree(hdl, cc->cc_serdnm);
6706330Sjc25722 		cc->cc_serdnm = NULL;
6716330Sjc25722 	}
6726330Sjc25722 
6736330Sjc25722 }
6746330Sjc25722 
675*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *
cmd_Lxcache_lookup_by_timeout_id(id_t id)676*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_lookup_by_timeout_id(id_t id)
677*10784Ssinanallur.balasubramanian@sun.com {
678*10784Ssinanallur.balasubramanian@sun.com 	cmd_cpu_t *cpu;
679*10784Ssinanallur.balasubramanian@sun.com 	cmd_Lxcache_t *cmd_Lxcache;
680*10784Ssinanallur.balasubramanian@sun.com 
681*10784Ssinanallur.balasubramanian@sun.com 	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL;
682*10784Ssinanallur.balasubramanian@sun.com 	    cpu = cmd_list_next(cpu)) {
683*10784Ssinanallur.balasubramanian@sun.com 		for (cmd_Lxcache = cmd_list_next(&cpu->cpu_Lxcaches);
684*10784Ssinanallur.balasubramanian@sun.com 		    cmd_Lxcache != NULL;
685*10784Ssinanallur.balasubramanian@sun.com 		    cmd_Lxcache = cmd_list_next(cmd_Lxcache)) {
686*10784Ssinanallur.balasubramanian@sun.com 			if (cmd_Lxcache->Lxcache_timeout_id == id)
687*10784Ssinanallur.balasubramanian@sun.com 				return (cmd_Lxcache);
688*10784Ssinanallur.balasubramanian@sun.com 		}
689*10784Ssinanallur.balasubramanian@sun.com 	}
690*10784Ssinanallur.balasubramanian@sun.com 	return (NULL);
691*10784Ssinanallur.balasubramanian@sun.com }
692*10784Ssinanallur.balasubramanian@sun.com 
6936330Sjc25722 void
cmd_Lxcache_gc(fmd_hdl_t * hdl)6946330Sjc25722 cmd_Lxcache_gc(fmd_hdl_t *hdl)
6956330Sjc25722 {
6966330Sjc25722 	cmd_cpu_t *cpu;
6976330Sjc25722 
6986330Sjc25722 	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL;
6996330Sjc25722 	    cpu = cmd_list_next(cpu))
7006330Sjc25722 		cmd_Lxcache_validate(hdl, cpu);
7016330Sjc25722 }
7026330Sjc25722 
7036330Sjc25722 cmd_evdisp_t
get_tagdata(cmd_cpu_t * cpu,cmd_ptrsubtype_t pstype,int32_t index,uint64_t * tag_data)7046330Sjc25722 get_tagdata(cmd_cpu_t *cpu, cmd_ptrsubtype_t pstype,
705*10784Ssinanallur.balasubramanian@sun.com 	    int32_t index, uint64_t	*tag_data)
7066330Sjc25722 {
7076330Sjc25722 	int		fd;
7086330Sjc25722 	cache_info_t	cache_info;
7096330Sjc25722 
7106330Sjc25722 	fd = open(mem_cache_device, O_RDONLY);
7116330Sjc25722 	if (fd == -1) {
7126330Sjc25722 		(void) printf(
7136330Sjc25722 		    "cpu_id = %d could not open %s to read tag info.\n",
7146330Sjc25722 		    cpu->cpu_cpuid, mem_cache_device);
7156330Sjc25722 		return (CMD_EVD_BAD);
7166330Sjc25722 	}
7176330Sjc25722 	switch (pstype) {
7186330Sjc25722 		case CMD_PTR_CPU_L2TAG:
7196330Sjc25722 		case CMD_PTR_CPU_L2DATA:
7206330Sjc25722 			cache_info.cache = L2_CACHE_TAG;
7216330Sjc25722 			break;
7226330Sjc25722 		case CMD_PTR_CPU_L3TAG:
7236330Sjc25722 		case CMD_PTR_CPU_L3DATA:
7246330Sjc25722 			cache_info.cache = L3_CACHE_TAG;
7256330Sjc25722 			break;
7266330Sjc25722 	}
7276330Sjc25722 	cache_info.cpu_id = cpu->cpu_cpuid;
7286330Sjc25722 	cache_info.index = index;
7296330Sjc25722 	cache_info.datap = tag_data;
7306330Sjc25722 	cache_info.way = 0;
7316330Sjc25722 
7326330Sjc25722 	if (test_mode) {
7336330Sjc25722 
7346330Sjc25722 		if (ioctl(fd, MEM_CACHE_READ_ERROR_INJECTED_TAGS, &cache_info)
7356330Sjc25722 		    == -1) {
7366330Sjc25722 			(void) printf("cpu_id = %d ioctl"
7376330Sjc25722 			    " MEM_CACHE_READ_ERROR_INJECTED_TAGS failed"
7386330Sjc25722 			    " errno = %d\n",
7396330Sjc25722 			    cpu->cpu_cpuid, errno);
7406330Sjc25722 			(void) close(fd);
7416330Sjc25722 			return (CMD_EVD_BAD);
7426330Sjc25722 		}
7436330Sjc25722 	} else {
7446330Sjc25722 		if (ioctl(fd, MEM_CACHE_READ_TAGS, &cache_info)
7456330Sjc25722 		    == -1) {
7466330Sjc25722 			(void) printf("cpu_id = %d ioctl"
7476330Sjc25722 			    " MEM_CACHE_READ_TAGS failed"
7486330Sjc25722 			    " errno = %d\n",
7496330Sjc25722 			    cpu->cpu_cpuid, errno);
7506330Sjc25722 			(void) close(fd);
7516330Sjc25722 			return (CMD_EVD_BAD);
7526330Sjc25722 		}
7536330Sjc25722 	}
7546330Sjc25722 	(void) close(fd);
7556330Sjc25722 	return (CMD_EVD_OK);
7566330Sjc25722 }
7576330Sjc25722 
7586330Sjc25722 int
get_index_retired_ways(cmd_cpu_t * cpu,cmd_ptrsubtype_t pstype,int32_t index)759*10784Ssinanallur.balasubramanian@sun.com get_index_retired_ways(cmd_cpu_t *cpu, cmd_ptrsubtype_t pstype, int32_t index)
7606330Sjc25722 {
7616330Sjc25722 	int		i, retired_ways;
7626330Sjc25722 	uint64_t	tag_data[PN_CACHE_NWAYS];
7636330Sjc25722 
7646330Sjc25722 	if (get_tagdata(cpu, pstype, index, tag_data) != 0) {
7656330Sjc25722 		return (-1);
7666330Sjc25722 	}
7676330Sjc25722 	retired_ways = 0;
7686330Sjc25722 	for (i = 0; i < PN_CACHE_NWAYS; i++) {
7696330Sjc25722 		if ((tag_data[i] & CH_ECSTATE_MASK) ==
7706330Sjc25722 		    PN_ECSTATE_NA)
7716330Sjc25722 			retired_ways++;
7726330Sjc25722 	}
7736330Sjc25722 	return (retired_ways);
7746330Sjc25722 }
7756330Sjc25722 
776*10784Ssinanallur.balasubramanian@sun.com boolean_t
cmd_cache_way_retire(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_Lxcache_t * Lxcache)7777256Sjc25722 cmd_cache_way_retire(fmd_hdl_t *hdl, cmd_cpu_t *cpu, cmd_Lxcache_t *Lxcache)
7787256Sjc25722 {
779*10784Ssinanallur.balasubramanian@sun.com 	const char		*fltnm;
7807256Sjc25722 	cache_info_t    cache_info;
7817256Sjc25722 	int ret, fd;
7827256Sjc25722 
7837256Sjc25722 	fltnm = cmd_type_to_str(Lxcache->Lxcache_type);
7847256Sjc25722 	fd = open(mem_cache_device, O_RDWR);
7857256Sjc25722 	if (fd == -1) {
7867256Sjc25722 		fmd_hdl_debug(hdl,
7877256Sjc25722 		    "fltnm:cpu_id %d open of %s failed\n",
7887256Sjc25722 		    fltnm, cpu->cpu_cpuid, mem_cache_device);
7897256Sjc25722 		return (B_FALSE);
7907256Sjc25722 	}
7917256Sjc25722 	cache_info.cpu_id = cpu->cpu_cpuid;
7927256Sjc25722 	cache_info.way = Lxcache->Lxcache_way;
7937256Sjc25722 	cache_info.bit = Lxcache->Lxcache_bit;
7947256Sjc25722 	cache_info.index = Lxcache->Lxcache_index;
7957256Sjc25722 
7967256Sjc25722 	switch (Lxcache->Lxcache_type) {
7977256Sjc25722 		case CMD_PTR_CPU_L2TAG:
7987256Sjc25722 			cache_info.cache = L2_CACHE_TAG;
7997256Sjc25722 			break;
8007256Sjc25722 		case CMD_PTR_CPU_L2DATA:
8017256Sjc25722 			cache_info.cache = L2_CACHE_DATA;
8027256Sjc25722 			break;
8037256Sjc25722 		case CMD_PTR_CPU_L3TAG:
8047256Sjc25722 			cache_info.cache = L3_CACHE_TAG;
8057256Sjc25722 			break;
8067256Sjc25722 		case CMD_PTR_CPU_L3DATA:
8077256Sjc25722 			cache_info.cache = L3_CACHE_DATA;
8087256Sjc25722 			break;
8097256Sjc25722 	}
8107256Sjc25722 
8117256Sjc25722 	fmd_hdl_debug(hdl,
8127256Sjc25722 	    "\n%s:cpu %d: Retiring index %d, way %d bit %d\n",
8137256Sjc25722 	    fltnm, cpu->cpu_cpuid, cache_info.index, cache_info.way,
8147256Sjc25722 	    (int16_t)cache_info.bit);
8157256Sjc25722 	ret = ioctl(fd, MEM_CACHE_RETIRE, &cache_info);
8167256Sjc25722 	(void) close(fd);
8177256Sjc25722 	if (ret == -1) {
8187256Sjc25722 		fmd_hdl_debug(hdl,
8197256Sjc25722 		    "fltnm:cpu_id %d MEM_CACHE_RETIRE ioctl failed\n",
8207256Sjc25722 		    fltnm, cpu->cpu_cpuid);
8217256Sjc25722 		return (B_FALSE);
8227256Sjc25722 	}
8237256Sjc25722 
8247256Sjc25722 	return (B_TRUE);
8257256Sjc25722 }
8267256Sjc25722 
8277256Sjc25722 boolean_t
cmd_cache_way_unretire(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_Lxcache_t * Lxcache)8287256Sjc25722 cmd_cache_way_unretire(fmd_hdl_t *hdl, cmd_cpu_t *cpu, cmd_Lxcache_t *Lxcache)
8297256Sjc25722 {
830*10784Ssinanallur.balasubramanian@sun.com 	const char		*fltnm;
8317256Sjc25722 	cache_info_t    cache_info;
8327256Sjc25722 	int ret, fd;
8337256Sjc25722 
8347256Sjc25722 	fltnm = cmd_type_to_str(Lxcache->Lxcache_type);
8357256Sjc25722 	fd = open(mem_cache_device, O_RDWR);
8367256Sjc25722 	if (fd == -1) {
8377256Sjc25722 		fmd_hdl_debug(hdl,
8387256Sjc25722 		    "fltnm:cpu_id %d open of %s failed\n",
8397256Sjc25722 		    fltnm, cpu->cpu_cpuid, mem_cache_device);
8407256Sjc25722 		return (B_FALSE);
8417256Sjc25722 	}
8427256Sjc25722 	cache_info.cpu_id = cpu->cpu_cpuid;
8437256Sjc25722 	cache_info.way = Lxcache->Lxcache_way;
8447256Sjc25722 	cache_info.bit = Lxcache->Lxcache_bit;
8457256Sjc25722 	cache_info.index = Lxcache->Lxcache_index;
8467256Sjc25722 
8477256Sjc25722 	switch (Lxcache->Lxcache_type) {
8487256Sjc25722 		case CMD_PTR_CPU_L2TAG:
8497256Sjc25722 			cache_info.cache = L2_CACHE_TAG;
8507256Sjc25722 			break;
8517256Sjc25722 		case CMD_PTR_CPU_L2DATA:
8527256Sjc25722 			cache_info.cache = L2_CACHE_DATA;
8537256Sjc25722 			break;
8547256Sjc25722 		case CMD_PTR_CPU_L3TAG:
8557256Sjc25722 			cache_info.cache = L3_CACHE_TAG;
8567256Sjc25722 			break;
8577256Sjc25722 		case CMD_PTR_CPU_L3DATA:
8587256Sjc25722 			cache_info.cache = L3_CACHE_DATA;
8597256Sjc25722 			break;
8607256Sjc25722 	}
8617256Sjc25722 
8627256Sjc25722 	fmd_hdl_debug(hdl,
8637256Sjc25722 	    "\n%s:cpu %d: Unretiring index %d, way %d bit %d\n",
8647256Sjc25722 	    fltnm, cpu->cpu_cpuid, cache_info.index, cache_info.way,
8657256Sjc25722 	    (int16_t)cache_info.bit);
8667256Sjc25722 	ret = ioctl(fd, MEM_CACHE_UNRETIRE, &cache_info);
8677256Sjc25722 	(void) close(fd);
8687256Sjc25722 	if (ret == -1) {
8697256Sjc25722 		fmd_hdl_debug(hdl,
8707256Sjc25722 		    "fltnm:cpu_id %d MEM_CACHE_UNRETIRE ioctl failed\n",
8717256Sjc25722 		    fltnm, cpu->cpu_cpuid);
8727256Sjc25722 		return (B_FALSE);
8737256Sjc25722 	}
8747256Sjc25722 
8757256Sjc25722 	return (B_TRUE);
8767256Sjc25722 }
8777256Sjc25722 
8787256Sjc25722 static cmd_Lxcache_t *
cmd_Lxcache_lookup_by_type_index_way_flags(cmd_cpu_t * cpu,cmd_ptrsubtype_t type,int32_t index,int8_t way,int32_t flags)8797256Sjc25722 cmd_Lxcache_lookup_by_type_index_way_flags(cmd_cpu_t *cpu,
880*10784Ssinanallur.balasubramanian@sun.com     cmd_ptrsubtype_t type, int32_t index, int8_t way, int32_t flags)
8817256Sjc25722 {
8827256Sjc25722 	cmd_Lxcache_t *cmd_Lxcache;
8837256Sjc25722 
8847256Sjc25722 	for (cmd_Lxcache = cmd_list_next(&cpu->cpu_Lxcaches);
8857256Sjc25722 	    cmd_Lxcache != NULL;
8867256Sjc25722 	    cmd_Lxcache = cmd_list_next(cmd_Lxcache)) {
8877256Sjc25722 		if ((cmd_Lxcache->Lxcache_index == index) &&
8887256Sjc25722 		    (cmd_Lxcache->Lxcache_way == way) &&
8897256Sjc25722 		    (cmd_Lxcache->Lxcache_type == type) &&
8907256Sjc25722 		    (cmd_Lxcache->Lxcache_flags & flags))
8917256Sjc25722 			return (cmd_Lxcache);
8927256Sjc25722 	}
8937256Sjc25722 	return (NULL);
8947256Sjc25722 }
895*10784Ssinanallur.balasubramanian@sun.com 
896*10784Ssinanallur.balasubramanian@sun.com static int8_t
cmd_Lxcache_get_bit_array_of_available_ways(cmd_cpu_t * cpu,cmd_ptrsubtype_t type,int32_t index)897*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_get_bit_array_of_available_ways(cmd_cpu_t *cpu,
898*10784Ssinanallur.balasubramanian@sun.com     cmd_ptrsubtype_t type, int32_t index)
899*10784Ssinanallur.balasubramanian@sun.com {
900*10784Ssinanallur.balasubramanian@sun.com 	uint8_t bit_array_of_unavailable_ways;
901*10784Ssinanallur.balasubramanian@sun.com 	uint8_t bit_array_of_available_ways;
902*10784Ssinanallur.balasubramanian@sun.com 	cmd_ptrsubtype_t match_type;
903*10784Ssinanallur.balasubramanian@sun.com 	cmd_Lxcache_t *cmd_Lxcache;
904*10784Ssinanallur.balasubramanian@sun.com 	uint8_t bit_array_of_retired_ways;
905*10784Ssinanallur.balasubramanian@sun.com 
906*10784Ssinanallur.balasubramanian@sun.com 
907*10784Ssinanallur.balasubramanian@sun.com 	/*
908*10784Ssinanallur.balasubramanian@sun.com 	 * We scan the Lxcache structures for this CPU and collect
909*10784Ssinanallur.balasubramanian@sun.com 	 * the following 2 information.
910*10784Ssinanallur.balasubramanian@sun.com 	 * - bit_array_of_retired_ways
911*10784Ssinanallur.balasubramanian@sun.com 	 * - bit_array_of_unavailable_ways
912*10784Ssinanallur.balasubramanian@sun.com 	 * If type is Lx_TAG then unavailable_ways will not include ways that
913*10784Ssinanallur.balasubramanian@sun.com 	 * were retired due to DATA faults, because these ways can still be
914*10784Ssinanallur.balasubramanian@sun.com 	 * re-retired for TAG faults.
915*10784Ssinanallur.balasubramanian@sun.com 	 * If 3 ways have been retired then we protect the only remaining
916*10784Ssinanallur.balasubramanian@sun.com 	 * unretired way by marking it as unavailable.
917*10784Ssinanallur.balasubramanian@sun.com 	 */
918*10784Ssinanallur.balasubramanian@sun.com 	bit_array_of_unavailable_ways = 0;
919*10784Ssinanallur.balasubramanian@sun.com 	bit_array_of_retired_ways = 0;
920*10784Ssinanallur.balasubramanian@sun.com 	switch (type) {
921*10784Ssinanallur.balasubramanian@sun.com 		case CMD_PTR_CPU_L2TAG:
922*10784Ssinanallur.balasubramanian@sun.com 			match_type = CMD_PTR_CPU_L2DATA;
923*10784Ssinanallur.balasubramanian@sun.com 			break;
924*10784Ssinanallur.balasubramanian@sun.com 		case CMD_PTR_CPU_L2DATA:
925*10784Ssinanallur.balasubramanian@sun.com 			match_type = CMD_PTR_CPU_L2TAG;
926*10784Ssinanallur.balasubramanian@sun.com 			break;
927*10784Ssinanallur.balasubramanian@sun.com 		case CMD_PTR_CPU_L3TAG:
928*10784Ssinanallur.balasubramanian@sun.com 			match_type = CMD_PTR_CPU_L3DATA;
929*10784Ssinanallur.balasubramanian@sun.com 			break;
930*10784Ssinanallur.balasubramanian@sun.com 		case CMD_PTR_CPU_L3DATA:
931*10784Ssinanallur.balasubramanian@sun.com 			match_type = CMD_PTR_CPU_L3TAG;
932*10784Ssinanallur.balasubramanian@sun.com 			break;
933*10784Ssinanallur.balasubramanian@sun.com 	}
934*10784Ssinanallur.balasubramanian@sun.com 
935*10784Ssinanallur.balasubramanian@sun.com 	for (cmd_Lxcache = cmd_list_next(&cpu->cpu_Lxcaches);
936*10784Ssinanallur.balasubramanian@sun.com 	    cmd_Lxcache != NULL;
937*10784Ssinanallur.balasubramanian@sun.com 	    cmd_Lxcache = cmd_list_next(cmd_Lxcache)) {
938*10784Ssinanallur.balasubramanian@sun.com 		if ((cmd_Lxcache->Lxcache_index == index) &&
939*10784Ssinanallur.balasubramanian@sun.com 		    ((cmd_Lxcache->Lxcache_type == type) ||
940*10784Ssinanallur.balasubramanian@sun.com 		    (cmd_Lxcache->Lxcache_type == match_type)) &&
941*10784Ssinanallur.balasubramanian@sun.com 		    (cmd_Lxcache->Lxcache_flags &
942*10784Ssinanallur.balasubramanian@sun.com 		    (CMD_LxCACHE_F_RETIRED | CMD_LxCACHE_F_RERETIRED))) {
943*10784Ssinanallur.balasubramanian@sun.com 			bit_array_of_retired_ways |=
944*10784Ssinanallur.balasubramanian@sun.com 			    (1 << cmd_Lxcache->Lxcache_way);
945*10784Ssinanallur.balasubramanian@sun.com 			/*
946*10784Ssinanallur.balasubramanian@sun.com 			 * If we are calling this while handling TAG errors
947*10784Ssinanallur.balasubramanian@sun.com 			 * we can reretire the cachelines retired due to DATA
948*10784Ssinanallur.balasubramanian@sun.com 			 * errors. We will ignore the cachelnes that are
949*10784Ssinanallur.balasubramanian@sun.com 			 * retired due to DATA faults.
950*10784Ssinanallur.balasubramanian@sun.com 			 */
951*10784Ssinanallur.balasubramanian@sun.com 			if ((type == CMD_PTR_CPU_L2TAG) &&
952*10784Ssinanallur.balasubramanian@sun.com 			    (cmd_Lxcache->Lxcache_type == CMD_PTR_CPU_L2DATA))
953*10784Ssinanallur.balasubramanian@sun.com 				continue;
954*10784Ssinanallur.balasubramanian@sun.com 			if ((type == CMD_PTR_CPU_L3TAG) &&
955*10784Ssinanallur.balasubramanian@sun.com 			    (cmd_Lxcache->Lxcache_type == CMD_PTR_CPU_L3DATA))
956*10784Ssinanallur.balasubramanian@sun.com 				continue;
957*10784Ssinanallur.balasubramanian@sun.com 			bit_array_of_unavailable_ways |=
958*10784Ssinanallur.balasubramanian@sun.com 			    (1 << cmd_Lxcache->Lxcache_way);
959*10784Ssinanallur.balasubramanian@sun.com 		}
960*10784Ssinanallur.balasubramanian@sun.com 	}
961*10784Ssinanallur.balasubramanian@sun.com 	if (cmd_num_of_bits[bit_array_of_retired_ways & 0xf] == 3) {
962*10784Ssinanallur.balasubramanian@sun.com 		/*
963*10784Ssinanallur.balasubramanian@sun.com 		 * special case: 3 ways are already retired.
964*10784Ssinanallur.balasubramanian@sun.com 		 * The Lone unretired way is set as 1, rest are set as 0.
965*10784Ssinanallur.balasubramanian@sun.com 		 * We now OR this with bit_array_of_unavailable_ways
966*10784Ssinanallur.balasubramanian@sun.com 		 * so that this unretired way will not be allocated.
967*10784Ssinanallur.balasubramanian@sun.com 		 */
968*10784Ssinanallur.balasubramanian@sun.com 		bit_array_of_retired_ways ^= 0xf;
969*10784Ssinanallur.balasubramanian@sun.com 		bit_array_of_retired_ways &= 0xf;
970*10784Ssinanallur.balasubramanian@sun.com 		bit_array_of_unavailable_ways |= bit_array_of_retired_ways;
971*10784Ssinanallur.balasubramanian@sun.com 	}
972*10784Ssinanallur.balasubramanian@sun.com 	bit_array_of_available_ways =
973*10784Ssinanallur.balasubramanian@sun.com 	    ((bit_array_of_unavailable_ways ^ 0xf) & 0xf);
974*10784Ssinanallur.balasubramanian@sun.com 	return (bit_array_of_available_ways);
975*10784Ssinanallur.balasubramanian@sun.com }
976*10784Ssinanallur.balasubramanian@sun.com 
977*10784Ssinanallur.balasubramanian@sun.com 
978*10784Ssinanallur.balasubramanian@sun.com /*
979*10784Ssinanallur.balasubramanian@sun.com  * Look for a way next to the specified way that is
980*10784Ssinanallur.balasubramanian@sun.com  * not in a retired state.
981*10784Ssinanallur.balasubramanian@sun.com  * We stop when way 3 is reached.
982*10784Ssinanallur.balasubramanian@sun.com  */
983*10784Ssinanallur.balasubramanian@sun.com int8_t
cmd_Lxcache_get_next_retirable_way(cmd_cpu_t * cpu,int32_t index,cmd_ptrsubtype_t pstype,int8_t specified_way)984*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_get_next_retirable_way(cmd_cpu_t *cpu,
985*10784Ssinanallur.balasubramanian@sun.com     int32_t index, cmd_ptrsubtype_t pstype, int8_t specified_way)
986*10784Ssinanallur.balasubramanian@sun.com {
987*10784Ssinanallur.balasubramanian@sun.com 	uint8_t bit_array_of_ways;
988*10784Ssinanallur.balasubramanian@sun.com 	int8_t mask;
989*10784Ssinanallur.balasubramanian@sun.com 
990*10784Ssinanallur.balasubramanian@sun.com 	if (specified_way == 3)
991*10784Ssinanallur.balasubramanian@sun.com 		return (-1);
992*10784Ssinanallur.balasubramanian@sun.com 	bit_array_of_ways = cmd_Lxcache_get_bit_array_of_available_ways(
993*10784Ssinanallur.balasubramanian@sun.com 	    cpu,
994*10784Ssinanallur.balasubramanian@sun.com 	    pstype, index);
995*10784Ssinanallur.balasubramanian@sun.com 	if (specified_way == 2)
996*10784Ssinanallur.balasubramanian@sun.com 		mask = 0x8;
997*10784Ssinanallur.balasubramanian@sun.com 	else if (specified_way == 1)
998*10784Ssinanallur.balasubramanian@sun.com 		mask = 0xc;
999*10784Ssinanallur.balasubramanian@sun.com 	else
1000*10784Ssinanallur.balasubramanian@sun.com 		mask = 0xe;
1001*10784Ssinanallur.balasubramanian@sun.com 	return (cmd_lowest_way[bit_array_of_ways & mask]);
1002*10784Ssinanallur.balasubramanian@sun.com }
1003*10784Ssinanallur.balasubramanian@sun.com 
1004*10784Ssinanallur.balasubramanian@sun.com int8_t
cmd_Lxcache_get_lowest_retirable_way(cmd_cpu_t * cpu,int32_t index,cmd_ptrsubtype_t pstype)1005*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_get_lowest_retirable_way(cmd_cpu_t *cpu,
1006*10784Ssinanallur.balasubramanian@sun.com     int32_t index, cmd_ptrsubtype_t pstype)
1007*10784Ssinanallur.balasubramanian@sun.com {
1008*10784Ssinanallur.balasubramanian@sun.com 	uint8_t bit_array_of_ways;
1009*10784Ssinanallur.balasubramanian@sun.com 
1010*10784Ssinanallur.balasubramanian@sun.com 	bit_array_of_ways = cmd_Lxcache_get_bit_array_of_available_ways(
1011*10784Ssinanallur.balasubramanian@sun.com 	    cpu,
1012*10784Ssinanallur.balasubramanian@sun.com 	    pstype, index);
1013*10784Ssinanallur.balasubramanian@sun.com 	return (cmd_lowest_way[bit_array_of_ways]);
1014*10784Ssinanallur.balasubramanian@sun.com }
1015*10784Ssinanallur.balasubramanian@sun.com 
1016*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *
cmd_Lxcache_lookup_by_type_index_way_reason(cmd_cpu_t * cpu,cmd_ptrsubtype_t pstype,int32_t index,int8_t way,int32_t reason)1017*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_lookup_by_type_index_way_reason(cmd_cpu_t *cpu,
1018*10784Ssinanallur.balasubramanian@sun.com     cmd_ptrsubtype_t pstype, int32_t index, int8_t way, int32_t reason)
1019*10784Ssinanallur.balasubramanian@sun.com {
1020*10784Ssinanallur.balasubramanian@sun.com 	cmd_Lxcache_t *cmd_Lxcache;
1021*10784Ssinanallur.balasubramanian@sun.com 
1022*10784Ssinanallur.balasubramanian@sun.com 	for (cmd_Lxcache = cmd_list_next(&cpu->cpu_Lxcaches);
1023*10784Ssinanallur.balasubramanian@sun.com 	    cmd_Lxcache != NULL;
1024*10784Ssinanallur.balasubramanian@sun.com 	    cmd_Lxcache = cmd_list_next(cmd_Lxcache)) {
1025*10784Ssinanallur.balasubramanian@sun.com 		if ((cmd_Lxcache->Lxcache_index == (uint32_t)index) &&
1026*10784Ssinanallur.balasubramanian@sun.com 		    (cmd_Lxcache->Lxcache_way == (uint32_t)way) &&
1027*10784Ssinanallur.balasubramanian@sun.com 		    (cmd_Lxcache->Lxcache_reason & reason) &&
1028*10784Ssinanallur.balasubramanian@sun.com 		    (cmd_Lxcache->Lxcache_type == pstype)) {
1029*10784Ssinanallur.balasubramanian@sun.com 			return (cmd_Lxcache);
1030*10784Ssinanallur.balasubramanian@sun.com 		}
1031*10784Ssinanallur.balasubramanian@sun.com 	}
1032*10784Ssinanallur.balasubramanian@sun.com 	return (NULL);
1033*10784Ssinanallur.balasubramanian@sun.com }
1034*10784Ssinanallur.balasubramanian@sun.com 
1035*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_t *
cmd_Lxcache_lookup_by_type_index_bit_reason(cmd_cpu_t * cpu,cmd_ptrsubtype_t pstype,int32_t index,int16_t bit,int32_t reason)1036*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_lookup_by_type_index_bit_reason(cmd_cpu_t *cpu,
1037*10784Ssinanallur.balasubramanian@sun.com     cmd_ptrsubtype_t pstype, int32_t index, int16_t bit, int32_t reason)
1038*10784Ssinanallur.balasubramanian@sun.com {
1039*10784Ssinanallur.balasubramanian@sun.com 	cmd_Lxcache_t *cmd_Lxcache;
1040*10784Ssinanallur.balasubramanian@sun.com 
1041*10784Ssinanallur.balasubramanian@sun.com 	for (cmd_Lxcache = cmd_list_next(&cpu->cpu_Lxcaches);
1042*10784Ssinanallur.balasubramanian@sun.com 	    cmd_Lxcache != NULL;
1043*10784Ssinanallur.balasubramanian@sun.com 	    cmd_Lxcache = cmd_list_next(cmd_Lxcache)) {
1044*10784Ssinanallur.balasubramanian@sun.com 		if ((cmd_Lxcache->Lxcache_index == (uint32_t)index) &&
1045*10784Ssinanallur.balasubramanian@sun.com 		    (cmd_Lxcache->Lxcache_bit == (uint16_t)bit) &&
1046*10784Ssinanallur.balasubramanian@sun.com 		    (cmd_Lxcache->Lxcache_reason & reason) &&
1047*10784Ssinanallur.balasubramanian@sun.com 		    (cmd_Lxcache->Lxcache_type == pstype)) {
1048*10784Ssinanallur.balasubramanian@sun.com 			return (cmd_Lxcache);
1049*10784Ssinanallur.balasubramanian@sun.com 		}
1050*10784Ssinanallur.balasubramanian@sun.com 	}
1051*10784Ssinanallur.balasubramanian@sun.com 	return (NULL);
1052*10784Ssinanallur.balasubramanian@sun.com }
1053*10784Ssinanallur.balasubramanian@sun.com 
1054*10784Ssinanallur.balasubramanian@sun.com void
cmd_Lxcache_destroy_anonymous_serd_engines(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_ptrsubtype_t type,int32_t index,int16_t bit)1055*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_destroy_anonymous_serd_engines(fmd_hdl_t *hdl, cmd_cpu_t *cpu,
1056*10784Ssinanallur.balasubramanian@sun.com     cmd_ptrsubtype_t type, int32_t index, int16_t bit)
1057*10784Ssinanallur.balasubramanian@sun.com {
1058*10784Ssinanallur.balasubramanian@sun.com 	cmd_Lxcache_t *cmd_Lxcache;
1059*10784Ssinanallur.balasubramanian@sun.com 	cmd_case_t *cc;
1060*10784Ssinanallur.balasubramanian@sun.com 
1061*10784Ssinanallur.balasubramanian@sun.com 	for (cmd_Lxcache = cmd_list_next(&cpu->cpu_Lxcaches);
1062*10784Ssinanallur.balasubramanian@sun.com 	    cmd_Lxcache != NULL;
1063*10784Ssinanallur.balasubramanian@sun.com 	    cmd_Lxcache = cmd_list_next(cmd_Lxcache)) {
1064*10784Ssinanallur.balasubramanian@sun.com 		if ((cmd_Lxcache->Lxcache_type == type) &&
1065*10784Ssinanallur.balasubramanian@sun.com 		    (cmd_Lxcache->Lxcache_index == (uint32_t)index) &&
1066*10784Ssinanallur.balasubramanian@sun.com 		    (cmd_Lxcache->Lxcache_bit == (uint16_t)bit) &&
1067*10784Ssinanallur.balasubramanian@sun.com 		    (cmd_Lxcache->Lxcache_way == (uint32_t)CMD_ANON_WAY)) {
1068*10784Ssinanallur.balasubramanian@sun.com 			cc = &cmd_Lxcache->Lxcache_case;
1069*10784Ssinanallur.balasubramanian@sun.com 			if (cc == NULL)
1070*10784Ssinanallur.balasubramanian@sun.com 				continue;
1071*10784Ssinanallur.balasubramanian@sun.com 			if (cc->cc_serdnm != NULL) {
1072*10784Ssinanallur.balasubramanian@sun.com 				if (fmd_serd_exists(hdl, cc->cc_serdnm)) {
1073*10784Ssinanallur.balasubramanian@sun.com 					fmd_hdl_debug(hdl,
1074*10784Ssinanallur.balasubramanian@sun.com 					    "\n%s:cpu_id %d destroying SERD"
1075*10784Ssinanallur.balasubramanian@sun.com 					    " engine %s\n",
1076*10784Ssinanallur.balasubramanian@sun.com 					    cmd_type_to_str(type),
1077*10784Ssinanallur.balasubramanian@sun.com 					    cpu->cpu_cpuid, cc->cc_serdnm);
1078*10784Ssinanallur.balasubramanian@sun.com 					fmd_serd_destroy(hdl, cc->cc_serdnm);
1079*10784Ssinanallur.balasubramanian@sun.com 				}
1080*10784Ssinanallur.balasubramanian@sun.com 				fmd_hdl_strfree(hdl, cc->cc_serdnm);
1081*10784Ssinanallur.balasubramanian@sun.com 				cc->cc_serdnm = NULL;
1082*10784Ssinanallur.balasubramanian@sun.com 			}
1083*10784Ssinanallur.balasubramanian@sun.com 		}
1084*10784Ssinanallur.balasubramanian@sun.com 	}
1085*10784Ssinanallur.balasubramanian@sun.com }
1086*10784Ssinanallur.balasubramanian@sun.com 
1087*10784Ssinanallur.balasubramanian@sun.com ssize_t
cmd_fmri_nvl2str(fmd_hdl_t * hdl,nvlist_t * nvl,char * buf,size_t buflen)1088*10784Ssinanallur.balasubramanian@sun.com cmd_fmri_nvl2str(fmd_hdl_t *hdl, nvlist_t *nvl, char *buf, size_t buflen)
1089*10784Ssinanallur.balasubramanian@sun.com {
1090*10784Ssinanallur.balasubramanian@sun.com 	uint8_t type;
1091*10784Ssinanallur.balasubramanian@sun.com 	uint32_t cpuid, way;
1092*10784Ssinanallur.balasubramanian@sun.com 	uint32_t	index;
1093*10784Ssinanallur.balasubramanian@sun.com 	uint16_t	bit;
1094*10784Ssinanallur.balasubramanian@sun.com 	char *serstr = NULL;
1095*10784Ssinanallur.balasubramanian@sun.com 	char	missing_list[128];
1096*10784Ssinanallur.balasubramanian@sun.com 
1097*10784Ssinanallur.balasubramanian@sun.com 	missing_list[0] = 0;
1098*10784Ssinanallur.balasubramanian@sun.com 	if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) != 0)
1099*10784Ssinanallur.balasubramanian@sun.com 		(void) strcat(missing_list, FM_FMRI_CPU_ID);
1100*10784Ssinanallur.balasubramanian@sun.com 	if (nvlist_lookup_string(nvl, FM_FMRI_CPU_SERIAL_ID, &serstr) != 0)
1101*10784Ssinanallur.balasubramanian@sun.com 		(void) strcat(missing_list, FM_FMRI_CPU_SERIAL_ID);
1102*10784Ssinanallur.balasubramanian@sun.com 	if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_CACHE_INDEX, &index) != 0)
1103*10784Ssinanallur.balasubramanian@sun.com 		(void) strcat(missing_list, FM_FMRI_CPU_CACHE_INDEX);
1104*10784Ssinanallur.balasubramanian@sun.com 	if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_CACHE_WAY, &way) != 0)
1105*10784Ssinanallur.balasubramanian@sun.com 		(void) strcat(missing_list, FM_FMRI_CPU_CACHE_WAY);
1106*10784Ssinanallur.balasubramanian@sun.com 	if (nvlist_lookup_uint16(nvl, FM_FMRI_CPU_CACHE_BIT, &bit) != 0)
1107*10784Ssinanallur.balasubramanian@sun.com 		(void) strcat(missing_list, FM_FMRI_CPU_CACHE_BIT);
1108*10784Ssinanallur.balasubramanian@sun.com 	if (nvlist_lookup_uint8(nvl, FM_FMRI_CPU_CACHE_TYPE, &type) != 0)
1109*10784Ssinanallur.balasubramanian@sun.com 		(void) strcat(missing_list, FM_FMRI_CPU_CACHE_TYPE);
1110*10784Ssinanallur.balasubramanian@sun.com 
1111*10784Ssinanallur.balasubramanian@sun.com 	if (strlen(missing_list) != 0) {
1112*10784Ssinanallur.balasubramanian@sun.com 		fmd_hdl_debug(hdl,
1113*10784Ssinanallur.balasubramanian@sun.com 		    "\ncmd_fmri_nvl2str: missing %s in fmri\n",
1114*10784Ssinanallur.balasubramanian@sun.com 		    missing_list);
1115*10784Ssinanallur.balasubramanian@sun.com 		return (-1);
1116*10784Ssinanallur.balasubramanian@sun.com 	}
1117*10784Ssinanallur.balasubramanian@sun.com 
1118*10784Ssinanallur.balasubramanian@sun.com 	return (snprintf(buf, buflen,
1119*10784Ssinanallur.balasubramanian@sun.com 	    "cpu:///%s=%u/%s=%s/%s=%u/%s=%u/%s=%d/%s=%d",
1120*10784Ssinanallur.balasubramanian@sun.com 	    FM_FMRI_CPU_ID, cpuid,
1121*10784Ssinanallur.balasubramanian@sun.com 	    FM_FMRI_CPU_SERIAL_ID, serstr,
1122*10784Ssinanallur.balasubramanian@sun.com 	    FM_FMRI_CPU_CACHE_INDEX, index,
1123*10784Ssinanallur.balasubramanian@sun.com 	    FM_FMRI_CPU_CACHE_WAY, way,
1124*10784Ssinanallur.balasubramanian@sun.com 	    FM_FMRI_CPU_CACHE_BIT, bit,
1125*10784Ssinanallur.balasubramanian@sun.com 	    FM_FMRI_CPU_CACHE_TYPE, type));
1126*10784Ssinanallur.balasubramanian@sun.com }
1127*10784Ssinanallur.balasubramanian@sun.com 
11287256Sjc25722 boolean_t
cmd_create_case_for_Lxcache(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_Lxcache_t * cmd_Lxcache)1129*10784Ssinanallur.balasubramanian@sun.com cmd_create_case_for_Lxcache(fmd_hdl_t *hdl, cmd_cpu_t *cpu,
1130*10784Ssinanallur.balasubramanian@sun.com     cmd_Lxcache_t *cmd_Lxcache)
1131*10784Ssinanallur.balasubramanian@sun.com {
1132*10784Ssinanallur.balasubramanian@sun.com 	const char *fltnm;
1133*10784Ssinanallur.balasubramanian@sun.com 	const char *uuid;
1134*10784Ssinanallur.balasubramanian@sun.com 
1135*10784Ssinanallur.balasubramanian@sun.com 	if (cmd_Lxcache->Lxcache_case.cc_cp != NULL)
1136*10784Ssinanallur.balasubramanian@sun.com 		return (B_TRUE);
1137*10784Ssinanallur.balasubramanian@sun.com 	cmd_Lxcache->Lxcache_case.cc_cp = cmd_case_create(hdl,
1138*10784Ssinanallur.balasubramanian@sun.com 	    &cmd_Lxcache->Lxcache_header, CMD_PTR_LxCACHE_CASE,
1139*10784Ssinanallur.balasubramanian@sun.com 	    &uuid);
1140*10784Ssinanallur.balasubramanian@sun.com 	fltnm = cmd_type_to_str(cmd_Lxcache->Lxcache_type);
1141*10784Ssinanallur.balasubramanian@sun.com 	if (cmd_Lxcache->Lxcache_case.cc_cp == NULL) {
1142*10784Ssinanallur.balasubramanian@sun.com 		fmd_hdl_debug(hdl,
1143*10784Ssinanallur.balasubramanian@sun.com 		    "\n%s:cpu_id %d:Failed to create a case for"
1144*10784Ssinanallur.balasubramanian@sun.com 		    " index %d way %d bit %d\n",
1145*10784Ssinanallur.balasubramanian@sun.com 		    fltnm, cpu->cpu_cpuid,
1146*10784Ssinanallur.balasubramanian@sun.com 		    cmd_Lxcache->Lxcache_index,
1147*10784Ssinanallur.balasubramanian@sun.com 		    cmd_Lxcache->Lxcache_way, cmd_Lxcache->Lxcache_bit);
1148*10784Ssinanallur.balasubramanian@sun.com 		return (B_FALSE);
1149*10784Ssinanallur.balasubramanian@sun.com 	}
1150*10784Ssinanallur.balasubramanian@sun.com 	fmd_hdl_debug(hdl,
1151*10784Ssinanallur.balasubramanian@sun.com 	    "\n%s:cpu_id %d: New case %s created.\n",
1152*10784Ssinanallur.balasubramanian@sun.com 	    fltnm, cpu->cpu_cpuid, uuid);
1153*10784Ssinanallur.balasubramanian@sun.com 	if (cmd_Lxcache->Lxcache_ep)
1154*10784Ssinanallur.balasubramanian@sun.com 		fmd_case_add_ereport(hdl, cmd_Lxcache->Lxcache_case.cc_cp,
1155*10784Ssinanallur.balasubramanian@sun.com 		    cmd_Lxcache->Lxcache_ep);
1156*10784Ssinanallur.balasubramanian@sun.com 	return (B_TRUE);
1157*10784Ssinanallur.balasubramanian@sun.com }
1158*10784Ssinanallur.balasubramanian@sun.com 
1159*10784Ssinanallur.balasubramanian@sun.com static int
cmd_repair_fmri(fmd_hdl_t * hdl,char * buf)1160*10784Ssinanallur.balasubramanian@sun.com cmd_repair_fmri(fmd_hdl_t *hdl, char *buf)
1161*10784Ssinanallur.balasubramanian@sun.com {
1162*10784Ssinanallur.balasubramanian@sun.com 	int err;
1163*10784Ssinanallur.balasubramanian@sun.com 
1164*10784Ssinanallur.balasubramanian@sun.com 	err = fmd_repair_asru(hdl, buf);
1165*10784Ssinanallur.balasubramanian@sun.com 	if (err) {
1166*10784Ssinanallur.balasubramanian@sun.com 		fmd_hdl_debug(hdl,
1167*10784Ssinanallur.balasubramanian@sun.com 		    "Failed to repair %s err = %d\n", buf, err);
1168*10784Ssinanallur.balasubramanian@sun.com 	}
1169*10784Ssinanallur.balasubramanian@sun.com 	return (err);
1170*10784Ssinanallur.balasubramanian@sun.com }
1171*10784Ssinanallur.balasubramanian@sun.com 
1172*10784Ssinanallur.balasubramanian@sun.com boolean_t
cmd_Lxcache_unretire(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_Lxcache_t * unretire_this_Lxcache,const char * fltnm)1173*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_unretire(fmd_hdl_t *hdl, cmd_cpu_t *cpu,
1174*10784Ssinanallur.balasubramanian@sun.com     cmd_Lxcache_t *unretire_this_Lxcache, const char *fltnm)
11757256Sjc25722 {
11767256Sjc25722 	cmd_ptrsubtype_t data_type;
1177*10784Ssinanallur.balasubramanian@sun.com 	cmd_Lxcache_t *previously_retired_Lxcache;
1178*10784Ssinanallur.balasubramanian@sun.com 	int	found_reretired_cacheline = 0;
1179*10784Ssinanallur.balasubramanian@sun.com 	int	certainty;
11807256Sjc25722 
11817256Sjc25722 	/*
11827256Sjc25722 	 * If we are unretiring a cacheline retired due to suspected TAG
11837256Sjc25722 	 * fault, then we must first check if we are using a cacheline
11847256Sjc25722 	 * that was retired earlier for DATA fault.
11857256Sjc25722 	 * If so we will not unretire the cacheline.
11867256Sjc25722 	 * We will change the flags to reflect the current condition.
11877256Sjc25722 	 * We will return success, though.
11887256Sjc25722 	 */
1189*10784Ssinanallur.balasubramanian@sun.com 	if (IS_TAG(unretire_this_Lxcache->Lxcache_type)) {
1190*10784Ssinanallur.balasubramanian@sun.com 		if (unretire_this_Lxcache->Lxcache_type == CMD_PTR_CPU_L2TAG)
11917256Sjc25722 			data_type = CMD_PTR_CPU_L2DATA;
1192*10784Ssinanallur.balasubramanian@sun.com 		if (unretire_this_Lxcache->Lxcache_type == CMD_PTR_CPU_L3TAG)
11937256Sjc25722 			data_type = CMD_PTR_CPU_L3DATA;
11947256Sjc25722 		fmd_hdl_debug(hdl,
11957256Sjc25722 		    "\n%s:cpuid %d checking if there is a %s"
11967256Sjc25722 		    " cacheline re-retired at this index %d and way %d\n",
11977256Sjc25722 		    fltnm, cpu->cpu_cpuid, cmd_type_to_str(data_type),
1198*10784Ssinanallur.balasubramanian@sun.com 		    unretire_this_Lxcache->Lxcache_index,
1199*10784Ssinanallur.balasubramanian@sun.com 		    unretire_this_Lxcache->Lxcache_way);
1200*10784Ssinanallur.balasubramanian@sun.com 		previously_retired_Lxcache =
1201*10784Ssinanallur.balasubramanian@sun.com 		    cmd_Lxcache_lookup_by_type_index_way_flags(
1202*10784Ssinanallur.balasubramanian@sun.com 		    cpu, data_type, unretire_this_Lxcache->Lxcache_index,
1203*10784Ssinanallur.balasubramanian@sun.com 		    unretire_this_Lxcache->Lxcache_way,
1204*10784Ssinanallur.balasubramanian@sun.com 		    CMD_LxCACHE_F_RERETIRED);
1205*10784Ssinanallur.balasubramanian@sun.com 		if (previously_retired_Lxcache) {
1206*10784Ssinanallur.balasubramanian@sun.com 			fmd_hdl_debug(hdl,
1207*10784Ssinanallur.balasubramanian@sun.com 			    "\n%s:cpuid %d Found a %s cacheline re-retired at"
1208*10784Ssinanallur.balasubramanian@sun.com 			    " this index %d and way %d. Will mark this"
1209*10784Ssinanallur.balasubramanian@sun.com 			    " RETIRED\n",
1210*10784Ssinanallur.balasubramanian@sun.com 			    fltnm, cpu->cpu_cpuid, cmd_type_to_str(data_type),
1211*10784Ssinanallur.balasubramanian@sun.com 			    unretire_this_Lxcache->Lxcache_index,
1212*10784Ssinanallur.balasubramanian@sun.com 			    unretire_this_Lxcache->Lxcache_way);
1213*10784Ssinanallur.balasubramanian@sun.com 			/*
1214*10784Ssinanallur.balasubramanian@sun.com 			 * We call the cmd_Lxcache_fault to inform fmd
1215*10784Ssinanallur.balasubramanian@sun.com 			 * about the suspect fmri. The cacheline is already
1216*10784Ssinanallur.balasubramanian@sun.com 			 * retired but the existing suspect fmri is for TAG
1217*10784Ssinanallur.balasubramanian@sun.com 			 * fault which will be removed in this routine.
1218*10784Ssinanallur.balasubramanian@sun.com 			 */
1219*10784Ssinanallur.balasubramanian@sun.com 			if (previously_retired_Lxcache->Lxcache_reason
1220*10784Ssinanallur.balasubramanian@sun.com 			    == CMD_LXCONVICTED)
1221*10784Ssinanallur.balasubramanian@sun.com 				certainty = HUNDRED_PERCENT;
1222*10784Ssinanallur.balasubramanian@sun.com 			else
1223*10784Ssinanallur.balasubramanian@sun.com 				certainty = SUSPECT_PERCENT;
1224*10784Ssinanallur.balasubramanian@sun.com 			cmd_Lxcache_fault(hdl, cpu, previously_retired_Lxcache,
1225*10784Ssinanallur.balasubramanian@sun.com 			    fltnm, cpu->cpu_fru_nvl, certainty);
1226*10784Ssinanallur.balasubramanian@sun.com 			previously_retired_Lxcache->Lxcache_flags =
1227*10784Ssinanallur.balasubramanian@sun.com 			    CMD_LxCACHE_F_RETIRED;
1228*10784Ssinanallur.balasubramanian@sun.com 			/*
1229*10784Ssinanallur.balasubramanian@sun.com 			 * Update persistent storage
1230*10784Ssinanallur.balasubramanian@sun.com 			 */
1231*10784Ssinanallur.balasubramanian@sun.com 			cmd_Lxcache_write(hdl, previously_retired_Lxcache);
1232*10784Ssinanallur.balasubramanian@sun.com 			found_reretired_cacheline = 1;
1233*10784Ssinanallur.balasubramanian@sun.com 		}
1234*10784Ssinanallur.balasubramanian@sun.com 	} else {
1235*10784Ssinanallur.balasubramanian@sun.com 		/*
1236*10784Ssinanallur.balasubramanian@sun.com 		 * We have been called to unretire a cacheline retired
1237*10784Ssinanallur.balasubramanian@sun.com 		 * earlier due to DATA errors.
1238*10784Ssinanallur.balasubramanian@sun.com 		 * If this cacheline is marked RERETIRED then it means that
1239*10784Ssinanallur.balasubramanian@sun.com 		 * the cacheline has been retired due to TAG errors and
1240*10784Ssinanallur.balasubramanian@sun.com 		 * we should not be unretiring the cacheline.
1241*10784Ssinanallur.balasubramanian@sun.com 		 */
1242*10784Ssinanallur.balasubramanian@sun.com 		if (unretire_this_Lxcache->Lxcache_flags &
1243*10784Ssinanallur.balasubramanian@sun.com 		    CMD_LxCACHE_F_RERETIRED) {
1244*10784Ssinanallur.balasubramanian@sun.com 			fmd_hdl_debug(hdl,
1245*10784Ssinanallur.balasubramanian@sun.com 			    "\n%s:cpuid %d The cacheline at index %d and"
1246*10784Ssinanallur.balasubramanian@sun.com 			    " way %d  which we are attempting to unretire"
1247*10784Ssinanallur.balasubramanian@sun.com 			    " is in RERETIRED state. Therefore we will not"
1248*10784Ssinanallur.balasubramanian@sun.com 			    " unretire it but will mark it as RETIRED.\n",
1249*10784Ssinanallur.balasubramanian@sun.com 			    fltnm, cpu->cpu_cpuid,
1250*10784Ssinanallur.balasubramanian@sun.com 			    unretire_this_Lxcache->Lxcache_index,
1251*10784Ssinanallur.balasubramanian@sun.com 			    unretire_this_Lxcache->Lxcache_way);
1252*10784Ssinanallur.balasubramanian@sun.com 			found_reretired_cacheline = 1;
12537256Sjc25722 		}
12547256Sjc25722 	}
12557256Sjc25722 	/*
1256*10784Ssinanallur.balasubramanian@sun.com 	 * if we did not find a RERETIRED cacheline above
1257*10784Ssinanallur.balasubramanian@sun.com 	 * unretire the cacheline.
1258*10784Ssinanallur.balasubramanian@sun.com 	 */
1259*10784Ssinanallur.balasubramanian@sun.com 	if (!found_reretired_cacheline) {
1260*10784Ssinanallur.balasubramanian@sun.com 		if (cmd_cache_way_unretire(hdl, cpu, unretire_this_Lxcache)
1261*10784Ssinanallur.balasubramanian@sun.com 		    == B_FALSE)
1262*10784Ssinanallur.balasubramanian@sun.com 			return (B_FALSE);
1263*10784Ssinanallur.balasubramanian@sun.com 	}
1264*10784Ssinanallur.balasubramanian@sun.com 	unretire_this_Lxcache->Lxcache_flags = CMD_LxCACHE_F_UNRETIRED;
1265*10784Ssinanallur.balasubramanian@sun.com 	/*
1266*10784Ssinanallur.balasubramanian@sun.com 	 * We have exonerated the cacheline. We need to inform the fmd
1267*10784Ssinanallur.balasubramanian@sun.com 	 * that we have repaired the suspect fmri that we retired earlier.
12687256Sjc25722 	 * The cpumem agent will not unretire cacheline in response to
12697256Sjc25722 	 * the list.repair events it receives.
12707256Sjc25722 	 */
1271*10784Ssinanallur.balasubramanian@sun.com 	if (unretire_this_Lxcache->Lxcache_retired_fmri[0] != 0) {
12727256Sjc25722 		fmd_hdl_debug(hdl,
12737256Sjc25722 		    "\n%s:cpuid %d Repairing the retired fmri %s",
12747256Sjc25722 		    fltnm, cpu->cpu_cpuid,
1275*10784Ssinanallur.balasubramanian@sun.com 		    unretire_this_Lxcache->Lxcache_retired_fmri);
1276*10784Ssinanallur.balasubramanian@sun.com 		if (cmd_repair_fmri(hdl,
1277*10784Ssinanallur.balasubramanian@sun.com 		    unretire_this_Lxcache->Lxcache_retired_fmri) != 0) {
1278*10784Ssinanallur.balasubramanian@sun.com 			fmd_hdl_debug(hdl,
1279*10784Ssinanallur.balasubramanian@sun.com 			    "\n%s:cpuid %d Failed to repair retired fmri.",
1280*10784Ssinanallur.balasubramanian@sun.com 			    fltnm, cpu->cpu_cpuid);
12817256Sjc25722 			/*
12827256Sjc25722 			 * We need to retire the cacheline that we just
12837256Sjc25722 			 * unretired.
12847256Sjc25722 			 */
1285*10784Ssinanallur.balasubramanian@sun.com 			if (cmd_cache_way_retire(hdl, cpu,
1286*10784Ssinanallur.balasubramanian@sun.com 			    unretire_this_Lxcache) == B_FALSE) {
12877256Sjc25722 				/*
12887256Sjc25722 				 * A hopeless situation.
12897256Sjc25722 				 * cannot maintain consistency of cacheline
12907256Sjc25722 				 * sate between fmd and DE.
12917256Sjc25722 				 * Aborting the DE.
12927256Sjc25722 				 */
12937256Sjc25722 				fmd_hdl_abort(hdl,
12947256Sjc25722 				    "\n%s:cpuid %d We are unable to repair"
12957256Sjc25722 				    " the fmri we just unretired and are"
12967256Sjc25722 				    " unable to restore the DE and fmd to"
12977256Sjc25722 				    " a sane state.\n",
12987256Sjc25722 				    fltnm, cpu->cpu_cpuid);
12997256Sjc25722 			}
13007256Sjc25722 			return (B_FALSE);
13017256Sjc25722 		} else {
1302*10784Ssinanallur.balasubramanian@sun.com 			unretire_this_Lxcache->Lxcache_retired_fmri[0] = 0;
13037256Sjc25722 		}
13047256Sjc25722 	}
13057256Sjc25722 	return (B_TRUE);
13067256Sjc25722 }
1307*10784Ssinanallur.balasubramanian@sun.com 
1308*10784Ssinanallur.balasubramanian@sun.com boolean_t
cmd_Lxcache_retire(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_Lxcache_t * retire_this_Lxcache,const char * fltnm,uint_t cert)1309*10784Ssinanallur.balasubramanian@sun.com cmd_Lxcache_retire(fmd_hdl_t *hdl, cmd_cpu_t *cpu,
1310*10784Ssinanallur.balasubramanian@sun.com     cmd_Lxcache_t *retire_this_Lxcache, const char *fltnm, uint_t cert)
1311*10784Ssinanallur.balasubramanian@sun.com {
1312*10784Ssinanallur.balasubramanian@sun.com 	cmd_Lxcache_t *previously_retired_Lxcache;
1313*10784Ssinanallur.balasubramanian@sun.com 	cmd_ptrsubtype_t data_type;
1314*10784Ssinanallur.balasubramanian@sun.com 	const char	*uuid;
1315*10784Ssinanallur.balasubramanian@sun.com 	char	suspect_list[128];
1316*10784Ssinanallur.balasubramanian@sun.com 
1317*10784Ssinanallur.balasubramanian@sun.com 	fmd_hdl_debug(hdl,
1318*10784Ssinanallur.balasubramanian@sun.com 	    "\n%s:cpu_id %d: cmd_Lxcache_retire called for index %d"
1319*10784Ssinanallur.balasubramanian@sun.com 	    " way %d bit %d\n",
1320*10784Ssinanallur.balasubramanian@sun.com 	    fltnm, cpu->cpu_cpuid, retire_this_Lxcache->Lxcache_index,
1321*10784Ssinanallur.balasubramanian@sun.com 	    retire_this_Lxcache->Lxcache_way, retire_this_Lxcache->Lxcache_bit);
1322*10784Ssinanallur.balasubramanian@sun.com 	if (fmd_case_solved(hdl, retire_this_Lxcache->Lxcache_case.cc_cp)) {
1323*10784Ssinanallur.balasubramanian@sun.com 		/*
1324*10784Ssinanallur.balasubramanian@sun.com 		 * Case solved implies that the cache line is already
1325*10784Ssinanallur.balasubramanian@sun.com 		 * retired as SUSPECT_0_TAG and we are here to retire this
1326*10784Ssinanallur.balasubramanian@sun.com 		 * as SUSPECT_1_TAG.
1327*10784Ssinanallur.balasubramanian@sun.com 		 * We will first repair the retired cacheline
1328*10784Ssinanallur.balasubramanian@sun.com 		 * so that it does not get retired during replay for
1329*10784Ssinanallur.balasubramanian@sun.com 		 *  wrong reason.
1330*10784Ssinanallur.balasubramanian@sun.com 		 * If we are able to repair the retired cacheline we close the
1331*10784Ssinanallur.balasubramanian@sun.com 		 * case and open a new case for it.
1332*10784Ssinanallur.balasubramanian@sun.com 		 */
1333*10784Ssinanallur.balasubramanian@sun.com 		if (retire_this_Lxcache->Lxcache_reason !=
1334*10784Ssinanallur.balasubramanian@sun.com 		    CMD_LXSUSPECT_0_TAG) {
1335*10784Ssinanallur.balasubramanian@sun.com 			fmd_hdl_debug(hdl,
1336*10784Ssinanallur.balasubramanian@sun.com 			    "\n%s:cpu_id %d: Unexpected condition encountered."
1337*10784Ssinanallur.balasubramanian@sun.com 			    " Expected the reason for retirement as"
1338*10784Ssinanallur.balasubramanian@sun.com 			    " SUSPECT_0_TAG however found the reason"
1339*10784Ssinanallur.balasubramanian@sun.com 			    " to be %s\n",
1340*10784Ssinanallur.balasubramanian@sun.com 			    fltnm, cpu->cpu_cpuid,
1341*10784Ssinanallur.balasubramanian@sun.com 			    cmd_reason_to_str(
1342*10784Ssinanallur.balasubramanian@sun.com 			    retire_this_Lxcache->Lxcache_reason));
1343*10784Ssinanallur.balasubramanian@sun.com 			return (B_FALSE);
1344*10784Ssinanallur.balasubramanian@sun.com 		}
1345*10784Ssinanallur.balasubramanian@sun.com 		fmd_hdl_debug(hdl,
1346*10784Ssinanallur.balasubramanian@sun.com 		    "\n%s:cpu_id %d: We are re-retiring SUSPECT_0_TAG as"
1347*10784Ssinanallur.balasubramanian@sun.com 		    " SUSPECT_1_TAG index %d way %d bit %d\n",
1348*10784Ssinanallur.balasubramanian@sun.com 		    fltnm, cpu->cpu_cpuid,
1349*10784Ssinanallur.balasubramanian@sun.com 		    retire_this_Lxcache->Lxcache_index,
1350*10784Ssinanallur.balasubramanian@sun.com 		    retire_this_Lxcache->Lxcache_way,
1351*10784Ssinanallur.balasubramanian@sun.com 		    retire_this_Lxcache->Lxcache_bit);
1352*10784Ssinanallur.balasubramanian@sun.com 		fmd_hdl_debug(hdl,
1353*10784Ssinanallur.balasubramanian@sun.com 		    "\n%s:cpu_id %d: The existing case for this Lxcache has"
1354*10784Ssinanallur.balasubramanian@sun.com 		    " has been already solved. We will first repair the suspect"
1355*10784Ssinanallur.balasubramanian@sun.com 		    " cacheline and if we are successful then close this case,"
1356*10784Ssinanallur.balasubramanian@sun.com 		    " and open a new case.\n",
1357*10784Ssinanallur.balasubramanian@sun.com 		    fltnm, cpu->cpu_cpuid);
1358*10784Ssinanallur.balasubramanian@sun.com 		/*
1359*10784Ssinanallur.balasubramanian@sun.com 		 * repair the retired cacheline.
1360*10784Ssinanallur.balasubramanian@sun.com 		 */
1361*10784Ssinanallur.balasubramanian@sun.com 		if (retire_this_Lxcache->Lxcache_retired_fmri[0] != 0) {
1362*10784Ssinanallur.balasubramanian@sun.com 			fmd_hdl_debug(hdl,
1363*10784Ssinanallur.balasubramanian@sun.com 			    "\n%s:cpuid %d Repairing the retired suspect"
1364*10784Ssinanallur.balasubramanian@sun.com 			    " cacheline %s\n",
1365*10784Ssinanallur.balasubramanian@sun.com 			    fltnm, cpu->cpu_cpuid,
1366*10784Ssinanallur.balasubramanian@sun.com 			    retire_this_Lxcache->Lxcache_retired_fmri);
1367*10784Ssinanallur.balasubramanian@sun.com 			if (cmd_repair_fmri(hdl,
1368*10784Ssinanallur.balasubramanian@sun.com 			    retire_this_Lxcache->Lxcache_retired_fmri) != 0) {
1369*10784Ssinanallur.balasubramanian@sun.com 				fmd_hdl_debug(hdl,
1370*10784Ssinanallur.balasubramanian@sun.com 				    "\n%s:cpuid %d Failed to repair the"
1371*10784Ssinanallur.balasubramanian@sun.com 				    " retired fmri.",
1372*10784Ssinanallur.balasubramanian@sun.com 				    fltnm, cpu->cpu_cpuid);
1373*10784Ssinanallur.balasubramanian@sun.com 				return (B_FALSE);
1374*10784Ssinanallur.balasubramanian@sun.com 			} else {
1375*10784Ssinanallur.balasubramanian@sun.com 				retire_this_Lxcache->Lxcache_retired_fmri[0] =
1376*10784Ssinanallur.balasubramanian@sun.com 				    0;
1377*10784Ssinanallur.balasubramanian@sun.com 			}
1378*10784Ssinanallur.balasubramanian@sun.com 		}
1379*10784Ssinanallur.balasubramanian@sun.com 		uuid = fmd_case_uuid(hdl,
1380*10784Ssinanallur.balasubramanian@sun.com 		    retire_this_Lxcache->Lxcache_case.cc_cp);
1381*10784Ssinanallur.balasubramanian@sun.com 		fmd_hdl_debug(hdl,
1382*10784Ssinanallur.balasubramanian@sun.com 		    "\n%s:cpuid %d: Closing the case %s\n",
1383*10784Ssinanallur.balasubramanian@sun.com 		    fltnm, cpu->cpu_cpuid, uuid);
1384*10784Ssinanallur.balasubramanian@sun.com 		cmd_case_fini(hdl, retire_this_Lxcache->Lxcache_case.cc_cp,
1385*10784Ssinanallur.balasubramanian@sun.com 		    FMD_B_TRUE);
1386*10784Ssinanallur.balasubramanian@sun.com 		retire_this_Lxcache->Lxcache_case.cc_cp = NULL;
1387*10784Ssinanallur.balasubramanian@sun.com 		if (cmd_create_case_for_Lxcache(hdl, cpu, retire_this_Lxcache)
1388*10784Ssinanallur.balasubramanian@sun.com 		    == B_FALSE)
1389*10784Ssinanallur.balasubramanian@sun.com 			return (B_FALSE);
1390*10784Ssinanallur.balasubramanian@sun.com 	} else {
1391*10784Ssinanallur.balasubramanian@sun.com 		/*
1392*10784Ssinanallur.balasubramanian@sun.com 		 * Not a SUSPECT_0_TAG.
1393*10784Ssinanallur.balasubramanian@sun.com 		 * We should be entering this path if the cacheline is
1394*10784Ssinanallur.balasubramanian@sun.com 		 * transitioning  from ACTIVE/UNRETIRED to RETIRED state.
1395*10784Ssinanallur.balasubramanian@sun.com 		 * If the cacheline state is not as expected we print debug
1396*10784Ssinanallur.balasubramanian@sun.com 		 * message and return failure.
1397*10784Ssinanallur.balasubramanian@sun.com 		 */
1398*10784Ssinanallur.balasubramanian@sun.com 		if ((retire_this_Lxcache->Lxcache_flags !=
1399*10784Ssinanallur.balasubramanian@sun.com 		    CMD_LxCACHE_F_ACTIVE) &&
1400*10784Ssinanallur.balasubramanian@sun.com 		    (retire_this_Lxcache->Lxcache_flags
1401*10784Ssinanallur.balasubramanian@sun.com 		    != CMD_LxCACHE_F_UNRETIRED)) {
1402*10784Ssinanallur.balasubramanian@sun.com 			/*
1403*10784Ssinanallur.balasubramanian@sun.com 			 * Unexpected condition.
1404*10784Ssinanallur.balasubramanian@sun.com 			 */
1405*10784Ssinanallur.balasubramanian@sun.com 			fmd_hdl_debug(hdl,
1406*10784Ssinanallur.balasubramanian@sun.com 			    "\n%s:cpu_id %d:Unexpected state %s for the"
1407*10784Ssinanallur.balasubramanian@sun.com 			    " cacheline at index %d way %d encountered.\n",
1408*10784Ssinanallur.balasubramanian@sun.com 			    fltnm, cpu->cpu_cpuid,
1409*10784Ssinanallur.balasubramanian@sun.com 			    cmd_flags_to_str(
1410*10784Ssinanallur.balasubramanian@sun.com 			    retire_this_Lxcache->Lxcache_flags),
1411*10784Ssinanallur.balasubramanian@sun.com 			    retire_this_Lxcache->Lxcache_index,
1412*10784Ssinanallur.balasubramanian@sun.com 			    retire_this_Lxcache->Lxcache_way);
1413*10784Ssinanallur.balasubramanian@sun.com 			return (B_FALSE);
1414*10784Ssinanallur.balasubramanian@sun.com 		}
1415*10784Ssinanallur.balasubramanian@sun.com 	}
1416*10784Ssinanallur.balasubramanian@sun.com 	suspect_list[0] = 0;
1417*10784Ssinanallur.balasubramanian@sun.com 	(void) cmd_fmri_nvl2str(hdl, retire_this_Lxcache->Lxcache_asru.fmri_nvl,
1418*10784Ssinanallur.balasubramanian@sun.com 	    suspect_list, sizeof (suspect_list));
1419*10784Ssinanallur.balasubramanian@sun.com 	fmd_hdl_debug(hdl,
1420*10784Ssinanallur.balasubramanian@sun.com 	    "\n%s:cpu_id %d:current suspect list is %s\n",
1421*10784Ssinanallur.balasubramanian@sun.com 	    fltnm, cpu->cpu_cpuid, suspect_list);
1422*10784Ssinanallur.balasubramanian@sun.com 	cmd_Lxcache_fault(hdl, cpu, retire_this_Lxcache, fltnm,
1423*10784Ssinanallur.balasubramanian@sun.com 	    cpu->cpu_fru_nvl,
1424*10784Ssinanallur.balasubramanian@sun.com 	    cert);
1425*10784Ssinanallur.balasubramanian@sun.com 	retire_this_Lxcache->Lxcache_flags = CMD_LxCACHE_F_RETIRED;
1426*10784Ssinanallur.balasubramanian@sun.com 	if (IS_TAG(retire_this_Lxcache->Lxcache_type)) {
1427*10784Ssinanallur.balasubramanian@sun.com 		/*
1428*10784Ssinanallur.balasubramanian@sun.com 		 * If the cacheline we just retired was retired earlier
1429*10784Ssinanallur.balasubramanian@sun.com 		 * due to DATA faults we mark the Lxcache
1430*10784Ssinanallur.balasubramanian@sun.com 		 * corresponding to DATA as RERETIRED.
1431*10784Ssinanallur.balasubramanian@sun.com 		 */
1432*10784Ssinanallur.balasubramanian@sun.com 		if (retire_this_Lxcache->Lxcache_type == CMD_PTR_CPU_L2TAG)
1433*10784Ssinanallur.balasubramanian@sun.com 			data_type = CMD_PTR_CPU_L2DATA;
1434*10784Ssinanallur.balasubramanian@sun.com 		if (retire_this_Lxcache->Lxcache_type == CMD_PTR_CPU_L3TAG)
1435*10784Ssinanallur.balasubramanian@sun.com 			data_type = CMD_PTR_CPU_L3DATA;
1436*10784Ssinanallur.balasubramanian@sun.com 		fmd_hdl_debug(hdl,
1437*10784Ssinanallur.balasubramanian@sun.com 		    "\n%s:cpuid %d checking if there is a %s"
1438*10784Ssinanallur.balasubramanian@sun.com 		    " cacheline retired at this index %d way %d\n",
1439*10784Ssinanallur.balasubramanian@sun.com 		    fltnm, cpu->cpu_cpuid,
1440*10784Ssinanallur.balasubramanian@sun.com 		    cmd_type_to_str(data_type),
1441*10784Ssinanallur.balasubramanian@sun.com 		    retire_this_Lxcache->Lxcache_index,
1442*10784Ssinanallur.balasubramanian@sun.com 		    retire_this_Lxcache->Lxcache_way);
1443*10784Ssinanallur.balasubramanian@sun.com 		previously_retired_Lxcache =
1444*10784Ssinanallur.balasubramanian@sun.com 		    cmd_Lxcache_lookup_by_type_index_way_flags(cpu,
1445*10784Ssinanallur.balasubramanian@sun.com 		    data_type, retire_this_Lxcache->Lxcache_index,
1446*10784Ssinanallur.balasubramanian@sun.com 		    retire_this_Lxcache->Lxcache_way, CMD_LxCACHE_F_RETIRED);
1447*10784Ssinanallur.balasubramanian@sun.com 		if (previously_retired_Lxcache) {
1448*10784Ssinanallur.balasubramanian@sun.com 			fmd_hdl_debug(hdl,
1449*10784Ssinanallur.balasubramanian@sun.com 			    "\n%s:cpu_id %d: Found  index %d way %d"
1450*10784Ssinanallur.balasubramanian@sun.com 			    " retired earlier. Will mark this Lxcache"
1451*10784Ssinanallur.balasubramanian@sun.com 			    " as RERETIRED.\n",
1452*10784Ssinanallur.balasubramanian@sun.com 			    fltnm, cpu->cpu_cpuid,
1453*10784Ssinanallur.balasubramanian@sun.com 			    retire_this_Lxcache->Lxcache_index,
1454*10784Ssinanallur.balasubramanian@sun.com 			    retire_this_Lxcache->Lxcache_way);
1455*10784Ssinanallur.balasubramanian@sun.com 			/*
1456*10784Ssinanallur.balasubramanian@sun.com 			 * First repair the retired cacheline and if successful
1457*10784Ssinanallur.balasubramanian@sun.com 			 * close the existing case and create a new case.
1458*10784Ssinanallur.balasubramanian@sun.com 			 */
1459*10784Ssinanallur.balasubramanian@sun.com 
1460*10784Ssinanallur.balasubramanian@sun.com 			/*
1461*10784Ssinanallur.balasubramanian@sun.com 			 * This cacheline has already been retired for
1462*10784Ssinanallur.balasubramanian@sun.com 			 * TAG fault.
1463*10784Ssinanallur.balasubramanian@sun.com 			 * Repair the previously retired DATA fault cacheline so
1464*10784Ssinanallur.balasubramanian@sun.com 			 * that it does not get retired by fmd during replay.
1465*10784Ssinanallur.balasubramanian@sun.com 			 */
1466*10784Ssinanallur.balasubramanian@sun.com 			if (previously_retired_Lxcache->Lxcache_retired_fmri[0]
1467*10784Ssinanallur.balasubramanian@sun.com 			    != 0) {
1468*10784Ssinanallur.balasubramanian@sun.com 				fmd_hdl_debug(hdl,
1469*10784Ssinanallur.balasubramanian@sun.com 				    "\n%s:cpuid %d Repairing the cacheline"
1470*10784Ssinanallur.balasubramanian@sun.com 				    " retired due to data errors. %s\n",
1471*10784Ssinanallur.balasubramanian@sun.com 				    fltnm, cpu->cpu_cpuid,
1472*10784Ssinanallur.balasubramanian@sun.com 				    previously_retired_Lxcache->
1473*10784Ssinanallur.balasubramanian@sun.com 				    Lxcache_retired_fmri);
1474*10784Ssinanallur.balasubramanian@sun.com 				if (cmd_repair_fmri(hdl,
1475*10784Ssinanallur.balasubramanian@sun.com 				    previously_retired_Lxcache->
1476*10784Ssinanallur.balasubramanian@sun.com 				    Lxcache_retired_fmri)
1477*10784Ssinanallur.balasubramanian@sun.com 				    != 0) {
1478*10784Ssinanallur.balasubramanian@sun.com 					fmd_hdl_debug(hdl,
1479*10784Ssinanallur.balasubramanian@sun.com 					    "\n%s:cpuid %d Failed to repair the"
1480*10784Ssinanallur.balasubramanian@sun.com 					    " retired fmri.",
1481*10784Ssinanallur.balasubramanian@sun.com 					    fltnm, cpu->cpu_cpuid);
1482*10784Ssinanallur.balasubramanian@sun.com 					return (B_FALSE);
1483*10784Ssinanallur.balasubramanian@sun.com 				} else {
1484*10784Ssinanallur.balasubramanian@sun.com 					previously_retired_Lxcache->
1485*10784Ssinanallur.balasubramanian@sun.com 					    Lxcache_retired_fmri[0] = 0;
1486*10784Ssinanallur.balasubramanian@sun.com 				}
1487*10784Ssinanallur.balasubramanian@sun.com 			}
1488*10784Ssinanallur.balasubramanian@sun.com 			cmd_case_fini(hdl,
1489*10784Ssinanallur.balasubramanian@sun.com 			    previously_retired_Lxcache->Lxcache_case.cc_cp,
1490*10784Ssinanallur.balasubramanian@sun.com 			    FMD_B_TRUE);
1491*10784Ssinanallur.balasubramanian@sun.com 			previously_retired_Lxcache->Lxcache_case.cc_cp = NULL;
1492*10784Ssinanallur.balasubramanian@sun.com 			previously_retired_Lxcache->Lxcache_flags =
1493*10784Ssinanallur.balasubramanian@sun.com 			    CMD_LxCACHE_F_RERETIRED;
1494*10784Ssinanallur.balasubramanian@sun.com 			/*
1495*10784Ssinanallur.balasubramanian@sun.com 			 * Update persistent storage
1496*10784Ssinanallur.balasubramanian@sun.com 			 */
1497*10784Ssinanallur.balasubramanian@sun.com 			cmd_Lxcache_write(hdl, previously_retired_Lxcache);
1498*10784Ssinanallur.balasubramanian@sun.com 			/*
1499*10784Ssinanallur.balasubramanian@sun.com 			 * Create a new case so that this Lxcache structure
1500*10784Ssinanallur.balasubramanian@sun.com 			 * gets restored on replay.
1501*10784Ssinanallur.balasubramanian@sun.com 			 */
1502*10784Ssinanallur.balasubramanian@sun.com 			if (cmd_create_case_for_Lxcache(hdl, cpu,
1503*10784Ssinanallur.balasubramanian@sun.com 			    previously_retired_Lxcache) == B_FALSE)
1504*10784Ssinanallur.balasubramanian@sun.com 				return (B_FALSE);
1505*10784Ssinanallur.balasubramanian@sun.com 		}
1506*10784Ssinanallur.balasubramanian@sun.com 	}
1507*10784Ssinanallur.balasubramanian@sun.com 	cmd_retire_cpu_if_limits_exceeded(hdl, cpu,
1508*10784Ssinanallur.balasubramanian@sun.com 	    retire_this_Lxcache->Lxcache_type,
1509*10784Ssinanallur.balasubramanian@sun.com 	    fltnm);
1510*10784Ssinanallur.balasubramanian@sun.com 	return (B_TRUE);
1511*10784Ssinanallur.balasubramanian@sun.com }
1512