1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/systm.h> 31*0Sstevel@tonic-gate #include <sys/cmn_err.h> 32*0Sstevel@tonic-gate #include <sys/cpuvar.h> 33*0Sstevel@tonic-gate #include <sys/thread.h> 34*0Sstevel@tonic-gate #include <sys/disp.h> 35*0Sstevel@tonic-gate #include <sys/kmem.h> 36*0Sstevel@tonic-gate #include <sys/debug.h> 37*0Sstevel@tonic-gate #include <sys/sysmacros.h> 38*0Sstevel@tonic-gate #include <sys/cpupart.h> 39*0Sstevel@tonic-gate #include <sys/pset.h> 40*0Sstevel@tonic-gate #include <sys/modctl.h> 41*0Sstevel@tonic-gate #include <sys/syscall.h> 42*0Sstevel@tonic-gate #include <sys/task.h> 43*0Sstevel@tonic-gate #include <sys/loadavg.h> 44*0Sstevel@tonic-gate #include <sys/fss.h> 45*0Sstevel@tonic-gate #include <sys/pool.h> 46*0Sstevel@tonic-gate #include <sys/pool_pset.h> 47*0Sstevel@tonic-gate #include <sys/policy.h> 48*0Sstevel@tonic-gate #include <sys/zone.h> 49*0Sstevel@tonic-gate #include <sys/contract/process_impl.h> 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate static int pset(int, long, long, long, long); 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate static struct sysent pset_sysent = { 54*0Sstevel@tonic-gate 5, 55*0Sstevel@tonic-gate SE_ARGC | SE_NOUNLOAD, 56*0Sstevel@tonic-gate (int (*)())pset, 57*0Sstevel@tonic-gate }; 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate static struct modlsys modlsys = { 60*0Sstevel@tonic-gate &mod_syscallops, "processor sets", &pset_sysent 61*0Sstevel@tonic-gate }; 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 64*0Sstevel@tonic-gate static struct modlsys modlsys32 = { 65*0Sstevel@tonic-gate &mod_syscallops32, "32-bit pset(2) syscall", &pset_sysent 66*0Sstevel@tonic-gate }; 67*0Sstevel@tonic-gate #endif 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate static struct modlinkage modlinkage = { 70*0Sstevel@tonic-gate MODREV_1, 71*0Sstevel@tonic-gate &modlsys, 72*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 73*0Sstevel@tonic-gate &modlsys32, 74*0Sstevel@tonic-gate #endif 75*0Sstevel@tonic-gate NULL 76*0Sstevel@tonic-gate }; 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate #define PSET_BADATTR(attr) ((~PSET_NOESCAPE) & (attr)) 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate int 81*0Sstevel@tonic-gate _init(void) 82*0Sstevel@tonic-gate { 83*0Sstevel@tonic-gate return (mod_install(&modlinkage)); 84*0Sstevel@tonic-gate } 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate int 87*0Sstevel@tonic-gate _info(struct modinfo *modinfop) 88*0Sstevel@tonic-gate { 89*0Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 90*0Sstevel@tonic-gate } 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate static int 93*0Sstevel@tonic-gate pset_create(psetid_t *psetp) 94*0Sstevel@tonic-gate { 95*0Sstevel@tonic-gate psetid_t newpset; 96*0Sstevel@tonic-gate int error; 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate if (secpolicy_pset(CRED()) != 0) 99*0Sstevel@tonic-gate return (set_errno(EPERM)); 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate pool_lock(); 102*0Sstevel@tonic-gate if (pool_state == POOL_ENABLED) { 103*0Sstevel@tonic-gate pool_unlock(); 104*0Sstevel@tonic-gate return (set_errno(ENOTSUP)); 105*0Sstevel@tonic-gate } 106*0Sstevel@tonic-gate error = cpupart_create(&newpset); 107*0Sstevel@tonic-gate if (error) { 108*0Sstevel@tonic-gate pool_unlock(); 109*0Sstevel@tonic-gate return (set_errno(error)); 110*0Sstevel@tonic-gate } 111*0Sstevel@tonic-gate if (copyout(&newpset, psetp, sizeof (psetid_t)) != 0) { 112*0Sstevel@tonic-gate (void) cpupart_destroy(newpset); 113*0Sstevel@tonic-gate pool_unlock(); 114*0Sstevel@tonic-gate return (set_errno(EFAULT)); 115*0Sstevel@tonic-gate } 116*0Sstevel@tonic-gate pool_unlock(); 117*0Sstevel@tonic-gate return (error); 118*0Sstevel@tonic-gate } 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate static int 121*0Sstevel@tonic-gate pset_destroy(psetid_t pset) 122*0Sstevel@tonic-gate { 123*0Sstevel@tonic-gate int error; 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate if (secpolicy_pset(CRED()) != 0) 126*0Sstevel@tonic-gate return (set_errno(EPERM)); 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate pool_lock(); 129*0Sstevel@tonic-gate if (pool_state == POOL_ENABLED) { 130*0Sstevel@tonic-gate pool_unlock(); 131*0Sstevel@tonic-gate return (set_errno(ENOTSUP)); 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate error = cpupart_destroy(pset); 134*0Sstevel@tonic-gate pool_unlock(); 135*0Sstevel@tonic-gate if (error) 136*0Sstevel@tonic-gate return (set_errno(error)); 137*0Sstevel@tonic-gate else 138*0Sstevel@tonic-gate return (0); 139*0Sstevel@tonic-gate } 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate static int 142*0Sstevel@tonic-gate pset_assign(psetid_t pset, processorid_t cpuid, psetid_t *opset, int forced) 143*0Sstevel@tonic-gate { 144*0Sstevel@tonic-gate psetid_t oldpset; 145*0Sstevel@tonic-gate int error = 0; 146*0Sstevel@tonic-gate cpu_t *cp; 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate if (pset != PS_QUERY && secpolicy_pset(CRED()) != 0) 149*0Sstevel@tonic-gate return (set_errno(EPERM)); 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate pool_lock(); 152*0Sstevel@tonic-gate if (pset != PS_QUERY && pool_state == POOL_ENABLED) { 153*0Sstevel@tonic-gate pool_unlock(); 154*0Sstevel@tonic-gate return (set_errno(ENOTSUP)); 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate mutex_enter(&cpu_lock); 158*0Sstevel@tonic-gate if ((cp = cpu_get(cpuid)) == NULL) { 159*0Sstevel@tonic-gate mutex_exit(&cpu_lock); 160*0Sstevel@tonic-gate pool_unlock(); 161*0Sstevel@tonic-gate return (set_errno(EINVAL)); 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate oldpset = cpupart_query_cpu(cp); 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate if (pset != PS_QUERY) 167*0Sstevel@tonic-gate error = cpupart_attach_cpu(pset, cp, forced); 168*0Sstevel@tonic-gate mutex_exit(&cpu_lock); 169*0Sstevel@tonic-gate pool_unlock(); 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate if (error) 172*0Sstevel@tonic-gate return (set_errno(error)); 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate if (opset != NULL) 175*0Sstevel@tonic-gate if (copyout(&oldpset, opset, sizeof (psetid_t)) != 0) 176*0Sstevel@tonic-gate return (set_errno(EFAULT)); 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate return (0); 179*0Sstevel@tonic-gate } 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate static int 182*0Sstevel@tonic-gate pset_info(psetid_t pset, int *typep, uint_t *numcpusp, 183*0Sstevel@tonic-gate processorid_t *cpulistp) 184*0Sstevel@tonic-gate { 185*0Sstevel@tonic-gate int pset_type; 186*0Sstevel@tonic-gate uint_t user_ncpus = 0, real_ncpus, copy_ncpus; 187*0Sstevel@tonic-gate processorid_t *pset_cpus = NULL; 188*0Sstevel@tonic-gate int error = 0; 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate if (numcpusp != NULL) { 191*0Sstevel@tonic-gate if (copyin(numcpusp, &user_ncpus, sizeof (uint_t)) != 0) 192*0Sstevel@tonic-gate return (set_errno(EFAULT)); 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate if (user_ncpus > max_ncpus) /* sanity check */ 196*0Sstevel@tonic-gate user_ncpus = max_ncpus; 197*0Sstevel@tonic-gate if (user_ncpus != 0 && cpulistp != NULL) 198*0Sstevel@tonic-gate pset_cpus = kmem_alloc(sizeof (processorid_t) * user_ncpus, 199*0Sstevel@tonic-gate KM_SLEEP); 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate real_ncpus = user_ncpus; 202*0Sstevel@tonic-gate if ((error = cpupart_get_cpus(&pset, pset_cpus, &real_ncpus)) != 0) 203*0Sstevel@tonic-gate goto out; 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate /* 206*0Sstevel@tonic-gate * Now copyout the information about this processor set. 207*0Sstevel@tonic-gate */ 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate /* 210*0Sstevel@tonic-gate * Get number of cpus to copy back. If the user didn't pass in 211*0Sstevel@tonic-gate * a big enough buffer, only copy back as many cpus as fits in 212*0Sstevel@tonic-gate * the buffer but copy back the real number of cpus. 213*0Sstevel@tonic-gate */ 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate if (user_ncpus != 0 && cpulistp != NULL) { 216*0Sstevel@tonic-gate copy_ncpus = MIN(real_ncpus, user_ncpus); 217*0Sstevel@tonic-gate if (copyout(pset_cpus, cpulistp, 218*0Sstevel@tonic-gate sizeof (processorid_t) * copy_ncpus) != 0) { 219*0Sstevel@tonic-gate error = EFAULT; 220*0Sstevel@tonic-gate goto out; 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate } 223*0Sstevel@tonic-gate if (pset_cpus != NULL) 224*0Sstevel@tonic-gate kmem_free(pset_cpus, sizeof (processorid_t) * user_ncpus); 225*0Sstevel@tonic-gate if (typep != NULL) { 226*0Sstevel@tonic-gate if (pset == PS_NONE) 227*0Sstevel@tonic-gate pset_type = PS_NONE; 228*0Sstevel@tonic-gate else 229*0Sstevel@tonic-gate pset_type = PS_PRIVATE; 230*0Sstevel@tonic-gate if (copyout(&pset_type, typep, sizeof (int)) != 0) 231*0Sstevel@tonic-gate return (set_errno(EFAULT)); 232*0Sstevel@tonic-gate } 233*0Sstevel@tonic-gate if (numcpusp != NULL) 234*0Sstevel@tonic-gate if (copyout(&real_ncpus, numcpusp, sizeof (uint_t)) != 0) 235*0Sstevel@tonic-gate return (set_errno(EFAULT)); 236*0Sstevel@tonic-gate return (0); 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate out: 239*0Sstevel@tonic-gate if (pset_cpus != NULL) 240*0Sstevel@tonic-gate kmem_free(pset_cpus, sizeof (processorid_t) * user_ncpus); 241*0Sstevel@tonic-gate return (set_errno(error)); 242*0Sstevel@tonic-gate } 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate static int 245*0Sstevel@tonic-gate pset_bind_thread(kthread_t *tp, psetid_t pset, psetid_t *oldpset, void *projbuf, 246*0Sstevel@tonic-gate void *zonebuf) 247*0Sstevel@tonic-gate { 248*0Sstevel@tonic-gate int error = 0; 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate ASSERT(pool_lock_held()); 251*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 252*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ttoproc(tp)->p_lock)); 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate *oldpset = tp->t_bind_pset; 255*0Sstevel@tonic-gate if (pset != PS_QUERY) { 256*0Sstevel@tonic-gate /* 257*0Sstevel@tonic-gate * Must have the same UID as the target process or 258*0Sstevel@tonic-gate * have PRIV_PROC_OWNER privilege. 259*0Sstevel@tonic-gate */ 260*0Sstevel@tonic-gate if (!hasprocperm(tp->t_cred, CRED())) 261*0Sstevel@tonic-gate return (EPERM); 262*0Sstevel@tonic-gate /* 263*0Sstevel@tonic-gate * Unbinding of an unbound thread should always succeed. 264*0Sstevel@tonic-gate */ 265*0Sstevel@tonic-gate if (*oldpset == PS_NONE && pset == PS_NONE) 266*0Sstevel@tonic-gate return (0); 267*0Sstevel@tonic-gate /* 268*0Sstevel@tonic-gate * Only privileged processes can move threads from psets with 269*0Sstevel@tonic-gate * PSET_NOESCAPE attribute. 270*0Sstevel@tonic-gate */ 271*0Sstevel@tonic-gate if ((tp->t_cpupart->cp_attr & PSET_NOESCAPE) && 272*0Sstevel@tonic-gate secpolicy_pset(CRED()) != 0) 273*0Sstevel@tonic-gate return (EPERM); 274*0Sstevel@tonic-gate if ((error = cpupart_bind_thread(tp, pset, 0, 275*0Sstevel@tonic-gate projbuf, zonebuf)) == 0) 276*0Sstevel@tonic-gate tp->t_bind_pset = pset; 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate return (error); 279*0Sstevel@tonic-gate } 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate static int 282*0Sstevel@tonic-gate pset_bind_process(proc_t *pp, psetid_t pset, psetid_t *oldpset, void *projbuf, 283*0Sstevel@tonic-gate void *zonebuf) 284*0Sstevel@tonic-gate { 285*0Sstevel@tonic-gate int error = 0; 286*0Sstevel@tonic-gate kthread_t *tp; 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate /* skip kernel processes */ 289*0Sstevel@tonic-gate if (pset != PS_QUERY && pp->p_flag & SSYS) { 290*0Sstevel@tonic-gate *oldpset = PS_NONE; 291*0Sstevel@tonic-gate return (0); 292*0Sstevel@tonic-gate } 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate mutex_enter(&pp->p_lock); 295*0Sstevel@tonic-gate tp = pp->p_tlist; 296*0Sstevel@tonic-gate if (tp != NULL) { 297*0Sstevel@tonic-gate do { 298*0Sstevel@tonic-gate int rval; 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate rval = pset_bind_thread(tp, pset, oldpset, projbuf, 301*0Sstevel@tonic-gate zonebuf); 302*0Sstevel@tonic-gate if (error == 0) 303*0Sstevel@tonic-gate error = rval; 304*0Sstevel@tonic-gate } while ((tp = tp->t_forw) != pp->p_tlist); 305*0Sstevel@tonic-gate } else 306*0Sstevel@tonic-gate error = ESRCH; 307*0Sstevel@tonic-gate mutex_exit(&pp->p_lock); 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate return (error); 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate static int 313*0Sstevel@tonic-gate pset_bind_task(task_t *tk, psetid_t pset, psetid_t *oldpset, void *projbuf, 314*0Sstevel@tonic-gate void *zonebuf) 315*0Sstevel@tonic-gate { 316*0Sstevel@tonic-gate int error = 0; 317*0Sstevel@tonic-gate proc_t *pp; 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pidlock)); 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate if ((pp = tk->tk_memb_list) == NULL) { 322*0Sstevel@tonic-gate return (ESRCH); 323*0Sstevel@tonic-gate } 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate do { 326*0Sstevel@tonic-gate int rval; 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate rval = pset_bind_process(pp, pset, oldpset, projbuf, zonebuf); 329*0Sstevel@tonic-gate if (error == 0) 330*0Sstevel@tonic-gate error = rval; 331*0Sstevel@tonic-gate } while ((pp = pp->p_tasknext) != tk->tk_memb_list); 332*0Sstevel@tonic-gate 333*0Sstevel@tonic-gate return (error); 334*0Sstevel@tonic-gate } 335*0Sstevel@tonic-gate 336*0Sstevel@tonic-gate static int 337*0Sstevel@tonic-gate pset_bind_project(kproject_t *kpj, psetid_t pset, psetid_t *oldpset, 338*0Sstevel@tonic-gate void *projbuf, void *zonebuf) 339*0Sstevel@tonic-gate { 340*0Sstevel@tonic-gate int error = 0; 341*0Sstevel@tonic-gate proc_t *pp; 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pidlock)); 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate for (pp = practive; pp != NULL; pp = pp->p_next) { 346*0Sstevel@tonic-gate if (pp->p_tlist == NULL) 347*0Sstevel@tonic-gate continue; 348*0Sstevel@tonic-gate if (pp->p_task->tk_proj == kpj) { 349*0Sstevel@tonic-gate int rval; 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate rval = pset_bind_process(pp, pset, oldpset, projbuf, 352*0Sstevel@tonic-gate zonebuf); 353*0Sstevel@tonic-gate if (error == 0) 354*0Sstevel@tonic-gate error = rval; 355*0Sstevel@tonic-gate } 356*0Sstevel@tonic-gate } 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate return (error); 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate static int 362*0Sstevel@tonic-gate pset_bind_zone(zone_t *zptr, psetid_t pset, psetid_t *oldpset, void *projbuf, 363*0Sstevel@tonic-gate void *zonebuf) 364*0Sstevel@tonic-gate { 365*0Sstevel@tonic-gate int error = 0; 366*0Sstevel@tonic-gate proc_t *pp; 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pidlock)); 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate for (pp = practive; pp != NULL; pp = pp->p_next) { 371*0Sstevel@tonic-gate if (pp->p_zone == zptr) { 372*0Sstevel@tonic-gate int rval; 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate rval = pset_bind_process(pp, pset, oldpset, projbuf, 375*0Sstevel@tonic-gate zonebuf); 376*0Sstevel@tonic-gate if (error == 0) 377*0Sstevel@tonic-gate error = rval; 378*0Sstevel@tonic-gate } 379*0Sstevel@tonic-gate } 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate return (error); 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate /* 385*0Sstevel@tonic-gate * Unbind all threads from the specified processor set, or from all 386*0Sstevel@tonic-gate * processor sets. 387*0Sstevel@tonic-gate */ 388*0Sstevel@tonic-gate static int 389*0Sstevel@tonic-gate pset_unbind(psetid_t pset, void *projbuf, void *zonebuf, idtype_t idtype) 390*0Sstevel@tonic-gate { 391*0Sstevel@tonic-gate psetid_t olbind; 392*0Sstevel@tonic-gate kthread_t *tp; 393*0Sstevel@tonic-gate int error = 0; 394*0Sstevel@tonic-gate int rval; 395*0Sstevel@tonic-gate proc_t *pp; 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate if (idtype == P_PSETID && cpupart_find(pset) == NULL) 400*0Sstevel@tonic-gate return (EINVAL); 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate mutex_enter(&pidlock); 403*0Sstevel@tonic-gate for (pp = practive; pp != NULL; pp = pp->p_next) { 404*0Sstevel@tonic-gate mutex_enter(&pp->p_lock); 405*0Sstevel@tonic-gate tp = pp->p_tlist; 406*0Sstevel@tonic-gate /* 407*0Sstevel@tonic-gate * Skip zombies and kernel processes, and processes in 408*0Sstevel@tonic-gate * other zones, if called from a non-global zone. 409*0Sstevel@tonic-gate */ 410*0Sstevel@tonic-gate if (tp == NULL || (pp->p_flag & SSYS) || 411*0Sstevel@tonic-gate !HASZONEACCESS(curproc, pp->p_zone->zone_id)) { 412*0Sstevel@tonic-gate mutex_exit(&pp->p_lock); 413*0Sstevel@tonic-gate continue; 414*0Sstevel@tonic-gate } 415*0Sstevel@tonic-gate do { 416*0Sstevel@tonic-gate if ((idtype == P_PSETID && tp->t_bind_pset != pset) || 417*0Sstevel@tonic-gate (idtype == P_ALL && tp->t_bind_pset == PS_NONE)) 418*0Sstevel@tonic-gate continue; 419*0Sstevel@tonic-gate rval = pset_bind_thread(tp, PS_NONE, &olbind, 420*0Sstevel@tonic-gate projbuf, zonebuf); 421*0Sstevel@tonic-gate if (error == 0) 422*0Sstevel@tonic-gate error = rval; 423*0Sstevel@tonic-gate } while ((tp = tp->t_forw) != pp->p_tlist); 424*0Sstevel@tonic-gate mutex_exit(&pp->p_lock); 425*0Sstevel@tonic-gate } 426*0Sstevel@tonic-gate mutex_exit(&pidlock); 427*0Sstevel@tonic-gate return (error); 428*0Sstevel@tonic-gate } 429*0Sstevel@tonic-gate 430*0Sstevel@tonic-gate static int 431*0Sstevel@tonic-gate pset_bind_contract(cont_process_t *ctp, psetid_t pset, psetid_t *oldpset, 432*0Sstevel@tonic-gate void *projbuf, void *zonebuf) 433*0Sstevel@tonic-gate { 434*0Sstevel@tonic-gate int error = 0; 435*0Sstevel@tonic-gate proc_t *pp; 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pidlock)); 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate for (pp = practive; pp != NULL; pp = pp->p_next) { 440*0Sstevel@tonic-gate if (pp->p_ct_process == ctp) { 441*0Sstevel@tonic-gate int rval; 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate rval = pset_bind_process(pp, pset, oldpset, projbuf, 444*0Sstevel@tonic-gate zonebuf); 445*0Sstevel@tonic-gate if (error == 0) 446*0Sstevel@tonic-gate error = rval; 447*0Sstevel@tonic-gate } 448*0Sstevel@tonic-gate } 449*0Sstevel@tonic-gate 450*0Sstevel@tonic-gate return (error); 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate static int 454*0Sstevel@tonic-gate pset_bind(psetid_t pset, idtype_t idtype, id_t id, psetid_t *opset) 455*0Sstevel@tonic-gate { 456*0Sstevel@tonic-gate kthread_t *tp; 457*0Sstevel@tonic-gate proc_t *pp; 458*0Sstevel@tonic-gate task_t *tk; 459*0Sstevel@tonic-gate kproject_t *kpj; 460*0Sstevel@tonic-gate contract_t *ct; 461*0Sstevel@tonic-gate zone_t *zptr; 462*0Sstevel@tonic-gate psetid_t oldpset; 463*0Sstevel@tonic-gate int error = 0; 464*0Sstevel@tonic-gate void *projbuf, *zonebuf; 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate pool_lock(); 467*0Sstevel@tonic-gate if (pset != PS_QUERY) { 468*0Sstevel@tonic-gate /* 469*0Sstevel@tonic-gate * Check if the set actually exists before checking 470*0Sstevel@tonic-gate * permissions. This is the historical error 471*0Sstevel@tonic-gate * precedence. Note that if pset was PS_MYID, the 472*0Sstevel@tonic-gate * cpupart_get_cpus call will change it to the 473*0Sstevel@tonic-gate * processor set id of the caller (or PS_NONE if the 474*0Sstevel@tonic-gate * caller is not bound to a processor set). 475*0Sstevel@tonic-gate */ 476*0Sstevel@tonic-gate if (pool_state == POOL_ENABLED) { 477*0Sstevel@tonic-gate pool_unlock(); 478*0Sstevel@tonic-gate return (set_errno(ENOTSUP)); 479*0Sstevel@tonic-gate } 480*0Sstevel@tonic-gate if (cpupart_get_cpus(&pset, NULL, NULL) != 0) { 481*0Sstevel@tonic-gate pool_unlock(); 482*0Sstevel@tonic-gate return (set_errno(EINVAL)); 483*0Sstevel@tonic-gate } else if (pset != PS_NONE && secpolicy_pset(CRED()) != 0) { 484*0Sstevel@tonic-gate pool_unlock(); 485*0Sstevel@tonic-gate return (set_errno(EPERM)); 486*0Sstevel@tonic-gate } 487*0Sstevel@tonic-gate } 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate /* 490*0Sstevel@tonic-gate * Pre-allocate enough buffers for FSS for all active projects 491*0Sstevel@tonic-gate * and for all active zones on the system. Unused buffers will 492*0Sstevel@tonic-gate * be freed later by fss_freebuf(). 493*0Sstevel@tonic-gate */ 494*0Sstevel@tonic-gate mutex_enter(&cpu_lock); 495*0Sstevel@tonic-gate projbuf = fss_allocbuf(FSS_NPROJ_BUF, FSS_ALLOC_PROJ); 496*0Sstevel@tonic-gate zonebuf = fss_allocbuf(FSS_NPROJ_BUF, FSS_ALLOC_ZONE); 497*0Sstevel@tonic-gate 498*0Sstevel@tonic-gate switch (idtype) { 499*0Sstevel@tonic-gate case P_LWPID: 500*0Sstevel@tonic-gate pp = curproc; 501*0Sstevel@tonic-gate mutex_enter(&pidlock); 502*0Sstevel@tonic-gate mutex_enter(&pp->p_lock); 503*0Sstevel@tonic-gate if (id == P_MYID) { 504*0Sstevel@tonic-gate tp = curthread; 505*0Sstevel@tonic-gate } else { 506*0Sstevel@tonic-gate if ((tp = idtot(pp, id)) == NULL) { 507*0Sstevel@tonic-gate mutex_exit(&pp->p_lock); 508*0Sstevel@tonic-gate mutex_exit(&pidlock); 509*0Sstevel@tonic-gate error = ESRCH; 510*0Sstevel@tonic-gate break; 511*0Sstevel@tonic-gate } 512*0Sstevel@tonic-gate } 513*0Sstevel@tonic-gate error = pset_bind_thread(tp, pset, &oldpset, projbuf, zonebuf); 514*0Sstevel@tonic-gate mutex_exit(&pp->p_lock); 515*0Sstevel@tonic-gate mutex_exit(&pidlock); 516*0Sstevel@tonic-gate break; 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate case P_PID: 519*0Sstevel@tonic-gate mutex_enter(&pidlock); 520*0Sstevel@tonic-gate if (id == P_MYID) { 521*0Sstevel@tonic-gate pp = curproc; 522*0Sstevel@tonic-gate } else if ((pp = prfind(id)) == NULL) { 523*0Sstevel@tonic-gate mutex_exit(&pidlock); 524*0Sstevel@tonic-gate error = ESRCH; 525*0Sstevel@tonic-gate break; 526*0Sstevel@tonic-gate } 527*0Sstevel@tonic-gate error = pset_bind_process(pp, pset, &oldpset, projbuf, zonebuf); 528*0Sstevel@tonic-gate mutex_exit(&pidlock); 529*0Sstevel@tonic-gate break; 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate case P_TASKID: 532*0Sstevel@tonic-gate mutex_enter(&pidlock); 533*0Sstevel@tonic-gate if (id == P_MYID) 534*0Sstevel@tonic-gate id = curproc->p_task->tk_tkid; 535*0Sstevel@tonic-gate if ((tk = task_hold_by_id(id)) == NULL) { 536*0Sstevel@tonic-gate mutex_exit(&pidlock); 537*0Sstevel@tonic-gate error = ESRCH; 538*0Sstevel@tonic-gate break; 539*0Sstevel@tonic-gate } 540*0Sstevel@tonic-gate error = pset_bind_task(tk, pset, &oldpset, projbuf, zonebuf); 541*0Sstevel@tonic-gate mutex_exit(&pidlock); 542*0Sstevel@tonic-gate task_rele(tk); 543*0Sstevel@tonic-gate break; 544*0Sstevel@tonic-gate 545*0Sstevel@tonic-gate case P_PROJID: 546*0Sstevel@tonic-gate if (id == P_MYID) 547*0Sstevel@tonic-gate id = curprojid(); 548*0Sstevel@tonic-gate if ((kpj = project_hold_by_id(id, getzoneid(), 549*0Sstevel@tonic-gate PROJECT_HOLD_FIND)) == NULL) { 550*0Sstevel@tonic-gate error = ESRCH; 551*0Sstevel@tonic-gate break; 552*0Sstevel@tonic-gate } 553*0Sstevel@tonic-gate mutex_enter(&pidlock); 554*0Sstevel@tonic-gate error = pset_bind_project(kpj, pset, &oldpset, projbuf, 555*0Sstevel@tonic-gate zonebuf); 556*0Sstevel@tonic-gate mutex_exit(&pidlock); 557*0Sstevel@tonic-gate project_rele(kpj); 558*0Sstevel@tonic-gate break; 559*0Sstevel@tonic-gate 560*0Sstevel@tonic-gate case P_ZONEID: 561*0Sstevel@tonic-gate if (id == P_MYID) 562*0Sstevel@tonic-gate id = getzoneid(); 563*0Sstevel@tonic-gate if ((zptr = zone_find_by_id(id)) == NULL) { 564*0Sstevel@tonic-gate error = ESRCH; 565*0Sstevel@tonic-gate break; 566*0Sstevel@tonic-gate } 567*0Sstevel@tonic-gate mutex_enter(&pidlock); 568*0Sstevel@tonic-gate error = pset_bind_zone(zptr, pset, &oldpset, projbuf, zonebuf); 569*0Sstevel@tonic-gate mutex_exit(&pidlock); 570*0Sstevel@tonic-gate zone_rele(zptr); 571*0Sstevel@tonic-gate break; 572*0Sstevel@tonic-gate 573*0Sstevel@tonic-gate case P_CTID: 574*0Sstevel@tonic-gate if (id == P_MYID) 575*0Sstevel@tonic-gate id = PRCTID(curproc); 576*0Sstevel@tonic-gate if ((ct = contract_type_ptr(process_type, id, 577*0Sstevel@tonic-gate curproc->p_zone->zone_uniqid)) == NULL) { 578*0Sstevel@tonic-gate error = ESRCH; 579*0Sstevel@tonic-gate break; 580*0Sstevel@tonic-gate } 581*0Sstevel@tonic-gate mutex_enter(&pidlock); 582*0Sstevel@tonic-gate error = pset_bind_contract(ct->ct_data, pset, &oldpset, projbuf, 583*0Sstevel@tonic-gate zonebuf); 584*0Sstevel@tonic-gate mutex_exit(&pidlock); 585*0Sstevel@tonic-gate contract_rele(ct); 586*0Sstevel@tonic-gate break; 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gate case P_PSETID: 589*0Sstevel@tonic-gate if (id == P_MYID || pset != PS_NONE || !INGLOBALZONE(curproc)) { 590*0Sstevel@tonic-gate error = EINVAL; 591*0Sstevel@tonic-gate break; 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate error = pset_unbind(id, projbuf, zonebuf, idtype); 594*0Sstevel@tonic-gate break; 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate case P_ALL: 597*0Sstevel@tonic-gate if (id == P_MYID || pset != PS_NONE || !INGLOBALZONE(curproc)) { 598*0Sstevel@tonic-gate error = EINVAL; 599*0Sstevel@tonic-gate break; 600*0Sstevel@tonic-gate } 601*0Sstevel@tonic-gate error = pset_unbind(PS_NONE, projbuf, zonebuf, idtype); 602*0Sstevel@tonic-gate break; 603*0Sstevel@tonic-gate 604*0Sstevel@tonic-gate default: 605*0Sstevel@tonic-gate error = EINVAL; 606*0Sstevel@tonic-gate break; 607*0Sstevel@tonic-gate } 608*0Sstevel@tonic-gate 609*0Sstevel@tonic-gate fss_freebuf(projbuf, FSS_ALLOC_PROJ); 610*0Sstevel@tonic-gate fss_freebuf(zonebuf, FSS_ALLOC_ZONE); 611*0Sstevel@tonic-gate mutex_exit(&cpu_lock); 612*0Sstevel@tonic-gate pool_unlock(); 613*0Sstevel@tonic-gate 614*0Sstevel@tonic-gate if (error != 0) 615*0Sstevel@tonic-gate return (set_errno(error)); 616*0Sstevel@tonic-gate if (opset != NULL) { 617*0Sstevel@tonic-gate if (copyout(&oldpset, opset, sizeof (psetid_t)) != 0) 618*0Sstevel@tonic-gate return (set_errno(EFAULT)); 619*0Sstevel@tonic-gate } 620*0Sstevel@tonic-gate return (0); 621*0Sstevel@tonic-gate } 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate /* 624*0Sstevel@tonic-gate * Report load average statistics for the specified processor set. 625*0Sstevel@tonic-gate */ 626*0Sstevel@tonic-gate static int 627*0Sstevel@tonic-gate pset_getloadavg(psetid_t pset, int *buf, int nelem) 628*0Sstevel@tonic-gate { 629*0Sstevel@tonic-gate int *loadbuf; 630*0Sstevel@tonic-gate int error = 0; 631*0Sstevel@tonic-gate 632*0Sstevel@tonic-gate if (nelem < 0) 633*0Sstevel@tonic-gate return (set_errno(EINVAL)); 634*0Sstevel@tonic-gate 635*0Sstevel@tonic-gate /* 636*0Sstevel@tonic-gate * We keep the same number of load average statistics for processor 637*0Sstevel@tonic-gate * sets as we do for the system as a whole. 638*0Sstevel@tonic-gate */ 639*0Sstevel@tonic-gate if (nelem > LOADAVG_NSTATS) 640*0Sstevel@tonic-gate nelem = LOADAVG_NSTATS; 641*0Sstevel@tonic-gate 642*0Sstevel@tonic-gate loadbuf = kmem_alloc(nelem * sizeof (int), KM_SLEEP); 643*0Sstevel@tonic-gate 644*0Sstevel@tonic-gate mutex_enter(&cpu_lock); 645*0Sstevel@tonic-gate error = cpupart_get_loadavg(pset, loadbuf, nelem); 646*0Sstevel@tonic-gate mutex_exit(&cpu_lock); 647*0Sstevel@tonic-gate if (!error && nelem && copyout(loadbuf, buf, nelem * sizeof (int)) != 0) 648*0Sstevel@tonic-gate error = EFAULT; 649*0Sstevel@tonic-gate 650*0Sstevel@tonic-gate kmem_free(loadbuf, nelem * sizeof (int)); 651*0Sstevel@tonic-gate 652*0Sstevel@tonic-gate if (error) 653*0Sstevel@tonic-gate return (set_errno(error)); 654*0Sstevel@tonic-gate else 655*0Sstevel@tonic-gate return (0); 656*0Sstevel@tonic-gate } 657*0Sstevel@tonic-gate 658*0Sstevel@tonic-gate 659*0Sstevel@tonic-gate /* 660*0Sstevel@tonic-gate * Return list of active processor sets, up to a maximum indicated by 661*0Sstevel@tonic-gate * numpsets. The total number of processor sets is stored in the 662*0Sstevel@tonic-gate * location pointed to by numpsets. 663*0Sstevel@tonic-gate */ 664*0Sstevel@tonic-gate static int 665*0Sstevel@tonic-gate pset_list(psetid_t *psetlist, uint_t *numpsets) 666*0Sstevel@tonic-gate { 667*0Sstevel@tonic-gate uint_t user_npsets = 0; 668*0Sstevel@tonic-gate uint_t real_npsets; 669*0Sstevel@tonic-gate psetid_t *psets = NULL; 670*0Sstevel@tonic-gate int error = 0; 671*0Sstevel@tonic-gate 672*0Sstevel@tonic-gate if (numpsets != NULL) { 673*0Sstevel@tonic-gate if (copyin(numpsets, &user_npsets, sizeof (uint_t)) != 0) 674*0Sstevel@tonic-gate return (set_errno(EFAULT)); 675*0Sstevel@tonic-gate } 676*0Sstevel@tonic-gate 677*0Sstevel@tonic-gate /* 678*0Sstevel@tonic-gate * Get the list of all processor sets. First we need to find 679*0Sstevel@tonic-gate * out how many there are, so we can allocate a large enough 680*0Sstevel@tonic-gate * buffer. 681*0Sstevel@tonic-gate */ 682*0Sstevel@tonic-gate mutex_enter(&cpu_lock); 683*0Sstevel@tonic-gate if (!INGLOBALZONE(curproc) && pool_pset_enabled()) { 684*0Sstevel@tonic-gate psetid_t psetid = zone_pset_get(curproc->p_zone); 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gate if (psetid == PS_NONE) { 687*0Sstevel@tonic-gate real_npsets = 0; 688*0Sstevel@tonic-gate } else { 689*0Sstevel@tonic-gate real_npsets = 1; 690*0Sstevel@tonic-gate psets = kmem_alloc(real_npsets * sizeof (psetid_t), 691*0Sstevel@tonic-gate KM_SLEEP); 692*0Sstevel@tonic-gate psets[0] = psetid; 693*0Sstevel@tonic-gate } 694*0Sstevel@tonic-gate } else { 695*0Sstevel@tonic-gate real_npsets = cpupart_list(0, NULL, CP_ALL); 696*0Sstevel@tonic-gate if (real_npsets) { 697*0Sstevel@tonic-gate psets = kmem_alloc(real_npsets * sizeof (psetid_t), 698*0Sstevel@tonic-gate KM_SLEEP); 699*0Sstevel@tonic-gate (void) cpupart_list(psets, real_npsets, CP_ALL); 700*0Sstevel@tonic-gate } 701*0Sstevel@tonic-gate } 702*0Sstevel@tonic-gate mutex_exit(&cpu_lock); 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gate if (user_npsets > real_npsets) 705*0Sstevel@tonic-gate user_npsets = real_npsets; 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gate if (numpsets != NULL) { 708*0Sstevel@tonic-gate if (copyout(&real_npsets, numpsets, sizeof (uint_t)) != 0) 709*0Sstevel@tonic-gate error = EFAULT; 710*0Sstevel@tonic-gate else if (psetlist != NULL && user_npsets != 0) { 711*0Sstevel@tonic-gate if (copyout(psets, psetlist, 712*0Sstevel@tonic-gate user_npsets * sizeof (psetid_t)) != 0) 713*0Sstevel@tonic-gate error = EFAULT; 714*0Sstevel@tonic-gate } 715*0Sstevel@tonic-gate } 716*0Sstevel@tonic-gate 717*0Sstevel@tonic-gate if (real_npsets) 718*0Sstevel@tonic-gate kmem_free(psets, real_npsets * sizeof (psetid_t)); 719*0Sstevel@tonic-gate 720*0Sstevel@tonic-gate if (error) 721*0Sstevel@tonic-gate return (set_errno(error)); 722*0Sstevel@tonic-gate else 723*0Sstevel@tonic-gate return (0); 724*0Sstevel@tonic-gate } 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate static int 727*0Sstevel@tonic-gate pset_setattr(psetid_t pset, uint_t attr) 728*0Sstevel@tonic-gate { 729*0Sstevel@tonic-gate int error; 730*0Sstevel@tonic-gate 731*0Sstevel@tonic-gate if (secpolicy_pset(CRED()) != 0) 732*0Sstevel@tonic-gate return (set_errno(EPERM)); 733*0Sstevel@tonic-gate pool_lock(); 734*0Sstevel@tonic-gate if (pool_state == POOL_ENABLED) { 735*0Sstevel@tonic-gate pool_unlock(); 736*0Sstevel@tonic-gate return (set_errno(ENOTSUP)); 737*0Sstevel@tonic-gate } 738*0Sstevel@tonic-gate if (pset == PS_QUERY || PSET_BADATTR(attr)) { 739*0Sstevel@tonic-gate pool_unlock(); 740*0Sstevel@tonic-gate return (set_errno(EINVAL)); 741*0Sstevel@tonic-gate } 742*0Sstevel@tonic-gate if ((error = cpupart_setattr(pset, attr)) != 0) { 743*0Sstevel@tonic-gate pool_unlock(); 744*0Sstevel@tonic-gate return (set_errno(error)); 745*0Sstevel@tonic-gate } 746*0Sstevel@tonic-gate pool_unlock(); 747*0Sstevel@tonic-gate return (0); 748*0Sstevel@tonic-gate } 749*0Sstevel@tonic-gate 750*0Sstevel@tonic-gate static int 751*0Sstevel@tonic-gate pset_getattr(psetid_t pset, uint_t *attrp) 752*0Sstevel@tonic-gate { 753*0Sstevel@tonic-gate int error = 0; 754*0Sstevel@tonic-gate uint_t attr; 755*0Sstevel@tonic-gate 756*0Sstevel@tonic-gate if (pset == PS_QUERY) 757*0Sstevel@tonic-gate return (set_errno(EINVAL)); 758*0Sstevel@tonic-gate if ((error = cpupart_getattr(pset, &attr)) != 0) 759*0Sstevel@tonic-gate return (set_errno(error)); 760*0Sstevel@tonic-gate if (copyout(&attr, attrp, sizeof (uint_t)) != 0) 761*0Sstevel@tonic-gate return (set_errno(EFAULT)); 762*0Sstevel@tonic-gate return (0); 763*0Sstevel@tonic-gate } 764*0Sstevel@tonic-gate 765*0Sstevel@tonic-gate static int 766*0Sstevel@tonic-gate pset(int subcode, long arg1, long arg2, long arg3, long arg4) 767*0Sstevel@tonic-gate { 768*0Sstevel@tonic-gate switch (subcode) { 769*0Sstevel@tonic-gate case PSET_CREATE: 770*0Sstevel@tonic-gate return (pset_create((psetid_t *)arg1)); 771*0Sstevel@tonic-gate case PSET_DESTROY: 772*0Sstevel@tonic-gate return (pset_destroy((psetid_t)arg1)); 773*0Sstevel@tonic-gate case PSET_ASSIGN: 774*0Sstevel@tonic-gate return (pset_assign((psetid_t)arg1, 775*0Sstevel@tonic-gate (processorid_t)arg2, (psetid_t *)arg3, 0)); 776*0Sstevel@tonic-gate case PSET_INFO: 777*0Sstevel@tonic-gate return (pset_info((psetid_t)arg1, (int *)arg2, 778*0Sstevel@tonic-gate (uint_t *)arg3, (processorid_t *)arg4)); 779*0Sstevel@tonic-gate case PSET_BIND: 780*0Sstevel@tonic-gate return (pset_bind((psetid_t)arg1, (idtype_t)arg2, 781*0Sstevel@tonic-gate (id_t)arg3, (psetid_t *)arg4)); 782*0Sstevel@tonic-gate case PSET_GETLOADAVG: 783*0Sstevel@tonic-gate return (pset_getloadavg((psetid_t)arg1, (int *)arg2, 784*0Sstevel@tonic-gate (int)arg3)); 785*0Sstevel@tonic-gate case PSET_LIST: 786*0Sstevel@tonic-gate return (pset_list((psetid_t *)arg1, (uint_t *)arg2)); 787*0Sstevel@tonic-gate case PSET_SETATTR: 788*0Sstevel@tonic-gate return (pset_setattr((psetid_t)arg1, (uint_t)arg2)); 789*0Sstevel@tonic-gate case PSET_GETATTR: 790*0Sstevel@tonic-gate return (pset_getattr((psetid_t)arg1, (uint_t *)arg2)); 791*0Sstevel@tonic-gate case PSET_ASSIGN_FORCED: 792*0Sstevel@tonic-gate return (pset_assign((psetid_t)arg1, 793*0Sstevel@tonic-gate (processorid_t)arg2, (psetid_t *)arg3, 1)); 794*0Sstevel@tonic-gate default: 795*0Sstevel@tonic-gate return (set_errno(EINVAL)); 796*0Sstevel@tonic-gate } 797*0Sstevel@tonic-gate } 798