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