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