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