xref: /illumos-gate/usr/src/uts/common/os/pool_pset.c (revision c3377ee9)
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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
27*c3377ee9SJohn Levon /*
28*c3377ee9SJohn Levon  * Copyright 2019 Joyent, Inc.
29*c3377ee9SJohn Levon  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <sys/pool.h>
327c478bd9Sstevel@tonic-gate #include <sys/pool_impl.h>
337c478bd9Sstevel@tonic-gate #include <sys/pool_pset.h>
347c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
357c478bd9Sstevel@tonic-gate #include <sys/cpupart.h>
367c478bd9Sstevel@tonic-gate #include <sys/mutex.h>
377c478bd9Sstevel@tonic-gate #include <sys/errno.h>
387c478bd9Sstevel@tonic-gate #include <sys/systm.h>
397c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
407c478bd9Sstevel@tonic-gate #include <sys/fss.h>
417c478bd9Sstevel@tonic-gate #include <sys/exacct.h>
427c478bd9Sstevel@tonic-gate #include <sys/time.h>
437c478bd9Sstevel@tonic-gate #include <sys/policy.h>
447c478bd9Sstevel@tonic-gate #include <sys/class.h>
457c478bd9Sstevel@tonic-gate #include <sys/list.h>
467c478bd9Sstevel@tonic-gate #include <sys/cred.h>
477c478bd9Sstevel@tonic-gate #include <sys/zone.h>
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate /*
507c478bd9Sstevel@tonic-gate  * Processor set plugin for pools.
517c478bd9Sstevel@tonic-gate  *
527c478bd9Sstevel@tonic-gate  * This file contains various routines used by the common pools layer to create,
537c478bd9Sstevel@tonic-gate  * modify, and destroy processor sets.  All processor sets created by this
547c478bd9Sstevel@tonic-gate  * plug-in are stored in the pool_pset_list doubly-linked list, which is
557c478bd9Sstevel@tonic-gate  * guaranteed to always have an entry for the default processor set,
567c478bd9Sstevel@tonic-gate  * pool_pset_default.
577c478bd9Sstevel@tonic-gate  *
587c478bd9Sstevel@tonic-gate  * Interaction with zones:
597c478bd9Sstevel@tonic-gate  *
607c478bd9Sstevel@tonic-gate  * If pools are enabled, non-global zones only have visibility into the
617c478bd9Sstevel@tonic-gate  * pset of the pool to which they are bound.  This is accomplished by
627c478bd9Sstevel@tonic-gate  * changing the set of processors and processor sets which are visible
637c478bd9Sstevel@tonic-gate  * through both systemcall interfaces and system kstats.
647c478bd9Sstevel@tonic-gate  *
657c478bd9Sstevel@tonic-gate  * To avoid grabbing pool_lock() during cpu change operations, we cache
667c478bd9Sstevel@tonic-gate  * the pset the zone is currently bound to, and can read this value
677c478bd9Sstevel@tonic-gate  * while under cpu_lock.  The special psetid_t token ZONE_PS_INVAL means
687c478bd9Sstevel@tonic-gate  * that pools are disabled, and provides a mechanism for determining if the
697c478bd9Sstevel@tonic-gate  * status of pools without grabbing pool_lock().
707c478bd9Sstevel@tonic-gate  *
717c478bd9Sstevel@tonic-gate  * To avoid grabbing any locks to determine the instantaneous value of
727c478bd9Sstevel@tonic-gate  * the number of configured and online cpus in the zone, we also cache
737c478bd9Sstevel@tonic-gate  * these values in a zone_t.  If these values are zero, the pools
747c478bd9Sstevel@tonic-gate  * facility must be disabled, in which case relevant systemcall
757c478bd9Sstevel@tonic-gate  * interfaces will return the values for the system as a whole.
767c478bd9Sstevel@tonic-gate  *
777c478bd9Sstevel@tonic-gate  * The various kstat interfaces are dealt with as follows: if pools are
787c478bd9Sstevel@tonic-gate  * disabled all cpu-related kstats should be exported to all zones.
797c478bd9Sstevel@tonic-gate  * When pools are enabled we begin maintaining a list of "permitted
807c478bd9Sstevel@tonic-gate  * zones" on a per-kstat basis.  There are various hooks throughout the
817c478bd9Sstevel@tonic-gate  * code to update this list when certain pools- or cpu-related events
827c478bd9Sstevel@tonic-gate  * occur.
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate static list_t pool_pset_list;	/* doubly-linked list of psets */
867c478bd9Sstevel@tonic-gate pool_pset_t *pool_pset_default;	/* default pset */
877c478bd9Sstevel@tonic-gate hrtime_t pool_pset_mod;		/* last modification time for psets */
887c478bd9Sstevel@tonic-gate hrtime_t pool_cpu_mod;		/* last modification time for CPUs */
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate static pool_pset_t *
pool_lookup_pset_by_id(psetid_t psetid)917c478bd9Sstevel@tonic-gate pool_lookup_pset_by_id(psetid_t psetid)
927c478bd9Sstevel@tonic-gate {
937c478bd9Sstevel@tonic-gate 	pool_pset_t *pset = pool_pset_default;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	for (pset = list_head(&pool_pset_list); pset;
987c478bd9Sstevel@tonic-gate 	    pset = list_next(&pool_pset_list, pset)) {
997c478bd9Sstevel@tonic-gate 		if (pset->pset_id == psetid)
1007c478bd9Sstevel@tonic-gate 			return (pset);
1017c478bd9Sstevel@tonic-gate 	}
1027c478bd9Sstevel@tonic-gate 	return (NULL);
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate struct setup_arg {
1067c478bd9Sstevel@tonic-gate 	psetid_t psetid;
1077c478bd9Sstevel@tonic-gate 	cpu_t *cpu;
1087c478bd9Sstevel@tonic-gate 	cpu_setup_t what;
1097c478bd9Sstevel@tonic-gate };
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate /*
1127c478bd9Sstevel@tonic-gate  * Callback function used to apply a cpu configuration event to a zone.
1137c478bd9Sstevel@tonic-gate  */
1147c478bd9Sstevel@tonic-gate static int
pool_pset_setup_cb(zone_t * zone,void * arg)1157c478bd9Sstevel@tonic-gate pool_pset_setup_cb(zone_t *zone, void *arg)
1167c478bd9Sstevel@tonic-gate {
1177c478bd9Sstevel@tonic-gate 	struct setup_arg *sa = arg;
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock));
1207c478bd9Sstevel@tonic-gate 	ASSERT(INGLOBALZONE(curproc));
1217c478bd9Sstevel@tonic-gate 	ASSERT(zone != NULL);
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	if (zone == global_zone)
1247c478bd9Sstevel@tonic-gate 		return (0);
1257c478bd9Sstevel@tonic-gate 	if (zone_pset_get(zone) != sa->psetid)
1267c478bd9Sstevel@tonic-gate 		return (0);	/* ignore */
1277c478bd9Sstevel@tonic-gate 	switch (sa->what) {
1287c478bd9Sstevel@tonic-gate 	case CPU_CONFIG:
1297c478bd9Sstevel@tonic-gate 		cpu_visibility_configure(sa->cpu, zone);
1307c478bd9Sstevel@tonic-gate 		break;
1317c478bd9Sstevel@tonic-gate 	case CPU_UNCONFIG:
1327c478bd9Sstevel@tonic-gate 		cpu_visibility_unconfigure(sa->cpu, zone);
1337c478bd9Sstevel@tonic-gate 		break;
1347c478bd9Sstevel@tonic-gate 	case CPU_ON:
1357c478bd9Sstevel@tonic-gate 		cpu_visibility_online(sa->cpu, zone);
1367c478bd9Sstevel@tonic-gate 		break;
1377c478bd9Sstevel@tonic-gate 	case CPU_OFF:
1387c478bd9Sstevel@tonic-gate 		cpu_visibility_offline(sa->cpu, zone);
1397c478bd9Sstevel@tonic-gate 		break;
1407c478bd9Sstevel@tonic-gate 	case CPU_CPUPART_IN:
1417c478bd9Sstevel@tonic-gate 		cpu_visibility_add(sa->cpu, zone);
1427c478bd9Sstevel@tonic-gate 		break;
1437c478bd9Sstevel@tonic-gate 	case CPU_CPUPART_OUT:
1447c478bd9Sstevel@tonic-gate 		cpu_visibility_remove(sa->cpu, zone);
1457c478bd9Sstevel@tonic-gate 		break;
1467c478bd9Sstevel@tonic-gate 	default:
1477c478bd9Sstevel@tonic-gate 		cmn_err(CE_PANIC, "invalid cpu_setup_t value %d", sa->what);
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 	return (0);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate /*
1537c478bd9Sstevel@tonic-gate  * Callback function to be executed when a noteworthy cpu event takes
1547c478bd9Sstevel@tonic-gate  * place.  Will ensure that the event is reflected by the zones which
1557c478bd9Sstevel@tonic-gate  * were affected by it.
1567c478bd9Sstevel@tonic-gate  */
1577c478bd9Sstevel@tonic-gate /* ARGSUSED */
1587c478bd9Sstevel@tonic-gate static int
pool_pset_cpu_setup(cpu_setup_t what,int id,void * arg)1597c478bd9Sstevel@tonic-gate pool_pset_cpu_setup(cpu_setup_t what, int id, void *arg)
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate 	processorid_t cpuid = id;
1627c478bd9Sstevel@tonic-gate 	struct setup_arg sarg;
1637c478bd9Sstevel@tonic-gate 	int error;
1647c478bd9Sstevel@tonic-gate 	cpu_t *c;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock));
1677c478bd9Sstevel@tonic-gate 	ASSERT(INGLOBALZONE(curproc));
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	if (!pool_pset_enabled())
1707c478bd9Sstevel@tonic-gate 		return (0);
1717c478bd9Sstevel@tonic-gate 	if (what != CPU_CONFIG && what != CPU_UNCONFIG &&
1727c478bd9Sstevel@tonic-gate 	    what != CPU_ON && what != CPU_OFF &&
1737c478bd9Sstevel@tonic-gate 	    what != CPU_CPUPART_IN && what != CPU_CPUPART_OUT)
1747c478bd9Sstevel@tonic-gate 		return (0);
1757c478bd9Sstevel@tonic-gate 	c = cpu_get(cpuid);
1767c478bd9Sstevel@tonic-gate 	ASSERT(c != NULL);
1777c478bd9Sstevel@tonic-gate 	sarg.psetid = cpupart_query_cpu(c);
1787c478bd9Sstevel@tonic-gate 	sarg.cpu = c;
1797c478bd9Sstevel@tonic-gate 	sarg.what = what;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	error = zone_walk(pool_pset_setup_cb, &sarg);
1827c478bd9Sstevel@tonic-gate 	ASSERT(error == 0);
1837c478bd9Sstevel@tonic-gate 	return (0);
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate /*
1877c478bd9Sstevel@tonic-gate  * Initialize processor set plugin.  Called once at boot time.
1887c478bd9Sstevel@tonic-gate  */
1897c478bd9Sstevel@tonic-gate void
pool_pset_init(void)1907c478bd9Sstevel@tonic-gate pool_pset_init(void)
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate 	ASSERT(pool_pset_default == NULL);
1937c478bd9Sstevel@tonic-gate 	pool_pset_default = kmem_zalloc(sizeof (pool_pset_t), KM_SLEEP);
1947c478bd9Sstevel@tonic-gate 	pool_pset_default->pset_id = PS_NONE;
1957c478bd9Sstevel@tonic-gate 	pool_pset_default->pset_npools = 1;	/* for pool_default */
1967c478bd9Sstevel@tonic-gate 	pool_default->pool_pset = pool_pset_default;
1977c478bd9Sstevel@tonic-gate 	list_create(&pool_pset_list, sizeof (pool_pset_t),
1987c478bd9Sstevel@tonic-gate 	    offsetof(pool_pset_t, pset_link));
1997c478bd9Sstevel@tonic-gate 	list_insert_head(&pool_pset_list, pool_pset_default);
2007c478bd9Sstevel@tonic-gate 	mutex_enter(&cpu_lock);
2017c478bd9Sstevel@tonic-gate 	register_cpu_setup_func(pool_pset_cpu_setup, NULL);
2027c478bd9Sstevel@tonic-gate 	mutex_exit(&cpu_lock);
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate /*
2067c478bd9Sstevel@tonic-gate  * Dummy wrapper function that returns 0 to satisfy zone_walk().
2077c478bd9Sstevel@tonic-gate  */
2087c478bd9Sstevel@tonic-gate static int
pool_pset_zone_pset_set(zone_t * zone,void * arg)2097c478bd9Sstevel@tonic-gate pool_pset_zone_pset_set(zone_t *zone, void *arg)
2107c478bd9Sstevel@tonic-gate {
2117c478bd9Sstevel@tonic-gate 	psetid_t psetid = (psetid_t)(uintptr_t)arg;
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock));
2147c478bd9Sstevel@tonic-gate 	zone_pset_set(zone, psetid);
2157c478bd9Sstevel@tonic-gate 	return (0);
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate /*
2197c478bd9Sstevel@tonic-gate  * Enable processor set plugin.
2207c478bd9Sstevel@tonic-gate  */
2217c478bd9Sstevel@tonic-gate int
pool_pset_enable(void)2227c478bd9Sstevel@tonic-gate pool_pset_enable(void)
2237c478bd9Sstevel@tonic-gate {
2247c478bd9Sstevel@tonic-gate 	int error;
2257c478bd9Sstevel@tonic-gate 	nvlist_t *props;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
2287c478bd9Sstevel@tonic-gate 	ASSERT(INGLOBALZONE(curproc));
2297c478bd9Sstevel@tonic-gate 	/*
2307c478bd9Sstevel@tonic-gate 	 * Can't enable pools if there are existing cpu partitions.
2317c478bd9Sstevel@tonic-gate 	 */
2327c478bd9Sstevel@tonic-gate 	mutex_enter(&cpu_lock);
2337c478bd9Sstevel@tonic-gate 	if (cp_numparts > 1) {
2347c478bd9Sstevel@tonic-gate 		mutex_exit(&cpu_lock);
2357c478bd9Sstevel@tonic-gate 		return (EEXIST);
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	/*
2397c478bd9Sstevel@tonic-gate 	 * We want to switch things such that everything that was tagged with
2407c478bd9Sstevel@tonic-gate 	 * the special ALL_ZONES token now is explicitly visible to all zones:
2417c478bd9Sstevel@tonic-gate 	 * first add individual zones to the visibility list then remove the
2427c478bd9Sstevel@tonic-gate 	 * special "ALL_ZONES" token.  There must only be the default pset
2437c478bd9Sstevel@tonic-gate 	 * (PS_NONE) active if pools are being enabled, so we only need to
2447c478bd9Sstevel@tonic-gate 	 * deal with it.
2457c478bd9Sstevel@tonic-gate 	 *
2467c478bd9Sstevel@tonic-gate 	 * We want to make pool_pset_enabled() start returning B_TRUE before
2477c478bd9Sstevel@tonic-gate 	 * we call any of the visibility update functions.
2487c478bd9Sstevel@tonic-gate 	 */
2497c478bd9Sstevel@tonic-gate 	global_zone->zone_psetid = PS_NONE;
2507c478bd9Sstevel@tonic-gate 	/*
2517c478bd9Sstevel@tonic-gate 	 * We need to explicitly handle the global zone since
2527c478bd9Sstevel@tonic-gate 	 * zone_pset_set() won't modify it.
2537c478bd9Sstevel@tonic-gate 	 */
2547c478bd9Sstevel@tonic-gate 	pool_pset_visibility_add(PS_NONE, global_zone);
2557c478bd9Sstevel@tonic-gate 	/*
2567c478bd9Sstevel@tonic-gate 	 * A NULL argument means the ALL_ZONES token.
2577c478bd9Sstevel@tonic-gate 	 */
2587c478bd9Sstevel@tonic-gate 	pool_pset_visibility_remove(PS_NONE, NULL);
2597c478bd9Sstevel@tonic-gate 	error = zone_walk(pool_pset_zone_pset_set, (void *)PS_NONE);
2607c478bd9Sstevel@tonic-gate 	ASSERT(error == 0);
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	/*
2637c478bd9Sstevel@tonic-gate 	 * It is safe to drop cpu_lock here.  We're still
2647c478bd9Sstevel@tonic-gate 	 * holding pool_lock so no new cpu partitions can
2657c478bd9Sstevel@tonic-gate 	 * be created while we're here.
2667c478bd9Sstevel@tonic-gate 	 */
2677c478bd9Sstevel@tonic-gate 	mutex_exit(&cpu_lock);
2687c478bd9Sstevel@tonic-gate 	(void) nvlist_alloc(&pool_pset_default->pset_props,
2697c478bd9Sstevel@tonic-gate 	    NV_UNIQUE_NAME, KM_SLEEP);
2707c478bd9Sstevel@tonic-gate 	props = pool_pset_default->pset_props;
2717c478bd9Sstevel@tonic-gate 	(void) nvlist_add_string(props, "pset.name", "pset_default");
2727c478bd9Sstevel@tonic-gate 	(void) nvlist_add_string(props, "pset.comment", "");
2737c478bd9Sstevel@tonic-gate 	(void) nvlist_add_int64(props, "pset.sys_id", PS_NONE);
2747c478bd9Sstevel@tonic-gate 	(void) nvlist_add_string(props, "pset.units", "population");
2757c478bd9Sstevel@tonic-gate 	(void) nvlist_add_byte(props, "pset.default", 1);
2767c478bd9Sstevel@tonic-gate 	(void) nvlist_add_uint64(props, "pset.max", 65536);
2777c478bd9Sstevel@tonic-gate 	(void) nvlist_add_uint64(props, "pset.min", 1);
2787c478bd9Sstevel@tonic-gate 	pool_pset_mod = pool_cpu_mod = gethrtime();
2797c478bd9Sstevel@tonic-gate 	return (0);
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate /*
2837c478bd9Sstevel@tonic-gate  * Disable processor set plugin.
2847c478bd9Sstevel@tonic-gate  */
2857c478bd9Sstevel@tonic-gate int
pool_pset_disable(void)2867c478bd9Sstevel@tonic-gate pool_pset_disable(void)
2877c478bd9Sstevel@tonic-gate {
2887c478bd9Sstevel@tonic-gate 	processorid_t cpuid;
2897c478bd9Sstevel@tonic-gate 	cpu_t *cpu;
2907c478bd9Sstevel@tonic-gate 	int error;
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
2937c478bd9Sstevel@tonic-gate 	ASSERT(INGLOBALZONE(curproc));
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 	mutex_enter(&cpu_lock);
2967c478bd9Sstevel@tonic-gate 	if (cp_numparts > 1) {	/* make sure only default pset is left */
2977c478bd9Sstevel@tonic-gate 		mutex_exit(&cpu_lock);
2987c478bd9Sstevel@tonic-gate 		return (EBUSY);
2997c478bd9Sstevel@tonic-gate 	}
3007c478bd9Sstevel@tonic-gate 	/*
3017c478bd9Sstevel@tonic-gate 	 * Remove all non-system CPU and processor set properties
3027c478bd9Sstevel@tonic-gate 	 */
3037c478bd9Sstevel@tonic-gate 	for (cpuid = 0; cpuid < NCPU; cpuid++) {
3047c478bd9Sstevel@tonic-gate 		if ((cpu = cpu_get(cpuid)) == NULL)
3057c478bd9Sstevel@tonic-gate 			continue;
3067c478bd9Sstevel@tonic-gate 		if (cpu->cpu_props != NULL) {
3077c478bd9Sstevel@tonic-gate 			(void) nvlist_free(cpu->cpu_props);
3087c478bd9Sstevel@tonic-gate 			cpu->cpu_props = NULL;
3097c478bd9Sstevel@tonic-gate 		}
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	/*
3137c478bd9Sstevel@tonic-gate 	 * We want to switch things such that everything is now visible
3147c478bd9Sstevel@tonic-gate 	 * to ALL_ZONES: first add the special "ALL_ZONES" token to the
3157c478bd9Sstevel@tonic-gate 	 * visibility list then remove individual zones.  There must
3167c478bd9Sstevel@tonic-gate 	 * only be the default pset active if pools are being disabled,
3177c478bd9Sstevel@tonic-gate 	 * so we only need to deal with it.
3187c478bd9Sstevel@tonic-gate 	 */
3197c478bd9Sstevel@tonic-gate 	error = zone_walk(pool_pset_zone_pset_set, (void *)ZONE_PS_INVAL);
3207c478bd9Sstevel@tonic-gate 	ASSERT(error == 0);
3217c478bd9Sstevel@tonic-gate 	pool_pset_visibility_add(PS_NONE, NULL);
3227c478bd9Sstevel@tonic-gate 	pool_pset_visibility_remove(PS_NONE, global_zone);
3237c478bd9Sstevel@tonic-gate 	/*
3247c478bd9Sstevel@tonic-gate 	 * pool_pset_enabled() will henceforth return B_FALSE.
3257c478bd9Sstevel@tonic-gate 	 */
3267c478bd9Sstevel@tonic-gate 	global_zone->zone_psetid = ZONE_PS_INVAL;
3277c478bd9Sstevel@tonic-gate 	mutex_exit(&cpu_lock);
3287c478bd9Sstevel@tonic-gate 	if (pool_pset_default->pset_props != NULL) {
3297c478bd9Sstevel@tonic-gate 		nvlist_free(pool_pset_default->pset_props);
3307c478bd9Sstevel@tonic-gate 		pool_pset_default->pset_props = NULL;
3317c478bd9Sstevel@tonic-gate 	}
3327c478bd9Sstevel@tonic-gate 	return (0);
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate /*
3367c478bd9Sstevel@tonic-gate  * Create new processor set and give it a temporary name.
3377c478bd9Sstevel@tonic-gate  */
3387c478bd9Sstevel@tonic-gate int
pool_pset_create(psetid_t * id)3397c478bd9Sstevel@tonic-gate pool_pset_create(psetid_t *id)
3407c478bd9Sstevel@tonic-gate {
3417c478bd9Sstevel@tonic-gate 	char pset_name[40];
3427c478bd9Sstevel@tonic-gate 	pool_pset_t *pset;
3437c478bd9Sstevel@tonic-gate 	psetid_t psetid;
3447c478bd9Sstevel@tonic-gate 	int err;
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
3477c478bd9Sstevel@tonic-gate 	if ((err = cpupart_create(&psetid)) != 0)
3487c478bd9Sstevel@tonic-gate 		return (err);
3497c478bd9Sstevel@tonic-gate 	pset = kmem_alloc(sizeof (pool_pset_t), KM_SLEEP);
3507c478bd9Sstevel@tonic-gate 	pset->pset_id = *id = psetid;
3517c478bd9Sstevel@tonic-gate 	pset->pset_npools = 0;
3527c478bd9Sstevel@tonic-gate 	(void) nvlist_alloc(&pset->pset_props, NV_UNIQUE_NAME, KM_SLEEP);
3537c478bd9Sstevel@tonic-gate 	(void) nvlist_add_int64(pset->pset_props, "pset.sys_id", psetid);
3547c478bd9Sstevel@tonic-gate 	(void) nvlist_add_byte(pset->pset_props, "pset.default", 0);
3557c478bd9Sstevel@tonic-gate 	pool_pset_mod = gethrtime();
3567c478bd9Sstevel@tonic-gate 	(void) snprintf(pset_name, sizeof (pset_name), "pset_%lld",
3577c478bd9Sstevel@tonic-gate 	    pool_pset_mod);
3587c478bd9Sstevel@tonic-gate 	(void) nvlist_add_string(pset->pset_props, "pset.name", pset_name);
3597c478bd9Sstevel@tonic-gate 	list_insert_tail(&pool_pset_list, pset);
3607c478bd9Sstevel@tonic-gate 	return (0);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate /*
3647c478bd9Sstevel@tonic-gate  * Destroy existing processor set.
3657c478bd9Sstevel@tonic-gate  */
3667c478bd9Sstevel@tonic-gate int
pool_pset_destroy(psetid_t psetid)3677c478bd9Sstevel@tonic-gate pool_pset_destroy(psetid_t psetid)
3687c478bd9Sstevel@tonic-gate {
3697c478bd9Sstevel@tonic-gate 	pool_pset_t *pset;
3707c478bd9Sstevel@tonic-gate 	int ret;
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	if (psetid == PS_NONE)
3757c478bd9Sstevel@tonic-gate 		return (EINVAL);
3767c478bd9Sstevel@tonic-gate 	if ((pset = pool_lookup_pset_by_id(psetid)) == NULL)
3777c478bd9Sstevel@tonic-gate 		return (ESRCH);
3787c478bd9Sstevel@tonic-gate 	if (pset->pset_npools > 0) /* can't destroy associated psets */
3797c478bd9Sstevel@tonic-gate 		return (EBUSY);
3807c478bd9Sstevel@tonic-gate 	if ((ret = cpupart_destroy(pset->pset_id)) != 0)
3817c478bd9Sstevel@tonic-gate 		return (ret);
3827c478bd9Sstevel@tonic-gate 	(void) nvlist_free(pset->pset_props);
3837c478bd9Sstevel@tonic-gate 	list_remove(&pool_pset_list, pset);
3847c478bd9Sstevel@tonic-gate 	pool_pset_mod = gethrtime();
3857c478bd9Sstevel@tonic-gate 	kmem_free(pset, sizeof (pool_pset_t));
3867c478bd9Sstevel@tonic-gate 	return (0);
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate /*
3907c478bd9Sstevel@tonic-gate  * Change the visibility of a pset (and all contained cpus) in a zone.
3917c478bd9Sstevel@tonic-gate  * A NULL zone argument implies the special ALL_ZONES token.
3927c478bd9Sstevel@tonic-gate  */
3937c478bd9Sstevel@tonic-gate static void
pool_pset_visibility_change(psetid_t psetid,zone_t * zone,boolean_t add)3947c478bd9Sstevel@tonic-gate pool_pset_visibility_change(psetid_t psetid, zone_t *zone, boolean_t add)
3957c478bd9Sstevel@tonic-gate {
3967c478bd9Sstevel@tonic-gate 	zoneid_t zoneid = zone ? zone->zone_id : ALL_ZONES;
3977c478bd9Sstevel@tonic-gate 	cpupart_t *cp;
3987c478bd9Sstevel@tonic-gate 	cpu_t *c;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock));
4017c478bd9Sstevel@tonic-gate 	ASSERT(psetid != ZONE_PS_INVAL);
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	cp = cpupart_find(psetid);
4047c478bd9Sstevel@tonic-gate 	ASSERT(cp != NULL);
4057c478bd9Sstevel@tonic-gate 	if (cp->cp_kstat != NULL) {
4067c478bd9Sstevel@tonic-gate 		if (add)
4077c478bd9Sstevel@tonic-gate 			kstat_zone_add(cp->cp_kstat, zoneid);
4087c478bd9Sstevel@tonic-gate 		else
4097c478bd9Sstevel@tonic-gate 			kstat_zone_remove(cp->cp_kstat, zoneid);
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	c = cpu_list;
4137c478bd9Sstevel@tonic-gate 	do {
4147c478bd9Sstevel@tonic-gate 		ASSERT(c != NULL);
4157c478bd9Sstevel@tonic-gate 		if (c->cpu_part == cp && !cpu_is_poweredoff(c)) {
4167c478bd9Sstevel@tonic-gate 			if (add)
4177c478bd9Sstevel@tonic-gate 				cpu_visibility_add(c, zone);
4187c478bd9Sstevel@tonic-gate 			else
4197c478bd9Sstevel@tonic-gate 				cpu_visibility_remove(c, zone);
4207c478bd9Sstevel@tonic-gate 		}
4217c478bd9Sstevel@tonic-gate 	} while ((c = c->cpu_next) != cpu_list);
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate /*
4257c478bd9Sstevel@tonic-gate  * Make the processor set visible to the zone.  A NULL value for
4267c478bd9Sstevel@tonic-gate  * the zone means that the special ALL_ZONES token should be added to
4277c478bd9Sstevel@tonic-gate  * the visibility list.
4287c478bd9Sstevel@tonic-gate  */
4297c478bd9Sstevel@tonic-gate void
pool_pset_visibility_add(psetid_t psetid,zone_t * zone)4307c478bd9Sstevel@tonic-gate pool_pset_visibility_add(psetid_t psetid, zone_t *zone)
4317c478bd9Sstevel@tonic-gate {
4327c478bd9Sstevel@tonic-gate 	pool_pset_visibility_change(psetid, zone, B_TRUE);
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate /*
4367c478bd9Sstevel@tonic-gate  * Remove zone's visibility into the processor set.  A NULL value for
4377c478bd9Sstevel@tonic-gate  * the zone means that the special ALL_ZONES token should be removed
4387c478bd9Sstevel@tonic-gate  * from the visibility list.
4397c478bd9Sstevel@tonic-gate  */
4407c478bd9Sstevel@tonic-gate void
pool_pset_visibility_remove(psetid_t psetid,zone_t * zone)4417c478bd9Sstevel@tonic-gate pool_pset_visibility_remove(psetid_t psetid, zone_t *zone)
4427c478bd9Sstevel@tonic-gate {
4437c478bd9Sstevel@tonic-gate 	pool_pset_visibility_change(psetid, zone, B_FALSE);
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate /*
4477c478bd9Sstevel@tonic-gate  * Quick way of seeing if pools are enabled (as far as processor sets are
4487c478bd9Sstevel@tonic-gate  * concerned) without holding pool_lock().
4497c478bd9Sstevel@tonic-gate  */
4507c478bd9Sstevel@tonic-gate boolean_t
pool_pset_enabled(void)4517c478bd9Sstevel@tonic-gate pool_pset_enabled(void)
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock));
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 	return (zone_pset_get(global_zone) != ZONE_PS_INVAL);
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate struct assoc_zone_arg {
4597c478bd9Sstevel@tonic-gate 	poolid_t poolid;
4607c478bd9Sstevel@tonic-gate 	psetid_t newpsetid;
4617c478bd9Sstevel@tonic-gate };
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate /*
4647c478bd9Sstevel@tonic-gate  * Callback function to update a zone's processor set visibility when
4657c478bd9Sstevel@tonic-gate  * a pool is associated with a processor set.
4667c478bd9Sstevel@tonic-gate  */
4677c478bd9Sstevel@tonic-gate static int
pool_pset_assoc_zone_cb(zone_t * zone,void * arg)4687c478bd9Sstevel@tonic-gate pool_pset_assoc_zone_cb(zone_t *zone, void *arg)
4697c478bd9Sstevel@tonic-gate {
4707c478bd9Sstevel@tonic-gate 	struct assoc_zone_arg *aza = arg;
4717c478bd9Sstevel@tonic-gate 	pool_t *pool;
4727c478bd9Sstevel@tonic-gate 	zoneid_t zoneid = zone->zone_id;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
4757c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock));
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	if (zoneid == GLOBAL_ZONEID)
4787c478bd9Sstevel@tonic-gate 		return (0);
4797c478bd9Sstevel@tonic-gate 	pool = zone_pool_get(zone);
4807c478bd9Sstevel@tonic-gate 	if (pool->pool_id == aza->poolid)
4817c478bd9Sstevel@tonic-gate 		zone_pset_set(zone, aza->newpsetid);
4827c478bd9Sstevel@tonic-gate 	return (0);
4837c478bd9Sstevel@tonic-gate }
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate /*
4867c478bd9Sstevel@tonic-gate  * Associate pool with new processor set.
4877c478bd9Sstevel@tonic-gate  */
4887c478bd9Sstevel@tonic-gate int
pool_pset_assoc(poolid_t poolid,psetid_t psetid)4897c478bd9Sstevel@tonic-gate pool_pset_assoc(poolid_t poolid, psetid_t psetid)
4907c478bd9Sstevel@tonic-gate {
4917c478bd9Sstevel@tonic-gate 	pool_t *pool;
4927c478bd9Sstevel@tonic-gate 	pool_pset_t *pset, *oldpset;
4937c478bd9Sstevel@tonic-gate 	int err = 0;
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	if ((pool = pool_lookup_pool_by_id(poolid)) == NULL ||
4987c478bd9Sstevel@tonic-gate 	    (pset = pool_lookup_pset_by_id(psetid)) == NULL) {
4997c478bd9Sstevel@tonic-gate 		return (ESRCH);
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate 	if (pool->pool_pset->pset_id == psetid) {
5027c478bd9Sstevel@tonic-gate 		/*
5037c478bd9Sstevel@tonic-gate 		 * Already associated.
5047c478bd9Sstevel@tonic-gate 		 */
5057c478bd9Sstevel@tonic-gate 		return (0);
5067c478bd9Sstevel@tonic-gate 	}
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 	/*
5097c478bd9Sstevel@tonic-gate 	 * Hang the new pset off the pool, and rebind all of the pool's
5107c478bd9Sstevel@tonic-gate 	 * processes to it.  If pool_do_bind fails, all processes will remain
5117c478bd9Sstevel@tonic-gate 	 * bound to the old set.
5127c478bd9Sstevel@tonic-gate 	 */
5137c478bd9Sstevel@tonic-gate 	oldpset = pool->pool_pset;
5147c478bd9Sstevel@tonic-gate 	pool->pool_pset = pset;
5157c478bd9Sstevel@tonic-gate 	err = pool_do_bind(pool, P_POOLID, poolid, POOL_BIND_PSET);
5167c478bd9Sstevel@tonic-gate 	if (err) {
5177c478bd9Sstevel@tonic-gate 		pool->pool_pset = oldpset;
5187c478bd9Sstevel@tonic-gate 	} else {
5197c478bd9Sstevel@tonic-gate 		struct assoc_zone_arg azarg;
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 		/*
5227c478bd9Sstevel@tonic-gate 		 * Update zones' visibility to reflect changes.
5237c478bd9Sstevel@tonic-gate 		 */
5247c478bd9Sstevel@tonic-gate 		azarg.poolid = poolid;
5257c478bd9Sstevel@tonic-gate 		azarg.newpsetid = pset->pset_id;
5267c478bd9Sstevel@tonic-gate 		mutex_enter(&cpu_lock);
5277c478bd9Sstevel@tonic-gate 		err = zone_walk(pool_pset_assoc_zone_cb, &azarg);
5287c478bd9Sstevel@tonic-gate 		ASSERT(err == 0);
5297c478bd9Sstevel@tonic-gate 		mutex_exit(&cpu_lock);
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 		oldpset->pset_npools--;
5327c478bd9Sstevel@tonic-gate 		pset->pset_npools++;
5337c478bd9Sstevel@tonic-gate 	}
5347c478bd9Sstevel@tonic-gate 	return (err);
5357c478bd9Sstevel@tonic-gate }
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate /*
5387c478bd9Sstevel@tonic-gate  * Transfer specified CPUs between processor sets.
5397c478bd9Sstevel@tonic-gate  */
5407c478bd9Sstevel@tonic-gate int
pool_pset_xtransfer(psetid_t src,psetid_t dst,size_t size,id_t * ids)5417c478bd9Sstevel@tonic-gate pool_pset_xtransfer(psetid_t src, psetid_t dst, size_t size, id_t *ids)
5427c478bd9Sstevel@tonic-gate {
5437c478bd9Sstevel@tonic-gate 	struct cpu *cpu;
5447c478bd9Sstevel@tonic-gate 	int ret = 0;
5457c478bd9Sstevel@tonic-gate 	int id;
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
5487c478bd9Sstevel@tonic-gate 	ASSERT(INGLOBALZONE(curproc));
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	if (size == 0 || size > max_ncpus)	/* quick sanity check */
5517c478bd9Sstevel@tonic-gate 		return (EINVAL);
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	mutex_enter(&cpu_lock);
5547c478bd9Sstevel@tonic-gate 	for (id = 0; id < size; id++) {
5557c478bd9Sstevel@tonic-gate 		if ((cpu = cpu_get((processorid_t)ids[id])) == NULL ||
5567c478bd9Sstevel@tonic-gate 		    cpupart_query_cpu(cpu) != src) {
5577c478bd9Sstevel@tonic-gate 			ret = EINVAL;
5587c478bd9Sstevel@tonic-gate 			break;
5597c478bd9Sstevel@tonic-gate 		}
5607c478bd9Sstevel@tonic-gate 		if ((ret = cpupart_attach_cpu(dst, cpu, 1)) != 0)
5617c478bd9Sstevel@tonic-gate 			break;
5627c478bd9Sstevel@tonic-gate 	}
5637c478bd9Sstevel@tonic-gate 	mutex_exit(&cpu_lock);
5647c478bd9Sstevel@tonic-gate 	if (ret == 0)
5657c478bd9Sstevel@tonic-gate 		pool_pset_mod = gethrtime();
5667c478bd9Sstevel@tonic-gate 	return (ret);
5677c478bd9Sstevel@tonic-gate }
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate /*
5707c478bd9Sstevel@tonic-gate  * Bind process to processor set.  This should never fail because
5717c478bd9Sstevel@tonic-gate  * we should've done all preliminary checks before calling it.
5727c478bd9Sstevel@tonic-gate  */
5737c478bd9Sstevel@tonic-gate void
pool_pset_bind(proc_t * p,psetid_t psetid,void * projbuf,void * zonebuf)5747c478bd9Sstevel@tonic-gate pool_pset_bind(proc_t *p, psetid_t psetid, void *projbuf, void *zonebuf)
5757c478bd9Sstevel@tonic-gate {
5767c478bd9Sstevel@tonic-gate 	kthread_t *t;
5777c478bd9Sstevel@tonic-gate 	int ret;
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
5807c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock));
5817c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&pidlock));
5827c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&p->p_lock));
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	if ((t = p->p_tlist) == NULL)
5857c478bd9Sstevel@tonic-gate 		return;
5867c478bd9Sstevel@tonic-gate 	do {
5877c478bd9Sstevel@tonic-gate 		ret = cpupart_bind_thread(t, psetid, 0, projbuf, zonebuf);
5887c478bd9Sstevel@tonic-gate 		ASSERT(ret == 0);
5897c478bd9Sstevel@tonic-gate 		t->t_bind_pset = psetid;
5907c478bd9Sstevel@tonic-gate 	} while ((t = t->t_forw) != p->p_tlist);
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate /*
5947c478bd9Sstevel@tonic-gate  * See the comment above pool_do_bind() for the semantics of the pset_bind_*()
5957c478bd9Sstevel@tonic-gate  * functions.  These must be kept in sync with cpupart_move_thread, and
5967c478bd9Sstevel@tonic-gate  * anything else that could fail a pool_pset_bind.
5977c478bd9Sstevel@tonic-gate  *
5987c478bd9Sstevel@tonic-gate  * Returns non-zero errno on failure and zero on success.
5997c478bd9Sstevel@tonic-gate  * Iff successful, cpu_lock is held on return.
6007c478bd9Sstevel@tonic-gate  */
6017c478bd9Sstevel@tonic-gate int
pset_bind_start(proc_t ** procs,pool_t * pool)6027c478bd9Sstevel@tonic-gate pset_bind_start(proc_t **procs, pool_t *pool)
6037c478bd9Sstevel@tonic-gate {
6047c478bd9Sstevel@tonic-gate 	cred_t *pcred;
6057c478bd9Sstevel@tonic-gate 	proc_t *p, **pp;
6067c478bd9Sstevel@tonic-gate 	kthread_t *t;
6077c478bd9Sstevel@tonic-gate 	cpupart_t *newpp;
6087c478bd9Sstevel@tonic-gate 	int ret;
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	extern int cpupart_movable_thread(kthread_id_t, cpupart_t *, int);
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
6137c478bd9Sstevel@tonic-gate 	ASSERT(INGLOBALZONE(curproc));
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	mutex_enter(&cpu_lock);
6167c478bd9Sstevel@tonic-gate 	weakbinding_stop();
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 	newpp = cpupart_find(pool->pool_pset->pset_id);
6197c478bd9Sstevel@tonic-gate 	ASSERT(newpp != NULL);
6207c478bd9Sstevel@tonic-gate 	if (newpp->cp_cpulist == NULL) {
6217c478bd9Sstevel@tonic-gate 		weakbinding_start();
6227c478bd9Sstevel@tonic-gate 		mutex_exit(&cpu_lock);
6237c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
6247c478bd9Sstevel@tonic-gate 	}
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 	pcred = crgetcred();
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate 	/*
6297c478bd9Sstevel@tonic-gate 	 * Check for the PRIV_PROC_PRIOCNTL privilege that is required
6307c478bd9Sstevel@tonic-gate 	 * to enter and exit scheduling classes.  If other privileges
6317c478bd9Sstevel@tonic-gate 	 * are required by CL_ENTERCLASS/CL_CANEXIT types of routines
6327c478bd9Sstevel@tonic-gate 	 * in the future, this code will have to be updated.
6337c478bd9Sstevel@tonic-gate 	 */
6347c478bd9Sstevel@tonic-gate 	if (secpolicy_setpriority(pcred) != 0) {
6357c478bd9Sstevel@tonic-gate 		weakbinding_start();
6367c478bd9Sstevel@tonic-gate 		mutex_exit(&cpu_lock);
6377c478bd9Sstevel@tonic-gate 		crfree(pcred);
6387c478bd9Sstevel@tonic-gate 		return (EPERM);
6397c478bd9Sstevel@tonic-gate 	}
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	for (pp = procs; (p = *pp) != NULL; pp++) {
6427c478bd9Sstevel@tonic-gate 		mutex_enter(&p->p_lock);
6437c478bd9Sstevel@tonic-gate 		if ((t = p->p_tlist) == NULL) {
6447c478bd9Sstevel@tonic-gate 			mutex_exit(&p->p_lock);
6457c478bd9Sstevel@tonic-gate 			continue;
6467c478bd9Sstevel@tonic-gate 		}
6477c478bd9Sstevel@tonic-gate 		/*
6487c478bd9Sstevel@tonic-gate 		 * Check our basic permissions to control this process.
6497c478bd9Sstevel@tonic-gate 		 */
6507c478bd9Sstevel@tonic-gate 		if (!prochasprocperm(p, curproc, pcred)) {
6517c478bd9Sstevel@tonic-gate 			mutex_exit(&p->p_lock);
6527c478bd9Sstevel@tonic-gate 			weakbinding_start();
6537c478bd9Sstevel@tonic-gate 			mutex_exit(&cpu_lock);
6547c478bd9Sstevel@tonic-gate 			crfree(pcred);
6557c478bd9Sstevel@tonic-gate 			return (EPERM);
6567c478bd9Sstevel@tonic-gate 		}
6577c478bd9Sstevel@tonic-gate 		do {
6587c478bd9Sstevel@tonic-gate 			/*
6597c478bd9Sstevel@tonic-gate 			 * Check that all threads can be moved to
6607c478bd9Sstevel@tonic-gate 			 * a new processor set.
6617c478bd9Sstevel@tonic-gate 			 */
6627c478bd9Sstevel@tonic-gate 			thread_lock(t);
6637c478bd9Sstevel@tonic-gate 			ret = cpupart_movable_thread(t, newpp, 0);
6647c478bd9Sstevel@tonic-gate 			thread_unlock(t);
6657c478bd9Sstevel@tonic-gate 			if (ret != 0) {
6667c478bd9Sstevel@tonic-gate 				mutex_exit(&p->p_lock);
6677c478bd9Sstevel@tonic-gate 				weakbinding_start();
6687c478bd9Sstevel@tonic-gate 				mutex_exit(&cpu_lock);
6697c478bd9Sstevel@tonic-gate 				crfree(pcred);
6707c478bd9Sstevel@tonic-gate 				return (ret);
6717c478bd9Sstevel@tonic-gate 			}
6727c478bd9Sstevel@tonic-gate 		} while ((t = t->t_forw) != p->p_tlist);
6737c478bd9Sstevel@tonic-gate 		mutex_exit(&p->p_lock);
6747c478bd9Sstevel@tonic-gate 	}
6757c478bd9Sstevel@tonic-gate 	crfree(pcred);
6767c478bd9Sstevel@tonic-gate 	return (0);	/* with cpu_lock held and weakbinding stopped */
6777c478bd9Sstevel@tonic-gate }
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6807c478bd9Sstevel@tonic-gate void
pset_bind_abort(proc_t ** procs,pool_t * pool)6817c478bd9Sstevel@tonic-gate pset_bind_abort(proc_t **procs, pool_t *pool)
6827c478bd9Sstevel@tonic-gate {
6837c478bd9Sstevel@tonic-gate 	mutex_exit(&cpu_lock);
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate void
pset_bind_finish(void)6877c478bd9Sstevel@tonic-gate pset_bind_finish(void)
6887c478bd9Sstevel@tonic-gate {
6897c478bd9Sstevel@tonic-gate 	weakbinding_start();
6907c478bd9Sstevel@tonic-gate 	mutex_exit(&cpu_lock);
6917c478bd9Sstevel@tonic-gate }
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate static pool_property_t pool_pset_props[] = {
6947c478bd9Sstevel@tonic-gate 	{ "pset.name",			DATA_TYPE_STRING,	PP_RDWR },
6957c478bd9Sstevel@tonic-gate 	{ "pset.comment",		DATA_TYPE_STRING,	PP_RDWR },
6967c478bd9Sstevel@tonic-gate 	{ "pset.sys_id",		DATA_TYPE_UINT64,	PP_READ },
6977c478bd9Sstevel@tonic-gate 	{ "pset.units",			DATA_TYPE_STRING,	PP_RDWR },
6987c478bd9Sstevel@tonic-gate 	{ "pset.default",		DATA_TYPE_BYTE,		PP_READ },
6997c478bd9Sstevel@tonic-gate 	{ "pset.min",			DATA_TYPE_UINT64,	PP_RDWR },
7007c478bd9Sstevel@tonic-gate 	{ "pset.max",			DATA_TYPE_UINT64,	PP_RDWR },
7017c478bd9Sstevel@tonic-gate 	{ "pset.size",			DATA_TYPE_UINT64,	PP_READ },
7027c478bd9Sstevel@tonic-gate 	{ "pset.load",			DATA_TYPE_UINT64,	PP_READ },
7037c478bd9Sstevel@tonic-gate 	{ "pset.poold.objectives",	DATA_TYPE_STRING,
7047c478bd9Sstevel@tonic-gate 	    PP_RDWR | PP_OPTIONAL },
7057c478bd9Sstevel@tonic-gate 	{ NULL,				0,			0 }
7067c478bd9Sstevel@tonic-gate };
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate static pool_property_t pool_cpu_props[] = {
7097c478bd9Sstevel@tonic-gate 	{ "cpu.sys_id",			DATA_TYPE_UINT64,	PP_READ },
7107c478bd9Sstevel@tonic-gate 	{ "cpu.comment",		DATA_TYPE_STRING,	PP_RDWR },
7117c478bd9Sstevel@tonic-gate 	{ "cpu.status",			DATA_TYPE_STRING,	PP_RDWR },
7127c478bd9Sstevel@tonic-gate 	{ "cpu.pinned",			DATA_TYPE_BYTE,
7137c478bd9Sstevel@tonic-gate 	    PP_RDWR | PP_OPTIONAL },
7147c478bd9Sstevel@tonic-gate 	{ NULL,				0,			0 }
7157c478bd9Sstevel@tonic-gate };
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate /*
7187c478bd9Sstevel@tonic-gate  * Put property on the specified processor set.
7197c478bd9Sstevel@tonic-gate  */
7207c478bd9Sstevel@tonic-gate int
pool_pset_propput(psetid_t psetid,nvpair_t * pair)7217c478bd9Sstevel@tonic-gate pool_pset_propput(psetid_t psetid, nvpair_t *pair)
7227c478bd9Sstevel@tonic-gate {
7237c478bd9Sstevel@tonic-gate 	pool_pset_t *pset;
7247c478bd9Sstevel@tonic-gate 	int ret;
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 	if ((pset = pool_lookup_pset_by_id(psetid)) == NULL)
7297c478bd9Sstevel@tonic-gate 		return (ESRCH);
7307c478bd9Sstevel@tonic-gate 	ret = pool_propput_common(pset->pset_props, pair, pool_pset_props);
7317c478bd9Sstevel@tonic-gate 	if (ret == 0)
7327c478bd9Sstevel@tonic-gate 		pool_pset_mod = gethrtime();
7337c478bd9Sstevel@tonic-gate 	return (ret);
7347c478bd9Sstevel@tonic-gate }
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate /*
7377c478bd9Sstevel@tonic-gate  * Remove existing processor set property.
7387c478bd9Sstevel@tonic-gate  */
7397c478bd9Sstevel@tonic-gate int
pool_pset_proprm(psetid_t psetid,char * name)7407c478bd9Sstevel@tonic-gate pool_pset_proprm(psetid_t psetid, char *name)
7417c478bd9Sstevel@tonic-gate {
7427c478bd9Sstevel@tonic-gate 	pool_pset_t *pset;
7437c478bd9Sstevel@tonic-gate 	int ret;
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 	if ((pset = pool_lookup_pset_by_id(psetid)) == NULL)
7487c478bd9Sstevel@tonic-gate 		return (EINVAL);
7497c478bd9Sstevel@tonic-gate 	ret = pool_proprm_common(pset->pset_props, name, pool_pset_props);
7507c478bd9Sstevel@tonic-gate 	if (ret == 0)
7517c478bd9Sstevel@tonic-gate 		pool_pset_mod = gethrtime();
7527c478bd9Sstevel@tonic-gate 	return (ret);
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate /*
7567c478bd9Sstevel@tonic-gate  * Put new CPU property.
7577c478bd9Sstevel@tonic-gate  * Handle special case of "cpu.status".
7587c478bd9Sstevel@tonic-gate  */
7597c478bd9Sstevel@tonic-gate int
pool_cpu_propput(processorid_t cpuid,nvpair_t * pair)7607c478bd9Sstevel@tonic-gate pool_cpu_propput(processorid_t cpuid, nvpair_t *pair)
7617c478bd9Sstevel@tonic-gate {
7627c478bd9Sstevel@tonic-gate 	int ret = 0;
7637c478bd9Sstevel@tonic-gate 	cpu_t *cpu;
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
7667c478bd9Sstevel@tonic-gate 	ASSERT(INGLOBALZONE(curproc));
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 	if (nvpair_type(pair) == DATA_TYPE_STRING &&
7697c478bd9Sstevel@tonic-gate 	    strcmp(nvpair_name(pair), "cpu.status") == 0) {
7707c478bd9Sstevel@tonic-gate 		char *val;
7717c478bd9Sstevel@tonic-gate 		int status;
7727c478bd9Sstevel@tonic-gate 		int old_status;
7737c478bd9Sstevel@tonic-gate 		(void) nvpair_value_string(pair, &val);
7747c478bd9Sstevel@tonic-gate 		if (strcmp(val, PS_OFFLINE) == 0)
7757c478bd9Sstevel@tonic-gate 			status = P_OFFLINE;
7767c478bd9Sstevel@tonic-gate 		else if (strcmp(val, PS_ONLINE) == 0)
7777c478bd9Sstevel@tonic-gate 			status = P_ONLINE;
7787c478bd9Sstevel@tonic-gate 		else if (strcmp(val, PS_NOINTR) == 0)
7797c478bd9Sstevel@tonic-gate 			status = P_NOINTR;
7807c478bd9Sstevel@tonic-gate 		else if (strcmp(val, PS_FAULTED) == 0)
7817c478bd9Sstevel@tonic-gate 			status = P_FAULTED;
7827c478bd9Sstevel@tonic-gate 		else if (strcmp(val, PS_SPARE) == 0)
7837c478bd9Sstevel@tonic-gate 			status = P_SPARE;
7847c478bd9Sstevel@tonic-gate 		else
7857c478bd9Sstevel@tonic-gate 			return (EINVAL);
7867c478bd9Sstevel@tonic-gate 		ret = p_online_internal(cpuid, status, &old_status);
7877c478bd9Sstevel@tonic-gate 	} else {
7887c478bd9Sstevel@tonic-gate 		mutex_enter(&cpu_lock);
7897c478bd9Sstevel@tonic-gate 		if ((cpu = cpu_get(cpuid)) == NULL)
7907c478bd9Sstevel@tonic-gate 			ret = EINVAL;
7917c478bd9Sstevel@tonic-gate 		if (cpu->cpu_props == NULL) {
7927c478bd9Sstevel@tonic-gate 			(void) nvlist_alloc(&cpu->cpu_props,
7937c478bd9Sstevel@tonic-gate 			    NV_UNIQUE_NAME, KM_SLEEP);
7947c478bd9Sstevel@tonic-gate 			(void) nvlist_add_string(cpu->cpu_props,
7957c478bd9Sstevel@tonic-gate 			    "cpu.comment", "");
7967c478bd9Sstevel@tonic-gate 		}
7977c478bd9Sstevel@tonic-gate 		ret = pool_propput_common(cpu->cpu_props, pair, pool_cpu_props);
7987c478bd9Sstevel@tonic-gate 		if (ret == 0)
7997c478bd9Sstevel@tonic-gate 			pool_cpu_mod = gethrtime();
8007c478bd9Sstevel@tonic-gate 		mutex_exit(&cpu_lock);
8017c478bd9Sstevel@tonic-gate 	}
8027c478bd9Sstevel@tonic-gate 	return (ret);
8037c478bd9Sstevel@tonic-gate }
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate /*
8067c478bd9Sstevel@tonic-gate  * Remove existing CPU property.
8077c478bd9Sstevel@tonic-gate  */
8087c478bd9Sstevel@tonic-gate int
pool_cpu_proprm(processorid_t cpuid,char * name)8097c478bd9Sstevel@tonic-gate pool_cpu_proprm(processorid_t cpuid, char *name)
8107c478bd9Sstevel@tonic-gate {
8117c478bd9Sstevel@tonic-gate 	int ret;
8127c478bd9Sstevel@tonic-gate 	cpu_t *cpu;
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
8157c478bd9Sstevel@tonic-gate 	ASSERT(INGLOBALZONE(curproc));
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate 	mutex_enter(&cpu_lock);
8187c478bd9Sstevel@tonic-gate 	if ((cpu = cpu_get(cpuid)) == NULL || cpu_is_poweredoff(cpu)) {
8197c478bd9Sstevel@tonic-gate 		ret = EINVAL;
8207c478bd9Sstevel@tonic-gate 	} else {
8217c478bd9Sstevel@tonic-gate 		if (cpu->cpu_props == NULL)
8227c478bd9Sstevel@tonic-gate 			ret = EINVAL;
8237c478bd9Sstevel@tonic-gate 		else
8247c478bd9Sstevel@tonic-gate 			ret = pool_proprm_common(cpu->cpu_props, name,
8257c478bd9Sstevel@tonic-gate 			    pool_cpu_props);
8267c478bd9Sstevel@tonic-gate 	}
8277c478bd9Sstevel@tonic-gate 	if (ret == 0)
8287c478bd9Sstevel@tonic-gate 		pool_cpu_mod = gethrtime();
8297c478bd9Sstevel@tonic-gate 	mutex_exit(&cpu_lock);
8307c478bd9Sstevel@tonic-gate 	return (ret);
8317c478bd9Sstevel@tonic-gate }
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate /*
8347c478bd9Sstevel@tonic-gate  * This macro returns load average multiplied by 1000 w/o losing precision
8357c478bd9Sstevel@tonic-gate  */
8367c478bd9Sstevel@tonic-gate #define	PSET_LOAD(f)	(((f >> 16) * 1000) + (((f & 0xffff) * 1000) / 0xffff))
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate /*
8397c478bd9Sstevel@tonic-gate  * Take a snapshot of the current state of processor sets and CPUs,
8407c478bd9Sstevel@tonic-gate  * pack it in the exacct format, and attach it to specified exacct record.
8417c478bd9Sstevel@tonic-gate  */
8427c478bd9Sstevel@tonic-gate int
pool_pset_pack(ea_object_t * eo_system)8437c478bd9Sstevel@tonic-gate pool_pset_pack(ea_object_t *eo_system)
8447c478bd9Sstevel@tonic-gate {
8457c478bd9Sstevel@tonic-gate 	ea_object_t *eo_pset, *eo_cpu;
8467c478bd9Sstevel@tonic-gate 	cpupart_t *cpupart;
8477c478bd9Sstevel@tonic-gate 	psetid_t mypsetid;
8487c478bd9Sstevel@tonic-gate 	pool_pset_t *pset;
8497c478bd9Sstevel@tonic-gate 	nvlist_t *nvl;
8507c478bd9Sstevel@tonic-gate 	size_t bufsz;
8517c478bd9Sstevel@tonic-gate 	cpu_t *cpu;
8527c478bd9Sstevel@tonic-gate 	char *buf;
8537c478bd9Sstevel@tonic-gate 	int ncpu;
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 	mutex_enter(&cpu_lock);
8587c478bd9Sstevel@tonic-gate 	mypsetid = zone_pset_get(curproc->p_zone);
8597c478bd9Sstevel@tonic-gate 	for (pset = list_head(&pool_pset_list); pset;
8607c478bd9Sstevel@tonic-gate 	    pset = list_next(&pool_pset_list, pset)) {
8617c478bd9Sstevel@tonic-gate 		psetid_t psetid = pset->pset_id;
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 		if (!INGLOBALZONE(curproc) && mypsetid != psetid)
8647c478bd9Sstevel@tonic-gate 			continue;
8657c478bd9Sstevel@tonic-gate 		cpupart = cpupart_find(psetid);
8667c478bd9Sstevel@tonic-gate 		ASSERT(cpupart != NULL);
8677c478bd9Sstevel@tonic-gate 		eo_pset = ea_alloc_group(EXT_GROUP |
8687c478bd9Sstevel@tonic-gate 		    EXC_LOCAL | EXD_GROUP_PSET);
8697c478bd9Sstevel@tonic-gate 		(void) ea_attach_item(eo_pset, &psetid, sizeof (id_t),
8707c478bd9Sstevel@tonic-gate 		    EXC_LOCAL | EXD_PSET_PSETID | EXT_UINT32);
8717c478bd9Sstevel@tonic-gate 		/*
8727c478bd9Sstevel@tonic-gate 		 * Pack info for all CPUs in this processor set.
8737c478bd9Sstevel@tonic-gate 		 */
8747c478bd9Sstevel@tonic-gate 		ncpu = 0;
8757c478bd9Sstevel@tonic-gate 		cpu = cpu_list;
8767c478bd9Sstevel@tonic-gate 		do {
8777c478bd9Sstevel@tonic-gate 			if (cpu->cpu_part != cpupart)	/* not our pset */
8787c478bd9Sstevel@tonic-gate 				continue;
8797c478bd9Sstevel@tonic-gate 			ncpu++;
8807c478bd9Sstevel@tonic-gate 			eo_cpu = ea_alloc_group(EXT_GROUP
8817c478bd9Sstevel@tonic-gate 			    | EXC_LOCAL | EXD_GROUP_CPU);
8827c478bd9Sstevel@tonic-gate 			(void) ea_attach_item(eo_cpu, &cpu->cpu_id,
8837c478bd9Sstevel@tonic-gate 			    sizeof (processorid_t),
8847c478bd9Sstevel@tonic-gate 			    EXC_LOCAL | EXD_CPU_CPUID | EXT_UINT32);
8857c478bd9Sstevel@tonic-gate 			if (cpu->cpu_props == NULL) {
8867c478bd9Sstevel@tonic-gate 				(void) nvlist_alloc(&cpu->cpu_props,
8877c478bd9Sstevel@tonic-gate 				    NV_UNIQUE_NAME, KM_SLEEP);
8887c478bd9Sstevel@tonic-gate 				(void) nvlist_add_string(cpu->cpu_props,
8897c478bd9Sstevel@tonic-gate 				    "cpu.comment", "");
8907c478bd9Sstevel@tonic-gate 			}
8917c478bd9Sstevel@tonic-gate 			(void) nvlist_dup(cpu->cpu_props, &nvl, KM_SLEEP);
8927c478bd9Sstevel@tonic-gate 			(void) nvlist_add_int64(nvl, "cpu.sys_id", cpu->cpu_id);
8937c478bd9Sstevel@tonic-gate 			(void) nvlist_add_string(nvl, "cpu.status",
894*c3377ee9SJohn Levon 			    (char *)cpu_get_state_str(cpu->cpu_flags));
8957c478bd9Sstevel@tonic-gate 			buf = NULL;
8967c478bd9Sstevel@tonic-gate 			bufsz = 0;
8977c478bd9Sstevel@tonic-gate 			(void) nvlist_pack(nvl, &buf, &bufsz,
8987c478bd9Sstevel@tonic-gate 			    NV_ENCODE_NATIVE, 0);
8997c478bd9Sstevel@tonic-gate 			(void) ea_attach_item(eo_cpu, buf, bufsz,
9007c478bd9Sstevel@tonic-gate 			    EXC_LOCAL | EXD_CPU_PROP | EXT_RAW);
9017c478bd9Sstevel@tonic-gate 			(void) nvlist_free(nvl);
9027c478bd9Sstevel@tonic-gate 			kmem_free(buf, bufsz);
9037c478bd9Sstevel@tonic-gate 			(void) ea_attach_to_group(eo_pset, eo_cpu);
9047c478bd9Sstevel@tonic-gate 		} while ((cpu = cpu->cpu_next) != cpu_list);
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 		(void) nvlist_dup(pset->pset_props, &nvl, KM_SLEEP);
9077c478bd9Sstevel@tonic-gate 		(void) nvlist_add_uint64(nvl, "pset.size", ncpu);
9087c478bd9Sstevel@tonic-gate 		(void) nvlist_add_uint64(nvl, "pset.load",
9097c478bd9Sstevel@tonic-gate 		    (uint64_t)PSET_LOAD(cpupart->cp_hp_avenrun[0]));
9107c478bd9Sstevel@tonic-gate 		buf = NULL;
9117c478bd9Sstevel@tonic-gate 		bufsz = 0;
9127c478bd9Sstevel@tonic-gate 		(void) nvlist_pack(nvl, &buf, &bufsz, NV_ENCODE_NATIVE, 0);
9137c478bd9Sstevel@tonic-gate 		(void) ea_attach_item(eo_pset, buf, bufsz,
9147c478bd9Sstevel@tonic-gate 		    EXC_LOCAL | EXD_PSET_PROP | EXT_RAW);
9157c478bd9Sstevel@tonic-gate 		(void) nvlist_free(nvl);
9167c478bd9Sstevel@tonic-gate 		kmem_free(buf, bufsz);
9177c478bd9Sstevel@tonic-gate 
9187c478bd9Sstevel@tonic-gate 		(void) ea_attach_to_group(eo_system, eo_pset);
9197c478bd9Sstevel@tonic-gate 	}
9207c478bd9Sstevel@tonic-gate 	mutex_exit(&cpu_lock);
9217c478bd9Sstevel@tonic-gate 	return (0);
9227c478bd9Sstevel@tonic-gate }
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate /*
9257c478bd9Sstevel@tonic-gate  * Get dynamic property for processor sets.
9267c478bd9Sstevel@tonic-gate  * The only dynamic property currently implemented is "pset.load".
9277c478bd9Sstevel@tonic-gate  */
9287c478bd9Sstevel@tonic-gate int
pool_pset_propget(psetid_t psetid,char * name,nvlist_t * nvl)9297c478bd9Sstevel@tonic-gate pool_pset_propget(psetid_t psetid, char *name, nvlist_t *nvl)
9307c478bd9Sstevel@tonic-gate {
9317c478bd9Sstevel@tonic-gate 	cpupart_t *cpupart;
9327c478bd9Sstevel@tonic-gate 	pool_pset_t *pset;
9337c478bd9Sstevel@tonic-gate 	int ret = ESRCH;
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 	mutex_enter(&cpu_lock);
9387c478bd9Sstevel@tonic-gate 	pset = pool_lookup_pset_by_id(psetid);
9397c478bd9Sstevel@tonic-gate 	cpupart = cpupart_find(psetid);
9407c478bd9Sstevel@tonic-gate 	if (cpupart == NULL || pset == NULL) {
9417c478bd9Sstevel@tonic-gate 		mutex_exit(&cpu_lock);
9427c478bd9Sstevel@tonic-gate 		return (EINVAL);
9437c478bd9Sstevel@tonic-gate 	}
9447c478bd9Sstevel@tonic-gate 	if (strcmp(name, "pset.load") == 0)
9457c478bd9Sstevel@tonic-gate 		ret = nvlist_add_uint64(nvl, "pset.load",
9467c478bd9Sstevel@tonic-gate 		    (uint64_t)PSET_LOAD(cpupart->cp_hp_avenrun[0]));
9477c478bd9Sstevel@tonic-gate 	else
9487c478bd9Sstevel@tonic-gate 		ret = EINVAL;
9497c478bd9Sstevel@tonic-gate 	mutex_exit(&cpu_lock);
9507c478bd9Sstevel@tonic-gate 	return (ret);
9517c478bd9Sstevel@tonic-gate }
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate /*
9547c478bd9Sstevel@tonic-gate  * Get dynamic property for CPUs.
9557c478bd9Sstevel@tonic-gate  * The only dynamic property currently implemented is "cpu.status".
9567c478bd9Sstevel@tonic-gate  */
9577c478bd9Sstevel@tonic-gate int
pool_cpu_propget(processorid_t cpuid,char * name,nvlist_t * nvl)9587c478bd9Sstevel@tonic-gate pool_cpu_propget(processorid_t cpuid, char *name, nvlist_t *nvl)
9597c478bd9Sstevel@tonic-gate {
9607c478bd9Sstevel@tonic-gate 	int ret = ESRCH;
9617c478bd9Sstevel@tonic-gate 	cpu_t *cpu;
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate 	ASSERT(pool_lock_held());
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 	mutex_enter(&cpu_lock);
9667c478bd9Sstevel@tonic-gate 	if ((cpu = cpu_get(cpuid)) == NULL) {
9677c478bd9Sstevel@tonic-gate 		mutex_exit(&cpu_lock);
9687c478bd9Sstevel@tonic-gate 		return (ESRCH);
9697c478bd9Sstevel@tonic-gate 	}
9707c478bd9Sstevel@tonic-gate 	if (strcmp(name, "cpu.status") == 0) {
9717c478bd9Sstevel@tonic-gate 		ret = nvlist_add_string(nvl, "cpu.status",
972*c3377ee9SJohn Levon 		    (char *)cpu_get_state_str(cpu->cpu_flags));
9737c478bd9Sstevel@tonic-gate 	} else {
9747c478bd9Sstevel@tonic-gate 		ret = EINVAL;
9757c478bd9Sstevel@tonic-gate 	}
9767c478bd9Sstevel@tonic-gate 	mutex_exit(&cpu_lock);
9777c478bd9Sstevel@tonic-gate 	return (ret);
9787c478bd9Sstevel@tonic-gate }
979