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