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