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