xref: /onnv-gate/usr/src/cmd/fm/modules/sun4/cpumem-diagnosis/cmd_state.c (revision 11370:4533f8d5ce97)
1600Stsien /*
2600Stsien  * CDDL HEADER START
3600Stsien  *
4600Stsien  * The contents of this file are subject to the terms of the
51772Sjl139090  * Common Development and Distribution License (the "License").
61772Sjl139090  * You may not use this file except in compliance with the License.
7600Stsien  *
8600Stsien  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9600Stsien  * or http://www.opensolaris.org/os/licensing.
10600Stsien  * See the License for the specific language governing permissions
11600Stsien  * and limitations under the License.
12600Stsien  *
13600Stsien  * When distributing Covered Code, include this CDDL HEADER in each
14600Stsien  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15600Stsien  * If applicable, add the following below this CDDL HEADER, with the
16600Stsien  * fields enclosed by brackets "[]" replaced with your own identifying
17600Stsien  * information: Portions Copyright [yyyy] [name of copyright owner]
18600Stsien  *
19600Stsien  * CDDL HEADER END
20600Stsien  */
21600Stsien /*
22*11370SMary.Beale@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23600Stsien  * Use is subject to license terms.
24600Stsien  */
25600Stsien 
26600Stsien 
27600Stsien /*
28600Stsien  * Case management and saved state restoration
29600Stsien  */
30600Stsien 
31600Stsien #include <cmd_state.h>
32600Stsien #include <cmd_cpu.h>
33600Stsien #include <cmd_mem.h>
34600Stsien #include <cmd_page.h>
35600Stsien #include <cmd_dimm.h>
361186Sayznaga #ifdef sun4u
371186Sayznaga #include <cmd_dp.h>
381186Sayznaga #include <cmd_dp_page.h>
396330Sjc25722 #include <cmd_Lxcache.h>
401186Sayznaga #endif
41600Stsien #include <cmd_bank.h>
42600Stsien #include <cmd.h>
434759Ssd77468 #ifdef sun4v
444759Ssd77468 #include <cmd_branch.h>
454759Ssd77468 #endif
46600Stsien 
47600Stsien #include <string.h>
48600Stsien #include <fm/fmd_api.h>
49600Stsien 
501772Sjl139090 #ifdef sun4u
511772Sjl139090 #include <cmd_opl.h>
521772Sjl139090 #endif
531772Sjl139090 
54600Stsien /* Must be in sync with cmd_ptrsubtype_t */
55600Stsien static cmd_case_closer_f *const cmd_case_closers[] = {
56600Stsien 	NULL,
57600Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_ICACHE */
58600Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_DCACHE */
59600Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_PCACHE */
60600Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_ITLB */
61600Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_DTLB */
62600Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_L2DATA */
63600Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_L2DATA_UERETRY */
64600Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_L2TAG */
65600Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_L3DATA */
66600Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_L3DATA_UERETRY */
67600Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_L3TAG */
68600Stsien 	cmd_dimm_close,		/* CMD_PTR_DIMM_CASE */
69600Stsien 	cmd_bank_close,		/* CMD_PTR_BANK_CASE */
70600Stsien 	cmd_page_close,		/* CMD_PTR_PAGE_CASE */
71600Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_FPU */
72962Stsien 	NULL,			/* CMD_PTR_CPU_XR_RETRY */
73962Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_IREG */
74962Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_FREG */
75962Stsien 	cmd_cpuerr_close,	/* CMD_PTR_CPU_MAU */
761186Sayznaga 	cmd_cpuerr_close,	/* CMD_PTR_CPU_L2CTL */
771186Sayznaga #ifdef sun4u
781186Sayznaga 	cmd_dp_close,		/* CMD_PTR_DP_CASE */
791186Sayznaga #else
801186Sayznaga 	NULL,			/* CMD_PTR_DP_CASE */
811186Sayznaga #endif
821772Sjl139090 	NULL,			/* CMD_PTR_DP_PAGE_DEFER */
831772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_INV_SFSR */
841772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UE_DET_CPU */
851772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UE_DET_IO */
861772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_MTLB */
871772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_TLBP */
881772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_INV_URG */
891772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_CRE */
901772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_TSB_CTX */
911772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_TSBP */
921772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_PSTATE */
931772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_TSTATE */
941772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_IUG_F */
951772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_IUG_R */
961772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_SDC */
971772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_WDT */
981772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_DTLB */
991772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_ITLB */
1001772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_CORE_ERR */
1011772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_DAE */
1021772Sjl139090 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_IAE */
1033325Ssd77468 	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_UGE */
1044759Ssd77468 	cmd_cpuerr_close,	/* CMD_PTR_CPU_MISC_REGS */
1054759Ssd77468 	cmd_cpuerr_close,	/* CMD_PTR_CPU_LFU */
1064759Ssd77468 #ifdef sun4v
1074759Ssd77468 	cmd_branch_close	/* CMD_PTR_BRANCH_CASE */
1084759Ssd77468 #else
1096330Sjc25722 	NULL,
1106330Sjc25722 	cmd_Lxcache_close,	/* CMD_PTR_CACHE_CASE */
1116330Sjc25722 
1124759Ssd77468 #endif
113600Stsien };
114600Stsien 
115600Stsien fmd_case_t *
cmd_case_create(fmd_hdl_t * hdl,cmd_header_t * hdr,cmd_ptrsubtype_t ptrsubtype,const char ** uuidp)116600Stsien cmd_case_create(fmd_hdl_t *hdl, cmd_header_t *hdr, cmd_ptrsubtype_t ptrsubtype,
117600Stsien     const char **uuidp)
118600Stsien {
119600Stsien 	cmd_case_ptr_t ptr;
120600Stsien 	cmd_case_closer_t *cl;
121600Stsien 	fmd_case_t *cp;
122600Stsien 
123600Stsien 	cl = fmd_hdl_alloc(hdl, sizeof (cmd_case_closer_t), FMD_SLEEP);
124600Stsien 	cl->cl_func = cmd_case_closers[ptrsubtype];
125600Stsien 	cl->cl_arg = hdr;
126600Stsien 
127600Stsien 	cp = fmd_case_open(hdl, cl);
128600Stsien 
129600Stsien 	ptr.ptr_type = hdr->hdr_nodetype;
130600Stsien 	ptr.ptr_subtype = ptrsubtype;
131600Stsien 	(void) strcpy(ptr.ptr_name, hdr->hdr_bufname);
132600Stsien 
133600Stsien 	*uuidp = fmd_case_uuid(hdl, cp);
134600Stsien 	fmd_buf_write(hdl, cp, *uuidp, &ptr, sizeof (cmd_case_ptr_t));
135600Stsien 
136600Stsien 	return (cp);
137600Stsien }
138600Stsien 
139600Stsien void
cmd_case_redirect(fmd_hdl_t * hdl,fmd_case_t * cp,cmd_ptrsubtype_t newsubtype)140600Stsien cmd_case_redirect(fmd_hdl_t *hdl, fmd_case_t *cp, cmd_ptrsubtype_t newsubtype)
141600Stsien {
142600Stsien 	const char *uuid = fmd_case_uuid(hdl, cp);
143600Stsien 	cmd_case_ptr_t ptr;
144600Stsien 
145600Stsien 	fmd_buf_read(hdl, cp, uuid, &ptr, sizeof (cmd_case_ptr_t));
146600Stsien 	fmd_hdl_debug(hdl, "redirecting case %s from %d to %d\n", uuid,
147600Stsien 	    ptr.ptr_subtype, newsubtype);
148600Stsien 	ptr.ptr_subtype = newsubtype;
149600Stsien 	fmd_buf_write(hdl, cp, uuid, &ptr, sizeof (cmd_case_ptr_t));
150600Stsien }
151600Stsien 
152600Stsien void
cmd_case_fini(fmd_hdl_t * hdl,fmd_case_t * cp,int close)153600Stsien cmd_case_fini(fmd_hdl_t *hdl, fmd_case_t *cp, int close)
154600Stsien {
155600Stsien 	const char *uuid = fmd_case_uuid(hdl, cp);
156600Stsien 	cmd_case_closer_t *cl = fmd_case_getspecific(hdl, cp);
157600Stsien 
158600Stsien 	if (close) {
159600Stsien 		fmd_hdl_debug(hdl, "closing case %s\n", uuid);
160600Stsien 
161600Stsien 		if (fmd_serd_exists(hdl, uuid))
162600Stsien 			fmd_serd_destroy(hdl, uuid);
163600Stsien 
164600Stsien 		if (fmd_buf_size(hdl, cp, uuid) != 0)
165600Stsien 			fmd_buf_destroy(hdl, cp, uuid);
166600Stsien 
167600Stsien 		fmd_case_setspecific(hdl, cp, NULL);
168600Stsien 		fmd_case_close(hdl, cp);
169600Stsien 	}
170600Stsien 
171600Stsien 	if (cl != NULL)
172600Stsien 		fmd_hdl_free(hdl, cl, sizeof (cmd_case_closer_t));
173600Stsien }
174600Stsien 
175600Stsien /* Must be in sync with cmd_nodetype_t */
176600Stsien static cmd_case_restorer_f *const cmd_case_restorers[] = {
177600Stsien 	NULL,
178600Stsien 	cmd_cpu_restore,	/* CMD_NT_CPU */
179600Stsien 	cmd_dimm_restore,	/* CMD_NT_DIMM */
180600Stsien 	cmd_bank_restore,	/* CMD_NT_BANK */
1811186Sayznaga 	cmd_page_restore,	/* CMD_NT_PAGE */
1821186Sayznaga #ifdef sun4u
1836330Sjc25722 	cmd_dp_restore,		/* CMD_NT_DP */
1846330Sjc25722 	cmd_Lxcache_restore,	/* CMD_NT_CACHE */
1851186Sayznaga #endif
1864759Ssd77468 #ifdef sun4v
1874759Ssd77468 	cmd_branch_restore	/* CMD_NT_BRANCH */
1884759Ssd77468 #endif
189600Stsien };
190600Stsien 
191600Stsien int
cmd_state_restore(fmd_hdl_t * hdl)192600Stsien cmd_state_restore(fmd_hdl_t *hdl)
193600Stsien {
194600Stsien 	fmd_case_t *cp = NULL;
195600Stsien 
196600Stsien 	while ((cp = fmd_case_next(hdl, cp)) != NULL) {
197600Stsien 		const char *uuid = fmd_case_uuid(hdl, cp);
198600Stsien 		cmd_case_closer_t *cl;
199600Stsien 		cmd_case_ptr_t ptr;
200600Stsien 		void *thing;
201600Stsien 		size_t sz;
202600Stsien 
203600Stsien 		if ((sz = fmd_buf_size(hdl, cp, uuid)) == 0)
204600Stsien 			continue;
205600Stsien 		else if (sz != sizeof (cmd_case_ptr_t))
206600Stsien 			return (cmd_set_errno(EINVAL));
207600Stsien 
208600Stsien 		fmd_buf_read(hdl, cp, fmd_case_uuid(hdl, cp), &ptr,
209600Stsien 		    sizeof (cmd_case_ptr_t));
210600Stsien 
211*11370SMary.Beale@Sun.COM 		if (ptr.ptr_type == 0 || ptr.ptr_type >=
212600Stsien 		    sizeof (cmd_case_restorers) /
213600Stsien 		    sizeof (cmd_case_restorer_f *))
214600Stsien 			return (cmd_set_errno(EINVAL));
215600Stsien 
216600Stsien 		if ((thing = cmd_case_restorers[ptr.ptr_type](hdl,
2176208Smb91622 		    cp, &ptr)) == NULL) {
2186208Smb91622 			fmd_hdl_debug(hdl, "Unable to restore case %s\n", uuid);
2196208Smb91622 			continue;
2206208Smb91622 		}
221600Stsien 
222600Stsien 		cl = fmd_hdl_alloc(hdl, sizeof (cmd_case_closer_t), FMD_SLEEP);
223600Stsien 		cl->cl_func = cmd_case_closers[ptr.ptr_subtype];
224600Stsien 		cl->cl_arg = thing;
225600Stsien 		fmd_case_setspecific(hdl, cp, cl);
226600Stsien 	}
227600Stsien 
228600Stsien 	cmd_trw_restore(hdl);
229600Stsien 
230600Stsien 	cmd_cpu_validate(hdl);
231600Stsien 	cmd_bank_validate(hdl);
232600Stsien 	cmd_dimm_validate(hdl);
2331186Sayznaga #ifdef sun4u
2341186Sayznaga 	/*
2351186Sayznaga 	 * cmd_dp_page_validate() must be done before cmd_dp_validate()
2361186Sayznaga 	 * and cmd_page_validate()
2371186Sayznaga 	 */
2381186Sayznaga 	cmd_dp_page_validate(hdl);
2391186Sayznaga 	cmd_dp_validate(hdl);
2401186Sayznaga #endif
241600Stsien 	cmd_page_validate(hdl);
2424759Ssd77468 #ifdef sun4v
2434759Ssd77468 	cmd_branch_validate(hdl);
2444759Ssd77468 #endif
2451186Sayznaga 
246600Stsien 	return (0);
247600Stsien }
248600Stsien 
249600Stsien void
cmd_case_restore(fmd_hdl_t * hdl,cmd_case_t * cc,fmd_case_t * cp,char * serdnm)250600Stsien cmd_case_restore(fmd_hdl_t *hdl, cmd_case_t *cc, fmd_case_t *cp, char *serdnm)
251600Stsien {
252600Stsien 	if (!fmd_serd_exists(hdl, serdnm)) {
253600Stsien 		fmd_hdl_strfree(hdl, serdnm);
254600Stsien 		serdnm = NULL;
255600Stsien 	}
256600Stsien 
257600Stsien 	cc->cc_cp = cp;
258600Stsien 	cc->cc_serdnm = serdnm;
259600Stsien }
260