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