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