Home | History | Annotate | Download | only in proc
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     27 /*	  All rights reserved.  	*/
     28 
     29 #include <sys/types.h>
     30 #include <sys/param.h>
     31 #include <sys/vmparam.h>
     32 #include <sys/var.h>
     33 #include <sys/cmn_err.h>
     34 #include <sys/cred.h>
     35 #include <sys/debug.h>
     36 #include <sys/errno.h>
     37 #include <sys/file.h>
     38 #include <sys/inline.h>
     39 #include <sys/kmem.h>
     40 #include <sys/proc.h>
     41 #include <sys/sysmacros.h>
     42 #include <sys/systm.h>
     43 #include <sys/vfs.h>
     44 #include <sys/vnode.h>
     45 #include <sys/cpuvar.h>
     46 #include <sys/session.h>
     47 #include <sys/signal.h>
     48 #include <sys/auxv.h>
     49 #include <sys/user.h>
     50 #include <sys/disp.h>
     51 #include <sys/class.h>
     52 #include <sys/ts.h>
     53 #include <sys/mman.h>
     54 #include <sys/fault.h>
     55 #include <sys/syscall.h>
     56 #include <sys/schedctl.h>
     57 #include <sys/pset.h>
     58 #include <sys/old_procfs.h>
     59 #include <sys/zone.h>
     60 #include <sys/time.h>
     61 #include <sys/msacct.h>
     62 #include <vm/rm.h>
     63 #include <vm/as.h>
     64 #include <vm/rm.h>
     65 #include <vm/seg.h>
     66 #include <vm/seg_vn.h>
     67 #include <sys/contract_impl.h>
     68 #include <sys/ctfs_impl.h>
     69 #include <sys/ctfs.h>
     70 
     71 #if defined(__i386) || defined(__i386_COMPAT)
     72 #include <sys/sysi86.h>
     73 #endif
     74 
     75 #include <fs/proc/prdata.h>
     76 
     77 static	int	isprwrioctl(int);
     78 static	ulong_t	prmaprunflags(long);
     79 static	long	prmapsetflags(long);
     80 static	void	prsetrun(kthread_t *, prrun_t *);
     81 static	int	propenm(prnode_t *, caddr_t, caddr_t, int *, cred_t *);
     82 extern	void	oprgetstatus(kthread_t *, prstatus_t *, zone_t *);
     83 extern	void	oprgetpsinfo(proc_t *, prpsinfo_t *, kthread_t *);
     84 static	int	oprgetmap(proc_t *, list_t *);
     85 
     86 static int
     87 prctioctl(prnode_t *pnp, int cmd, intptr_t arg, int flag, cred_t *cr)
     88 {
     89 	int error = 0;
     90 	ct_kparam_t kparam;
     91 	ct_param_t *param = &kparam.param;
     92 	ct_template_t *tmpl;
     93 
     94 	if (cmd != CT_TSET && cmd != CT_TGET)
     95 		return (EINVAL);
     96 
     97 	error = ctparam_copyin((void *)arg, &kparam, flag, cmd);
     98 	if (error != 0)
     99 		return (error);
    100 
    101 	if ((error = prlock(pnp, ZNO)) != 0) {
    102 		kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
    103 		return (error);
    104 	}
    105 
    106 	tmpl = pnp->pr_common->prc_thread->t_lwp->lwp_ct_active[pnp->pr_cttype];
    107 	if (tmpl == NULL) {
    108 		prunlock(pnp);
    109 		kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
    110 		return (ESTALE);
    111 	}
    112 
    113 	if (cmd == CT_TSET)
    114 		error = ctmpl_set(tmpl, &kparam, cr);
    115 	else
    116 		error = ctmpl_get(tmpl, &kparam);
    117 
    118 	prunlock(pnp);
    119 
    120 	if (cmd == CT_TGET && error == 0) {
    121 		error = ctparam_copyout(&kparam, (void *)arg, flag);
    122 	} else {
    123 		kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
    124 	}
    125 
    126 	return (error);
    127 }
    128 
    129 
    130 /*
    131  * Control operations (lots).
    132  */
    133 /*ARGSUSED*/
    134 #ifdef _SYSCALL32_IMPL
    135 static int
    136 prioctl64(
    137 	struct vnode *vp,
    138 	int cmd,
    139 	intptr_t arg,
    140 	int flag,
    141 	cred_t *cr,
    142 	int *rvalp,
    143 	caller_context_t *ct)
    144 #else
    145 int
    146 prioctl(
    147 	struct vnode *vp,
    148 	int cmd,
    149 	intptr_t arg,
    150 	int flag,
    151 	cred_t *cr,
    152 	int *rvalp,
    153 	caller_context_t *ct)
    154 #endif	/* _SYSCALL32_IMPL */
    155 {
    156 	caddr_t cmaddr = (caddr_t)arg;
    157 	proc_t *p;
    158 	user_t *up;
    159 	kthread_t *t;
    160 	klwp_t *lwp;
    161 	prnode_t *pnp = VTOP(vp);
    162 	prcommon_t *pcp;
    163 	prnode_t *xpnp = NULL;
    164 	int error;
    165 	int zdisp;
    166 	void *thing = NULL;
    167 	size_t thingsize = 0;
    168 
    169 	/*
    170 	 * For copyin()/copyout().
    171 	 */
    172 	union {
    173 		caddr_t		va;
    174 		int		signo;
    175 		int		nice;
    176 		uint_t		lwpid;
    177 		long		flags;
    178 		prstatus_t	prstat;
    179 		prrun_t		prrun;
    180 		sigset_t	smask;
    181 		siginfo_t	info;
    182 		sysset_t	prmask;
    183 		prgregset_t	regs;
    184 		prfpregset_t	fpregs;
    185 		prpsinfo_t	prps;
    186 		sigset_t	holdmask;
    187 		fltset_t	fltmask;
    188 		prcred_t	prcred;
    189 		prhusage_t	prhusage;
    190 		prmap_t		prmap;
    191 		auxv_t		auxv[__KERN_NAUXV_IMPL];
    192 	} un;
    193 
    194 	if (pnp->pr_type == PR_TMPL)
    195 		return (prctioctl(pnp, cmd, arg, flag, cr));
    196 
    197 	/*
    198 	 * Support for old /proc interface.
    199 	 */
    200 	if (pnp->pr_pidfile != NULL) {
    201 		ASSERT(pnp->pr_type == PR_PIDDIR);
    202 		vp = pnp->pr_pidfile;
    203 		pnp = VTOP(vp);
    204 		ASSERT(pnp->pr_type == PR_PIDFILE);
    205 	}
    206 
    207 	if (pnp->pr_type != PR_PIDFILE && pnp->pr_type != PR_LWPIDFILE)
    208 		return (ENOTTY);
    209 
    210 	/*
    211 	 * Fail ioctls which are logically "write" requests unless
    212 	 * the user has write permission.
    213 	 */
    214 	if ((flag & FWRITE) == 0 && isprwrioctl(cmd))
    215 		return (EBADF);
    216 
    217 	/*
    218 	 * Perform any necessary copyin() operations before
    219 	 * locking the process.  Helps avoid deadlocks and
    220 	 * improves performance.
    221 	 *
    222 	 * Also, detect invalid ioctl codes here to avoid
    223 	 * locking a process unnnecessarily.
    224 	 *
    225 	 * Also, prepare to allocate space that will be needed below,
    226 	 * case by case.
    227 	 */
    228 	error = 0;
    229 	switch (cmd) {
    230 	case PIOCGETPR:
    231 		thingsize = sizeof (proc_t);
    232 		break;
    233 	case PIOCGETU:
    234 		thingsize = sizeof (user_t);
    235 		break;
    236 	case PIOCSTOP:
    237 	case PIOCWSTOP:
    238 	case PIOCLWPIDS:
    239 	case PIOCGTRACE:
    240 	case PIOCGENTRY:
    241 	case PIOCGEXIT:
    242 	case PIOCSRLC:
    243 	case PIOCRRLC:
    244 	case PIOCSFORK:
    245 	case PIOCRFORK:
    246 	case PIOCGREG:
    247 	case PIOCGFPREG:
    248 	case PIOCSTATUS:
    249 	case PIOCLSTATUS:
    250 	case PIOCPSINFO:
    251 	case PIOCMAXSIG:
    252 	case PIOCGXREGSIZE:
    253 		break;
    254 	case PIOCSXREG:		/* set extra registers */
    255 	case PIOCGXREG:		/* get extra registers */
    256 #if defined(__sparc)
    257 		thingsize = sizeof (prxregset_t);
    258 #else
    259 		thingsize = 0;
    260 #endif
    261 		break;
    262 	case PIOCACTION:
    263 		thingsize = (NSIG-1) * sizeof (struct sigaction);
    264 		break;
    265 	case PIOCGHOLD:
    266 	case PIOCNMAP:
    267 	case PIOCMAP:
    268 	case PIOCGFAULT:
    269 	case PIOCCFAULT:
    270 	case PIOCCRED:
    271 	case PIOCGROUPS:
    272 	case PIOCUSAGE:
    273 	case PIOCLUSAGE:
    274 		break;
    275 	case PIOCOPENPD:
    276 		/*
    277 		 * We will need this below.
    278 		 * Allocate it now, before locking the process.
    279 		 */
    280 		xpnp = prgetnode(vp, PR_OPAGEDATA);
    281 		break;
    282 	case PIOCNAUXV:
    283 	case PIOCAUXV:
    284 		break;
    285 
    286 #if defined(__i386) || defined(__amd64)
    287 	case PIOCNLDT:
    288 	case PIOCLDT:
    289 		break;
    290 #endif	/* __i386 || __amd64 */
    291 
    292 #if defined(__sparc)
    293 	case PIOCGWIN:
    294 		thingsize = sizeof (gwindows_t);
    295 		break;
    296 #endif	/* __sparc */
    297 
    298 	case PIOCOPENM:		/* open mapped object for reading */
    299 		if (cmaddr == NULL)
    300 			un.va = NULL;
    301 		else if (copyin(cmaddr, &un.va, sizeof (un.va)))
    302 			error = EFAULT;
    303 		break;
    304 
    305 	case PIOCRUN:		/* make lwp or process runnable */
    306 		if (cmaddr == NULL)
    307 			un.prrun.pr_flags = 0;
    308 		else if (copyin(cmaddr, &un.prrun, sizeof (un.prrun)))
    309 			error = EFAULT;
    310 		break;
    311 
    312 	case PIOCOPENLWP:	/* return /proc lwp file descriptor */
    313 		if (copyin(cmaddr, &un.lwpid, sizeof (un.lwpid)))
    314 			error = EFAULT;
    315 		break;
    316 
    317 	case PIOCSTRACE:	/* set signal trace mask */
    318 		if (copyin(cmaddr, &un.smask, sizeof (un.smask)))
    319 			error = EFAULT;
    320 		break;
    321 
    322 	case PIOCSSIG:		/* set current signal */
    323 		if (cmaddr == NULL)
    324 			un.info.si_signo = 0;
    325 		else if (copyin(cmaddr, &un.info, sizeof (un.info)))
    326 			error = EFAULT;
    327 		break;
    328 
    329 	case PIOCKILL:		/* send signal */
    330 	case PIOCUNKILL:	/* delete a signal */
    331 		if (copyin(cmaddr, &un.signo, sizeof (un.signo)))
    332 			error = EFAULT;
    333 		break;
    334 
    335 	case PIOCNICE:		/* set nice priority */
    336 		if (copyin(cmaddr, &un.nice, sizeof (un.nice)))
    337 			error = EFAULT;
    338 		break;
    339 
    340 	case PIOCSENTRY:	/* set syscall entry bit mask */
    341 	case PIOCSEXIT:		/* set syscall exit bit mask */
    342 		if (copyin(cmaddr, &un.prmask, sizeof (un.prmask)))
    343 			error = EFAULT;
    344 		break;
    345 
    346 	case PIOCSET:		/* set process flags */
    347 	case PIOCRESET:		/* reset process flags */
    348 		if (copyin(cmaddr, &un.flags, sizeof (un.flags)))
    349 			error = EFAULT;
    350 		break;
    351 
    352 	case PIOCSREG:		/* set general registers */
    353 		if (copyin(cmaddr, un.regs, sizeof (un.regs)))
    354 			error = EFAULT;
    355 		break;
    356 
    357 	case PIOCSFPREG:	/* set floating-point registers */
    358 		if (copyin(cmaddr, &un.fpregs, sizeof (un.fpregs)))
    359 			error = EFAULT;
    360 		break;
    361 
    362 	case PIOCSHOLD:		/* set signal-hold mask */
    363 		if (copyin(cmaddr, &un.holdmask, sizeof (un.holdmask)))
    364 			error = EFAULT;
    365 		break;
    366 
    367 	case PIOCSFAULT:	/* set mask of traced faults */
    368 		if (copyin(cmaddr, &un.fltmask, sizeof (un.fltmask)))
    369 			error = EFAULT;
    370 		break;
    371 
    372 	default:
    373 		error = EINVAL;
    374 		break;
    375 	}
    376 
    377 	if (error)
    378 		return (error);
    379 
    380 startover:
    381 	/*
    382 	 * If we need kmem_alloc()d space then we allocate it now, before
    383 	 * grabbing the process lock.  Using kmem_alloc(KM_SLEEP) while
    384 	 * holding the process lock leads to deadlock with the clock thread.
    385 	 * (The clock thread wakes up the pageout daemon to free up space.
    386 	 * If the clock thread blocks behind us and we are sleeping waiting
    387 	 * for space, then space may never become available.)
    388 	 */
    389 	if (thingsize) {
    390 		ASSERT(thing == NULL);
    391 		thing = kmem_alloc(thingsize, KM_SLEEP);
    392 	}
    393 
    394 	switch (cmd) {
    395 	case PIOCPSINFO:
    396 	case PIOCGETPR:
    397 	case PIOCUSAGE:
    398 	case PIOCLUSAGE:
    399 		zdisp = ZYES;
    400 		break;
    401 	case PIOCSXREG:		/* set extra registers */
    402 		/*
    403 		 * perform copyin before grabbing the process lock
    404 		 */
    405 		if (thing) {
    406 			if (copyin(cmaddr, thing, thingsize)) {
    407 				kmem_free(thing, thingsize);
    408 				return (EFAULT);
    409 			}
    410 		}
    411 		/* fall through... */
    412 	default:
    413 		zdisp = ZNO;
    414 		break;
    415 	}
    416 
    417 	if ((error = prlock(pnp, zdisp)) != 0) {
    418 		if (thing != NULL)
    419 			kmem_free(thing, thingsize);
    420 		if (xpnp)
    421 			prfreenode(xpnp);
    422 		return (error);
    423 	}
    424 
    425 	pcp = pnp->pr_common;
    426 	p = pcp->prc_proc;
    427 	ASSERT(p != NULL);
    428 
    429 	/*
    430 	 * Choose a thread/lwp for the operation.
    431 	 */
    432 	if (zdisp == ZNO && cmd != PIOCSTOP && cmd != PIOCWSTOP) {
    433 		if (pnp->pr_type == PR_LWPIDFILE && cmd != PIOCLSTATUS) {
    434 			t = pcp->prc_thread;
    435 			ASSERT(t != NULL);
    436 		} else {
    437 			t = prchoose(p);	/* returns locked thread */
    438 			ASSERT(t != NULL);
    439 			thread_unlock(t);
    440 		}
    441 		lwp = ttolwp(t);
    442 	}
    443 
    444 	error = 0;
    445 	switch (cmd) {
    446 
    447 	case PIOCGETPR:		/* read struct proc */
    448 	{
    449 		proc_t *prp = thing;
    450 
    451 		*prp = *p;
    452 		prunlock(pnp);
    453 		if (copyout(prp, cmaddr, sizeof (proc_t)))
    454 			error = EFAULT;
    455 		kmem_free(prp, sizeof (proc_t));
    456 		thing = NULL;
    457 		break;
    458 	}
    459 
    460 	case PIOCGETU:		/* read u-area */
    461 	{
    462 		user_t *userp = thing;
    463 
    464 		up = PTOU(p);
    465 		*userp = *up;
    466 		prunlock(pnp);
    467 		if (copyout(userp, cmaddr, sizeof (user_t)))
    468 			error = EFAULT;
    469 		kmem_free(userp, sizeof (user_t));
    470 		thing = NULL;
    471 		break;
    472 	}
    473 
    474 	case PIOCOPENM:		/* open mapped object for reading */
    475 		error = propenm(pnp, cmaddr, un.va, rvalp, cr);
    476 		/* propenm() called prunlock(pnp) */
    477 		break;
    478 
    479 	case PIOCSTOP:		/* stop process or lwp from running */
    480 	case PIOCWSTOP:		/* wait for process or lwp to stop */
    481 		/*
    482 		 * Can't apply to a system process.
    483 		 */
    484 		if ((p->p_flag & SSYS) || p->p_as == &kas) {
    485 			prunlock(pnp);
    486 			error = EBUSY;
    487 			break;
    488 		}
    489 
    490 		if (cmd == PIOCSTOP)
    491 			pr_stop(pnp);
    492 
    493 		/*
    494 		 * If an lwp is waiting for itself or its process, don't wait.
    495 		 * The stopped lwp would never see the fact that it is stopped.
    496 		 */
    497 		if ((pnp->pr_type == PR_LWPIDFILE)?
    498 		    (pcp->prc_thread == curthread) : (p == curproc)) {
    499 			if (cmd == PIOCWSTOP)
    500 				error = EBUSY;
    501 			prunlock(pnp);
    502 			break;
    503 		}
    504 
    505 		if ((error = pr_wait_stop(pnp, (time_t)0)) != 0)
    506 			break;	/* pr_wait_stop() unlocked the process */
    507 
    508 		if (cmaddr == NULL)
    509 			prunlock(pnp);
    510 		else {
    511 			/*
    512 			 * Return process/lwp status information.
    513 			 */
    514 			t = pr_thread(pnp);	/* returns locked thread */
    515 			thread_unlock(t);
    516 			oprgetstatus(t, &un.prstat, VTOZONE(vp));
    517 			prunlock(pnp);
    518 			if (copyout(&un.prstat, cmaddr, sizeof (un.prstat)))
    519 				error = EFAULT;
    520 		}
    521 		break;
    522 
    523 	case PIOCRUN:		/* make lwp or process runnable */
    524 	{
    525 		long flags = un.prrun.pr_flags;
    526 
    527 		/*
    528 		 * Cannot set an lwp running is it is not stopped.
    529 		 * Also, no lwp other than the /proc agent lwp can
    530 		 * be set running so long as the /proc agent lwp exists.
    531 		 */
    532 		if ((!ISTOPPED(t) && !VSTOPPED(t) &&
    533 		    !(t->t_proc_flag & TP_PRSTOP)) ||
    534 		    (p->p_agenttp != NULL &&
    535 		    (t != p->p_agenttp || pnp->pr_type != PR_LWPIDFILE))) {
    536 			prunlock(pnp);
    537 			error = EBUSY;
    538 			break;
    539 		}
    540 
    541 		if (flags & (PRSHOLD|PRSTRACE|PRSFAULT|PRSVADDR))
    542 			prsetrun(t, &un.prrun);
    543 
    544 		error = pr_setrun(pnp, prmaprunflags(flags));
    545 
    546 		prunlock(pnp);
    547 		break;
    548 	}
    549 
    550 	case PIOCLWPIDS:	/* get array of lwp identifiers */
    551 	{
    552 		int nlwp;
    553 		int Nlwp;
    554 		id_t *idp;
    555 		id_t *Bidp;
    556 
    557 		Nlwp = nlwp = p->p_lwpcnt;
    558 
    559 		if (thing && thingsize != (Nlwp+1) * sizeof (id_t)) {
    560 			kmem_free(thing, thingsize);
    561 			thing = NULL;
    562 		}
    563 		if (thing == NULL) {
    564 			thingsize = (Nlwp+1) * sizeof (id_t);
    565 			thing = kmem_alloc(thingsize, KM_NOSLEEP);
    566 		}
    567 		if (thing == NULL) {
    568 			prunlock(pnp);
    569 			goto startover;
    570 		}
    571 
    572 		idp = thing;
    573 		thing = NULL;
    574 		Bidp = idp;
    575 		if ((t = p->p_tlist) != NULL) {
    576 			do {
    577 				ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
    578 				ASSERT(nlwp > 0);
    579 				--nlwp;
    580 				*idp++ = t->t_tid;
    581 			} while ((t = t->t_forw) != p->p_tlist);
    582 		}
    583 		*idp = 0;
    584 		ASSERT(nlwp == 0);
    585 		prunlock(pnp);
    586 		if (copyout(Bidp, cmaddr, (Nlwp+1) * sizeof (id_t)))
    587 			error = EFAULT;
    588 		kmem_free(Bidp, (Nlwp+1) * sizeof (id_t));
    589 		break;
    590 	}
    591 
    592 	case PIOCOPENLWP:	/* return /proc lwp file descriptor */
    593 	{
    594 		vnode_t *xvp;
    595 		int n;
    596 
    597 		prunlock(pnp);
    598 		if ((xvp = prlwpnode(pnp, un.lwpid)) == NULL)
    599 			error = ENOENT;
    600 		else if (error = fassign(&xvp, flag & (FREAD|FWRITE), &n)) {
    601 			VN_RELE(xvp);
    602 		} else
    603 			*rvalp = n;
    604 		break;
    605 	}
    606 
    607 	case PIOCOPENPD:	/* return /proc page data file descriptor */
    608 	{
    609 		vnode_t *xvp = PTOV(xpnp);
    610 		vnode_t *dp = pnp->pr_parent;
    611 		int n;
    612 
    613 		if (pnp->pr_type == PR_LWPIDFILE) {
    614 			dp = VTOP(dp)->pr_parent;
    615 			dp = VTOP(dp)->pr_parent;
    616 		}
    617 		ASSERT(VTOP(dp)->pr_type == PR_PIDDIR);
    618 
    619 		VN_HOLD(dp);
    620 		pcp = pnp->pr_pcommon;
    621 		xpnp->pr_ino = ptoi(pcp->prc_pid);
    622 		xpnp->pr_common = pcp;
    623 		xpnp->pr_pcommon = pcp;
    624 		xpnp->pr_parent = dp;
    625 
    626 		xpnp->pr_next = p->p_plist;
    627 		p->p_plist = xvp;
    628 
    629 		prunlock(pnp);
    630 		if (error = fassign(&xvp, FREAD, &n)) {
    631 			VN_RELE(xvp);
    632 		} else
    633 			*rvalp = n;
    634 
    635 		xpnp = NULL;
    636 		break;
    637 	}
    638 
    639 	case PIOCGTRACE:	/* get signal trace mask */
    640 		prassignset(&un.smask, &p->p_sigmask);
    641 		prunlock(pnp);
    642 		if (copyout(&un.smask, cmaddr, sizeof (un.smask)))
    643 			error = EFAULT;
    644 		break;
    645 
    646 	case PIOCSTRACE:	/* set signal trace mask */
    647 		prdelset(&un.smask, SIGKILL);
    648 		prassignset(&p->p_sigmask, &un.smask);
    649 		if (!sigisempty(&p->p_sigmask))
    650 			p->p_proc_flag |= P_PR_TRACE;
    651 		else if (prisempty(&p->p_fltmask)) {
    652 			up = PTOU(p);
    653 			if (up->u_systrap == 0)
    654 				p->p_proc_flag &= ~P_PR_TRACE;
    655 		}
    656 		prunlock(pnp);
    657 		break;
    658 
    659 	case PIOCSSIG:		/* set current signal */
    660 		error = pr_setsig(pnp, &un.info);
    661 		prunlock(pnp);
    662 		if (un.info.si_signo == SIGKILL && error == 0)
    663 			pr_wait_die(pnp);
    664 		break;
    665 
    666 	case PIOCKILL:		/* send signal */
    667 	{
    668 		int sig = (int)un.signo;
    669 
    670 		error = pr_kill(pnp, sig, cr);
    671 		prunlock(pnp);
    672 		if (sig == SIGKILL && error == 0)
    673 			pr_wait_die(pnp);
    674 		break;
    675 	}
    676 
    677 	case PIOCUNKILL:	/* delete a signal */
    678 		error = pr_unkill(pnp, (int)un.signo);
    679 		prunlock(pnp);
    680 		break;
    681 
    682 	case PIOCNICE:		/* set nice priority */
    683 		error = pr_nice(p, (int)un.nice, cr);
    684 		prunlock(pnp);
    685 		break;
    686 
    687 	case PIOCGENTRY:	/* get syscall entry bit mask */
    688 	case PIOCGEXIT:		/* get syscall exit bit mask */
    689 		up = PTOU(p);
    690 		if (cmd == PIOCGENTRY) {
    691 			prassignset(&un.prmask, &up->u_entrymask);
    692 		} else {
    693 			prassignset(&un.prmask, &up->u_exitmask);
    694 		}
    695 		prunlock(pnp);
    696 		if (copyout(&un.prmask, cmaddr, sizeof (un.prmask)))
    697 			error = EFAULT;
    698 		break;
    699 
    700 	case PIOCSENTRY:	/* set syscall entry bit mask */
    701 	case PIOCSEXIT:		/* set syscall exit bit mask */
    702 		pr_setentryexit(p, &un.prmask, cmd == PIOCSENTRY);
    703 		prunlock(pnp);
    704 		break;
    705 
    706 	case PIOCSRLC:		/* obsolete: set running on last /proc close */
    707 		error = pr_set(p, prmapsetflags(PR_RLC));
    708 		prunlock(pnp);
    709 		break;
    710 
    711 	case PIOCRRLC:		/* obsolete: reset run-on-last-close flag */
    712 		error = pr_unset(p, prmapsetflags(PR_RLC));
    713 		prunlock(pnp);
    714 		break;
    715 
    716 	case PIOCSFORK:		/* obsolete: set inherit-on-fork flag */
    717 		error = pr_set(p, prmapsetflags(PR_FORK));
    718 		prunlock(pnp);
    719 		break;
    720 
    721 	case PIOCRFORK:		/* obsolete: reset inherit-on-fork flag */
    722 		error = pr_unset(p, prmapsetflags(PR_FORK));
    723 		prunlock(pnp);
    724 		break;
    725 
    726 	case PIOCSET:		/* set process flags */
    727 		error = pr_set(p, prmapsetflags(un.flags));
    728 		prunlock(pnp);
    729 		break;
    730 
    731 	case PIOCRESET:		/* reset process flags */
    732 		error = pr_unset(p, prmapsetflags(un.flags));
    733 		prunlock(pnp);
    734 		break;
    735 
    736 	case PIOCGREG:		/* get general registers */
    737 		if (t->t_state != TS_STOPPED && !VSTOPPED(t))
    738 			bzero(un.regs, sizeof (un.regs));
    739 		else {
    740 			/* drop p_lock while touching the lwp's stack */
    741 			mutex_exit(&p->p_lock);
    742 			prgetprregs(lwp, un.regs);
    743 			mutex_enter(&p->p_lock);
    744 		}
    745 		prunlock(pnp);
    746 		if (copyout(un.regs, cmaddr, sizeof (un.regs)))
    747 			error = EFAULT;
    748 		break;
    749 
    750 	case PIOCSREG:		/* set general registers */
    751 		if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
    752 			error = EBUSY;
    753 		else {
    754 			/* drop p_lock while touching the lwp's stack */
    755 			mutex_exit(&p->p_lock);
    756 			prsetprregs(lwp, un.regs, 0);
    757 			mutex_enter(&p->p_lock);
    758 		}
    759 		prunlock(pnp);
    760 		break;
    761 
    762 	case PIOCGFPREG:	/* get floating-point registers */
    763 		if (!prhasfp()) {
    764 			prunlock(pnp);
    765 			error = EINVAL;	/* No FP support */
    766 			break;
    767 		}
    768 
    769 		if (t->t_state != TS_STOPPED && !VSTOPPED(t))
    770 			bzero(&un.fpregs, sizeof (un.fpregs));
    771 		else {
    772 			/* drop p_lock while touching the lwp's stack */
    773 			mutex_exit(&p->p_lock);
    774 			prgetprfpregs(lwp, &un.fpregs);
    775 			mutex_enter(&p->p_lock);
    776 		}
    777 		prunlock(pnp);
    778 		if (copyout(&un.fpregs, cmaddr, sizeof (un.fpregs)))
    779 			error = EFAULT;
    780 		break;
    781 
    782 	case PIOCSFPREG:	/* set floating-point registers */
    783 		if (!prhasfp())
    784 			error = EINVAL;	/* No FP support */
    785 		else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
    786 			error = EBUSY;
    787 		else {
    788 			/* drop p_lock while touching the lwp's stack */
    789 			mutex_exit(&p->p_lock);
    790 			prsetprfpregs(lwp, &un.fpregs);
    791 			mutex_enter(&p->p_lock);
    792 		}
    793 		prunlock(pnp);
    794 		break;
    795 
    796 	case PIOCGXREGSIZE:	/* get the size of the extra registers */
    797 	{
    798 		int xregsize;
    799 
    800 		if (prhasx(p)) {
    801 			xregsize = prgetprxregsize(p);
    802 			prunlock(pnp);
    803 			if (copyout(&xregsize, cmaddr, sizeof (xregsize)))
    804 				error = EFAULT;
    805 		} else {
    806 			prunlock(pnp);
    807 			error = EINVAL;	/* No extra register support */
    808 		}
    809 		break;
    810 	}
    811 
    812 	case PIOCGXREG:		/* get extra registers */
    813 		if (prhasx(p)) {
    814 			bzero(thing, thingsize);
    815 			if (t->t_state == TS_STOPPED || VSTOPPED(t)) {
    816 				/* drop p_lock to touch the stack */
    817 				mutex_exit(&p->p_lock);
    818 				prgetprxregs(lwp, thing);
    819 				mutex_enter(&p->p_lock);
    820 			}
    821 			prunlock(pnp);
    822 			if (copyout(thing, cmaddr, thingsize))
    823 				error = EFAULT;
    824 		} else {
    825 			prunlock(pnp);
    826 			error = EINVAL;	/* No extra register support */
    827 		}
    828 		if (thing) {
    829 			kmem_free(thing, thingsize);
    830 			thing = NULL;
    831 		}
    832 		break;
    833 
    834 	case PIOCSXREG:		/* set extra registers */
    835 		if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
    836 			error = EBUSY;
    837 		else if (!prhasx(p))
    838 			error = EINVAL;	/* No extra register support */
    839 		else if (thing) {
    840 			/* drop p_lock while touching the lwp's stack */
    841 			mutex_exit(&p->p_lock);
    842 			prsetprxregs(lwp, thing);
    843 			mutex_enter(&p->p_lock);
    844 		}
    845 		prunlock(pnp);
    846 		if (thing) {
    847 			kmem_free(thing, thingsize);
    848 			thing = NULL;
    849 		}
    850 		break;
    851 
    852 	case PIOCSTATUS:	/* get process/lwp status */
    853 		oprgetstatus(t, &un.prstat, VTOZONE(vp));
    854 		prunlock(pnp);
    855 		if (copyout(&un.prstat, cmaddr, sizeof (un.prstat)))
    856 			error = EFAULT;
    857 		break;
    858 
    859 	case PIOCLSTATUS:	/* get status for process & all lwps */
    860 	{
    861 		int Nlwp;
    862 		int nlwp;
    863 		prstatus_t *Bprsp;
    864 		prstatus_t *prsp;
    865 
    866 		nlwp = Nlwp = p->p_lwpcnt;
    867 
    868 		if (thing && thingsize != (Nlwp+1) * sizeof (prstatus_t)) {
    869 			kmem_free(thing, thingsize);
    870 			thing = NULL;
    871 		}
    872 		if (thing == NULL) {
    873 			thingsize = (Nlwp+1) * sizeof (prstatus_t);
    874 			thing = kmem_alloc(thingsize, KM_NOSLEEP);
    875 		}
    876 		if (thing == NULL) {
    877 			prunlock(pnp);
    878 			goto startover;
    879 		}
    880 
    881 		Bprsp = thing;
    882 		thing = NULL;
    883 		prsp = Bprsp;
    884 		oprgetstatus(t, prsp, VTOZONE(vp));
    885 		t = p->p_tlist;
    886 		do {
    887 			ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
    888 			ASSERT(nlwp > 0);
    889 			--nlwp;
    890 			oprgetstatus(t, ++prsp, VTOZONE(vp));
    891 		} while ((t = t->t_forw) != p->p_tlist);
    892 		ASSERT(nlwp == 0);
    893 		prunlock(pnp);
    894 		if (copyout(Bprsp, cmaddr, (Nlwp+1) * sizeof (prstatus_t)))
    895 			error = EFAULT;
    896 
    897 		kmem_free(Bprsp, (Nlwp+1) * sizeof (prstatus_t));
    898 		break;
    899 	}
    900 
    901 	case PIOCPSINFO:	/* get ps(1) information */
    902 	{
    903 		prpsinfo_t *psp = &un.prps;
    904 
    905 		oprgetpsinfo(p, psp,
    906 		    (pnp->pr_type == PR_LWPIDFILE)? pcp->prc_thread : NULL);
    907 
    908 		prunlock(pnp);
    909 		if (copyout(&un.prps, cmaddr, sizeof (un.prps)))
    910 			error = EFAULT;
    911 		break;
    912 	}
    913 
    914 	case PIOCMAXSIG:	/* get maximum signal number */
    915 	{
    916 		int n = NSIG-1;
    917 
    918 		prunlock(pnp);
    919 		if (copyout(&n, cmaddr, sizeof (n)))
    920 			error = EFAULT;
    921 		break;
    922 	}
    923 
    924 	case PIOCACTION:	/* get signal action structures */
    925 	{
    926 		uint_t sig;
    927 		struct sigaction *sap = thing;
    928 
    929 		up = PTOU(p);
    930 		for (sig = 1; sig < NSIG; sig++)
    931 			prgetaction(p, up, sig, &sap[sig-1]);
    932 		prunlock(pnp);
    933 		if (copyout(sap, cmaddr, (NSIG-1) * sizeof (struct sigaction)))
    934 			error = EFAULT;
    935 		kmem_free(sap, (NSIG-1) * sizeof (struct sigaction));
    936 		thing = NULL;
    937 		break;
    938 	}
    939 
    940 	case PIOCGHOLD:		/* get signal-hold mask */
    941 		schedctl_finish_sigblock(t);
    942 		sigktou(&t->t_hold, &un.holdmask);
    943 		prunlock(pnp);
    944 		if (copyout(&un.holdmask, cmaddr, sizeof (un.holdmask)))
    945 			error = EFAULT;
    946 		break;
    947 
    948 	case PIOCSHOLD:		/* set signal-hold mask */
    949 		pr_sethold(pnp, &un.holdmask);
    950 		prunlock(pnp);
    951 		break;
    952 
    953 	case PIOCNMAP:		/* get number of memory mappings */
    954 	{
    955 		int n;
    956 		struct as *as = p->p_as;
    957 
    958 		if ((p->p_flag & SSYS) || as == &kas)
    959 			n = 0;
    960 		else {
    961 			mutex_exit(&p->p_lock);
    962 			AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
    963 			n = prnsegs(as, 0);
    964 			AS_LOCK_EXIT(as, &as->a_lock);
    965 			mutex_enter(&p->p_lock);
    966 		}
    967 		prunlock(pnp);
    968 		if (copyout(&n, cmaddr, sizeof (int)))
    969 			error = EFAULT;
    970 		break;
    971 	}
    972 
    973 	case PIOCMAP:		/* get memory map information */
    974 	{
    975 		list_t iolhead;
    976 		struct as *as = p->p_as;
    977 
    978 		if ((p->p_flag & SSYS) || as == &kas) {
    979 			error = 0;
    980 			prunlock(pnp);
    981 		} else {
    982 			mutex_exit(&p->p_lock);
    983 			AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
    984 			error = oprgetmap(p, &iolhead);
    985 			AS_LOCK_EXIT(as, &as->a_lock);
    986 			mutex_enter(&p->p_lock);
    987 			prunlock(pnp);
    988 
    989 			error = pr_iol_copyout_and_free(&iolhead,
    990 			    &cmaddr, error);
    991 		}
    992 		/*
    993 		 * The procfs PIOCMAP ioctl returns an all-zero buffer
    994 		 * to indicate the end of the prmap[] array.
    995 		 * Append it to whatever has already been copied out.
    996 		 */
    997 		bzero(&un.prmap, sizeof (un.prmap));
    998 		if (!error && copyout(&un.prmap, cmaddr, sizeof (un.prmap)))
    999 			error = EFAULT;
   1000 
   1001 		break;
   1002 	}
   1003 
   1004 	case PIOCGFAULT:	/* get mask of traced faults */
   1005 		prassignset(&un.fltmask, &p->p_fltmask);
   1006 		prunlock(pnp);
   1007 		if (copyout(&un.fltmask, cmaddr, sizeof (un.fltmask)))
   1008 			error = EFAULT;
   1009 		break;
   1010 
   1011 	case PIOCSFAULT:	/* set mask of traced faults */
   1012 		pr_setfault(p, &un.fltmask);
   1013 		prunlock(pnp);
   1014 		break;
   1015 
   1016 	case PIOCCFAULT:	/* clear current fault */
   1017 		lwp->lwp_curflt = 0;
   1018 		prunlock(pnp);
   1019 		break;
   1020 
   1021 	case PIOCCRED:		/* get process credentials */
   1022 	{
   1023 		cred_t *cp;
   1024 
   1025 		mutex_enter(&p->p_crlock);
   1026 		cp = p->p_cred;
   1027 		un.prcred.pr_euid = crgetuid(cp);
   1028 		un.prcred.pr_ruid = crgetruid(cp);
   1029 		un.prcred.pr_suid = crgetsuid(cp);
   1030 		un.prcred.pr_egid = crgetgid(cp);
   1031 		un.prcred.pr_rgid = crgetrgid(cp);
   1032 		un.prcred.pr_sgid = crgetsgid(cp);
   1033 		un.prcred.pr_ngroups = crgetngroups(cp);
   1034 		mutex_exit(&p->p_crlock);
   1035 
   1036 		prunlock(pnp);
   1037 		if (copyout(&un.prcred, cmaddr, sizeof (un.prcred)))
   1038 			error = EFAULT;
   1039 		break;
   1040 	}
   1041 
   1042 	case PIOCGROUPS:	/* get supplementary groups */
   1043 	{
   1044 		cred_t *cp;
   1045 
   1046 		mutex_enter(&p->p_crlock);
   1047 		cp = p->p_cred;
   1048 		crhold(cp);
   1049 		mutex_exit(&p->p_crlock);
   1050 
   1051 		prunlock(pnp);
   1052 		if (copyout(crgetgroups(cp), cmaddr,
   1053 		    MAX(crgetngroups(cp), 1) * sizeof (gid_t)))
   1054 			error = EFAULT;
   1055 		crfree(cp);
   1056 		break;
   1057 	}
   1058 
   1059 	case PIOCUSAGE:		/* get usage info */
   1060 	{
   1061 		/*
   1062 		 * For an lwp file descriptor, return just the lwp usage.
   1063 		 * For a process file descriptor, return total usage,
   1064 		 * all current lwps plus all defunct lwps.
   1065 		 */
   1066 		prhusage_t *pup = &un.prhusage;
   1067 		prusage_t *upup;
   1068 
   1069 		bzero(pup, sizeof (*pup));
   1070 		pup->pr_tstamp = gethrtime();
   1071 
   1072 		if (pnp->pr_type == PR_LWPIDFILE) {
   1073 			t = pcp->prc_thread;
   1074 			if (t != NULL)
   1075 				prgetusage(t, pup);
   1076 			else
   1077 				error = ENOENT;
   1078 		} else {
   1079 			pup->pr_count  = p->p_defunct;
   1080 			pup->pr_create = p->p_mstart;
   1081 			pup->pr_term   = p->p_mterm;
   1082 
   1083 			pup->pr_rtime    = p->p_mlreal;
   1084 			pup->pr_utime    = p->p_acct[LMS_USER];
   1085 			pup->pr_stime    = p->p_acct[LMS_SYSTEM];
   1086 			pup->pr_ttime    = p->p_acct[LMS_TRAP];
   1087 			pup->pr_tftime   = p->p_acct[LMS_TFAULT];
   1088 			pup->pr_dftime   = p->p_acct[LMS_DFAULT];
   1089 			pup->pr_kftime   = p->p_acct[LMS_KFAULT];
   1090 			pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
   1091 			pup->pr_slptime  = p->p_acct[LMS_SLEEP];
   1092 			pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
   1093 			pup->pr_stoptime = p->p_acct[LMS_STOPPED];
   1094 
   1095 			pup->pr_minf  = p->p_ru.minflt;
   1096 			pup->pr_majf  = p->p_ru.majflt;
   1097 			pup->pr_nswap = p->p_ru.nswap;
   1098 			pup->pr_inblk = p->p_ru.inblock;
   1099 			pup->pr_oublk = p->p_ru.oublock;
   1100 			pup->pr_msnd  = p->p_ru.msgsnd;
   1101 			pup->pr_mrcv  = p->p_ru.msgrcv;
   1102 			pup->pr_sigs  = p->p_ru.nsignals;
   1103 			pup->pr_vctx  = p->p_ru.nvcsw;
   1104 			pup->pr_ictx  = p->p_ru.nivcsw;
   1105 			pup->pr_sysc  = p->p_ru.sysc;
   1106 			pup->pr_ioch  = p->p_ru.ioch;
   1107 
   1108 			/*
   1109 			 * Add the usage information for each active lwp.
   1110 			 */
   1111 			if ((t = p->p_tlist) != NULL &&
   1112 			    !(pcp->prc_flags & PRC_DESTROY)) {
   1113 				do {
   1114 					ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
   1115 					pup->pr_count++;
   1116 					praddusage(t, pup);
   1117 				} while ((t = t->t_forw) != p->p_tlist);
   1118 			}
   1119 		}
   1120 
   1121 		prunlock(pnp);
   1122 
   1123 		upup = kmem_zalloc(sizeof (*upup), KM_SLEEP);
   1124 		prcvtusage(&un.prhusage, upup);
   1125 		if (copyout(upup, cmaddr, sizeof (*upup)))
   1126 			error = EFAULT;
   1127 		kmem_free(upup, sizeof (*upup));
   1128 
   1129 		break;
   1130 	}
   1131 
   1132 	case PIOCLUSAGE:	/* get detailed usage info */
   1133 	{
   1134 		int Nlwp;
   1135 		int nlwp;
   1136 		prusage_t *upup;
   1137 		prusage_t *Bupup;
   1138 		prhusage_t *pup;
   1139 		hrtime_t curtime;
   1140 
   1141 		nlwp = Nlwp = (pcp->prc_flags & PRC_DESTROY)? 0 : p->p_lwpcnt;
   1142 
   1143 		if (thing && thingsize !=
   1144 		    sizeof (prhusage_t) + (Nlwp+1) * sizeof (prusage_t)) {
   1145 			kmem_free(thing, thingsize);
   1146 			thing = NULL;
   1147 		}
   1148 		if (thing == NULL) {
   1149 			thingsize = sizeof (prhusage_t) +
   1150 			    (Nlwp+1) * sizeof (prusage_t);
   1151 			thing = kmem_alloc(thingsize, KM_NOSLEEP);
   1152 		}
   1153 		if (thing == NULL) {
   1154 			prunlock(pnp);
   1155 			goto startover;
   1156 		}
   1157 
   1158 		pup = thing;
   1159 		upup = Bupup = (prusage_t *)(pup + 1);
   1160 
   1161 		ASSERT(p == pcp->prc_proc);
   1162 
   1163 		curtime = gethrtime();
   1164 
   1165 		/*
   1166 		 * First the summation over defunct lwps.
   1167 		 */
   1168 		bzero(pup, sizeof (*pup));
   1169 		pup->pr_count  = p->p_defunct;
   1170 		pup->pr_tstamp = curtime;
   1171 		pup->pr_create = p->p_mstart;
   1172 		pup->pr_term   = p->p_mterm;
   1173 
   1174 		pup->pr_rtime    = p->p_mlreal;
   1175 		pup->pr_utime    = p->p_acct[LMS_USER];
   1176 		pup->pr_stime    = p->p_acct[LMS_SYSTEM];
   1177 		pup->pr_ttime    = p->p_acct[LMS_TRAP];
   1178 		pup->pr_tftime   = p->p_acct[LMS_TFAULT];
   1179 		pup->pr_dftime   = p->p_acct[LMS_DFAULT];
   1180 		pup->pr_kftime   = p->p_acct[LMS_KFAULT];
   1181 		pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
   1182 		pup->pr_slptime  = p->p_acct[LMS_SLEEP];
   1183 		pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
   1184 		pup->pr_stoptime = p->p_acct[LMS_STOPPED];
   1185 
   1186 		pup->pr_minf  = p->p_ru.minflt;
   1187 		pup->pr_majf  = p->p_ru.majflt;
   1188 		pup->pr_nswap = p->p_ru.nswap;
   1189 		pup->pr_inblk = p->p_ru.inblock;
   1190 		pup->pr_oublk = p->p_ru.oublock;
   1191 		pup->pr_msnd  = p->p_ru.msgsnd;
   1192 		pup->pr_mrcv  = p->p_ru.msgrcv;
   1193 		pup->pr_sigs  = p->p_ru.nsignals;
   1194 		pup->pr_vctx  = p->p_ru.nvcsw;
   1195 		pup->pr_ictx  = p->p_ru.nivcsw;
   1196 		pup->pr_sysc  = p->p_ru.sysc;
   1197 		pup->pr_ioch  = p->p_ru.ioch;
   1198 
   1199 		prcvtusage(pup, upup);
   1200 
   1201 		/*
   1202 		 * Fill one prusage struct for each active lwp.
   1203 		 */
   1204 		if ((t = p->p_tlist) != NULL &&
   1205 		    !(pcp->prc_flags & PRC_DESTROY)) {
   1206 			do {
   1207 				ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
   1208 				ASSERT(nlwp > 0);
   1209 				--nlwp;
   1210 				upup++;
   1211 				prgetusage(t, pup);
   1212 				prcvtusage(pup, upup);
   1213 			} while ((t = t->t_forw) != p->p_tlist);
   1214 		}
   1215 		ASSERT(nlwp == 0);
   1216 
   1217 		prunlock(pnp);
   1218 		if (copyout(Bupup, cmaddr, (Nlwp+1) * sizeof (prusage_t)))
   1219 			error = EFAULT;
   1220 		kmem_free(thing, thingsize);
   1221 		thing = NULL;
   1222 		break;
   1223 	}
   1224 
   1225 	case PIOCNAUXV:		/* get number of aux vector entries */
   1226 	{
   1227 		int n = __KERN_NAUXV_IMPL;
   1228 
   1229 		prunlock(pnp);
   1230 		if (copyout(&n, cmaddr, sizeof (int)))
   1231 			error = EFAULT;
   1232 		break;
   1233 	}
   1234 
   1235 	case PIOCAUXV:		/* get aux vector (see sys/auxv.h) */
   1236 	{
   1237 		up = PTOU(p);
   1238 		bcopy(up->u_auxv, un.auxv,
   1239 		    __KERN_NAUXV_IMPL * sizeof (auxv_t));
   1240 		prunlock(pnp);
   1241 		if (copyout(un.auxv, cmaddr,
   1242 		    __KERN_NAUXV_IMPL * sizeof (auxv_t)))
   1243 			error = EFAULT;
   1244 		break;
   1245 	}
   1246 
   1247 #if defined(__i386) || defined(__amd64)
   1248 	case PIOCNLDT:		/* get number of LDT entries */
   1249 	{
   1250 		int n;
   1251 
   1252 		mutex_exit(&p->p_lock);
   1253 		mutex_enter(&p->p_ldtlock);
   1254 		n = prnldt(p);
   1255 		mutex_exit(&p->p_ldtlock);
   1256 		mutex_enter(&p->p_lock);
   1257 		prunlock(pnp);
   1258 		if (copyout(&n, cmaddr, sizeof (n)))
   1259 			error = EFAULT;
   1260 		break;
   1261 	}
   1262 
   1263 	case PIOCLDT:		/* get LDT entries */
   1264 	{
   1265 		struct ssd *ssd;
   1266 		int n;
   1267 
   1268 		mutex_exit(&p->p_lock);
   1269 		mutex_enter(&p->p_ldtlock);
   1270 		n = prnldt(p);
   1271 
   1272 		if (thing && thingsize != (n+1) * sizeof (*ssd)) {
   1273 			kmem_free(thing, thingsize);
   1274 			thing = NULL;
   1275 		}
   1276 		if (thing == NULL) {
   1277 			thingsize = (n+1) * sizeof (*ssd);
   1278 			thing = kmem_alloc(thingsize, KM_NOSLEEP);
   1279 		}
   1280 		if (thing == NULL) {
   1281 			mutex_exit(&p->p_ldtlock);
   1282 			mutex_enter(&p->p_lock);
   1283 			prunlock(pnp);
   1284 			goto startover;
   1285 		}
   1286 
   1287 		ssd = thing;
   1288 		thing = NULL;
   1289 		if (n != 0)
   1290 			prgetldt(p, ssd);
   1291 		mutex_exit(&p->p_ldtlock);
   1292 		mutex_enter(&p->p_lock);
   1293 		prunlock(pnp);
   1294 
   1295 		/* mark the end of the list with a null entry */
   1296 		bzero(&ssd[n], sizeof (*ssd));
   1297 		if (copyout(ssd, cmaddr, (n+1) * sizeof (*ssd)))
   1298 			error = EFAULT;
   1299 		kmem_free(ssd, (n+1) * sizeof (*ssd));
   1300 		break;
   1301 	}
   1302 #endif	/* __i386 || __amd64 */
   1303 
   1304 #if defined(__sparc)
   1305 	case PIOCGWIN:		/* get gwindows_t (see sys/reg.h) */
   1306 	{
   1307 		gwindows_t *gwp = thing;
   1308 
   1309 		/* drop p->p_lock while touching the stack */
   1310 		mutex_exit(&p->p_lock);
   1311 		bzero(gwp, sizeof (*gwp));
   1312 		prgetwindows(lwp, gwp);
   1313 		mutex_enter(&p->p_lock);
   1314 		prunlock(pnp);
   1315 		if (copyout(gwp, cmaddr, sizeof (*gwp)))
   1316 			error = EFAULT;
   1317 		kmem_free(gwp, sizeof (gwindows_t));
   1318 		thing = NULL;
   1319 		break;
   1320 	}
   1321 #endif	/* __sparc */
   1322 
   1323 	default:
   1324 		prunlock(pnp);
   1325 		error = EINVAL;
   1326 		break;
   1327 
   1328 	}
   1329 
   1330 	ASSERT(thing == NULL);
   1331 	ASSERT(xpnp == NULL);
   1332 	return (error);
   1333 }
   1334 
   1335 #ifdef _SYSCALL32_IMPL
   1336 
   1337 static int oprgetmap32(proc_t *, list_t *);
   1338 
   1339 void
   1340 oprgetstatus32(kthread_t *t, prstatus32_t *sp, zone_t *zp)
   1341 {
   1342 	proc_t *p = ttoproc(t);
   1343 	klwp_t *lwp = ttolwp(t);
   1344 	int32_t flags;
   1345 	user_t *up;
   1346 	ulong_t instr;
   1347 
   1348 	ASSERT(MUTEX_HELD(&p->p_lock));
   1349 
   1350 	up = PTOU(p);
   1351 	bzero(sp, sizeof (*sp));
   1352 	flags = 0L;
   1353 	if (t->t_state == TS_STOPPED) {
   1354 		flags |= PR_STOPPED;
   1355 		if ((t->t_schedflag & TS_PSTART) == 0)
   1356 			flags |= PR_ISTOP;
   1357 	} else if (VSTOPPED(t)) {
   1358 		flags |= PR_STOPPED|PR_ISTOP;
   1359 	}
   1360 	if (!(flags & PR_ISTOP) && (t->t_proc_flag & TP_PRSTOP))
   1361 		flags |= PR_DSTOP;
   1362 	if (lwp->lwp_asleep)
   1363 		flags |= PR_ASLEEP;
   1364 	if (p->p_proc_flag & P_PR_FORK)
   1365 		flags |= PR_FORK;
   1366 	if (p->p_proc_flag & P_PR_RUNLCL)
   1367 		flags |= PR_RLC;
   1368 	if (p->p_proc_flag & P_PR_KILLCL)
   1369 		flags |= PR_KLC;
   1370 	if (p->p_proc_flag & P_PR_ASYNC)
   1371 		flags |= PR_ASYNC;
   1372 	if (p->p_proc_flag & P_PR_BPTADJ)
   1373 		flags |= PR_BPTADJ;
   1374 	if (p->p_proc_flag & P_PR_PTRACE)
   1375 		flags |= PR_PCOMPAT;
   1376 	if (t->t_proc_flag & TP_MSACCT)
   1377 		flags |= PR_MSACCT;
   1378 	sp->pr_flags = flags;
   1379 	if (VSTOPPED(t)) {
   1380 		sp->pr_why   = PR_REQUESTED;
   1381 		sp->pr_what  = 0;
   1382 	} else {
   1383 		sp->pr_why   = t->t_whystop;
   1384 		sp->pr_what  = t->t_whatstop;
   1385 	}
   1386 
   1387 	if (t->t_whystop == PR_FAULTED) {
   1388 		siginfo_kto32(&lwp->lwp_siginfo, &sp->pr_info);
   1389 		if (t->t_whatstop == FLTPAGE)
   1390 			sp->pr_info.si_addr =
   1391 			    (caddr32_t)(uintptr_t)lwp->lwp_siginfo.si_addr;
   1392 	} else if (lwp->lwp_curinfo)
   1393 		siginfo_kto32(&lwp->lwp_curinfo->sq_info, &sp->pr_info);
   1394 
   1395 	if (SI_FROMUSER(&lwp->lwp_siginfo) && zp->zone_id != GLOBAL_ZONEID &&
   1396 	    sp->pr_info.si_zoneid != zp->zone_id) {
   1397 		sp->pr_info.si_pid = zp->zone_zsched->p_pid;
   1398 		sp->pr_info.si_uid = 0;
   1399 		sp->pr_info.si_ctid = -1;
   1400 		sp->pr_info.si_zoneid = zp->zone_id;
   1401 	}
   1402 
   1403 	sp->pr_cursig  = lwp->lwp_cursig;
   1404 	prassignset(&sp->pr_sigpend, &p->p_sig);
   1405 	prassignset(&sp->pr_lwppend, &t->t_sig);
   1406 	schedctl_finish_sigblock(t);
   1407 	prassignset(&sp->pr_sighold, &t->t_hold);
   1408 	sp->pr_altstack.ss_sp =
   1409 	    (caddr32_t)(uintptr_t)lwp->lwp_sigaltstack.ss_sp;
   1410 	sp->pr_altstack.ss_size = (size32_t)lwp->lwp_sigaltstack.ss_size;
   1411 	sp->pr_altstack.ss_flags = (int32_t)lwp->lwp_sigaltstack.ss_flags;
   1412 	prgetaction32(p, up, lwp->lwp_cursig, &sp->pr_action);
   1413 	sp->pr_pid   = p->p_pid;
   1414 	if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
   1415 	    (p->p_flag & SZONETOP)) {
   1416 		ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
   1417 		/*
   1418 		 * Inside local zones, fake zsched's pid as parent pids for
   1419 		 * processes which reference processes outside of the zone.
   1420 		 */
   1421 		sp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
   1422 	} else {
   1423 		sp->pr_ppid = p->p_ppid;
   1424 	}
   1425 	sp->pr_pgrp  = p->p_pgrp;
   1426 	sp->pr_sid   = p->p_sessp->s_sid;
   1427 	hrt2ts32(mstate_aggr_state(p, LMS_USER), &sp->pr_utime);
   1428 	hrt2ts32(mstate_aggr_state(p, LMS_SYSTEM), &sp->pr_stime);
   1429 	TICK_TO_TIMESTRUC32(p->p_cutime, &sp->pr_cutime);
   1430 	TICK_TO_TIMESTRUC32(p->p_cstime, &sp->pr_cstime);
   1431 	(void) strncpy(sp->pr_clname, sclass[t->t_cid].cl_name,
   1432 	    sizeof (sp->pr_clname) - 1);
   1433 	sp->pr_who = t->t_tid;
   1434 	sp->pr_nlwp = p->p_lwpcnt;
   1435 	sp->pr_brkbase = (caddr32_t)(uintptr_t)p->p_brkbase;
   1436 	sp->pr_brksize = (size32_t)p->p_brksize;
   1437 	sp->pr_stkbase = (caddr32_t)(uintptr_t)prgetstackbase(p);
   1438 	sp->pr_stksize = (size32_t)p->p_stksize;
   1439 	sp->pr_oldcontext = (caddr32_t)lwp->lwp_oldcontext;
   1440 	sp->pr_processor = t->t_cpu->cpu_id;
   1441 	sp->pr_bind = t->t_bind_cpu;
   1442 
   1443 	/*
   1444 	 * Fetch the current instruction, if not a system process.
   1445 	 * We don't attempt this unless the lwp is stopped.
   1446 	 */
   1447 	if ((p->p_flag & SSYS) || p->p_as == &kas)
   1448 		sp->pr_flags |= (PR_ISSYS|PR_PCINVAL);
   1449 	else if (!(flags & PR_STOPPED))
   1450 		sp->pr_flags |= PR_PCINVAL;
   1451 	else if (!prfetchinstr(lwp, &instr))
   1452 		sp->pr_flags |= PR_PCINVAL;
   1453 	else
   1454 		sp->pr_instr = (uint32_t)instr;
   1455 
   1456 	/*
   1457 	 * Drop p_lock while touching the lwp's stack.
   1458 	 */
   1459 	mutex_exit(&p->p_lock);
   1460 	if (prisstep(lwp))
   1461 		sp->pr_flags |= PR_STEP;
   1462 	if ((flags & (PR_STOPPED|PR_ASLEEP)) && t->t_sysnum) {
   1463 		int i;
   1464 		auxv_t *auxp;
   1465 
   1466 		sp->pr_syscall = get_syscall32_args(lwp,
   1467 		    (int *)sp->pr_sysarg, &i);
   1468 		sp->pr_nsysarg = (short)i;
   1469 		if (t->t_whystop == PR_SYSEXIT &&
   1470 		    (t->t_sysnum == SYS_exec || t->t_sysnum == SYS_execve)) {
   1471 			sp->pr_sysarg[0] = 0;
   1472 			sp->pr_sysarg[1] = (caddr32_t)up->u_argv;
   1473 			sp->pr_sysarg[2] = (caddr32_t)up->u_envp;
   1474 			for (i = 0, auxp = up->u_auxv;
   1475 			    i < sizeof (up->u_auxv) / sizeof (up->u_auxv[0]);
   1476 			    i++, auxp++) {
   1477 				if (auxp->a_type == AT_SUN_EXECNAME) {
   1478 					sp->pr_sysarg[0] =
   1479 					    (caddr32_t)
   1480 					    (uintptr_t)auxp->a_un.a_ptr;
   1481 					break;
   1482 				}
   1483 			}
   1484 		}
   1485 	}
   1486 	if ((flags & PR_STOPPED) || t == curthread)
   1487 		prgetprregs32(lwp, sp->pr_reg);
   1488 	mutex_enter(&p->p_lock);
   1489 }
   1490 
   1491 void
   1492 oprgetpsinfo32(proc_t *p, prpsinfo32_t *psp, kthread_t *tp)
   1493 {
   1494 	kthread_t *t;
   1495 	char c, state;
   1496 	user_t *up;
   1497 	dev_t d;
   1498 	uint64_t pct;
   1499 	int retval, niceval;
   1500 	cred_t *cred;
   1501 	struct as *as;
   1502 	hrtime_t hrutime, hrstime, cur_time;
   1503 
   1504 	ASSERT(MUTEX_HELD(&p->p_lock));
   1505 
   1506 	bzero(psp, sizeof (*psp));
   1507 
   1508 	if ((t = tp) == NULL)
   1509 		t = prchoose(p);	/* returns locked thread */
   1510 	else
   1511 		thread_lock(t);
   1512 
   1513 	/* kludge: map thread state enum into process state enum */
   1514 
   1515 	if (t == NULL) {
   1516 		state = TS_ZOMB;
   1517 	} else {
   1518 		state = VSTOPPED(t) ? TS_STOPPED : t->t_state;
   1519 		thread_unlock(t);
   1520 	}
   1521 
   1522 	switch (state) {
   1523 	case TS_SLEEP:		state = SSLEEP;		break;
   1524 	case TS_RUN:		state = SRUN;		break;
   1525 	case TS_ONPROC:		state = SONPROC;	break;
   1526 	case TS_ZOMB:		state = SZOMB;		break;
   1527 	case TS_STOPPED:	state = SSTOP;		break;
   1528 	default:		state = 0;		break;
   1529 	}
   1530 	switch (state) {
   1531 	case SSLEEP:	c = 'S';	break;
   1532 	case SRUN:	c = 'R';	break;
   1533 	case SZOMB:	c = 'Z';	break;
   1534 	case SSTOP:	c = 'T';	break;
   1535 	case SIDL:	c = 'I';	break;
   1536 	case SONPROC:	c = 'O';	break;
   1537 #ifdef SXBRK
   1538 	case SXBRK:	c = 'X';	break;
   1539 #endif
   1540 	default:	c = '?';	break;
   1541 	}
   1542 	psp->pr_state = state;
   1543 	psp->pr_sname = c;
   1544 	psp->pr_zomb = (state == SZOMB);
   1545 	/*
   1546 	 * only export SSYS and SMSACCT; everything else is off-limits to
   1547 	 * userland apps.
   1548 	 */
   1549 	psp->pr_flag = p->p_flag & (SSYS | SMSACCT);
   1550 
   1551 	mutex_enter(&p->p_crlock);
   1552 	cred = p->p_cred;
   1553 	psp->pr_uid = crgetruid(cred);
   1554 	psp->pr_gid = crgetrgid(cred);
   1555 	psp->pr_euid = crgetuid(cred);
   1556 	psp->pr_egid = crgetgid(cred);
   1557 	mutex_exit(&p->p_crlock);
   1558 
   1559 	psp->pr_pid = p->p_pid;
   1560 	if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
   1561 	    (p->p_flag & SZONETOP)) {
   1562 		ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
   1563 		/*
   1564 		 * Inside local zones, fake zsched's pid as parent pids for
   1565 		 * processes which reference processes outside of the zone.
   1566 		 */
   1567 		psp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
   1568 	} else {
   1569 		psp->pr_ppid = p->p_ppid;
   1570 	}
   1571 	psp->pr_pgrp = p->p_pgrp;
   1572 	psp->pr_sid = p->p_sessp->s_sid;
   1573 	psp->pr_addr = 0;	/* cannot represent 64-bit addr in 32 bits */
   1574 	hrutime = mstate_aggr_state(p, LMS_USER);
   1575 	hrstime = mstate_aggr_state(p, LMS_SYSTEM);
   1576 	hrt2ts32(hrutime + hrstime, &psp->pr_time);
   1577 	TICK_TO_TIMESTRUC32(p->p_cutime + p->p_cstime, &psp->pr_ctime);
   1578 	switch (p->p_model) {
   1579 	case DATAMODEL_ILP32:
   1580 		psp->pr_dmodel = PR_MODEL_ILP32;
   1581 		break;
   1582 	case DATAMODEL_LP64:
   1583 		psp->pr_dmodel = PR_MODEL_LP64;
   1584 		break;
   1585 	}
   1586 	if (state == SZOMB || t == NULL) {
   1587 		int wcode = p->p_wcode;		/* must be atomic read */
   1588 
   1589 		if (wcode)
   1590 			psp->pr_wstat = wstat(wcode, p->p_wdata);
   1591 		psp->pr_lttydev = PRNODEV32;
   1592 		psp->pr_ottydev = (o_dev_t)PRNODEV32;
   1593 		psp->pr_size = 0;
   1594 		psp->pr_rssize = 0;
   1595 		psp->pr_pctmem = 0;
   1596 	} else {
   1597 		up = PTOU(p);
   1598 		psp->pr_wchan = 0;	/* cannot represent in 32 bits */
   1599 		psp->pr_pri = t->t_pri;
   1600 		(void) strncpy(psp->pr_clname, sclass[t->t_cid].cl_name,
   1601 		    sizeof (psp->pr_clname) - 1);
   1602 		retval = CL_DONICE(t, NULL, 0, &niceval);
   1603 		if (retval == 0) {
   1604 			psp->pr_oldpri = v.v_maxsyspri - psp->pr_pri;
   1605 			psp->pr_nice = niceval + NZERO;
   1606 		} else {
   1607 			psp->pr_oldpri = 0;
   1608 			psp->pr_nice = 0;
   1609 		}
   1610 		d = cttydev(p);
   1611 #ifdef sun
   1612 		{
   1613 			extern dev_t rwsconsdev, rconsdev, uconsdev;
   1614 			/*
   1615 			 * If the controlling terminal is the real
   1616 			 * or workstation console device, map to what the
   1617 			 * user thinks is the console device. Handle case when
   1618 			 * rwsconsdev or rconsdev is set to NODEV for Starfire.
   1619 			 */
   1620 			if ((d == rwsconsdev || d == rconsdev) && d != NODEV)
   1621 				d = uconsdev;
   1622 		}
   1623 #endif
   1624 		(void) cmpldev(&psp->pr_lttydev, d);
   1625 		psp->pr_ottydev = cmpdev(d);
   1626 		TIMESPEC_TO_TIMESPEC32(&psp->pr_start, &up->u_start);
   1627 		bcopy(up->u_comm, psp->pr_fname,
   1628 		    MIN(sizeof (up->u_comm), sizeof (psp->pr_fname)-1));
   1629 		bcopy(up->u_psargs, psp->pr_psargs,
   1630 		    MIN(PRARGSZ-1, PSARGSZ));
   1631 		psp->pr_syscall = t->t_sysnum;
   1632 		psp->pr_argc = up->u_argc;
   1633 		psp->pr_argv = (caddr32_t)up->u_argv;
   1634 		psp->pr_envp = (caddr32_t)up->u_envp;
   1635 
   1636 		/* compute %cpu for the lwp or process */
   1637 		pct = 0;
   1638 		if ((t = tp) == NULL)
   1639 			t = p->p_tlist;
   1640 		cur_time = gethrtime_unscaled();
   1641 		do {
   1642 			pct += cpu_update_pct(t, cur_time);
   1643 			if (tp != NULL)		/* just do the one lwp */
   1644 				break;
   1645 		} while ((t = t->t_forw) != p->p_tlist);
   1646 
   1647 		psp->pr_pctcpu = prgetpctcpu(pct);
   1648 		psp->pr_cpu = (psp->pr_pctcpu*100 + 0x6000) >> 15; /* [0..99] */
   1649 		if (psp->pr_cpu > 99)
   1650 			psp->pr_cpu = 99;
   1651 
   1652 		if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
   1653 			psp->pr_size = 0;
   1654 			psp->pr_rssize = 0;
   1655 			psp->pr_pctmem = 0;
   1656 		} else {
   1657 			mutex_exit(&p->p_lock);
   1658 			AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
   1659 			psp->pr_size = (size32_t)btopr(as->a_resvsize);
   1660 			psp->pr_rssize = (size32_t)rm_asrss(as);
   1661 			psp->pr_pctmem = rm_pctmemory(as);
   1662 			AS_LOCK_EXIT(as, &as->a_lock);
   1663 			mutex_enter(&p->p_lock);
   1664 		}
   1665 	}
   1666 	psp->pr_bysize = (size32_t)ptob(psp->pr_size);
   1667 	psp->pr_byrssize = (size32_t)ptob(psp->pr_rssize);
   1668 
   1669 	/*
   1670 	 * If we are looking at an LP64 process, zero out
   1671 	 * the fields that cannot be represented in ILP32.
   1672 	 */
   1673 	if (p->p_model != DATAMODEL_ILP32) {
   1674 		psp->pr_size = 0;
   1675 		psp->pr_rssize = 0;
   1676 		psp->pr_bysize = 0;
   1677 		psp->pr_byrssize = 0;
   1678 		psp->pr_argv = 0;
   1679 		psp->pr_envp = 0;
   1680 	}
   1681 }
   1682 
   1683 /*ARGSUSED*/
   1684 static int
   1685 prioctl32(
   1686 	struct vnode *vp,
   1687 	int cmd,
   1688 	intptr_t arg,
   1689 	int flag,
   1690 	cred_t *cr,
   1691 	int *rvalp,
   1692 	caller_context_t *ct)
   1693 {
   1694 	caddr_t cmaddr = (caddr_t)arg;
   1695 	proc_t *p;
   1696 	user_t *up;
   1697 	kthread_t *t;
   1698 	klwp_t *lwp;
   1699 	prnode_t *pnp = VTOP(vp);
   1700 	prcommon_t *pcp;
   1701 	prnode_t *xpnp = NULL;
   1702 	int error;
   1703 	int zdisp;
   1704 	void *thing = NULL;
   1705 	size_t thingsize = 0;
   1706 
   1707 	/*
   1708 	 * For copyin()/copyout().
   1709 	 */
   1710 	union {
   1711 		caddr32_t	va;
   1712 		int		signo;
   1713 		int		nice;
   1714 		uint_t		lwpid;
   1715 		int32_t		flags;
   1716 		prstatus32_t	prstat;
   1717 		prrun32_t	prrun;
   1718 		sigset_t	smask;
   1719 		siginfo32_t	info;
   1720 		sysset_t	prmask;
   1721 		prgregset32_t	regs;
   1722 		prfpregset32_t	fpregs;
   1723 		prpsinfo32_t	prps;
   1724 		sigset_t	holdmask;
   1725 		fltset_t	fltmask;
   1726 		prcred_t	prcred;
   1727 		prusage32_t	prusage;
   1728 		prhusage_t	prhusage;
   1729 		ioc_prmap32_t	prmap;
   1730 		auxv32_t	auxv[__KERN_NAUXV_IMPL];
   1731 	} un32;
   1732 
   1733 	/*
   1734 	 * Native objects for internal use.
   1735 	 */
   1736 	union {
   1737 		caddr_t		va;
   1738 		int		signo;
   1739 		int		nice;
   1740 		uint_t		lwpid;
   1741 		long		flags;
   1742 		prstatus_t	prstat;
   1743 		prrun_t		prrun;
   1744 		sigset_t	smask;
   1745 		siginfo_t	info;
   1746 		sysset_t	prmask;
   1747 		prgregset_t	regs;
   1748 		prpsinfo_t	prps;
   1749 		sigset_t	holdmask;
   1750 		fltset_t	fltmask;
   1751 		prcred_t	prcred;
   1752 		prusage_t	prusage;
   1753 		prhusage_t	prhusage;
   1754 		auxv_t		auxv[__KERN_NAUXV_IMPL];
   1755 	} un;
   1756 
   1757 	if (pnp->pr_type == PR_TMPL)
   1758 		return (prctioctl(pnp, cmd, arg, flag, cr));
   1759 
   1760 	/*
   1761 	 * Support for old /proc interface.
   1762 	 */
   1763 	if (pnp->pr_pidfile != NULL) {
   1764 		ASSERT(pnp->pr_type == PR_PIDDIR);
   1765 		vp = pnp->pr_pidfile;
   1766 		pnp = VTOP(vp);
   1767 		ASSERT(pnp->pr_type == PR_PIDFILE);
   1768 	}
   1769 
   1770 	if (pnp->pr_type != PR_PIDFILE && pnp->pr_type != PR_LWPIDFILE)
   1771 		return (ENOTTY);
   1772 
   1773 	/*
   1774 	 * Fail ioctls which are logically "write" requests unless
   1775 	 * the user has write permission.
   1776 	 */
   1777 	if ((flag & FWRITE) == 0 && isprwrioctl(cmd))
   1778 		return (EBADF);
   1779 
   1780 	/*
   1781 	 * Perform any necessary copyin() operations before
   1782 	 * locking the process.  Helps avoid deadlocks and
   1783 	 * improves performance.
   1784 	 *
   1785 	 * Also, detect invalid ioctl codes here to avoid
   1786 	 * locking a process unnnecessarily.
   1787 	 *
   1788 	 * Also, prepare to allocate space that will be needed below,
   1789 	 * case by case.
   1790 	 */
   1791 	error = 0;
   1792 	switch (cmd) {
   1793 	case PIOCGETPR:
   1794 		thingsize = sizeof (proc_t);
   1795 		break;
   1796 	case PIOCGETU:
   1797 		thingsize = sizeof (user_t);
   1798 		break;
   1799 	case PIOCSTOP:
   1800 	case PIOCWSTOP:
   1801 	case PIOCLWPIDS:
   1802 	case PIOCGTRACE:
   1803 	case PIOCGENTRY:
   1804 	case PIOCGEXIT:
   1805 	case PIOCSRLC:
   1806 	case PIOCRRLC:
   1807 	case PIOCSFORK:
   1808 	case PIOCRFORK:
   1809 	case PIOCGREG:
   1810 	case PIOCGFPREG:
   1811 	case PIOCSTATUS:
   1812 	case PIOCLSTATUS:
   1813 	case PIOCPSINFO:
   1814 	case PIOCMAXSIG:
   1815 	case PIOCGXREGSIZE:
   1816 		break;
   1817 	case PIOCSXREG:		/* set extra registers */
   1818 	case PIOCGXREG:		/* get extra registers */
   1819 #if defined(__sparc)
   1820 		thingsize = sizeof (prxregset_t);
   1821 #else
   1822 		thingsize = 0;
   1823 #endif
   1824 		break;
   1825 	case PIOCACTION:
   1826 		thingsize = (NSIG-1) * sizeof (struct sigaction32);
   1827 		break;
   1828 	case PIOCGHOLD:
   1829 	case PIOCNMAP:
   1830 	case PIOCMAP:
   1831 	case PIOCGFAULT:
   1832 	case PIOCCFAULT:
   1833 	case PIOCCRED:
   1834 	case PIOCGROUPS:
   1835 	case PIOCUSAGE:
   1836 	case PIOCLUSAGE:
   1837 		break;
   1838 	case PIOCOPENPD:
   1839 		/*
   1840 		 * We will need this below.
   1841 		 * Allocate it now, before locking the process.
   1842 		 */
   1843 		xpnp = prgetnode(vp, PR_OPAGEDATA);
   1844 		break;
   1845 	case PIOCNAUXV:
   1846 	case PIOCAUXV:
   1847 		break;
   1848 
   1849 #if defined(__i386) || defined(__i386_COMPAT)
   1850 	case PIOCNLDT:
   1851 	case PIOCLDT:
   1852 		break;
   1853 #endif	/* __i386 || __i386_COMPAT */
   1854 
   1855 #if defined(__sparc)
   1856 	case PIOCGWIN:
   1857 		thingsize = sizeof (gwindows32_t);
   1858 		break;
   1859 #endif	/* __sparc */
   1860 
   1861 	case PIOCOPENM:		/* open mapped object for reading */
   1862 		if (cmaddr == NULL)
   1863 			un32.va = NULL;
   1864 		else if (copyin(cmaddr, &un32.va, sizeof (un32.va)))
   1865 			error = EFAULT;
   1866 		break;
   1867 
   1868 	case PIOCRUN:		/* make lwp or process runnable */
   1869 		if (cmaddr == NULL)
   1870 			un32.prrun.pr_flags = 0;
   1871 		else if (copyin(cmaddr, &un32.prrun, sizeof (un32.prrun)))
   1872 			error = EFAULT;
   1873 		break;
   1874 
   1875 	case PIOCOPENLWP:	/* return /proc lwp file descriptor */
   1876 		if (copyin(cmaddr, &un32.lwpid, sizeof (un32.lwpid)))
   1877 			error = EFAULT;
   1878 		break;
   1879 
   1880 	case PIOCSTRACE:	/* set signal trace mask */
   1881 		if (copyin(cmaddr, &un32.smask, sizeof (un32.smask)))
   1882 			error = EFAULT;
   1883 		break;
   1884 
   1885 	case PIOCSSIG:		/* set current signal */
   1886 		if (cmaddr == NULL)
   1887 			un32.info.si_signo = 0;
   1888 		else if (copyin(cmaddr, &un32.info, sizeof (un32.info)))
   1889 			error = EFAULT;
   1890 		break;
   1891 
   1892 	case PIOCKILL:		/* send signal */
   1893 	case PIOCUNKILL:	/* delete a signal */
   1894 		if (copyin(cmaddr, &un32.signo, sizeof (un32.signo)))
   1895 			error = EFAULT;
   1896 		break;
   1897 
   1898 	case PIOCNICE:		/* set nice priority */
   1899 		if (copyin(cmaddr, &un32.nice, sizeof (un32.nice)))
   1900 			error = EFAULT;
   1901 		break;
   1902 
   1903 	case PIOCSENTRY:	/* set syscall entry bit mask */
   1904 	case PIOCSEXIT:		/* set syscall exit bit mask */
   1905 		if (copyin(cmaddr, &un32.prmask, sizeof (un32.prmask)))
   1906 			error = EFAULT;
   1907 		break;
   1908 
   1909 	case PIOCSET:		/* set process flags */
   1910 	case PIOCRESET:		/* reset process flags */
   1911 		if (copyin(cmaddr, &un32.flags, sizeof (un32.flags)))
   1912 			error = EFAULT;
   1913 		break;
   1914 
   1915 	case PIOCSREG:		/* set general registers */
   1916 		if (copyin(cmaddr, un32.regs, sizeof (un32.regs)))
   1917 			error = EFAULT;
   1918 		break;
   1919 
   1920 	case PIOCSFPREG:	/* set floating-point registers */
   1921 		if (copyin(cmaddr, &un32.fpregs, sizeof (un32.fpregs)))
   1922 			error = EFAULT;
   1923 		break;
   1924 
   1925 	case PIOCSHOLD:		/* set signal-hold mask */
   1926 		if (copyin(cmaddr, &un32.holdmask, sizeof (un32.holdmask)))
   1927 			error = EFAULT;
   1928 		break;
   1929 
   1930 	case PIOCSFAULT:	/* set mask of traced faults */
   1931 		if (copyin(cmaddr, &un32.fltmask, sizeof (un32.fltmask)))
   1932 			error = EFAULT;
   1933 		break;
   1934 
   1935 	default:
   1936 		error = EINVAL;
   1937 		break;
   1938 	}
   1939 
   1940 	if (error)
   1941 		return (error);
   1942 
   1943 startover:
   1944 	/*
   1945 	 * If we need kmem_alloc()d space then we allocate it now, before
   1946 	 * grabbing the process lock.  Using kmem_alloc(KM_SLEEP) while
   1947 	 * holding the process lock leads to deadlock with the clock thread.
   1948 	 * (The clock thread wakes up the pageout daemon to free up space.
   1949 	 * If the clock thread blocks behind us and we are sleeping waiting
   1950 	 * for space, then space may never become available.)
   1951 	 */
   1952 	if (thingsize) {
   1953 		ASSERT(thing == NULL);
   1954 		thing = kmem_alloc(thingsize, KM_SLEEP);
   1955 	}
   1956 
   1957 	switch (cmd) {
   1958 	case PIOCPSINFO:
   1959 	case PIOCGETPR:
   1960 	case PIOCUSAGE:
   1961 	case PIOCLUSAGE:
   1962 		zdisp = ZYES;
   1963 		break;
   1964 	case PIOCSXREG:		/* set extra registers */
   1965 		/*
   1966 		 * perform copyin before grabbing the process lock
   1967 		 */
   1968 		if (thing) {
   1969 			if (copyin(cmaddr, thing, thingsize)) {
   1970 				kmem_free(thing, thingsize);
   1971 				return (EFAULT);
   1972 			}
   1973 		}
   1974 		/* fall through... */
   1975 	default:
   1976 		zdisp = ZNO;
   1977 		break;
   1978 	}
   1979 
   1980 	if ((error = prlock(pnp, zdisp)) != 0) {
   1981 		if (thing != NULL)
   1982 			kmem_free(thing, thingsize);
   1983 		if (xpnp)
   1984 			prfreenode(xpnp);
   1985 		return (error);
   1986 	}
   1987 
   1988 	pcp = pnp->pr_common;
   1989 	p = pcp->prc_proc;
   1990 	ASSERT(p != NULL);
   1991 
   1992 	/*
   1993 	 * Choose a thread/lwp for the operation.
   1994 	 */
   1995 	if (zdisp == ZNO && cmd != PIOCSTOP && cmd != PIOCWSTOP) {
   1996 		if (pnp->pr_type == PR_LWPIDFILE && cmd != PIOCLSTATUS) {
   1997 			t = pcp->prc_thread;
   1998 			ASSERT(t != NULL);
   1999 		} else {
   2000 			t = prchoose(p);	/* returns locked thread */
   2001 			ASSERT(t != NULL);
   2002 			thread_unlock(t);
   2003 		}
   2004 		lwp = ttolwp(t);
   2005 	}
   2006 
   2007 	error = 0;
   2008 	switch (cmd) {
   2009 
   2010 	case PIOCGETPR:		/* read struct proc */
   2011 	{
   2012 		proc_t *prp = thing;
   2013 
   2014 		*prp = *p;
   2015 		prunlock(pnp);
   2016 		if (copyout(prp, cmaddr, sizeof (proc_t)))
   2017 			error = EFAULT;
   2018 		kmem_free(prp, sizeof (proc_t));
   2019 		thing = NULL;
   2020 		break;
   2021 	}
   2022 
   2023 	case PIOCGETU:		/* read u-area */
   2024 	{
   2025 		user_t *userp = thing;
   2026 
   2027 		up = PTOU(p);
   2028 		*userp = *up;
   2029 		prunlock(pnp);
   2030 		if (copyout(userp, cmaddr, sizeof (user_t)))
   2031 			error = EFAULT;
   2032 		kmem_free(userp, sizeof (user_t));
   2033 		thing = NULL;
   2034 		break;
   2035 	}
   2036 
   2037 	case PIOCOPENM:		/* open mapped object for reading */
   2038 		if (PROCESS_NOT_32BIT(p) && cmaddr != NULL) {
   2039 			prunlock(pnp);
   2040 			error = EOVERFLOW;
   2041 			break;
   2042 		}
   2043 		error = propenm(pnp, cmaddr,
   2044 		    (caddr_t)(uintptr_t)un32.va, rvalp, cr);
   2045 		/* propenm() called prunlock(pnp) */
   2046 		break;
   2047 
   2048 	case PIOCSTOP:		/* stop process or lwp from running */
   2049 	case PIOCWSTOP:		/* wait for process or lwp to stop */
   2050 		/*
   2051 		 * Can't apply to a system process.
   2052 		 */
   2053 		if ((p->p_flag & SSYS) || p->p_as == &kas) {
   2054 			prunlock(pnp);
   2055 			error = EBUSY;
   2056 			break;
   2057 		}
   2058 
   2059 		if (cmd == PIOCSTOP)
   2060 			pr_stop(pnp);
   2061 
   2062 		/*
   2063 		 * If an lwp is waiting for itself or its process, don't wait.
   2064 		 * The lwp will never see the fact that itself is stopped.
   2065 		 */
   2066 		if ((pnp->pr_type == PR_LWPIDFILE)?
   2067 		    (pcp->prc_thread == curthread) : (p == curproc)) {
   2068 			if (cmd == PIOCWSTOP)
   2069 				error = EBUSY;
   2070 			prunlock(pnp);
   2071 			break;
   2072 		}
   2073 
   2074 		if ((error = pr_wait_stop(pnp, (time_t)0)) != 0)
   2075 			break;	/* pr_wait_stop() unlocked the process */
   2076 
   2077 		if (cmaddr == NULL)
   2078 			prunlock(pnp);
   2079 		else if (PROCESS_NOT_32BIT(p)) {
   2080 			prunlock(pnp);
   2081 			error = EOVERFLOW;
   2082 		} else {
   2083 			/*
   2084 			 * Return process/lwp status information.
   2085 			 */
   2086 			t = pr_thread(pnp);	/* returns locked thread */
   2087 			thread_unlock(t);
   2088 			oprgetstatus32(t, &un32.prstat, VTOZONE(vp));
   2089 			prunlock(pnp);
   2090 			if (copyout(&un32.prstat, cmaddr, sizeof (un32.prstat)))
   2091 				error = EFAULT;
   2092 		}
   2093 		break;
   2094 
   2095 	case PIOCRUN:		/* make lwp or process runnable */
   2096 	{
   2097 		long flags = un32.prrun.pr_flags;
   2098 
   2099 		/*
   2100 		 * Cannot set an lwp running is it is not stopped.
   2101 		 * Also, no lwp other than the /proc agent lwp can
   2102 		 * be set running so long as the /proc agent lwp exists.
   2103 		 */
   2104 		if ((!ISTOPPED(t) && !VSTOPPED(t) &&
   2105 		    !(t->t_proc_flag & TP_PRSTOP)) ||
   2106 		    (p->p_agenttp != NULL &&
   2107 		    (t != p->p_agenttp || pnp->pr_type != PR_LWPIDFILE))) {
   2108 			prunlock(pnp);
   2109 			error = EBUSY;
   2110 			break;
   2111 		}
   2112 
   2113 		if ((flags & PRSVADDR) && PROCESS_NOT_32BIT(p)) {
   2114 			prunlock(pnp);
   2115 			error = EOVERFLOW;
   2116 			break;
   2117 		}
   2118 
   2119 		if (flags & (PRSHOLD|PRSTRACE|PRSFAULT|PRSVADDR)) {
   2120 			un.prrun.pr_flags = (int)flags;
   2121 			un.prrun.pr_trace = un32.prrun.pr_trace;
   2122 			un.prrun.pr_sighold = un32.prrun.pr_sighold;
   2123 			un.prrun.pr_fault = un32.prrun.pr_fault;
   2124 			un.prrun.pr_vaddr =
   2125 			    (caddr_t)(uintptr_t)un32.prrun.pr_vaddr;
   2126 			prsetrun(t, &un.prrun);
   2127 		}
   2128 
   2129 		error = pr_setrun(pnp, prmaprunflags(flags));
   2130 
   2131 		prunlock(pnp);
   2132 		break;
   2133 	}
   2134 
   2135 	case PIOCLWPIDS:	/* get array of lwp identifiers */
   2136 	{
   2137 		int nlwp;
   2138 		int Nlwp;
   2139 		id_t *idp;
   2140 		id_t *Bidp;
   2141 
   2142 		Nlwp = nlwp = p->p_lwpcnt;
   2143 
   2144 		if (thing && thingsize != (Nlwp+1) * sizeof (id_t)) {
   2145 			kmem_free(thing, thingsize);
   2146 			thing = NULL;
   2147 		}
   2148 		if (thing == NULL) {
   2149 			thingsize = (Nlwp+1) * sizeof (id_t);
   2150 			thing = kmem_alloc(thingsize, KM_NOSLEEP);
   2151 		}
   2152 		if (thing == NULL) {
   2153 			prunlock(pnp);
   2154 			goto startover;
   2155 		}
   2156 
   2157 		idp = thing;
   2158 		thing = NULL;
   2159 		Bidp = idp;
   2160 		if ((t = p->p_tlist) != NULL) {
   2161 			do {
   2162 				ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
   2163 				ASSERT(nlwp > 0);
   2164 				--nlwp;
   2165 				*idp++ = t->t_tid;
   2166 			} while ((t = t->t_forw) != p->p_tlist);
   2167 		}
   2168 		*idp = 0;
   2169 		ASSERT(nlwp == 0);
   2170 		prunlock(pnp);
   2171 		if (copyout(Bidp, cmaddr, (Nlwp+1) * sizeof (id_t)))
   2172 			error = EFAULT;
   2173 		kmem_free(Bidp, (Nlwp+1) * sizeof (id_t));
   2174 		break;
   2175 	}
   2176 
   2177 	case PIOCOPENLWP:	/* return /proc lwp file descriptor */
   2178 	{
   2179 		vnode_t *xvp;
   2180 		int n;
   2181 
   2182 		prunlock(pnp);
   2183 		if ((xvp = prlwpnode(pnp, un32.lwpid)) == NULL)
   2184 			error = ENOENT;
   2185 		else if (error = fassign(&xvp, flag & (FREAD|FWRITE), &n)) {
   2186 			VN_RELE(xvp);
   2187 		} else
   2188 			*rvalp = n;
   2189 		break;
   2190 	}
   2191 
   2192 	case PIOCOPENPD:	/* return /proc page data file descriptor */
   2193 	{
   2194 		vnode_t *xvp = PTOV(xpnp);
   2195 		vnode_t *dp = pnp->pr_parent;
   2196 		int n;
   2197 
   2198 		if (PROCESS_NOT_32BIT(p)) {
   2199 			prunlock(pnp);
   2200 			prfreenode(xpnp);
   2201 			xpnp = NULL;
   2202 			error = EOVERFLOW;
   2203 			break;
   2204 		}
   2205 
   2206 		if (pnp->pr_type == PR_LWPIDFILE) {
   2207 			dp = VTOP(dp)->pr_parent;
   2208 			dp = VTOP(dp)->pr_parent;
   2209 		}
   2210 		ASSERT(VTOP(dp)->pr_type == PR_PIDDIR);
   2211 
   2212 		VN_HOLD(dp);
   2213 		pcp = pnp->pr_pcommon;
   2214 		xpnp->pr_ino = ptoi(pcp->prc_pid);
   2215 		xpnp->pr_common = pcp;
   2216 		xpnp->pr_pcommon = pcp;
   2217 		xpnp->pr_parent = dp;
   2218 
   2219 		xpnp->pr_next = p->p_plist;
   2220 		p->p_plist = xvp;
   2221 
   2222 		prunlock(pnp);
   2223 		if (error = fassign(&xvp, FREAD, &n)) {
   2224 			VN_RELE(xvp);
   2225 		} else
   2226 			*rvalp = n;
   2227 
   2228 		xpnp = NULL;
   2229 		break;
   2230 	}
   2231 
   2232 	case PIOCGTRACE:	/* get signal trace mask */
   2233 		prassignset(&un32.smask, &p->p_sigmask);
   2234 		prunlock(pnp);
   2235 		if (copyout(&un32.smask, cmaddr, sizeof (un32.smask)))
   2236 			error = EFAULT;
   2237 		break;
   2238 
   2239 	case PIOCSTRACE:	/* set signal trace mask */
   2240 		prdelset(&un32.smask, SIGKILL);
   2241 		prassignset(&p->p_sigmask, &un32.smask);
   2242 		if (!sigisempty(&p->p_sigmask))
   2243 			p->p_proc_flag |= P_PR_TRACE;
   2244 		else if (prisempty(&p->p_fltmask)) {
   2245 			up = PTOU(p);
   2246 			if (up->u_systrap == 0)
   2247 				p->p_proc_flag &= ~P_PR_TRACE;
   2248 		}
   2249 		prunlock(pnp);
   2250 		break;
   2251 
   2252 	case PIOCSSIG:		/* set current signal */
   2253 		if (un32.info.si_signo != 0 && PROCESS_NOT_32BIT(p)) {
   2254 			prunlock(pnp);
   2255 			error = EOVERFLOW;
   2256 		} else {
   2257 			bzero(&un.info, sizeof (un.info));
   2258 			siginfo_32tok(&un32.info, (k_siginfo_t *)&un.info);
   2259 			error = pr_setsig(pnp, &un.info);
   2260 			prunlock(pnp);
   2261 			if (un32.info.si_signo == SIGKILL && error == 0)
   2262 				pr_wait_die(pnp);
   2263 		}
   2264 		break;
   2265 
   2266 	case PIOCKILL:		/* send signal */
   2267 		error = pr_kill(pnp, un32.signo, cr);
   2268 		prunlock(pnp);
   2269 		if (un32.signo == SIGKILL && error == 0)
   2270 			pr_wait_die(pnp);
   2271 		break;
   2272 
   2273 	case PIOCUNKILL:	/* delete a signal */
   2274 		error = pr_unkill(pnp, un32.signo);
   2275 		prunlock(pnp);
   2276 		break;
   2277 
   2278 	case PIOCNICE:		/* set nice priority */
   2279 		error = pr_nice(p, un32.nice, cr);
   2280 		prunlock(pnp);
   2281 		break;
   2282 
   2283 	case PIOCGENTRY:	/* get syscall entry bit mask */
   2284 	case PIOCGEXIT:		/* get syscall exit bit mask */
   2285 		up = PTOU(p);
   2286 		if (cmd == PIOCGENTRY) {
   2287 			prassignset(&un32.prmask, &up->u_entrymask);
   2288 		} else {
   2289 			prassignset(&un32.prmask, &up->u_exitmask);
   2290 		}
   2291 		prunlock(pnp);
   2292 		if (copyout(&un32.prmask, cmaddr, sizeof (un32.prmask)))
   2293 			error = EFAULT;
   2294 		break;
   2295 
   2296 	case PIOCSENTRY:	/* set syscall entry bit mask */
   2297 	case PIOCSEXIT:		/* set syscall exit bit mask */
   2298 		pr_setentryexit(p, &un32.prmask, cmd == PIOCSENTRY);
   2299 		prunlock(pnp);
   2300 		break;
   2301 
   2302 	case PIOCSRLC:		/* obsolete: set running on last /proc close */
   2303 		error = pr_set(p, prmapsetflags(PR_RLC));
   2304 		prunlock(pnp);
   2305 		break;
   2306 
   2307 	case PIOCRRLC:		/* obsolete: reset run-on-last-close flag */
   2308 		error = pr_unset(p, prmapsetflags(PR_RLC));
   2309 		prunlock(pnp);
   2310 		break;
   2311 
   2312 	case PIOCSFORK:		/* obsolete: set inherit-on-fork flag */
   2313 		error = pr_set(p, prmapsetflags(PR_FORK));
   2314 		prunlock(pnp);
   2315 		break;
   2316 
   2317 	case PIOCRFORK:		/* obsolete: reset inherit-on-fork flag */
   2318 		error = pr_unset(p, prmapsetflags(PR_FORK));
   2319 		prunlock(pnp);
   2320 		break;
   2321 
   2322 	case PIOCSET:		/* set process flags */
   2323 		error = pr_set(p, prmapsetflags((long)un32.flags));
   2324 		prunlock(pnp);
   2325 		break;
   2326 
   2327 	case PIOCRESET:		/* reset process flags */
   2328 		error = pr_unset(p, prmapsetflags((long)un32.flags));
   2329 		prunlock(pnp);
   2330 		break;
   2331 
   2332 	case PIOCGREG:		/* get general registers */
   2333 		if (PROCESS_NOT_32BIT(p))
   2334 			error = EOVERFLOW;
   2335 		else if (t->t_state != TS_STOPPED && !VSTOPPED(t))
   2336 			bzero(un32.regs, sizeof (un32.regs));
   2337 		else {
   2338 			/* drop p_lock while touching the lwp's stack */
   2339 			mutex_exit(&p->p_lock);
   2340 			prgetprregs32(lwp, un32.regs);
   2341 			mutex_enter(&p->p_lock);
   2342 		}
   2343 		prunlock(pnp);
   2344 		if (error == 0 &&
   2345 		    copyout(un32.regs, cmaddr, sizeof (un32.regs)))
   2346 			error = EFAULT;
   2347 		break;
   2348 
   2349 	case PIOCSREG:		/* set general registers */
   2350 		if (PROCESS_NOT_32BIT(p))
   2351 			error = EOVERFLOW;
   2352 		else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
   2353 			error = EBUSY;
   2354 		else {
   2355 			/* drop p_lock while touching the lwp's stack */
   2356 			mutex_exit(&p->p_lock);
   2357 			prgregset_32ton(lwp, un32.regs, un.regs);
   2358 			prsetprregs(lwp, un.regs, 0);
   2359 			mutex_enter(&p->p_lock);
   2360 		}
   2361 		prunlock(pnp);
   2362 		break;
   2363 
   2364 	case PIOCGFPREG:	/* get floating-point registers */
   2365 		if (!prhasfp())
   2366 			error = EINVAL;	/* No FP support */
   2367 		else if (PROCESS_NOT_32BIT(p))
   2368 			error = EOVERFLOW;
   2369 		else if (t->t_state != TS_STOPPED && !VSTOPPED(t))
   2370 			bzero(&un32.fpregs, sizeof (un32.fpregs));
   2371 		else {
   2372 			/* drop p_lock while touching the lwp's stack */
   2373 			mutex_exit(&p->p_lock);
   2374 			prgetprfpregs32(lwp, &un32.fpregs);
   2375 			mutex_enter(&p->p_lock);
   2376 		}
   2377 		prunlock(pnp);
   2378 		if (error == 0 &&
   2379 		    copyout(&un32.fpregs, cmaddr, sizeof (un32.fpregs)))
   2380 			error = EFAULT;
   2381 		break;
   2382 
   2383 	case PIOCSFPREG:	/* set floating-point registers */
   2384 		if (!prhasfp())
   2385 			error = EINVAL;	/* No FP support */
   2386 		else if (PROCESS_NOT_32BIT(p))
   2387 			error = EOVERFLOW;
   2388 		else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
   2389 			error = EBUSY;
   2390 		else {
   2391 			/* drop p_lock while touching the lwp's stack */
   2392 			mutex_exit(&p->p_lock);
   2393 			prsetprfpregs32(lwp, &un32.fpregs);
   2394 			mutex_enter(&p->p_lock);
   2395 		}
   2396 		prunlock(pnp);
   2397 		break;
   2398 
   2399 	case PIOCGXREGSIZE:	/* get the size of the extra registers */
   2400 	{
   2401 		int xregsize;
   2402 
   2403 		if (prhasx(p)) {
   2404 			xregsize = prgetprxregsize(p);
   2405 			prunlock(pnp);
   2406 			if (copyout(&xregsize, cmaddr, sizeof (xregsize)))
   2407 				error = EFAULT;
   2408 		} else {
   2409 			prunlock(pnp);
   2410 			error = EINVAL;	/* No extra register support */
   2411 		}
   2412 		break;
   2413 	}
   2414 
   2415 	case PIOCGXREG:		/* get extra registers */
   2416 		if (PROCESS_NOT_32BIT(p))
   2417 			error = EOVERFLOW;
   2418 		else if (!prhasx(p))
   2419 			error = EINVAL;	/* No extra register support */
   2420 		else {
   2421 			bzero(thing, thingsize);
   2422 			if (t->t_state == TS_STOPPED || VSTOPPED(t)) {
   2423 				/* drop p_lock to touch the stack */
   2424 				mutex_exit(&p->p_lock);
   2425 				prgetprxregs(lwp, thing);
   2426 				mutex_enter(&p->p_lock);
   2427 			}
   2428 		}
   2429 		prunlock(pnp);
   2430 		if (error == 0 &&
   2431 		    copyout(thing, cmaddr, thingsize))
   2432 			error = EFAULT;
   2433 		if (thing) {
   2434 			kmem_free(thing, thingsize);
   2435 			thing = NULL;
   2436 		}
   2437 		break;
   2438 
   2439 	case PIOCSXREG:		/* set extra registers */
   2440 		if (PROCESS_NOT_32BIT(p))
   2441 			error = EOVERFLOW;
   2442 		else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
   2443 			error = EBUSY;
   2444 		else if (!prhasx(p))
   2445 			error = EINVAL;	/* No extra register support */
   2446 		else if (thing) {
   2447 			/* drop p_lock while touching the lwp's stack */
   2448 			mutex_exit(&p->p_lock);
   2449 			prsetprxregs(lwp, thing);
   2450 			mutex_enter(&p->p_lock);
   2451 		}
   2452 		prunlock(pnp);
   2453 		if (thing) {
   2454 			kmem_free(thing, thingsize);
   2455 			thing = NULL;
   2456 		}
   2457 		break;
   2458 
   2459 	case PIOCSTATUS:	/* get process/lwp status */
   2460 		if (PROCESS_NOT_32BIT(p)) {
   2461 			prunlock(pnp);
   2462 			error = EOVERFLOW;
   2463 			break;
   2464 		}
   2465 		oprgetstatus32(t, &un32.prstat, VTOZONE(vp));
   2466 		prunlock(pnp);
   2467 		if (copyout(&un32.prstat, cmaddr, sizeof (un32.prstat)))
   2468 			error = EFAULT;
   2469 		break;
   2470 
   2471 	case PIOCLSTATUS:	/* get status for process & all lwps */
   2472 	{
   2473 		int Nlwp;
   2474 		int nlwp;
   2475 		prstatus32_t *Bprsp;
   2476 		prstatus32_t *prsp;
   2477 
   2478 		if (PROCESS_NOT_32BIT(p)) {
   2479 			prunlock(pnp);
   2480 			if (thing) {
   2481 				kmem_free(thing, thingsize);
   2482 				thing = NULL;
   2483 			}
   2484 			error = EOVERFLOW;
   2485 			break;
   2486 		}
   2487 
   2488 		nlwp = Nlwp = p->p_lwpcnt;
   2489 
   2490 		if (thing && thingsize != (Nlwp+1) * sizeof (prstatus32_t)) {
   2491 			kmem_free(thing, thingsize);
   2492 			thing = NULL;
   2493 		}
   2494 		if (thing == NULL) {
   2495 			thingsize = (Nlwp+1) * sizeof (prstatus32_t);
   2496 			thing = kmem_alloc(thingsize, KM_NOSLEEP);
   2497 		}
   2498 		if (thing == NULL) {
   2499 			prunlock(pnp);
   2500 			goto startover;
   2501 		}
   2502 
   2503 		Bprsp = (prstatus32_t *)thing;
   2504 		thing = NULL;
   2505 		prsp = Bprsp;
   2506 		oprgetstatus32(t, prsp, VTOZONE(vp));
   2507 		t = p->p_tlist;
   2508 		do {
   2509 			ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
   2510 			ASSERT(nlwp > 0);
   2511 			--nlwp;
   2512 			oprgetstatus32(t, ++prsp, VTOZONE(vp));
   2513 		} while ((t = t->t_forw) != p->p_tlist);
   2514 		ASSERT(nlwp == 0);
   2515 		prunlock(pnp);
   2516 		if (copyout(Bprsp, cmaddr, (Nlwp+1) * sizeof (prstatus32_t)))
   2517 			error = EFAULT;
   2518 
   2519 		kmem_free(Bprsp, (Nlwp + 1) * sizeof (prstatus32_t));
   2520 		break;
   2521 	}
   2522 
   2523 	case PIOCPSINFO:	/* get ps(1) information */
   2524 	{
   2525 		prpsinfo32_t *psp = &un32.prps;
   2526 
   2527 		oprgetpsinfo32(p, psp,
   2528 		    (pnp->pr_type == PR_LWPIDFILE)? pcp->prc_thread : NULL);
   2529 
   2530 		prunlock(pnp);
   2531 		if (copyout(&un32.prps, cmaddr, sizeof (un32.prps)))
   2532 			error = EFAULT;
   2533 		break;
   2534 	}
   2535 
   2536 	case PIOCMAXSIG:	/* get maximum signal number */
   2537 	{
   2538 		int n = NSIG-1;
   2539 
   2540 		prunlock(pnp);
   2541 		if (copyout(&n, cmaddr, sizeof (int)))
   2542 			error = EFAULT;
   2543 		break;
   2544 	}
   2545 
   2546 	case PIOCACTION:	/* get signal action structures */
   2547 	{
   2548 		uint_t sig;
   2549 		struct sigaction32 *sap = thing;
   2550 
   2551 		if (PROCESS_NOT_32BIT(p))
   2552 			error = EOVERFLOW;
   2553 		else {
   2554 			up = PTOU(p);
   2555 			for (sig = 1; sig < NSIG; sig++)
   2556 				prgetaction32(p, up, sig, &sap[sig-1]);
   2557 		}
   2558 		prunlock(pnp);
   2559 		if (error == 0 &&
   2560 		    copyout(sap, cmaddr, (NSIG-1)*sizeof (struct sigaction32)))
   2561 			error = EFAULT;
   2562 		kmem_free(sap, (NSIG-1)*sizeof (struct sigaction32));
   2563 		thing = NULL;
   2564 		break;
   2565 	}
   2566 
   2567 	case PIOCGHOLD:		/* get signal-hold mask */
   2568 		schedctl_finish_sigblock(t);
   2569 		sigktou(&t->t_hold, &un32.holdmask);
   2570 		prunlock(pnp);
   2571 		if (copyout(&un32.holdmask, cmaddr, sizeof (un32.holdmask)))
   2572 			error = EFAULT;
   2573 		break;
   2574 
   2575 	case PIOCSHOLD:		/* set signal-hold mask */
   2576 		pr_sethold(pnp, &un32.holdmask);
   2577 		prunlock(pnp);
   2578 		break;
   2579 
   2580 	case PIOCNMAP:		/* get number of memory mappings */
   2581 	{
   2582 		int n;
   2583 		struct as *as = p->p_as;
   2584 
   2585 		if ((p->p_flag & SSYS) || as == &kas)
   2586 			n = 0;
   2587 		else {
   2588 			mutex_exit(&p->p_lock);
   2589 			AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
   2590 			n = prnsegs(as, 0);
   2591 			AS_LOCK_EXIT(as, &as->a_lock);
   2592 			mutex_enter(&p->p_lock);
   2593 		}
   2594 		prunlock(pnp);
   2595 		if (copyout(&n, cmaddr, sizeof (int)))
   2596 			error = EFAULT;
   2597 		break;
   2598 	}
   2599 
   2600 	case PIOCMAP:		/* get memory map information */
   2601 	{
   2602 		list_t iolhead;
   2603 		struct as *as = p->p_as;
   2604 
   2605 		if ((p->p_flag & SSYS) || as == &kas) {
   2606 			error = 0;
   2607 			prunlock(pnp);
   2608 		} else if (PROCESS_NOT_32BIT(p)) {
   2609 			error = EOVERFLOW;
   2610 			prunlock(pnp);
   2611 		} else {
   2612 			mutex_exit(&p->p_lock);
   2613 			AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
   2614 			error = oprgetmap32(p, &iolhead);
   2615 			AS_LOCK_EXIT(as, &as->a_lock);
   2616 			mutex_enter(&p->p_lock);
   2617 			prunlock(pnp);
   2618 
   2619 			error = pr_iol_copyout_and_free(&iolhead,
   2620 			    &cmaddr, error);
   2621 		}
   2622 		/*
   2623 		 * The procfs PIOCMAP ioctl returns an all-zero buffer
   2624 		 * to indicate the end of the prmap[] array.
   2625 		 * Append it to whatever has already been copied out.
   2626 		 */
   2627 		bzero(&un32.prmap, sizeof (un32.prmap));
   2628 		if (!error &&
   2629 		    copyout(&un32.prmap, cmaddr, sizeof (un32.prmap)))
   2630 				error = EFAULT;
   2631 		break;
   2632 	}
   2633 
   2634 	case PIOCGFAULT:	/* get mask of traced faults */
   2635 		prassignset(&un32.fltmask, &p->p_fltmask);
   2636 		prunlock(pnp);
   2637 		if (copyout(&un32.fltmask, cmaddr, sizeof (un32.fltmask)))
   2638 			error = EFAULT;
   2639 		break;
   2640 
   2641 	case PIOCSFAULT:	/* set mask of traced faults */
   2642 		pr_setfault(p, &un32.fltmask);
   2643 		prunlock(pnp);
   2644 		break;
   2645 
   2646 	case PIOCCFAULT:	/* clear current fault */
   2647 		lwp->lwp_curflt = 0;
   2648 		prunlock(pnp);
   2649 		break;
   2650 
   2651 	case PIOCCRED:		/* get process credentials */
   2652 	{
   2653 		cred_t *cp;
   2654 
   2655 		mutex_enter(&p->p_crlock);
   2656 		cp = p->p_cred;
   2657 		un32.prcred.pr_euid = crgetuid(cp);
   2658 		un32.prcred.pr_ruid = crgetruid(cp);
   2659 		un32.prcred.pr_suid = crgetsuid(cp);
   2660 		un32.prcred.pr_egid = crgetgid(cp);
   2661 		un32.prcred.pr_rgid = crgetrgid(cp);
   2662 		un32.prcred.pr_sgid = crgetsgid(cp);
   2663 		un32.prcred.pr_ngroups = crgetngroups(cp);
   2664 		mutex_exit(&p->p_crlock);
   2665 
   2666 		prunlock(pnp);
   2667 		if (copyout(&un32.prcred, cmaddr, sizeof (un32.prcred)))
   2668 			error = EFAULT;
   2669 		break;
   2670 	}
   2671 
   2672 	case PIOCGROUPS:	/* get supplementary groups */
   2673 	{
   2674 		cred_t *cp;
   2675 
   2676 		mutex_enter(&p->p_crlock);
   2677 		cp = p->p_cred;
   2678 		crhold(cp);
   2679 		mutex_exit(&p->p_crlock);
   2680 
   2681 		prunlock(pnp);
   2682 		if (copyout(crgetgroups(cp), cmaddr,
   2683 		    MAX(crgetngroups(cp), 1) * sizeof (gid_t)))
   2684 			error = EFAULT;
   2685 		crfree(cp);
   2686 		break;
   2687 	}
   2688 
   2689 	case PIOCUSAGE:		/* get usage info */
   2690 	{
   2691 		/*
   2692 		 * For an lwp file descriptor, return just the lwp usage.
   2693 		 * For a process file descriptor, return total usage,
   2694 		 * all current lwps plus all defunct lwps.
   2695 		 */
   2696 		prhusage_t *pup = &un32.prhusage;
   2697 		prusage32_t *upup;
   2698 
   2699 		bzero(pup, sizeof (*pup));
   2700 		pup->pr_tstamp = gethrtime();
   2701 
   2702 		if (pnp->pr_type == PR_LWPIDFILE) {
   2703 			t = pcp->prc_thread;
   2704 			if (t != NULL)
   2705 				prgetusage(t, pup);
   2706 			else
   2707 				error = ENOENT;
   2708 		} else {
   2709 			pup->pr_count  = p->p_defunct;
   2710 			pup->pr_create = p->p_mstart;
   2711 			pup->pr_term   = p->p_mterm;
   2712 
   2713 			pup->pr_rtime    = p->p_mlreal;
   2714 			pup->pr_utime    = p->p_acct[LMS_USER];
   2715 			pup->pr_stime    = p->p_acct[LMS_SYSTEM];
   2716 			pup->pr_ttime    = p->p_acct[LMS_TRAP];
   2717 			pup->pr_tftime   = p->p_acct[LMS_TFAULT];
   2718 			pup->pr_dftime   = p->p_acct[LMS_DFAULT];
   2719 			pup->pr_kftime   = p->p_acct[LMS_KFAULT];
   2720 			pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
   2721 			pup->pr_slptime  = p->p_acct[LMS_SLEEP];
   2722 			pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
   2723 			pup->pr_stoptime = p->p_acct[LMS_STOPPED];
   2724 
   2725 			pup->pr_minf  = p->p_ru.minflt;
   2726 			pup->pr_majf  = p->p_ru.majflt;
   2727 			pup->pr_nswap = p->p_ru.nswap;
   2728 			pup->pr_inblk = p->p_ru.inblock;
   2729 			pup->pr_oublk = p->p_ru.oublock;
   2730 			pup->pr_msnd  = p->p_ru.msgsnd;
   2731 			pup->pr_mrcv  = p->p_ru.msgrcv;
   2732 			pup->pr_sigs  = p->p_ru.nsignals;
   2733 			pup->pr_vctx  = p->p_ru.nvcsw;
   2734 			pup->pr_ictx  = p->p_ru.nivcsw;
   2735 			pup->pr_sysc  = p->p_ru.sysc;
   2736 			pup->pr_ioch  = p->p_ru.ioch;
   2737 
   2738 			/*
   2739 			 * Add the usage information for each active lwp.
   2740 			 */
   2741 			if ((t = p->p_tlist) != NULL &&
   2742 			    !(pcp->prc_flags & PRC_DESTROY)) {
   2743 				do {
   2744 					ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
   2745 					pup->pr_count++;
   2746 					praddusage(t, pup);
   2747 				} while ((t = t->t_forw) != p->p_tlist);
   2748 			}
   2749 		}
   2750 
   2751 		prunlock(pnp);
   2752 
   2753 		upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
   2754 		prcvtusage32(pup, upup);
   2755 		if (copyout(upup, cmaddr, sizeof (*upup)))
   2756 			error = EFAULT;
   2757 		kmem_free(upup, sizeof (*upup));
   2758 
   2759 		break;
   2760 	}
   2761 
   2762 	case PIOCLUSAGE:	/* get detailed usage info */
   2763 	{
   2764 		int Nlwp;
   2765 		int nlwp;
   2766 		prusage32_t *upup;
   2767 		prusage32_t *Bupup;
   2768 		prhusage_t *pup;
   2769 		hrtime_t curtime;
   2770 
   2771 		nlwp = Nlwp = (pcp->prc_flags & PRC_DESTROY)? 0 : p->p_lwpcnt;
   2772 
   2773 		if (thing && thingsize !=
   2774 		    sizeof (prhusage_t) + (Nlwp+1) * sizeof (prusage32_t)) {
   2775 			kmem_free(thing, thingsize);
   2776 			thing = NULL;
   2777 		}
   2778 		if (thing == NULL) {
   2779 			thingsize = sizeof (prhusage_t) +
   2780 			    (Nlwp+1) * sizeof (prusage32_t);
   2781 			thing = kmem_alloc(thingsize, KM_NOSLEEP);
   2782 		}
   2783 		if (thing == NULL) {
   2784 			prunlock(pnp);
   2785 			goto startover;
   2786 		}
   2787 
   2788 		pup = (prhusage_t *)thing;
   2789 		upup = Bupup = (prusage32_t *)(pup + 1);
   2790 
   2791 		ASSERT(p == pcp->prc_proc);
   2792 
   2793 		curtime = gethrtime();
   2794 
   2795 		/*
   2796 		 * First the summation over defunct lwps.
   2797 		 */
   2798 		bzero(pup, sizeof (*pup));
   2799 		pup->pr_count  = p->p_defunct;
   2800 		pup->pr_tstamp = curtime;
   2801 		pup->pr_create = p->p_mstart;
   2802 		pup->pr_term   = p->p_mterm;
   2803 
   2804 		pup->pr_rtime    = p->p_mlreal;
   2805 		pup->pr_utime    = p->p_acct[LMS_USER];
   2806 		pup->pr_stime    = p->p_acct[LMS_SYSTEM];
   2807 		pup->pr_ttime    = p->p_acct[LMS_TRAP];
   2808 		pup->pr_tftime   = p->p_acct[LMS_TFAULT];
   2809 		pup->pr_dftime   = p->p_acct[LMS_DFAULT];
   2810 		pup->pr_kftime   = p->p_acct[LMS_KFAULT];
   2811 		pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
   2812 		pup->pr_slptime  = p->p_acct[LMS_SLEEP];
   2813 		pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
   2814 		pup->pr_stoptime = p->p_acct[LMS_STOPPED];
   2815 
   2816 		pup->pr_minf  = p->p_ru.minflt;
   2817 		pup->pr_majf  = p->p_ru.majflt;
   2818 		pup->pr_nswap = p->p_ru.nswap;
   2819 		pup->pr_inblk = p->p_ru.inblock;
   2820 		pup->pr_oublk = p->p_ru.oublock;
   2821 		pup->pr_msnd  = p->p_ru.msgsnd;
   2822 		pup->pr_mrcv  = p->p_ru.msgrcv;
   2823 		pup->pr_sigs  = p->p_ru.nsignals;
   2824 		pup->pr_vctx  = p->p_ru.nvcsw;
   2825 		pup->pr_ictx  = p->p_ru.nivcsw;
   2826 		pup->pr_sysc  = p->p_ru.sysc;
   2827 		pup->pr_ioch  = p->p_ru.ioch;
   2828 
   2829 		prcvtusage32(pup, upup);
   2830 
   2831 		/*
   2832 		 * Fill one prusage struct for each active lwp.
   2833 		 */
   2834 		if ((t = p->p_tlist) != NULL &&
   2835 		    !(pcp->prc_flags & PRC_DESTROY)) {
   2836 			do {
   2837 				ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
   2838 				ASSERT(nlwp > 0);
   2839 				--nlwp;
   2840 				upup++;
   2841 				prgetusage(t, pup);
   2842 				prcvtusage32(pup, upup);
   2843 			} while ((t = t->t_forw) != p->p_tlist);
   2844 		}
   2845 		ASSERT(nlwp == 0);
   2846 
   2847 		prunlock(pnp);
   2848 		if (copyout(Bupup, cmaddr, (Nlwp+1) * sizeof (prusage32_t)))
   2849 			error = EFAULT;
   2850 		kmem_free(thing, thingsize);
   2851 		thing = NULL;
   2852 		break;
   2853 	}
   2854 
   2855 	case PIOCNAUXV:		/* get number of aux vector entries */
   2856 	{
   2857 		int n = __KERN_NAUXV_IMPL;
   2858 
   2859 		prunlock(pnp);
   2860 		if (copyout(&n, cmaddr, sizeof (int)))
   2861 			error = EFAULT;
   2862 		break;
   2863 	}
   2864 
   2865 	case PIOCAUXV:		/* get aux vector (see sys/auxv.h) */
   2866 	{
   2867 		int i;
   2868 
   2869 		if (PROCESS_NOT_32BIT(p)) {
   2870 			prunlock(pnp);
   2871 			error = EOVERFLOW;
   2872 		} else {
   2873 			up = PTOU(p);
   2874 			for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
   2875 				un32.auxv[i].a_type = up->u_auxv[i].a_type;
   2876 				un32.auxv[i].a_un.a_val =
   2877 				    (int32_t)up->u_auxv[i].a_un.a_val;
   2878 			}
   2879 			prunlock(pnp);
   2880 			if (copyout(un32.auxv, cmaddr,
   2881 			    __KERN_NAUXV_IMPL * sizeof (auxv32_t)))
   2882 				error = EFAULT;
   2883 		}
   2884 		break;
   2885 	}
   2886 
   2887 #if defined(__i386) || defined(__i386_COMPAT)
   2888 	case PIOCNLDT:		/* get number of LDT entries */
   2889 	{
   2890 		int n;
   2891 
   2892 		mutex_exit(&p->p_lock);
   2893 		mutex_enter(&p->p_ldtlock);
   2894 		n = prnldt(p);
   2895 		mutex_exit(&p->p_ldtlock);
   2896 		mutex_enter(&p->p_lock);
   2897 		prunlock(pnp);
   2898 		if (copyout(&n, cmaddr, sizeof (n)))
   2899 			error = EFAULT;
   2900 		break;
   2901 	}
   2902 
   2903 	case PIOCLDT:		/* get LDT entries */
   2904 	{
   2905 		struct ssd *ssd;
   2906 		int n;
   2907 
   2908 		mutex_exit(&p->p_lock);
   2909 		mutex_enter(&p->p_ldtlock);
   2910 		n = prnldt(p);
   2911 
   2912 		if (thing && thingsize != (n+1) * sizeof (*ssd)) {
   2913 			kmem_free(thing, thingsize);
   2914 			thing = NULL;
   2915 		}
   2916 		if (thing == NULL) {
   2917 			thingsize = (n+1) * sizeof (*ssd);
   2918 			thing = kmem_alloc(thingsize, KM_NOSLEEP);
   2919 		}
   2920 		if (thing == NULL) {
   2921 			mutex_exit(&p->p_ldtlock);
   2922 			mutex_enter(&p->p_lock);
   2923 			prunlock(pnp);
   2924 			goto startover;
   2925 		}
   2926 
   2927 		ssd = thing;
   2928 		thing = NULL;
   2929 		if (n != 0)
   2930 			prgetldt(p, ssd);
   2931 		mutex_exit(&p->p_ldtlock);
   2932 		mutex_enter(&p->p_lock);
   2933 		prunlock(pnp);
   2934 
   2935 		/* mark the end of the list with a null entry */
   2936 		bzero(&ssd[n], sizeof (*ssd));
   2937 		if (copyout(ssd, cmaddr, (n+1) * sizeof (*ssd)))
   2938 			error = EFAULT;
   2939 		kmem_free(ssd, (n+1) * sizeof (*ssd));
   2940 		break;
   2941 	}
   2942 #endif	/* __i386 || __i386_COMPAT */
   2943 
   2944 #if defined(__sparc)
   2945 	case PIOCGWIN:		/* get gwindows_t (see sys/reg.h) */
   2946 	{
   2947 		gwindows32_t *gwp = thing;
   2948 
   2949 		if (PROCESS_NOT_32BIT(p)) {
   2950 			prunlock(pnp);
   2951 			error = EOVERFLOW;
   2952 		} else {
   2953 			/* drop p->p_lock while touching the stack */
   2954 			mutex_exit(&p->p_lock);
   2955 			bzero(gwp, sizeof (*gwp));
   2956 			prgetwindows32(lwp, gwp);
   2957 			mutex_enter(&p->p_lock);
   2958 			prunlock(pnp);
   2959 			if (copyout(gwp, cmaddr, sizeof (*gwp)))
   2960 				error = EFAULT;
   2961 		}
   2962 		kmem_free(gwp, sizeof (*gwp));
   2963 		thing = NULL;
   2964 		break;
   2965 	}
   2966 #endif	/* __sparc */
   2967 
   2968 	default:
   2969 		prunlock(pnp);
   2970 		error = EINVAL;
   2971 		break;
   2972 
   2973 	}
   2974 
   2975 	ASSERT(thing == NULL);
   2976 	ASSERT(xpnp == NULL);
   2977 	return (error);
   2978 }
   2979 #endif	/* _SYSCALL32_IMPL */
   2980 
   2981 /*
   2982  * Distinguish "writeable" ioctl requests from others.
   2983  */
   2984 static int
   2985 isprwrioctl(int cmd)
   2986 {
   2987 	switch (cmd) {
   2988 	case PIOCSTOP:
   2989 	case PIOCRUN:
   2990 	case PIOCSTRACE:
   2991 	case PIOCSSIG:
   2992 	case PIOCKILL:
   2993 	case PIOCUNKILL:
   2994 	case PIOCNICE:
   2995 	case PIOCSENTRY:
   2996 	case PIOCSEXIT:
   2997 	case PIOCSRLC:
   2998 	case PIOCRRLC:
   2999 	case PIOCSREG:
   3000 	case PIOCSFPREG:
   3001 	case PIOCSXREG:
   3002 	case PIOCSHOLD:
   3003 	case PIOCSFAULT:
   3004 	case PIOCCFAULT:
   3005 	case PIOCSFORK:
   3006 	case PIOCRFORK:
   3007 	case PIOCSET:
   3008 	case PIOCRESET:
   3009 		return (1);
   3010 	}
   3011 	return (0);
   3012 }
   3013 
   3014 /*
   3015  * Map the ioctl() interface run flags to the new interface run flags.
   3016  */
   3017 static ulong_t
   3018 prmaprunflags(long flags)
   3019 {
   3020 	ulong_t newflags = 0;
   3021 
   3022 	if (flags & PRCSIG)
   3023 		newflags |= 0x01;
   3024 	if (flags & PRCFAULT)
   3025 		newflags |= 0x02;
   3026 	if (flags & PRSTEP)
   3027 		newflags |= 0x04;
   3028 	if (flags & PRSABORT)
   3029 		newflags |= 0x08;
   3030 	if (flags & PRSTOP)
   3031 		newflags |= 0x10;
   3032 	return (newflags);
   3033 }
   3034 
   3035 /*
   3036  * Map the ioctl() interface settable mode flags to the new interface flags.
   3037  */
   3038 static long
   3039 prmapsetflags(long flags)
   3040 {
   3041 	long newflags = 0;
   3042 
   3043 #define	ALLFLAGS	\
   3044 	(PR_FORK|PR_RLC|PR_KLC|PR_ASYNC|PR_BPTADJ|PR_MSACCT|PR_PCOMPAT)
   3045 
   3046 	if (flags & ~ALLFLAGS)
   3047 		newflags = 0xffff;	/* forces EINVAL */
   3048 	if (flags & PR_FORK)
   3049 		newflags |= (0x00100000 | 0x08000000);
   3050 	if (flags & PR_RLC)
   3051 		newflags |= 0x00200000;
   3052 	if (flags & PR_KLC)
   3053 		newflags |= 0x00400000;
   3054 	if (flags & PR_ASYNC)
   3055 		newflags |= 0x00800000;
   3056 	if (flags & PR_MSACCT)
   3057 		newflags |= 0x01000000;
   3058 	if (flags & PR_BPTADJ)
   3059 		newflags |= 0x02000000;
   3060 	if (flags & PR_PCOMPAT)
   3061 		newflags |= 0x04000000;
   3062 	return (newflags);
   3063 }
   3064 
   3065 /*
   3066  * Apply PIOCRUN options specific to the ioctl() interface.
   3067  */
   3068 static void
   3069 prsetrun(kthread_t *t, prrun_t *prp)
   3070 {
   3071 	proc_t *p = ttoproc(t);
   3072 	klwp_t *lwp = ttolwp(t);
   3073 	long flags = prp->pr_flags;
   3074 	user_t *up = PTOU(p);
   3075 
   3076 	ASSERT(MUTEX_HELD(&p->p_lock));
   3077 
   3078 	if (flags & PRSHOLD) {
   3079 		schedctl_finish_sigblock(t);
   3080 		sigutok(&prp->pr_sighold, &t->t_hold);
   3081 		t->t_sig_check = 1;	/* so ISSIG will be done */
   3082 	}
   3083 	if (flags & PRSTRACE) {
   3084 		prdelset(&prp->pr_trace, SIGKILL);
   3085 		prassignset(&p->p_sigmask, &prp->pr_trace);
   3086 		if (!sigisempty(&p->p_sigmask))
   3087 			p->p_proc_flag |= P_PR_TRACE;
   3088 		else if (prisempty(&p->p_fltmask)) {
   3089 			if (up->u_systrap == 0)
   3090 				p->p_proc_flag &= ~P_PR_TRACE;
   3091 		}
   3092 	}
   3093 	if (flags & PRSFAULT) {
   3094 		prassignset(&p->p_fltmask, &prp->pr_fault);
   3095 		if (!prisempty(&p->p_fltmask))
   3096 			p->p_proc_flag |= P_PR_TRACE;
   3097 		else if (sigisempty(&p->p_sigmask)) {
   3098 			if (up->u_systrap == 0)
   3099 				p->p_proc_flag &= ~P_PR_TRACE;
   3100 		}
   3101 	}
   3102 	/*
   3103 	 * prsvaddr() must be called before prstep() because
   3104 	 * stepping can depend on the current value of the PC.
   3105 	 * We drop p_lock while touching the lwp's registers (on stack).
   3106 	 */
   3107 	if (flags & PRSVADDR) {
   3108 		mutex_exit(&p->p_lock);
   3109 		prsvaddr(lwp, prp->pr_vaddr);
   3110 		mutex_enter(&p->p_lock);
   3111 	}
   3112 }
   3113 
   3114 /*
   3115  * Common code for PIOCOPENM
   3116  * Returns with the process unlocked.
   3117  */
   3118 static int
   3119 propenm(prnode_t *pnp, caddr_t cmaddr, caddr_t va, int *rvalp, cred_t *cr)
   3120 {
   3121 	proc_t *p = pnp->pr_common->prc_proc;
   3122 	struct as *as = p->p_as;
   3123 	int error = 0;
   3124 	struct seg *seg;
   3125 	struct vnode *xvp;
   3126 	int n;
   3127 
   3128 	/*
   3129 	 * By fiat, a system process has no address space.
   3130 	 */
   3131 	if ((p->p_flag & SSYS) || as == &kas) {
   3132 		error = EINVAL;
   3133 	} else if (cmaddr) {
   3134 		/*
   3135 		 * We drop p_lock before grabbing the address
   3136 		 * space lock in order to avoid a deadlock with
   3137 		 * the clock thread.  The process will not
   3138 		 * disappear and its address space will not
   3139 		 * change because it is marked P_PR_LOCK.
   3140 		 */
   3141 		mutex_exit(&p->p_lock);
   3142 		AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
   3143 		seg = as_segat(as, va);
   3144 		if (seg != NULL &&
   3145 		    seg->s_ops == &segvn_ops &&
   3146 		    SEGOP_GETVP(seg, va, &xvp) == 0 &&
   3147 		    xvp != NULL &&
   3148 		    xvp->v_type == VREG) {
   3149 			VN_HOLD(xvp);
   3150 		} else {
   3151 			error = EINVAL;
   3152 		}
   3153 		AS_LOCK_EXIT(as, &as->a_lock);
   3154 		mutex_enter(&p->p_lock);
   3155 	} else if ((xvp = p->p_exec) == NULL) {
   3156 		error = EINVAL;
   3157 	} else {
   3158 		VN_HOLD(xvp);
   3159 	}
   3160 
   3161 	prunlock(pnp);
   3162 
   3163 	if (error == 0) {
   3164 		if ((error = VOP_ACCESS(xvp, VREAD, 0, cr, NULL)) == 0)
   3165 			error = fassign(&xvp, FREAD, &n);
   3166 		if (error) {
   3167 			VN_RELE(xvp);
   3168 		} else {
   3169 			*rvalp = n;
   3170 		}
   3171 	}
   3172 
   3173 	return (error);
   3174 }
   3175 
   3176 /*
   3177  * Return old version of process/lwp status.
   3178  * The u-block is mapped in by this routine and unmapped at the end.
   3179  */
   3180 void
   3181 oprgetstatus(kthread_t *t, prstatus_t *sp, zone_t *zp)
   3182 {
   3183 	proc_t *p = ttoproc(t);
   3184 	klwp_t *lwp = ttolwp(t);
   3185 	int flags;
   3186 	user_t *up;
   3187 	ulong_t instr;
   3188 
   3189 	ASSERT(MUTEX_HELD(&p->p_lock));
   3190 
   3191 	up = PTOU(p);
   3192 	bzero(sp, sizeof (*sp));
   3193 	flags = 0;
   3194 	if (t->t_state == TS_STOPPED) {
   3195 		flags |= PR_STOPPED;
   3196 		if ((t->t_schedflag & TS_PSTART) == 0)
   3197 			flags |= PR_ISTOP;
   3198 	} else if (VSTOPPED(t)) {
   3199 		flags |= PR_STOPPED|PR_ISTOP;
   3200 	}
   3201 	if (!(flags & PR_ISTOP) && (t->t_proc_flag & TP_PRSTOP))
   3202 		flags |= PR_DSTOP;
   3203 	if (lwp->lwp_asleep)
   3204 		flags |= PR_ASLEEP;
   3205 	if (p->p_proc_flag & P_PR_FORK)
   3206 		flags |= PR_FORK;
   3207 	if (p->p_proc_flag & P_PR_RUNLCL)
   3208 		flags |= PR_RLC;
   3209 	if (p->p_proc_flag & P_PR_KILLCL)
   3210 		flags |= PR_KLC;
   3211 	if (p->p_proc_flag & P_PR_ASYNC)
   3212 		flags |= PR_ASYNC;
   3213 	if (p->p_proc_flag & P_PR_BPTADJ)
   3214 		flags |= PR_BPTADJ;
   3215 	if (p->p_proc_flag & P_PR_PTRACE)
   3216 		flags |= PR_PCOMPAT;
   3217 	if (t->t_proc_flag & TP_MSACCT)
   3218 		flags |= PR_MSACCT;
   3219 	sp->pr_flags = flags;
   3220 	if (VSTOPPED(t)) {
   3221 		sp->pr_why   = PR_REQUESTED;
   3222 		sp->pr_what  = 0;
   3223 	} else {
   3224 		sp->pr_why   = t->t_whystop;
   3225 		sp->pr_what  = t->t_whatstop;
   3226 	}
   3227 
   3228 	if (t->t_whystop == PR_FAULTED)
   3229 		bcopy(&lwp->lwp_siginfo,
   3230 		    &sp->pr_info, sizeof (k_siginfo_t));
   3231 	else if (lwp->lwp_curinfo)
   3232 		bcopy(&lwp->lwp_curinfo->sq_info,
   3233 		    &sp->pr_info, sizeof (k_siginfo_t));
   3234 
   3235 	if (SI_FROMUSER(&lwp->lwp_siginfo) && zp->zone_id != GLOBAL_ZONEID &&
   3236 	    sp->pr_info.si_zoneid != zp->zone_id) {
   3237 		sp->pr_info.si_pid = zp->zone_zsched->p_pid;
   3238 		sp->pr_info.si_uid = 0;
   3239 		sp->pr_info.si_ctid = -1;
   3240 		sp->pr_info.si_zoneid = zp->zone_id;
   3241 	}
   3242 
   3243 	sp->pr_cursig  = lwp->lwp_cursig;
   3244 	prassignset(&sp->pr_sigpend, &p->p_sig);
   3245 	prassignset(&sp->pr_lwppend, &t->t_sig);
   3246 	schedctl_finish_sigblock(t);
   3247 	prassignset(&sp->pr_sighold, &t->t_hold);
   3248 	sp->pr_altstack = lwp->lwp_sigaltstack;
   3249 	prgetaction(p, up, lwp->lwp_cursig, &sp->pr_action);
   3250 	sp->pr_pid   = p->p_pid;
   3251 	if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
   3252 	    (p->p_flag & SZONETOP)) {
   3253 		ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
   3254 		/*
   3255 		 * Inside local zones, fake zsched's pid as parent pids for
   3256 		 * processes which reference processes outside of the zone.
   3257 		 */
   3258 		sp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
   3259 	} else {
   3260 		sp->pr_ppid = p->p_ppid;
   3261 	}
   3262 	sp->pr_pgrp  = p->p_pgrp;
   3263 	sp->pr_sid   = p->p_sessp->s_sid;
   3264 	hrt2ts(mstate_aggr_state(p, LMS_USER), &sp->pr_utime);
   3265 	hrt2ts(mstate_aggr_state(p, LMS_SYSTEM), &sp->pr_stime);
   3266 	TICK_TO_TIMESTRUC(p->p_cutime, &sp->pr_cutime);
   3267 	TICK_TO_TIMESTRUC(p->p_cstime, &sp->pr_cstime);
   3268 	(void) strncpy(sp->pr_clname, sclass[t->t_cid].cl_name,
   3269 	    sizeof (sp->pr_clname) - 1);
   3270 	sp->pr_who = t->t_tid;
   3271 	sp->pr_nlwp = p->p_lwpcnt;
   3272 	sp->pr_brkbase = p->p_brkbase;
   3273 	sp->pr_brksize = p->p_brksize;
   3274 	sp->pr_stkbase = prgetstackbase(p);
   3275 	sp->pr_stksize = p->p_stksize;
   3276 	sp->pr_oldcontext = (struct ucontext *)lwp->lwp_oldcontext;
   3277 	sp->pr_processor = t->t_cpu->cpu_id;
   3278 	sp->pr_bind = t->t_bind_cpu;
   3279 
   3280 	/*
   3281 	 * Fetch the current instruction, if not a system process.
   3282 	 * We don't attempt this unless the lwp is stopped.
   3283 	 */
   3284 	if ((p->p_flag & SSYS) || p->p_as == &kas)
   3285 		sp->pr_flags |= (PR_ISSYS|PR_PCINVAL);
   3286 	else if (!(flags & PR_STOPPED))
   3287 		sp->pr_flags |= PR_PCINVAL;
   3288 	else if (!prfetchinstr(lwp, &instr))
   3289 		sp->pr_flags |= PR_PCINVAL;
   3290 	else
   3291 		sp->pr_instr = instr;
   3292 
   3293 	/*
   3294 	 * Drop p_lock while touching the lwp's stack.
   3295 	 */
   3296 	mutex_exit(&p->p_lock);
   3297 	if (prisstep(lwp))
   3298 		sp->pr_flags |= PR_STEP;
   3299 	if ((flags & (PR_STOPPED|PR_ASLEEP)) && t->t_sysnum) {
   3300 		int i;
   3301 		auxv_t *auxp;
   3302 
   3303 		sp->pr_syscall = get_syscall_args(lwp,
   3304 		    (long *)sp->pr_sysarg, &i);
   3305 		sp->pr_nsysarg = (short)i;
   3306 		if (t->t_whystop == PR_SYSEXIT &&
   3307 		    (t->t_sysnum == SYS_exec || t->t_sysnum == SYS_execve)) {
   3308 			sp->pr_sysarg[0] = 0;
   3309 			sp->pr_sysarg[1] = (uintptr_t)up->u_argv;
   3310 			sp->pr_sysarg[2] = (uintptr_t)up->u_envp;
   3311 			for (i = 0, auxp = up->u_auxv;
   3312 			    i < sizeof (up->u_auxv) / sizeof (up->u_auxv[0]);
   3313 			    i++, auxp++) {
   3314 				if (auxp->a_type == AT_SUN_EXECNAME) {
   3315 					sp->pr_sysarg[0] =
   3316 					    (uintptr_t)auxp->a_un.a_ptr;
   3317 					break;
   3318 				}
   3319 			}
   3320 		}
   3321 	}
   3322 	if ((flags & PR_STOPPED) || t == curthread)
   3323 		prgetprregs(lwp, sp->pr_reg);
   3324 	mutex_enter(&p->p_lock);
   3325 }
   3326 
   3327 /*
   3328  * Return old version of information used by ps(1).
   3329  */
   3330 void
   3331 oprgetpsinfo(proc_t *p, prpsinfo_t *psp, kthread_t *tp)
   3332 {
   3333 	kthread_t *t;
   3334 	char c, state;
   3335 	user_t *up;
   3336 	dev_t d;
   3337 	uint64_t pct;
   3338 	int retval, niceval;
   3339 	cred_t *cred;
   3340 	struct as *as;
   3341 	hrtime_t hrutime, hrstime, cur_time;
   3342 
   3343 	ASSERT(MUTEX_HELD(&p->p_lock));
   3344 
   3345 	bzero(psp, sizeof (*psp));
   3346 
   3347 	if ((t = tp) == NULL)
   3348 		t = prchoose(p);	/* returns locked thread */
   3349 	else
   3350 		thread_lock(t);
   3351 
   3352 	/* kludge: map thread state enum into process state enum */
   3353 
   3354 	if (t == NULL) {
   3355 		state = TS_ZOMB;
   3356 	} else {
   3357 		state = VSTOPPED(t) ? TS_STOPPED : t->t_state;
   3358 		thread_unlock(t);
   3359 	}
   3360 
   3361 	switch (state) {
   3362 	case TS_SLEEP:		state = SSLEEP;		break;
   3363 	case TS_RUN:		state = SRUN;		break;
   3364 	case TS_ONPROC:		state = SONPROC;	break;
   3365 	case TS_ZOMB:		state = SZOMB;		break;
   3366 	case TS_STOPPED:	state = SSTOP;		break;
   3367 	default:		state = 0;		break;
   3368 	}
   3369 	switch (state) {
   3370 	case SSLEEP:	c = 'S';	break;
   3371 	case SRUN:	c = 'R';	break;
   3372 	case SZOMB:	c = 'Z';	break;
   3373 	case SSTOP:	c = 'T';	break;
   3374 	case SIDL:	c = 'I';	break;
   3375 	case SONPROC:	c = 'O';	break;
   3376 #ifdef SXBRK
   3377 	case SXBRK:	c = 'X';	break;
   3378 #endif
   3379 	default:	c = '?';	break;
   3380 	}
   3381 	psp->pr_state = state;
   3382 	psp->pr_sname = c;
   3383 	psp->pr_zomb = (state == SZOMB);
   3384 	/*
   3385 	 * only export SSYS and SMSACCT; everything else is off-limits to
   3386 	 * userland apps.
   3387 	 */
   3388 	psp->pr_flag = p->p_flag & (SSYS | SMSACCT);
   3389 
   3390 	mutex_enter(&p->p_crlock);
   3391 	cred = p->p_cred;
   3392 	psp->pr_uid = crgetruid(cred);
   3393 	psp->pr_gid = crgetrgid(cred);
   3394 	psp->pr_euid = crgetuid(cred);
   3395 	psp->pr_egid = crgetgid(cred);
   3396 	mutex_exit(&p->p_crlock);
   3397 
   3398 	psp->pr_pid = p->p_pid;
   3399 	if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
   3400 	    (p->p_flag & SZONETOP)) {
   3401 		ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
   3402 		/*
   3403 		 * Inside local zones, fake zsched's pid as parent pids for
   3404 		 * processes which reference processes outside of the zone.
   3405 		 */
   3406 		psp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
   3407 	} else {
   3408 		psp->pr_ppid = p->p_ppid;
   3409 	}
   3410 	psp->pr_pgrp = p->p_pgrp;
   3411 	psp->pr_sid = p->p_sessp->s_sid;
   3412 	psp->pr_addr = prgetpsaddr(p);
   3413 	hrutime = mstate_aggr_state(p, LMS_USER);
   3414 	hrstime = mstate_aggr_state(p, LMS_SYSTEM);
   3415 	hrt2ts(hrutime + hrstime, &psp->pr_time);
   3416 	TICK_TO_TIMESTRUC(p->p_cutime + p->p_cstime, &psp->pr_ctime);
   3417 	switch (p->p_model) {
   3418 	case DATAMODEL_ILP32:
   3419 		psp->pr_dmodel = PR_MODEL_ILP32;
   3420 		break;
   3421 	case DATAMODEL_LP64:
   3422 		psp->pr_dmodel = PR_MODEL_LP64;
   3423 		break;
   3424 	}
   3425 	if (state == SZOMB || t == NULL) {
   3426 		int wcode = p->p_wcode;		/* must be atomic read */
   3427 
   3428 		if (wcode)
   3429 			psp->pr_wstat = wstat(wcode, p->p_wdata);
   3430 		psp->pr_lttydev = PRNODEV;
   3431 		psp->pr_ottydev = (o_dev_t)PRNODEV;
   3432 		psp->pr_size = 0;
   3433 		psp->pr_rssize = 0;
   3434 		psp->pr_pctmem = 0;
   3435 	} else {
   3436 		up = PTOU(p);
   3437 		psp->pr_wchan = t->t_wchan;
   3438 		psp->pr_pri = t->t_pri;
   3439 		(void) strncpy(psp->pr_clname, sclass[t->t_cid].cl_name,
   3440 		    sizeof (psp->pr_clname) - 1);
   3441 		retval = CL_DONICE(t, NULL, 0, &niceval);
   3442 		if (retval == 0) {
   3443 			psp->pr_oldpri = v.v_maxsyspri - psp->pr_pri;
   3444 			psp->pr_nice = niceval + NZERO;
   3445 		} else {
   3446 			psp->pr_oldpri = 0;
   3447 			psp->pr_nice = 0;
   3448 		}
   3449 		d = cttydev(p);
   3450 #ifdef sun
   3451 		{
   3452 			extern dev_t rwsconsdev, rconsdev, uconsdev;
   3453 			/*
   3454 			 * If the controlling terminal is the real
   3455 			 * or workstation console device, map to what the
   3456 			 * user thinks is the console device. Handle case when
   3457 			 * rwsconsdev or rconsdev is set to NODEV for Starfire.
   3458 			 */
   3459 			if ((d == rwsconsdev || d == rconsdev) && d != NODEV)
   3460 				d = uconsdev;
   3461 		}
   3462 #endif
   3463 		psp->pr_lttydev = (d == NODEV) ? PRNODEV : d;
   3464 		psp->pr_ottydev = cmpdev(d);
   3465 		psp->pr_start = up->u_start;
   3466 		bcopy(up->u_comm, psp->pr_fname,
   3467 		    MIN(sizeof (up->u_comm), sizeof (psp->pr_fname)-1));
   3468 		bcopy(up->u_psargs, psp->pr_psargs,
   3469 		    MIN(PRARGSZ-1, PSARGSZ));
   3470 		psp->pr_syscall = t->t_sysnum;
   3471 		psp->pr_argc = up->u_argc;
   3472 		psp->pr_argv = (char **)up->u_argv;
   3473 		psp->pr_envp = (char **)up->u_envp;
   3474 
   3475 		/* compute %cpu for the lwp or process */
   3476 		pct = 0;
   3477 		if ((t = tp) == NULL)
   3478 			t = p->p_tlist;
   3479 		cur_time = gethrtime_unscaled();
   3480 		do {
   3481 			pct += cpu_update_pct(t, cur_time);
   3482 			if (tp != NULL)		/* just do the one lwp */
   3483 				break;
   3484 		} while ((t = t->t_forw) != p->p_tlist);
   3485 
   3486 		psp->pr_pctcpu = prgetpctcpu(pct);
   3487 		psp->pr_cpu = (psp->pr_pctcpu*100 + 0x6000) >> 15; /* [0..99] */
   3488 		if (psp->pr_cpu > 99)
   3489 			psp->pr_cpu = 99;
   3490 
   3491 		if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
   3492 			psp->pr_size = 0;
   3493 			psp->pr_rssize = 0;
   3494 			psp->pr_pctmem = 0;
   3495 		} else {
   3496 			mutex_exit(&p->p_lock);
   3497 			AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
   3498 			psp->pr_size = btopr(as->a_resvsize);
   3499 			psp->pr_rssize = rm_asrss(as);
   3500 			psp->pr_pctmem = rm_pctmemory(as);
   3501 			AS_LOCK_EXIT(as, &as->a_lock);
   3502 			mutex_enter(&p->p_lock);
   3503 		}
   3504 	}
   3505 	psp->pr_bysize = ptob(psp->pr_size);
   3506 	psp->pr_byrssize = ptob(psp->pr_rssize);
   3507 }
   3508 
   3509 /*
   3510  * Return an array of structures with memory map information.
   3511  * We allocate here; the caller must deallocate.
   3512  * The caller is also responsible to append the zero-filled entry
   3513  * that terminates the PIOCMAP output buffer.
   3514  */
   3515 static int
   3516 oprgetmap(proc_t *p, list_t *iolhead)
   3517 {
   3518 	struct as *as = p->p_as;
   3519 	prmap_t *mp;
   3520 	struct seg *seg;
   3521 	struct seg *brkseg, *stkseg;
   3522 	uint_t prot;
   3523 
   3524 	ASSERT(as != &kas && AS_WRITE_HELD(as, &as->a_lock));
   3525 
   3526 	/*
   3527 	 * Request an initial buffer size that doesn't waste memory
   3528 	 * if the address space has only a small number of segments.
   3529 	 */
   3530 	pr_iol_initlist(iolhead, sizeof (*mp), avl_numnodes(&as->a_segtree));
   3531 
   3532 	if ((seg = AS_SEGFIRST(as)) == NULL)
   3533 		return (0);
   3534 
   3535 	brkseg = break_seg(p);
   3536 	stkseg = as_segat(as, prgetstackbase(p));
   3537 
   3538 	do {
   3539 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
   3540 		caddr_t saddr, naddr;
   3541 		void *tmp = NULL;
   3542 
   3543 		for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
   3544 			prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
   3545 			if (saddr == naddr)
   3546 				continue;
   3547 
   3548 			mp = pr_iol_newbuf(iolhead, sizeof (*mp));
   3549 
   3550 			mp->pr_vaddr = saddr;
   3551 			mp->pr_size = naddr - saddr;
   3552 			mp->pr_off = SEGOP_GETOFFSET(seg, saddr);
   3553 			mp->pr_mflags = 0;
   3554 			if (prot & PROT_READ)
   3555 				mp->pr_mflags |= MA_READ;
   3556 			if (prot & PROT_WRITE)
   3557 				mp->pr_mflags |= MA_WRITE;
   3558 			if (prot & PROT_EXEC)
   3559 				mp->pr_mflags |= MA_EXEC;
   3560 			if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
   3561 				mp->pr_mflags |= MA_SHARED;
   3562 			if (seg == brkseg)
   3563 				mp->pr_mflags |= MA_BREAK;
   3564 			else if (seg == stkseg)
   3565 				mp->pr_mflags |= MA_STACK;
   3566 			mp->pr_pagesize = PAGESIZE;
   3567 		}
   3568 		ASSERT(tmp == NULL);
   3569 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
   3570 
   3571 	return (0);
   3572 }
   3573 
   3574 #ifdef _SYSCALL32_IMPL
   3575 static int
   3576 oprgetmap32(proc_t *p, list_t *iolhead)
   3577 {
   3578 	struct as *as = p->p_as;
   3579 	ioc_prmap32_t *mp;
   3580 	struct seg *seg;
   3581 	struct seg *brkseg, *stkseg;
   3582 	uint_t prot;
   3583 
   3584 	ASSERT(as != &kas && AS_WRITE_HELD(as, &as->a_lock));
   3585 
   3586 	/*
   3587 	 * Request an initial buffer size that doesn't waste memory
   3588 	 * if the address space has only a small number of segments.
   3589 	 */
   3590 	pr_iol_initlist(iolhead, sizeof (*mp), avl_numnodes(&as->a_segtree));
   3591 
   3592 	if ((seg = AS_SEGFIRST(as)) == NULL)
   3593 		return (0);
   3594 
   3595 	brkseg = break_seg(p);
   3596 	stkseg = as_segat(as, prgetstackbase(p));
   3597 
   3598 	do {
   3599 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
   3600 		caddr_t saddr, naddr;
   3601 		void *tmp = NULL;
   3602 
   3603 		for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
   3604 			prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
   3605 			if (saddr == naddr)
   3606 				continue;
   3607 
   3608 			mp = pr_iol_newbuf(iolhead, sizeof (*mp));
   3609 
   3610 			mp->pr_vaddr = (caddr32_t)(uintptr_t)saddr;
   3611 			mp->pr_size = (size32_t)(naddr - saddr);
   3612 			mp->pr_off = (off32_t)SEGOP_GETOFFSET(seg, saddr);
   3613 			mp->pr_mflags = 0;
   3614 			if (prot & PROT_READ)
   3615 				mp->pr_mflags |= MA_READ;
   3616 			if (prot & PROT_WRITE)
   3617 				mp->pr_mflags |= MA_WRITE;
   3618 			if (prot & PROT_EXEC)
   3619 				mp->pr_mflags |= MA_EXEC;
   3620 			if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
   3621 				mp->pr_mflags |= MA_SHARED;
   3622 			if (seg == brkseg)
   3623 				mp->pr_mflags |= MA_BREAK;
   3624 			else if (seg == stkseg)
   3625 				mp->pr_mflags |= MA_STACK;
   3626 			mp->pr_pagesize = PAGESIZE;
   3627 		}
   3628 		ASSERT(tmp == NULL);
   3629 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
   3630 
   3631 	return (0);
   3632 }
   3633 #endif	/* _SYSCALL32_IMPL */
   3634 
   3635 /*
   3636  * Return the size of the old /proc page data file.
   3637  */
   3638 size_t
   3639 oprpdsize(struct as *as)
   3640 {
   3641 	struct seg *seg;
   3642 	size_t size;
   3643 
   3644 	ASSERT(as != &kas && AS_WRITE_HELD(as, &as->a_lock));
   3645 
   3646 	if ((seg = AS_SEGFIRST(as)) == NULL)
   3647 		return (0);
   3648 
   3649 	size = sizeof (prpageheader_t);
   3650 	do {
   3651 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
   3652 		caddr_t saddr, naddr;
   3653 		void *tmp = NULL;
   3654 		size_t npage;
   3655 
   3656 		for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
   3657 			(void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
   3658 			if ((npage = (naddr - saddr) / PAGESIZE) != 0)
   3659 				size += sizeof (prasmap_t) + roundlong(npage);
   3660 		}
   3661 		ASSERT(tmp == NULL);
   3662 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
   3663 
   3664 	return (size);
   3665 }
   3666 
   3667 #ifdef _SYSCALL32_IMPL
   3668 size_t
   3669 oprpdsize32(struct as *as)
   3670 {
   3671 	struct seg *seg;
   3672 	size_t size;
   3673 
   3674 	ASSERT(as != &kas && AS_WRITE_HELD(as, &as->a_lock));
   3675 
   3676 	if ((seg = AS_SEGFIRST(as)) == NULL)
   3677 		return (0);
   3678 
   3679 	size = sizeof (ioc_prpageheader32_t);
   3680 	do {
   3681 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
   3682 		caddr_t saddr, naddr;
   3683 		void *tmp = NULL;
   3684 		size_t npage;
   3685 
   3686 		for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
   3687 			(void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
   3688 			if ((npage = (naddr - saddr) / PAGESIZE) != 0)
   3689 				size += sizeof (ioc_prmap32_t) + round4(npage);
   3690 		}
   3691 		ASSERT(tmp == NULL);
   3692 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
   3693 
   3694 	return (size);
   3695 }
   3696 #endif	/* _SYSCALL32_IMPL */
   3697 
   3698 /*
   3699  * Read old /proc page data information.
   3700  */
   3701 int
   3702 oprpdread(struct as *as, uint_t hatid, struct uio *uiop)
   3703 {
   3704 	caddr_t buf;
   3705 	size_t size;
   3706 	prpageheader_t *php;
   3707 	prasmap_t *pmp;
   3708 	struct seg *seg;
   3709 	int error;
   3710 
   3711 again:
   3712 	AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
   3713 
   3714 	if ((seg = AS_SEGFIRST(as)) == NULL) {
   3715 		AS_LOCK_EXIT(as, &as->a_lock);
   3716 		return (0);
   3717 	}
   3718 	size = oprpdsize(as);
   3719 	if (uiop->uio_resid < size) {
   3720 		AS_LOCK_EXIT(as, &as->a_lock);
   3721 		return (E2BIG);
   3722 	}
   3723 
   3724 	buf = kmem_zalloc(size, KM_SLEEP);
   3725 	php = (prpageheader_t *)buf;
   3726 	pmp = (prasmap_t *)(buf + sizeof (prpageheader_t));
   3727 
   3728 	hrt2ts(gethrtime(), &php->pr_tstamp);
   3729 	php->pr_nmap = 0;
   3730 	php->pr_npage = 0;
   3731 	do {
   3732 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
   3733 		caddr_t saddr, naddr;
   3734 		void *tmp = NULL;
   3735 
   3736 		for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
   3737 			size_t len;
   3738 			size_t npage;
   3739 			uint_t prot;
   3740 			uintptr_t next;
   3741 
   3742 			prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
   3743 			if ((len = naddr - saddr) == 0)
   3744 				continue;
   3745 			npage = len / PAGESIZE;
   3746 			next = (uintptr_t)(pmp + 1) + roundlong(npage);
   3747 			/*
   3748 			 * It's possible that the address space can change
   3749 			 * subtlely even though we're holding as->a_lock
   3750 			 * due to the nondeterminism of page_exists() in
   3751 			 * the presence of asychronously flushed pages or
   3752 			 * mapped files whose sizes are changing.
   3753 			 * page_exists() may be called indirectly from
   3754 			 * pr_getprot() by a SEGOP_INCORE() routine.
   3755 			 * If this happens we need to make sure we don't
   3756 			 * overrun the buffer whose size we computed based
   3757 			 * on the initial iteration through the segments.
   3758 			 * Once we've detected an overflow, we need to clean
   3759 			 * up the temporary memory allocated in pr_getprot()
   3760 			 * and retry. If there's a pending signal, we return
   3761 			 * EINTR so that this thread can be dislodged if
   3762 			 * a latent bug causes us to spin indefinitely.
   3763 			 */
   3764 			if (next > (uintptr_t)buf + size) {
   3765 				pr_getprot_done(&tmp);
   3766 				AS_LOCK_EXIT(as, &as->a_lock);
   3767 
   3768 				kmem_free(buf, size);
   3769 
   3770 				if (ISSIG(curthread, JUSTLOOKING))
   3771 					return (EINTR);
   3772 
   3773 				goto again;
   3774 			}
   3775 
   3776 			php->pr_nmap++;
   3777 			php->pr_npage += npage;
   3778 			pmp->pr_vaddr = saddr;
   3779 			pmp->pr_npage = npage;
   3780 			pmp->pr_off = SEGOP_GETOFFSET(seg, saddr);
   3781 			pmp->pr_mflags = 0;
   3782 			if (prot & PROT_READ)
   3783 				pmp->pr_mflags |= MA_READ;
   3784 			if (prot & PROT_WRITE)
   3785 				pmp->pr_mflags |= MA_WRITE;
   3786 			if (prot & PROT_EXEC)
   3787 				pmp->pr_mflags |= MA_EXEC;
   3788 			if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
   3789 				pmp->pr_mflags |= MA_SHARED;
   3790 			pmp->pr_pagesize = PAGESIZE;
   3791 			hat_getstat(as, saddr, len, hatid,
   3792 			    (char *)(pmp + 1), HAT_SYNC_ZERORM);
   3793 			pmp = (prasmap_t *)next;
   3794 		}
   3795 		ASSERT(tmp == NULL);
   3796 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
   3797 
   3798 	AS_LOCK_EXIT(as, &as->a_lock);
   3799 
   3800 	ASSERT((uintptr_t)pmp <= (uintptr_t)buf + size);
   3801 	error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
   3802 	kmem_free(buf, size);
   3803 
   3804 	return (error);
   3805 }
   3806 
   3807 #ifdef _SYSCALL32_IMPL
   3808 int
   3809 oprpdread32(struct as *as, uint_t hatid, struct uio *uiop)
   3810 {
   3811 	caddr_t buf;
   3812 	size_t size;
   3813 	ioc_prpageheader32_t *php;
   3814 	ioc_prasmap32_t *pmp;
   3815 	struct seg *seg;
   3816 	int error;
   3817 
   3818 again:
   3819 	AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
   3820 
   3821 	if ((seg = AS_SEGFIRST(as)) == NULL) {
   3822 		AS_LOCK_EXIT(as, &as->a_lock);
   3823 		return (0);
   3824 	}
   3825 	size = oprpdsize32(as);
   3826 	if (uiop->uio_resid < size) {
   3827 		AS_LOCK_EXIT(as, &as->a_lock);
   3828 		return (E2BIG);
   3829 	}
   3830 
   3831 	buf = kmem_zalloc(size, KM_SLEEP);
   3832 	php = (ioc_prpageheader32_t *)buf;
   3833 	pmp = (ioc_prasmap32_t *)(buf + sizeof (ioc_prpageheader32_t));
   3834 
   3835 	hrt2ts32(gethrtime(), &php->pr_tstamp);
   3836 	php->pr_nmap = 0;
   3837 	php->pr_npage = 0;
   3838 	do {
   3839 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
   3840 		caddr_t saddr, naddr;
   3841 		void *tmp = NULL;
   3842 
   3843 		for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
   3844 			size_t len;
   3845 			size_t npage;
   3846 			uint_t prot;
   3847 			uintptr_t next;
   3848 
   3849 			prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
   3850 			if ((len = naddr - saddr) == 0)
   3851 				continue;
   3852 			npage = len / PAGESIZE;
   3853 			next = (uintptr_t)(pmp + 1) + round4(npage);
   3854 			/*
   3855 			 * It's possible that the address space can change
   3856 			 * subtlely even though we're holding as->a_lock
   3857 			 * due to the nondeterminism of page_exists() in
   3858 			 * the presence of asychronously flushed pages or
   3859 			 * mapped files whose sizes are changing.
   3860 			 * page_exists() may be called indirectly from
   3861 			 * pr_getprot() by a SEGOP_INCORE() routine.
   3862 			 * If this happens we need to make sure we don't
   3863 			 * overrun the buffer whose size we computed based
   3864 			 * on the initial iteration through the segments.
   3865 			 * Once we've detected an overflow, we need to clean
   3866 			 * up the temporary memory allocated in pr_getprot()
   3867 			 * and retry. If there's a pending signal, we return
   3868 			 * EINTR so that this thread can be dislodged if
   3869 			 * a latent bug causes us to spin indefinitely.
   3870 			 */
   3871 			if (next > (uintptr_t)buf + size) {
   3872 				pr_getprot_done(&tmp);
   3873 				AS_LOCK_EXIT(as, &as->a_lock);
   3874 
   3875 				kmem_free(buf, size);
   3876 
   3877 				if (ISSIG(curthread, JUSTLOOKING))
   3878 					return (EINTR);
   3879 
   3880 				goto again;
   3881 			}
   3882 
   3883 			php->pr_nmap++;
   3884 			php->pr_npage += npage;
   3885 			pmp->pr_vaddr = (uint32_t)(uintptr_t)saddr;
   3886 			pmp->pr_npage = (uint32_t)npage;
   3887 			pmp->pr_off = (int32_t)SEGOP_GETOFFSET(seg, saddr);
   3888 			pmp->pr_mflags = 0;
   3889 			if (prot & PROT_READ)
   3890 				pmp->pr_mflags |= MA_READ;
   3891 			if (prot & PROT_WRITE)
   3892 				pmp->pr_mflags |= MA_WRITE;
   3893 			if (prot & PROT_EXEC)
   3894 				pmp->pr_mflags |= MA_EXEC;
   3895 			if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
   3896 				pmp->pr_mflags |= MA_SHARED;
   3897 			pmp->pr_pagesize = PAGESIZE;
   3898 			hat_getstat(as, saddr, len, hatid,
   3899 			    (char *)(pmp + 1), HAT_SYNC_ZERORM);
   3900 			pmp = (ioc_prasmap32_t *)next;
   3901 		}
   3902 		ASSERT(tmp == NULL);
   3903 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
   3904 
   3905 	AS_LOCK_EXIT(as, &as->a_lock);
   3906 
   3907 	ASSERT((uintptr_t)pmp == (uintptr_t)buf + size);
   3908 	error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
   3909 	kmem_free(buf, size);
   3910 
   3911 	return (error);
   3912 }
   3913 #endif	/* _SYSCALL32_IMPL */
   3914 
   3915 /*ARGSUSED*/
   3916 #ifdef _SYSCALL32_IMPL
   3917 int
   3918 prioctl(
   3919 	struct vnode *vp,
   3920 	int cmd,
   3921 	intptr_t arg,
   3922 	int flag,
   3923 	cred_t *cr,
   3924 	int *rvalp,
   3925 	caller_context_t *ct)
   3926 {
   3927 	switch (curproc->p_model) {
   3928 	case DATAMODEL_ILP32:
   3929 		return (prioctl32(vp, cmd, arg, flag, cr, rvalp, ct));
   3930 	case DATAMODEL_LP64:
   3931 		return (prioctl64(vp, cmd, arg, flag, cr, rvalp, ct));
   3932 	default:
   3933 		return (ENOSYS);
   3934 	}
   3935 }
   3936 #endif	/* _SYSCALL32_IMPL */
   3937