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