xref: /onnv-gate/usr/src/uts/sun4v/io/fault_iso.c (revision 7799:05fc7b266484)
11991Sheppo /*
21991Sheppo  * CDDL HEADER START
31991Sheppo  *
41991Sheppo  * The contents of this file are subject to the terms of the
51991Sheppo  * Common Development and Distribution License (the "License").
61991Sheppo  * You may not use this file except in compliance with the License.
71991Sheppo  *
81991Sheppo  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91991Sheppo  * or http://www.opensolaris.org/os/licensing.
101991Sheppo  * See the License for the specific language governing permissions
111991Sheppo  * and limitations under the License.
121991Sheppo  *
131991Sheppo  * When distributing Covered Code, include this CDDL HEADER in each
141991Sheppo  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151991Sheppo  * If applicable, add the following below this CDDL HEADER, with the
161991Sheppo  * fields enclosed by brackets "[]" replaced with your own identifying
171991Sheppo  * information: Portions Copyright [yyyy] [name of copyright owner]
181991Sheppo  *
191991Sheppo  * CDDL HEADER END
201991Sheppo  */
211991Sheppo 
221991Sheppo /*
23*7799SRichard.Bean@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
241991Sheppo  * Use is subject to license terms.
251991Sheppo  */
261991Sheppo 
271991Sheppo /*
281991Sheppo  * sun4v Fault Isolation Services Module
291991Sheppo  */
301991Sheppo 
311991Sheppo #include <sys/modctl.h>
321991Sheppo #include <sys/cmn_err.h>
331991Sheppo #include <sys/machsystm.h>
341991Sheppo #include <sys/processor.h>
351991Sheppo #include <sys/mem.h>
361991Sheppo #include <vm/page.h>
371991Sheppo #include <sys/note.h>
381991Sheppo #include <sys/ds.h>
391991Sheppo #include <sys/fault_iso.h>
401991Sheppo 
411991Sheppo /*
421991Sheppo  * Debugging routines
431991Sheppo  */
441991Sheppo #ifdef DEBUG
451991Sheppo uint_t fi_debug = 0x0;
461991Sheppo #define	FI_DBG	if (fi_debug) cmn_err
471991Sheppo #else /* DEBUG */
481991Sheppo #define	FI_DBG	_NOTE(CONSTCOND) if (0) cmn_err
491991Sheppo #endif /* DEBUG */
501991Sheppo 
511991Sheppo /*
521991Sheppo  * Domains Services interaction
531991Sheppo  */
541991Sheppo static ds_svc_hdl_t	cpu_handle;
551991Sheppo static ds_svc_hdl_t	mem_handle;
561991Sheppo 
571991Sheppo static ds_ver_t		fi_vers[] = { { 1, 0 } };
581991Sheppo #define	FI_NVERS	(sizeof (fi_vers) / sizeof (fi_vers[0]))
591991Sheppo 
601991Sheppo static ds_capability_t cpu_cap = {
611991Sheppo 	"fma-cpu-service",	/* svc_id */
621991Sheppo 	fi_vers,		/* vers */
631991Sheppo 	FI_NVERS		/* nvers */
641991Sheppo };
651991Sheppo 
661991Sheppo static ds_capability_t mem_cap = {
671991Sheppo 	"fma-mem-service",	/* svc_id */
681991Sheppo 	fi_vers,		/* vers */
691991Sheppo 	FI_NVERS		/* nvers */
701991Sheppo };
711991Sheppo 
721991Sheppo static void fi_reg_handler(ds_cb_arg_t arg, ds_ver_t *ver, ds_svc_hdl_t hdl);
731991Sheppo static void fi_unreg_handler(ds_cb_arg_t arg);
741991Sheppo 
751991Sheppo static void cpu_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen);
761991Sheppo static void mem_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen);
771991Sheppo 
781991Sheppo static ds_clnt_ops_t cpu_ops = {
791991Sheppo 	fi_reg_handler,		/* ds_reg_cb */
801991Sheppo 	fi_unreg_handler,	/* ds_unreg_cb */
811991Sheppo 	cpu_data_handler,	/* ds_data_cb */
821991Sheppo 	&cpu_handle		/* cb_arg */
831991Sheppo };
841991Sheppo 
851991Sheppo static ds_clnt_ops_t mem_ops = {
861991Sheppo 	fi_reg_handler,		/* ds_reg_cb */
871991Sheppo 	fi_unreg_handler,	/* ds_unreg_cb */
881991Sheppo 	mem_data_handler,	/* ds_data_cb */
891991Sheppo 	&mem_handle		/* cb_arg */
901991Sheppo };
911991Sheppo 
921991Sheppo static int fi_init(void);
931991Sheppo static void fi_fini(void);
941991Sheppo 
951991Sheppo static struct modlmisc modlmisc = {
961991Sheppo 	&mod_miscops,
97*7799SRichard.Bean@Sun.COM 	"sun4v Fault Isolation Services"
981991Sheppo };
991991Sheppo 
1001991Sheppo static struct modlinkage modlinkage = {
1011991Sheppo 	MODREV_1,
1021991Sheppo 	(void *)&modlmisc,
1031991Sheppo 	NULL
1041991Sheppo };
1051991Sheppo 
1061991Sheppo int
_init(void)1071991Sheppo _init(void)
1081991Sheppo {
1091991Sheppo 	int	rv;
1101991Sheppo 
1111991Sheppo 	if ((rv = fi_init()) != 0)
1121991Sheppo 		return (rv);
1131991Sheppo 
1141991Sheppo 	if ((rv = mod_install(&modlinkage)) != 0)
1151991Sheppo 		fi_fini();
1161991Sheppo 
1171991Sheppo 	return (rv);
1181991Sheppo }
1191991Sheppo 
1201991Sheppo int
_info(struct modinfo * modinfop)1211991Sheppo _info(struct modinfo *modinfop)
1221991Sheppo {
1231991Sheppo 	return (mod_info(&modlinkage, modinfop));
1241991Sheppo }
1251991Sheppo 
1261991Sheppo int fi_allow_unload;
1271991Sheppo 
1281991Sheppo int
_fini(void)1291991Sheppo _fini(void)
1301991Sheppo {
1311991Sheppo 	int	status;
1321991Sheppo 
1331991Sheppo 	if (fi_allow_unload == 0)
1341991Sheppo 		return (EBUSY);
1351991Sheppo 
1361991Sheppo 	if ((status = mod_remove(&modlinkage)) == 0)
1371991Sheppo 		fi_fini();
1381991Sheppo 
1391991Sheppo 	return (status);
1401991Sheppo }
1411991Sheppo 
1421991Sheppo static int
fi_init(void)1431991Sheppo fi_init(void)
1441991Sheppo {
1451991Sheppo 	int	rv;
1461991Sheppo 
1471991Sheppo 	/* register CPU service with domain services framework */
1481991Sheppo 	rv = ds_cap_init(&cpu_cap, &cpu_ops);
1491991Sheppo 	if (rv != 0) {
1501991Sheppo 		FI_DBG(CE_CONT, "ds_cap_init failed: %d", rv);
1511991Sheppo 		return (rv);
1521991Sheppo 	}
1531991Sheppo 
1541991Sheppo 	/* register MEM servicewith domain services framework */
1551991Sheppo 	rv = ds_cap_init(&mem_cap, &mem_ops);
1561991Sheppo 	if (rv != 0) {
1571991Sheppo 		FI_DBG(CE_CONT, "ds_cap_init failed: %d", rv);
1581991Sheppo 		(void) ds_cap_fini(&cpu_cap);
1591991Sheppo 		return (rv);
1601991Sheppo 	}
1611991Sheppo 
1621991Sheppo 	return (rv);
1631991Sheppo }
1641991Sheppo 
1651991Sheppo static void
fi_fini(void)1661991Sheppo fi_fini(void)
1671991Sheppo {
1681991Sheppo 	/*
1691991Sheppo 	 * Stop incoming requests from Zeus
1701991Sheppo 	 */
1711991Sheppo 	(void) ds_cap_fini(&cpu_cap);
1721991Sheppo 	(void) ds_cap_fini(&mem_cap);
1731991Sheppo }
1741991Sheppo 
1751991Sheppo static void
cpu_data_handler(ds_cb_arg_t arg,void * buf,size_t buflen)1761991Sheppo cpu_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen)
1771991Sheppo {
1781991Sheppo 	_NOTE(ARGUNUSED(arg))
1791991Sheppo 
1801991Sheppo 	fma_cpu_service_req_t	*msg = buf;
1811991Sheppo 	fma_cpu_resp_t		resp_msg;
1821991Sheppo 	int			rv = 0;
1831991Sheppo 	int			cpu_status;
1841991Sheppo 	int			resp_back = 0;
1851991Sheppo 
1861991Sheppo 	/*
1871991Sheppo 	 * If the buffer is the wrong size for CPU calls or is NULL then
1881991Sheppo 	 * do not return any message. The call from the ldom mgr. will time out
1891991Sheppo 	 * and the response will be NULL.
1901991Sheppo 	 */
1911991Sheppo 	if (msg == NULL || buflen != sizeof (fma_cpu_service_req_t)) {
1921991Sheppo 		return;
1931991Sheppo 	}
1941991Sheppo 
1951991Sheppo 	FI_DBG(CE_CONT, "req_num = %ld, msg_type = %d, cpu_id = %d\n",
1961991Sheppo 	    msg->req_num, msg->msg_type, msg->cpu_id);
1971991Sheppo 
1981991Sheppo 	resp_msg.req_num = msg->req_num;
1991991Sheppo 
2001991Sheppo 	switch (msg->msg_type) {
2011991Sheppo 	case FMA_CPU_REQ_STATUS:
2021991Sheppo 		rv = p_online_internal(msg->cpu_id, P_STATUS,
2031991Sheppo 		    &cpu_status);
2041991Sheppo 		if (rv == EINVAL) {
2051991Sheppo 			FI_DBG(CE_CONT, "Failed p_online call failed."
2061991Sheppo 			    "Invalid CPU\n");
2071991Sheppo 			resp_msg.result = FMA_CPU_RESP_FAILURE;
2081991Sheppo 			resp_msg.status = FMA_CPU_STAT_ILLEGAL;
2091991Sheppo 			resp_back = 1;
2101991Sheppo 		}
2111991Sheppo 		break;
2121991Sheppo 	case FMA_CPU_REQ_OFFLINE:
2132336Snarayan 		rv = p_online_internal(msg->cpu_id, P_FAULTED,
2141991Sheppo 		    &cpu_status);
2151991Sheppo 		if (rv == EINVAL) {
2161991Sheppo 			FI_DBG(CE_CONT, "Failed p_online call failed."
2171991Sheppo 			    "Invalid CPU\n");
2181991Sheppo 			resp_msg.result = FMA_CPU_RESP_FAILURE;
2191991Sheppo 			resp_msg.status = FMA_CPU_STAT_ILLEGAL;
2201991Sheppo 			resp_back = 1;
2211991Sheppo 		} else if (rv == EBUSY) {
2221991Sheppo 			FI_DBG(CE_CONT, "Failed p_online call failed."
2231991Sheppo 			    "Tried to offline while busy\n");
2241991Sheppo 			resp_msg.result = FMA_CPU_RESP_FAILURE;
2251991Sheppo 			resp_msg.status = FMA_CPU_STAT_ONLINE;
2261991Sheppo 			resp_back = 1;
2271991Sheppo 		}
2281991Sheppo 		break;
2291991Sheppo 	case FMA_CPU_REQ_ONLINE:
2301991Sheppo 		rv = p_online_internal(msg->cpu_id, P_ONLINE,
2311991Sheppo 		    &cpu_status);
2321991Sheppo 		if (rv == EINVAL) {
2331991Sheppo 			FI_DBG(CE_CONT, "Failed p_online call failed."
2341991Sheppo 			    "Invalid CPU\n");
2351991Sheppo 			resp_msg.result = FMA_CPU_RESP_FAILURE;
2361991Sheppo 			resp_msg.status = FMA_CPU_STAT_ILLEGAL;
2371991Sheppo 			resp_back = 1;
2381991Sheppo 		} else if (rv == ENOTSUP) {
2391991Sheppo 			FI_DBG(CE_CONT, "Failed p_online call failed."
2401991Sheppo 			    "Online not supported for single CPU\n");
2411991Sheppo 			resp_msg.result = FMA_CPU_RESP_FAILURE;
2421991Sheppo 			resp_msg.status = FMA_CPU_STAT_OFFLINE;
2431991Sheppo 			resp_back = 1;
2441991Sheppo 		}
2451991Sheppo 		break;
2461991Sheppo 	default:
2471991Sheppo 		/*
2481991Sheppo 		 * If the msg_type was of unknown type simply return and
2491991Sheppo 		 * have the ldom mgr. time out with a NULL response.
2501991Sheppo 		 */
2511991Sheppo 		return;
2521991Sheppo 	}
2531991Sheppo 
2541991Sheppo 	if (rv != 0) {
2551991Sheppo 		if (resp_back) {
2561991Sheppo 			if ((rv = ds_cap_send(cpu_handle, &resp_msg,
2574419Snevin 			    sizeof (resp_msg))) != 0) {
2581991Sheppo 				FI_DBG(CE_CONT, "ds_cap_send failed (%d)\n",
2591991Sheppo 				    rv);
2601991Sheppo 			}
2611991Sheppo 			return;
2621991Sheppo 		}
2631991Sheppo 		ASSERT((rv == EINVAL) || ((rv == EBUSY) &&
2644419Snevin 		    (msg->msg_type == FMA_CPU_REQ_OFFLINE)) ||
2654419Snevin 		    ((rv == ENOTSUP) && (msg->msg_type == FMA_CPU_REQ_ONLINE)));
2661991Sheppo 
2671991Sheppo 		cmn_err(CE_WARN, "p_online_internal error not handled "
2681991Sheppo 		    "rv = %d\n", rv);
2691991Sheppo 	}
2701991Sheppo 
2711991Sheppo 	resp_msg.req_num = msg->req_num;
2721991Sheppo 	resp_msg.result = FMA_CPU_RESP_OK;
2731991Sheppo 
2741991Sheppo 	switch (cpu_status) {
2751991Sheppo 	case P_OFFLINE:
2761991Sheppo 	case P_FAULTED:
2771991Sheppo 	case P_POWEROFF:
2781991Sheppo 	case P_SPARE:
2791991Sheppo 		resp_msg.status = FMA_CPU_STAT_OFFLINE;
2801991Sheppo 		break;
2811991Sheppo 	case P_ONLINE:
2821991Sheppo 	case P_NOINTR:
2831991Sheppo 		resp_msg.status = FMA_CPU_STAT_ONLINE;
2841991Sheppo 		break;
2851991Sheppo 	default:
2861991Sheppo 		resp_msg.status = FMA_CPU_STAT_ILLEGAL;
2871991Sheppo 	}
2881991Sheppo 
2891991Sheppo 	if ((rv = ds_cap_send(cpu_handle, &resp_msg,
2901991Sheppo 	    sizeof (resp_msg))) != 0) {
2911991Sheppo 		FI_DBG(CE_CONT, "ds_cap_send failed (%d)\n", rv);
2921991Sheppo 	}
2931991Sheppo }
2941991Sheppo 
2951991Sheppo static void
mem_data_handler(ds_cb_arg_t arg,void * buf,size_t buflen)2961991Sheppo mem_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen)
2971991Sheppo {
2981991Sheppo 	_NOTE(ARGUNUSED(arg))
2991991Sheppo 
3001991Sheppo 	fma_mem_service_req_t	*msg = buf;
3011991Sheppo 	fma_mem_resp_t		resp_msg;
3021991Sheppo 	int			rv = 0;
3031991Sheppo 
3041991Sheppo 	/*
3051991Sheppo 	 * If the buffer is the wrong size for Mem calls or is NULL then
3061991Sheppo 	 * do not return any message. The call from the ldom mgr. will time out
3071991Sheppo 	 * and the response will be NULL.
3081991Sheppo 	 */
3091991Sheppo 	if (msg == NULL || buflen != sizeof (fma_mem_service_req_t)) {
3101991Sheppo 		return;
3111991Sheppo 	}
3121991Sheppo 
3131991Sheppo 	FI_DBG(CE_CONT, "req_num = %ld, msg_type = %d, memory addr = 0x%lx"
3141991Sheppo 	"memory length = 0x%lx\n", msg->req_num, msg->msg_type,
3151991Sheppo 	    msg->real_addr, msg->length);
3161991Sheppo 
3171991Sheppo 	resp_msg.req_num = msg->req_num;
3181991Sheppo 	resp_msg.res_addr = msg->real_addr;
3191991Sheppo 	resp_msg.res_length = msg->length;
3201991Sheppo 
3211991Sheppo 	/*
3221991Sheppo 	 * Information about return values for page calls can be referenced
3231991Sheppo 	 * in usr/src/uts/common/vm/page_retire.c
3241991Sheppo 	 */
3251991Sheppo 	switch (msg->msg_type) {
3261991Sheppo 	case FMA_MEM_REQ_STATUS:
3271991Sheppo 		rv = page_retire_check(msg->real_addr, NULL);
3281991Sheppo 		switch (rv) {
3291991Sheppo 		/* Page is retired */
3301991Sheppo 		case 0:
3311991Sheppo 			resp_msg.result = FMA_MEM_RESP_OK;
3321991Sheppo 			resp_msg.status = FMA_MEM_STAT_RETIRED;
3331991Sheppo 			break;
3341991Sheppo 		/* Page is pending. Send back failure and not retired */
3351991Sheppo 		case EAGAIN:
3361991Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
3371991Sheppo 			resp_msg.status = FMA_MEM_STAT_NOTRETIRED;
3381991Sheppo 			break;
3391991Sheppo 		/* Page is not retired. */
3401991Sheppo 		case EIO:
3414419Snevin 			resp_msg.result = FMA_MEM_RESP_OK;
3421991Sheppo 			resp_msg.status = FMA_MEM_STAT_NOTRETIRED;
3431991Sheppo 			break;
3441991Sheppo 		/* PA is not valid */
3451991Sheppo 		case EINVAL:
3461991Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
3471991Sheppo 			resp_msg.status = FMA_MEM_STAT_ILLEGAL;
3481991Sheppo 			break;
3491991Sheppo 		default:
3501991Sheppo 			ASSERT((rv == 0) || (rv == EAGAIN) || (rv == EIO) ||
3511991Sheppo 			    (rv ==  EINVAL));
3521991Sheppo 			cmn_err(CE_WARN, "fault_iso: return value from "
3531991Sheppo 			    "page_retire_check invalid: %d\n", rv);
3541991Sheppo 		}
3551991Sheppo 		break;
3561991Sheppo 	case FMA_MEM_REQ_RETIRE:
3571991Sheppo 		rv = page_retire(msg->real_addr, PR_FMA);
3581991Sheppo 		switch (rv) {
3591991Sheppo 		/* Page retired successfully */
3601991Sheppo 		case 0:
3611991Sheppo 			resp_msg.result = FMA_MEM_RESP_OK;
3621991Sheppo 			resp_msg.status = FMA_MEM_STAT_RETIRED;
3631991Sheppo 			break;
3641991Sheppo 		/* Tried to retire and now Pending retirement */
3651991Sheppo 		case EAGAIN:
3661991Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
3671991Sheppo 			resp_msg.status = FMA_MEM_STAT_NOTRETIRED;
3681991Sheppo 			break;
3691991Sheppo 		/* Did not try to retire. Page already retired */
3701991Sheppo 		case EIO:
3711991Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
3721991Sheppo 			resp_msg.status = FMA_MEM_STAT_RETIRED;
3731991Sheppo 			break;
3741991Sheppo 		/* PA is not valid */
3751991Sheppo 		case EINVAL:
3761991Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
3771991Sheppo 			resp_msg.status = FMA_MEM_STAT_ILLEGAL;
3781991Sheppo 			break;
3791991Sheppo 		default:
3801991Sheppo 			ASSERT((rv == 0) || (rv == EAGAIN) || (rv == EIO) ||
3811991Sheppo 			    (rv ==  EINVAL));
3821991Sheppo 			cmn_err(CE_WARN, "fault_iso: return value from "
3831991Sheppo 			    "page_retire invalid: %d\n", rv);
3841991Sheppo 		}
3851991Sheppo 		break;
3861991Sheppo 	case FMA_MEM_REQ_RESURRECT:
3871991Sheppo 		rv = page_unretire(msg->real_addr);
3881991Sheppo 		switch (rv) {
3891991Sheppo 		/* Page succesfullly unretired */
3901991Sheppo 		case 0:
3911991Sheppo 			resp_msg.result = FMA_MEM_RESP_OK;
3921991Sheppo 			resp_msg.status = FMA_MEM_STAT_NOTRETIRED;
3931991Sheppo 			break;
3941991Sheppo 		/* Page could not be locked. Still retired */
3951991Sheppo 		case EAGAIN:
3961991Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
3971991Sheppo 			resp_msg.status = FMA_MEM_STAT_RETIRED;
3981991Sheppo 			break;
3991991Sheppo 		/* Page was not retired already */
4001991Sheppo 		case EIO:
4011991Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
4021991Sheppo 			resp_msg.status = FMA_MEM_STAT_NOTRETIRED;
4031991Sheppo 			break;
4041991Sheppo 		/* PA is not valid */
4051991Sheppo 		case EINVAL:
4061991Sheppo 			resp_msg.result = FMA_MEM_RESP_FAILURE;
4071991Sheppo 			resp_msg.status = FMA_MEM_STAT_ILLEGAL;
4081991Sheppo 			break;
4091991Sheppo 		default:
4101991Sheppo 			ASSERT((rv == 0) || (rv == EAGAIN) || (rv == EIO) ||
4111991Sheppo 			    (rv ==  EINVAL));
4121991Sheppo 			cmn_err(CE_WARN, "fault_iso: return value from "
4131991Sheppo 			    "page_unretire invalid: %d\n", rv);
4141991Sheppo 		}
4151991Sheppo 		break;
4161991Sheppo 	default:
4171991Sheppo 		/*
4181991Sheppo 		 * If the msg_type was of unknown type simply return and
4191991Sheppo 		 * have the ldom mgr. time out with a NULL response.
4201991Sheppo 		 */
4211991Sheppo 		return;
4221991Sheppo 	}
4231991Sheppo 
4241991Sheppo 	if ((rv = ds_cap_send(mem_handle, &resp_msg, sizeof (resp_msg))) != 0) {
4251991Sheppo 		FI_DBG(CE_CONT, "ds_cap_send failed (%d)\n", rv);
4261991Sheppo 	}
4271991Sheppo }
4281991Sheppo 
4291991Sheppo static void
fi_reg_handler(ds_cb_arg_t arg,ds_ver_t * ver,ds_svc_hdl_t hdl)4301991Sheppo fi_reg_handler(ds_cb_arg_t arg, ds_ver_t *ver, ds_svc_hdl_t hdl)
4311991Sheppo {
4321991Sheppo 	FI_DBG(CE_CONT, "fi_reg_handler: arg=0x%p, ver=%d.%d, hdl=0x%lx\n",
4331991Sheppo 	    arg, ver->major, ver->minor, hdl);
4341991Sheppo 
4351991Sheppo 	if ((ds_svc_hdl_t *)arg == &cpu_handle)
4361991Sheppo 		cpu_handle = hdl;
4371991Sheppo 	if ((ds_svc_hdl_t *)arg == &mem_handle)
4381991Sheppo 		mem_handle = hdl;
4391991Sheppo }
4401991Sheppo 
4411991Sheppo static void
fi_unreg_handler(ds_cb_arg_t arg)4421991Sheppo fi_unreg_handler(ds_cb_arg_t arg)
4431991Sheppo {
4441991Sheppo 	FI_DBG(CE_CONT, "fi_unreg_handler: arg=0x%p\n", arg);
4451991Sheppo 
4461991Sheppo 	if ((ds_svc_hdl_t *)arg == &cpu_handle)
4471991Sheppo 		cpu_handle = DS_INVALID_HDL;
4481991Sheppo 	if ((ds_svc_hdl_t *)arg == &mem_handle)
4491991Sheppo 		mem_handle = DS_INVALID_HDL;
4501991Sheppo }
451