1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/pool.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/pool_impl.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/pool_pset.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/cpupart.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/mutex.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/fss.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/exacct.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/policy.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/class.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/list.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/zone.h> 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate /* 48*7c478bd9Sstevel@tonic-gate * Processor set plugin for pools. 49*7c478bd9Sstevel@tonic-gate * 50*7c478bd9Sstevel@tonic-gate * This file contains various routines used by the common pools layer to create, 51*7c478bd9Sstevel@tonic-gate * modify, and destroy processor sets. All processor sets created by this 52*7c478bd9Sstevel@tonic-gate * plug-in are stored in the pool_pset_list doubly-linked list, which is 53*7c478bd9Sstevel@tonic-gate * guaranteed to always have an entry for the default processor set, 54*7c478bd9Sstevel@tonic-gate * pool_pset_default. 55*7c478bd9Sstevel@tonic-gate * 56*7c478bd9Sstevel@tonic-gate * Interaction with zones: 57*7c478bd9Sstevel@tonic-gate * 58*7c478bd9Sstevel@tonic-gate * If pools are enabled, non-global zones only have visibility into the 59*7c478bd9Sstevel@tonic-gate * pset of the pool to which they are bound. This is accomplished by 60*7c478bd9Sstevel@tonic-gate * changing the set of processors and processor sets which are visible 61*7c478bd9Sstevel@tonic-gate * through both systemcall interfaces and system kstats. 62*7c478bd9Sstevel@tonic-gate * 63*7c478bd9Sstevel@tonic-gate * To avoid grabbing pool_lock() during cpu change operations, we cache 64*7c478bd9Sstevel@tonic-gate * the pset the zone is currently bound to, and can read this value 65*7c478bd9Sstevel@tonic-gate * while under cpu_lock. The special psetid_t token ZONE_PS_INVAL means 66*7c478bd9Sstevel@tonic-gate * that pools are disabled, and provides a mechanism for determining if the 67*7c478bd9Sstevel@tonic-gate * status of pools without grabbing pool_lock(). 68*7c478bd9Sstevel@tonic-gate * 69*7c478bd9Sstevel@tonic-gate * To avoid grabbing any locks to determine the instantaneous value of 70*7c478bd9Sstevel@tonic-gate * the number of configured and online cpus in the zone, we also cache 71*7c478bd9Sstevel@tonic-gate * these values in a zone_t. If these values are zero, the pools 72*7c478bd9Sstevel@tonic-gate * facility must be disabled, in which case relevant systemcall 73*7c478bd9Sstevel@tonic-gate * interfaces will return the values for the system as a whole. 74*7c478bd9Sstevel@tonic-gate * 75*7c478bd9Sstevel@tonic-gate * The various kstat interfaces are dealt with as follows: if pools are 76*7c478bd9Sstevel@tonic-gate * disabled all cpu-related kstats should be exported to all zones. 77*7c478bd9Sstevel@tonic-gate * When pools are enabled we begin maintaining a list of "permitted 78*7c478bd9Sstevel@tonic-gate * zones" on a per-kstat basis. There are various hooks throughout the 79*7c478bd9Sstevel@tonic-gate * code to update this list when certain pools- or cpu-related events 80*7c478bd9Sstevel@tonic-gate * occur. 81*7c478bd9Sstevel@tonic-gate */ 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate static list_t pool_pset_list; /* doubly-linked list of psets */ 84*7c478bd9Sstevel@tonic-gate pool_pset_t *pool_pset_default; /* default pset */ 85*7c478bd9Sstevel@tonic-gate hrtime_t pool_pset_mod; /* last modification time for psets */ 86*7c478bd9Sstevel@tonic-gate hrtime_t pool_cpu_mod; /* last modification time for CPUs */ 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate static pool_pset_t * 89*7c478bd9Sstevel@tonic-gate pool_lookup_pset_by_id(psetid_t psetid) 90*7c478bd9Sstevel@tonic-gate { 91*7c478bd9Sstevel@tonic-gate pool_pset_t *pset = pool_pset_default; 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate for (pset = list_head(&pool_pset_list); pset; 96*7c478bd9Sstevel@tonic-gate pset = list_next(&pool_pset_list, pset)) { 97*7c478bd9Sstevel@tonic-gate if (pset->pset_id == psetid) 98*7c478bd9Sstevel@tonic-gate return (pset); 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate return (NULL); 101*7c478bd9Sstevel@tonic-gate } 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate struct setup_arg { 104*7c478bd9Sstevel@tonic-gate psetid_t psetid; 105*7c478bd9Sstevel@tonic-gate cpu_t *cpu; 106*7c478bd9Sstevel@tonic-gate cpu_setup_t what; 107*7c478bd9Sstevel@tonic-gate }; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate /* 110*7c478bd9Sstevel@tonic-gate * Callback function used to apply a cpu configuration event to a zone. 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate static int 113*7c478bd9Sstevel@tonic-gate pool_pset_setup_cb(zone_t *zone, void *arg) 114*7c478bd9Sstevel@tonic-gate { 115*7c478bd9Sstevel@tonic-gate struct setup_arg *sa = arg; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 118*7c478bd9Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc)); 119*7c478bd9Sstevel@tonic-gate ASSERT(zone != NULL); 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate if (zone == global_zone) 122*7c478bd9Sstevel@tonic-gate return (0); 123*7c478bd9Sstevel@tonic-gate if (zone_pset_get(zone) != sa->psetid) 124*7c478bd9Sstevel@tonic-gate return (0); /* ignore */ 125*7c478bd9Sstevel@tonic-gate switch (sa->what) { 126*7c478bd9Sstevel@tonic-gate case CPU_CONFIG: 127*7c478bd9Sstevel@tonic-gate cpu_visibility_configure(sa->cpu, zone); 128*7c478bd9Sstevel@tonic-gate break; 129*7c478bd9Sstevel@tonic-gate case CPU_UNCONFIG: 130*7c478bd9Sstevel@tonic-gate cpu_visibility_unconfigure(sa->cpu, zone); 131*7c478bd9Sstevel@tonic-gate break; 132*7c478bd9Sstevel@tonic-gate case CPU_ON: 133*7c478bd9Sstevel@tonic-gate cpu_visibility_online(sa->cpu, zone); 134*7c478bd9Sstevel@tonic-gate break; 135*7c478bd9Sstevel@tonic-gate case CPU_OFF: 136*7c478bd9Sstevel@tonic-gate cpu_visibility_offline(sa->cpu, zone); 137*7c478bd9Sstevel@tonic-gate break; 138*7c478bd9Sstevel@tonic-gate case CPU_CPUPART_IN: 139*7c478bd9Sstevel@tonic-gate cpu_visibility_add(sa->cpu, zone); 140*7c478bd9Sstevel@tonic-gate break; 141*7c478bd9Sstevel@tonic-gate case CPU_CPUPART_OUT: 142*7c478bd9Sstevel@tonic-gate cpu_visibility_remove(sa->cpu, zone); 143*7c478bd9Sstevel@tonic-gate break; 144*7c478bd9Sstevel@tonic-gate default: 145*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "invalid cpu_setup_t value %d", sa->what); 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate return (0); 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate /* 151*7c478bd9Sstevel@tonic-gate * Callback function to be executed when a noteworthy cpu event takes 152*7c478bd9Sstevel@tonic-gate * place. Will ensure that the event is reflected by the zones which 153*7c478bd9Sstevel@tonic-gate * were affected by it. 154*7c478bd9Sstevel@tonic-gate */ 155*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 156*7c478bd9Sstevel@tonic-gate static int 157*7c478bd9Sstevel@tonic-gate pool_pset_cpu_setup(cpu_setup_t what, int id, void *arg) 158*7c478bd9Sstevel@tonic-gate { 159*7c478bd9Sstevel@tonic-gate processorid_t cpuid = id; 160*7c478bd9Sstevel@tonic-gate struct setup_arg sarg; 161*7c478bd9Sstevel@tonic-gate int error; 162*7c478bd9Sstevel@tonic-gate cpu_t *c; 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 165*7c478bd9Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc)); 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate if (!pool_pset_enabled()) 168*7c478bd9Sstevel@tonic-gate return (0); 169*7c478bd9Sstevel@tonic-gate if (what != CPU_CONFIG && what != CPU_UNCONFIG && 170*7c478bd9Sstevel@tonic-gate what != CPU_ON && what != CPU_OFF && 171*7c478bd9Sstevel@tonic-gate what != CPU_CPUPART_IN && what != CPU_CPUPART_OUT) 172*7c478bd9Sstevel@tonic-gate return (0); 173*7c478bd9Sstevel@tonic-gate c = cpu_get(cpuid); 174*7c478bd9Sstevel@tonic-gate ASSERT(c != NULL); 175*7c478bd9Sstevel@tonic-gate sarg.psetid = cpupart_query_cpu(c); 176*7c478bd9Sstevel@tonic-gate sarg.cpu = c; 177*7c478bd9Sstevel@tonic-gate sarg.what = what; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate error = zone_walk(pool_pset_setup_cb, &sarg); 180*7c478bd9Sstevel@tonic-gate ASSERT(error == 0); 181*7c478bd9Sstevel@tonic-gate return (0); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate /* 185*7c478bd9Sstevel@tonic-gate * Initialize processor set plugin. Called once at boot time. 186*7c478bd9Sstevel@tonic-gate */ 187*7c478bd9Sstevel@tonic-gate void 188*7c478bd9Sstevel@tonic-gate pool_pset_init(void) 189*7c478bd9Sstevel@tonic-gate { 190*7c478bd9Sstevel@tonic-gate ASSERT(pool_pset_default == NULL); 191*7c478bd9Sstevel@tonic-gate pool_pset_default = kmem_zalloc(sizeof (pool_pset_t), KM_SLEEP); 192*7c478bd9Sstevel@tonic-gate pool_pset_default->pset_id = PS_NONE; 193*7c478bd9Sstevel@tonic-gate pool_pset_default->pset_npools = 1; /* for pool_default */ 194*7c478bd9Sstevel@tonic-gate pool_default->pool_pset = pool_pset_default; 195*7c478bd9Sstevel@tonic-gate list_create(&pool_pset_list, sizeof (pool_pset_t), 196*7c478bd9Sstevel@tonic-gate offsetof(pool_pset_t, pset_link)); 197*7c478bd9Sstevel@tonic-gate list_insert_head(&pool_pset_list, pool_pset_default); 198*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 199*7c478bd9Sstevel@tonic-gate register_cpu_setup_func(pool_pset_cpu_setup, NULL); 200*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate /* 204*7c478bd9Sstevel@tonic-gate * Dummy wrapper function that returns 0 to satisfy zone_walk(). 205*7c478bd9Sstevel@tonic-gate */ 206*7c478bd9Sstevel@tonic-gate static int 207*7c478bd9Sstevel@tonic-gate pool_pset_zone_pset_set(zone_t *zone, void *arg) 208*7c478bd9Sstevel@tonic-gate { 209*7c478bd9Sstevel@tonic-gate psetid_t psetid = (psetid_t)(uintptr_t)arg; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 212*7c478bd9Sstevel@tonic-gate zone_pset_set(zone, psetid); 213*7c478bd9Sstevel@tonic-gate return (0); 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate /* 217*7c478bd9Sstevel@tonic-gate * Enable processor set plugin. 218*7c478bd9Sstevel@tonic-gate */ 219*7c478bd9Sstevel@tonic-gate int 220*7c478bd9Sstevel@tonic-gate pool_pset_enable(void) 221*7c478bd9Sstevel@tonic-gate { 222*7c478bd9Sstevel@tonic-gate int error; 223*7c478bd9Sstevel@tonic-gate nvlist_t *props; 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 226*7c478bd9Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc)); 227*7c478bd9Sstevel@tonic-gate /* 228*7c478bd9Sstevel@tonic-gate * Can't enable pools if there are existing cpu partitions. 229*7c478bd9Sstevel@tonic-gate */ 230*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 231*7c478bd9Sstevel@tonic-gate if (cp_numparts > 1) { 232*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 233*7c478bd9Sstevel@tonic-gate return (EEXIST); 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate /* 237*7c478bd9Sstevel@tonic-gate * We want to switch things such that everything that was tagged with 238*7c478bd9Sstevel@tonic-gate * the special ALL_ZONES token now is explicitly visible to all zones: 239*7c478bd9Sstevel@tonic-gate * first add individual zones to the visibility list then remove the 240*7c478bd9Sstevel@tonic-gate * special "ALL_ZONES" token. There must only be the default pset 241*7c478bd9Sstevel@tonic-gate * (PS_NONE) active if pools are being enabled, so we only need to 242*7c478bd9Sstevel@tonic-gate * deal with it. 243*7c478bd9Sstevel@tonic-gate * 244*7c478bd9Sstevel@tonic-gate * We want to make pool_pset_enabled() start returning B_TRUE before 245*7c478bd9Sstevel@tonic-gate * we call any of the visibility update functions. 246*7c478bd9Sstevel@tonic-gate */ 247*7c478bd9Sstevel@tonic-gate global_zone->zone_psetid = PS_NONE; 248*7c478bd9Sstevel@tonic-gate /* 249*7c478bd9Sstevel@tonic-gate * We need to explicitly handle the global zone since 250*7c478bd9Sstevel@tonic-gate * zone_pset_set() won't modify it. 251*7c478bd9Sstevel@tonic-gate */ 252*7c478bd9Sstevel@tonic-gate pool_pset_visibility_add(PS_NONE, global_zone); 253*7c478bd9Sstevel@tonic-gate /* 254*7c478bd9Sstevel@tonic-gate * A NULL argument means the ALL_ZONES token. 255*7c478bd9Sstevel@tonic-gate */ 256*7c478bd9Sstevel@tonic-gate pool_pset_visibility_remove(PS_NONE, NULL); 257*7c478bd9Sstevel@tonic-gate error = zone_walk(pool_pset_zone_pset_set, (void *)PS_NONE); 258*7c478bd9Sstevel@tonic-gate ASSERT(error == 0); 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate /* 261*7c478bd9Sstevel@tonic-gate * It is safe to drop cpu_lock here. We're still 262*7c478bd9Sstevel@tonic-gate * holding pool_lock so no new cpu partitions can 263*7c478bd9Sstevel@tonic-gate * be created while we're here. 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 266*7c478bd9Sstevel@tonic-gate (void) nvlist_alloc(&pool_pset_default->pset_props, 267*7c478bd9Sstevel@tonic-gate NV_UNIQUE_NAME, KM_SLEEP); 268*7c478bd9Sstevel@tonic-gate props = pool_pset_default->pset_props; 269*7c478bd9Sstevel@tonic-gate (void) nvlist_add_string(props, "pset.name", "pset_default"); 270*7c478bd9Sstevel@tonic-gate (void) nvlist_add_string(props, "pset.comment", ""); 271*7c478bd9Sstevel@tonic-gate (void) nvlist_add_int64(props, "pset.sys_id", PS_NONE); 272*7c478bd9Sstevel@tonic-gate (void) nvlist_add_string(props, "pset.units", "population"); 273*7c478bd9Sstevel@tonic-gate (void) nvlist_add_byte(props, "pset.default", 1); 274*7c478bd9Sstevel@tonic-gate (void) nvlist_add_uint64(props, "pset.max", 65536); 275*7c478bd9Sstevel@tonic-gate (void) nvlist_add_uint64(props, "pset.min", 1); 276*7c478bd9Sstevel@tonic-gate pool_pset_mod = pool_cpu_mod = gethrtime(); 277*7c478bd9Sstevel@tonic-gate return (0); 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate /* 281*7c478bd9Sstevel@tonic-gate * Disable processor set plugin. 282*7c478bd9Sstevel@tonic-gate */ 283*7c478bd9Sstevel@tonic-gate int 284*7c478bd9Sstevel@tonic-gate pool_pset_disable(void) 285*7c478bd9Sstevel@tonic-gate { 286*7c478bd9Sstevel@tonic-gate processorid_t cpuid; 287*7c478bd9Sstevel@tonic-gate cpu_t *cpu; 288*7c478bd9Sstevel@tonic-gate int error; 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 291*7c478bd9Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc)); 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 294*7c478bd9Sstevel@tonic-gate if (cp_numparts > 1) { /* make sure only default pset is left */ 295*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 296*7c478bd9Sstevel@tonic-gate return (EBUSY); 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate /* 299*7c478bd9Sstevel@tonic-gate * Remove all non-system CPU and processor set properties 300*7c478bd9Sstevel@tonic-gate */ 301*7c478bd9Sstevel@tonic-gate for (cpuid = 0; cpuid < NCPU; cpuid++) { 302*7c478bd9Sstevel@tonic-gate if ((cpu = cpu_get(cpuid)) == NULL) 303*7c478bd9Sstevel@tonic-gate continue; 304*7c478bd9Sstevel@tonic-gate if (cpu->cpu_props != NULL) { 305*7c478bd9Sstevel@tonic-gate (void) nvlist_free(cpu->cpu_props); 306*7c478bd9Sstevel@tonic-gate cpu->cpu_props = NULL; 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate /* 311*7c478bd9Sstevel@tonic-gate * We want to switch things such that everything is now visible 312*7c478bd9Sstevel@tonic-gate * to ALL_ZONES: first add the special "ALL_ZONES" token to the 313*7c478bd9Sstevel@tonic-gate * visibility list then remove individual zones. There must 314*7c478bd9Sstevel@tonic-gate * only be the default pset active if pools are being disabled, 315*7c478bd9Sstevel@tonic-gate * so we only need to deal with it. 316*7c478bd9Sstevel@tonic-gate */ 317*7c478bd9Sstevel@tonic-gate error = zone_walk(pool_pset_zone_pset_set, (void *)ZONE_PS_INVAL); 318*7c478bd9Sstevel@tonic-gate ASSERT(error == 0); 319*7c478bd9Sstevel@tonic-gate pool_pset_visibility_add(PS_NONE, NULL); 320*7c478bd9Sstevel@tonic-gate pool_pset_visibility_remove(PS_NONE, global_zone); 321*7c478bd9Sstevel@tonic-gate /* 322*7c478bd9Sstevel@tonic-gate * pool_pset_enabled() will henceforth return B_FALSE. 323*7c478bd9Sstevel@tonic-gate */ 324*7c478bd9Sstevel@tonic-gate global_zone->zone_psetid = ZONE_PS_INVAL; 325*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 326*7c478bd9Sstevel@tonic-gate if (pool_pset_default->pset_props != NULL) { 327*7c478bd9Sstevel@tonic-gate nvlist_free(pool_pset_default->pset_props); 328*7c478bd9Sstevel@tonic-gate pool_pset_default->pset_props = NULL; 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate return (0); 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate /* 334*7c478bd9Sstevel@tonic-gate * Create new processor set and give it a temporary name. 335*7c478bd9Sstevel@tonic-gate */ 336*7c478bd9Sstevel@tonic-gate int 337*7c478bd9Sstevel@tonic-gate pool_pset_create(psetid_t *id) 338*7c478bd9Sstevel@tonic-gate { 339*7c478bd9Sstevel@tonic-gate char pset_name[40]; 340*7c478bd9Sstevel@tonic-gate pool_pset_t *pset; 341*7c478bd9Sstevel@tonic-gate psetid_t psetid; 342*7c478bd9Sstevel@tonic-gate int err; 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 345*7c478bd9Sstevel@tonic-gate if ((err = cpupart_create(&psetid)) != 0) 346*7c478bd9Sstevel@tonic-gate return (err); 347*7c478bd9Sstevel@tonic-gate pset = kmem_alloc(sizeof (pool_pset_t), KM_SLEEP); 348*7c478bd9Sstevel@tonic-gate pset->pset_id = *id = psetid; 349*7c478bd9Sstevel@tonic-gate pset->pset_npools = 0; 350*7c478bd9Sstevel@tonic-gate (void) nvlist_alloc(&pset->pset_props, NV_UNIQUE_NAME, KM_SLEEP); 351*7c478bd9Sstevel@tonic-gate (void) nvlist_add_int64(pset->pset_props, "pset.sys_id", psetid); 352*7c478bd9Sstevel@tonic-gate (void) nvlist_add_byte(pset->pset_props, "pset.default", 0); 353*7c478bd9Sstevel@tonic-gate pool_pset_mod = gethrtime(); 354*7c478bd9Sstevel@tonic-gate (void) snprintf(pset_name, sizeof (pset_name), "pset_%lld", 355*7c478bd9Sstevel@tonic-gate pool_pset_mod); 356*7c478bd9Sstevel@tonic-gate (void) nvlist_add_string(pset->pset_props, "pset.name", pset_name); 357*7c478bd9Sstevel@tonic-gate list_insert_tail(&pool_pset_list, pset); 358*7c478bd9Sstevel@tonic-gate return (0); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate /* 362*7c478bd9Sstevel@tonic-gate * Destroy existing processor set. 363*7c478bd9Sstevel@tonic-gate */ 364*7c478bd9Sstevel@tonic-gate int 365*7c478bd9Sstevel@tonic-gate pool_pset_destroy(psetid_t psetid) 366*7c478bd9Sstevel@tonic-gate { 367*7c478bd9Sstevel@tonic-gate pool_pset_t *pset; 368*7c478bd9Sstevel@tonic-gate int ret; 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate if (psetid == PS_NONE) 373*7c478bd9Sstevel@tonic-gate return (EINVAL); 374*7c478bd9Sstevel@tonic-gate if ((pset = pool_lookup_pset_by_id(psetid)) == NULL) 375*7c478bd9Sstevel@tonic-gate return (ESRCH); 376*7c478bd9Sstevel@tonic-gate if (pset->pset_npools > 0) /* can't destroy associated psets */ 377*7c478bd9Sstevel@tonic-gate return (EBUSY); 378*7c478bd9Sstevel@tonic-gate if ((ret = cpupart_destroy(pset->pset_id)) != 0) 379*7c478bd9Sstevel@tonic-gate return (ret); 380*7c478bd9Sstevel@tonic-gate (void) nvlist_free(pset->pset_props); 381*7c478bd9Sstevel@tonic-gate list_remove(&pool_pset_list, pset); 382*7c478bd9Sstevel@tonic-gate pool_pset_mod = gethrtime(); 383*7c478bd9Sstevel@tonic-gate kmem_free(pset, sizeof (pool_pset_t)); 384*7c478bd9Sstevel@tonic-gate return (0); 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate /* 388*7c478bd9Sstevel@tonic-gate * Change the visibility of a pset (and all contained cpus) in a zone. 389*7c478bd9Sstevel@tonic-gate * A NULL zone argument implies the special ALL_ZONES token. 390*7c478bd9Sstevel@tonic-gate */ 391*7c478bd9Sstevel@tonic-gate static void 392*7c478bd9Sstevel@tonic-gate pool_pset_visibility_change(psetid_t psetid, zone_t *zone, boolean_t add) 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate zoneid_t zoneid = zone ? zone->zone_id : ALL_ZONES; 395*7c478bd9Sstevel@tonic-gate cpupart_t *cp; 396*7c478bd9Sstevel@tonic-gate cpu_t *c; 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 399*7c478bd9Sstevel@tonic-gate ASSERT(psetid != ZONE_PS_INVAL); 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate cp = cpupart_find(psetid); 402*7c478bd9Sstevel@tonic-gate ASSERT(cp != NULL); 403*7c478bd9Sstevel@tonic-gate if (cp->cp_kstat != NULL) { 404*7c478bd9Sstevel@tonic-gate if (add) 405*7c478bd9Sstevel@tonic-gate kstat_zone_add(cp->cp_kstat, zoneid); 406*7c478bd9Sstevel@tonic-gate else 407*7c478bd9Sstevel@tonic-gate kstat_zone_remove(cp->cp_kstat, zoneid); 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate c = cpu_list; 411*7c478bd9Sstevel@tonic-gate do { 412*7c478bd9Sstevel@tonic-gate ASSERT(c != NULL); 413*7c478bd9Sstevel@tonic-gate if (c->cpu_part == cp && !cpu_is_poweredoff(c)) { 414*7c478bd9Sstevel@tonic-gate if (add) 415*7c478bd9Sstevel@tonic-gate cpu_visibility_add(c, zone); 416*7c478bd9Sstevel@tonic-gate else 417*7c478bd9Sstevel@tonic-gate cpu_visibility_remove(c, zone); 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate } while ((c = c->cpu_next) != cpu_list); 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate /* 423*7c478bd9Sstevel@tonic-gate * Make the processor set visible to the zone. A NULL value for 424*7c478bd9Sstevel@tonic-gate * the zone means that the special ALL_ZONES token should be added to 425*7c478bd9Sstevel@tonic-gate * the visibility list. 426*7c478bd9Sstevel@tonic-gate */ 427*7c478bd9Sstevel@tonic-gate void 428*7c478bd9Sstevel@tonic-gate pool_pset_visibility_add(psetid_t psetid, zone_t *zone) 429*7c478bd9Sstevel@tonic-gate { 430*7c478bd9Sstevel@tonic-gate pool_pset_visibility_change(psetid, zone, B_TRUE); 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate /* 434*7c478bd9Sstevel@tonic-gate * Remove zone's visibility into the processor set. A NULL value for 435*7c478bd9Sstevel@tonic-gate * the zone means that the special ALL_ZONES token should be removed 436*7c478bd9Sstevel@tonic-gate * from the visibility list. 437*7c478bd9Sstevel@tonic-gate */ 438*7c478bd9Sstevel@tonic-gate void 439*7c478bd9Sstevel@tonic-gate pool_pset_visibility_remove(psetid_t psetid, zone_t *zone) 440*7c478bd9Sstevel@tonic-gate { 441*7c478bd9Sstevel@tonic-gate pool_pset_visibility_change(psetid, zone, B_FALSE); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate /* 445*7c478bd9Sstevel@tonic-gate * Quick way of seeing if pools are enabled (as far as processor sets are 446*7c478bd9Sstevel@tonic-gate * concerned) without holding pool_lock(). 447*7c478bd9Sstevel@tonic-gate */ 448*7c478bd9Sstevel@tonic-gate boolean_t 449*7c478bd9Sstevel@tonic-gate pool_pset_enabled(void) 450*7c478bd9Sstevel@tonic-gate { 451*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate return (zone_pset_get(global_zone) != ZONE_PS_INVAL); 454*7c478bd9Sstevel@tonic-gate } 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate struct assoc_zone_arg { 457*7c478bd9Sstevel@tonic-gate poolid_t poolid; 458*7c478bd9Sstevel@tonic-gate psetid_t newpsetid; 459*7c478bd9Sstevel@tonic-gate }; 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate /* 462*7c478bd9Sstevel@tonic-gate * Callback function to update a zone's processor set visibility when 463*7c478bd9Sstevel@tonic-gate * a pool is associated with a processor set. 464*7c478bd9Sstevel@tonic-gate */ 465*7c478bd9Sstevel@tonic-gate static int 466*7c478bd9Sstevel@tonic-gate pool_pset_assoc_zone_cb(zone_t *zone, void *arg) 467*7c478bd9Sstevel@tonic-gate { 468*7c478bd9Sstevel@tonic-gate struct assoc_zone_arg *aza = arg; 469*7c478bd9Sstevel@tonic-gate pool_t *pool; 470*7c478bd9Sstevel@tonic-gate zoneid_t zoneid = zone->zone_id; 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 473*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate if (zoneid == GLOBAL_ZONEID) 476*7c478bd9Sstevel@tonic-gate return (0); 477*7c478bd9Sstevel@tonic-gate pool = zone_pool_get(zone); 478*7c478bd9Sstevel@tonic-gate if (pool->pool_id == aza->poolid) 479*7c478bd9Sstevel@tonic-gate zone_pset_set(zone, aza->newpsetid); 480*7c478bd9Sstevel@tonic-gate return (0); 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate /* 484*7c478bd9Sstevel@tonic-gate * Associate pool with new processor set. 485*7c478bd9Sstevel@tonic-gate */ 486*7c478bd9Sstevel@tonic-gate int 487*7c478bd9Sstevel@tonic-gate pool_pset_assoc(poolid_t poolid, psetid_t psetid) 488*7c478bd9Sstevel@tonic-gate { 489*7c478bd9Sstevel@tonic-gate pool_t *pool; 490*7c478bd9Sstevel@tonic-gate pool_pset_t *pset, *oldpset; 491*7c478bd9Sstevel@tonic-gate int err = 0; 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate if ((pool = pool_lookup_pool_by_id(poolid)) == NULL || 496*7c478bd9Sstevel@tonic-gate (pset = pool_lookup_pset_by_id(psetid)) == NULL) { 497*7c478bd9Sstevel@tonic-gate return (ESRCH); 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate if (pool->pool_pset->pset_id == psetid) { 500*7c478bd9Sstevel@tonic-gate /* 501*7c478bd9Sstevel@tonic-gate * Already associated. 502*7c478bd9Sstevel@tonic-gate */ 503*7c478bd9Sstevel@tonic-gate return (0); 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate /* 507*7c478bd9Sstevel@tonic-gate * Hang the new pset off the pool, and rebind all of the pool's 508*7c478bd9Sstevel@tonic-gate * processes to it. If pool_do_bind fails, all processes will remain 509*7c478bd9Sstevel@tonic-gate * bound to the old set. 510*7c478bd9Sstevel@tonic-gate */ 511*7c478bd9Sstevel@tonic-gate oldpset = pool->pool_pset; 512*7c478bd9Sstevel@tonic-gate pool->pool_pset = pset; 513*7c478bd9Sstevel@tonic-gate err = pool_do_bind(pool, P_POOLID, poolid, POOL_BIND_PSET); 514*7c478bd9Sstevel@tonic-gate if (err) { 515*7c478bd9Sstevel@tonic-gate pool->pool_pset = oldpset; 516*7c478bd9Sstevel@tonic-gate } else { 517*7c478bd9Sstevel@tonic-gate struct assoc_zone_arg azarg; 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate /* 520*7c478bd9Sstevel@tonic-gate * Update zones' visibility to reflect changes. 521*7c478bd9Sstevel@tonic-gate */ 522*7c478bd9Sstevel@tonic-gate azarg.poolid = poolid; 523*7c478bd9Sstevel@tonic-gate azarg.newpsetid = pset->pset_id; 524*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 525*7c478bd9Sstevel@tonic-gate err = zone_walk(pool_pset_assoc_zone_cb, &azarg); 526*7c478bd9Sstevel@tonic-gate ASSERT(err == 0); 527*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate oldpset->pset_npools--; 530*7c478bd9Sstevel@tonic-gate pset->pset_npools++; 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate return (err); 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate /* 536*7c478bd9Sstevel@tonic-gate * Transfer specified CPUs between processor sets. 537*7c478bd9Sstevel@tonic-gate */ 538*7c478bd9Sstevel@tonic-gate int 539*7c478bd9Sstevel@tonic-gate pool_pset_xtransfer(psetid_t src, psetid_t dst, size_t size, id_t *ids) 540*7c478bd9Sstevel@tonic-gate { 541*7c478bd9Sstevel@tonic-gate struct cpu *cpu; 542*7c478bd9Sstevel@tonic-gate int ret = 0; 543*7c478bd9Sstevel@tonic-gate int id; 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 546*7c478bd9Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc)); 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate if (size == 0 || size > max_ncpus) /* quick sanity check */ 549*7c478bd9Sstevel@tonic-gate return (EINVAL); 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 552*7c478bd9Sstevel@tonic-gate for (id = 0; id < size; id++) { 553*7c478bd9Sstevel@tonic-gate if ((cpu = cpu_get((processorid_t)ids[id])) == NULL || 554*7c478bd9Sstevel@tonic-gate cpupart_query_cpu(cpu) != src) { 555*7c478bd9Sstevel@tonic-gate ret = EINVAL; 556*7c478bd9Sstevel@tonic-gate break; 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate if ((ret = cpupart_attach_cpu(dst, cpu, 1)) != 0) 559*7c478bd9Sstevel@tonic-gate break; 560*7c478bd9Sstevel@tonic-gate } 561*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 562*7c478bd9Sstevel@tonic-gate if (ret == 0) 563*7c478bd9Sstevel@tonic-gate pool_pset_mod = gethrtime(); 564*7c478bd9Sstevel@tonic-gate return (ret); 565*7c478bd9Sstevel@tonic-gate } 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate /* 568*7c478bd9Sstevel@tonic-gate * Bind process to processor set. This should never fail because 569*7c478bd9Sstevel@tonic-gate * we should've done all preliminary checks before calling it. 570*7c478bd9Sstevel@tonic-gate */ 571*7c478bd9Sstevel@tonic-gate void 572*7c478bd9Sstevel@tonic-gate pool_pset_bind(proc_t *p, psetid_t psetid, void *projbuf, void *zonebuf) 573*7c478bd9Sstevel@tonic-gate { 574*7c478bd9Sstevel@tonic-gate kthread_t *t; 575*7c478bd9Sstevel@tonic-gate int ret; 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 578*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 579*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pidlock)); 580*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate if ((t = p->p_tlist) == NULL) 583*7c478bd9Sstevel@tonic-gate return; 584*7c478bd9Sstevel@tonic-gate do { 585*7c478bd9Sstevel@tonic-gate ret = cpupart_bind_thread(t, psetid, 0, projbuf, zonebuf); 586*7c478bd9Sstevel@tonic-gate ASSERT(ret == 0); 587*7c478bd9Sstevel@tonic-gate t->t_bind_pset = psetid; 588*7c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist); 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate /* 592*7c478bd9Sstevel@tonic-gate * See the comment above pool_do_bind() for the semantics of the pset_bind_*() 593*7c478bd9Sstevel@tonic-gate * functions. These must be kept in sync with cpupart_move_thread, and 594*7c478bd9Sstevel@tonic-gate * anything else that could fail a pool_pset_bind. 595*7c478bd9Sstevel@tonic-gate * 596*7c478bd9Sstevel@tonic-gate * Returns non-zero errno on failure and zero on success. 597*7c478bd9Sstevel@tonic-gate * Iff successful, cpu_lock is held on return. 598*7c478bd9Sstevel@tonic-gate */ 599*7c478bd9Sstevel@tonic-gate int 600*7c478bd9Sstevel@tonic-gate pset_bind_start(proc_t **procs, pool_t *pool) 601*7c478bd9Sstevel@tonic-gate { 602*7c478bd9Sstevel@tonic-gate cred_t *pcred; 603*7c478bd9Sstevel@tonic-gate proc_t *p, **pp; 604*7c478bd9Sstevel@tonic-gate kthread_t *t; 605*7c478bd9Sstevel@tonic-gate cpupart_t *newpp; 606*7c478bd9Sstevel@tonic-gate int ret; 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate extern int cpupart_movable_thread(kthread_id_t, cpupart_t *, int); 609*7c478bd9Sstevel@tonic-gate 610*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 611*7c478bd9Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc)); 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 614*7c478bd9Sstevel@tonic-gate weakbinding_stop(); 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate newpp = cpupart_find(pool->pool_pset->pset_id); 617*7c478bd9Sstevel@tonic-gate ASSERT(newpp != NULL); 618*7c478bd9Sstevel@tonic-gate if (newpp->cp_cpulist == NULL) { 619*7c478bd9Sstevel@tonic-gate weakbinding_start(); 620*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 621*7c478bd9Sstevel@tonic-gate return (ENOTSUP); 622*7c478bd9Sstevel@tonic-gate } 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate pcred = crgetcred(); 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate /* 627*7c478bd9Sstevel@tonic-gate * Check for the PRIV_PROC_PRIOCNTL privilege that is required 628*7c478bd9Sstevel@tonic-gate * to enter and exit scheduling classes. If other privileges 629*7c478bd9Sstevel@tonic-gate * are required by CL_ENTERCLASS/CL_CANEXIT types of routines 630*7c478bd9Sstevel@tonic-gate * in the future, this code will have to be updated. 631*7c478bd9Sstevel@tonic-gate */ 632*7c478bd9Sstevel@tonic-gate if (secpolicy_setpriority(pcred) != 0) { 633*7c478bd9Sstevel@tonic-gate weakbinding_start(); 634*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 635*7c478bd9Sstevel@tonic-gate crfree(pcred); 636*7c478bd9Sstevel@tonic-gate return (EPERM); 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate for (pp = procs; (p = *pp) != NULL; pp++) { 640*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 641*7c478bd9Sstevel@tonic-gate if ((t = p->p_tlist) == NULL) { 642*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 643*7c478bd9Sstevel@tonic-gate continue; 644*7c478bd9Sstevel@tonic-gate } 645*7c478bd9Sstevel@tonic-gate /* 646*7c478bd9Sstevel@tonic-gate * Check our basic permissions to control this process. 647*7c478bd9Sstevel@tonic-gate */ 648*7c478bd9Sstevel@tonic-gate if (!prochasprocperm(p, curproc, pcred)) { 649*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 650*7c478bd9Sstevel@tonic-gate weakbinding_start(); 651*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 652*7c478bd9Sstevel@tonic-gate crfree(pcred); 653*7c478bd9Sstevel@tonic-gate return (EPERM); 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate do { 656*7c478bd9Sstevel@tonic-gate /* 657*7c478bd9Sstevel@tonic-gate * Check that all threads can be moved to 658*7c478bd9Sstevel@tonic-gate * a new processor set. 659*7c478bd9Sstevel@tonic-gate */ 660*7c478bd9Sstevel@tonic-gate thread_lock(t); 661*7c478bd9Sstevel@tonic-gate ret = cpupart_movable_thread(t, newpp, 0); 662*7c478bd9Sstevel@tonic-gate thread_unlock(t); 663*7c478bd9Sstevel@tonic-gate if (ret != 0) { 664*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 665*7c478bd9Sstevel@tonic-gate weakbinding_start(); 666*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 667*7c478bd9Sstevel@tonic-gate crfree(pcred); 668*7c478bd9Sstevel@tonic-gate return (ret); 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist); 671*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 672*7c478bd9Sstevel@tonic-gate } 673*7c478bd9Sstevel@tonic-gate crfree(pcred); 674*7c478bd9Sstevel@tonic-gate return (0); /* with cpu_lock held and weakbinding stopped */ 675*7c478bd9Sstevel@tonic-gate } 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 678*7c478bd9Sstevel@tonic-gate void 679*7c478bd9Sstevel@tonic-gate pset_bind_abort(proc_t **procs, pool_t *pool) 680*7c478bd9Sstevel@tonic-gate { 681*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate void 685*7c478bd9Sstevel@tonic-gate pset_bind_finish(void) 686*7c478bd9Sstevel@tonic-gate { 687*7c478bd9Sstevel@tonic-gate weakbinding_start(); 688*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 689*7c478bd9Sstevel@tonic-gate } 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate static pool_property_t pool_pset_props[] = { 692*7c478bd9Sstevel@tonic-gate { "pset.name", DATA_TYPE_STRING, PP_RDWR }, 693*7c478bd9Sstevel@tonic-gate { "pset.comment", DATA_TYPE_STRING, PP_RDWR }, 694*7c478bd9Sstevel@tonic-gate { "pset.sys_id", DATA_TYPE_UINT64, PP_READ }, 695*7c478bd9Sstevel@tonic-gate { "pset.units", DATA_TYPE_STRING, PP_RDWR }, 696*7c478bd9Sstevel@tonic-gate { "pset.default", DATA_TYPE_BYTE, PP_READ }, 697*7c478bd9Sstevel@tonic-gate { "pset.min", DATA_TYPE_UINT64, PP_RDWR }, 698*7c478bd9Sstevel@tonic-gate { "pset.max", DATA_TYPE_UINT64, PP_RDWR }, 699*7c478bd9Sstevel@tonic-gate { "pset.size", DATA_TYPE_UINT64, PP_READ }, 700*7c478bd9Sstevel@tonic-gate { "pset.load", DATA_TYPE_UINT64, PP_READ }, 701*7c478bd9Sstevel@tonic-gate { "pset.poold.objectives", DATA_TYPE_STRING, 702*7c478bd9Sstevel@tonic-gate PP_RDWR | PP_OPTIONAL }, 703*7c478bd9Sstevel@tonic-gate { NULL, 0, 0 } 704*7c478bd9Sstevel@tonic-gate }; 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate static pool_property_t pool_cpu_props[] = { 707*7c478bd9Sstevel@tonic-gate { "cpu.sys_id", DATA_TYPE_UINT64, PP_READ }, 708*7c478bd9Sstevel@tonic-gate { "cpu.comment", DATA_TYPE_STRING, PP_RDWR }, 709*7c478bd9Sstevel@tonic-gate { "cpu.status", DATA_TYPE_STRING, PP_RDWR }, 710*7c478bd9Sstevel@tonic-gate { "cpu.pinned", DATA_TYPE_BYTE, 711*7c478bd9Sstevel@tonic-gate PP_RDWR | PP_OPTIONAL }, 712*7c478bd9Sstevel@tonic-gate { NULL, 0, 0 } 713*7c478bd9Sstevel@tonic-gate }; 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate /* 716*7c478bd9Sstevel@tonic-gate * Put property on the specified processor set. 717*7c478bd9Sstevel@tonic-gate */ 718*7c478bd9Sstevel@tonic-gate int 719*7c478bd9Sstevel@tonic-gate pool_pset_propput(psetid_t psetid, nvpair_t *pair) 720*7c478bd9Sstevel@tonic-gate { 721*7c478bd9Sstevel@tonic-gate pool_pset_t *pset; 722*7c478bd9Sstevel@tonic-gate int ret; 723*7c478bd9Sstevel@tonic-gate 724*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate if ((pset = pool_lookup_pset_by_id(psetid)) == NULL) 727*7c478bd9Sstevel@tonic-gate return (ESRCH); 728*7c478bd9Sstevel@tonic-gate ret = pool_propput_common(pset->pset_props, pair, pool_pset_props); 729*7c478bd9Sstevel@tonic-gate if (ret == 0) 730*7c478bd9Sstevel@tonic-gate pool_pset_mod = gethrtime(); 731*7c478bd9Sstevel@tonic-gate return (ret); 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate /* 735*7c478bd9Sstevel@tonic-gate * Remove existing processor set property. 736*7c478bd9Sstevel@tonic-gate */ 737*7c478bd9Sstevel@tonic-gate int 738*7c478bd9Sstevel@tonic-gate pool_pset_proprm(psetid_t psetid, char *name) 739*7c478bd9Sstevel@tonic-gate { 740*7c478bd9Sstevel@tonic-gate pool_pset_t *pset; 741*7c478bd9Sstevel@tonic-gate int ret; 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate if ((pset = pool_lookup_pset_by_id(psetid)) == NULL) 746*7c478bd9Sstevel@tonic-gate return (EINVAL); 747*7c478bd9Sstevel@tonic-gate ret = pool_proprm_common(pset->pset_props, name, pool_pset_props); 748*7c478bd9Sstevel@tonic-gate if (ret == 0) 749*7c478bd9Sstevel@tonic-gate pool_pset_mod = gethrtime(); 750*7c478bd9Sstevel@tonic-gate return (ret); 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate /* 754*7c478bd9Sstevel@tonic-gate * Put new CPU property. 755*7c478bd9Sstevel@tonic-gate * Handle special case of "cpu.status". 756*7c478bd9Sstevel@tonic-gate */ 757*7c478bd9Sstevel@tonic-gate int 758*7c478bd9Sstevel@tonic-gate pool_cpu_propput(processorid_t cpuid, nvpair_t *pair) 759*7c478bd9Sstevel@tonic-gate { 760*7c478bd9Sstevel@tonic-gate int ret = 0; 761*7c478bd9Sstevel@tonic-gate cpu_t *cpu; 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 764*7c478bd9Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc)); 765*7c478bd9Sstevel@tonic-gate 766*7c478bd9Sstevel@tonic-gate if (nvpair_type(pair) == DATA_TYPE_STRING && 767*7c478bd9Sstevel@tonic-gate strcmp(nvpair_name(pair), "cpu.status") == 0) { 768*7c478bd9Sstevel@tonic-gate char *val; 769*7c478bd9Sstevel@tonic-gate int status; 770*7c478bd9Sstevel@tonic-gate int old_status; 771*7c478bd9Sstevel@tonic-gate (void) nvpair_value_string(pair, &val); 772*7c478bd9Sstevel@tonic-gate if (strcmp(val, PS_OFFLINE) == 0) 773*7c478bd9Sstevel@tonic-gate status = P_OFFLINE; 774*7c478bd9Sstevel@tonic-gate else if (strcmp(val, PS_ONLINE) == 0) 775*7c478bd9Sstevel@tonic-gate status = P_ONLINE; 776*7c478bd9Sstevel@tonic-gate else if (strcmp(val, PS_NOINTR) == 0) 777*7c478bd9Sstevel@tonic-gate status = P_NOINTR; 778*7c478bd9Sstevel@tonic-gate else if (strcmp(val, PS_FAULTED) == 0) 779*7c478bd9Sstevel@tonic-gate status = P_FAULTED; 780*7c478bd9Sstevel@tonic-gate else if (strcmp(val, PS_SPARE) == 0) 781*7c478bd9Sstevel@tonic-gate status = P_SPARE; 782*7c478bd9Sstevel@tonic-gate else 783*7c478bd9Sstevel@tonic-gate return (EINVAL); 784*7c478bd9Sstevel@tonic-gate ret = p_online_internal(cpuid, status, &old_status); 785*7c478bd9Sstevel@tonic-gate } else { 786*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 787*7c478bd9Sstevel@tonic-gate if ((cpu = cpu_get(cpuid)) == NULL) 788*7c478bd9Sstevel@tonic-gate ret = EINVAL; 789*7c478bd9Sstevel@tonic-gate if (cpu->cpu_props == NULL) { 790*7c478bd9Sstevel@tonic-gate (void) nvlist_alloc(&cpu->cpu_props, 791*7c478bd9Sstevel@tonic-gate NV_UNIQUE_NAME, KM_SLEEP); 792*7c478bd9Sstevel@tonic-gate (void) nvlist_add_string(cpu->cpu_props, 793*7c478bd9Sstevel@tonic-gate "cpu.comment", ""); 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate ret = pool_propput_common(cpu->cpu_props, pair, pool_cpu_props); 796*7c478bd9Sstevel@tonic-gate if (ret == 0) 797*7c478bd9Sstevel@tonic-gate pool_cpu_mod = gethrtime(); 798*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 799*7c478bd9Sstevel@tonic-gate } 800*7c478bd9Sstevel@tonic-gate return (ret); 801*7c478bd9Sstevel@tonic-gate } 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate /* 804*7c478bd9Sstevel@tonic-gate * Remove existing CPU property. 805*7c478bd9Sstevel@tonic-gate */ 806*7c478bd9Sstevel@tonic-gate int 807*7c478bd9Sstevel@tonic-gate pool_cpu_proprm(processorid_t cpuid, char *name) 808*7c478bd9Sstevel@tonic-gate { 809*7c478bd9Sstevel@tonic-gate int ret; 810*7c478bd9Sstevel@tonic-gate cpu_t *cpu; 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 813*7c478bd9Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc)); 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 816*7c478bd9Sstevel@tonic-gate if ((cpu = cpu_get(cpuid)) == NULL || cpu_is_poweredoff(cpu)) { 817*7c478bd9Sstevel@tonic-gate ret = EINVAL; 818*7c478bd9Sstevel@tonic-gate } else { 819*7c478bd9Sstevel@tonic-gate if (cpu->cpu_props == NULL) 820*7c478bd9Sstevel@tonic-gate ret = EINVAL; 821*7c478bd9Sstevel@tonic-gate else 822*7c478bd9Sstevel@tonic-gate ret = pool_proprm_common(cpu->cpu_props, name, 823*7c478bd9Sstevel@tonic-gate pool_cpu_props); 824*7c478bd9Sstevel@tonic-gate } 825*7c478bd9Sstevel@tonic-gate if (ret == 0) 826*7c478bd9Sstevel@tonic-gate pool_cpu_mod = gethrtime(); 827*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 828*7c478bd9Sstevel@tonic-gate return (ret); 829*7c478bd9Sstevel@tonic-gate } 830*7c478bd9Sstevel@tonic-gate 831*7c478bd9Sstevel@tonic-gate /* 832*7c478bd9Sstevel@tonic-gate * This macro returns load average multiplied by 1000 w/o losing precision 833*7c478bd9Sstevel@tonic-gate */ 834*7c478bd9Sstevel@tonic-gate #define PSET_LOAD(f) (((f >> 16) * 1000) + (((f & 0xffff) * 1000) / 0xffff)) 835*7c478bd9Sstevel@tonic-gate 836*7c478bd9Sstevel@tonic-gate /* 837*7c478bd9Sstevel@tonic-gate * Take a snapshot of the current state of processor sets and CPUs, 838*7c478bd9Sstevel@tonic-gate * pack it in the exacct format, and attach it to specified exacct record. 839*7c478bd9Sstevel@tonic-gate */ 840*7c478bd9Sstevel@tonic-gate int 841*7c478bd9Sstevel@tonic-gate pool_pset_pack(ea_object_t *eo_system) 842*7c478bd9Sstevel@tonic-gate { 843*7c478bd9Sstevel@tonic-gate ea_object_t *eo_pset, *eo_cpu; 844*7c478bd9Sstevel@tonic-gate cpupart_t *cpupart; 845*7c478bd9Sstevel@tonic-gate psetid_t mypsetid; 846*7c478bd9Sstevel@tonic-gate pool_pset_t *pset; 847*7c478bd9Sstevel@tonic-gate nvlist_t *nvl; 848*7c478bd9Sstevel@tonic-gate size_t bufsz; 849*7c478bd9Sstevel@tonic-gate cpu_t *cpu; 850*7c478bd9Sstevel@tonic-gate char *buf; 851*7c478bd9Sstevel@tonic-gate int ncpu; 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 856*7c478bd9Sstevel@tonic-gate mypsetid = zone_pset_get(curproc->p_zone); 857*7c478bd9Sstevel@tonic-gate for (pset = list_head(&pool_pset_list); pset; 858*7c478bd9Sstevel@tonic-gate pset = list_next(&pool_pset_list, pset)) { 859*7c478bd9Sstevel@tonic-gate psetid_t psetid = pset->pset_id; 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate if (!INGLOBALZONE(curproc) && mypsetid != psetid) 862*7c478bd9Sstevel@tonic-gate continue; 863*7c478bd9Sstevel@tonic-gate cpupart = cpupart_find(psetid); 864*7c478bd9Sstevel@tonic-gate ASSERT(cpupart != NULL); 865*7c478bd9Sstevel@tonic-gate eo_pset = ea_alloc_group(EXT_GROUP | 866*7c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_GROUP_PSET); 867*7c478bd9Sstevel@tonic-gate (void) ea_attach_item(eo_pset, &psetid, sizeof (id_t), 868*7c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_PSET_PSETID | EXT_UINT32); 869*7c478bd9Sstevel@tonic-gate /* 870*7c478bd9Sstevel@tonic-gate * Pack info for all CPUs in this processor set. 871*7c478bd9Sstevel@tonic-gate */ 872*7c478bd9Sstevel@tonic-gate ncpu = 0; 873*7c478bd9Sstevel@tonic-gate cpu = cpu_list; 874*7c478bd9Sstevel@tonic-gate do { 875*7c478bd9Sstevel@tonic-gate if (cpu->cpu_part != cpupart) /* not our pset */ 876*7c478bd9Sstevel@tonic-gate continue; 877*7c478bd9Sstevel@tonic-gate ncpu++; 878*7c478bd9Sstevel@tonic-gate eo_cpu = ea_alloc_group(EXT_GROUP 879*7c478bd9Sstevel@tonic-gate | EXC_LOCAL | EXD_GROUP_CPU); 880*7c478bd9Sstevel@tonic-gate (void) ea_attach_item(eo_cpu, &cpu->cpu_id, 881*7c478bd9Sstevel@tonic-gate sizeof (processorid_t), 882*7c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_CPU_CPUID | EXT_UINT32); 883*7c478bd9Sstevel@tonic-gate if (cpu->cpu_props == NULL) { 884*7c478bd9Sstevel@tonic-gate (void) nvlist_alloc(&cpu->cpu_props, 885*7c478bd9Sstevel@tonic-gate NV_UNIQUE_NAME, KM_SLEEP); 886*7c478bd9Sstevel@tonic-gate (void) nvlist_add_string(cpu->cpu_props, 887*7c478bd9Sstevel@tonic-gate "cpu.comment", ""); 888*7c478bd9Sstevel@tonic-gate } 889*7c478bd9Sstevel@tonic-gate (void) nvlist_dup(cpu->cpu_props, &nvl, KM_SLEEP); 890*7c478bd9Sstevel@tonic-gate (void) nvlist_add_int64(nvl, "cpu.sys_id", cpu->cpu_id); 891*7c478bd9Sstevel@tonic-gate (void) nvlist_add_string(nvl, "cpu.status", 892*7c478bd9Sstevel@tonic-gate (char *)cpu_get_state_str(cpu)); 893*7c478bd9Sstevel@tonic-gate buf = NULL; 894*7c478bd9Sstevel@tonic-gate bufsz = 0; 895*7c478bd9Sstevel@tonic-gate (void) nvlist_pack(nvl, &buf, &bufsz, 896*7c478bd9Sstevel@tonic-gate NV_ENCODE_NATIVE, 0); 897*7c478bd9Sstevel@tonic-gate (void) ea_attach_item(eo_cpu, buf, bufsz, 898*7c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_CPU_PROP | EXT_RAW); 899*7c478bd9Sstevel@tonic-gate (void) nvlist_free(nvl); 900*7c478bd9Sstevel@tonic-gate kmem_free(buf, bufsz); 901*7c478bd9Sstevel@tonic-gate (void) ea_attach_to_group(eo_pset, eo_cpu); 902*7c478bd9Sstevel@tonic-gate } while ((cpu = cpu->cpu_next) != cpu_list); 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate (void) nvlist_dup(pset->pset_props, &nvl, KM_SLEEP); 905*7c478bd9Sstevel@tonic-gate (void) nvlist_add_uint64(nvl, "pset.size", ncpu); 906*7c478bd9Sstevel@tonic-gate (void) nvlist_add_uint64(nvl, "pset.load", 907*7c478bd9Sstevel@tonic-gate (uint64_t)PSET_LOAD(cpupart->cp_hp_avenrun[0])); 908*7c478bd9Sstevel@tonic-gate buf = NULL; 909*7c478bd9Sstevel@tonic-gate bufsz = 0; 910*7c478bd9Sstevel@tonic-gate (void) nvlist_pack(nvl, &buf, &bufsz, NV_ENCODE_NATIVE, 0); 911*7c478bd9Sstevel@tonic-gate (void) ea_attach_item(eo_pset, buf, bufsz, 912*7c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_PSET_PROP | EXT_RAW); 913*7c478bd9Sstevel@tonic-gate (void) nvlist_free(nvl); 914*7c478bd9Sstevel@tonic-gate kmem_free(buf, bufsz); 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate (void) ea_attach_to_group(eo_system, eo_pset); 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 919*7c478bd9Sstevel@tonic-gate return (0); 920*7c478bd9Sstevel@tonic-gate } 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate /* 923*7c478bd9Sstevel@tonic-gate * Get dynamic property for processor sets. 924*7c478bd9Sstevel@tonic-gate * The only dynamic property currently implemented is "pset.load". 925*7c478bd9Sstevel@tonic-gate */ 926*7c478bd9Sstevel@tonic-gate int 927*7c478bd9Sstevel@tonic-gate pool_pset_propget(psetid_t psetid, char *name, nvlist_t *nvl) 928*7c478bd9Sstevel@tonic-gate { 929*7c478bd9Sstevel@tonic-gate cpupart_t *cpupart; 930*7c478bd9Sstevel@tonic-gate pool_pset_t *pset; 931*7c478bd9Sstevel@tonic-gate int ret = ESRCH; 932*7c478bd9Sstevel@tonic-gate 933*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 936*7c478bd9Sstevel@tonic-gate pset = pool_lookup_pset_by_id(psetid); 937*7c478bd9Sstevel@tonic-gate cpupart = cpupart_find(psetid); 938*7c478bd9Sstevel@tonic-gate if (cpupart == NULL || pset == NULL) { 939*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 940*7c478bd9Sstevel@tonic-gate return (EINVAL); 941*7c478bd9Sstevel@tonic-gate } 942*7c478bd9Sstevel@tonic-gate if (strcmp(name, "pset.load") == 0) 943*7c478bd9Sstevel@tonic-gate ret = nvlist_add_uint64(nvl, "pset.load", 944*7c478bd9Sstevel@tonic-gate (uint64_t)PSET_LOAD(cpupart->cp_hp_avenrun[0])); 945*7c478bd9Sstevel@tonic-gate else 946*7c478bd9Sstevel@tonic-gate ret = EINVAL; 947*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 948*7c478bd9Sstevel@tonic-gate return (ret); 949*7c478bd9Sstevel@tonic-gate } 950*7c478bd9Sstevel@tonic-gate 951*7c478bd9Sstevel@tonic-gate /* 952*7c478bd9Sstevel@tonic-gate * Get dynamic property for CPUs. 953*7c478bd9Sstevel@tonic-gate * The only dynamic property currently implemented is "cpu.status". 954*7c478bd9Sstevel@tonic-gate */ 955*7c478bd9Sstevel@tonic-gate int 956*7c478bd9Sstevel@tonic-gate pool_cpu_propget(processorid_t cpuid, char *name, nvlist_t *nvl) 957*7c478bd9Sstevel@tonic-gate { 958*7c478bd9Sstevel@tonic-gate int ret = ESRCH; 959*7c478bd9Sstevel@tonic-gate cpu_t *cpu; 960*7c478bd9Sstevel@tonic-gate 961*7c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 962*7c478bd9Sstevel@tonic-gate 963*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 964*7c478bd9Sstevel@tonic-gate if ((cpu = cpu_get(cpuid)) == NULL) { 965*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 966*7c478bd9Sstevel@tonic-gate return (ESRCH); 967*7c478bd9Sstevel@tonic-gate } 968*7c478bd9Sstevel@tonic-gate if (strcmp(name, "cpu.status") == 0) { 969*7c478bd9Sstevel@tonic-gate ret = nvlist_add_string(nvl, "cpu.status", 970*7c478bd9Sstevel@tonic-gate (char *)cpu_get_state_str(cpu)); 971*7c478bd9Sstevel@tonic-gate } else { 972*7c478bd9Sstevel@tonic-gate ret = EINVAL; 973*7c478bd9Sstevel@tonic-gate } 974*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 975*7c478bd9Sstevel@tonic-gate return (ret); 976*7c478bd9Sstevel@tonic-gate } 977