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