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