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