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