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