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