xref: /illumos-gate/usr/src/uts/sun4v/io/fault_iso.c (revision f500b196)
11ae08745Sheppo /*
21ae08745Sheppo  * CDDL HEADER START
31ae08745Sheppo  *
41ae08745Sheppo  * The contents of this file are subject to the terms of the
51ae08745Sheppo  * Common Development and Distribution License (the "License").
61ae08745Sheppo  * You may not use this file except in compliance with the License.
71ae08745Sheppo  *
81ae08745Sheppo  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91ae08745Sheppo  * or http://www.opensolaris.org/os/licensing.
101ae08745Sheppo  * See the License for the specific language governing permissions
111ae08745Sheppo  * and limitations under the License.
121ae08745Sheppo  *
131ae08745Sheppo  * When distributing Covered Code, include this CDDL HEADER in each
141ae08745Sheppo  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151ae08745Sheppo  * If applicable, add the following below this CDDL HEADER, with the
161ae08745Sheppo  * fields enclosed by brackets "[]" replaced with your own identifying
171ae08745Sheppo  * information: Portions Copyright [yyyy] [name of copyright owner]
181ae08745Sheppo  *
191ae08745Sheppo  * CDDL HEADER END
201ae08745Sheppo  */
211ae08745Sheppo 
221ae08745Sheppo /*
23*f500b196SRichard Bean  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
241ae08745Sheppo  * Use is subject to license terms.
251ae08745Sheppo  */
261ae08745Sheppo 
271ae08745Sheppo /*
281ae08745Sheppo  * sun4v Fault Isolation Services Module
291ae08745Sheppo  */
301ae08745Sheppo 
311ae08745Sheppo #include <sys/modctl.h>
321ae08745Sheppo #include <sys/cmn_err.h>
331ae08745Sheppo #include <sys/machsystm.h>
341ae08745Sheppo #include <sys/processor.h>
351ae08745Sheppo #include <sys/mem.h>
361ae08745Sheppo #include <vm/page.h>
371ae08745Sheppo #include <sys/note.h>
381ae08745Sheppo #include <sys/ds.h>
391ae08745Sheppo #include <sys/fault_iso.h>
401ae08745Sheppo 
411ae08745Sheppo /*
421ae08745Sheppo  * Debugging routines
431ae08745Sheppo  */
441ae08745Sheppo #ifdef DEBUG
451ae08745Sheppo uint_t fi_debug = 0x0;
461ae08745Sheppo #define	FI_DBG	if (fi_debug) cmn_err
471ae08745Sheppo #else /* DEBUG */
481ae08745Sheppo #define	FI_DBG	_NOTE(CONSTCOND) if (0) cmn_err
491ae08745Sheppo #endif /* DEBUG */
501ae08745Sheppo 
511ae08745Sheppo /*
521ae08745Sheppo  * Domains Services interaction
531ae08745Sheppo  */
541ae08745Sheppo static ds_svc_hdl_t	cpu_handle;
551ae08745Sheppo static ds_svc_hdl_t	mem_handle;
561ae08745Sheppo 
571ae08745Sheppo static ds_ver_t		fi_vers[] = { { 1, 0 } };
581ae08745Sheppo #define	FI_NVERS	(sizeof (fi_vers) / sizeof (fi_vers[0]))
591ae08745Sheppo 
601ae08745Sheppo static ds_capability_t cpu_cap = {
611ae08745Sheppo 	"fma-cpu-service",	/* svc_id */
621ae08745Sheppo 	fi_vers,		/* vers */
631ae08745Sheppo 	FI_NVERS		/* nvers */
641ae08745Sheppo };
651ae08745Sheppo 
661ae08745Sheppo static ds_capability_t mem_cap = {
671ae08745Sheppo 	"fma-mem-service",	/* svc_id */
681ae08745Sheppo 	fi_vers,		/* vers */
691ae08745Sheppo 	FI_NVERS		/* nvers */
701ae08745Sheppo };
711ae08745Sheppo 
721ae08745Sheppo static void fi_reg_handler(ds_cb_arg_t arg, ds_ver_t *ver, ds_svc_hdl_t hdl);
731ae08745Sheppo static void fi_unreg_handler(ds_cb_arg_t arg);
741ae08745Sheppo 
751ae08745Sheppo static void cpu_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen);
761ae08745Sheppo static void mem_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen);
771ae08745Sheppo 
781ae08745Sheppo static ds_clnt_ops_t cpu_ops = {
791ae08745Sheppo 	fi_reg_handler,		/* ds_reg_cb */
801ae08745Sheppo 	fi_unreg_handler,	/* ds_unreg_cb */
811ae08745Sheppo 	cpu_data_handler,	/* ds_data_cb */
821ae08745Sheppo 	&cpu_handle		/* cb_arg */
831ae08745Sheppo };
841ae08745Sheppo 
851ae08745Sheppo static ds_clnt_ops_t mem_ops = {
861ae08745Sheppo 	fi_reg_handler,		/* ds_reg_cb */
871ae08745Sheppo 	fi_unreg_handler,	/* ds_unreg_cb */
881ae08745Sheppo 	mem_data_handler,	/* ds_data_cb */
891ae08745Sheppo 	&mem_handle		/* cb_arg */
901ae08745Sheppo };
911ae08745Sheppo 
921ae08745Sheppo static int fi_init(void);
931ae08745Sheppo static void fi_fini(void);
941ae08745Sheppo 
951ae08745Sheppo static struct modlmisc modlmisc = {
961ae08745Sheppo 	&mod_miscops,
97*f500b196SRichard Bean 	"sun4v Fault Isolation Services"
981ae08745Sheppo };
991ae08745Sheppo 
1001ae08745Sheppo static struct modlinkage modlinkage = {
1011ae08745Sheppo 	MODREV_1,
1021ae08745Sheppo 	(void *)&modlmisc,
1031ae08745Sheppo 	NULL
1041ae08745Sheppo };
1051ae08745Sheppo 
1061ae08745Sheppo int
_init(void)1071ae08745Sheppo _init(void)
1081ae08745Sheppo {
1091ae08745Sheppo 	int	rv;
1101ae08745Sheppo 
1111ae08745Sheppo 	if ((rv = fi_init()) != 0)
1121ae08745Sheppo 		return (rv);
1131ae08745Sheppo 
1141ae08745Sheppo 	if ((rv = mod_install(&modlinkage)) != 0)
1151ae08745Sheppo 		fi_fini();
1161ae08745Sheppo 
1171ae08745Sheppo 	return (rv);
1181ae08745Sheppo }
1191ae08745Sheppo 
1201ae08745Sheppo int
_info(struct modinfo * modinfop)1211ae08745Sheppo _info(struct modinfo *modinfop)
1221ae08745Sheppo {
1231ae08745Sheppo 	return (mod_info(&modlinkage, modinfop));
1241ae08745Sheppo }
1251ae08745Sheppo 
1261ae08745Sheppo int fi_allow_unload;
1271ae08745Sheppo 
1281ae08745Sheppo int
_fini(void)1291ae08745Sheppo _fini(void)
1301ae08745Sheppo {
1311ae08745Sheppo 	int	status;
1321ae08745Sheppo 
1331ae08745Sheppo 	if (fi_allow_unload == 0)
1341ae08745Sheppo 		return (EBUSY);
1351ae08745Sheppo 
1361ae08745Sheppo 	if ((status = mod_remove(&modlinkage)) == 0)
1371ae08745Sheppo 		fi_fini();
1381ae08745Sheppo 
1391ae08745Sheppo 	return (status);
1401ae08745Sheppo }
1411ae08745Sheppo 
1421ae08745Sheppo static int
fi_init(void)1431ae08745Sheppo fi_init(void)
1441ae08745Sheppo {
1451ae08745Sheppo 	int	rv;
1461ae08745Sheppo 
1471ae08745Sheppo 	/* register CPU service with domain services framework */
1481ae08745Sheppo 	rv = ds_cap_init(&cpu_cap, &cpu_ops);
1491ae08745Sheppo 	if (rv != 0) {
1501ae08745Sheppo 		FI_DBG(CE_CONT, "ds_cap_init failed: %d", rv);
1511ae08745Sheppo 		return (rv);
1521ae08745Sheppo 	}
1531ae08745Sheppo 
1541ae08745Sheppo 	/* register MEM servicewith domain services framework */
1551ae08745Sheppo 	rv = ds_cap_init(&mem_cap, &mem_ops);
1561ae08745Sheppo 	if (rv != 0) {
1571ae08745Sheppo 		FI_DBG(CE_CONT, "ds_cap_init failed: %d", rv);
1581ae08745Sheppo 		(void) ds_cap_fini(&cpu_cap);
1591ae08745Sheppo 		return (rv);
1601ae08745Sheppo 	}
1611ae08745Sheppo 
1621ae08745Sheppo 	return (rv);
1631ae08745Sheppo }
1641ae08745Sheppo 
1651ae08745Sheppo static void
fi_fini(void)1661ae08745Sheppo fi_fini(void)
1671ae08745Sheppo {
1681ae08745Sheppo 	/*
1691ae08745Sheppo 	 * Stop incoming requests from Zeus
1701ae08745Sheppo 	 */
1711ae08745Sheppo 	(void) ds_cap_fini(&cpu_cap);
1721ae08745Sheppo 	(void) ds_cap_fini(&mem_cap);
1731ae08745Sheppo }
1741ae08745Sheppo 
1751ae08745Sheppo static void
cpu_data_handler(ds_cb_arg_t arg,void * buf,size_t buflen)1761ae08745Sheppo cpu_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen)
1771ae08745Sheppo {
1781ae08745Sheppo 	_NOTE(ARGUNUSED(arg))
1791ae08745Sheppo 
1801ae08745Sheppo 	fma_cpu_service_req_t	*msg = buf;
1811ae08745Sheppo 	fma_cpu_resp_t		resp_msg;
1821ae08745Sheppo 	int			rv = 0;
1831ae08745Sheppo 	int			cpu_status;
1841ae08745Sheppo 	int			resp_back = 0;
1851ae08745Sheppo 
1861ae08745Sheppo 	/*
1871ae08745Sheppo 	 * If the buffer is the wrong size for CPU calls or is NULL then
1881ae08745Sheppo 	 * do not return any message. The call from the ldom mgr. will time out
1891ae08745Sheppo 	 * and the response will be NULL.
1901ae08745Sheppo 	 */
1911ae08745Sheppo 	if (msg == NULL || buflen != sizeof (fma_cpu_service_req_t)) {
1921ae08745Sheppo 		return;
1931ae08745Sheppo 	}
1941ae08745Sheppo 
1951ae08745Sheppo 	FI_DBG(CE_CONT, "req_num = %ld, msg_type = %d, cpu_id = %d\n",
1961ae08745Sheppo 	    msg->req_num, msg->msg_type, msg->cpu_id);
1971ae08745Sheppo 
1981ae08745Sheppo 	resp_msg.req_num = msg->req_num;
1991ae08745Sheppo 
2001ae08745Sheppo 	switch (msg->msg_type) {
2011ae08745Sheppo 	case FMA_CPU_REQ_STATUS:
2021ae08745Sheppo 		rv = p_online_internal(msg->cpu_id, P_STATUS,
2031ae08745Sheppo 		    &cpu_status);
2041ae08745Sheppo 		if (rv == EINVAL) {
2051ae08745Sheppo 			FI_DBG(CE_CONT, "Failed p_online call failed."
2061ae08745Sheppo 			    "Invalid CPU\n");
2071ae08745Sheppo 			resp_msg.result = FMA_CPU_RESP_FAILURE;
2081ae08745Sheppo 			resp_msg.status = FMA_CPU_STAT_ILLEGAL;
2091ae08745Sheppo 			resp_back = 1;
2101ae08745Sheppo 		}
2111ae08745Sheppo 		break;
2121ae08745Sheppo 	case FMA_CPU_REQ_OFFLINE:
213d10e4ef2Snarayan 		rv = p_online_internal(msg->cpu_id, P_FAULTED,
2141ae08745Sheppo 		    &cpu_status);
2151ae08745Sheppo 		if (rv == EINVAL) {
2161ae08745Sheppo 			FI_DBG(CE_CONT, "Failed p_online call failed."
2171ae08745Sheppo 			    "Invalid CPU\n");
2181ae08745Sheppo 			resp_msg.result = FMA_CPU_RESP_FAILURE;
2191ae08745Sheppo 			resp_msg.status = FMA_CPU_STAT_ILLEGAL;
2201ae08745Sheppo 			resp_back = 1;
2211ae08745Sheppo 		} else if (rv == EBUSY) {
2221ae08745Sheppo 			FI_DBG(CE_CONT, "Failed p_online call failed."
2231ae08745Sheppo 			    "Tried to offline while busy\n");
2241ae08745Sheppo 			resp_msg.result = FMA_CPU_RESP_FAILURE;
2251ae08745Sheppo 			resp_msg.status = FMA_CPU_STAT_ONLINE;
2261ae08745Sheppo 			resp_back = 1;
2271ae08745Sheppo 		}
2281ae08745Sheppo 		break;
2291ae08745Sheppo 	case FMA_CPU_REQ_ONLINE:
2301ae08745Sheppo 		rv = p_online_internal(msg->cpu_id, P_ONLINE,
2311ae08745Sheppo 		    &cpu_status);
2321ae08745Sheppo 		if (rv == EINVAL) {
2331ae08745Sheppo 			FI_DBG(CE_CONT, "Failed p_online call failed."
2341ae08745Sheppo 			    "Invalid CPU\n");
2351ae08745Sheppo 			resp_msg.result = FMA_CPU_RESP_FAILURE;
2361ae08745Sheppo 			resp_msg.status = FMA_CPU_STAT_ILLEGAL;
2371ae08745Sheppo 			resp_back = 1;
2381ae08745Sheppo 		} else if (rv == ENOTSUP) {
2391ae08745Sheppo 			FI_DBG(CE_CONT, "Failed p_online call failed."
2401ae08745Sheppo 			    "Online not supported for single CPU\n");
2411ae08745Sheppo 			resp_msg.result = FMA_CPU_RESP_FAILURE;
2421ae08745Sheppo 			resp_msg.status = FMA_CPU_STAT_OFFLINE;
2431ae08745Sheppo 			resp_back = 1;
2441ae08745Sheppo 		}
2451ae08745Sheppo 		break;
2461ae08745Sheppo 	default:
2471ae08745Sheppo 		/*
2481ae08745Sheppo 		 * If the msg_type was of unknown type simply return and
2491ae08745Sheppo 		 * have the ldom mgr. time out with a NULL response.
2501ae08745Sheppo 		 */
2511ae08745Sheppo 		return;
2521ae08745Sheppo 	}
2531ae08745Sheppo 
2541ae08745Sheppo 	if (rv != 0) {
2551ae08745Sheppo 		if (resp_back) {
2561ae08745Sheppo 			if ((rv = ds_cap_send(cpu_handle, &resp_msg,
2574f7823a1Snevin 			    sizeof (resp_msg))) != 0) {
2581ae08745Sheppo 				FI_DBG(CE_CONT, "ds_cap_send failed (%d)\n",
2591ae08745Sheppo 				    rv);
2601ae08745Sheppo 			}
2611ae08745Sheppo 			return;
2621ae08745Sheppo 		}
2631ae08745Sheppo 		ASSERT((rv == EINVAL) || ((rv == EBUSY) &&
2644f7823a1Snevin 		    (msg->msg_type == FMA_CPU_REQ_OFFLINE)) ||
2654f7823a1Snevin 		    ((rv == ENOTSUP) && (msg->msg_type == FMA_CPU_REQ_ONLINE)));
2661ae08745Sheppo 
2671ae08745Sheppo 		cmn_err(CE_WARN, "p_online_internal error not handled "
2681ae08745Sheppo 		    "rv = %d\n", rv);
2691ae08745Sheppo 	}
2701ae08745Sheppo 
2711ae08745Sheppo 	resp_msg.req_num = msg->req_num;
2721ae08745Sheppo 	resp_msg.result = FMA_CPU_RESP_OK;
2731ae08745Sheppo 
2741ae08745Sheppo 	switch (cpu_status) {
2751ae08745Sheppo 	case P_OFFLINE:
2761ae08745Sheppo 	case P_FAULTED:
2771ae08745Sheppo 	case P_POWEROFF:
2781ae08745Sheppo 	case P_SPARE:
2791ae08745Sheppo 		resp_msg.status = FMA_CPU_STAT_OFFLINE;
2801ae08745Sheppo 		break;
2811ae08745Sheppo 	case P_ONLINE:
2821ae08745Sheppo 	case P_NOINTR:
2831ae08745Sheppo 		resp_msg.status = FMA_CPU_STAT_ONLINE;
2841ae08745Sheppo 		break;
2851ae08745Sheppo 	default:
2861ae08745Sheppo 		resp_msg.status = FMA_CPU_STAT_ILLEGAL;
2871ae08745Sheppo 	}
2881ae08745Sheppo 
2891ae08745Sheppo 	if ((rv = ds_cap_send(cpu_handle, &resp_msg,
2901ae08745Sheppo 	    sizeof (resp_msg))) != 0) {
2911ae08745Sheppo 		FI_DBG(CE_CONT, "ds_cap_send failed (%d)\n", rv);
2921ae08745Sheppo 	}
2931ae08745Sheppo }
2941ae08745Sheppo 
2951ae08745Sheppo static void
mem_data_handler(ds_cb_arg_t arg,void * buf,size_t buflen)2961ae08745Sheppo mem_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen)
2971ae08745Sheppo {
2981ae08745Sheppo 	_NOTE(ARGUNUSED(arg))
2991ae08745Sheppo 
3001ae08745Sheppo 	fma_mem_service_req_t	*msg = buf;
3011ae08745Sheppo 	fma_mem_resp_t		resp_msg;
3021ae08745Sheppo 	int			rv = 0;
3031ae08745Sheppo 
3041ae08745Sheppo 	/*
3051ae08745Sheppo 	 * If the buffer is the wrong size for Mem calls or is NULL then
3061ae08745Sheppo 	 * do not return any message. The call from the ldom mgr. will time out
3071ae08745Sheppo 	 * and the response will be NULL.
3081ae08745Sheppo 	 */
3091ae08745Sheppo 	if (msg == NULL || buflen != sizeof (fma_mem_service_req_t)) {
3101ae08745Sheppo 		return;
3111ae08745Sheppo 	}
3121ae08745Sheppo 
3131ae08745Sheppo 	FI_DBG(CE_CONT, "req_num = %ld, msg_type = %d, memory addr = 0x%lx"
3141ae08745Sheppo 	"memory length = 0x%lx\n", msg->req_num, msg->msg_type,
3151ae08745Sheppo 	    msg->real_addr, msg->length);
3161ae08745Sheppo 
3171ae08745Sheppo 	resp_msg.req_num = msg->req_num;
3181ae08745Sheppo 	resp_msg.res_addr = msg->real_addr;
3191ae08745Sheppo 	resp_msg.res_length = msg->length;
3201ae08745Sheppo 
3211ae08745Sheppo 	/*
3221ae08745Sheppo 	 * Information about return values for page calls can be referenced
3231ae08745Sheppo 	 * in usr/src/uts/common/vm/page_retire.c
3241ae08745Sheppo 	 */
3251ae08745Sheppo 	switch (msg->msg_type) {
3261ae08745Sheppo 	case FMA_MEM_REQ_STATUS:
3271ae08745Sheppo 		rv = page_retire_check(msg->real_addr, NULL);
3281ae08745Sheppo 		switch (rv) {
3291ae08745Sheppo 		/* Page is retired */
3301ae08745Sheppo 		case 0:
3311ae08745Sheppo 			resp_msg.result = FMA_MEM_RESP_OK;
3321ae08745Sheppo 			resp_msg.status = FMA_MEM_STAT_RETIRED;
3331ae08745Sheppo 			break;
3341ae08745Sheppo 		/* Page is pending. Send back failure and not retired */
3351ae08745Sheppo 		case EAGAIN:
3361ae08745Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
3371ae08745Sheppo 			resp_msg.status = FMA_MEM_STAT_NOTRETIRED;
3381ae08745Sheppo 			break;
3391ae08745Sheppo 		/* Page is not retired. */
3401ae08745Sheppo 		case EIO:
3414f7823a1Snevin 			resp_msg.result = FMA_MEM_RESP_OK;
3421ae08745Sheppo 			resp_msg.status = FMA_MEM_STAT_NOTRETIRED;
3431ae08745Sheppo 			break;
3441ae08745Sheppo 		/* PA is not valid */
3451ae08745Sheppo 		case EINVAL:
3461ae08745Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
3471ae08745Sheppo 			resp_msg.status = FMA_MEM_STAT_ILLEGAL;
3481ae08745Sheppo 			break;
3491ae08745Sheppo 		default:
3501ae08745Sheppo 			ASSERT((rv == 0) || (rv == EAGAIN) || (rv == EIO) ||
3511ae08745Sheppo 			    (rv ==  EINVAL));
3521ae08745Sheppo 			cmn_err(CE_WARN, "fault_iso: return value from "
3531ae08745Sheppo 			    "page_retire_check invalid: %d\n", rv);
3541ae08745Sheppo 		}
3551ae08745Sheppo 		break;
3561ae08745Sheppo 	case FMA_MEM_REQ_RETIRE:
3571ae08745Sheppo 		rv = page_retire(msg->real_addr, PR_FMA);
3581ae08745Sheppo 		switch (rv) {
3591ae08745Sheppo 		/* Page retired successfully */
3601ae08745Sheppo 		case 0:
3611ae08745Sheppo 			resp_msg.result = FMA_MEM_RESP_OK;
3621ae08745Sheppo 			resp_msg.status = FMA_MEM_STAT_RETIRED;
3631ae08745Sheppo 			break;
3641ae08745Sheppo 		/* Tried to retire and now Pending retirement */
3651ae08745Sheppo 		case EAGAIN:
3661ae08745Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
3671ae08745Sheppo 			resp_msg.status = FMA_MEM_STAT_NOTRETIRED;
3681ae08745Sheppo 			break;
3691ae08745Sheppo 		/* Did not try to retire. Page already retired */
3701ae08745Sheppo 		case EIO:
3711ae08745Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
3721ae08745Sheppo 			resp_msg.status = FMA_MEM_STAT_RETIRED;
3731ae08745Sheppo 			break;
3741ae08745Sheppo 		/* PA is not valid */
3751ae08745Sheppo 		case EINVAL:
3761ae08745Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
3771ae08745Sheppo 			resp_msg.status = FMA_MEM_STAT_ILLEGAL;
3781ae08745Sheppo 			break;
3791ae08745Sheppo 		default:
3801ae08745Sheppo 			ASSERT((rv == 0) || (rv == EAGAIN) || (rv == EIO) ||
3811ae08745Sheppo 			    (rv ==  EINVAL));
3821ae08745Sheppo 			cmn_err(CE_WARN, "fault_iso: return value from "
3831ae08745Sheppo 			    "page_retire invalid: %d\n", rv);
3841ae08745Sheppo 		}
3851ae08745Sheppo 		break;
3861ae08745Sheppo 	case FMA_MEM_REQ_RESURRECT:
3871ae08745Sheppo 		rv = page_unretire(msg->real_addr);
3881ae08745Sheppo 		switch (rv) {
3891ae08745Sheppo 		/* Page succesfullly unretired */
3901ae08745Sheppo 		case 0:
3911ae08745Sheppo 			resp_msg.result = FMA_MEM_RESP_OK;
3921ae08745Sheppo 			resp_msg.status = FMA_MEM_STAT_NOTRETIRED;
3931ae08745Sheppo 			break;
3941ae08745Sheppo 		/* Page could not be locked. Still retired */
3951ae08745Sheppo 		case EAGAIN:
3961ae08745Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
3971ae08745Sheppo 			resp_msg.status = FMA_MEM_STAT_RETIRED;
3981ae08745Sheppo 			break;
3991ae08745Sheppo 		/* Page was not retired already */
4001ae08745Sheppo 		case EIO:
4011ae08745Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
4021ae08745Sheppo 			resp_msg.status = FMA_MEM_STAT_NOTRETIRED;
4031ae08745Sheppo 			break;
4041ae08745Sheppo 		/* PA is not valid */
4051ae08745Sheppo 		case EINVAL:
4061ae08745Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
4071ae08745Sheppo 			resp_msg.status = FMA_MEM_STAT_ILLEGAL;
4081ae08745Sheppo 			break;
4091ae08745Sheppo 		default:
4101ae08745Sheppo 			ASSERT((rv == 0) || (rv == EAGAIN) || (rv == EIO) ||
4111ae08745Sheppo 			    (rv ==  EINVAL));
4121ae08745Sheppo 			cmn_err(CE_WARN, "fault_iso: return value from "
4131ae08745Sheppo 			    "page_unretire invalid: %d\n", rv);
4141ae08745Sheppo 		}
4151ae08745Sheppo 		break;
4161ae08745Sheppo 	default:
4171ae08745Sheppo 		/*
4181ae08745Sheppo 		 * If the msg_type was of unknown type simply return and
4191ae08745Sheppo 		 * have the ldom mgr. time out with a NULL response.
4201ae08745Sheppo 		 */
4211ae08745Sheppo 		return;
4221ae08745Sheppo 	}
4231ae08745Sheppo 
4241ae08745Sheppo 	if ((rv = ds_cap_send(mem_handle, &resp_msg, sizeof (resp_msg))) != 0) {
4251ae08745Sheppo 		FI_DBG(CE_CONT, "ds_cap_send failed (%d)\n", rv);
4261ae08745Sheppo 	}
4271ae08745Sheppo }
4281ae08745Sheppo 
4291ae08745Sheppo static void
fi_reg_handler(ds_cb_arg_t arg,ds_ver_t * ver,ds_svc_hdl_t hdl)4301ae08745Sheppo fi_reg_handler(ds_cb_arg_t arg, ds_ver_t *ver, ds_svc_hdl_t hdl)
4311ae08745Sheppo {
4321ae08745Sheppo 	FI_DBG(CE_CONT, "fi_reg_handler: arg=0x%p, ver=%d.%d, hdl=0x%lx\n",
4331ae08745Sheppo 	    arg, ver->major, ver->minor, hdl);
4341ae08745Sheppo 
4351ae08745Sheppo 	if ((ds_svc_hdl_t *)arg == &cpu_handle)
4361ae08745Sheppo 		cpu_handle = hdl;
4371ae08745Sheppo 	if ((ds_svc_hdl_t *)arg == &mem_handle)
4381ae08745Sheppo 		mem_handle = hdl;
4391ae08745Sheppo }
4401ae08745Sheppo 
4411ae08745Sheppo static void
fi_unreg_handler(ds_cb_arg_t arg)4421ae08745Sheppo fi_unreg_handler(ds_cb_arg_t arg)
4431ae08745Sheppo {
4441ae08745Sheppo 	FI_DBG(CE_CONT, "fi_unreg_handler: arg=0x%p\n", arg);
4451ae08745Sheppo 
4461ae08745Sheppo 	if ((ds_svc_hdl_t *)arg == &cpu_handle)
4471ae08745Sheppo 		cpu_handle = DS_INVALID_HDL;
4481ae08745Sheppo 	if ((ds_svc_hdl_t *)arg == &mem_handle)
4491ae08745Sheppo 		mem_handle = DS_INVALID_HDL;
4501ae08745Sheppo }
451