xref: /titanic_50/usr/src/uts/sun4v/os/mach_descrip.c (revision d2365b013d4199b49b3a1438d57aea23423e02ad)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * 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.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
211ae08745Sheppo 
227c478bd9Sstevel@tonic-gate /*
23*d2365b01SPavel Tatashin  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
271ae08745Sheppo /*
281ae08745Sheppo  * Kernel Machine Description (MD)
291ae08745Sheppo  *
301ae08745Sheppo  * The Kernel maintains a global copy of the machine description for
311ae08745Sheppo  * the system. This is for use by all kernel subsystems and is exported
321ae08745Sheppo  * to user applications through the the 'mdesc' device driver. It is
331ae08745Sheppo  * initially copied in from the Hypervisor at boot time, but can be
341ae08745Sheppo  * updated dynamically on demand. The Kernel provides an interface
351ae08745Sheppo  * for consumers to obtain a handle to the global MD. Consumers of the
361ae08745Sheppo  * MD must use the specified interfaces. An update interface is provided
371ae08745Sheppo  * for platform services to intiate an MD update on notification by a
381ae08745Sheppo  * service entity.
391ae08745Sheppo  *
401ae08745Sheppo  * Locks
411ae08745Sheppo  * The current global MD is protected by the curr_mach_descrip_lock.
421ae08745Sheppo  * Each Machine description has a lock to synchornize its ref count.
431ae08745Sheppo  * The Obsolete MD list is protected by the obs_list_lock.
441ae08745Sheppo  */
451ae08745Sheppo 
467c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
477c478bd9Sstevel@tonic-gate #include <sys/vm.h>
487c478bd9Sstevel@tonic-gate #include <sys/cpu.h>
497c478bd9Sstevel@tonic-gate #include <sys/intreg.h>
507c478bd9Sstevel@tonic-gate #include <sys/machcpuvar.h>
517c478bd9Sstevel@tonic-gate #include <sys/machparam.h>
527c478bd9Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
537c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h>
547c478bd9Sstevel@tonic-gate #include <sys/error.h>
557c478bd9Sstevel@tonic-gate #include <sys/hypervisor_api.h>
567c478bd9Sstevel@tonic-gate #include <sys/types.h>
577c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
581ae08745Sheppo #include <sys/mdesc.h>
591ae08745Sheppo #include <sys/mdesc_impl.h>
607c478bd9Sstevel@tonic-gate #include <sys/mach_descrip.h>
611ae08745Sheppo #include <sys/prom_plat.h>
621ae08745Sheppo #include <sys/promif.h>
634bac2208Snarayan #include <sys/ldoms.h>
641ae08745Sheppo 
651ae08745Sheppo static void *mach_descrip_strt_meta_alloc(size_t size);
661ae08745Sheppo static void mach_descrip_strt_meta_free(void *buf, size_t size);
671ae08745Sheppo static void *mach_descrip_strt_buf_alloc(size_t size, size_t align);
681ae08745Sheppo static void mach_descrip_strt_buf_free(void *buf, size_t size);
691ae08745Sheppo static void *mach_descrip_buf_alloc(size_t size, size_t align);
701ae08745Sheppo static void *mach_descrip_meta_alloc(size_t size);
711ae08745Sheppo static uint64_t mach_descrip_find_md_gen(caddr_t ptr);
721ae08745Sheppo static void init_md_params(void);
734bac2208Snarayan static void init_domaining_capabilities(md_t *mdp, mde_cookie_t *listp);
741ae08745Sheppo 
757c478bd9Sstevel@tonic-gate /*
761ae08745Sheppo  * Global ptr of the current generation Machine Description
777c478bd9Sstevel@tonic-gate  */
781ae08745Sheppo static machine_descrip_t *curr_mach_descrip;
797c478bd9Sstevel@tonic-gate 
801ae08745Sheppo /*
811ae08745Sheppo  * Initialized by machine_descrip_startup_init in startup.
821ae08745Sheppo  * machine_descript_init will reintialize the structure with
831ae08745Sheppo  * the vmem allocators once the vmem is available in the boot up
841ae08745Sheppo  * process.
851ae08745Sheppo  */
861ae08745Sheppo static machine_descrip_memops_t *curr_mach_descrip_memops = NULL;
877c478bd9Sstevel@tonic-gate 
881ae08745Sheppo static machine_descrip_memops_t startup_memops = {
891ae08745Sheppo 	mach_descrip_strt_buf_alloc,
901ae08745Sheppo 	mach_descrip_strt_buf_free,
911ae08745Sheppo 	mach_descrip_strt_meta_alloc,
921ae08745Sheppo 	mach_descrip_strt_meta_free,
931ae08745Sheppo };
947c478bd9Sstevel@tonic-gate 
951ae08745Sheppo static machine_descrip_memops_t mach_descrip_memops = {
961ae08745Sheppo 	mach_descrip_buf_alloc,
971ae08745Sheppo 	contig_mem_free,
981ae08745Sheppo 	mach_descrip_meta_alloc,
991ae08745Sheppo 	kmem_free,
1001ae08745Sheppo };
1011ae08745Sheppo 
1021ae08745Sheppo static kmutex_t curr_mach_descrip_lock;
1031ae08745Sheppo /*
1041ae08745Sheppo  * List of obsolete Machine Descriptions
1051ae08745Sheppo  * Machine descriptions that have users are put on this list
1061ae08745Sheppo  * and freed after the last user has called md_fini_handle.
1071ae08745Sheppo  */
1081ae08745Sheppo static machine_descrip_t *obs_machine_descrip_list;
1091ae08745Sheppo 
1101ae08745Sheppo static kmutex_t obs_list_lock;
1111ae08745Sheppo 
1121ae08745Sheppo static const char alloc_fail_msg[] =
1131ae08745Sheppo 	"MD: cannot allocate MD buffer of size %ld bytes\n";
1141ae08745Sheppo 
1151ae08745Sheppo /*
1164bac2208Snarayan  * Global flags that indicate what domaining features are
1174bac2208Snarayan  * available, if any. The value is set at boot time based on
1184bac2208Snarayan  * the value of the 'domaining-enabled' property in the MD
1194bac2208Snarayan  * and the global override flag below. Updates to this
1204bac2208Snarayan  * variable after boot are not supported.
1211ae08745Sheppo  */
1224bac2208Snarayan uint_t domaining_capabilities;
1231ae08745Sheppo 
1241ae08745Sheppo /*
1254bac2208Snarayan  * Global override for the 'domaining_capailities' flags. If this
1261ae08745Sheppo  * flag is set in /etc/system, domaining features are disabled,
1271ae08745Sheppo  * ignoring the value of the 'domaining-enabled' property in
1281ae08745Sheppo  * the MD.
1291ae08745Sheppo  */
1301ae08745Sheppo uint_t force_domaining_disabled;
1311ae08745Sheppo 
1329bb6917bSarao #define	META_ALLOC_ALIGN	8
1331ae08745Sheppo #define	HAS_GEN(x)	(x != MDESC_INVAL_GEN)
1341ae08745Sheppo 
1351ae08745Sheppo #ifdef DEBUG
1361ae08745Sheppo static int mach_descrip_debug = 0;
1371ae08745Sheppo 
1381ae08745Sheppo #define	MDP(ARGS)	if (mach_descrip_debug) prom_printf ARGS
1391ae08745Sheppo #define	PRINT_LIST() 	if (mach_descrip_debug) print_obs_list()
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate #ifdef	MACH_DESC_DEBUG
1427c478bd9Sstevel@tonic-gate static void
dump_buf(uint8_t * bufp,int size)1437c478bd9Sstevel@tonic-gate dump_buf(uint8_t *bufp, int size)
1447c478bd9Sstevel@tonic-gate {
1457c478bd9Sstevel@tonic-gate 	int i;
1467c478bd9Sstevel@tonic-gate 	for (i = 0; i < size; i += 16) {
1477c478bd9Sstevel@tonic-gate 		int j;
1487c478bd9Sstevel@tonic-gate 		prom_printf("0x%04x :", i);
1497c478bd9Sstevel@tonic-gate 		for (j = 0; j < 16 && (i+j) < size; j++)
1507c478bd9Sstevel@tonic-gate 			prom_printf(" %02x", bufp[i+j]);
1517c478bd9Sstevel@tonic-gate 		prom_printf("\n");
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate }
1541ae08745Sheppo #endif /* MACH_DESC_DEBUG */
1557c478bd9Sstevel@tonic-gate 
1561ae08745Sheppo static void
print_obs_list(void)1571ae08745Sheppo print_obs_list(void)
1587c478bd9Sstevel@tonic-gate {
1591ae08745Sheppo 	machine_descrip_t *lmdescp;
1601ae08745Sheppo 	mutex_enter(&obs_list_lock);
1611ae08745Sheppo 
1621ae08745Sheppo 	lmdescp	= obs_machine_descrip_list;
1631ae08745Sheppo 	prom_printf("MD_obs_list->");
1641ae08745Sheppo 	while (lmdescp != NULL) {
1651ae08745Sheppo 		prom_printf("g:%ld,r:%d", lmdescp->gen, lmdescp->refcnt);
1661ae08745Sheppo 
1671ae08745Sheppo 		lmdescp = lmdescp->next;
1681ae08745Sheppo 		prom_printf("->");
1691ae08745Sheppo 	}
1701ae08745Sheppo 	prom_printf("NULL\n");
1711ae08745Sheppo 	mutex_exit(&obs_list_lock);
1721ae08745Sheppo }
1731ae08745Sheppo 
1741ae08745Sheppo #else
1751ae08745Sheppo #define	MDP(ARGS)
1761ae08745Sheppo #define	PRINT_LIST()
1771ae08745Sheppo #endif /* DEBUG */
1781ae08745Sheppo 
1791ae08745Sheppo /*
1801ae08745Sheppo  * MD obsolete list managment functions
1811ae08745Sheppo  */
1821ae08745Sheppo static machine_descrip_t *
md_obs_list_look_up_by_gen(uint64_t gen)1831ae08745Sheppo md_obs_list_look_up_by_gen(uint64_t gen)
1841ae08745Sheppo {
1851ae08745Sheppo 	machine_descrip_t *mdescp;
1861ae08745Sheppo 
1871ae08745Sheppo 	mutex_enter(&obs_list_lock);
1881ae08745Sheppo 	mdescp = obs_machine_descrip_list;
1891ae08745Sheppo 
1901ae08745Sheppo 	while (mdescp != NULL) {
1911ae08745Sheppo 		if (mdescp->gen == gen) {
1921ae08745Sheppo 			mutex_exit(&obs_list_lock);
1931ae08745Sheppo 			return (mdescp);
1941ae08745Sheppo 		}
1951ae08745Sheppo 		mdescp = mdescp->next;
1961ae08745Sheppo 	}
1971ae08745Sheppo 
1981ae08745Sheppo 	mutex_exit(&obs_list_lock);
1991ae08745Sheppo 	return (mdescp);
2001ae08745Sheppo }
2011ae08745Sheppo 
2021ae08745Sheppo static void
md_obs_list_remove(machine_descrip_t * mdescp)2031ae08745Sheppo md_obs_list_remove(machine_descrip_t *mdescp)
2041ae08745Sheppo {
2051ae08745Sheppo 	machine_descrip_t *lmdescp;
2061ae08745Sheppo 
2071ae08745Sheppo 	mutex_enter(&obs_list_lock);
2081ae08745Sheppo 
2091ae08745Sheppo 	lmdescp	= obs_machine_descrip_list;
2101ae08745Sheppo 
2111ae08745Sheppo 	if (obs_machine_descrip_list == mdescp) {
2121ae08745Sheppo 		obs_machine_descrip_list = mdescp->next;
2131ae08745Sheppo 	} else {
2141ae08745Sheppo 		while (lmdescp != NULL) {
2151ae08745Sheppo 			if (lmdescp->next == mdescp) {
2161ae08745Sheppo 				lmdescp->next = mdescp->next;
2171ae08745Sheppo 				mdescp->next = NULL;
2181ae08745Sheppo 				break;
2191ae08745Sheppo 			}
2201ae08745Sheppo 			lmdescp = lmdescp->next;
2211ae08745Sheppo 		}
2221ae08745Sheppo 	}
2231ae08745Sheppo 	mutex_exit(&obs_list_lock);
2241ae08745Sheppo 	PRINT_LIST();
2251ae08745Sheppo }
2261ae08745Sheppo 
2271ae08745Sheppo static void
md_obs_list_add(machine_descrip_t * mdescp)2281ae08745Sheppo md_obs_list_add(machine_descrip_t *mdescp)
2291ae08745Sheppo {
2301ae08745Sheppo 	mutex_enter(&obs_list_lock);
2311ae08745Sheppo 
2321ae08745Sheppo 	mdescp->next = obs_machine_descrip_list;
2331ae08745Sheppo 	obs_machine_descrip_list = mdescp;
2341ae08745Sheppo 
2351ae08745Sheppo 	mutex_exit(&obs_list_lock);
2361ae08745Sheppo 	PRINT_LIST();
2371ae08745Sheppo }
2381ae08745Sheppo 
2391ae08745Sheppo /*
2401ae08745Sheppo  * Allocate a machine_descrip meta structure and intitialize it.
2411ae08745Sheppo  */
2421ae08745Sheppo static machine_descrip_t *
new_mach_descrip(void)2431ae08745Sheppo new_mach_descrip(void)
2441ae08745Sheppo {
2451ae08745Sheppo 	machine_descrip_t *mdescp;
2461ae08745Sheppo 
2471ae08745Sheppo 	mdescp = (machine_descrip_t *)(*curr_mach_descrip_memops->meta_allocp)
2481ae08745Sheppo 	    (sizeof (machine_descrip_t));
2491ae08745Sheppo 	if (mdescp != NULL) {
2501ae08745Sheppo 		bzero(mdescp, sizeof (*mdescp));
2511ae08745Sheppo 		mdescp->memops = curr_mach_descrip_memops;
2521ae08745Sheppo 		mutex_init(&mdescp->lock, NULL, MUTEX_DRIVER, NULL);
2531ae08745Sheppo 	}
2541ae08745Sheppo 
2551ae08745Sheppo 	return (mdescp);
2561ae08745Sheppo }
2571ae08745Sheppo 
2581ae08745Sheppo /*
2591ae08745Sheppo  * Free a machine_descrip meta structure and intitialize it.
2601ae08745Sheppo  * Also free the MD buffer.
2611ae08745Sheppo  */
2621ae08745Sheppo static void
destroy_machine_descrip(machine_descrip_t * mdescp)2631ae08745Sheppo destroy_machine_descrip(machine_descrip_t *mdescp)
2641ae08745Sheppo {
2651ae08745Sheppo 	machine_descrip_memops_t  *mdesc_memopsp;
2661ae08745Sheppo 
2671ae08745Sheppo 	ASSERT((mdescp != NULL));
2681ae08745Sheppo 
2691ae08745Sheppo 	mdesc_memopsp = mdescp->memops;
2701ae08745Sheppo 	if (mdescp->memops == NULL)
2711ae08745Sheppo 		panic("destroy_machine_descrip: memops NULL\n");
2721ae08745Sheppo 
2731ae08745Sheppo 	(*mdesc_memopsp->buf_freep)(mdescp->va, mdescp->space);
2741ae08745Sheppo 	mutex_destroy(&mdescp->lock);
2751ae08745Sheppo 	(*mdesc_memopsp->meta_freep)(mdescp, sizeof (*mdescp));
2761ae08745Sheppo }
2771ae08745Sheppo 
2781ae08745Sheppo /*
2791ae08745Sheppo  * Call into the Hypervisor to retrieve the most recent copy of the
2801ae08745Sheppo  * machine description. If references to the current MD are active
2811ae08745Sheppo  * stow it in the obsolete MD list and update the current MD reference
2821ae08745Sheppo  * with the new one.
2831ae08745Sheppo  * The obsolete list contains one MD per generation. If the firmware
2841ae08745Sheppo  * doesn't support MD generation fail the call.
2851ae08745Sheppo  */
2861ae08745Sheppo int
mach_descrip_update(void)2871ae08745Sheppo mach_descrip_update(void)
2881ae08745Sheppo {
2891ae08745Sheppo 	uint64_t	md_size0, md_size;
2901ae08745Sheppo 	uint64_t	md_space = 0;
2911ae08745Sheppo 	uint64_t	hvret;
2921ae08745Sheppo 	caddr_t		tbuf = NULL;
2931ae08745Sheppo 	uint64_t	tbuf_pa;
2941ae08745Sheppo 	uint64_t	tgen;
2951ae08745Sheppo 	int		ret = 0;
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	MDP(("MD: Requesting buffer size\n"));
2987c478bd9Sstevel@tonic-gate 
2991ae08745Sheppo 	ASSERT((curr_mach_descrip != NULL));
3001ae08745Sheppo 
3011ae08745Sheppo 	mutex_enter(&curr_mach_descrip_lock);
3027c478bd9Sstevel@tonic-gate 
303ea841a36Sarao 	/*
3041ae08745Sheppo 	 * If the required MD size changes between our first call
3051ae08745Sheppo 	 * to hv_mach_desc (to find the required buf size) and the
306d1a9c4c1Sjm22469 	 * second call (to get the actual MD) and our allocated
307d1a9c4c1Sjm22469 	 * memory is insufficient, loop until we have allocated
308d1a9c4c1Sjm22469 	 * sufficient space.
309ea841a36Sarao 	 */
3101ae08745Sheppo 	do {
3111ae08745Sheppo 		if (tbuf != NULL)
3121ae08745Sheppo 			(*curr_mach_descrip_memops->buf_freep)(tbuf, md_space);
3137c478bd9Sstevel@tonic-gate 
3141ae08745Sheppo 		md_size0 = 0LL;
3151ae08745Sheppo 		(void) hv_mach_desc((uint64_t)0, &md_size0);
3161ae08745Sheppo 		MDP(("MD: buffer size is %ld\n", md_size0));
3177c478bd9Sstevel@tonic-gate 
3181ae08745Sheppo 		/*
3191ae08745Sheppo 		 * Align allocated space to nearest page.
3201ae08745Sheppo 		 * contig_mem_alloc_align() requires a power of 2 alignment.
3211ae08745Sheppo 		 */
3221ae08745Sheppo 		md_space = P2ROUNDUP(md_size0, PAGESIZE);
3231ae08745Sheppo 		MDP(("MD: allocated space is %ld\n", md_space));
3247c478bd9Sstevel@tonic-gate 
3251ae08745Sheppo 		tbuf = (caddr_t)(*curr_mach_descrip_memops->buf_allocp)
3261ae08745Sheppo 		    (md_space, PAGESIZE);
3271ae08745Sheppo 		if (tbuf == NULL) {
3281ae08745Sheppo 			ret = -1;
3291ae08745Sheppo 			goto done;
3301ae08745Sheppo 		}
3317c478bd9Sstevel@tonic-gate 
3321ae08745Sheppo 		tbuf_pa =  va_to_pa(tbuf);
333d1a9c4c1Sjm22469 		md_size = md_space;
3341ae08745Sheppo 		hvret = hv_mach_desc(tbuf_pa, &md_size);
3351ae08745Sheppo 		MDP(("MD: HV return code = %ld\n", hvret));
3367c478bd9Sstevel@tonic-gate 
3371ae08745Sheppo 		/*
3381ae08745Sheppo 		 * We get H_EINVAL if our buffer size is too small. In
3391ae08745Sheppo 		 * that case stay in the loop, reallocate the buffer
3401ae08745Sheppo 		 * and try again.
3411ae08745Sheppo 		 */
3421ae08745Sheppo 		if (hvret != H_EOK && hvret != H_EINVAL) {
3431ae08745Sheppo 			MDP(("MD: Failed with code %ld from HV\n", hvret));
3441ae08745Sheppo 			ret = -1;
3451ae08745Sheppo 			goto done;
3461ae08745Sheppo 		}
3477c478bd9Sstevel@tonic-gate 
348d1a9c4c1Sjm22469 	} while (md_space < md_size);
3497c478bd9Sstevel@tonic-gate 
3501ae08745Sheppo 	tgen = mach_descrip_find_md_gen(tbuf);
3511ae08745Sheppo 
3521ae08745Sheppo #ifdef DEBUG
3531ae08745Sheppo 	if (!HAS_GEN(tgen)) {
3541ae08745Sheppo 		MDP(("MD: generation number not found\n"));
3551ae08745Sheppo 	} else
3561ae08745Sheppo 		MDP(("MD: generation number %ld\n", tgen));
3571ae08745Sheppo #endif /* DEBUG */
3581ae08745Sheppo 
3591ae08745Sheppo 	if (curr_mach_descrip->va != NULL) {
3601ae08745Sheppo 
3611ae08745Sheppo 		/* check for the same generation number */
3621ae08745Sheppo 		if (HAS_GEN(tgen) && ((curr_mach_descrip->gen == tgen) &&
3631ae08745Sheppo 		    (curr_mach_descrip->size == md_size))) {
3641ae08745Sheppo #ifdef DEBUG
3651ae08745Sheppo 			/*
3661ae08745Sheppo 			 * Pedantic Check for generation number. If the
3671ae08745Sheppo 			 * generation number is the same, make sure the
3681ae08745Sheppo 			 * MDs are really identical.
3691ae08745Sheppo 			 */
3701ae08745Sheppo 			if (bcmp(curr_mach_descrip->va, tbuf, md_size) != 0) {
3711ae08745Sheppo 				cmn_err(CE_WARN, "machine_descrip_update: MDs "
3721ae08745Sheppo 				    "with the same generation (%ld) are not "
3731ae08745Sheppo 				    "identical", tgen);
3741ae08745Sheppo 				ret = -1;
3751ae08745Sheppo 				goto done;
3761ae08745Sheppo 			}
3771ae08745Sheppo #endif
3781ae08745Sheppo 			ret = 0;
3791ae08745Sheppo 			goto done;
3801ae08745Sheppo 		}
3811ae08745Sheppo 
3821ae08745Sheppo 		/* check for generations moving backwards */
3831ae08745Sheppo 		if (HAS_GEN(tgen) && HAS_GEN(curr_mach_descrip->gen) &&
3841ae08745Sheppo 		    (curr_mach_descrip->gen > tgen)) {
3851ae08745Sheppo 			cmn_err(CE_WARN, "machine_descrip_update: new MD"
3861ae08745Sheppo 			    " older generation (%ld) than current MD (%ld)",
3871ae08745Sheppo 			    tgen, curr_mach_descrip->gen);
3881ae08745Sheppo 			ret = -1;
3891ae08745Sheppo 			goto done;
3901ae08745Sheppo 		}
3911ae08745Sheppo 
3921ae08745Sheppo 		if (curr_mach_descrip->refcnt == 0) {
3931ae08745Sheppo 
3941ae08745Sheppo 			MDP(("MD: freeing old md buffer gen %ld\n",
3951ae08745Sheppo 			    curr_mach_descrip->gen));
3961ae08745Sheppo 
3971ae08745Sheppo 			/* Free old space */
3981ae08745Sheppo 			ASSERT(curr_mach_descrip->space > 0);
3991ae08745Sheppo 
4001ae08745Sheppo 			(*curr_mach_descrip_memops->buf_freep)
4011ae08745Sheppo 			    (curr_mach_descrip->va, curr_mach_descrip->space);
4027c478bd9Sstevel@tonic-gate 		} else {
4031ae08745Sheppo 			if (!HAS_GEN(tgen)) {
4041ae08745Sheppo 				/*
4051ae08745Sheppo 				 * No update support if FW
4061ae08745Sheppo 				 * doesn't have MD generation id
4071ae08745Sheppo 				 * feature.
4081ae08745Sheppo 				 */
4091ae08745Sheppo 				prom_printf("WARNING: F/W does not support MD "
4101ae08745Sheppo 				    "generation count, MD update failed\n");
4111ae08745Sheppo 				ret = -1;
4121ae08745Sheppo 				goto done;
4131ae08745Sheppo 			}
4141ae08745Sheppo 
4151ae08745Sheppo 			MDP(("MD: adding to obs list %ld\n",
4161ae08745Sheppo 			    curr_mach_descrip->gen));
4171ae08745Sheppo 
4181ae08745Sheppo 			md_obs_list_add(curr_mach_descrip);
4191ae08745Sheppo 
4201ae08745Sheppo 			curr_mach_descrip = new_mach_descrip();
4211ae08745Sheppo 
4221ae08745Sheppo 			if (curr_mach_descrip == NULL) {
4231ae08745Sheppo 				panic("Allocation for machine description"
4241ae08745Sheppo 				    " failed\n");
4251ae08745Sheppo 			}
4261ae08745Sheppo 		}
4271ae08745Sheppo 	}
4281ae08745Sheppo 
4291ae08745Sheppo 	curr_mach_descrip->va = tbuf;
4301ae08745Sheppo 	curr_mach_descrip->gen = tgen;
4311ae08745Sheppo 	curr_mach_descrip->size = md_size;
4321ae08745Sheppo 	curr_mach_descrip->space = md_space;
4331ae08745Sheppo 
4347c478bd9Sstevel@tonic-gate #ifdef MACH_DESC_DEBUG
4351ae08745Sheppo 	dump_buf((uint8_t *)curr_mach_descrip->va, md_size);
4367c478bd9Sstevel@tonic-gate #endif /* MACH_DESC_DEBUG */
4377c478bd9Sstevel@tonic-gate 
4381ae08745Sheppo 	mutex_exit(&curr_mach_descrip_lock);
4391ae08745Sheppo 	return (ret);
4401ae08745Sheppo 
4411ae08745Sheppo done:
4421ae08745Sheppo 	if (tbuf != NULL)
4431ae08745Sheppo 		(*curr_mach_descrip_memops->buf_freep)(tbuf, md_space);
4441ae08745Sheppo 	mutex_exit(&curr_mach_descrip_lock);
4451ae08745Sheppo 	return (ret);
4461ae08745Sheppo }
4471ae08745Sheppo 
4481ae08745Sheppo static void *
mach_descrip_buf_alloc(size_t size,size_t align)4491ae08745Sheppo mach_descrip_buf_alloc(size_t size, size_t align)
4501ae08745Sheppo {
4511ae08745Sheppo 	void *p;
4521ae08745Sheppo 
4531ae08745Sheppo 	if ((p = contig_mem_alloc_align(size, align)) == NULL)
4541ae08745Sheppo 		cmn_err(CE_WARN, alloc_fail_msg, size);
4551ae08745Sheppo 
4561ae08745Sheppo 	return (p);
4571ae08745Sheppo }
4581ae08745Sheppo 
4591ae08745Sheppo static void *
mach_descrip_strt_meta_alloc(size_t size)4601ae08745Sheppo mach_descrip_strt_meta_alloc(size_t size)
4611ae08745Sheppo {
4629bb6917bSarao 	return (mach_descrip_strt_buf_alloc(size, META_ALLOC_ALIGN));
4631ae08745Sheppo }
4641ae08745Sheppo 
4651ae08745Sheppo static void
mach_descrip_strt_meta_free(void * buf,size_t size)4661ae08745Sheppo mach_descrip_strt_meta_free(void *buf, size_t size)
4671ae08745Sheppo {
4689bb6917bSarao 	mach_descrip_strt_buf_free(buf, size);
4691ae08745Sheppo }
4701ae08745Sheppo 
4711ae08745Sheppo static void *
mach_descrip_strt_buf_alloc(size_t size,size_t align)4721ae08745Sheppo mach_descrip_strt_buf_alloc(size_t size, size_t align)
4731ae08745Sheppo {
4741ae08745Sheppo 	void *p = prom_alloc((caddr_t)0, size, align);
4751ae08745Sheppo 
4761ae08745Sheppo 	if (p == NULL)
4771ae08745Sheppo 		prom_printf(alloc_fail_msg, size);
4781ae08745Sheppo 
4791ae08745Sheppo 	return (p);
4801ae08745Sheppo }
4811ae08745Sheppo 
4821ae08745Sheppo static void
mach_descrip_strt_buf_free(void * buf,size_t size)4831ae08745Sheppo mach_descrip_strt_buf_free(void *buf, size_t size)
4841ae08745Sheppo {
4851ae08745Sheppo 	prom_free((caddr_t)buf, size);
4861ae08745Sheppo }
4871ae08745Sheppo 
4881ae08745Sheppo static void *
mach_descrip_meta_alloc(size_t size)4891ae08745Sheppo mach_descrip_meta_alloc(size_t size)
4901ae08745Sheppo {
4911ae08745Sheppo 	return (kmem_alloc(size, KM_SLEEP));
4921ae08745Sheppo }
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate /*
4951ae08745Sheppo  * Initialize the kernel's Machine Description(MD) framework
4961ae08745Sheppo  * early on in startup during mlsetup() so consumers
4971ae08745Sheppo  * can get to the MD before the VM system has been initialized.
4981ae08745Sheppo  *
4991ae08745Sheppo  * Also get the most recent version of the MD.
5007c478bd9Sstevel@tonic-gate  */
5011ae08745Sheppo void
mach_descrip_startup_init(void)5021ae08745Sheppo mach_descrip_startup_init(void)
5031ae08745Sheppo {
5047c478bd9Sstevel@tonic-gate 
5051ae08745Sheppo 	mutex_init(&curr_mach_descrip_lock, NULL, MUTEX_DRIVER, NULL);
5061ae08745Sheppo 	mutex_init(&obs_list_lock, NULL, MUTEX_DRIVER, NULL);
5071ae08745Sheppo 
5081ae08745Sheppo 	obs_machine_descrip_list = NULL;
5091ae08745Sheppo 
5101ae08745Sheppo 	curr_mach_descrip_memops = &startup_memops;
5111ae08745Sheppo 
5121ae08745Sheppo 	curr_mach_descrip = new_mach_descrip();
5131ae08745Sheppo 	if (curr_mach_descrip == NULL)
5141ae08745Sheppo 		panic("Allocation for machine description failed\n");
5151ae08745Sheppo 
5161ae08745Sheppo 	if (mach_descrip_update())
5171ae08745Sheppo 		panic("Machine description initialization failed\n");
5181ae08745Sheppo 
5191ae08745Sheppo }
5201ae08745Sheppo 
5211ae08745Sheppo /*
5221ae08745Sheppo  * Counterpart to the above init function.  Free up resources
5231ae08745Sheppo  * allocated at startup by mach_descrip_startup_setup().
5241ae08745Sheppo  * And reset machine description framework state.
5251ae08745Sheppo  *
5261ae08745Sheppo  * All consumers must have fini'ed their handles at this point.
5271ae08745Sheppo  */
5281ae08745Sheppo void
mach_descrip_startup_fini(void)5291ae08745Sheppo mach_descrip_startup_fini(void)
5301ae08745Sheppo {
5311ae08745Sheppo 
5321ae08745Sheppo 	ASSERT((curr_mach_descrip != NULL));
5331ae08745Sheppo 	ASSERT((curr_mach_descrip->refcnt == 0));
5341ae08745Sheppo 	ASSERT((obs_machine_descrip_list == NULL));
5351ae08745Sheppo 
5361ae08745Sheppo 	destroy_machine_descrip(curr_mach_descrip);
5371ae08745Sheppo 	curr_mach_descrip = NULL;
5381ae08745Sheppo 	curr_mach_descrip_memops = NULL;
5391ae08745Sheppo }
5401ae08745Sheppo 
5411ae08745Sheppo /*
5421ae08745Sheppo  * Initialize the kernel's Machine Description(MD) framework
5431ae08745Sheppo  * after the the VM system has been initialized.
5441ae08745Sheppo  *
5451ae08745Sheppo  * Also get the most recent version of the MD.
5461ae08745Sheppo  * Assumes that the machine description frame work is in a clean
5471ae08745Sheppo  * state and the machine description intialized during startup
5481ae08745Sheppo  * has been cleaned up and resources deallocated.
5491ae08745Sheppo  */
5501ae08745Sheppo void
mach_descrip_init(void)5511ae08745Sheppo mach_descrip_init(void)
5521ae08745Sheppo {
5531ae08745Sheppo 	ASSERT((curr_mach_descrip == NULL &&
5541ae08745Sheppo 	    curr_mach_descrip_memops == NULL));
5551ae08745Sheppo 
5561ae08745Sheppo 	curr_mach_descrip_memops = &mach_descrip_memops;
5571ae08745Sheppo 
5581ae08745Sheppo 	curr_mach_descrip = new_mach_descrip();
5591ae08745Sheppo 	if (curr_mach_descrip == NULL)
5601ae08745Sheppo 		panic("Allocation for machine description failed\n");
5611ae08745Sheppo 
5621ae08745Sheppo 	if (mach_descrip_update())
5631ae08745Sheppo 		panic("Machine description intialization failed\n");
5641ae08745Sheppo 
5651ae08745Sheppo 	/* read in global params */
5661ae08745Sheppo 	init_md_params();
5671ae08745Sheppo }
5681ae08745Sheppo 
5691ae08745Sheppo /*
5701ae08745Sheppo  * Client interface to get a handle to the current MD.
5711ae08745Sheppo  * The md_fini_handle() interface should be used to
5721ae08745Sheppo  * clean up the refernce to the MD returned by this function.
5731ae08745Sheppo  */
5741ae08745Sheppo md_t *
md_get_handle(void)5751ae08745Sheppo md_get_handle(void)
5761ae08745Sheppo {
5771ae08745Sheppo 	md_t *mdp;
5781ae08745Sheppo 
579d1a9c4c1Sjm22469 	mdp = NULL;
580d1a9c4c1Sjm22469 
5811ae08745Sheppo 	mutex_enter(&curr_mach_descrip_lock);
5821ae08745Sheppo 
583d1a9c4c1Sjm22469 	if (curr_mach_descrip != NULL) {
5841ae08745Sheppo 
5851ae08745Sheppo 		mdp = md_init_intern(curr_mach_descrip->va,
5861ae08745Sheppo 		    curr_mach_descrip->memops->meta_allocp,
5871ae08745Sheppo 		    curr_mach_descrip->memops->meta_freep);
5881ae08745Sheppo 
589d1a9c4c1Sjm22469 		if (mdp != NULL)
590d1a9c4c1Sjm22469 			curr_mach_descrip->refcnt++;
591d1a9c4c1Sjm22469 	}
592d1a9c4c1Sjm22469 
5931ae08745Sheppo 	mutex_exit(&curr_mach_descrip_lock);
5941ae08745Sheppo 
5951ae08745Sheppo 	return (mdp);
5961ae08745Sheppo }
5971ae08745Sheppo 
5981ae08745Sheppo /*
5991ae08745Sheppo  * Client interface to clean up the refernce to the MD returned
6001ae08745Sheppo  * by md_get_handle().
6011ae08745Sheppo  */
6021ae08745Sheppo int
md_fini_handle(md_t * ptr)6031ae08745Sheppo md_fini_handle(md_t *ptr)
6041ae08745Sheppo {
6051ae08745Sheppo 	machine_descrip_t *mdescp;
6061ae08745Sheppo 	md_impl_t *mdp;
6071ae08745Sheppo 
6081ae08745Sheppo 
6091ae08745Sheppo 	mdp = (md_impl_t *)ptr;
6101ae08745Sheppo 
6111ae08745Sheppo 	if (mdp == NULL)
6121ae08745Sheppo 		return (-1);
6131ae08745Sheppo 	/*
6141ae08745Sheppo 	 * Check if mdp is current MD gen
6151ae08745Sheppo 	 */
6161ae08745Sheppo 	mutex_enter(&curr_mach_descrip_lock);
6171ae08745Sheppo 
6181ae08745Sheppo 	if (curr_mach_descrip->gen == mdp->gen) {
6191ae08745Sheppo 		curr_mach_descrip->refcnt--;
6201ae08745Sheppo 		mutex_exit(&curr_mach_descrip_lock);
6211ae08745Sheppo 		goto fini;
6221ae08745Sheppo 	}
6231ae08745Sheppo 	mutex_exit(&curr_mach_descrip_lock);
6241ae08745Sheppo 
6251ae08745Sheppo 	/*
6261ae08745Sheppo 	 * MD is in the obsolete list
6271ae08745Sheppo 	 */
6281ae08745Sheppo 	mdescp = md_obs_list_look_up_by_gen(mdp->gen);
6291ae08745Sheppo 	if (mdescp == NULL)
6301ae08745Sheppo 		return (-1);
6311ae08745Sheppo 
6321ae08745Sheppo 	mutex_enter(&mdescp->lock);
6331ae08745Sheppo 	mdescp->refcnt--;
6341ae08745Sheppo 	if (mdescp->refcnt == 0) {
6351ae08745Sheppo 		md_obs_list_remove(mdescp);
6361ae08745Sheppo 		mutex_exit(&mdescp->lock);
6371ae08745Sheppo 		destroy_machine_descrip(mdescp);
6381ae08745Sheppo 		goto fini;
6391ae08745Sheppo 	}
6401ae08745Sheppo 	mutex_exit(&mdescp->lock);
6411ae08745Sheppo 
6421ae08745Sheppo fini:
6431ae08745Sheppo 	return (md_fini(ptr));
6441ae08745Sheppo }
6451ae08745Sheppo 
6461ae08745Sheppo /*
6471ae08745Sheppo  * General purpose initialization function used to extract parameters
6481ae08745Sheppo  * from the MD during the boot process. This is called immediately after
6491ae08745Sheppo  * the in kernel copy of the MD has been initialized so that global
6501ae08745Sheppo  * flags are available to various subsystems as they get initialized.
6511ae08745Sheppo  */
6521ae08745Sheppo static void
init_md_params(void)6531ae08745Sheppo init_md_params(void)
6541ae08745Sheppo {
6551ae08745Sheppo 	md_t		*mdp;
6561ae08745Sheppo 	int		num_nodes;
6571ae08745Sheppo 	mde_cookie_t	*listp;
6581ae08745Sheppo 	int		listsz;
6591ae08745Sheppo 
6601ae08745Sheppo 	mdp = md_get_handle();
6611ae08745Sheppo 	ASSERT(mdp);
6621ae08745Sheppo 	num_nodes = md_node_count(mdp);
6631ae08745Sheppo 	ASSERT(num_nodes >= 0);
6641ae08745Sheppo 
6651ae08745Sheppo 	listsz = num_nodes * sizeof (mde_cookie_t);
6661ae08745Sheppo 	listp = (mde_cookie_t *)
6671ae08745Sheppo 	    (*curr_mach_descrip_memops->meta_allocp)(listsz);
6681ae08745Sheppo 
6691ae08745Sheppo 	/*
6701ae08745Sheppo 	 * Import various parameters from the MD. For now,
6711ae08745Sheppo 	 * the only parameter of interest is whether or not
6721ae08745Sheppo 	 * domaining features are supported.
6731ae08745Sheppo 	 */
6744bac2208Snarayan 	init_domaining_capabilities(mdp, listp);
6751ae08745Sheppo 
6761ae08745Sheppo 	(*curr_mach_descrip_memops->meta_freep)(listp, listsz);
6771ae08745Sheppo 	(void) md_fini_handle(mdp);
6781ae08745Sheppo }
6791ae08745Sheppo 
6801ae08745Sheppo static void
init_domaining_capabilities(md_t * mdp,mde_cookie_t * listp)6814bac2208Snarayan init_domaining_capabilities(md_t *mdp, mde_cookie_t *listp)
6821ae08745Sheppo {
6831ae08745Sheppo 	mde_cookie_t	rootnode;
6841ae08745Sheppo 	int		num_nodes;
6851ae08745Sheppo 	uint64_t	val = 0;
6861ae08745Sheppo 
6871ae08745Sheppo 	rootnode = md_root_node(mdp);
6881ae08745Sheppo 	ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE);
6891ae08745Sheppo 
6901ae08745Sheppo 	num_nodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "platform"),
6911ae08745Sheppo 	    md_find_name(mdp, "fwd"), listp);
6921ae08745Sheppo 
6931ae08745Sheppo 	/* should only be one platform node */
6941ae08745Sheppo 	ASSERT(num_nodes == 1);
6951ae08745Sheppo 
6961ae08745Sheppo 	if (md_get_prop_val(mdp, *listp, "domaining-enabled", &val) != 0) {
6971ae08745Sheppo 		/*
6981ae08745Sheppo 		 * The property is not present. This implies
6991ae08745Sheppo 		 * that the firmware does not support domaining
7001ae08745Sheppo 		 * features.
7011ae08745Sheppo 		 */
7021ae08745Sheppo 		MDP(("'domaining-enabled' property not present\n"));
7031ae08745Sheppo 
7044bac2208Snarayan 		domaining_capabilities = 0;
7051ae08745Sheppo 		return;
7061ae08745Sheppo 	}
7071ae08745Sheppo 
7084bac2208Snarayan 	domaining_capabilities = DOMAINING_SUPPORTED;
7091ae08745Sheppo 
7104bac2208Snarayan 	if (val == 1) {
7114bac2208Snarayan 		if (force_domaining_disabled) {
7124bac2208Snarayan 			MDP(("domaining manually disabled\n"));
7134bac2208Snarayan 		} else {
7144bac2208Snarayan 			domaining_capabilities |= DOMAINING_ENABLED;
7154bac2208Snarayan 		}
7164bac2208Snarayan 	}
7174bac2208Snarayan 
7184bac2208Snarayan 	MDP(("domaining_capabilities= 0x%x\n", domaining_capabilities));
7191ae08745Sheppo }
7201ae08745Sheppo 
7211ae08745Sheppo /*
7221ae08745Sheppo  * Client interface to get a pointer to the raw MD buffer
7231ae08745Sheppo  * Private to kernel and mdesc driver.
7241ae08745Sheppo  */
7251ae08745Sheppo caddr_t
md_get_md_raw(md_t * ptr)7261ae08745Sheppo md_get_md_raw(md_t *ptr)
7271ae08745Sheppo {
7281ae08745Sheppo 	md_impl_t *mdp;
7291ae08745Sheppo 
7301ae08745Sheppo 	mdp = (md_impl_t *)ptr;
7311ae08745Sheppo 	if (mdp ==  NULL)
7321ae08745Sheppo 		return (NULL);
7331ae08745Sheppo 	return (mdp->caddr);
7341ae08745Sheppo }
7351ae08745Sheppo 
7361ae08745Sheppo /*
7371ae08745Sheppo  * This is called before an MD structure is intialized, so
7381ae08745Sheppo  * it walks the raw MD looking for the generation property.
7391ae08745Sheppo  */
7401ae08745Sheppo static uint64_t
mach_descrip_find_md_gen(caddr_t ptr)7411ae08745Sheppo mach_descrip_find_md_gen(caddr_t ptr)
7421ae08745Sheppo {
7431ae08745Sheppo 	md_header_t	*hdrp;
7441ae08745Sheppo 	md_element_t	*mdep;
7451ae08745Sheppo 	md_element_t	*rootnode = NULL;
7461ae08745Sheppo 	md_element_t	*elem = NULL;
7471ae08745Sheppo 	char		*namep;
7481ae08745Sheppo 	boolean_t	done;
7491ae08745Sheppo 	int		idx;
7501ae08745Sheppo 
7511ae08745Sheppo 	hdrp = (md_header_t *)ptr;
7521ae08745Sheppo 	mdep = (md_element_t *)(ptr + MD_HEADER_SIZE);
7531ae08745Sheppo 	namep = (char *)(ptr + MD_HEADER_SIZE + hdrp->node_blk_sz);
7541ae08745Sheppo 
7551ae08745Sheppo 	/*
7561ae08745Sheppo 	 * Very basic check for alignment to avoid
7571ae08745Sheppo 	 * bus error issues.
7581ae08745Sheppo 	 */
7591ae08745Sheppo 	if ((((uint64_t)ptr) & 7) != 0)
7601ae08745Sheppo 		return (MDESC_INVAL_GEN);
7611ae08745Sheppo 
7621ae08745Sheppo 	if (mdtoh32(hdrp->transport_version) != MD_TRANSPORT_VERSION) {
7631ae08745Sheppo 		return (MDESC_INVAL_GEN);
7641ae08745Sheppo 	}
7651ae08745Sheppo 
7661ae08745Sheppo 	/*
7671ae08745Sheppo 	 * Search for the root node. Perform the walk manually
7681ae08745Sheppo 	 * since the MD structure is not set up yet.
7691ae08745Sheppo 	 */
7701ae08745Sheppo 	for (idx = 0, done = B_FALSE; done == B_FALSE; ) {
7711ae08745Sheppo 
7721ae08745Sheppo 		md_element_t *np = &(mdep[idx]);
7731ae08745Sheppo 
7741ae08745Sheppo 		switch (MDE_TAG(np)) {
7751ae08745Sheppo 		case MDET_LIST_END:
7761ae08745Sheppo 			done = B_TRUE;
7771ae08745Sheppo 			break;
7781ae08745Sheppo 
7791ae08745Sheppo 		case MDET_NODE:
7801ae08745Sheppo 			if (strcmp(namep + MDE_NAME(np), "root") == 0) {
7811ae08745Sheppo 				/* found root node */
7821ae08745Sheppo 				rootnode = np;
7831ae08745Sheppo 				done = B_TRUE;
7841ae08745Sheppo 				break;
7851ae08745Sheppo 			}
7861ae08745Sheppo 			idx = MDE_PROP_INDEX(np);
7871ae08745Sheppo 			break;
7881ae08745Sheppo 
7891ae08745Sheppo 		default:
7901ae08745Sheppo 			/* ignore */
7911ae08745Sheppo 			idx++;
7927c478bd9Sstevel@tonic-gate 		}
7937c478bd9Sstevel@tonic-gate 	}
7941ae08745Sheppo 
7951ae08745Sheppo 	if (rootnode == NULL) {
7961ae08745Sheppo 		/* root not found */
7971ae08745Sheppo 		return (MDESC_INVAL_GEN);
7981ae08745Sheppo 	}
7991ae08745Sheppo 
8001ae08745Sheppo 	/* search the rootnode for the generation property */
8011ae08745Sheppo 	for (elem = (rootnode + 1); MDE_TAG(elem) != MDET_NODE_END; elem++) {
8021ae08745Sheppo 
8031ae08745Sheppo 		char *prop_name;
8041ae08745Sheppo 
8051ae08745Sheppo 		/* generation field is a prop_val */
8061ae08745Sheppo 		if (MDE_TAG(elem) != MDET_PROP_VAL)
8071ae08745Sheppo 			continue;
8081ae08745Sheppo 
8091ae08745Sheppo 		prop_name = namep + MDE_NAME(elem);
8101ae08745Sheppo 
8111ae08745Sheppo 		if (strcmp(prop_name, "md-generation#") == 0) {
8121ae08745Sheppo 			return (MDE_PROP_VALUE(elem));
8131ae08745Sheppo 		}
8141ae08745Sheppo 	}
8151ae08745Sheppo 
8161ae08745Sheppo 	return (MDESC_INVAL_GEN);
8171ae08745Sheppo }
8181ae08745Sheppo 
8191ae08745Sheppo /*
8201ae08745Sheppo  * Failed to allocate the list : Return value -1
8211ae08745Sheppo  * md_scan_dag API failed      : Return the result from md_scan_dag API
8221ae08745Sheppo  */
8231ae08745Sheppo int
md_alloc_scan_dag(md_t * ptr,mde_cookie_t startnode,char * node_name,char * dag,mde_cookie_t ** list)8241ae08745Sheppo md_alloc_scan_dag(md_t *ptr,
8251ae08745Sheppo 	mde_cookie_t startnode,
8261ae08745Sheppo 	char *node_name,
8271ae08745Sheppo 	char *dag,
8281ae08745Sheppo 	mde_cookie_t **list)
8291ae08745Sheppo {
8301ae08745Sheppo 	int res;
8311ae08745Sheppo 	md_impl_t *mdp = (md_impl_t *)ptr;
8321ae08745Sheppo 
8331ae08745Sheppo 	*list = (mde_cookie_t *)mdp->allocp(sizeof (mde_cookie_t) *
8341ae08745Sheppo 	    mdp->node_count);
8351ae08745Sheppo 	if (*list == NULL)
8361ae08745Sheppo 		return (-1);
8371ae08745Sheppo 
8381ae08745Sheppo 	res = md_scan_dag(ptr, startnode,
8391ae08745Sheppo 	    md_find_name(ptr, node_name),
8401ae08745Sheppo 	    md_find_name(ptr, dag), *list);
8411ae08745Sheppo 
8421ae08745Sheppo 	/*
8431ae08745Sheppo 	 * If md_scan_dag API returned 0 or -1 then free the buffer
8441ae08745Sheppo 	 * and return -1 to indicate the error from this API.
8451ae08745Sheppo 	 */
8461ae08745Sheppo 	if (res < 1) {
8471ae08745Sheppo 		md_free_scan_dag(ptr, list);
8481ae08745Sheppo 		*list = NULL;
8491ae08745Sheppo 	}
8501ae08745Sheppo 
8511ae08745Sheppo 	return (res);
8521ae08745Sheppo }
8531ae08745Sheppo 
8541ae08745Sheppo void
md_free_scan_dag(md_t * ptr,mde_cookie_t ** list)8551ae08745Sheppo md_free_scan_dag(md_t *ptr,
8561ae08745Sheppo 	mde_cookie_t **list)
8571ae08745Sheppo {
8581ae08745Sheppo 	md_impl_t *mdp = (md_impl_t *)ptr;
8591ae08745Sheppo 
8601ae08745Sheppo 	mdp->freep(*list, sizeof (mde_cookie_t) * mdp->node_count);
8617c478bd9Sstevel@tonic-gate }
862*d2365b01SPavel Tatashin 
863*d2365b01SPavel Tatashin /*
864*d2365b01SPavel Tatashin  * Return generation number of current machine descriptor. Can be used for
865*d2365b01SPavel Tatashin  * performance purposes to avoid requesting new md handle just to see if graph
866*d2365b01SPavel Tatashin  * was updated.
867*d2365b01SPavel Tatashin  */
868*d2365b01SPavel Tatashin uint64_t
md_get_current_gen(void)869*d2365b01SPavel Tatashin md_get_current_gen(void)
870*d2365b01SPavel Tatashin {
871*d2365b01SPavel Tatashin 	uint64_t gen = MDESC_INVAL_GEN;
872*d2365b01SPavel Tatashin 
873*d2365b01SPavel Tatashin 	mutex_enter(&curr_mach_descrip_lock);
874*d2365b01SPavel Tatashin 
875*d2365b01SPavel Tatashin 	if (curr_mach_descrip != NULL)
876*d2365b01SPavel Tatashin 		gen = (curr_mach_descrip->gen);
877*d2365b01SPavel Tatashin 
878*d2365b01SPavel Tatashin 	mutex_exit(&curr_mach_descrip_lock);
879*d2365b01SPavel Tatashin 
880*d2365b01SPavel Tatashin 	return (gen);
881*d2365b01SPavel Tatashin }
882