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