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