17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
525cf1a3jl * Common Development and Distribution License (the "License").
625cf1a3jl * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217c478bdstevel@tonic-gate/*
22dadce0fMary Beale * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bdstevel@tonic-gate * Use is subject to license terms.
247c478bdstevel@tonic-gate */
257c478bdstevel@tonic-gate
267c478bdstevel@tonic-gate
277c478bdstevel@tonic-gate/*
287c478bdstevel@tonic-gate * Case management and saved state restoration
297c478bdstevel@tonic-gate */
307c478bdstevel@tonic-gate
317c478bdstevel@tonic-gate#include <cmd_state.h>
327c478bdstevel@tonic-gate#include <cmd_cpu.h>
337c478bdstevel@tonic-gate#include <cmd_mem.h>
347c478bdstevel@tonic-gate#include <cmd_page.h>
357c478bdstevel@tonic-gate#include <cmd_dimm.h>
36d00f015ayznaga#ifdef sun4u
37d00f015ayznaga#include <cmd_dp.h>
38d00f015ayznaga#include <cmd_dp_page.h>
397bebe46jc#include <cmd_Lxcache.h>
40d00f015ayznaga#endif
417c478bdstevel@tonic-gate#include <cmd_bank.h>
427c478bdstevel@tonic-gate#include <cmd.h>
43fbd1c0dsd#ifdef sun4v
44fbd1c0dsd#include <cmd_branch.h>
45fbd1c0dsd#endif
467c478bdstevel@tonic-gate
477c478bdstevel@tonic-gate#include <string.h>
487c478bdstevel@tonic-gate#include <fm/fmd_api.h>
497c478bdstevel@tonic-gate
5025cf1a3jl#ifdef sun4u
5125cf1a3jl#include <cmd_opl.h>
5225cf1a3jl#endif
5325cf1a3jl
547c478bdstevel@tonic-gate/* Must be in sync with cmd_ptrsubtype_t */
557c478bdstevel@tonic-gatestatic cmd_case_closer_f *const cmd_case_closers[] = {
567c478bdstevel@tonic-gate	NULL,
577c478bdstevel@tonic-gate	cmd_cpuerr_close,	/* CMD_PTR_CPU_ICACHE */
587c478bdstevel@tonic-gate	cmd_cpuerr_close,	/* CMD_PTR_CPU_DCACHE */
597c478bdstevel@tonic-gate	cmd_cpuerr_close,	/* CMD_PTR_CPU_PCACHE */
607c478bdstevel@tonic-gate	cmd_cpuerr_close,	/* CMD_PTR_CPU_ITLB */
617c478bdstevel@tonic-gate	cmd_cpuerr_close,	/* CMD_PTR_CPU_DTLB */
627c478bdstevel@tonic-gate	cmd_cpuerr_close,	/* CMD_PTR_CPU_L2DATA */
637c478bdstevel@tonic-gate	cmd_cpuerr_close,	/* CMD_PTR_CPU_L2DATA_UERETRY */
647c478bdstevel@tonic-gate	cmd_cpuerr_close,	/* CMD_PTR_CPU_L2TAG */
657c478bdstevel@tonic-gate	cmd_cpuerr_close,	/* CMD_PTR_CPU_L3DATA */
667c478bdstevel@tonic-gate	cmd_cpuerr_close,	/* CMD_PTR_CPU_L3DATA_UERETRY */
677c478bdstevel@tonic-gate	cmd_cpuerr_close,	/* CMD_PTR_CPU_L3TAG */
687c478bdstevel@tonic-gate	cmd_dimm_close,		/* CMD_PTR_DIMM_CASE */
697c478bdstevel@tonic-gate	cmd_bank_close,		/* CMD_PTR_BANK_CASE */
707c478bdstevel@tonic-gate	cmd_page_close,		/* CMD_PTR_PAGE_CASE */
717c478bdstevel@tonic-gate	cmd_cpuerr_close,	/* CMD_PTR_CPU_FPU */
726dfee48tsien	NULL,			/* CMD_PTR_CPU_XR_RETRY */
736dfee48tsien	cmd_cpuerr_close,	/* CMD_PTR_CPU_IREG */
746dfee48tsien	cmd_cpuerr_close,	/* CMD_PTR_CPU_FREG */
756dfee48tsien	cmd_cpuerr_close,	/* CMD_PTR_CPU_MAU */
76d00f015ayznaga	cmd_cpuerr_close,	/* CMD_PTR_CPU_L2CTL */
77d00f015ayznaga#ifdef sun4u
78d00f015ayznaga	cmd_dp_close,		/* CMD_PTR_DP_CASE */
79d00f015ayznaga#else
80d00f015ayznaga	NULL,			/* CMD_PTR_DP_CASE */
81d00f015ayznaga#endif
8225cf1a3jl	NULL,			/* CMD_PTR_DP_PAGE_DEFER */
8325cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_INV_SFSR */
8425cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UE_DET_CPU */
8525cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UE_DET_IO */
8625cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_MTLB */
8725cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_TLBP */
8825cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_INV_URG */
8925cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_CRE */
9025cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_TSB_CTX */
9125cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_TSBP */
9225cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_PSTATE */
9325cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_TSTATE */
9425cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_IUG_F */
9525cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_IUG_R */
9625cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_SDC */
9725cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_WDT */
9825cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_DTLB */
9925cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_ITLB */
10025cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_CORE_ERR */
10125cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_DAE */
10225cf1a3jl	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_IAE */
10314ea4bbsd	cmd_cpuerr_close,	/* CMD_PTR_CPU_UGESR_UGE */
104fbd1c0dsd	cmd_cpuerr_close,	/* CMD_PTR_CPU_MISC_REGS */
105fbd1c0dsd	cmd_cpuerr_close,	/* CMD_PTR_CPU_LFU */
106fbd1c0dsd#ifdef sun4v
107fbd1c0dsd	cmd_branch_close	/* CMD_PTR_BRANCH_CASE */
108fbd1c0dsd#else
1097bebe46jc	NULL,
1107bebe46jc	cmd_Lxcache_close,	/* CMD_PTR_CACHE_CASE */
1117bebe46jc
112fbd1c0dsd#endif
1137c478bdstevel@tonic-gate};
1147c478bdstevel@tonic-gate
1157c478bdstevel@tonic-gatefmd_case_t *
1167c478bdstevel@tonic-gatecmd_case_create(fmd_hdl_t *hdl, cmd_header_t *hdr, cmd_ptrsubtype_t ptrsubtype,
1177c478bdstevel@tonic-gate    const char **uuidp)
1187c478bdstevel@tonic-gate{
1197c478bdstevel@tonic-gate	cmd_case_ptr_t ptr;
1207c478bdstevel@tonic-gate	cmd_case_closer_t *cl;
1217c478bdstevel@tonic-gate	fmd_case_t *cp;
1227c478bdstevel@tonic-gate
1237c478bdstevel@tonic-gate	cl = fmd_hdl_alloc(hdl, sizeof (cmd_case_closer_t), FMD_SLEEP);
1247c478bdstevel@tonic-gate	cl->cl_func = cmd_case_closers[ptrsubtype];
1257c478bdstevel@tonic-gate	cl->cl_arg = hdr;
1267c478bdstevel@tonic-gate
1277c478bdstevel@tonic-gate	cp = fmd_case_open(hdl, cl);
1287c478bdstevel@tonic-gate
1297c478bdstevel@tonic-gate	ptr.ptr_type = hdr->hdr_nodetype;
1307c478bdstevel@tonic-gate	ptr.ptr_subtype = ptrsubtype;
1317c478bdstevel@tonic-gate	(void) strcpy(ptr.ptr_name, hdr->hdr_bufname);
1327c478bdstevel@tonic-gate
1337c478bdstevel@tonic-gate	*uuidp = fmd_case_uuid(hdl, cp);
1347c478bdstevel@tonic-gate	fmd_buf_write(hdl, cp, *uuidp, &ptr, sizeof (cmd_case_ptr_t));
1357c478bdstevel@tonic-gate
1367c478bdstevel@tonic-gate	return (cp);
1377c478bdstevel@tonic-gate}
1387c478bdstevel@tonic-gate
1397c478bdstevel@tonic-gatevoid
1407c478bdstevel@tonic-gatecmd_case_redirect(fmd_hdl_t *hdl, fmd_case_t *cp, cmd_ptrsubtype_t newsubtype)
1417c478bdstevel@tonic-gate{
1427c478bdstevel@tonic-gate	const char *uuid = fmd_case_uuid(hdl, cp);
1437c478bdstevel@tonic-gate	cmd_case_ptr_t ptr;
1447c478bdstevel@tonic-gate
1457c478bdstevel@tonic-gate	fmd_buf_read(hdl, cp, uuid, &ptr, sizeof (cmd_case_ptr_t));
1467c478bdstevel@tonic-gate	fmd_hdl_debug(hdl, "redirecting case %s from %d to %d\n", uuid,
1477c478bdstevel@tonic-gate	    ptr.ptr_subtype, newsubtype);
1487c478bdstevel@tonic-gate	ptr.ptr_subtype = newsubtype;
1497c478bdstevel@tonic-gate	fmd_buf_write(hdl, cp, uuid, &ptr, sizeof (cmd_case_ptr_t));
1507c478bdstevel@tonic-gate}
1517c478bdstevel@tonic-gate
1527c478bdstevel@tonic-gatevoid
1537c478bdstevel@tonic-gatecmd_case_fini(fmd_hdl_t *hdl, fmd_case_t *cp, int close)
1547c478bdstevel@tonic-gate{
1557c478bdstevel@tonic-gate	const char *uuid = fmd_case_uuid(hdl, cp);
1567c478bdstevel@tonic-gate	cmd_case_closer_t *cl = fmd_case_getspecific(hdl, cp);
1577c478bdstevel@tonic-gate
1587c478bdstevel@tonic-gate	if (close) {
1597c478bdstevel@tonic-gate		fmd_hdl_debug(hdl, "closing case %s\n", uuid);
1607c478bdstevel@tonic-gate
1617c478bdstevel@tonic-gate		if (fmd_serd_exists(hdl, uuid))
1627c478bdstevel@tonic-gate			fmd_serd_destroy(hdl, uuid);
1637c478bdstevel@tonic-gate
1647c478bdstevel@tonic-gate		if (fmd_buf_size(hdl, cp, uuid) != 0)
1657c478bdstevel@tonic-gate			fmd_buf_destroy(hdl, cp, uuid);
1667c478bdstevel@tonic-gate
1677c478bdstevel@tonic-gate		fmd_case_setspecific(hdl, cp, NULL);
1687c478bdstevel@tonic-gate		fmd_case_close(hdl, cp);
1697c478bdstevel@tonic-gate	}
1707c478bdstevel@tonic-gate
1717c478bdstevel@tonic-gate	if (cl != NULL)
1727c478bdstevel@tonic-gate		fmd_hdl_free(hdl, cl, sizeof (cmd_case_closer_t));
1737c478bdstevel@tonic-gate}
1747c478bdstevel@tonic-gate
1757c478bdstevel@tonic-gate/* Must be in sync with cmd_nodetype_t */
1767c478bdstevel@tonic-gatestatic cmd_case_restorer_f *const cmd_case_restorers[] = {
1777c478bdstevel@tonic-gate	NULL,
1787c478bdstevel@tonic-gate	cmd_cpu_restore,	/* CMD_NT_CPU */
1797c478bdstevel@tonic-gate	cmd_dimm_restore,	/* CMD_NT_DIMM */
1807c478bdstevel@tonic-gate	cmd_bank_restore,	/* CMD_NT_BANK */
181d00f015ayznaga	cmd_page_restore,	/* CMD_NT_PAGE */
182d00f015ayznaga#ifdef sun4u
1837bebe46jc	cmd_dp_restore,		/* CMD_NT_DP */
1847bebe46jc	cmd_Lxcache_restore,	/* CMD_NT_CACHE */
185d00f015ayznaga#endif
186fbd1c0dsd#ifdef sun4v
187fbd1c0dsd	cmd_branch_restore	/* CMD_NT_BRANCH */
188fbd1c0dsd#endif
1897c478bdstevel@tonic-gate};
1907c478bdstevel@tonic-gate
1917c478bdstevel@tonic-gateint
1927c478bdstevel@tonic-gatecmd_state_restore(fmd_hdl_t *hdl)
1937c478bdstevel@tonic-gate{
1947c478bdstevel@tonic-gate	fmd_case_t *cp = NULL;
1957c478bdstevel@tonic-gate
1967c478bdstevel@tonic-gate	while ((cp = fmd_case_next(hdl, cp)) != NULL) {
1977c478bdstevel@tonic-gate		const char *uuid = fmd_case_uuid(hdl, cp);
1987c478bdstevel@tonic-gate		cmd_case_closer_t *cl;
1997c478bdstevel@tonic-gate		cmd_case_ptr_t ptr;
2007c478bdstevel@tonic-gate		void *thing;
2017c478bdstevel@tonic-gate		size_t sz;
2027c478bdstevel@tonic-gate
2037c478bdstevel@tonic-gate		if ((sz = fmd_buf_size(hdl, cp, uuid)) == 0)
2047c478bdstevel@tonic-gate			continue;
2057c478bdstevel@tonic-gate		else if (sz != sizeof (cmd_case_ptr_t))
2067c478bdstevel@tonic-gate			return (cmd_set_errno(EINVAL));
2077c478bdstevel@tonic-gate
2087c478bdstevel@tonic-gate		fmd_buf_read(hdl, cp, fmd_case_uuid(hdl, cp), &ptr,
2097c478bdstevel@tonic-gate		    sizeof (cmd_case_ptr_t));
2107c478bdstevel@tonic-gate
211dadce0fMary Beale		if (ptr.ptr_type == 0 || ptr.ptr_type >=
2127c478bdstevel@tonic-gate		    sizeof (cmd_case_restorers) /
2137c478bdstevel@tonic-gate		    sizeof (cmd_case_restorer_f *))
2147c478bdstevel@tonic-gate			return (cmd_set_errno(EINVAL));
2157c478bdstevel@tonic-gate
2167c478bdstevel@tonic-gate		if ((thing = cmd_case_restorers[ptr.ptr_type](hdl,
217c498d93mb		    cp, &ptr)) == NULL) {
218c498d93mb			fmd_hdl_debug(hdl, "Unable to restore case %s\n", uuid);
219c498d93mb			continue;
220c498d93mb		}
2217c478bdstevel@tonic-gate
2227c478bdstevel@tonic-gate		cl = fmd_hdl_alloc(hdl, sizeof (cmd_case_closer_t), FMD_SLEEP);
2237c478bdstevel@tonic-gate		cl->cl_func = cmd_case_closers[ptr.ptr_subtype];
2247c478bdstevel@tonic-gate		cl->cl_arg = thing;
2257c478bdstevel@tonic-gate		fmd_case_setspecific(hdl, cp, cl);
2267c478bdstevel@tonic-gate	}
2277c478bdstevel@tonic-gate
2287c478bdstevel@tonic-gate	cmd_trw_restore(hdl);
2297c478bdstevel@tonic-gate
2307c478bdstevel@tonic-gate	cmd_cpu_validate(hdl);
2317c478bdstevel@tonic-gate	cmd_bank_validate(hdl);
2327c478bdstevel@tonic-gate	cmd_dimm_validate(hdl);
233d00f015ayznaga#ifdef sun4u
234d00f015ayznaga	/*
235d00f015ayznaga	 * cmd_dp_page_validate() must be done before cmd_dp_validate()
236d00f015ayznaga	 * and cmd_page_validate()
237d00f015ayznaga	 */
238d00f015ayznaga	cmd_dp_page_validate(hdl);
239d00f015ayznaga	cmd_dp_validate(hdl);
240d00f015ayznaga#endif
2417c478bdstevel@tonic-gate	cmd_page_validate(hdl);
242fbd1c0dsd#ifdef sun4v
243fbd1c0dsd	cmd_branch_validate(hdl);
244fbd1c0dsd#endif
245d00f015ayznaga
2467c478bdstevel@tonic-gate	return (0);
2477c478bdstevel@tonic-gate}
2487c478bdstevel@tonic-gate
2497c478bdstevel@tonic-gatevoid
2507c478bdstevel@tonic-gatecmd_case_restore(fmd_hdl_t *hdl, cmd_case_t *cc, fmd_case_t *cp, char *serdnm)
2517c478bdstevel@tonic-gate{
2527c478bdstevel@tonic-gate	if (!fmd_serd_exists(hdl, serdnm)) {
2537c478bdstevel@tonic-gate		fmd_hdl_strfree(hdl, serdnm);
2547c478bdstevel@tonic-gate		serdnm = NULL;
2557c478bdstevel@tonic-gate	}
2567c478bdstevel@tonic-gate
2577c478bdstevel@tonic-gate	cc->cc_cp = cp;
2587c478bdstevel@tonic-gate	cc->cc_serdnm = serdnm;
2597c478bdstevel@tonic-gate}
260