17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
5870619efrankho * Common Development and Distribution License (the "License").
6870619efrankho * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
21eb9dbf0Roger A. Faulkner
227c478bdstevel@tonic-gate/*
238fd04b8Roger A. Faulkner * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
247c478bdstevel@tonic-gate * Use is subject to license terms.
25284ce98Patrick Mooney * Copyright 2017 Joyent, Inc.
267c478bdstevel@tonic-gate */
277c478bdstevel@tonic-gate
287c478bdstevel@tonic-gate/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
29e14d4b2Toomas Soome/*	  All rights reserved.	*/
307c478bdstevel@tonic-gate
317c478bdstevel@tonic-gate#include <sys/types.h>
327c478bdstevel@tonic-gate#include <sys/param.h>
337c478bdstevel@tonic-gate#include <sys/vmparam.h>
347c478bdstevel@tonic-gate#include <sys/var.h>
357c478bdstevel@tonic-gate#include <sys/cmn_err.h>
367c478bdstevel@tonic-gate#include <sys/cred.h>
377c478bdstevel@tonic-gate#include <sys/debug.h>
387c478bdstevel@tonic-gate#include <sys/errno.h>
397c478bdstevel@tonic-gate#include <sys/file.h>
407c478bdstevel@tonic-gate#include <sys/inline.h>
417c478bdstevel@tonic-gate#include <sys/kmem.h>
427c478bdstevel@tonic-gate#include <sys/proc.h>
43eb9dbf0Roger A. Faulkner#include <sys/brand.h>
447c478bdstevel@tonic-gate#include <sys/sysmacros.h>
457c478bdstevel@tonic-gate#include <sys/systm.h>
467c478bdstevel@tonic-gate#include <sys/vfs.h>
477c478bdstevel@tonic-gate#include <sys/vnode.h>
487c478bdstevel@tonic-gate#include <sys/cpuvar.h>
497c478bdstevel@tonic-gate#include <sys/session.h>
507c478bdstevel@tonic-gate#include <sys/signal.h>
517c478bdstevel@tonic-gate#include <sys/auxv.h>
527c478bdstevel@tonic-gate#include <sys/user.h>
537c478bdstevel@tonic-gate#include <sys/disp.h>
547c478bdstevel@tonic-gate#include <sys/class.h>
557c478bdstevel@tonic-gate#include <sys/ts.h>
567c478bdstevel@tonic-gate#include <sys/mman.h>
577c478bdstevel@tonic-gate#include <sys/fault.h>
587c478bdstevel@tonic-gate#include <sys/syscall.h>
597c478bdstevel@tonic-gate#include <sys/schedctl.h>
607c478bdstevel@tonic-gate#include <sys/pset.h>
617c478bdstevel@tonic-gate#include <sys/old_procfs.h>
627c478bdstevel@tonic-gate#include <sys/zone.h>
637c478bdstevel@tonic-gate#include <sys/time.h>
647c478bdstevel@tonic-gate#include <sys/msacct.h>
657c478bdstevel@tonic-gate#include <vm/rm.h>
667c478bdstevel@tonic-gate#include <vm/as.h>
677c478bdstevel@tonic-gate#include <vm/rm.h>
687c478bdstevel@tonic-gate#include <vm/seg.h>
697c478bdstevel@tonic-gate#include <vm/seg_vn.h>
707c478bdstevel@tonic-gate#include <sys/contract_impl.h>
717c478bdstevel@tonic-gate#include <sys/ctfs_impl.h>
727c478bdstevel@tonic-gate#include <sys/ctfs.h>
737c478bdstevel@tonic-gate
747c478bdstevel@tonic-gate#if defined(__i386) || defined(__i386_COMPAT)
757c478bdstevel@tonic-gate#include <sys/sysi86.h>
767c478bdstevel@tonic-gate#endif
777c478bdstevel@tonic-gate
787c478bdstevel@tonic-gate#include <fs/proc/prdata.h>
797c478bdstevel@tonic-gate
807c478bdstevel@tonic-gatestatic	int	isprwrioctl(int);
817c478bdstevel@tonic-gatestatic	ulong_t	prmaprunflags(long);
827c478bdstevel@tonic-gatestatic	long	prmapsetflags(long);
837c478bdstevel@tonic-gatestatic	void	prsetrun(kthread_t *, prrun_t *);
847c478bdstevel@tonic-gatestatic	int	propenm(prnode_t *, caddr_t, caddr_t, int *, cred_t *);
857c478bdstevel@tonic-gateextern	void	oprgetstatus(kthread_t *, prstatus_t *, zone_t *);
867c478bdstevel@tonic-gateextern	void	oprgetpsinfo(proc_t *, prpsinfo_t *, kthread_t *);
87870619efrankhostatic	int	oprgetmap(proc_t *, list_t *);
887c478bdstevel@tonic-gate
897c478bdstevel@tonic-gatestatic int
907c478bdstevel@tonic-gateprctioctl(prnode_t *pnp, int cmd, intptr_t arg, int flag, cred_t *cr)
917c478bdstevel@tonic-gate{
927c478bdstevel@tonic-gate	int error = 0;
93c5a9a4fAntonello Cruz	ct_kparam_t kparam;
94c5a9a4fAntonello Cruz	ct_param_t *param = &kparam.param;
957c478bdstevel@tonic-gate	ct_template_t *tmpl;
967c478bdstevel@tonic-gate
977c478bdstevel@tonic-gate	if (cmd != CT_TSET && cmd != CT_TGET)
987c478bdstevel@tonic-gate		return (EINVAL);
997c478bdstevel@tonic-gate
100c5a9a4fAntonello Cruz	error = ctparam_copyin((void *)arg, &kparam, flag, cmd);
101c5a9a4fAntonello Cruz	if (error != 0)
102c5a9a4fAntonello Cruz		return (error);
1037c478bdstevel@tonic-gate
104c5a9a4fAntonello Cruz	if ((error = prlock(pnp, ZNO)) != 0) {
105c5a9a4fAntonello Cruz		kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
1067c478bdstevel@tonic-gate		return (error);
107c5a9a4fAntonello Cruz	}
1087c478bdstevel@tonic-gate
1097c478bdstevel@tonic-gate	tmpl = pnp->pr_common->prc_thread->t_lwp->lwp_ct_active[pnp->pr_cttype];
1107c478bdstevel@tonic-gate	if (tmpl == NULL) {
1117c478bdstevel@tonic-gate		prunlock(pnp);
112c5a9a4fAntonello Cruz		kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
1137c478bdstevel@tonic-gate		return (ESTALE);
1147c478bdstevel@tonic-gate	}
1157c478bdstevel@tonic-gate
1167c478bdstevel@tonic-gate	if (cmd == CT_TSET)
117c5a9a4fAntonello Cruz		error = ctmpl_set(tmpl, &kparam, cr);
1187c478bdstevel@tonic-gate	else
119c5a9a4fAntonello Cruz		error = ctmpl_get(tmpl, &kparam);
1207c478bdstevel@tonic-gate
1217c478bdstevel@tonic-gate	prunlock(pnp);
1227c478bdstevel@tonic-gate
123c5a9a4fAntonello Cruz	if (cmd == CT_TGET && error == 0) {
124c5a9a4fAntonello Cruz		error = ctparam_copyout(&kparam, (void *)arg, flag);
125c5a9a4fAntonello Cruz	} else {
126c5a9a4fAntonello Cruz		kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
127c5a9a4fAntonello Cruz	}
1287c478bdstevel@tonic-gate
1297c478bdstevel@tonic-gate	return (error);
1307c478bdstevel@tonic-gate}
1317c478bdstevel@tonic-gate
1327c478bdstevel@tonic-gate
1337c478bdstevel@tonic-gate/*
1347c478bdstevel@tonic-gate * Control operations (lots).
1357c478bdstevel@tonic-gate */
136da6c28aamw/*ARGSUSED*/
1377c478bdstevel@tonic-gate#ifdef _SYSCALL32_IMPL
1387c478bdstevel@tonic-gatestatic int
139e14d4b2Toomas Soomeprioctl64(struct vnode *vp, int cmd, intptr_t arg, int flag, cred_t *cr,
140e14d4b2Toomas Soome    int *rvalp, caller_context_t *ct)
1417c478bdstevel@tonic-gate#else
1427c478bdstevel@tonic-gateint
143e14d4b2Toomas Soomeprioctl(struct vnode *vp, int cmd, intptr_t arg, int flag, cred_t *cr,
144e14d4b2Toomas Soome    int *rvalp, caller_context_t *ct)
1457c478bdstevel@tonic-gate#endif	/* _SYSCALL32_IMPL */
1467c478bdstevel@tonic-gate{
147eb9dbf0Roger A. Faulkner	int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
1487c478bdstevel@tonic-gate	caddr_t cmaddr = (caddr_t)arg;
1497c478bdstevel@tonic-gate	proc_t *p;
1507c478bdstevel@tonic-gate	user_t *up;
1517c478bdstevel@tonic-gate	kthread_t *t;
1527c478bdstevel@tonic-gate	klwp_t *lwp;
1537c478bdstevel@tonic-gate	prnode_t *pnp = VTOP(vp);
1547c478bdstevel@tonic-gate	prcommon_t *pcp;
1557c478bdstevel@tonic-gate	prnode_t *xpnp = NULL;
1567c478bdstevel@tonic-gate	int error;
1577c478bdstevel@tonic-gate	int zdisp;
1587c478bdstevel@tonic-gate	void *thing = NULL;
1597c478bdstevel@tonic-gate	size_t thingsize = 0;
1607c478bdstevel@tonic-gate
1617c478bdstevel@tonic-gate	/*
1627c478bdstevel@tonic-gate	 * For copyin()/copyout().
1637c478bdstevel@tonic-gate	 */
1647c478bdstevel@tonic-gate	union {
1657c478bdstevel@tonic-gate		caddr_t		va;
1667c478bdstevel@tonic-gate		int		signo;
1677c478bdstevel@tonic-gate		int		nice;
1687c478bdstevel@tonic-gate		uint_t		lwpid;
1697c478bdstevel@tonic-gate		long		flags;
1707c478bdstevel@tonic-gate		prstatus_t	prstat;
1717c478bdstevel@tonic-gate		prrun_t		prrun;
1727c478bdstevel@tonic-gate		sigset_t	smask;
1737c478bdstevel@tonic-gate		siginfo_t	info;
1747c478bdstevel@tonic-gate		sysset_t	prmask;
1757c478bdstevel@tonic-gate		prgregset_t	regs;
1767c478bdstevel@tonic-gate		prfpregset_t	fpregs;
1777c478bdstevel@tonic-gate		prpsinfo_t	prps;
1787c478bdstevel@tonic-gate		sigset_t	holdmask;
1797c478bdstevel@tonic-gate		fltset_t	fltmask;
1807c478bdstevel@tonic-gate		prcred_t	prcred;
1817c478bdstevel@tonic-gate		prhusage_t	prhusage;
1827c478bdstevel@tonic-gate		prmap_t		prmap;
1837c478bdstevel@tonic-gate		auxv_t		auxv[__KERN_NAUXV_IMPL];
1847c478bdstevel@tonic-gate	} un;
1857c478bdstevel@tonic-gate
1867c478bdstevel@tonic-gate	if (pnp->pr_type == PR_TMPL)
1877c478bdstevel@tonic-gate		return (prctioctl(pnp, cmd, arg, flag, cr));
1887c478bdstevel@tonic-gate
1897c478bdstevel@tonic-gate	/*
1907c478bdstevel@tonic-gate	 * Support for old /proc interface.
1917c478bdstevel@tonic-gate	 */
1927c478bdstevel@tonic-gate	if (pnp->pr_pidfile != NULL) {
1937c478bdstevel@tonic-gate		ASSERT(pnp->pr_type == PR_PIDDIR);
1947c478bdstevel@tonic-gate		vp = pnp->pr_pidfile;
1957c478bdstevel@tonic-gate		pnp = VTOP(vp);
1967c478bdstevel@tonic-gate		ASSERT(pnp->pr_type == PR_PIDFILE);
1977c478bdstevel@tonic-gate	}
1987c478bdstevel@tonic-gate
1997c478bdstevel@tonic-gate	if (pnp->pr_type != PR_PIDFILE && pnp->pr_type != PR_LWPIDFILE)
2007c478bdstevel@tonic-gate		return (ENOTTY);
2017c478bdstevel@tonic-gate
2027c478bdstevel@tonic-gate	/*
2037c478bdstevel@tonic-gate	 * Fail ioctls which are logically "write" requests unless
2047c478bdstevel@tonic-gate	 * the user has write permission.
2057c478bdstevel@tonic-gate	 */
2067c478bdstevel@tonic-gate	if ((flag & FWRITE) == 0 && isprwrioctl(cmd))
2077c478bdstevel@tonic-gate		return (EBADF);
2087c478bdstevel@tonic-gate
2097c478bdstevel@tonic-gate	/*
2107c478bdstevel@tonic-gate	 * Perform any necessary copyin() operations before
2117c478bdstevel@tonic-gate	 * locking the process.  Helps avoid deadlocks and
2127c478bdstevel@tonic-gate	 * improves performance.
2137c478bdstevel@tonic-gate	 *
2147c478bdstevel@tonic-gate	 * Also, detect invalid ioctl codes here to avoid
2157c478bdstevel@tonic-gate	 * locking a process unnnecessarily.
2167c478bdstevel@tonic-gate	 *
2177c478bdstevel@tonic-gate	 * Also, prepare to allocate space that will be needed below,
2187c478bdstevel@tonic-gate	 * case by case.
2197c478bdstevel@tonic-gate	 */
2207c478bdstevel@tonic-gate	error = 0;
2217c478bdstevel@tonic-gate	switch (cmd) {
2227c478bdstevel@tonic-gate	case PIOCGETPR:
2237c478bdstevel@tonic-gate		thingsize = sizeof (proc_t);
2247c478bdstevel@tonic-gate		break;
2257c478bdstevel@tonic-gate	case PIOCGETU:
2267c478bdstevel@tonic-gate		thingsize = sizeof (user_t);
2277c478bdstevel@tonic-gate		break;
2287c478bdstevel@tonic-gate	case PIOCSTOP:
2297c478bdstevel@tonic-gate	case PIOCWSTOP:
2307c478bdstevel@tonic-gate	case PIOCLWPIDS:
2317c478bdstevel@tonic-gate	case PIOCGTRACE:
2327c478bdstevel@tonic-gate	case PIOCGENTRY:
2337c478bdstevel@tonic-gate	case PIOCGEXIT:
2347c478bdstevel@tonic-gate	case PIOCSRLC:
2357c478bdstevel@tonic-gate	case PIOCRRLC:
2367c478bdstevel@tonic-gate	case PIOCSFORK:
2377c478bdstevel@tonic-gate	case PIOCRFORK:
2387c478bdstevel@tonic-gate	case PIOCGREG:
2397c478bdstevel@tonic-gate	case PIOCGFPREG:
2407c478bdstevel@tonic-gate	case PIOCSTATUS:
2417c478bdstevel@tonic-gate	case PIOCLSTATUS:
2427c478bdstevel@tonic-gate	case PIOCPSINFO:
2437c478bdstevel@tonic-gate	case PIOCMAXSIG:
2447c478bdstevel@tonic-gate	case PIOCGXREGSIZE:
2457c478bdstevel@tonic-gate		break;
2467c478bdstevel@tonic-gate	case PIOCSXREG:		/* set extra registers */
2477c478bdstevel@tonic-gate	case PIOCGXREG:		/* get extra registers */
2487c478bdstevel@tonic-gate#if defined(__sparc)
2497c478bdstevel@tonic-gate		thingsize = sizeof (prxregset_t);
2507c478bdstevel@tonic-gate#else
2517c478bdstevel@tonic-gate		thingsize = 0;
2527c478bdstevel@tonic-gate#endif
2537c478bdstevel@tonic-gate		break;
2547c478bdstevel@tonic-gate	case PIOCACTION:
255eb9dbf0Roger A. Faulkner		thingsize = (nsig-1) * sizeof (struct sigaction);
2567c478bdstevel@tonic-gate		break;
2577c478bdstevel@tonic-gate	case PIOCGHOLD:
2587c478bdstevel@tonic-gate	case PIOCNMAP:
2597c478bdstevel@tonic-gate	case PIOCMAP:
2607c478bdstevel@tonic-gate	case PIOCGFAULT:
2617c478bdstevel@tonic-gate	case PIOCCFAULT:
2627c478bdstevel@tonic-gate	case PIOCCRED:
2637c478bdstevel@tonic-gate	case PIOCGROUPS:
2647c478bdstevel@tonic-gate	case PIOCUSAGE:
2657c478bdstevel@tonic-gate	case PIOCLUSAGE:
2667c478bdstevel@tonic-gate		break;
2677c478bdstevel@tonic-gate	case PIOCOPENPD:
2687c478bdstevel@tonic-gate		/*
2697c478bdstevel@tonic-gate		 * We will need this below.
2707c478bdstevel@tonic-gate		 * Allocate it now, before locking the process.
2717c478bdstevel@tonic-gate		 */
2727c478bdstevel@tonic-gate		xpnp = prgetnode(vp, PR_OPAGEDATA);
2737c478bdstevel@tonic-gate		break;
2747c478bdstevel@tonic-gate	case PIOCNAUXV:
2757c478bdstevel@tonic-gate	case PIOCAUXV:
2767c478bdstevel@tonic-gate		break;
2777c478bdstevel@tonic-gate
2787c478bdstevel@tonic-gate#if defined(__i386) || defined(__amd64)
2797c478bdstevel@tonic-gate	case PIOCNLDT:
2807c478bdstevel@tonic-gate	case PIOCLDT:
2817c478bdstevel@tonic-gate		break;
2827c478bdstevel@tonic-gate#endif	/* __i386 || __amd64 */
2837c478bdstevel@tonic-gate
2847c478bdstevel@tonic-gate#if defined(__sparc)
2857c478bdstevel@tonic-gate	case PIOCGWIN:
2867c478bdstevel@tonic-gate		thingsize = sizeof (gwindows_t);
2877c478bdstevel@tonic-gate		break;
2887c478bdstevel@tonic-gate#endif	/* __sparc */
2897c478bdstevel@tonic-gate
2907c478bdstevel@tonic-gate	case PIOCOPENM:		/* open mapped object for reading */
2917c478bdstevel@tonic-gate		if (cmaddr == NULL)
2927c478bdstevel@tonic-gate			un.va = NULL;
2937c478bdstevel@tonic-gate		else if (copyin(cmaddr, &un.va, sizeof (un.va)))
2947c478bdstevel@tonic-gate			error = EFAULT;
2957c478bdstevel@tonic-gate		break;
2967c478bdstevel@tonic-gate
2977c478bdstevel@tonic-gate	case PIOCRUN:		/* make lwp or process runnable */
2987c478bdstevel@tonic-gate		if (cmaddr == NULL)
2997c478bdstevel@tonic-gate			un.prrun.pr_flags = 0;
3007c478bdstevel@tonic-gate		else if (copyin(cmaddr, &un.prrun, sizeof (un.prrun)))
3017c478bdstevel@tonic-gate			error = EFAULT;
3027c478bdstevel@tonic-gate		break;
3037c478bdstevel@tonic-gate
3047c478bdstevel@tonic-gate	case PIOCOPENLWP:	/* return /proc lwp file descriptor */
3057c478bdstevel@tonic-gate		if (copyin(cmaddr, &un.lwpid, sizeof (un.lwpid)))
3067c478bdstevel@tonic-gate			error = EFAULT;
3077c478bdstevel@tonic-gate		break;
3087c478bdstevel@tonic-gate
3097c478bdstevel@tonic-gate	case PIOCSTRACE:	/* set signal trace mask */
3107c478bdstevel@tonic-gate		if (copyin(cmaddr, &un.smask, sizeof (un.smask)))
3117c478bdstevel@tonic-gate			error = EFAULT;
3127c478bdstevel@tonic-gate		break;
3137c478bdstevel@tonic-gate
3147c478bdstevel@tonic-gate	case PIOCSSIG:		/* set current signal */
3157c478bdstevel@tonic-gate		if (cmaddr == NULL)
3167c478bdstevel@tonic-gate			un.info.si_signo = 0;
3177c478bdstevel@tonic-gate		else if (copyin(cmaddr, &un.info, sizeof (un.info)))
3187c478bdstevel@tonic-gate			error = EFAULT;
3197c478bdstevel@tonic-gate		break;
3207c478bdstevel@tonic-gate
3217c478bdstevel@tonic-gate	case PIOCKILL:		/* send signal */
3227c478bdstevel@tonic-gate	case PIOCUNKILL:	/* delete a signal */
3237c478bdstevel@tonic-gate		if (copyin(cmaddr, &un.signo, sizeof (un.signo)))
3247c478bdstevel@tonic-gate			error = EFAULT;
3257c478bdstevel@tonic-gate		break;
3267c478bdstevel@tonic-gate
3277c478bdstevel@tonic-gate	case PIOCNICE:		/* set nice priority */
3287c478bdstevel@tonic-gate		if (copyin(cmaddr, &un.nice, sizeof (un.nice)))
3297c478bdstevel@tonic-gate			error = EFAULT;
3307c478bdstevel@tonic-gate		break;
3317c478bdstevel@tonic-gate
3327c478bdstevel@tonic-gate	case PIOCSENTRY:	/* set syscall entry bit mask */
3337c478bdstevel@tonic-gate	case PIOCSEXIT:		/* set syscall exit bit mask */
3347c478bdstevel@tonic-gate		if (copyin(cmaddr, &un.prmask, sizeof (un.prmask)))
3357c478bdstevel@tonic-gate			error = EFAULT;
3367c478bdstevel@tonic-gate		break;
3377c478bdstevel@tonic-gate
3387c478bdstevel@tonic-gate	case PIOCSET:		/* set process flags */
3397c478bdstevel@tonic-gate	case PIOCRESET:		/* reset process flags */
3407c478bdstevel@tonic-gate		if (copyin(cmaddr, &un.flags, sizeof (un.flags)))
3417c478bdstevel@tonic-gate			error = EFAULT;
3427c478bdstevel@tonic-gate		break;
3437c478bdstevel@tonic-gate
3447c478bdstevel@tonic-gate	case PIOCSREG:		/* set general registers */
3457c478bdstevel@tonic-gate		if (copyin(cmaddr, un.regs, sizeof (un.regs)))
3467c478bdstevel@tonic-gate			error = EFAULT;
3477c478bdstevel@tonic-gate		break;
3487c478bdstevel@tonic-gate
3497c478bdstevel@tonic-gate	case PIOCSFPREG:	/* set floating-point registers */
3507c478bdstevel@tonic-gate		if (copyin(cmaddr, &un.fpregs, sizeof (un.fpregs)))
3517c478bdstevel@tonic-gate			error = EFAULT;
3527c478bdstevel@tonic-gate		break;
3537c478bdstevel@tonic-gate
3547c478bdstevel@tonic-gate	case PIOCSHOLD:		/* set signal-hold mask */
3557c478bdstevel@tonic-gate		if (copyin(cmaddr, &un.holdmask, sizeof (un.holdmask)))
3567c478bdstevel@tonic-gate			error = EFAULT;
3577c478bdstevel@tonic-gate		break;
3587c478bdstevel@tonic-gate
3597c478bdstevel@tonic-gate	case PIOCSFAULT:	/* set mask of traced faults */
3607c478bdstevel@tonic-gate		if (copyin(cmaddr, &un.fltmask, sizeof (un.fltmask)))
3617c478bdstevel@tonic-gate			error = EFAULT;
3627c478bdstevel@tonic-gate		break;
3637c478bdstevel@tonic-gate
3647c478bdstevel@tonic-gate	default:
3657c478bdstevel@tonic-gate		error = EINVAL;
3667c478bdstevel@tonic-gate		break;
3677c478bdstevel@tonic-gate	}
3687c478bdstevel@tonic-gate
3697c478bdstevel@tonic-gate	if (error)
3707c478bdstevel@tonic-gate		return (error);
3717c478bdstevel@tonic-gate
3727c478bdstevel@tonic-gatestartover:
3737c478bdstevel@tonic-gate	/*
3747c478bdstevel@tonic-gate	 * If we need kmem_alloc()d space then we allocate it now, before
3757c478bdstevel@tonic-gate	 * grabbing the process lock.  Using kmem_alloc(KM_SLEEP) while
3767c478bdstevel@tonic-gate	 * holding the process lock leads to deadlock with the clock thread.
3777c478bdstevel@tonic-gate	 * (The clock thread wakes up the pageout daemon to free up space.
3787c478bdstevel@tonic-gate	 * If the clock thread blocks behind us and we are sleeping waiting
3797c478bdstevel@tonic-gate	 * for space, then space may never become available.)
3807c478bdstevel@tonic-gate	 */
3817c478bdstevel@tonic-gate	if (thingsize) {
3827c478bdstevel@tonic-gate		ASSERT(thing == NULL);
3837c478bdstevel@tonic-gate		thing = kmem_alloc(thingsize, KM_SLEEP);
3847c478bdstevel@tonic-gate	}
3857c478bdstevel@tonic-gate
3867c478bdstevel@tonic-gate	switch (cmd) {
3877c478bdstevel@tonic-gate	case PIOCPSINFO:
3887c478bdstevel@tonic-gate	case PIOCGETPR:
3897c478bdstevel@tonic-gate	case PIOCUSAGE:
3907c478bdstevel@tonic-gate	case PIOCLUSAGE:
3917c478bdstevel@tonic-gate		zdisp = ZYES;
3927c478bdstevel@tonic-gate		break;
3937c478bdstevel@tonic-gate	case PIOCSXREG:		/* set extra registers */
3947c478bdstevel@tonic-gate		/*
3957c478bdstevel@tonic-gate		 * perform copyin before grabbing the process lock
3967c478bdstevel@tonic-gate		 */
3977c478bdstevel@tonic-gate		if (thing) {
3987c478bdstevel@tonic-gate			if (copyin(cmaddr, thing, thingsize)) {
3997c478bdstevel@tonic-gate				kmem_free(thing, thingsize);
4007c478bdstevel@tonic-gate				return (EFAULT);
4017c478bdstevel@tonic-gate			}
4027c478bdstevel@tonic-gate		}
4037c478bdstevel@tonic-gate		/* fall through... */
4047c478bdstevel@tonic-gate	default:
4057c478bdstevel@tonic-gate		zdisp = ZNO;
4067c478bdstevel@tonic-gate		break;
4077c478bdstevel@tonic-gate	}
4087c478bdstevel@tonic-gate
4097c478bdstevel@tonic-gate	if ((error = prlock(pnp, zdisp)) != 0) {
4107c478bdstevel@tonic-gate		if (thing != NULL)
4117c478bdstevel@tonic-gate			kmem_free(thing, thingsize);
4127c478bdstevel@tonic-gate		if (xpnp)
4137c478bdstevel@tonic-gate			prfreenode(xpnp);
4147c478bdstevel@tonic-gate		return (error);
4157c478bdstevel@tonic-gate	}
4167c478bdstevel@tonic-gate
4177c478bdstevel@tonic-gate	pcp = pnp->pr_common;
4187c478bdstevel@tonic-gate	p = pcp->prc_proc;
4197c478bdstevel@tonic-gate	ASSERT(p != NULL);
4207c478bdstevel@tonic-gate
4217c478bdstevel@tonic-gate	/*
4227c478bdstevel@tonic-gate	 * Choose a thread/lwp for the operation.
4237c478bdstevel@tonic-gate	 */
4247c478bdstevel@tonic-gate	if (zdisp == ZNO && cmd != PIOCSTOP && cmd != PIOCWSTOP) {
4257c478bdstevel@tonic-gate		if (pnp->pr_type == PR_LWPIDFILE && cmd != PIOCLSTATUS) {
4267c478bdstevel@tonic-gate			t = pcp->prc_thread;
4277c478bdstevel@tonic-gate			ASSERT(t != NULL);
4287c478bdstevel@tonic-gate		} else {
4297c478bdstevel@tonic-gate			t = prchoose(p);	/* returns locked thread */
4307c478bdstevel@tonic-gate			ASSERT(t != NULL);
4317c478bdstevel@tonic-gate			thread_unlock(t);
4327c478bdstevel@tonic-gate		}
4337c478bdstevel@tonic-gate		lwp = ttolwp(t);
4347c478bdstevel@tonic-gate	}
4357c478bdstevel@tonic-gate
4367c478bdstevel@tonic-gate	error = 0;
4377c478bdstevel@tonic-gate	switch (cmd) {
4387c478bdstevel@tonic-gate
4397c478bdstevel@tonic-gate	case PIOCGETPR:		/* read struct proc */
4407c478bdstevel@tonic-gate	{
4417c478bdstevel@tonic-gate		proc_t *prp = thing;
4427c478bdstevel@tonic-gate
4437c478bdstevel@tonic-gate		*prp = *p;
4447c478bdstevel@tonic-gate		prunlock(pnp);
4457c478bdstevel@tonic-gate		if (copyout(prp, cmaddr, sizeof (proc_t)))
4467c478bdstevel@tonic-gate			error = EFAULT;
4477c478bdstevel@tonic-gate		kmem_free(prp, sizeof (proc_t));
4487c478bdstevel@tonic-gate		thing = NULL;
4497c478bdstevel@tonic-gate		break;
4507c478bdstevel@tonic-gate	}
4517c478bdstevel@tonic-gate
4527c478bdstevel@tonic-gate	case PIOCGETU:		/* read u-area */
4537c478bdstevel@tonic-gate	{
4547c478bdstevel@tonic-gate		user_t *userp = thing;
4557c478bdstevel@tonic-gate
4567c478bdstevel@tonic-gate		up = PTOU(p);
4577c478bdstevel@tonic-gate		*userp = *up;
4587c478bdstevel@tonic-gate		prunlock(pnp);
4597c478bdstevel@tonic-gate		if (copyout(userp, cmaddr, sizeof (user_t)))
4607c478bdstevel@tonic-gate			error = EFAULT;
4617c478bdstevel@tonic-gate		kmem_free(userp, sizeof (user_t));
4627c478bdstevel@tonic-gate		thing = NULL;
4637c478bdstevel@tonic-gate		break;
4647c478bdstevel@tonic-gate	}
4657c478bdstevel@tonic-gate
4667c478bdstevel@tonic-gate	case PIOCOPENM:		/* open mapped object for reading */
4677c478bdstevel@tonic-gate		error = propenm(pnp, cmaddr, un.va, rvalp, cr);
4687c478bdstevel@tonic-gate		/* propenm() called prunlock(pnp) */
4697c478bdstevel@tonic-gate		break;
4707c478bdstevel@tonic-gate
4717c478bdstevel@tonic-gate	case PIOCSTOP:		/* stop process or lwp from running */
4727c478bdstevel@tonic-gate	case PIOCWSTOP:		/* wait for process or lwp to stop */
4737c478bdstevel@tonic-gate		/*
4747c478bdstevel@tonic-gate		 * Can't apply to a system process.
4757c478bdstevel@tonic-gate		 */
4767c478bdstevel@tonic-gate		if ((p->p_flag & SSYS) || p->p_as == &kas) {
4777c478bdstevel@tonic-gate			prunlock(pnp);
4787c478bdstevel@tonic-gate			error = EBUSY;
4797c478bdstevel@tonic-gate			break;
4807c478bdstevel@tonic-gate		}
4817c478bdstevel@tonic-gate
4827c478bdstevel@tonic-gate		if (cmd == PIOCSTOP)
4837c478bdstevel@tonic-gate			pr_stop(pnp);
4847c478bdstevel@tonic-gate
4857c478bdstevel@tonic-gate		/*
4867c478bdstevel@tonic-gate		 * If an lwp is waiting for itself or its process, don't wait.
4877c478bdstevel@tonic-gate		 * The stopped lwp would never see the fact that it is stopped.
4887c478bdstevel@tonic-gate		 */
4897c478bdstevel@tonic-gate		if ((pnp->pr_type == PR_LWPIDFILE)?
4907c478bdstevel@tonic-gate		    (pcp->prc_thread == curthread) : (p == curproc)) {
4917c478bdstevel@tonic-gate			if (cmd == PIOCWSTOP)
4927c478bdstevel@tonic-gate				error = EBUSY;
4937c478bdstevel@tonic-gate			prunlock(pnp);
4947c478bdstevel@tonic-gate			break;
4957c478bdstevel@tonic-gate		}
4967c478bdstevel@tonic-gate
4977c478bdstevel@tonic-gate		if ((error = pr_wait_stop(pnp, (time_t)0)) != 0)
4987c478bdstevel@tonic-gate			break;	/* pr_wait_stop() unlocked the process */
4997c478bdstevel@tonic-gate
5007c478bdstevel@tonic-gate		if (cmaddr == NULL)
5017c478bdstevel@tonic-gate			prunlock(pnp);
5027c478bdstevel@tonic-gate		else {
5037c478bdstevel@tonic-gate			/*
5047c478bdstevel@tonic-gate			 * Return process/lwp status information.
5057c478bdstevel@tonic-gate			 */
5067c478bdstevel@tonic-gate			t = pr_thread(pnp);	/* returns locked thread */
5077c478bdstevel@tonic-gate			thread_unlock(t);
508fa9e406ahrens			oprgetstatus(t, &un.prstat, VTOZONE(vp));
5097c478bdstevel@tonic-gate			prunlock(pnp);
5107c478bdstevel@tonic-gate			if (copyout(&un.prstat, cmaddr, sizeof (un.prstat)))
5117c478bdstevel@tonic-gate				error = EFAULT;
5127c478bdstevel@tonic-gate		}
5137c478bdstevel@tonic-gate		break;
5147c478bdstevel@tonic-gate
5157c478bdstevel@tonic-gate	case PIOCRUN:		/* make lwp or process runnable */
5167c478bdstevel@tonic-gate	{
5177c478bdstevel@tonic-gate		long flags = un.prrun.pr_flags;
5187c478bdstevel@tonic-gate
5197c478bdstevel@tonic-gate		/*
5207c478bdstevel@tonic-gate		 * Cannot set an lwp running is it is not stopped.
5217c478bdstevel@tonic-gate		 * Also, no lwp other than the /proc agent lwp can
5227c478bdstevel@tonic-gate		 * be set running so long as the /proc agent lwp exists.
5237c478bdstevel@tonic-gate		 */
5247c478bdstevel@tonic-gate		if ((!ISTOPPED(t) && !VSTOPPED(t) &&
5257c478bdstevel@tonic-gate		    !(t->t_proc_flag & TP_PRSTOP)) ||
5267c478bdstevel@tonic-gate		    (p->p_agenttp != NULL &&
5277c478bdstevel@tonic-gate		    (t != p->p_agenttp || pnp->pr_type != PR_LWPIDFILE))) {
5287c478bdstevel@tonic-gate			prunlock(pnp);
5297c478bdstevel@tonic-gate			error = EBUSY;
5307c478bdstevel@tonic-gate			break;
5317c478bdstevel@tonic-gate		}
5327c478bdstevel@tonic-gate
5337c478bdstevel@tonic-gate		if (flags & (PRSHOLD|PRSTRACE|PRSFAULT|PRSVADDR))
5347c478bdstevel@tonic-gate			prsetrun(t, &un.prrun);
5357c478bdstevel@tonic-gate
5367c478bdstevel@tonic-gate		error = pr_setrun(pnp, prmaprunflags(flags));
5377c478bdstevel@tonic-gate
5387c478bdstevel@tonic-gate		prunlock(pnp);
5397c478bdstevel@tonic-gate		break;
5407c478bdstevel@tonic-gate	}
5417c478bdstevel@tonic-gate
5427c478bdstevel@tonic-gate	case PIOCLWPIDS:	/* get array of lwp identifiers */
5437c478bdstevel@tonic-gate	{
5447c478bdstevel@tonic-gate		int nlwp;
5457c478bdstevel@tonic-gate		int Nlwp;
5467c478bdstevel@tonic-gate		id_t *idp;
5477c478bdstevel@tonic-gate		id_t *Bidp;
5487c478bdstevel@tonic-gate
5497c478bdstevel@tonic-gate		Nlwp = nlwp = p->p_lwpcnt;
5507c478bdstevel@tonic-gate
5517c478bdstevel@tonic-gate		if (thing && thingsize != (Nlwp+1) * sizeof (id_t)) {
5527c478bdstevel@tonic-gate			kmem_free(thing, thingsize);
5537c478bdstevel@tonic-gate			thing = NULL;
5547c478bdstevel@tonic-gate		}
5557c478bdstevel@tonic-gate		if (thing == NULL) {
5567c478bdstevel@tonic-gate			thingsize = (Nlwp+1) * sizeof (id_t);
5577c478bdstevel@tonic-gate			thing = kmem_alloc(thingsize, KM_NOSLEEP);
5587c478bdstevel@tonic-gate		}
5597c478bdstevel@tonic-gate		if (thing == NULL) {
5607c478bdstevel@tonic-gate			prunlock(pnp);
5617c478bdstevel@tonic-gate			goto startover;
5627c478bdstevel@tonic-gate		}
5637c478bdstevel@tonic-gate
5647c478bdstevel@tonic-gate		idp = thing;
5657c478bdstevel@tonic-gate		thing = NULL;
5667c478bdstevel@tonic-gate		Bidp = idp;
5677c478bdstevel@tonic-gate		if ((t = p->p_tlist) != NULL) {
5687c478bdstevel@tonic-gate			do {
5697c478bdstevel@tonic-gate				ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
5707c478bdstevel@tonic-gate				ASSERT(nlwp > 0);
5717c478bdstevel@tonic-gate				--nlwp;
5727c478bdstevel@tonic-gate				*idp++ = t->t_tid;
5737c478bdstevel@tonic-gate			} while ((t = t->t_forw) != p->p_tlist);
5747c478bdstevel@tonic-gate		}
5757c478bdstevel@tonic-gate		*idp = 0;
5767c478bdstevel@tonic-gate		ASSERT(nlwp == 0);
5777c478bdstevel@tonic-gate		prunlock(pnp);
5787c478bdstevel@tonic-gate		if (copyout(Bidp, cmaddr, (Nlwp+1) * sizeof (id_t)))
5797c478bdstevel@tonic-gate			error = EFAULT;
5807c478bdstevel@tonic-gate		kmem_free(Bidp, (Nlwp+1) * sizeof (id_t));
5817c478bdstevel@tonic-gate		break;
5827c478bdstevel@tonic-gate	}
5837c478bdstevel@tonic-gate
5847c478bdstevel@tonic-gate	case PIOCOPENLWP:	/* return /proc lwp file descriptor */
5857c478bdstevel@tonic-gate	{
5867c478bdstevel@tonic-gate		vnode_t *xvp;
5877c478bdstevel@tonic-gate		int n;
5887c478bdstevel@tonic-gate
5897c478bdstevel@tonic-gate		prunlock(pnp);
5907c478bdstevel@tonic-gate		if ((xvp = prlwpnode(pnp, un.lwpid)) == NULL)
5917c478bdstevel@tonic-gate			error = ENOENT;
5927c478bdstevel@tonic-gate		else if (error = fassign(&xvp, flag & (FREAD|FWRITE), &n)) {
5937c478bdstevel@tonic-gate			VN_RELE(xvp);
5947c478bdstevel@tonic-gate		} else
5957c478bdstevel@tonic-gate			*rvalp = n;
5967c478bdstevel@tonic-gate		break;
5977c478bdstevel@tonic-gate	}
5987c478bdstevel@tonic-gate
5997c478bdstevel@tonic-gate	case PIOCOPENPD:	/* return /proc page data file descriptor */
6007c478bdstevel@tonic-gate	{
6017c478bdstevel@tonic-gate		vnode_t *xvp = PTOV(xpnp);
6027c478bdstevel@tonic-gate		vnode_t *dp = pnp->pr_parent;
6037c478bdstevel@tonic-gate		int n;
6047c478bdstevel@tonic-gate
6057c478bdstevel@tonic-gate		if (pnp->pr_type == PR_LWPIDFILE) {
6067c478bdstevel@tonic-gate			dp = VTOP(dp)->pr_parent;
6077c478bdstevel@tonic-gate			dp = VTOP(dp)->pr_parent;
6087c478bdstevel@tonic-gate		}
6097c478bdstevel@tonic-gate		ASSERT(VTOP(dp)->pr_type == PR_PIDDIR);
6107c478bdstevel@tonic-gate
6117c478bdstevel@tonic-gate		VN_HOLD(dp);
6127c478bdstevel@tonic-gate		pcp = pnp->pr_pcommon;
6137c478bdstevel@tonic-gate		xpnp->pr_ino = ptoi(pcp->prc_pid);
6147c478bdstevel@tonic-gate		xpnp->pr_common = pcp;
6157c478bdstevel@tonic-gate		xpnp->pr_pcommon = pcp;
6167c478bdstevel@tonic-gate		xpnp->pr_parent = dp;
6177c478bdstevel@tonic-gate
6187c478bdstevel@tonic-gate		xpnp->pr_next = p->p_plist;
6197c478bdstevel@tonic-gate		p->p_plist = xvp;
6207c478bdstevel@tonic-gate
6217c478bdstevel@tonic-gate		prunlock(pnp);
6227c478bdstevel@tonic-gate		if (error = fassign(&xvp, FREAD, &n)) {
6237c478bdstevel@tonic-gate			VN_RELE(xvp);
6247c478bdstevel@tonic-gate		} else
6257c478bdstevel@tonic-gate			*rvalp = n;
6267c478bdstevel@tonic-gate
6277c478bdstevel@tonic-gate		xpnp = NULL;
6287c478bdstevel@tonic-gate		break;
6297c478bdstevel@tonic-gate	}
6307c478bdstevel@tonic-gate
6317c478bdstevel@tonic-gate	case PIOCGTRACE:	/* get signal trace mask */
6327c478bdstevel@tonic-gate		prassignset(&un.smask, &p->p_sigmask);
6337c478bdstevel@tonic-gate		prunlock(pnp);
6347c478bdstevel@tonic-gate		if (copyout(&un.smask, cmaddr, sizeof (un.smask)))
6357c478bdstevel@tonic-gate			error = EFAULT;
6367c478bdstevel@tonic-gate		break;
6377c478bdstevel@tonic-gate
6387c478bdstevel@tonic-gate	case PIOCSTRACE:	/* set signal trace mask */
6397c478bdstevel@tonic-gate		prdelset(&un.smask, SIGKILL);
6407c478bdstevel@tonic-gate		prassignset(&p->p_sigmask, &un.smask);
6417c478bdstevel@tonic-gate		if (!sigisempty(&p->p_sigmask))
6427c478bdstevel@tonic-gate			p->p_proc_flag |= P_PR_TRACE;
6437c478bdstevel@tonic-gate		else if (prisempty(&p->p_fltmask)) {
6447c478bdstevel@tonic-gate			up = PTOU(p);
6457c478bdstevel@tonic-gate			if (up->u_systrap == 0)
6467c478bdstevel@tonic-gate				p->p_proc_flag &= ~P_PR_TRACE;
6477c478bdstevel@tonic-gate		}
6487c478bdstevel@tonic-gate		prunlock(pnp);
6497c478bdstevel@tonic-gate		break;
6507c478bdstevel@tonic-gate
6517c478bdstevel@tonic-gate	case PIOCSSIG:		/* set current signal */
6527c478bdstevel@tonic-gate		error = pr_setsig(pnp, &un.info);
6537c478bdstevel@tonic-gate		prunlock(pnp);
6547c478bdstevel@tonic-gate		if (un.info.si_signo == SIGKILL && error == 0)
6557c478bdstevel@tonic-gate			pr_wait_die(pnp);
6567c478bdstevel@tonic-gate		break;
6577c478bdstevel@tonic-gate
6587c478bdstevel@tonic-gate	case PIOCKILL:		/* send signal */
6597c478bdstevel@tonic-gate	{
6607c478bdstevel@tonic-gate		int sig = (int)un.signo;
6617c478bdstevel@tonic-gate
6627c478bdstevel@tonic-gate		error = pr_kill(pnp, sig, cr);
6637c478bdstevel@tonic-gate		prunlock(pnp);
6647c478bdstevel@tonic-gate		if (sig == SIGKILL && error == 0)
6657c478bdstevel@tonic-gate			pr_wait_die(pnp);
6667c478bdstevel@tonic-gate		break;
6677c478bdstevel@tonic-gate	}
6687c478bdstevel@tonic-gate
6697c478bdstevel@tonic-gate	case PIOCUNKILL:	/* delete a signal */
6707c478bdstevel@tonic-gate		error = pr_unkill(pnp, (int)un.signo);
6717c478bdstevel@tonic-gate		prunlock(pnp);
6727c478bdstevel@tonic-gate		break;
6737c478bdstevel@tonic-gate
6747c478bdstevel@tonic-gate	case PIOCNICE:		/* set nice priority */
6757c478bdstevel@tonic-gate		error = pr_nice(p, (int)un.nice, cr);
6767c478bdstevel@tonic-gate		prunlock(pnp);
6777c478bdstevel@tonic-gate		break;
6787c478bdstevel@tonic-gate
6797c478bdstevel@tonic-gate	case PIOCGENTRY:	/* get syscall entry bit mask */
6807c478bdstevel@tonic-gate	case PIOCGEXIT:		/* get syscall exit bit mask */
6817c478bdstevel@tonic-gate		up = PTOU(p);
6827c478bdstevel@tonic-gate		if (cmd == PIOCGENTRY) {
6837c478bdstevel@tonic-gate			prassignset(&un.prmask, &up->u_entrymask);
6847c478bdstevel@tonic-gate		} else {
6857c478bdstevel@tonic-gate			prassignset(&un.prmask, &up->u_exitmask);
6867c478bdstevel@tonic-gate		}
6877c478bdstevel@tonic-gate		prunlock(pnp);
6887c478bdstevel@tonic-gate		if (copyout(&un.prmask, cmaddr, sizeof (un.prmask)))
6897c478bdstevel@tonic-gate			error = EFAULT;
6907c478bdstevel@tonic-gate		break;
6917c478bdstevel@tonic-gate
6927c478bdstevel@tonic-gate	case PIOCSENTRY:	/* set syscall entry bit mask */
6937c478bdstevel@tonic-gate	case PIOCSEXIT:		/* set syscall exit bit mask */
6947c478bdstevel@tonic-gate		pr_setentryexit(p, &un.prmask, cmd == PIOCSENTRY);
6957c478bdstevel@tonic-gate		prunlock(pnp);
6967c478bdstevel@tonic-gate		break;
6977c478bdstevel@tonic-gate
6987c478bdstevel@tonic-gate	case PIOCSRLC:		/* obsolete: set running on last /proc close */
6997c478bdstevel@tonic-gate		error = pr_set(p, prmapsetflags(PR_RLC));
7007c478bdstevel@tonic-gate		prunlock(pnp);
7017c478bdstevel@tonic-gate		break;
7027c478bdstevel@tonic-gate
7037c478bdstevel@tonic-gate	case PIOCRRLC:		/* obsolete: reset run-on-last-close flag */
7047c478bdstevel@tonic-gate		error = pr_unset(p, prmapsetflags(PR_RLC));
7057c478bdstevel@tonic-gate		prunlock(pnp);
7067c478bdstevel@tonic-gate		break;
7077c478bdstevel@tonic-gate
7087c478bdstevel@tonic-gate	case PIOCSFORK:		/* obsolete: set inherit-on-fork flag */
7097c478bdstevel@tonic-gate		error = pr_set(p, prmapsetflags(PR_FORK));
7107c478bdstevel@tonic-gate		prunlock(pnp);
7117c478bdstevel@tonic-gate		break;
7127c478bdstevel@tonic-gate
7137c478bdstevel@tonic-gate	case PIOCRFORK:		/* obsolete: reset inherit-on-fork flag */
7147c478bdstevel@tonic-gate		error = pr_unset(p, prmapsetflags(PR_FORK));
7157c478bdstevel@tonic-gate		prunlock(pnp);
7167c478bdstevel@tonic-gate		break;
7177c478bdstevel@tonic-gate
7187c478bdstevel@tonic-gate	case PIOCSET:		/* set process flags */
7197c478bdstevel@tonic-gate		error = pr_set(p, prmapsetflags(un.flags));
7207c478bdstevel@tonic-gate		prunlock(pnp);
7217c478bdstevel@tonic-gate		break;
7227c478bdstevel@tonic-gate
7237c478bdstevel@tonic-gate	case PIOCRESET:		/* reset process flags */
7247c478bdstevel@tonic-gate		error = pr_unset(p, prmapsetflags(un.flags));
7257c478bdstevel@tonic-gate		prunlock(pnp);
7267c478bdstevel@tonic-gate		break;
7277c478bdstevel@tonic-gate
7287c478bdstevel@tonic-gate	case PIOCGREG:		/* get general registers */
7297c478bdstevel@tonic-gate		if (t->t_state != TS_STOPPED && !VSTOPPED(t))
7307c478bdstevel@tonic-gate			bzero(un.regs, sizeof (un.regs));
7317c478bdstevel@tonic-gate		else {
7327c478bdstevel@tonic-gate			/* drop p_lock while touching the lwp's stack */
7337c478bdstevel@tonic-gate			mutex_exit(&p->p_lock);
7347c478bdstevel@tonic-gate			prgetprregs(lwp, un.regs);
7357c478bdstevel@tonic-gate			mutex_enter(&p->p_lock);
7367c478bdstevel@tonic-gate		}
7377c478bdstevel@tonic-gate		prunlock(pnp);
7387c478bdstevel@tonic-gate		if (copyout(un.regs, cmaddr, sizeof (un.regs)))
7397c478bdstevel@tonic-gate			error = EFAULT;
7407c478bdstevel@tonic-gate		break;
7417c478bdstevel@tonic-gate
7427c478bdstevel@tonic-gate	case PIOCSREG:		/* set general registers */
7437c478bdstevel@tonic-gate		if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
7447c478bdstevel@tonic-gate			error = EBUSY;
7457c478bdstevel@tonic-gate		else {
7467c478bdstevel@tonic-gate			/* drop p_lock while touching the lwp's stack */
7477c478bdstevel@tonic-gate			mutex_exit(&p->p_lock);
7487c478bdstevel@tonic-gate			prsetprregs(lwp, un.regs, 0);
7497c478bdstevel@tonic-gate			mutex_enter(&p->p_lock);
7507c478bdstevel@tonic-gate		}
7517c478bdstevel@tonic-gate		prunlock(pnp);
7527c478bdstevel@tonic-gate		break;
7537c478bdstevel@tonic-gate
7547c478bdstevel@tonic-gate	case PIOCGFPREG:	/* get floating-point registers */
7557c478bdstevel@tonic-gate		if (!prhasfp()) {
7567c478bdstevel@tonic-gate			prunlock(pnp);
7577c478bdstevel@tonic-gate			error = EINVAL;	/* No FP support */
7587c478bdstevel@tonic-gate			break;
7597c478bdstevel@tonic-gate		}
7607c478bdstevel@tonic-gate
7617c478bdstevel@tonic-gate		if (t->t_state != TS_STOPPED && !VSTOPPED(t))
7627c478bdstevel@tonic-gate			bzero(&un.fpregs, sizeof (un.fpregs));
7637c478bdstevel@tonic-gate		else {
7647c478bdstevel@tonic-gate			/* drop p_lock while touching the lwp's stack */
7657c478bdstevel@tonic-gate			mutex_exit(&p->p_lock);
7667c478bdstevel@tonic-gate			prgetprfpregs(lwp, &un.fpregs);
7677c478bdstevel@tonic-gate			mutex_enter(&p->p_lock);
7687c478bdstevel@tonic-gate		}
7697c478bdstevel@tonic-gate		prunlock(pnp);
7707c478bdstevel@tonic-gate		if (copyout(&un.fpregs, cmaddr, sizeof (un.fpregs)))
7717c478bdstevel@tonic-gate			error = EFAULT;
7727c478bdstevel@tonic-gate		break;
7737c478bdstevel@tonic-gate
7747c478bdstevel@tonic-gate	case PIOCSFPREG:	/* set floating-point registers */
7757c478bdstevel@tonic-gate		if (!prhasfp())
7767c478bdstevel@tonic-gate			error = EINVAL;	/* No FP support */
7777c478bdstevel@tonic-gate		else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
7787c478bdstevel@tonic-gate			error = EBUSY;
7797c478bdstevel@tonic-gate		else {
7807c478bdstevel@tonic-gate			/* drop p_lock while touching the lwp's stack */
7817c478bdstevel@tonic-gate			mutex_exit(&p->p_lock);
7827c478bdstevel@tonic-gate			prsetprfpregs(lwp, &un.fpregs);
7837c478bdstevel@tonic-gate			mutex_enter(&p->p_lock);
7847c478bdstevel@tonic-gate		}
7857c478bdstevel@tonic-gate		prunlock(pnp);
7867c478bdstevel@tonic-gate		break;
7877c478bdstevel@tonic-gate
7887c478bdstevel@tonic-gate	case PIOCGXREGSIZE:	/* get the size of the extra registers */
7897c478bdstevel@tonic-gate	{
7907c478bdstevel@tonic-gate		int xregsize;
7917c478bdstevel@tonic-gate
7927c478bdstevel@tonic-gate		if (prhasx(p)) {
7937c478bdstevel@tonic-gate			xregsize = prgetprxregsize(p);
7947c478bdstevel@tonic-gate			prunlock(pnp);
7957c478bdstevel@tonic-gate			if (copyout(&xregsize, cmaddr, sizeof (xregsize)))
7967c478bdstevel@tonic-gate				error = EFAULT;
7977c478bdstevel@tonic-gate		} else {
7987c478bdstevel@tonic-gate			prunlock(pnp);
7997c478bdstevel@tonic-gate			error = EINVAL;	/* No extra register support */
8007c478bdstevel@tonic-gate		}
8017c478bdstevel@tonic-gate		break;
8027c478bdstevel@tonic-gate	}
8037c478bdstevel@tonic-gate
8047c478bdstevel@tonic-gate	case PIOCGXREG:		/* get extra registers */
8057c478bdstevel@tonic-gate		if (prhasx(p)) {
8067c478bdstevel@tonic-gate			bzero(thing, thingsize);
8077c478bdstevel@tonic-gate			if (t->t_state == TS_STOPPED || VSTOPPED(t)) {
8087c478bdstevel@tonic-gate				/* drop p_lock to touch the stack */
8097c478bdstevel@tonic-gate				mutex_exit(&p->p_lock);
8107c478bdstevel@tonic-gate				prgetprxregs(lwp, thing);
8117c478bdstevel@tonic-gate				mutex_enter(&p->p_lock);
8127c478bdstevel@tonic-gate			}
8137c478bdstevel@tonic-gate			prunlock(pnp);
8147c478bdstevel@tonic-gate			if (copyout(thing, cmaddr, thingsize))
8157c478bdstevel@tonic-gate				error = EFAULT;
8167c478bdstevel@tonic-gate		} else {
8177c478bdstevel@tonic-gate			prunlock(pnp);
8187c478bdstevel@tonic-gate			error = EINVAL;	/* No extra register support */
8197c478bdstevel@tonic-gate		}
8207c478bdstevel@tonic-gate		if (thing) {
8217c478bdstevel@tonic-gate			kmem_free(thing, thingsize);
8227c478bdstevel@tonic-gate			thing = NULL;
8237c478bdstevel@tonic-gate		}
8247c478bdstevel@tonic-gate		break;
8257c478bdstevel@tonic-gate
8267c478bdstevel@tonic-gate	case PIOCSXREG:		/* set extra registers */
8277c478bdstevel@tonic-gate		if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
8287c478bdstevel@tonic-gate			error = EBUSY;
8297c478bdstevel@tonic-gate		else if (!prhasx(p))
8307c478bdstevel@tonic-gate			error = EINVAL;	/* No extra register support */
8317c478bdstevel@tonic-gate		else if (thing) {
8327c478bdstevel@tonic-gate			/* drop p_lock while touching the lwp's stack */
8337c478bdstevel@tonic-gate			mutex_exit(&p->p_lock);
8347c478bdstevel@tonic-gate			prsetprxregs(lwp, thing);
8357c478bdstevel@tonic-gate			mutex_enter(&p->p_lock);
8367c478bdstevel@tonic-gate		}
8377c478bdstevel@tonic-gate		prunlock(pnp);
8387c478bdstevel@tonic-gate		if (thing) {
8397c478bdstevel@tonic-gate			kmem_free(thing, thingsize);
8407c478bdstevel@tonic-gate			thing = NULL;
8417c478bdstevel@tonic-gate		}
8427c478bdstevel@tonic-gate		break;
8437c478bdstevel@tonic-gate
8447c478bdstevel@tonic-gate	case PIOCSTATUS:	/* get process/lwp status */
845fa9e406ahrens		oprgetstatus(t, &un.prstat, VTOZONE(vp));
8467c478bdstevel@tonic-gate		prunlock(pnp);
8477c478bdstevel@tonic-gate		if (copyout(&un.prstat, cmaddr, sizeof (un.prstat)))
8487c478bdstevel@tonic-gate			error = EFAULT;
8497c478bdstevel@tonic-gate		break;
8507c478bdstevel@tonic-gate
8517c478bdstevel@tonic-gate	case PIOCLSTATUS:	/* get status for process & all lwps */
8527c478bdstevel@tonic-gate	{
8537c478bdstevel@tonic-gate		int Nlwp;
8547c478bdstevel@tonic-gate		int nlwp;
8557c478bdstevel@tonic-gate		prstatus_t *Bprsp;
8567c478bdstevel@tonic-gate		prstatus_t *prsp;
8577c478bdstevel@tonic-gate
8587c478bdstevel@tonic-gate		nlwp = Nlwp = p->p_lwpcnt;
8597c478bdstevel@tonic-gate
8607c478bdstevel@tonic-gate		if (thing && thingsize != (Nlwp+1) * sizeof (prstatus_t)) {
8617c478bdstevel@tonic-gate			kmem_free(thing, thingsize);
8627c478bdstevel@tonic-gate			thing = NULL;
8637c478bdstevel@tonic-gate		}
8647c478bdstevel@tonic-gate		if (thing == NULL) {
8657c478bdstevel@tonic-gate			thingsize = (Nlwp+1) * sizeof (prstatus_t);
8667c478bdstevel@tonic-gate			thing = kmem_alloc(thingsize, KM_NOSLEEP);
8677c478bdstevel@tonic-gate		}
8687c478bdstevel@tonic-gate		if (thing == NULL) {
8697c478bdstevel@tonic-gate			prunlock(pnp);
8707c478bdstevel@tonic-gate			goto startover;
8717c478bdstevel@tonic-gate		}
8727c478bdstevel@tonic-gate
8737c478bdstevel@tonic-gate		Bprsp = thing;
8747c478bdstevel@tonic-gate		thing = NULL;
8757c478bdstevel@tonic-gate		prsp = Bprsp;
876fa9e406ahrens		oprgetstatus(t, prsp, VTOZONE(vp));
8777c478bdstevel@tonic-gate		t = p->p_tlist;
8787c478bdstevel@tonic-gate		do {
8797c478bdstevel@tonic-gate			ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
8807c478bdstevel@tonic-gate			ASSERT(nlwp > 0);
8817c478bdstevel@tonic-gate			--nlwp;
882fa9e406ahrens			oprgetstatus(t, ++prsp, VTOZONE(vp));
8837c478bdstevel@tonic-gate		} while ((t = t->t_forw) != p->p_tlist);
8847c478bdstevel@tonic-gate		ASSERT(nlwp == 0);
8857c478bdstevel@tonic-gate		prunlock(pnp);
8867c478bdstevel@tonic-gate		if (copyout(Bprsp, cmaddr, (Nlwp+1) * sizeof (prstatus_t)))
8877c478bdstevel@tonic-gate			error = EFAULT;
8887c478bdstevel@tonic-gate
8897c478bdstevel@tonic-gate		kmem_free(Bprsp, (Nlwp+1) * sizeof (prstatus_t));
8907c478bdstevel@tonic-gate		break;
8917c478bdstevel@tonic-gate	}
8927c478bdstevel@tonic-gate
8937c478bdstevel@tonic-gate	case PIOCPSINFO:	/* get ps(1) information */
8947c478bdstevel@tonic-gate	{
8957c478bdstevel@tonic-gate		prpsinfo_t *psp = &un.prps;
8967c478bdstevel@tonic-gate
8977c478bdstevel@tonic-gate		oprgetpsinfo(p, psp,
8987c478bdstevel@tonic-gate		    (pnp->pr_type == PR_LWPIDFILE)? pcp->prc_thread : NULL);
8997c478bdstevel@tonic-gate
9007c478bdstevel@tonic-gate		prunlock(pnp);
9017c478bdstevel@tonic-gate		if (copyout(&un.prps, cmaddr, sizeof (un.prps)))
9027c478bdstevel@tonic-gate			error = EFAULT;
9037c478bdstevel@tonic-gate		break;
9047c478bdstevel@tonic-gate	}
9057c478bdstevel@tonic-gate
9067c478bdstevel@tonic-gate	case PIOCMAXSIG:	/* get maximum signal number */
9077c478bdstevel@tonic-gate	{
908eb9dbf0Roger A. Faulkner		int n = nsig-1;
9097c478bdstevel@tonic-gate
9107c478bdstevel@tonic-gate		prunlock(pnp);
9117c478bdstevel@tonic-gate		if (copyout(&n, cmaddr, sizeof (n)))
9127c478bdstevel@tonic-gate			error = EFAULT;
9137c478bdstevel@tonic-gate		break;
9147c478bdstevel@tonic-gate	}
9157c478bdstevel@tonic-gate
9167c478bdstevel@tonic-gate	case PIOCACTION:	/* get signal action structures */
9177c478bdstevel@tonic-gate	{
9187c478bdstevel@tonic-gate		uint_t sig;
9197c478bdstevel@tonic-gate		struct sigaction *sap = thing;
9207c478bdstevel@tonic-gate
9217c478bdstevel@tonic-gate		up = PTOU(p);
922eb9dbf0Roger A. Faulkner		for (sig = 1; sig < nsig; sig++)
9237c478bdstevel@tonic-gate			prgetaction(p, up, sig, &sap[sig-1]);
9247c478bdstevel@tonic-gate		prunlock(pnp);
925eb9dbf0Roger A. Faulkner		if (copyout(sap, cmaddr, (nsig-1) * sizeof (struct sigaction)))
9267c478bdstevel@tonic-gate			error = EFAULT;
927eb9dbf0Roger A. Faulkner		kmem_free(sap, (nsig-1) * sizeof (struct sigaction));
9287c478bdstevel@tonic-gate		thing = NULL;
9297c478bdstevel@tonic-gate		break;
9307c478bdstevel@tonic-gate	}
9317c478bdstevel@tonic-gate
9327c478bdstevel@tonic-gate	case PIOCGHOLD:		/* get signal-hold mask */
93372a6dc1Patrick Mooney		prgethold(t, &un.holdmask);
9347c478bdstevel@tonic-gate		prunlock(pnp);
9357c478bdstevel@tonic-gate		if (copyout(&un.holdmask, cmaddr, sizeof (un.holdmask)))
9367c478bdstevel@tonic-gate			error = EFAULT;
9377c478bdstevel@tonic-gate		break;
9387c478bdstevel@tonic-gate
9397c478bdstevel@tonic-gate	case PIOCSHOLD:		/* set signal-hold mask */
9407c478bdstevel@tonic-gate		pr_sethold(pnp, &un.holdmask);
9417c478bdstevel@tonic-gate		prunlock(pnp);
9427c478bdstevel@tonic-gate		break;
9437c478bdstevel@tonic-gate
9447c478bdstevel@tonic-gate	case PIOCNMAP:		/* get number of memory mappings */
9457c478bdstevel@tonic-gate	{
9467c478bdstevel@tonic-gate		int n;
9477c478bdstevel@tonic-gate		struct as *as = p->p_as;
9487c478bdstevel@tonic-gate
9497c478bdstevel@tonic-gate		if ((p->p_flag & SSYS) || as == &kas)
9507c478bdstevel@tonic-gate			n = 0;
9517c478bdstevel@tonic-gate		else {
9527c478bdstevel@tonic-gate			mutex_exit(&p->p_lock);
953dc32d87Josef 'Jeff' Sipek			AS_LOCK_ENTER(as, RW_WRITER);
9547c478bdstevel@tonic-gate			n = prnsegs(as, 0);
955dc32d87Josef 'Jeff' Sipek			AS_LOCK_EXIT(as);
9567c478bdstevel@tonic-gate			mutex_enter(&p->p_lock);
9577c478bdstevel@tonic-gate		}
9587c478bdstevel@tonic-gate		prunlock(pnp);
9597c478bdstevel@tonic-gate		if (copyout(&n, cmaddr, sizeof (int)))
9607c478bdstevel@tonic-gate			error = EFAULT;
9617c478bdstevel@tonic-gate		break;
9627c478bdstevel@tonic-gate	}
9637c478bdstevel@tonic-gate
9647c478bdstevel@tonic-gate	case PIOCMAP:		/* get memory map information */
9657c478bdstevel@tonic-gate	{
966870619efrankho		list_t iolhead;
9677c478bdstevel@tonic-gate		struct as *as = p->p_as;
9687c478bdstevel@tonic-gate
969870619efrankho		if ((p->p_flag & SSYS) || as == &kas) {
970870619efrankho			error = 0;
971870619efrankho			prunlock(pnp);
9727c478bdstevel@tonic-gate		} else {
9737c478bdstevel@tonic-gate			mutex_exit(&p->p_lock);
974dc32d87Josef 'Jeff' Sipek			AS_LOCK_ENTER(as, RW_WRITER);
975870619efrankho			error = oprgetmap(p, &iolhead);
976dc32d87Josef 'Jeff' Sipek			AS_LOCK_EXIT(as);
9777c478bdstevel@tonic-gate			mutex_enter(&p->p_lock);
978870619efrankho			prunlock(pnp);
9797c478bdstevel@tonic-gate
980870619efrankho			error = pr_iol_copyout_and_free(&iolhead,
981870619efrankho			    &cmaddr, error);
982870619efrankho		}
983870619efrankho		/*
984870619efrankho		 * The procfs PIOCMAP ioctl returns an all-zero buffer
985870619efrankho		 * to indicate the end of the prmap[] array.
986870619efrankho		 * Append it to whatever has already been copied out.
987870619efrankho		 */
988870619efrankho		bzero(&un.prmap, sizeof (un.prmap));
989870619efrankho		if (!error && copyout(&un.prmap, cmaddr, sizeof (un.prmap)))
9907c478bdstevel@tonic-gate			error = EFAULT;
991870619efrankho
9927c478bdstevel@tonic-gate		break;
9937c478bdstevel@tonic-gate	}
9947c478bdstevel@tonic-gate
9957c478bdstevel@tonic-gate	case PIOCGFAULT:	/* get mask of traced faults */
9967c478bdstevel@tonic-gate		prassignset(&un.fltmask, &p->p_fltmask);
9977c478bdstevel@tonic-gate		prunlock(pnp);
9987c478bdstevel@tonic-gate		if (copyout(&un.fltmask, cmaddr, sizeof (un.fltmask)))
9997c478bdstevel@tonic-gate			error = EFAULT;
10007c478bdstevel@tonic-gate		break;
10017c478bdstevel@tonic-gate
10027c478bdstevel@tonic-gate	case PIOCSFAULT:	/* set mask of traced faults */
10037c478bdstevel@tonic-gate		pr_setfault(p, &un.fltmask);
10047c478bdstevel@tonic-gate		prunlock(pnp);
10057c478bdstevel@tonic-gate		break;
10067c478bdstevel@tonic-gate
10077c478bdstevel@tonic-gate	case PIOCCFAULT:	/* clear current fault */
10087c478bdstevel@tonic-gate		lwp->lwp_curflt = 0;
10097c478bdstevel@tonic-gate		prunlock(pnp);
10107c478bdstevel@tonic-gate		break;
10117c478bdstevel@tonic-gate
10127c478bdstevel@tonic-gate	case PIOCCRED:		/* get process credentials */
10137c478bdstevel@tonic-gate	{
10147c478bdstevel@tonic-gate		cred_t *cp;
10157c478bdstevel@tonic-gate
10167c478bdstevel@tonic-gate		mutex_enter(&p->p_crlock);
10177c478bdstevel@tonic-gate		cp = p->p_cred;
10187c478bdstevel@tonic-gate		un.prcred.pr_euid = crgetuid(cp);
10197c478bdstevel@tonic-gate		un.prcred.pr_ruid = crgetruid(cp);
10207c478bdstevel@tonic-gate		un.prcred.pr_suid = crgetsuid(cp);
10217c478bdstevel@tonic-gate		un.prcred.pr_egid = crgetgid(cp);
10227c478bdstevel@tonic-gate		un.prcred.pr_rgid = crgetrgid(cp);
10237c478bdstevel@tonic-gate		un.prcred.pr_sgid = crgetsgid(cp);
10247c478bdstevel@tonic-gate		un.prcred.pr_ngroups = crgetngroups(cp);
10257c478bdstevel@tonic-gate		mutex_exit(&p->p_crlock);
10267c478bdstevel@tonic-gate
10277c478bdstevel@tonic-gate		prunlock(pnp);
10287c478bdstevel@tonic-gate		if (copyout(&un.prcred, cmaddr, sizeof (un.prcred)))
10297c478bdstevel@tonic-gate			error = EFAULT;
10307c478bdstevel@tonic-gate		break;
10317c478bdstevel@tonic-gate	}
10327c478bdstevel@tonic-gate
10337c478bdstevel@tonic-gate	case PIOCGROUPS:	/* get supplementary groups */
10347c478bdstevel@tonic-gate	{
10357c478bdstevel@tonic-gate		cred_t *cp;
10367c478bdstevel@tonic-gate
10377c478bdstevel@tonic-gate		mutex_enter(&p->p_crlock);
10387c478bdstevel@tonic-gate		cp = p->p_cred;
10397c478bdstevel@tonic-gate		crhold(cp);
10407c478bdstevel@tonic-gate		mutex_exit(&p->p_crlock);
10417c478bdstevel@tonic-gate
10427c478bdstevel@tonic-gate		prunlock(pnp);
10437c478bdstevel@tonic-gate		if (copyout(crgetgroups(cp), cmaddr,
10447c478bdstevel@tonic-gate		    MAX(crgetngroups(cp), 1) * sizeof (gid_t)))
10457c478bdstevel@tonic-gate			error = EFAULT;
10467c478bdstevel@tonic-gate		crfree(cp);
10477c478bdstevel@tonic-gate		break;
10487c478bdstevel@tonic-gate	}
10497c478bdstevel@tonic-gate
10507c478bdstevel@tonic-gate	case PIOCUSAGE:		/* get usage info */
10517c478bdstevel@tonic-gate	{
10527c478bdstevel@tonic-gate		/*
10537c478bdstevel@tonic-gate		 * For an lwp file descriptor, return just the lwp usage.
10547c478bdstevel@tonic-gate		 * For a process file descriptor, return total usage,
10557c478bdstevel@tonic-gate		 * all current lwps plus all defunct lwps.
10567c478bdstevel@tonic-gate		 */
10577c478bdstevel@tonic-gate		prhusage_t *pup = &un.prhusage;
10587c478bdstevel@tonic-gate		prusage_t *upup;
10597c478bdstevel@tonic-gate
10607c478bdstevel@tonic-gate		bzero(pup, sizeof (*pup));
10617c478bdstevel@tonic-gate		pup->pr_tstamp = gethrtime();
10627c478bdstevel@tonic-gate
10637c478bdstevel@tonic-gate		if (pnp->pr_type == PR_LWPIDFILE) {
10647c478bdstevel@tonic-gate			t = pcp->prc_thread;
10657c478bdstevel@tonic-gate			if (t != NULL)
10667c478bdstevel@tonic-gate				prgetusage(t, pup);
10677c478bdstevel@tonic-gate			else
10687c478bdstevel@tonic-gate				error = ENOENT;
10697c478bdstevel@tonic-gate		} else {
10707c478bdstevel@tonic-gate			pup->pr_count  = p->p_defunct;
10717c478bdstevel@tonic-gate			pup->pr_create = p->p_mstart;
10727c478bdstevel@tonic-gate			pup->pr_term   = p->p_mterm;
10737c478bdstevel@tonic-gate
10747c478bdstevel@tonic-gate			pup->pr_rtime    = p->p_mlreal;
10757c478bdstevel@tonic-gate			pup->pr_utime    = p->p_acct[LMS_USER];
10767c478bdstevel@tonic-gate			pup->pr_stime    = p->p_acct[LMS_SYSTEM];
10777c478bdstevel@tonic-gate			pup->pr_ttime    = p->p_acct[LMS_TRAP];
10787c478bdstevel@tonic-gate			pup->pr_tftime   = p->p_acct[LMS_TFAULT];
10797c478bdstevel@tonic-gate			pup->pr_dftime   = p->p_acct[LMS_DFAULT];
10807c478bdstevel@tonic-gate			pup->pr_kftime   = p->p_acct[LMS_KFAULT];
10817c478bdstevel@tonic-gate			pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
10827c478bdstevel@tonic-gate			pup->pr_slptime  = p->p_acct[LMS_SLEEP];
10837c478bdstevel@tonic-gate			pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
10847c478bdstevel@tonic-gate			pup->pr_stoptime = p->p_acct[LMS_STOPPED];
10857c478bdstevel@tonic-gate
10867c478bdstevel@tonic-gate			pup->pr_minf  = p->p_ru.minflt;
10877c478bdstevel@tonic-gate			pup->pr_majf  = p->p_ru.majflt;
10887c478bdstevel@tonic-gate			pup->pr_nswap = p->p_ru.nswap;
10897c478bdstevel@tonic-gate			pup->pr_inblk = p->p_ru.inblock;
10907c478bdstevel@tonic-gate			pup->pr_oublk = p->p_ru.oublock;
10917c478bdstevel@tonic-gate			pup->pr_msnd  = p->p_ru.msgsnd;
10927c478bdstevel@tonic-gate			pup->pr_mrcv  = p->p_ru.msgrcv;
10937c478bdstevel@tonic-gate			pup->pr_sigs  = p->p_ru.nsignals;
10947c478bdstevel@tonic-gate			pup->pr_vctx  = p->p_ru.nvcsw;
10957c478bdstevel@tonic-gate			pup->pr_ictx  = p->p_ru.nivcsw;
10967c478bdstevel@tonic-gate			pup->pr_sysc  = p->p_ru.sysc;
10977c478bdstevel@tonic-gate			pup->pr_ioch  = p->p_ru.ioch;
10987c478bdstevel@tonic-gate
10997c478bdstevel@tonic-gate			/*
11007c478bdstevel@tonic-gate			 * Add the usage information for each active lwp.
11017c478bdstevel@tonic-gate			 */
11027c478bdstevel@tonic-gate			if ((t = p->p_tlist) != NULL &&
11037c478bdstevel@tonic-gate			    !(pcp->prc_flags & PRC_DESTROY)) {
11047c478bdstevel@tonic-gate				do {
11057c478bdstevel@tonic-gate					ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
11067c478bdstevel@tonic-gate					pup->pr_count++;
11077c478bdstevel@tonic-gate					praddusage(t, pup);
11087c478bdstevel@tonic-gate				} while ((t = t->t_forw) != p->p_tlist);
11097c478bdstevel@tonic-gate			}
11107c478bdstevel@tonic-gate		}
11117c478bdstevel@tonic-gate
11127c478bdstevel@tonic-gate		prunlock(pnp);
11137c478bdstevel@tonic-gate
11147c478bdstevel@tonic-gate		upup = kmem_zalloc(sizeof (*upup), KM_SLEEP);
11157c478bdstevel@tonic-gate		prcvtusage(&un.prhusage, upup);
11167c478bdstevel@tonic-gate		if (copyout(upup, cmaddr, sizeof (*upup)))
11177c478bdstevel@tonic-gate			error = EFAULT;
11187c478bdstevel@tonic-gate		kmem_free(upup, sizeof (*upup));
11197c478bdstevel@tonic-gate
11207c478bdstevel@tonic-gate		break;
11217c478bdstevel@tonic-gate	}
11227c478bdstevel@tonic-gate
11237c478bdstevel@tonic-gate	case PIOCLUSAGE:	/* get detailed usage info */
11247c478bdstevel@tonic-gate	{
11257c478bdstevel@tonic-gate		int Nlwp;
11267c478bdstevel@tonic-gate		int nlwp;
11277c478bdstevel@tonic-gate		prusage_t *upup;
11287c478bdstevel@tonic-gate		prusage_t *Bupup;
11297c478bdstevel@tonic-gate		prhusage_t *pup;
11307c478bdstevel@tonic-gate		hrtime_t curtime;
11317c478bdstevel@tonic-gate
11327c478bdstevel@tonic-gate		nlwp = Nlwp = (pcp->prc_flags & PRC_DESTROY)? 0 : p->p_lwpcnt;
11337c478bdstevel@tonic-gate
11347c478bdstevel@tonic-gate		if (thing && thingsize !=
11357c478bdstevel@tonic-gate		    sizeof (prhusage_t) + (Nlwp+1) * sizeof (prusage_t)) {
11367c478bdstevel@tonic-gate			kmem_free(thing, thingsize);
11377c478bdstevel@tonic-gate			thing = NULL;
11387c478bdstevel@tonic-gate		}
11397c478bdstevel@tonic-gate		if (thing == NULL) {
11407c478bdstevel@tonic-gate			thingsize = sizeof (prhusage_t) +
11417c478bdstevel@tonic-gate			    (Nlwp+1) * sizeof (prusage_t);
11427c478bdstevel@tonic-gate			thing = kmem_alloc(thingsize, KM_NOSLEEP);
11437c478bdstevel@tonic-gate		}
11447c478bdstevel@tonic-gate		if (thing == NULL) {
11457c478bdstevel@tonic-gate			prunlock(pnp);
11467c478bdstevel@tonic-gate			goto startover;
11477c478bdstevel@tonic-gate		}
11487c478bdstevel@tonic-gate
11497c478bdstevel@tonic-gate		pup = thing;
11507c478bdstevel@tonic-gate		upup = Bupup = (prusage_t *)(pup + 1);
11517c478bdstevel@tonic-gate
11527c478bdstevel@tonic-gate		ASSERT(p == pcp->prc_proc);
11537c478bdstevel@tonic-gate
11547c478bdstevel@tonic-gate		curtime = gethrtime();
11557c478bdstevel@tonic-gate
11567c478bdstevel@tonic-gate		/*
11577c478bdstevel@tonic-gate		 * First the summation over defunct lwps.
11587c478bdstevel@tonic-gate		 */
11597c478bdstevel@tonic-gate		bzero(pup, sizeof (*pup));
11607c478bdstevel@tonic-gate		pup->pr_count  = p->p_defunct;
11617c478bdstevel@tonic-gate		pup->pr_tstamp = curtime;
11627c478bdstevel@tonic-gate		pup->pr_create = p->p_mstart;
11637c478bdstevel@tonic-gate		pup->pr_term   = p->p_mterm;
11647c478bdstevel@tonic-gate
11657c478bdstevel@tonic-gate		pup->pr_rtime    = p->p_mlreal;
11667c478bdstevel@tonic-gate		pup->pr_utime    = p->p_acct[LMS_USER];
11677c478bdstevel@tonic-gate		pup->pr_stime    = p->p_acct[LMS_SYSTEM];
11687c478bdstevel@tonic-gate		pup->pr_ttime    = p->p_acct[LMS_TRAP];
11697c478bdstevel@tonic-gate		pup->pr_tftime   = p->p_acct[LMS_TFAULT];
11707c478bdstevel@tonic-gate		pup->pr_dftime   = p->p_acct[LMS_DFAULT];
11717c478bdstevel@tonic-gate		pup->pr_kftime   = p->p_acct[LMS_KFAULT];
11727c478bdstevel@tonic-gate		pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
11737c478bdstevel@tonic-gate		pup->pr_slptime  = p->p_acct[LMS_SLEEP];
11747c478bdstevel@tonic-gate		pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
11757c478bdstevel@tonic-gate		pup->pr_stoptime = p->p_acct[LMS_STOPPED];
11767c478bdstevel@tonic-gate
11777c478bdstevel@tonic-gate		pup->pr_minf  = p->p_ru.minflt;
11787c478bdstevel@tonic-gate		pup->pr_majf  = p->p_ru.majflt;
11797c478bdstevel@tonic-gate		pup->pr_nswap = p->p_ru.nswap;
11807c478bdstevel@tonic-gate		pup->pr_inblk = p->p_ru.inblock;
11817c478bdstevel@tonic-gate		pup->pr_oublk = p->p_ru.oublock;
11827c478bdstevel@tonic-gate		pup->pr_msnd  = p->p_ru.msgsnd;
11837c478bdstevel@tonic-gate		pup->pr_mrcv  = p->p_ru.msgrcv;
11847c478bdstevel@tonic-gate		pup->pr_sigs  = p->p_ru.nsignals;
11857c478bdstevel@tonic-gate		pup->pr_vctx  = p->p_ru.nvcsw;
11867c478bdstevel@tonic-gate		pup->pr_ictx  = p->p_ru.nivcsw;
11877c478bdstevel@tonic-gate		pup->pr_sysc  = p->p_ru.sysc;
11887c478bdstevel@tonic-gate		pup->pr_ioch  = p->p_ru.ioch;
11897c478bdstevel@tonic-gate
11907c478bdstevel@tonic-gate		prcvtusage(pup, upup);
11917c478bdstevel@tonic-gate
11927c478bdstevel@tonic-gate		/*
11937c478bdstevel@tonic-gate		 * Fill one prusage struct for each active lwp.
11947c478bdstevel@tonic-gate		 */
11957c478bdstevel@tonic-gate		if ((t = p->p_tlist) != NULL &&
11967c478bdstevel@tonic-gate		    !(pcp->prc_flags & PRC_DESTROY)) {
11977c478bdstevel@tonic-gate			do {
11987c478bdstevel@tonic-gate				ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
11997c478bdstevel@tonic-gate				ASSERT(nlwp > 0);
12007c478bdstevel@tonic-gate				--nlwp;
12017c478bdstevel@tonic-gate				upup++;
12027c478bdstevel@tonic-gate				prgetusage(t, pup);
12037c478bdstevel@tonic-gate				prcvtusage(pup, upup);
12047c478bdstevel@tonic-gate			} while ((t = t->t_forw) != p->p_tlist);
12057c478bdstevel@tonic-gate		}
12067c478bdstevel@tonic-gate		ASSERT(nlwp == 0);
12077c478bdstevel@tonic-gate
12087c478bdstevel@tonic-gate		prunlock(pnp);
12097c478bdstevel@tonic-gate		if (copyout(Bupup, cmaddr, (Nlwp+1) * sizeof (prusage_t)))
12107c478bdstevel@tonic-gate			error = EFAULT;
12117c478bdstevel@tonic-gate		kmem_free(thing, thingsize);
12127c478bdstevel@tonic-gate		thing = NULL;
12137c478bdstevel@tonic-gate		break;
12147c478bdstevel@tonic-gate	}
12157c478bdstevel@tonic-gate
12167c478bdstevel@tonic-gate	case PIOCNAUXV:		/* get number of aux vector entries */
12177c478bdstevel@tonic-gate	{
12187c478bdstevel@tonic-gate		int n = __KERN_NAUXV_IMPL;
12197c478bdstevel@tonic-gate
12207c478bdstevel@tonic-gate		prunlock(pnp);
12217c478bdstevel@tonic-gate		if (copyout(&n, cmaddr, sizeof (int)))
12227c478bdstevel@tonic-gate			error = EFAULT;
12237c478bdstevel@tonic-gate		break;
12247c478bdstevel@tonic-gate	}
12257c478bdstevel@tonic-gate
12267c478bdstevel@tonic-gate	case PIOCAUXV:		/* get aux vector (see sys/auxv.h) */
12277c478bdstevel@tonic-gate	{
12287c478bdstevel@tonic-gate		up = PTOU(p);
12297c478bdstevel@tonic-gate		bcopy(up->u_auxv, un.auxv,
12307c478bdstevel@tonic-gate		    __KERN_NAUXV_IMPL * sizeof (auxv_t));
12317c478bdstevel@tonic-gate		prunlock(pnp);
12327c478bdstevel@tonic-gate		if (copyout(un.auxv, cmaddr,
12337c478bdstevel@tonic-gate		    __KERN_NAUXV_IMPL * sizeof (auxv_t)))
12347c478bdstevel@tonic-gate			error = EFAULT;
12357c478bdstevel@tonic-gate		break;
12367c478bdstevel@tonic-gate	}
12377c478bdstevel@tonic-gate
12387c478bdstevel@tonic-gate#if defined(__i386) || defined(__amd64)
12397c478bdstevel@tonic-gate	case PIOCNLDT:		/* get number of LDT entries */
12407c478bdstevel@tonic-gate	{
12417c478bdstevel@tonic-gate		int n;
12427c478bdstevel@tonic-gate
12436e092beVamsi Nagineni		mutex_exit(&p->p_lock);
12447c478bdstevel@tonic-gate		mutex_enter(&p->p_ldtlock);
12457c478bdstevel@tonic-gate		n = prnldt(p);
12467c478bdstevel@tonic-gate		mutex_exit(&p->p_ldtlock);
12476e092beVamsi Nagineni		mutex_enter(&p->p_lock);
12487c478bdstevel@tonic-gate		prunlock(pnp);
12497c478bdstevel@tonic-gate		if (copyout(&n, cmaddr, sizeof (n)))
12507c478bdstevel@tonic-gate			error = EFAULT;
12517c478bdstevel@tonic-gate		break;
12527c478bdstevel@tonic-gate	}
12537c478bdstevel@tonic-gate
12547c478bdstevel@tonic-gate	case PIOCLDT:		/* get LDT entries */
12557c478bdstevel@tonic-gate	{
12567c478bdstevel@tonic-gate		struct ssd *ssd;
12577c478bdstevel@tonic-gate		int n;
12587c478bdstevel@tonic-gate
12596e092beVamsi Nagineni		mutex_exit(&p->p_lock);
12607c478bdstevel@tonic-gate		mutex_enter(&p->p_ldtlock);
12617c478bdstevel@tonic-gate		n = prnldt(p);
12627c478bdstevel@tonic-gate
12637c478bdstevel@tonic-gate		if (thing && thingsize != (n+1) * sizeof (*ssd)) {
12647c478bdstevel@tonic-gate			kmem_free(thing, thingsize);
12657c478bdstevel@tonic-gate			thing = NULL;
12667c478bdstevel@tonic-gate		}
12677c478bdstevel@tonic-gate		if (thing == NULL) {
12687c478bdstevel@tonic-gate			thingsize = (n+1) * sizeof (*ssd);
12697c478bdstevel@tonic-gate			thing = kmem_alloc(thingsize, KM_NOSLEEP);
12707c478bdstevel@tonic-gate		}
12717c478bdstevel@tonic-gate		if (thing == NULL) {
12727c478bdstevel@tonic-gate			mutex_exit(&p->p_ldtlock);
12736e092beVamsi Nagineni			mutex_enter(&p->p_lock);
12747c478bdstevel@tonic-gate			prunlock(pnp);
12757c478bdstevel@tonic-gate			goto startover;
12767c478bdstevel@tonic-gate		}
12777c478bdstevel@tonic-gate
12787c478bdstevel@tonic-gate		ssd = thing;
12797c478bdstevel@tonic-gate		thing = NULL;
12807c478bdstevel@tonic-gate		if (n != 0)
12817c478bdstevel@tonic-gate			prgetldt(p, ssd);
12827c478bdstevel@tonic-gate		mutex_exit(&p->p_ldtlock);
12836e092beVamsi Nagineni		mutex_enter(&p->p_lock);
12847c478bdstevel@tonic-gate		prunlock(pnp);
12857c478bdstevel@tonic-gate
12867c478bdstevel@tonic-gate		/* mark the end of the list with a null entry */
12877c478bdstevel@tonic-gate		bzero(&ssd[n], sizeof (*ssd));
12887c478bdstevel@tonic-gate		if (copyout(ssd, cmaddr, (n+1) * sizeof (*ssd)))
12897c478bdstevel@tonic-gate			error = EFAULT;
12907c478bdstevel@tonic-gate		kmem_free(ssd, (n+1) * sizeof (*ssd));
12917c478bdstevel@tonic-gate		break;
12927c478bdstevel@tonic-gate	}
12937c478bdstevel@tonic-gate#endif	/* __i386 || __amd64 */
12947c478bdstevel@tonic-gate
12957c478bdstevel@tonic-gate#if defined(__sparc)
12967c478bdstevel@tonic-gate	case PIOCGWIN:		/* get gwindows_t (see sys/reg.h) */
12977c478bdstevel@tonic-gate	{
12987c478bdstevel@tonic-gate		gwindows_t *gwp = thing;
12997c478bdstevel@tonic-gate
13007c478bdstevel@tonic-gate		/* drop p->p_lock while touching the stack */
13017c478bdstevel@tonic-gate		mutex_exit(&p->p_lock);
13027c478bdstevel@tonic-gate		bzero(gwp, sizeof (*gwp));
13037c478bdstevel@tonic-gate		prgetwindows(lwp, gwp);
13047c478bdstevel@tonic-gate		mutex_enter(&p->p_lock);
13057c478bdstevel@tonic-gate		prunlock(pnp);
13067c478bdstevel@tonic-gate		if (copyout(gwp, cmaddr, sizeof (*gwp)))
13077c478bdstevel@tonic-gate			error = EFAULT;
13087c478bdstevel@tonic-gate		kmem_free(gwp, sizeof (gwindows_t));
13097c478bdstevel@tonic-gate		thing = NULL;
13107c478bdstevel@tonic-gate		break;
13117c478bdstevel@tonic-gate	}
13127c478bdstevel@tonic-gate#endif	/* __sparc */
13137c478bdstevel@tonic-gate
13147c478bdstevel@tonic-gate	default:
13157c478bdstevel@tonic-gate		prunlock(pnp);
13167c478bdstevel@tonic-gate		error = EINVAL;
13177c478bdstevel@tonic-gate		break;
13187c478bdstevel@tonic-gate
13197c478bdstevel@tonic-gate	}
13207c478bdstevel@tonic-gate
13217c478bdstevel@tonic-gate	ASSERT(thing == NULL);
13227c478bdstevel@tonic-gate	ASSERT(xpnp == NULL);
13237c478bdstevel@tonic-gate	return (error);
13247c478bdstevel@tonic-gate}
13257c478bdstevel@tonic-gate
13267c478bdstevel@tonic-gate#ifdef _SYSCALL32_IMPL
13277c478bdstevel@tonic-gate
1328870619efrankhostatic int oprgetmap32(proc_t *, list_t *);
13297c478bdstevel@tonic-gate
13307c478bdstevel@tonic-gatevoid
13317c478bdstevel@tonic-gateoprgetstatus32(kthread_t *t, prstatus32_t *sp, zone_t *zp)
13327c478bdstevel@tonic-gate{
13337c478bdstevel@tonic-gate	proc_t *p = ttoproc(t);
13347c478bdstevel@tonic-gate	klwp_t *lwp = ttolwp(t);
13357c478bdstevel@tonic-gate	int32_t flags;
13367c478bdstevel@tonic-gate	user_t *up;
13377c478bdstevel@tonic-gate	ulong_t instr;
13387c478bdstevel@tonic-gate
13397c478bdstevel@tonic-gate	ASSERT(MUTEX_HELD(&p->p_lock));
13407c478bdstevel@tonic-gate
13417c478bdstevel@tonic-gate	up = PTOU(p);
13427c478bdstevel@tonic-gate	bzero(sp, sizeof (*sp));
13437c478bdstevel@tonic-gate	flags = 0L;
13447c478bdstevel@tonic-gate	if (t->t_state == TS_STOPPED) {
13457c478bdstevel@tonic-gate		flags |= PR_STOPPED;
13467c478bdstevel@tonic-gate		if ((t->t_schedflag & TS_PSTART) == 0)
13477c478bdstevel@tonic-gate			flags |= PR_ISTOP;
13487c478bdstevel@tonic-gate	} else if (VSTOPPED(t)) {
13497c478bdstevel@tonic-gate		flags |= PR_STOPPED|PR_ISTOP;
13507c478bdstevel@tonic-gate	}
13517c478bdstevel@tonic-gate	if (!(flags & PR_ISTOP) && (t->t_proc_flag & TP_PRSTOP))
13527c478bdstevel@tonic-gate		flags |= PR_DSTOP;
13537c478bdstevel@tonic-gate	if (lwp->lwp_asleep)
13547c478bdstevel@tonic-gate		flags |= PR_ASLEEP;
13557c478bdstevel@tonic-gate	if (p->p_proc_flag & P_PR_FORK)
13567c478bdstevel@tonic-gate		flags |= PR_FORK;
13577c478bdstevel@tonic-gate	if (p->p_proc_flag & P_PR_RUNLCL)
13587c478bdstevel@tonic-gate		flags |= PR_RLC;
13597c478bdstevel@tonic-gate	if (p->p_proc_flag & P_PR_KILLCL)
13607c478bdstevel@tonic-gate		flags |= PR_KLC;
13617c478bdstevel@tonic-gate	if (p->p_proc_flag & P_PR_ASYNC)
13627c478bdstevel@tonic-gate		flags |= PR_ASYNC;
13637c478bdstevel@tonic-gate	if (p->p_proc_flag & P_PR_BPTADJ)
13647c478bdstevel@tonic-gate		flags |= PR_BPTADJ;
13657c478bdstevel@tonic-gate	if (p->p_proc_flag & P_PR_PTRACE)
13667c478bdstevel@tonic-gate		flags |= PR_PCOMPAT;
13677c478bdstevel@tonic-gate	if (t->t_proc_flag & TP_MSACCT)
13687c478bdstevel@tonic-gate		flags |= PR_MSACCT;
13697c478bdstevel@tonic-gate	sp->pr_flags = flags;
13707c478bdstevel@tonic-gate	if (VSTOPPED(t)) {
13717c478bdstevel@tonic-gate		sp->pr_why   = PR_REQUESTED;
13727c478bdstevel@tonic-gate		sp->pr_what  = 0;
13737c478bdstevel@tonic-gate	} else {
13747c478bdstevel@tonic-gate		sp->pr_why   = t->t_whystop;
13757c478bdstevel@tonic-gate		sp->pr_what  = t->t_whatstop;
13767c478bdstevel@tonic-gate	}
13777c478bdstevel@tonic-gate
13787c478bdstevel@tonic-gate	if (t->t_whystop == PR_FAULTED) {
13797c478bdstevel@tonic-gate		siginfo_kto32(&lwp->lwp_siginfo, &sp->pr_info);
13807c478bdstevel@tonic-gate		if (t->t_whatstop == FLTPAGE)
13817c478bdstevel@tonic-gate			sp->pr_info.si_addr =
13827c478bdstevel@tonic-gate			    (caddr32_t)(uintptr_t)lwp->lwp_siginfo.si_addr;
13837c478bdstevel@tonic-gate	} else if (lwp->lwp_curinfo)
13847c478bdstevel@tonic-gate		siginfo_kto32(&lwp->lwp_curinfo->sq_info, &sp->pr_info);
13857c478bdstevel@tonic-gate
13867c478bdstevel@tonic-gate	if (SI_FROMUSER(&lwp->lwp_siginfo) && zp->zone_id != GLOBAL_ZONEID &&
13877c478bdstevel@tonic-gate	    sp->pr_info.si_zoneid != zp->zone_id) {
13887c478bdstevel@tonic-gate		sp->pr_info.si_pid = zp->zone_zsched->p_pid;
13897c478bdstevel@tonic-gate		sp->pr_info.si_uid = 0;
13907c478bdstevel@tonic-gate		sp->pr_info.si_ctid = -1;
13917c478bdstevel@tonic-gate		sp->pr_info.si_zoneid = zp->zone_id;
13927c478bdstevel@tonic-gate	}
13937c478bdstevel@tonic-gate
13947c478bdstevel@tonic-gate	sp->pr_cursig  = lwp->lwp_cursig;
13957c478bdstevel@tonic-gate	prassignset(&sp->pr_sigpend, &p->p_sig);
13967c478bdstevel@tonic-gate	prassignset(&sp->pr_lwppend, &t->t_sig);
139772a6dc1Patrick Mooney	prgethold(t, &sp->pr_sighold);
13987c478bdstevel@tonic-gate	sp->pr_altstack.ss_sp =
13997c478bdstevel@tonic-gate	    (caddr32_t)(uintptr_t)lwp->lwp_sigaltstack.ss_sp;
14007c478bdstevel@tonic-gate	sp->pr_altstack.ss_size = (size32_t)lwp->lwp_sigaltstack.ss_size;
14017c478bdstevel@tonic-gate	sp->pr_altstack.ss_flags = (int32_t)lwp->lwp_sigaltstack.ss_flags;
14027c478bdstevel@tonic-gate	prgetaction32(p, up, lwp->lwp_cursig, &sp->pr_action);
14037c478bdstevel@tonic-gate	sp->pr_pid   = p->p_pid;
14047c478bdstevel@tonic-gate	if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
14057c478bdstevel@tonic-gate	    (p->p_flag & SZONETOP)) {
14067c478bdstevel@tonic-gate		ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
14077c478bdstevel@tonic-gate		/*
14087c478bdstevel@tonic-gate		 * Inside local zones, fake zsched's pid as parent pids for
14097c478bdstevel@tonic-gate		 * processes which reference processes outside of the zone.
14107c478bdstevel@tonic-gate		 */
14117c478bdstevel@tonic-gate		sp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
14127c478bdstevel@tonic-gate	} else {
14137c478bdstevel@tonic-gate		sp->pr_ppid = p->p_ppid;
14147c478bdstevel@tonic-gate	}
14157c478bdstevel@tonic-gate	sp->pr_pgrp  = p->p_pgrp;
14167c478bdstevel@tonic-gate	sp->pr_sid   = p->p_sessp->s_sid;
14177c478bdstevel@tonic-gate	hrt2ts32(mstate_aggr_state(p, LMS_USER), &sp->pr_utime);
14187c478bdstevel@tonic-gate	hrt2ts32(mstate_aggr_state(p, LMS_SYSTEM), &sp->pr_stime);
14197c478bdstevel@tonic-gate	TICK_TO_TIMESTRUC32(p->p_cutime, &sp->pr_cutime);
14207c478bdstevel@tonic-gate	TICK_TO_TIMESTRUC32(p->p_cstime, &sp->pr_cstime);
14217c478bdstevel@tonic-gate	(void) strncpy(sp->pr_clname, sclass[t->t_cid].cl_name,
142225b463cethindra	    sizeof (sp->pr_clname) - 1);
14237c478bdstevel@tonic-gate	sp->pr_who = t->t_tid;
14247c478bdstevel@tonic-gate	sp->pr_nlwp = p->p_lwpcnt;
14257c478bdstevel@tonic-gate	sp->pr_brkbase = (caddr32_t)(uintptr_t)p->p_brkbase;
14267c478bdstevel@tonic-gate	sp->pr_brksize = (size32_t)p->p_brksize;
14277c478bdstevel@tonic-gate	sp->pr_stkbase = (caddr32_t)(uintptr_t)prgetstackbase(p);
14287c478bdstevel@tonic-gate	sp->pr_stksize = (size32_t)p->p_stksize;
14297c478bdstevel@tonic-gate	sp->pr_oldcontext = (caddr32_t)lwp->lwp_oldcontext;
14307c478bdstevel@tonic-gate	sp->pr_processor = t->t_cpu->cpu_id;
14317c478bdstevel@tonic-gate	sp->pr_bind = t->t_bind_cpu;
14327c478bdstevel@tonic-gate
14337c478bdstevel@tonic-gate	/*
14347c478bdstevel@tonic-gate	 * Fetch the current instruction, if not a system process.
14357c478bdstevel@tonic-gate	 * We don't attempt this unless the lwp is stopped.
14367c478bdstevel@tonic-gate	 */
14377c478bdstevel@tonic-gate	if ((p->p_flag & SSYS) || p->p_as == &kas)
14387c478bdstevel@tonic-gate		sp->pr_flags |= (PR_ISSYS|PR_PCINVAL);
14397c478bdstevel@tonic-gate	else if (!(flags & PR_STOPPED))
14407c478bdstevel@tonic-gate		sp->pr_flags |= PR_PCINVAL;
14417c478bdstevel@tonic-gate	else if (!prfetchinstr(lwp, &instr))
14427c478bdstevel@tonic-gate		sp->pr_flags |= PR_PCINVAL;
14437c478bdstevel@tonic-gate	else
14447c478bdstevel@tonic-gate		sp->pr_instr = (uint32_t)instr;
14457c478bdstevel@tonic-gate
14467c478bdstevel@tonic-gate	/*
14477c478bdstevel@tonic-gate	 * Drop p_lock while touching the lwp's stack.
14487c478bdstevel@tonic-gate	 */
14497c478bdstevel@tonic-gate	mutex_exit(&p->p_lock);
14507c478bdstevel@tonic-gate	if (prisstep(lwp))
14517c478bdstevel@tonic-gate		sp->pr_flags |= PR_STEP;
14527c478bdstevel@tonic-gate	if ((flags & (PR_STOPPED|PR_ASLEEP)) && t->t_sysnum) {
14537c478bdstevel@tonic-gate		int i;
14547c478bdstevel@tonic-gate		auxv_t *auxp;
14557c478bdstevel@tonic-gate
14567c478bdstevel@tonic-gate		sp->pr_syscall = get_syscall32_args(lwp,
145725b463cethindra		    (int *)sp->pr_sysarg, &i);
14587c478bdstevel@tonic-gate		sp->pr_nsysarg = (short)i;
14598fd04b8Roger A. Faulkner		if (t->t_whystop == PR_SYSEXIT && t->t_sysnum == SYS_execve) {
14607c478bdstevel@tonic-gate			sp->pr_sysarg[0] = 0;
14617c478bdstevel@tonic-gate			sp->pr_sysarg[1] = (caddr32_t)up->u_argv;
14627c478bdstevel@tonic-gate			sp->pr_sysarg[2] = (caddr32_t)up->u_envp;
14637c478bdstevel@tonic-gate			for (i = 0, auxp = up->u_auxv;
14647c478bdstevel@tonic-gate			    i < sizeof (up->u_auxv) / sizeof (up->u_auxv[0]);
14657c478bdstevel@tonic-gate			    i++, auxp++) {
14667c478bdstevel@tonic-gate				if (auxp->a_type == AT_SUN_EXECNAME) {
14677c478bdstevel@tonic-gate					sp->pr_sysarg[0] =
146825b463cethindra					    (caddr32_t)
146925b463cethindra					    (uintptr_t)auxp->a_un.a_ptr;
14707c478bdstevel@tonic-gate					break;
14717c478bdstevel@tonic-gate				}
14727c478bdstevel@tonic-gate			}
14737c478bdstevel@tonic-gate		}
14747c478bdstevel@tonic-gate	}
14757c478bdstevel@tonic-gate	if ((flags & PR_STOPPED) || t == curthread)
14767c478bdstevel@tonic-gate		prgetprregs32(lwp, sp->pr_reg);
14777c478bdstevel@tonic-gate	mutex_enter(&p->p_lock);
14787c478bdstevel@tonic-gate}
14797c478bdstevel@tonic-gate
14807c478bdstevel@tonic-gatevoid
14817c478bdstevel@tonic-gateoprgetpsinfo32(proc_t *p, prpsinfo32_t *psp, kthread_t *tp)
14827c478bdstevel@tonic-gate{
14837c478bdstevel@tonic-gate	kthread_t *t;
14847c478bdstevel@tonic-gate	char c, state;
14857c478bdstevel@tonic-gate	user_t *up;
14867c478bdstevel@tonic-gate	dev_t d;
14877c478bdstevel@tonic-gate	uint64_t pct;
14887c478bdstevel@tonic-gate	int retval, niceval;
14897c478bdstevel@tonic-gate	cred_t *cred;
14907c478bdstevel@tonic-gate	struct as *as;
14917c478bdstevel@tonic-gate	hrtime_t hrutime, hrstime, cur_time;
14927c478bdstevel@tonic-gate
14937c478bdstevel@tonic-gate	ASSERT(MUTEX_HELD(&p->p_lock));
14947c478bdstevel@tonic-gate
14957c478bdstevel@tonic-gate	bzero(psp, sizeof (*psp));
14967c478bdstevel@tonic-gate
14977c478bdstevel@tonic-gate	if ((t = tp) == NULL)
14987c478bdstevel@tonic-gate		t = prchoose(p);	/* returns locked thread */
14997c478bdstevel@tonic-gate	else
15007c478bdstevel@tonic-gate		thread_lock(t);
15017c478bdstevel@tonic-gate
15027c478bdstevel@tonic-gate	/* kludge: map thread state enum into process state enum */
15037c478bdstevel@tonic-gate
15047c478bdstevel@tonic-gate	if (t == NULL) {
15057c478bdstevel@tonic-gate		state = TS_ZOMB;
15067c478bdstevel@tonic-gate	} else {
15077c478bdstevel@tonic-gate		state = VSTOPPED(t) ? TS_STOPPED : t->t_state;
15087c478bdstevel@tonic-gate		thread_unlock(t);
15097c478bdstevel@tonic-gate	}
15107c478bdstevel@tonic-gate
15117c478bdstevel@tonic-gate	switch (state) {
15127c478bdstevel@tonic-gate	case TS_SLEEP:		state = SSLEEP;		break;
15137c478bdstevel@tonic-gate	case TS_RUN:		state = SRUN;		break;
15147c478bdstevel@tonic-gate	case TS_ONPROC:		state = SONPROC;	break;
15157c478bdstevel@tonic-gate	case TS_ZOMB:		state = SZOMB;		break;
15167c478bdstevel@tonic-gate	case TS_STOPPED:	state = SSTOP;		break;
15177c478bdstevel@tonic-gate	default:		state = 0;		break;
15187c478bdstevel@tonic-gate	}
15197c478bdstevel@tonic-gate	switch (state) {
15207c478bdstevel@tonic-gate	case SSLEEP:	c = 'S';	break;
15217c478bdstevel@tonic-gate	case SRUN:	c = 'R';	break;
15227c478bdstevel@tonic-gate	case SZOMB:	c = 'Z';	break;
15237c478bdstevel@tonic-gate	case SSTOP:	c = 'T';	break;
15247c478bdstevel@tonic-gate	case SIDL:	c = 'I';	break;
15257c478bdstevel@tonic-gate	case SONPROC:	c = 'O';	break;
15267c478bdstevel@tonic-gate#ifdef SXBRK
15277c478bdstevel@tonic-gate	case SXBRK:	c = 'X';	break;
15287c478bdstevel@tonic-gate#endif
15297c478bdstevel@tonic-gate	default:	c = '?';	break;
15307c478bdstevel@tonic-gate	}
15317c478bdstevel@tonic-gate	psp->pr_state = state;
15327c478bdstevel@tonic-gate	psp->pr_sname = c;
15337c478bdstevel@tonic-gate	psp->pr_zomb = (state == SZOMB);
15347c478bdstevel@tonic-gate	/*
15357c478bdstevel@tonic-gate	 * only export SSYS and SMSACCT; everything else is off-limits to
15367c478bdstevel@tonic-gate	 * userland apps.
15377c478bdstevel@tonic-gate	 */
15387c478bdstevel@tonic-gate	psp->pr_flag = p->p_flag & (SSYS | SMSACCT);
15397c478bdstevel@tonic-gate
15407c478bdstevel@tonic-gate	mutex_enter(&p->p_crlock);
15417c478bdstevel@tonic-gate	cred = p->p_cred;
15427c478bdstevel@tonic-gate	psp->pr_uid = crgetruid(cred);
15437c478bdstevel@tonic-gate	psp->pr_gid = crgetrgid(cred);
15447c478bdstevel@tonic-gate	psp->pr_euid = crgetuid(cred);
15457c478bdstevel@tonic-gate	psp->pr_egid = crgetgid(cred);
15467c478bdstevel@tonic-gate	mutex_exit(&p->p_crlock);
15477c478bdstevel@tonic-gate
15487c478bdstevel@tonic-gate	psp->pr_pid = p->p_pid;
15497c478bdstevel@tonic-gate	if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
15507c478bdstevel@tonic-gate	    (p->p_flag & SZONETOP)) {
15517c478bdstevel@tonic-gate		ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
15527c478bdstevel@tonic-gate		/*
15537c478bdstevel@tonic-gate		 * Inside local zones, fake zsched's pid as parent pids for
15547c478bdstevel@tonic-gate		 * processes which reference processes outside of the zone.
15557c478bdstevel@tonic-gate		 */
15567c478bdstevel@tonic-gate		psp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
15577c478bdstevel@tonic-gate	} else {
15587c478bdstevel@tonic-gate		psp->pr_ppid = p->p_ppid;
15597c478bdstevel@tonic-gate	}
15607c478bdstevel@tonic-gate	psp->pr_pgrp = p->p_pgrp;
15617c478bdstevel@tonic-gate	psp->pr_sid = p->p_sessp->s_sid;
15627c478bdstevel@tonic-gate	psp->pr_addr = 0;	/* cannot represent 64-bit addr in 32 bits */
15637c478bdstevel@tonic-gate	hrutime = mstate_aggr_state(p, LMS_USER);
15647c478bdstevel@tonic-gate	hrstime = mstate_aggr_state(p, LMS_SYSTEM);
15657c478bdstevel@tonic-gate	hrt2ts32(hrutime + hrstime, &psp->pr_time);
15667c478bdstevel@tonic-gate	TICK_TO_TIMESTRUC32(p->p_cutime + p->p_cstime, &psp->pr_ctime);
15677c478bdstevel@tonic-gate	switch (p->p_model) {
15687c478bdstevel@tonic-gate	case DATAMODEL_ILP32:
15697c478bdstevel@tonic-gate		psp->pr_dmodel = PR_MODEL_ILP32;
15707c478bdstevel@tonic-gate		break;
15717c478bdstevel@tonic-gate	case DATAMODEL_LP64:
15727c478bdstevel@tonic-gate		psp->pr_dmodel = PR_MODEL_LP64;
15737c478bdstevel@tonic-gate		break;
15747c478bdstevel@tonic-gate	}
15757c478bdstevel@tonic-gate	if (state == SZOMB || t == NULL) {
15767c478bdstevel@tonic-gate		int wcode = p->p_wcode;		/* must be atomic read */
15777c478bdstevel@tonic-gate
15787c478bdstevel@tonic-gate		if (wcode)
15797c478bdstevel@tonic-gate			psp->pr_wstat = wstat(wcode, p->p_wdata);
15807c478bdstevel@tonic-gate		psp->pr_lttydev = PRNODEV32;
15817c478bdstevel@tonic-gate		psp->pr_ottydev = (o_dev_t)PRNODEV32;
15827c478bdstevel@tonic-gate		psp->pr_size = 0;
15837c478bdstevel@tonic-gate		psp->pr_rssize = 0;
15847c478bdstevel@tonic-gate		psp->pr_pctmem = 0;
15857c478bdstevel@tonic-gate	} else {
15867c478bdstevel@tonic-gate		up = PTOU(p);
15877c478bdstevel@tonic-gate		psp->pr_wchan = 0;	/* cannot represent in 32 bits */
15887c478bdstevel@tonic-gate		psp->pr_pri = t->t_pri;
15897c478bdstevel@tonic-gate		(void) strncpy(psp->pr_clname, sclass[t->t_cid].cl_name,
159025b463cethindra		    sizeof (psp->pr_clname) - 1);
15917c478bdstevel@tonic-gate		retval = CL_DONICE(t, NULL, 0, &niceval);
15927c478bdstevel@tonic-gate		if (retval == 0) {
15937c478bdstevel@tonic-gate			psp->pr_oldpri = v.v_maxsyspri - psp->pr_pri;
15947c478bdstevel@tonic-gate			psp->pr_nice = niceval + NZERO;
15957c478bdstevel@tonic-gate		} else {
15967c478bdstevel@tonic-gate			psp->pr_oldpri = 0;
15977c478bdstevel@tonic-gate			psp->pr_nice = 0;
15987c478bdstevel@tonic-gate		}
15997c478bdstevel@tonic-gate		d = cttydev(p);
16007c478bdstevel@tonic-gate#ifdef sun
16017c478bdstevel@tonic-gate		{
16027c478bdstevel@tonic-gate			extern dev_t rwsconsdev, rconsdev, uconsdev;
16037c478bdstevel@tonic-gate			/*
16047c478bdstevel@tonic-gate			 * If the controlling terminal is the real
16057c478bdstevel@tonic-gate			 * or workstation console device, map to what the
160625b463cethindra			 * user thinks is the console device. Handle case when
160725b463cethindra			 * rwsconsdev or rconsdev is set to NODEV for Starfire.
16087c478bdstevel@tonic-gate			 */
160925b463cethindra			if ((d == rwsconsdev || d == rconsdev) && d != NODEV)
16107c478bdstevel@tonic-gate				d = uconsdev;
16117c478bdstevel@tonic-gate		}
16127c478bdstevel@tonic-gate#endif
16137c478bdstevel@tonic-gate		(void) cmpldev(&psp->pr_lttydev, d);
16147c478bdstevel@tonic-gate		psp->pr_ottydev = cmpdev(d);
16157c478bdstevel@tonic-gate		TIMESPEC_TO_TIMESPEC32(&psp->pr_start, &up->u_start);
16167c478bdstevel@tonic-gate		bcopy(up->u_comm, psp->pr_fname,
16177c478bdstevel@tonic-gate		    MIN(sizeof (up->u_comm), sizeof (psp->pr_fname)-1));
16187c478bdstevel@tonic-gate		bcopy(up->u_psargs, psp->pr_psargs,
16197c478bdstevel@tonic-gate		    MIN(PRARGSZ-1, PSARGSZ));
16207c478bdstevel@tonic-gate		psp->pr_syscall = t->t_sysnum;
16217c478bdstevel@tonic-gate		psp->pr_argc = up->u_argc;
16227c478bdstevel@tonic-gate		psp->pr_argv = (caddr32_t)up->u_argv;
16237c478bdstevel@tonic-gate		psp->pr_envp = (caddr32_t)up->u_envp;
16247c478bdstevel@tonic-gate
16257c478bdstevel@tonic-gate		/* compute %cpu for the lwp or process */
16267c478bdstevel@tonic-gate		pct = 0;
16277c478bdstevel@tonic-gate		if ((t = tp) == NULL)
16287c478bdstevel@tonic-gate			t = p->p_tlist;
16297c478bdstevel@tonic-gate		cur_time = gethrtime_unscaled();
16307c478bdstevel@tonic-gate		do {
16317c478bdstevel@tonic-gate			pct += cpu_update_pct(t, cur_time);
16327c478bdstevel@tonic-gate			if (tp != NULL)		/* just do the one lwp */
16337c478bdstevel@tonic-gate				break;
16347c478bdstevel@tonic-gate		} while ((t = t->t_forw) != p->p_tlist);
16357c478bdstevel@tonic-gate
16367c478bdstevel@tonic-gate		psp->pr_pctcpu = prgetpctcpu(pct);
16377c478bdstevel@tonic-gate		psp->pr_cpu = (psp->pr_pctcpu*100 + 0x6000) >> 15; /* [0..99] */
16387c478bdstevel@tonic-gate		if (psp->pr_cpu > 99)
16397c478bdstevel@tonic-gate			psp->pr_cpu = 99;
16407c478bdstevel@tonic-gate
16417c478bdstevel@tonic-gate		if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
16427c478bdstevel@tonic-gate			psp->pr_size = 0;
16437c478bdstevel@tonic-gate			psp->pr_rssize = 0;
16447c478bdstevel@tonic-gate			psp->pr_pctmem = 0;
16457c478bdstevel@tonic-gate		} else {
16467c478bdstevel@tonic-gate			mutex_exit(&p->p_lock);
1647dc32d87Josef 'Jeff' Sipek			AS_LOCK_ENTER(as, RW_READER);
16484068821Sudheer A			psp->pr_size = (size32_t)btopr(as->a_resvsize);
16497c478bdstevel@tonic-gate			psp->pr_rssize = (size32_t)rm_asrss(as);
16507c478bdstevel@tonic-gate			psp->pr_pctmem = rm_pctmemory(as);
1651dc32d87Josef 'Jeff' Sipek			AS_LOCK_EXIT(as);
16527c478bdstevel@tonic-gate			mutex_enter(&p->p_lock);
16537c478bdstevel@tonic-gate		}
16547c478bdstevel@tonic-gate	}
16557c478bdstevel@tonic-gate	psp->pr_bysize = (size32_t)ptob(psp->pr_size);
16567c478bdstevel@tonic-gate	psp->pr_byrssize = (size32_t)ptob(psp->pr_rssize);
16577c478bdstevel@tonic-gate
16587c478bdstevel@tonic-gate	/*
16597c478bdstevel@tonic-gate	 * If we are looking at an LP64 process, zero out
16607c478bdstevel@tonic-gate	 * the fields that cannot be represented in ILP32.
16617c478bdstevel@tonic-gate	 */
16627c478bdstevel@tonic-gate	if (p->p_model != DATAMODEL_ILP32) {
16637c478bdstevel@tonic-gate		psp->pr_size = 0;
16647c478bdstevel@tonic-gate		psp->pr_rssize = 0;
16657c478bdstevel@tonic-gate		psp->pr_bysize = 0;
16667c478bdstevel@tonic-gate		psp->pr_byrssize = 0;
16677c478bdstevel@tonic-gate		psp->pr_argv = 0;
16687c478bdstevel@tonic-gate		psp->pr_envp = 0;
16697c478bdstevel@tonic-gate	}
16707c478bdstevel@tonic-gate}
16717c478bdstevel@tonic-gate
1672da6c28aamw/*ARGSUSED*/
16737c478bdstevel@tonic-gatestatic int
167472a6dc1Patrick Mooneyprioctl32(struct vnode *vp, int cmd, intptr_t arg, int flag, cred_t *cr,
167572a6dc1Patrick Mooney    int *rvalp, caller_context_t *ct)
16767c478bdstevel@tonic-gate{
1677eb9dbf0Roger A. Faulkner	int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
16787c478bdstevel@tonic-gate	caddr_t cmaddr = (caddr_t)arg;
16797c478bdstevel@tonic-gate	proc_t *p;
16807c478bdstevel@tonic-gate	user_t *up;
16817c478bdstevel@tonic-gate	kthread_t *t;
16827c478bdstevel@tonic-gate	klwp_t *lwp;
16837c478bdstevel@tonic-gate	prnode_t *pnp = VTOP(vp);
16847c478bdstevel@tonic-gate	prcommon_t *pcp;
16857c478bdstevel@tonic-gate	prnode_t *xpnp = NULL;
16867c478bdstevel@tonic-gate	int error;
16877c478bdstevel@tonic-gate	int zdisp;
16887c478bdstevel@tonic-gate	void *thing = NULL;
16897c478bdstevel@tonic-gate	size_t thingsize = 0;
16907c478bdstevel@tonic-gate
16917c478bdstevel@tonic-gate	/*
16927c478bdstevel@tonic-gate	 * For copyin()/copyout().
16937c478bdstevel@tonic-gate	 */
16947c478bdstevel@tonic-gate	union {
16957c478bdstevel@tonic-gate		caddr32_t	va;
16967c478bdstevel@tonic-gate		int		signo;
16977c478bdstevel@tonic-gate		int		nice;
16987c478bdstevel@tonic-gate		uint_t		lwpid;
16997c478bdstevel@tonic-gate		int32_t		flags;
17007c478bdstevel@tonic-gate		prstatus32_t	prstat;
17017c478bdstevel@tonic-gate		prrun32_t	prrun;
17027c478bdstevel@tonic-gate		sigset_t	smask;
17037c478bdstevel@tonic-gate		siginfo32_t	info;
17047c478bdstevel@tonic-gate		sysset_t	prmask;
17057c478bdstevel@tonic-gate		prgregset32_t	regs;
17067c478bdstevel@tonic-gate		prfpregset32_t	fpregs;
17077c478bdstevel@tonic-gate		prpsinfo32_t	prps;
17087c478bdstevel@tonic-gate		sigset_t	holdmask;
17097c478bdstevel@tonic-gate		fltset_t	fltmask;
17107c478bdstevel@tonic-gate		prcred_t	prcred;
17117c478bdstevel@tonic-gate		prusage32_t	prusage;
17127c478bdstevel@tonic-gate		prhusage_t	prhusage;
17137c478bdstevel@tonic-gate		ioc_prmap32_t	prmap;
17147c478bdstevel@tonic-gate		auxv32_t	auxv[__KERN_NAUXV_IMPL];
17157c478bdstevel@tonic-gate	} un32;
17167c478bdstevel@tonic-gate
17177c478bdstevel@tonic-gate	/*
17187c478bdstevel@tonic-gate	 * Native objects for internal use.
17197c478bdstevel@tonic-gate	 */
17207c478bdstevel@tonic-gate	union {
17217c478bdstevel@tonic-gate		caddr_t		va;
17227c478bdstevel@tonic-gate		int		signo;
17237c478bdstevel@tonic-gate		int		nice;
17247c478bdstevel@tonic-gate		uint_t		lwpid;
17257c478bdstevel@tonic-gate		long		flags;
17267c478bdstevel@tonic-gate		prstatus_t	prstat;
17277c478bdstevel@tonic-gate		prrun_t		prrun;
17287c478bdstevel@tonic-gate		sigset_t	smask;
17297c478bdstevel@tonic-gate		siginfo_t	info;
17307c478bdstevel@tonic-gate		sysset_t	prmask;
17317c478bdstevel@tonic-gate		prgregset_t	regs;
17327c478bdstevel@tonic-gate		prpsinfo_t	prps;
17337c478bdstevel@tonic-gate		sigset_t	holdmask;
17347c478bdstevel@tonic-gate		fltset_t	fltmask;
17357c478bdstevel@tonic-gate		prcred_t	prcred;
17367c478bdstevel@tonic-gate		prusage_t	prusage;
17377c478bdstevel@tonic-gate		prhusage_t	prhusage;
17387c478bdstevel@tonic-gate		auxv_t		auxv[__KERN_NAUXV_IMPL];
17397c478bdstevel@tonic-gate	} un;
17407c478bdstevel@tonic-gate
17417c478bdstevel@tonic-gate	if (pnp->pr_type == PR_TMPL)
17427c478bdstevel@tonic-gate		return (prctioctl(pnp, cmd, arg, flag, cr));
17437c478bdstevel@tonic-gate
17447c478bdstevel@tonic-gate	/*
17457c478bdstevel@tonic-gate	 * Support for old /proc interface.
17467c478bdstevel@tonic-gate	 */
17477c478bdstevel@tonic-gate	if (pnp->pr_pidfile != NULL) {
17487c478bdstevel@tonic-gate		ASSERT(pnp->pr_type == PR_PIDDIR);
17497c478bdstevel@tonic-gate		vp = pnp->pr_pidfile;
17507c478bdstevel@tonic-gate		pnp = VTOP(vp);
17517c478bdstevel@tonic-gate		ASSERT(pnp->pr_type == PR_PIDFILE);
17527c478bdstevel@tonic-gate	}
17537c478bdstevel@tonic-gate
17547c478bdstevel@tonic-gate	if (pnp->pr_type != PR_PIDFILE && pnp->pr_type != PR_LWPIDFILE)
17557c478bdstevel@tonic-gate		return (ENOTTY);
17567c478bdstevel@tonic-gate
17577c478bdstevel@tonic-gate	/*
17587c478bdstevel@tonic-gate	 * Fail ioctls which are logically "write" requests unless
17597c478bdstevel@tonic-gate	 * the user has write permission.
17607c478bdstevel@tonic-gate	 */
17617c478bdstevel@tonic-gate	if ((flag & FWRITE) == 0 && isprwrioctl(cmd))
17627c478bdstevel@tonic-gate		return (EBADF);
17637c478bdstevel@tonic-gate
17647c478bdstevel@tonic-gate	/*
17657c478bdstevel@tonic-gate	 * Perform any necessary copyin() operations before
17667c478bdstevel@tonic-gate	 * locking the process.  Helps avoid deadlocks and
17677c478bdstevel@tonic-gate	 * improves performance.
17687c478bdstevel@tonic-gate	 *
17697c478bdstevel@tonic-gate	 * Also, detect invalid ioctl codes here to avoid
17707c478bdstevel@tonic-gate	 * locking a process unnnecessarily.
17717c478bdstevel@tonic-gate	 *
17727c478bdstevel@tonic-gate	 * Also, prepare to allocate space that will be needed below,
17737c478bdstevel@tonic-gate	 * case by case.
17747c478bdstevel@tonic-gate	 */
17757c478bdstevel@tonic-gate	error = 0;
17767c478bdstevel@tonic-gate	switch (cmd) {
17777c478bdstevel@tonic-gate	case PIOCGETPR:
17787c478bdstevel@tonic-gate		thingsize = sizeof (proc_t);
17797c478bdstevel@tonic-gate		break;
17807c478bdstevel@tonic-gate	case PIOCGETU:
17817c478bdstevel@tonic-gate		thingsize = sizeof (user_t);
17827c478bdstevel@tonic-gate		break;
17837c478bdstevel@tonic-gate	case PIOCSTOP:
17847c478bdstevel@tonic-gate	case PIOCWSTOP:
17857c478bdstevel@tonic-gate	case PIOCLWPIDS:
17867c478bdstevel@tonic-gate	case PIOCGTRACE:
17877c478bdstevel@tonic-gate	case PIOCGENTRY:
17887c478bdstevel@tonic-gate	case PIOCGEXIT:
17897c478bdstevel@tonic-gate	case PIOCSRLC:
17907c478bdstevel@tonic-gate	case PIOCRRLC:
17917c478bdstevel@tonic-gate	case PIOCSFORK:
17927c478bdstevel@tonic-gate	case PIOCRFORK:
17937c478bdstevel@tonic-gate	case PIOCGREG:
17947c478bdstevel@tonic-gate	case PIOCGFPREG:
17957c478bdstevel@tonic-gate	case PIOCSTATUS:
17967c478bdstevel@tonic-gate	case PIOCLSTATUS:
17977c478bdstevel@tonic-gate	case PIOCPSINFO:
17987c478bdstevel@tonic-gate	case PIOCMAXSIG:
17997c478bdstevel@tonic-gate	case PIOCGXREGSIZE:
18007c478bdstevel@tonic-gate		break;
18017c478bdstevel@tonic-gate	case PIOCSXREG:		/* set extra registers */
18027c478bdstevel@tonic-gate	case PIOCGXREG:		/* get extra registers */
18037c478bdstevel@tonic-gate#if defined(__sparc)
18047c478bdstevel@tonic-gate		thingsize = sizeof (prxregset_t);
18057c478bdstevel@tonic-gate#else
18067c478bdstevel@tonic-gate		thingsize = 0;
18077c478bdstevel@tonic-gate#endif
18087c478bdstevel@tonic-gate		break;
18097c478bdstevel@tonic-gate	case PIOCACTION:
1810eb9dbf0Roger A. Faulkner		thingsize = (nsig-1) * sizeof (struct sigaction32);
18117c478bdstevel@tonic-gate		break;
18127c478bdstevel@tonic-gate	case PIOCGHOLD:
18137c478bdstevel@tonic-gate	case PIOCNMAP:
18147c478bdstevel@tonic-gate	case PIOCMAP:
18157c478bdstevel@tonic-gate	case PIOCGFAULT:
18167c478bdstevel@tonic-gate	case PIOCCFAULT:
18177c478bdstevel@tonic-gate	case PIOCCRED:
18187c478bdstevel@tonic-gate	case PIOCGROUPS:
18197c478bdstevel@tonic-gate	case PIOCUSAGE:
18207c478bdstevel@tonic-gate	case PIOCLUSAGE:
18217c478bdstevel@tonic-gate		break;
18227c478bdstevel@tonic-gate	case PIOCOPENPD:
18237c478bdstevel@tonic-gate		/*
18247c478bdstevel@tonic-gate		 * We will need this below.
18257c478bdstevel@tonic-gate		 * Allocate it now, before locking the process.
18267c478bdstevel@tonic-gate		 */
18277c478bdstevel@tonic-gate		xpnp = prgetnode(vp, PR_OPAGEDATA);
18287c478bdstevel@tonic-gate		break;
18297c478bdstevel@tonic-gate	case PIOCNAUXV:
18307c478bdstevel@tonic-gate	case PIOCAUXV:
18317c478bdstevel@tonic-gate		break;
18327c478bdstevel@tonic-gate
18337c478bdstevel@tonic-gate#if defined(__i386) || defined(__i386_COMPAT)
18347c478bdstevel@tonic-gate	case PIOCNLDT:
18357c478bdstevel@tonic-gate	case PIOCLDT:
18367c478bdstevel@tonic-gate		break;
18377c478bdstevel@tonic-gate#endif	/* __i386 || __i386_COMPAT */
18387c478bdstevel@tonic-gate
18397c478bdstevel@tonic-gate#if defined(__sparc)
18407c478bdstevel@tonic-gate	case PIOCGWIN:
18417c478bdstevel@tonic-gate		thingsize = sizeof (gwindows32_t);
18427c478bdstevel@tonic-gate		break;
18437c478bdstevel@tonic-gate#endif	/* __sparc */
18447c478bdstevel@tonic-gate
18457c478bdstevel@tonic-gate	case PIOCOPENM:		/* open mapped object for reading */
18467c478bdstevel@tonic-gate		if (cmaddr == NULL)
1847e14d4b2Toomas Soome			un32.va = (caddr32_t)(uintptr_t)NULL;
18487c478bdstevel@tonic-gate		else if (copyin(cmaddr, &un32.va, sizeof (un32.va)))
18497c478bdstevel@tonic-gate			error = EFAULT;
18507c478bdstevel@tonic-gate		break;
18517c478bdstevel@tonic-gate
18527c478bdstevel@tonic-gate	case PIOCRUN:		/* make lwp or process runnable */
18537c478bdstevel@tonic-gate		if (cmaddr == NULL)
18547c478bdstevel@tonic-gate			un32.prrun.pr_flags = 0;
18557c478bdstevel@tonic-gate		else if (copyin(cmaddr, &un32.prrun, sizeof (un32.prrun)))
18567c478bdstevel@tonic-gate			error = EFAULT;
18577c478bdstevel@tonic-gate		break;
18587c478bdstevel@tonic-gate
18597c478bdstevel@tonic-gate	case PIOCOPENLWP:	/* return /proc lwp file descriptor */
18607c478bdstevel@tonic-gate		if (copyin(cmaddr, &un32.lwpid, sizeof (un32.lwpid)))
18617c478bdstevel@tonic-gate			error = EFAULT;
18627c478bdstevel@tonic-gate		break;
18637c478bdstevel@tonic-gate
18647c478bdstevel@tonic-gate	case PIOCSTRACE:	/* set signal trace mask */
18657c478bdstevel@tonic-gate		if (copyin(cmaddr, &un32.smask, sizeof (un32.smask)))
18667c478bdstevel@tonic-gate			error = EFAULT;
18677c478bdstevel@tonic-gate		break;
18687c478bdstevel@tonic-gate
18697c478bdstevel@tonic-gate	case PIOCSSIG:		/* set current signal */
18707c478bdstevel@tonic-gate		if (cmaddr == NULL)
18717c478bdstevel@tonic-gate			un32.info.si_signo = 0;
18727c478bdstevel@tonic-gate		else if (copyin(cmaddr, &un32.info, sizeof (un32.info)))
18737c478bdstevel@tonic-gate			error = EFAULT;
18747c478bdstevel@tonic-gate		break;
18757c478bdstevel@tonic-gate
18767c478bdstevel@tonic-gate	case PIOCKILL:		/* send signal */
18777c478bdstevel@tonic-gate	case PIOCUNKILL:	/* delete a signal */
18787c478bdstevel@tonic-gate		if (copyin(cmaddr, &un32.signo, sizeof (un32.signo)))
18797c478bdstevel@tonic-gate			error = EFAULT;
18807c478bdstevel@tonic-gate		break;
18817c478bdstevel@tonic-gate
18827c478bdstevel@tonic-gate	case PIOCNICE:		/* set nice priority */
18837c478bdstevel@tonic-gate		if (copyin(cmaddr, &un32.nice, sizeof (un32.nice)))
18847c478bdstevel@tonic-gate			error = EFAULT;
18857c478bdstevel@tonic-gate		break;
18867c478bdstevel@tonic-gate
18877c478bdstevel@tonic-gate	case PIOCSENTRY:	/* set syscall entry bit mask */
18887c478bdstevel@tonic-gate	case PIOCSEXIT:		/* set syscall exit bit mask */
18897c478bdstevel@tonic-gate		if (copyin(cmaddr, &un32.prmask, sizeof (un32.prmask)))
18907c478bdstevel@tonic-gate			error = EFAULT;
18917c478bdstevel@tonic-gate		break;
18927c478bdstevel@tonic-gate
18937c478bdstevel@tonic-gate	case PIOCSET:		/* set process flags */
18947c478bdstevel@tonic-gate	case PIOCRESET:		/* reset process flags */
18957c478bdstevel@tonic-gate		if (copyin(cmaddr, &un32.flags, sizeof (un32.flags)))
18967c478bdstevel@tonic-gate			error = EFAULT;
18977c478bdstevel@tonic-gate		break;
18987c478bdstevel@tonic-gate
18997c478bdstevel@tonic-gate	case PIOCSREG:		/* set general registers */
19007c478bdstevel@tonic-gate		if (copyin(cmaddr, un32.regs, sizeof (un32.regs)))
19017c478bdstevel@tonic-gate			error = EFAULT;
19027c478bdstevel@tonic-gate		break;
19037c478bdstevel@tonic-gate
19047c478bdstevel@tonic-gate	case PIOCSFPREG:	/* set floating-point registers */
19057c478bdstevel@tonic-gate		if (copyin(cmaddr, &un32.fpregs, sizeof (un32.fpregs)))
19067c478bdstevel@tonic-gate			error = EFAULT;
19077c478bdstevel@tonic-gate		break;
19087c478bdstevel@tonic-gate
19097c478bdstevel@tonic-gate	case PIOCSHOLD:		/* set signal-hold mask */
19107c478bdstevel@tonic-gate		if (copyin(cmaddr, &un32.holdmask, sizeof (un32.holdmask)))
19117c478bdstevel@tonic-gate			error = EFAULT;
19127c478bdstevel@tonic-gate		break;
19137c478bdstevel@tonic-gate
19147c478bdstevel@tonic-gate	case PIOCSFAULT:	/* set mask of traced faults */
19157c478bdstevel@tonic-gate		if (copyin(cmaddr, &un32.fltmask, sizeof (un32.fltmask)))
19167c478bdstevel@tonic-gate			error = EFAULT;
19177c478bdstevel@tonic-gate		break;
19187c478bdstevel@tonic-gate
19197c478bdstevel@tonic-gate	default:
19207c478bdstevel@tonic-gate		error = EINVAL;
19217c478bdstevel@tonic-gate		break;
19227c478bdstevel@tonic-gate	}
19237c478bdstevel@tonic-gate
19247c478bdstevel@tonic-gate	if (error)
19257c478bdstevel@tonic-gate		return (error);
19267c478bdstevel@tonic-gate
19277c478bdstevel@tonic-gatestartover:
19287c478bdstevel@tonic-gate	/*
19297c478bdstevel@tonic-gate	 * If we need kmem_alloc()d space then we allocate it now, before
19307c478bdstevel@tonic-gate	 * grabbing the process lock.  Using kmem_alloc(KM_SLEEP) while
19317c478bdstevel@tonic-gate	 * holding the process lock leads to deadlock with the clock thread.
19327c478bdstevel@tonic-gate	 * (The clock thread wakes up the pageout daemon to free up space.
19337c478bdstevel@tonic-gate	 * If the clock thread blocks behind us and we are sleeping waiting
19347c478bdstevel@tonic-gate	 * for space, then space may never become available.)
19357c478bdstevel@tonic-gate	 */
19367c478bdstevel@tonic-gate	if (thingsize) {
19377c478bdstevel@tonic-gate		ASSERT(thing == NULL);
19387c478bdstevel@tonic-gate		thing = kmem_alloc(thingsize, KM_SLEEP);
19397c478bdstevel@tonic-gate	}
19407c478bdstevel@tonic-gate
19417c478bdstevel@tonic-gate	switch (cmd) {
19427c478bdstevel@tonic-gate	case PIOCPSINFO:
19437c478bdstevel@tonic-gate	case PIOCGETPR:
19447c478bdstevel@tonic-gate	case PIOCUSAGE:
19457c478bdstevel@tonic-gate	case PIOCLUSAGE:
19467c478bdstevel@tonic-gate		zdisp = ZYES;
19477c478bdstevel@tonic-gate		break;
19487c478bdstevel@tonic-gate	case PIOCSXREG:		/* set extra registers */
19497c478bdstevel@tonic-gate		/*
19507c478bdstevel@tonic-gate		 * perform copyin before grabbing the process lock
19517c478bdstevel@tonic-gate		 */
19527c478bdstevel@tonic-gate		if (thing) {
19537c478bdstevel@tonic-gate			if (copyin(cmaddr, thing, thingsize)) {
19547c478bdstevel@tonic-gate				kmem_free(thing, thingsize);
19557c478bdstevel@tonic-gate				return (EFAULT);
19567c478bdstevel@tonic-gate			}
19577c478bdstevel@tonic-gate		}
19587c478bdstevel@tonic-gate		/* fall through... */
19597c478bdstevel@tonic-gate	default:
19607c478bdstevel@tonic-gate		zdisp = ZNO;
19617c478bdstevel@tonic-gate		break;
19627c478bdstevel@tonic-gate	}
19637c478bdstevel@tonic-gate
19647c478bdstevel@tonic-gate	if ((error = prlock(pnp, zdisp)) != 0) {
19657c478bdstevel@tonic-gate		if (thing != NULL)
19667c478bdstevel@tonic-gate			kmem_free(thing, thingsize);
19677c478bdstevel@tonic-gate		if (xpnp)
19687c478bdstevel@tonic-gate			prfreenode(xpnp);
19697c478bdstevel@tonic-gate		return (error);
19707c478bdstevel@tonic-gate	}
19717c478bdstevel@tonic-gate
19727c478bdstevel@tonic-gate	pcp = pnp->pr_common;
19737c478bdstevel@tonic-gate	p = pcp->prc_proc;
19747c478bdstevel@tonic-gate	ASSERT(p != NULL);
19757c478bdstevel@tonic-gate
19767c478bdstevel@tonic-gate	/*
19777c478bdstevel@tonic-gate	 * Choose a thread/lwp for the operation.
19787c478bdstevel@tonic-gate	 */
19797c478bdstevel@tonic-gate	if (zdisp == ZNO && cmd != PIOCSTOP && cmd != PIOCWSTOP) {
19807c478bdstevel@tonic-gate		if (pnp->pr_type == PR_LWPIDFILE && cmd != PIOCLSTATUS) {
19817c478bdstevel@tonic-gate			t = pcp->prc_thread;
19827c478bdstevel@tonic-gate			ASSERT(t != NULL);
19837c478bdstevel@tonic-gate		} else {
19847c478bdstevel@tonic-gate			t = prchoose(p);	/* returns locked thread */
19857c478bdstevel@tonic-gate			ASSERT(t != NULL);
19867c478bdstevel@tonic-gate			thread_unlock(t);
19877c478bdstevel@tonic-gate		}
19887c478bdstevel@tonic-gate		lwp = ttolwp(t);
19897c478bdstevel@tonic-gate	}
19907c478bdstevel@tonic-gate
19917c478bdstevel@tonic-gate	error = 0;
19927c478bdstevel@tonic-gate	switch (cmd) {
19937c478bdstevel@tonic-gate
19947c478bdstevel@tonic-gate	case PIOCGETPR:		/* read struct proc */
19957c478bdstevel@tonic-gate	{
19967c478bdstevel@tonic-gate		proc_t *prp = thing;
19977c478bdstevel@tonic-gate
19987c478bdstevel@tonic-gate		*prp = *p;
19997c478bdstevel@tonic-gate		prunlock(pnp);
20007c478bdstevel@tonic-gate		if (copyout(prp, cmaddr, sizeof (proc_t)))
20017c478bdstevel@tonic-gate			error = EFAULT;
20027c478bdstevel@tonic-gate		kmem_free(prp, sizeof (proc_t));
20037c478bdstevel@tonic-gate		thing = NULL;
20047c478bdstevel@tonic-gate		break;
20057c478bdstevel@tonic-gate	}
20067c478bdstevel@tonic-gate
20077c478bdstevel@tonic-gate	case PIOCGETU:		/* read u-area */
20087c478bdstevel@tonic-gate	{
20097c478bdstevel@tonic-gate		user_t *userp = thing;
20107c478bdstevel@tonic-gate
20117c478bdstevel@tonic-gate		up = PTOU(p);
20127c478bdstevel@tonic-gate		*userp = *up;
20137c478bdstevel@tonic-gate		prunlock(pnp);
20147c478bdstevel@tonic-gate		if (copyout(userp, cmaddr, sizeof (user_t)))
20157c478bdstevel@tonic-gate			error = EFAULT;
20167c478bdstevel@tonic-gate		kmem_free(userp, sizeof (user_t));
20177c478bdstevel@tonic-gate		thing = NULL;
20187c478bdstevel@tonic-gate		break;
20197c478bdstevel@tonic-gate	}
20207c478bdstevel@tonic-gate
20217c478bdstevel@tonic-gate	case PIOCOPENM:		/* open mapped object for reading */
20227c478bdstevel@tonic-gate		if (PROCESS_NOT_32BIT(p) && cmaddr != NULL) {
20237c478bdstevel@tonic-gate			prunlock(pnp);
20247c478bdstevel@tonic-gate			error = EOVERFLOW;
20257c478bdstevel@tonic-gate			break;
20267c478bdstevel@tonic-gate		}
20277c478bdstevel@tonic-gate		error = propenm(pnp, cmaddr,
20287c478bdstevel@tonic-gate		    (caddr_t)(uintptr_t)un32.va, rvalp, cr);
20297c478bdstevel@tonic-gate		/* propenm() called prunlock(pnp) */
20307c478bdstevel@tonic-gate		break;
20317c478bdstevel@tonic-gate
20327c478bdstevel@tonic-gate	case PIOCSTOP:		/* stop process or lwp from running */
20337c478bdstevel@tonic-gate	case PIOCWSTOP:		/* wait for process or lwp to stop */
20347c478bdstevel@tonic-gate		/*
20357c478bdstevel@tonic-gate		 * Can't apply to a system process.
20367c478bdstevel@tonic-gate		 */
20377c478bdstevel@tonic-gate		if ((p->p_flag & SSYS) || p->p_as == &kas) {
20387c478bdstevel@tonic-gate			prunlock(pnp);
20397c478bdstevel@tonic-gate			error = EBUSY;
20407c478bdstevel@tonic-gate			break;
20417c478bdstevel@tonic-gate		}
20427c478bdstevel@tonic-gate
20437c478bdstevel@tonic-gate		if (cmd == PIOCSTOP)
20447c478bdstevel@tonic-gate			pr_stop(pnp);
20457c478bdstevel@tonic-gate
20467c478bdstevel@tonic-gate		/*
20477c478bdstevel@tonic-gate		 * If an lwp is waiting for itself or its process, don't wait.
20487c478bdstevel@tonic-gate		 * The lwp will never see the fact that itself is stopped.
20497c478bdstevel@tonic-gate		 */
20507c478bdstevel@tonic-gate		if ((pnp->pr_type == PR_LWPIDFILE)?
20517c478bdstevel@tonic-gate		    (pcp->prc_thread == curthread) : (p == curproc)) {
20527c478bdstevel@tonic-gate			if (cmd == PIOCWSTOP)
20537c478bdstevel@tonic-gate				error = EBUSY;
20547c478bdstevel@tonic-gate			prunlock(pnp);
20557c478bdstevel@tonic-gate			break;
20567c478bdstevel@tonic-gate		}
20577c478bdstevel@tonic-gate
20587c478bdstevel@tonic-gate		if ((error = pr_wait_stop(pnp, (time_t)0)) != 0)
20597c478bdstevel@tonic-gate			break;	/* pr_wait_stop() unlocked the process */
20607c478bdstevel@tonic-gate
20617c478bdstevel@tonic-gate		if (cmaddr == NULL)
20627c478bdstevel@tonic-gate			prunlock(pnp);
20637c478bdstevel@tonic-gate		else if (PROCESS_NOT_32BIT(p)) {
20647c478bdstevel@tonic-gate			prunlock(pnp);
20657c478bdstevel@tonic-gate			error = EOVERFLOW;
20667c478bdstevel@tonic-gate		} else {
20677c478bdstevel@tonic-gate			/*
20687c478bdstevel@tonic-gate			 * Return process/lwp status information.
20697c478bdstevel@tonic-gate			 */
20707c478bdstevel@tonic-gate			t = pr_thread(pnp);	/* returns locked thread */
20717c478bdstevel@tonic-gate			thread_unlock(t);
2072fa9e406ahrens			oprgetstatus32(t, &un32.prstat, VTOZONE(vp));
20737c478bdstevel@tonic-gate			prunlock(pnp);
20747c478bdstevel@tonic-gate			if (copyout(&un32.prstat, cmaddr, sizeof (un32.prstat)))
20757c478bdstevel@tonic-gate				error = EFAULT;
20767c478bdstevel@tonic-gate		}
20777c478bdstevel@tonic-gate		break;
20787c478bdstevel@tonic-gate
20797c478bdstevel@tonic-gate	case PIOCRUN:		/* make lwp or process runnable */
20807c478bdstevel@tonic-gate	{
20817c478bdstevel@tonic-gate		long flags = un32.prrun.pr_flags;
20827c478bdstevel@tonic-gate
20837c478bdstevel@tonic-gate		/*
20847c478bdstevel@tonic-gate		 * Cannot set an lwp running is it is not stopped.
20857c478bdstevel@tonic-gate		 * Also, no lwp other than the /proc agent lwp can
20867c478bdstevel@tonic-gate		 * be set running so long as the /proc agent lwp exists.
20877c478bdstevel@tonic-gate		 */
20887c478bdstevel@tonic-gate		if ((!ISTOPPED(t) && !VSTOPPED(t) &&
20897c478bdstevel@tonic-gate		    !(t->t_proc_flag & TP_PRSTOP)) ||
20907c478bdstevel@tonic-gate		    (p->p_agenttp != NULL &&
20917c478bdstevel@tonic-gate		    (t != p->p_agenttp || pnp->pr_type != PR_LWPIDFILE))) {
20927c478bdstevel@tonic-gate			prunlock(pnp);
20937c478bdstevel@tonic-gate			error = EBUSY;
20947c478bdstevel@tonic-gate			break;
20957c478bdstevel@tonic-gate		}
20967c478bdstevel@tonic-gate
20977c478bdstevel@tonic-gate		if ((flags & PRSVADDR) && PROCESS_NOT_32BIT(p)) {
20987c478bdstevel@tonic-gate			prunlock(pnp);
20997c478bdstevel@tonic-gate			error = EOVERFLOW;
21007c478bdstevel@tonic-gate			break;
21017c478bdstevel@tonic-gate		}
21027c478bdstevel@tonic-gate
21037c478bdstevel@tonic-gate		if (flags & (PRSHOLD|PRSTRACE|PRSFAULT|PRSVADDR)) {
21047c478bdstevel@tonic-gate			un.prrun.pr_flags = (int)flags;
21057c478bdstevel@tonic-gate			un.prrun.pr_trace = un32.prrun.pr_trace;
21067c478bdstevel@tonic-gate			un.prrun.pr_sighold = un32.prrun.pr_sighold;
21077c478bdstevel@tonic-gate			un.prrun.pr_fault = un32.prrun.pr_fault;
21087c478bdstevel@tonic-gate			un.prrun.pr_vaddr =
21097c478bdstevel@tonic-gate			    (caddr_t)(uintptr_t)un32.prrun.pr_vaddr;
21107c478bdstevel@tonic-gate			prsetrun(t, &un.prrun);
21117c478bdstevel@tonic-gate		}
21127c478bdstevel@tonic-gate
21137c478bdstevel@tonic-gate		error = pr_setrun(pnp, prmaprunflags(flags));
21147c478bdstevel@tonic-gate
21157c478bdstevel@tonic-gate		prunlock(pnp);
21167c478bdstevel@tonic-gate		break;
21177c478bdstevel@tonic-gate	}
21187c478bdstevel@tonic-gate
21197c478bdstevel@tonic-gate	case PIOCLWPIDS:	/* get array of lwp identifiers */
21207c478bdstevel@tonic-gate	{
21217c478bdstevel@tonic-gate		int nlwp;
21227c478bdstevel@tonic-gate		int Nlwp;
21237c478bdstevel@tonic-gate		id_t *idp;
21247c478bdstevel@tonic-gate		id_t *Bidp;
21257c478bdstevel@tonic-gate
21267c478bdstevel@tonic-gate		Nlwp = nlwp = p->p_lwpcnt;
21277c478bdstevel@tonic-gate
21287c478bdstevel@tonic-gate		if (thing && thingsize != (Nlwp+1) * sizeof (id_t)) {
21297c478bdstevel@tonic-gate			kmem_free(thing, thingsize);
21307c478bdstevel@tonic-gate			thing = NULL;
21317c478bdstevel@tonic-gate		}
21327c478bdstevel@tonic-gate		if (thing == NULL) {
21337c478bdstevel@tonic-gate			thingsize = (Nlwp+1) * sizeof (id_t);
21347c478bdstevel@tonic-gate			thing = kmem_alloc(thingsize, KM_NOSLEEP);
21357c478bdstevel@tonic-gate		}
21367c478bdstevel@tonic-gate		if (thing == NULL) {
21377c478bdstevel@tonic-gate			prunlock(pnp);
21387c478bdstevel@tonic-gate			goto startover;
21397c478bdstevel@tonic-gate		}
21407c478bdstevel@tonic-gate
21417c478bdstevel@tonic-gate		idp = thing;
21427c478bdstevel@tonic-gate		thing = NULL;
21437c478bdstevel@tonic-gate		Bidp = idp;
21447c478bdstevel@tonic-gate		if ((t = p->p_tlist) != NULL) {
21457c478bdstevel@tonic-gate			do {
21467c478bdstevel@tonic-gate				ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
21477c478bdstevel@tonic-gate				ASSERT(nlwp > 0);
21487c478bdstevel@tonic-gate				--nlwp;
21497c478bdstevel@tonic-gate				*idp++ = t->t_tid;
21507c478bdstevel@tonic-gate			} while ((t = t->t_forw) != p->p_tlist);
21517c478bdstevel@tonic-gate		}
21527c478bdstevel@tonic-gate		*idp = 0;
21537c478bdstevel@tonic-gate		ASSERT(nlwp == 0);
21547c478bdstevel@tonic-gate		prunlock(pnp);
21557c478bdstevel@tonic-gate		if (copyout(Bidp, cmaddr, (Nlwp+1) * sizeof (id_t)))
21567c478bdstevel@tonic-gate			error = EFAULT;
21577c478bdstevel@tonic-gate		kmem_free(Bidp, (Nlwp+1) * sizeof (id_t));
21587c478bdstevel@tonic-gate		break;
21597c478bdstevel@tonic-gate	}
21607c478bdstevel@tonic-gate
21617c478bdstevel@tonic-gate	case PIOCOPENLWP:	/* return /proc lwp file descriptor */
21627c478bdstevel@tonic-gate	{
21637c478bdstevel@tonic-gate		vnode_t *xvp;
21647c478bdstevel@tonic-gate		int n;
21657c478bdstevel@tonic-gate
21667c478bdstevel@tonic-gate		prunlock(pnp);
21677c478bdstevel@tonic-gate		if ((xvp = prlwpnode(pnp, un32.lwpid)) == NULL)
21687c478bdstevel@tonic-gate			error = ENOENT;
21697c478bdstevel@tonic-gate		else if (error = fassign(&xvp, flag & (FREAD|FWRITE), &n)) {
21707c478bdstevel@tonic-gate			VN_RELE(xvp);
21717c478bdstevel@tonic-gate		} else
21727c478bdstevel@tonic-gate			*rvalp = n;
21737c478bdstevel@tonic-gate		break;
21747c478bdstevel@tonic-gate	}
21757c478bdstevel@tonic-gate
21767c478bdstevel@tonic-gate	case PIOCOPENPD:	/* return /proc page data file descriptor */
21777c478bdstevel@tonic-gate	{
21787c478bdstevel@tonic-gate		vnode_t *xvp = PTOV(xpnp);
21797c478bdstevel@tonic-gate		vnode_t *dp = pnp->pr_parent;
21807c478bdstevel@tonic-gate		int n;
21817c478bdstevel@tonic-gate
21827c478bdstevel@tonic-gate		if (PROCESS_NOT_32BIT(p)) {
21837c478bdstevel@tonic-gate			prunlock(pnp);
21847c478bdstevel@tonic-gate			prfreenode(xpnp);
21857c478bdstevel@tonic-gate			xpnp = NULL;
21867c478bdstevel@tonic-gate			error = EOVERFLOW;
21877c478bdstevel@tonic-gate			break;
21887c478bdstevel@tonic-gate		}
21897c478bdstevel@tonic-gate
21907c478bdstevel@tonic-gate		if (pnp->pr_type == PR_LWPIDFILE) {
21917c478bdstevel@tonic-gate			dp = VTOP(dp)->pr_parent;
21927c478bdstevel@tonic-gate			dp = VTOP(dp)->pr_parent;
21937c478bdstevel@tonic-gate		}
21947c478bdstevel@tonic-gate		ASSERT(VTOP(dp)->pr_type == PR_PIDDIR);
21957c478bdstevel@tonic-gate
21967c478bdstevel@tonic-gate		VN_HOLD(dp);
21977c478bdstevel@tonic-gate		pcp = pnp->pr_pcommon;
21987c478bdstevel@tonic-gate		xpnp->pr_ino = ptoi(pcp->prc_pid);
21997c478bdstevel@tonic-gate		xpnp->pr_common = pcp;
22007c478bdstevel@tonic-gate		xpnp->pr_pcommon = pcp;
22017c478bdstevel@tonic-gate		xpnp->pr_parent = dp;
22027c478bdstevel@tonic-gate
22037c478bdstevel@tonic-gate		xpnp->pr_next = p->p_plist;
22047c478bdstevel@tonic-gate		p->p_plist = xvp;
22057c478bdstevel@tonic-gate
22067c478bdstevel@tonic-gate		prunlock(pnp);
22077c478bdstevel@tonic-gate		if (error = fassign(&xvp, FREAD, &n)) {
22087c478bdstevel@tonic-gate			VN_RELE(xvp);
22097c478bdstevel@tonic-gate		} else
22107c478bdstevel@tonic-gate			*rvalp = n;
22117c478bdstevel@tonic-gate
22127c478bdstevel@tonic-gate		xpnp = NULL;
22137c478bdstevel@tonic-gate		break;
22147c478bdstevel@tonic-gate	}
22157c478bdstevel@tonic-gate
22167c478bdstevel@tonic-gate	case PIOCGTRACE:	/* get signal trace mask */
22177c478bdstevel@tonic-gate		prassignset(&un32.smask, &p->p_sigmask);
22187c478bdstevel@tonic-gate		prunlock(pnp);
22197c478bdstevel@tonic-gate		if (copyout(&un32.smask, cmaddr, sizeof (un32.smask)))
22207c478bdstevel@tonic-gate			error = EFAULT;
22217c478bdstevel@tonic-gate		break;
22227c478bdstevel@tonic-gate
22237c478bdstevel@tonic-gate	case PIOCSTRACE:	/* set signal trace mask */
22247c478bdstevel@tonic-gate		prdelset(&un32.smask, SIGKILL);
22257c478bdstevel@tonic-gate		prassignset(&p->p_sigmask, &un32.smask);
22267c478bdstevel@tonic-gate		if (!sigisempty(&p->p_sigmask))
22277c478bdstevel@tonic-gate			p->p_proc_flag |= P_PR_TRACE;
22287c478bdstevel@tonic-gate		else if (prisempty(&p->p_fltmask)) {
22297c478bdstevel@tonic-gate			up = PTOU(p);
22307c478bdstevel@tonic-gate			if (up->u_systrap == 0)
22317c478bdstevel@tonic-gate				p->p_proc_flag &= ~P_PR_TRACE;
22327c478bdstevel@tonic-gate		}
22337c478bdstevel@tonic-gate		prunlock(pnp);
22347c478bdstevel@tonic-gate		break;
22357c478bdstevel@tonic-gate
22367c478bdstevel@tonic-gate	case PIOCSSIG:		/* set current signal */
22377c478bdstevel@tonic-gate		if (un32.info.si_signo != 0 && PROCESS_NOT_32BIT(p)) {
22387c478bdstevel@tonic-gate			prunlock(pnp);
22397c478bdstevel@tonic-gate			error = EOVERFLOW;
22407c478bdstevel@tonic-gate		} else {
22417c478bdstevel@tonic-gate			bzero(&un.info, sizeof (un.info));
22427c478bdstevel@tonic-gate			siginfo_32tok(&un32.info, (k_siginfo_t *)&un.info);
22437c478bdstevel@tonic-gate			error = pr_setsig(pnp, &un.info);
22447c478bdstevel@tonic-gate			prunlock(pnp);
22457c478bdstevel@tonic-gate			if (un32.info.si_signo == SIGKILL && error == 0)
22467c478bdstevel@tonic-gate				pr_wait_die(pnp);
22477c478bdstevel@tonic-gate		}
22487c478bdstevel@tonic-gate		break;
22497c478bdstevel@tonic-gate
22507c478bdstevel@tonic-gate	case PIOCKILL:		/* send signal */
22517c478bdstevel@tonic-gate		error = pr_kill(pnp, un32.signo, cr);
22527c478bdstevel@tonic-gate		prunlock(pnp);
22537c478bdstevel@tonic-gate		if (un32.signo == SIGKILL && error == 0)
22547c478bdstevel@tonic-gate			pr_wait_die(pnp);
22557c478bdstevel@tonic-gate		break;
22567c478bdstevel@tonic-gate
22577c478bdstevel@tonic-gate	case PIOCUNKILL:	/* delete a signal */
22587c478bdstevel@tonic-gate		error = pr_unkill(pnp, un32.signo);
22597c478bdstevel@tonic-gate		prunlock(pnp);
22607c478bdstevel@tonic-gate		break;
22617c478bdstevel@tonic-gate
22627c478bdstevel@tonic-gate	case PIOCNICE:		/* set nice priority */
22637c478bdstevel@tonic-gate		error = pr_nice(p, un32.nice, cr);
22647c478bdstevel@tonic-gate		prunlock(pnp);
22657c478bdstevel@tonic-gate		break;
22667c478bdstevel@tonic-gate
22677c478bdstevel@tonic-gate	case PIOCGENTRY:	/* get syscall entry bit mask */
22687c478bdstevel@tonic-gate	case PIOCGEXIT:		/* get syscall exit bit mask */
22697c478bdstevel@tonic-gate		up = PTOU(p);
22707c478bdstevel@tonic-gate		if (cmd == PIOCGENTRY) {
22717c478bdstevel@tonic-gate			prassignset(&un32.prmask, &up->u_entrymask);
22727c478bdstevel@tonic-gate		} else {
22737c478bdstevel@tonic-gate			prassignset(&un32.prmask, &up->u_exitmask);
22747c478bdstevel@tonic-gate		}
22757c478bdstevel@tonic-gate		prunlock(pnp);
22767c478bdstevel@tonic-gate		if (copyout(&un32.prmask, cmaddr, sizeof (un32.prmask)))
22777c478bdstevel@tonic-gate			error = EFAULT;
22787c478bdstevel@tonic-gate		break;
22797c478bdstevel@tonic-gate
22807c478bdstevel@tonic-gate	case PIOCSENTRY:	/* set syscall entry bit mask */
22817c478bdstevel@tonic-gate	case PIOCSEXIT:		/* set syscall exit bit mask */
22827c478bdstevel@tonic-gate		pr_setentryexit(p, &un32.prmask, cmd == PIOCSENTRY);
22837c478bdstevel@tonic-gate		prunlock(pnp);
22847c478bdstevel@tonic-gate		break;
22857c478bdstevel@tonic-gate
22867c478bdstevel@tonic-gate	case PIOCSRLC:		/* obsolete: set running on last /proc close */
22877c478bdstevel@tonic-gate		error = pr_set(p, prmapsetflags(PR_RLC));
22887c478bdstevel@tonic-gate		prunlock(pnp);
22897c478bdstevel@tonic-gate		break;
22907c478bdstevel@tonic-gate
22917c478bdstevel@tonic-gate	case PIOCRRLC:		/* obsolete: reset run-on-last-close flag */
22927c478bdstevel@tonic-gate		error = pr_unset(p, prmapsetflags(PR_RLC));
22937c478bdstevel@tonic-gate		prunlock(pnp);
22947c478bdstevel@tonic-gate		break;
22957c478bdstevel@tonic-gate
22967c478bdstevel@tonic-gate	case PIOCSFORK:		/* obsolete: set inherit-on-fork flag */
22977c478bdstevel@tonic-gate		error = pr_set(p, prmapsetflags(PR_FORK));
22987c478bdstevel@tonic-gate		prunlock(pnp);
22997c478bdstevel@tonic-gate		break;
23007c478bdstevel@tonic-gate
23017c478bdstevel@tonic-gate	case PIOCRFORK:		/* obsolete: reset inherit-on-fork flag */
23027c478bdstevel@tonic-gate		error = pr_unset(p, prmapsetflags(PR_FORK));
23037c478bdstevel@tonic-gate		prunlock(pnp);
23047c478bdstevel@tonic-gate		break;
23057c478bdstevel@tonic-gate
23067c478bdstevel@tonic-gate	case PIOCSET:		/* set process flags */
23077c478bdstevel@tonic-gate		error = pr_set(p, prmapsetflags((long)un32.flags));
23087c478bdstevel@tonic-gate		prunlock(pnp);
23097c478bdstevel@tonic-gate		break;
23107c478bdstevel@tonic-gate
23117c478bdstevel@tonic-gate	case PIOCRESET:		/* reset process flags */
23127c478bdstevel@tonic-gate		error = pr_unset(p, prmapsetflags((long)un32.flags));
23137c478bdstevel@tonic-gate		prunlock(pnp);
23147c478bdstevel@tonic-gate		break;
23157c478bdstevel@tonic-gate
23167c478bdstevel@tonic-gate	case PIOCGREG:		/* get general registers */
23177c478bdstevel@tonic-gate		if (PROCESS_NOT_32BIT(p))
23187c478bdstevel@tonic-gate			error = EOVERFLOW;
23197c478bdstevel@tonic-gate		else if (t->t_state != TS_STOPPED && !VSTOPPED(t))
23207c478bdstevel@tonic-gate			bzero(un32.regs, sizeof (un32.regs));
23217c478bdstevel@tonic-gate		else {
23227c478bdstevel@tonic-gate			/* drop p_lock while touching the lwp's stack */
23237c478bdstevel@tonic-gate			mutex_exit(&p->p_lock);
23247c478bdstevel@tonic-gate			prgetprregs32(lwp, un32.regs);
23257c478bdstevel@tonic-gate			mutex_enter(&p->p_lock);
23267c478bdstevel@tonic-gate		}
23277c478bdstevel@tonic-gate		prunlock(pnp);
23287c478bdstevel@tonic-gate		if (error == 0 &&
23297c478bdstevel@tonic-gate		    copyout(un32.regs, cmaddr, sizeof (un32.regs)))
23307c478bdstevel@tonic-gate			error = EFAULT;
23317c478bdstevel@tonic-gate		break;
23327c478bdstevel@tonic-gate
23337c478bdstevel@tonic-gate	case PIOCSREG:		/* set general registers */
23347c478bdstevel@tonic-gate		if (PROCESS_NOT_32BIT(p))
23357c478bdstevel@tonic-gate			error = EOVERFLOW;
23367c478bdstevel@tonic-gate		else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
23377c478bdstevel@tonic-gate			error = EBUSY;
23387c478bdstevel@tonic-gate		else {
23397c478bdstevel@tonic-gate			/* drop p_lock while touching the lwp's stack */
23407c478bdstevel@tonic-gate			mutex_exit(&p->p_lock);
23417c478bdstevel@tonic-gate			prgregset_32ton(lwp, un32.regs, un.regs);
23427c478bdstevel@tonic-gate			prsetprregs(lwp, un.regs, 0);
23437c478bdstevel@tonic-gate			mutex_enter(&p->p_lock);
23447c478bdstevel@tonic-gate		}
23457c478bdstevel@tonic-gate		prunlock(pnp);
23467c478bdstevel@tonic-gate		break;
23477c478bdstevel@tonic-gate
23487c478bdstevel@tonic-gate	case PIOCGFPREG:	/* get floating-point registers */
23497c478bdstevel@tonic-gate		if (!prhasfp())
23507c478bdstevel@tonic-gate			error = EINVAL;	/* No FP support */
23517c478bdstevel@tonic-gate		else if (PROCESS_NOT_32BIT(p))
23527c478bdstevel@tonic-gate			error = EOVERFLOW;
23537c478bdstevel@tonic-gate		else if (t->t_state != TS_STOPPED && !VSTOPPED(t))
23547c478bdstevel@tonic-gate			bzero(&un32.fpregs, sizeof (un32.fpregs));
23557c478bdstevel@tonic-gate		else {
23567c478bdstevel@tonic-gate			/* drop p_lock while touching the lwp's stack */
23577c478bdstevel@tonic-gate			mutex_exit(&p->p_lock);
23587c478bdstevel@tonic-gate			prgetprfpregs32(lwp, &un32.fpregs);
23597c478bdstevel@tonic-gate			mutex_enter(&p->p_lock);
23607c478bdstevel@tonic-gate		}
23617c478bdstevel@tonic-gate		prunlock(pnp);
23627c478bdstevel@tonic-gate		if (error == 0 &&
23637c478bdstevel@tonic-gate		    copyout(&un32.fpregs, cmaddr, sizeof (un32.fpregs)))
23647c478bdstevel@tonic-gate			error = EFAULT;
23657c478bdstevel@tonic-gate		break;
23667c478bdstevel@tonic-gate
23677c478bdstevel@tonic-gate	case PIOCSFPREG:	/* set floating-point registers */
23687c478bdstevel@tonic-gate		if (!prhasfp())
23697c478bdstevel@tonic-gate			error = EINVAL;	/* No FP support */
23707c478bdstevel@tonic-gate		else if (PROCESS_NOT_32BIT(p))
23717c478bdstevel@tonic-gate			error = EOVERFLOW;
23727c478bdstevel@tonic-gate		else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
23737c478bdstevel@tonic-gate			error = EBUSY;
23747c478bdstevel@tonic-gate		else {
23757c478bdstevel@tonic-gate			/* drop p_lock while touching the lwp's stack */
23767c478bdstevel@tonic-gate			mutex_exit(&p->p_lock);
23777c478bdstevel@tonic-gate			prsetprfpregs32(lwp, &un32.fpregs);
23787c478bdstevel@tonic-gate			mutex_enter(&p->p_lock);
23797c478bdstevel@tonic-gate		}
23807c478bdstevel@tonic-gate		prunlock(pnp);
23817c478bdstevel@tonic-gate		break;
23827c478bdstevel@tonic-gate
23837c478bdstevel@tonic-gate	case PIOCGXREGSIZE:	/* get the size of the extra registers */
23847c478bdstevel@tonic-gate	{
23857c478bdstevel@tonic-gate		int xregsize;
23867c478bdstevel@tonic-gate
23877c478bdstevel@tonic-gate		if (prhasx(p)) {
23887c478bdstevel@tonic-gate			xregsize = prgetprxregsize(p);
23897c478bdstevel@tonic-gate			prunlock(pnp);
23907c478bdstevel@tonic-gate			if (copyout(&xregsize, cmaddr, sizeof (xregsize)))
23917c478bdstevel@tonic-gate				error = EFAULT;
23927c478bdstevel@tonic-gate		} else {
23937c478bdstevel@tonic-gate			prunlock(pnp);
23947c478bdstevel@tonic-gate			error = EINVAL;	/* No extra register support */
23957c478bdstevel@tonic-gate		}
23967c478bdstevel@tonic-gate		break;
23977c478bdstevel@tonic-gate	}
23987c478bdstevel@tonic-gate
23997c478bdstevel@tonic-gate	case PIOCGXREG:		/* get extra registers */
24007c478bdstevel@tonic-gate		if (PROCESS_NOT_32BIT(p))
24017c478bdstevel@tonic-gate			error = EOVERFLOW;
24027c478bdstevel@tonic-gate		else if (!prhasx(p))
24037c478bdstevel@tonic-gate			error = EINVAL;	/* No extra register support */
24047c478bdstevel@tonic-gate		else {
24057c478bdstevel@tonic-gate			bzero(thing, thingsize);
24067c478bdstevel@tonic-gate			if (t->t_state == TS_STOPPED || VSTOPPED(t)) {
24077c478bdstevel@tonic-gate				/* drop p_lock to touch the stack */
24087c478bdstevel@tonic-gate				mutex_exit(&p->p_lock);
24097c478bdstevel@tonic-gate				prgetprxregs(lwp, thing);
2410