1600Stsien /*
2600Stsien  * CDDL HEADER START
3600Stsien  *
4600Stsien  * The contents of this file are subject to the terms of the
53325Ssd77468  * Common Development and Distribution License (the "License").
63325Ssd77468  * 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*8006STom.Pothier@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23600Stsien  * Use is subject to license terms.
24600Stsien  */
25600Stsien 
26600Stsien /*
27600Stsien  * Fault-handling routines for page retirement faults
28600Stsien  */
29600Stsien 
30600Stsien #include <cmd_page.h>
31600Stsien #include <cmd.h>
323325Ssd77468 #include <cmd_mem.h>
33600Stsien 
34600Stsien #include <errno.h>
35600Stsien #include <string.h>
36600Stsien #include <fm/fmd_api.h>
37600Stsien #include <sys/fm/protocol.h>
383657Stsien #ifdef sun4v
393657Stsien #include <cmd_hc_sun4v.h>
403657Stsien #include <cmd_dimm.h>
413657Stsien #endif
42600Stsien 
43600Stsien void
cmd_page_fault(fmd_hdl_t * hdl,nvlist_t * modasru,nvlist_t * modfru,fmd_event_t * ep,uint64_t afar)44600Stsien cmd_page_fault(fmd_hdl_t *hdl, nvlist_t *modasru, nvlist_t *modfru,
45600Stsien     fmd_event_t *ep, uint64_t afar)
46600Stsien {
47*8006STom.Pothier@Sun.COM 	cmd_page_t *page = NULL;
48600Stsien 	const char *uuid;
493763Std122701 	nvlist_t *flt;
503763Std122701 #ifdef sun4v
513763Std122701 	nvlist_t *nvlfru;
523763Std122701 #endif
53600Stsien 
54*8006STom.Pothier@Sun.COM 	page = cmd_page_lookup(afar);
55*8006STom.Pothier@Sun.COM 	if (page != NULL) {
56600Stsien 		/*
57*8006STom.Pothier@Sun.COM 		 * If the page has already been retired then *page
58*8006STom.Pothier@Sun.COM 		 * would have been freed and recreated. Thus the
59*8006STom.Pothier@Sun.COM 		 * flag would be 0x0 - check to see if the page
60*8006STom.Pothier@Sun.COM 		 * is unusable (retired).
61600Stsien 		 */
62*8006STom.Pothier@Sun.COM 		if (page->page_flags & CMD_MEM_F_FAULTING ||
63*8006STom.Pothier@Sun.COM 		    fmd_nvl_fmri_unusable(hdl, page->page_asru_nvl)) {
64*8006STom.Pothier@Sun.COM 			/* Page already faulted, don't fault again. */
65*8006STom.Pothier@Sun.COM 			page->page_flags |= CMD_MEM_F_FAULTING;
66*8006STom.Pothier@Sun.COM 			return;
67*8006STom.Pothier@Sun.COM 		}
68*8006STom.Pothier@Sun.COM 	} else {
69*8006STom.Pothier@Sun.COM 		page = cmd_page_create(hdl, modasru, afar);
70600Stsien 	}
71600Stsien 
72*8006STom.Pothier@Sun.COM 	page->page_flags |= CMD_MEM_F_FAULTING;
733325Ssd77468 	if (page->page_case.cc_cp == NULL)
744934Stsien 		page->page_case.cc_cp = cmd_case_create(hdl,
754934Stsien 		    &page->page_header, CMD_PTR_PAGE_CASE, &uuid);
76600Stsien 
773657Stsien #ifdef sun4v
783730Std122701 	nvlfru = cmd_mem2hc(hdl, modfru);
794934Stsien 	flt = cmd_nvl_create_fault(hdl, "fault.memory.page", 100,
803730Std122701 	    page->page_asru_nvl, nvlfru, NULL);
813657Stsien 	flt = cmd_fault_add_location(hdl, flt, cmd_fmri_get_unum(modfru));
823730Std122701 	if (nvlfru != NULL)
833730Std122701 		nvlist_free(nvlfru);
843657Stsien #else /* sun4v */
854934Stsien 	flt = cmd_nvl_create_fault(hdl, "fault.memory.page", 100,
86600Stsien 	    page->page_asru_nvl, modfru, NULL);
873657Stsien #endif /* sun4v */
88600Stsien 
89600Stsien 	if (nvlist_add_boolean_value(flt, FM_SUSPECT_MESSAGE, B_FALSE) != 0)
90600Stsien 		fmd_hdl_abort(hdl, "failed to add no-message member to fault");
91600Stsien 
923325Ssd77468 	fmd_case_add_ereport(hdl, page->page_case.cc_cp, ep);
933325Ssd77468 	fmd_case_add_suspect(hdl, page->page_case.cc_cp, flt);
943325Ssd77468 	fmd_case_solve(hdl, page->page_case.cc_cp);
95600Stsien }
96600Stsien 
97600Stsien void
cmd_page_close(fmd_hdl_t * hdl,void * arg)98600Stsien cmd_page_close(fmd_hdl_t *hdl, void *arg)
99600Stsien {
100600Stsien 	cmd_page_destroy(hdl, arg);
101600Stsien }
102