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