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]
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>
34 #include <sys/cmn_err.h>
36 #include <sys/debug.h>
37 #include <sys/errno.h>
39 #include <sys/inline.h>
42 #include <sys/brand.h>
43 #include <sys/sysmacros.h>
44 #include <sys/systm.h>
46 #include <sys/vnode.h>
47 #include <sys/cpuvar.h>
48 #include <sys/session.h>
49 #include <sys/signal.h>
53 #include <sys/class.h>
56 #include <sys/fault.h>
57 #include <sys/syscall.h>
58 #include <sys/schedctl.h>
60 #include <sys/old_procfs.h>
63 #include <sys/msacct.h>
68 #include <vm/seg_vn.h>
69 #include <sys/contract_impl.h>
70 #include <sys/ctfs_impl.h>
73 #if defined(__i386) || defined(__i386_COMPAT)
74 #include <sys/sysi86.h>
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
*);
89 prctioctl(prnode_t
*pnp
, int cmd
, intptr_t arg
, int flag
, cred_t
*cr
)
93 ct_param_t
*param
= &kparam
.param
;
96 if (cmd
!= CT_TSET
&& cmd
!= CT_TGET
)
99 error
= ctparam_copyin((void *)arg
, &kparam
, flag
, cmd
);
103 if ((error
= prlock(pnp
, ZNO
)) != 0) {
104 kmem_free(kparam
.ctpm_kbuf
, param
->ctpm_size
);
108 tmpl
= pnp
->pr_common
->prc_thread
->t_lwp
->lwp_ct_active
[pnp
->pr_cttype
];
111 kmem_free(kparam
.ctpm_kbuf
, param
->ctpm_size
);
116 error
= ctmpl_set(tmpl
, &kparam
, cr
);
118 error
= ctmpl_get(tmpl
, &kparam
);
122 if (cmd
== CT_TGET
&& error
== 0) {
123 error
= ctparam_copyout(&kparam
, (void *)arg
, flag
);
125 kmem_free(kparam
.ctpm_kbuf
, param
->ctpm_size
);
133 * Control operations (lots).
136 #ifdef _SYSCALL32_IMPL
145 caller_context_t
*ct
)
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
;
164 prnode_t
*pnp
= VTOP(vp
);
166 prnode_t
*xpnp
= NULL
;
170 size_t thingsize
= 0;
173 * For copyin()/copyout().
194 auxv_t auxv
[__KERN_NAUXV_IMPL
];
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
;
207 ASSERT(pnp
->pr_type
== PR_PIDFILE
);
210 if (pnp
->pr_type
!= PR_PIDFILE
&& pnp
->pr_type
!= PR_LWPIDFILE
)
214 * Fail ioctls which are logically "write" requests unless
215 * the user has write permission.
217 if ((flag
& FWRITE
) == 0 && isprwrioctl(cmd
))
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,
234 thingsize
= sizeof (proc_t
);
237 thingsize
= sizeof (user_t
);
257 case PIOCSXREG
: /* set extra registers */
258 case PIOCGXREG
: /* get extra registers */
260 thingsize
= sizeof (prxregset_t
);
266 thingsize
= (nsig
-1) * sizeof (struct sigaction
);
280 * We will need this below.
281 * Allocate it now, before locking the process.
283 xpnp
= prgetnode(vp
, PR_OPAGEDATA
);
289 #if defined(__i386) || defined(__amd64)
293 #endif /* __i386 || __amd64 */
297 thingsize
= sizeof (gwindows_t
);
301 case PIOCOPENM
: /* open mapped object for reading */
304 else if (copyin(cmaddr
, &un
.va
, sizeof (un
.va
)))
308 case PIOCRUN
: /* make lwp or process runnable */
310 un
.prrun
.pr_flags
= 0;
311 else if (copyin(cmaddr
, &un
.prrun
, sizeof (un
.prrun
)))
315 case PIOCOPENLWP
: /* return /proc lwp file descriptor */
316 if (copyin(cmaddr
, &un
.lwpid
, sizeof (un
.lwpid
)))
320 case PIOCSTRACE
: /* set signal trace mask */
321 if (copyin(cmaddr
, &un
.smask
, sizeof (un
.smask
)))
325 case PIOCSSIG
: /* set current signal */
327 un
.info
.si_signo
= 0;
328 else if (copyin(cmaddr
, &un
.info
, sizeof (un
.info
)))
332 case PIOCKILL
: /* send signal */
333 case PIOCUNKILL
: /* delete a signal */
334 if (copyin(cmaddr
, &un
.signo
, sizeof (un
.signo
)))
338 case PIOCNICE
: /* set nice priority */
339 if (copyin(cmaddr
, &un
.nice
, sizeof (un
.nice
)))
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
)))
349 case PIOCSET
: /* set process flags */
350 case PIOCRESET
: /* reset process flags */
351 if (copyin(cmaddr
, &un
.flags
, sizeof (un
.flags
)))
355 case PIOCSREG
: /* set general registers */
356 if (copyin(cmaddr
, un
.regs
, sizeof (un
.regs
)))
360 case PIOCSFPREG
: /* set floating-point registers */
361 if (copyin(cmaddr
, &un
.fpregs
, sizeof (un
.fpregs
)))
365 case PIOCSHOLD
: /* set signal-hold mask */
366 if (copyin(cmaddr
, &un
.holdmask
, sizeof (un
.holdmask
)))
370 case PIOCSFAULT
: /* set mask of traced faults */
371 if (copyin(cmaddr
, &un
.fltmask
, sizeof (un
.fltmask
)))
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.)
393 ASSERT(thing
== NULL
);
394 thing
= kmem_alloc(thingsize
, KM_SLEEP
);
404 case PIOCSXREG
: /* set extra registers */
406 * perform copyin before grabbing the process lock
409 if (copyin(cmaddr
, thing
, thingsize
)) {
410 kmem_free(thing
, thingsize
);
414 /* fall through... */
420 if ((error
= prlock(pnp
, zdisp
)) != 0) {
422 kmem_free(thing
, thingsize
);
428 pcp
= pnp
->pr_common
;
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
) {
440 t
= prchoose(p
); /* returns locked thread */
450 case PIOCGETPR
: /* read struct proc */
456 if (copyout(prp
, cmaddr
, sizeof (proc_t
)))
458 kmem_free(prp
, sizeof (proc_t
));
463 case PIOCGETU
: /* read u-area */
465 user_t
*userp
= thing
;
470 if (copyout(userp
, cmaddr
, sizeof (user_t
)))
472 kmem_free(userp
, sizeof (user_t
));
477 case PIOCOPENM
: /* open mapped object for reading */
478 error
= propenm(pnp
, cmaddr
, un
.va
, rvalp
, cr
);
479 /* propenm() called prunlock(pnp) */
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
) {
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
)
508 if ((error
= pr_wait_stop(pnp
, (time_t)0)) != 0)
509 break; /* pr_wait_stop() unlocked the process */
515 * Return process/lwp status information.
517 t
= pr_thread(pnp
); /* returns locked thread */
519 oprgetstatus(t
, &un
.prstat
, VTOZONE(vp
));
521 if (copyout(&un
.prstat
, cmaddr
, sizeof (un
.prstat
)))
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
))) {
544 if (flags
& (PRSHOLD
|PRSTRACE
|PRSFAULT
|PRSVADDR
))
545 prsetrun(t
, &un
.prrun
);
547 error
= pr_setrun(pnp
, prmaprunflags(flags
));
553 case PIOCLWPIDS
: /* get array of lwp identifiers */
560 Nlwp
= nlwp
= p
->p_lwpcnt
;
562 if (thing
&& thingsize
!= (Nlwp
+1) * sizeof (id_t
)) {
563 kmem_free(thing
, thingsize
);
567 thingsize
= (Nlwp
+1) * sizeof (id_t
);
568 thing
= kmem_alloc(thingsize
, KM_NOSLEEP
);
578 if ((t
= p
->p_tlist
) != NULL
) {
580 ASSERT(!(t
->t_proc_flag
& TP_LWPEXIT
));
584 } while ((t
= t
->t_forw
) != p
->p_tlist
);
589 if (copyout(Bidp
, cmaddr
, (Nlwp
+1) * sizeof (id_t
)))
591 kmem_free(Bidp
, (Nlwp
+1) * sizeof (id_t
));
595 case PIOCOPENLWP
: /* return /proc lwp file descriptor */
601 if ((xvp
= prlwpnode(pnp
, un
.lwpid
)) == NULL
)
603 else if (error
= fassign(&xvp
, flag
& (FREAD
|FWRITE
), &n
)) {
610 case PIOCOPENPD
: /* return /proc page data file descriptor */
612 vnode_t
*xvp
= PTOV(xpnp
);
613 vnode_t
*dp
= pnp
->pr_parent
;
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
);
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
;
633 if (error
= fassign(&xvp
, FREAD
, &n
)) {
642 case PIOCGTRACE
: /* get signal trace mask */
643 prassignset(&un
.smask
, &p
->p_sigmask
);
645 if (copyout(&un
.smask
, cmaddr
, sizeof (un
.smask
)))
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
)) {
656 if (up
->u_systrap
== 0)
657 p
->p_proc_flag
&= ~P_PR_TRACE
;
662 case PIOCSSIG
: /* set current signal */
663 error
= pr_setsig(pnp
, &un
.info
);
665 if (un
.info
.si_signo
== SIGKILL
&& error
== 0)
669 case PIOCKILL
: /* send signal */
671 int sig
= (int)un
.signo
;
673 error
= pr_kill(pnp
, sig
, cr
);
675 if (sig
== SIGKILL
&& error
== 0)
680 case PIOCUNKILL
: /* delete a signal */
681 error
= pr_unkill(pnp
, (int)un
.signo
);
685 case PIOCNICE
: /* set nice priority */
686 error
= pr_nice(p
, (int)un
.nice
, cr
);
690 case PIOCGENTRY
: /* get syscall entry bit mask */
691 case PIOCGEXIT
: /* get syscall exit bit mask */
693 if (cmd
== PIOCGENTRY
) {
694 prassignset(&un
.prmask
, &up
->u_entrymask
);
696 prassignset(&un
.prmask
, &up
->u_exitmask
);
699 if (copyout(&un
.prmask
, cmaddr
, sizeof (un
.prmask
)))
703 case PIOCSENTRY
: /* set syscall entry bit mask */
704 case PIOCSEXIT
: /* set syscall exit bit mask */
705 pr_setentryexit(p
, &un
.prmask
, cmd
== PIOCSENTRY
);
709 case PIOCSRLC
: /* obsolete: set running on last /proc close */
710 error
= pr_set(p
, prmapsetflags(PR_RLC
));
714 case PIOCRRLC
: /* obsolete: reset run-on-last-close flag */
715 error
= pr_unset(p
, prmapsetflags(PR_RLC
));
719 case PIOCSFORK
: /* obsolete: set inherit-on-fork flag */
720 error
= pr_set(p
, prmapsetflags(PR_FORK
));
724 case PIOCRFORK
: /* obsolete: reset inherit-on-fork flag */
725 error
= pr_unset(p
, prmapsetflags(PR_FORK
));
729 case PIOCSET
: /* set process flags */
730 error
= pr_set(p
, prmapsetflags(un
.flags
));
734 case PIOCRESET
: /* reset process flags */
735 error
= pr_unset(p
, prmapsetflags(un
.flags
));
739 case PIOCGREG
: /* get general registers */
740 if (t
->t_state
!= TS_STOPPED
&& !VSTOPPED(t
))
741 bzero(un
.regs
, sizeof (un
.regs
));
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
);
749 if (copyout(un
.regs
, cmaddr
, sizeof (un
.regs
)))
753 case PIOCSREG
: /* set general registers */
754 if (!ISTOPPED(t
) && !VSTOPPED(t
) && !DSTOPPED(t
))
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
);
765 case PIOCGFPREG
: /* get floating-point registers */
768 error
= EINVAL
; /* No FP support */
772 if (t
->t_state
!= TS_STOPPED
&& !VSTOPPED(t
))
773 bzero(&un
.fpregs
, sizeof (un
.fpregs
));
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
);
781 if (copyout(&un
.fpregs
, cmaddr
, sizeof (un
.fpregs
)))
785 case PIOCSFPREG
: /* set floating-point registers */
787 error
= EINVAL
; /* No FP support */
788 else if (!ISTOPPED(t
) && !VSTOPPED(t
) && !DSTOPPED(t
))
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
);
799 case PIOCGXREGSIZE
: /* get the size of the extra registers */
804 xregsize
= prgetprxregsize(p
);
806 if (copyout(&xregsize
, cmaddr
, sizeof (xregsize
)))
810 error
= EINVAL
; /* No extra register support */
815 case PIOCGXREG
: /* get extra registers */
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
);
825 if (copyout(thing
, cmaddr
, thingsize
))
829 error
= EINVAL
; /* No extra register support */
832 kmem_free(thing
, thingsize
);
837 case PIOCSXREG
: /* set extra registers */
838 if (!ISTOPPED(t
) && !VSTOPPED(t
) && !DSTOPPED(t
))
841 error
= EINVAL
; /* No extra register support */
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
);
850 kmem_free(thing
, thingsize
);
855 case PIOCSTATUS
: /* get process/lwp status */
856 oprgetstatus(t
, &un
.prstat
, VTOZONE(vp
));
858 if (copyout(&un
.prstat
, cmaddr
, sizeof (un
.prstat
)))
862 case PIOCLSTATUS
: /* get status for process & all lwps */
869 nlwp
= Nlwp
= p
->p_lwpcnt
;
871 if (thing
&& thingsize
!= (Nlwp
+1) * sizeof (prstatus_t
)) {
872 kmem_free(thing
, thingsize
);
876 thingsize
= (Nlwp
+1) * sizeof (prstatus_t
);
877 thing
= kmem_alloc(thingsize
, KM_NOSLEEP
);
887 oprgetstatus(t
, prsp
, VTOZONE(vp
));
890 ASSERT(!(t
->t_proc_flag
& TP_LWPEXIT
));
893 oprgetstatus(t
, ++prsp
, VTOZONE(vp
));
894 } while ((t
= t
->t_forw
) != p
->p_tlist
);
897 if (copyout(Bprsp
, cmaddr
, (Nlwp
+1) * sizeof (prstatus_t
)))
900 kmem_free(Bprsp
, (Nlwp
+1) * sizeof (prstatus_t
));
904 case PIOCPSINFO
: /* get ps(1) information */
906 prpsinfo_t
*psp
= &un
.prps
;
909 (pnp
->pr_type
== PR_LWPIDFILE
)? pcp
->prc_thread
: NULL
);
912 if (copyout(&un
.prps
, cmaddr
, sizeof (un
.prps
)))
917 case PIOCMAXSIG
: /* get maximum signal number */
922 if (copyout(&n
, cmaddr
, sizeof (n
)))
927 case PIOCACTION
: /* get signal action structures */
930 struct sigaction
*sap
= thing
;
933 for (sig
= 1; sig
< nsig
; sig
++)
934 prgetaction(p
, up
, sig
, &sap
[sig
-1]);
936 if (copyout(sap
, cmaddr
, (nsig
-1) * sizeof (struct sigaction
)))
938 kmem_free(sap
, (nsig
-1) * sizeof (struct sigaction
));
943 case PIOCGHOLD
: /* get signal-hold mask */
944 schedctl_finish_sigblock(t
);
945 sigktou(&t
->t_hold
, &un
.holdmask
);
947 if (copyout(&un
.holdmask
, cmaddr
, sizeof (un
.holdmask
)))
951 case PIOCSHOLD
: /* set signal-hold mask */
952 pr_sethold(pnp
, &un
.holdmask
);
956 case PIOCNMAP
: /* get number of memory mappings */
959 struct as
*as
= p
->p_as
;
961 if ((p
->p_flag
& SSYS
) || as
== &kas
)
964 mutex_exit(&p
->p_lock
);
965 AS_LOCK_ENTER(as
, RW_WRITER
);
968 mutex_enter(&p
->p_lock
);
971 if (copyout(&n
, cmaddr
, sizeof (int)))
976 case PIOCMAP
: /* get memory map information */
979 struct as
*as
= p
->p_as
;
981 if ((p
->p_flag
& SSYS
) || as
== &kas
) {
985 mutex_exit(&p
->p_lock
);
986 AS_LOCK_ENTER(as
, RW_WRITER
);
987 error
= oprgetmap(p
, &iolhead
);
989 mutex_enter(&p
->p_lock
);
992 error
= pr_iol_copyout_and_free(&iolhead
,
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
)))
1007 case PIOCGFAULT
: /* get mask of traced faults */
1008 prassignset(&un
.fltmask
, &p
->p_fltmask
);
1010 if (copyout(&un
.fltmask
, cmaddr
, sizeof (un
.fltmask
)))
1014 case PIOCSFAULT
: /* set mask of traced faults */
1015 pr_setfault(p
, &un
.fltmask
);
1019 case PIOCCFAULT
: /* clear current fault */
1020 lwp
->lwp_curflt
= 0;
1024 case PIOCCRED
: /* get process credentials */
1028 mutex_enter(&p
->p_crlock
);
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
);
1040 if (copyout(&un
.prcred
, cmaddr
, sizeof (un
.prcred
)))
1045 case PIOCGROUPS
: /* get supplementary groups */
1049 mutex_enter(&p
->p_crlock
);
1052 mutex_exit(&p
->p_crlock
);
1055 if (copyout(crgetgroups(cp
), cmaddr
,
1056 MAX(crgetngroups(cp
), 1) * sizeof (gid_t
)))
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
;
1072 bzero(pup
, sizeof (*pup
));
1073 pup
->pr_tstamp
= gethrtime();
1075 if (pnp
->pr_type
== PR_LWPIDFILE
) {
1076 t
= pcp
->prc_thread
;
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
)) {
1117 ASSERT(!(t
->t_proc_flag
& TP_LWPEXIT
));
1120 } while ((t
= t
->t_forw
) != p
->p_tlist
);
1126 upup
= kmem_zalloc(sizeof (*upup
), KM_SLEEP
);
1127 prcvtusage(&un
.prhusage
, upup
);
1128 if (copyout(upup
, cmaddr
, sizeof (*upup
)))
1130 kmem_free(upup
, sizeof (*upup
));
1135 case PIOCLUSAGE
: /* get detailed usage info */
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
);
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
) {
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
)) {
1210 ASSERT(!(t
->t_proc_flag
& TP_LWPEXIT
));
1215 prcvtusage(pup
, upup
);
1216 } while ((t
= t
->t_forw
) != p
->p_tlist
);
1221 if (copyout(Bupup
, cmaddr
, (Nlwp
+1) * sizeof (prusage_t
)))
1223 kmem_free(thing
, thingsize
);
1228 case PIOCNAUXV
: /* get number of aux vector entries */
1230 int n
= __KERN_NAUXV_IMPL
;
1233 if (copyout(&n
, cmaddr
, sizeof (int)))
1238 case PIOCAUXV
: /* get aux vector (see sys/auxv.h) */
1241 bcopy(up
->u_auxv
, un
.auxv
,
1242 __KERN_NAUXV_IMPL
* sizeof (auxv_t
));
1244 if (copyout(un
.auxv
, cmaddr
,
1245 __KERN_NAUXV_IMPL
* sizeof (auxv_t
)))
1250 #if defined(__i386) || defined(__amd64)
1251 case PIOCNLDT
: /* get number of LDT entries */
1255 mutex_exit(&p
->p_lock
);
1256 mutex_enter(&p
->p_ldtlock
);
1258 mutex_exit(&p
->p_ldtlock
);
1259 mutex_enter(&p
->p_lock
);
1261 if (copyout(&n
, cmaddr
, sizeof (n
)))
1266 case PIOCLDT
: /* get LDT entries */
1271 mutex_exit(&p
->p_lock
);
1272 mutex_enter(&p
->p_ldtlock
);
1275 if (thing
&& thingsize
!= (n
+1) * sizeof (*ssd
)) {
1276 kmem_free(thing
, thingsize
);
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
);
1294 mutex_exit(&p
->p_ldtlock
);
1295 mutex_enter(&p
->p_lock
);
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
)))
1302 kmem_free(ssd
, (n
+1) * sizeof (*ssd
));
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
);
1318 if (copyout(gwp
, cmaddr
, sizeof (*gwp
)))
1320 kmem_free(gwp
, sizeof (gwindows_t
));
1324 #endif /* __sparc */
1333 ASSERT(thing
== NULL
);
1334 ASSERT(xpnp
== NULL
);
1338 #ifdef _SYSCALL32_IMPL
1340 static int oprgetmap32(proc_t
*, list_t
*);
1343 oprgetstatus32(kthread_t
*t
, prstatus32_t
*sp
, zone_t
*zp
)
1345 proc_t
*p
= ttoproc(t
);
1346 klwp_t
*lwp
= ttolwp(t
);
1351 ASSERT(MUTEX_HELD(&p
->p_lock
));
1354 bzero(sp
, sizeof (*sp
));
1356 if (t
->t_state
== TS_STOPPED
) {
1357 flags
|= PR_STOPPED
;
1358 if ((t
->t_schedflag
& TS_PSTART
) == 0)
1360 } else if (VSTOPPED(t
)) {
1361 flags
|= PR_STOPPED
|PR_ISTOP
;
1363 if (!(flags
& PR_ISTOP
) && (t
->t_proc_flag
& TP_PRSTOP
))
1365 if (lwp
->lwp_asleep
)
1367 if (p
->p_proc_flag
& P_PR_FORK
)
1369 if (p
->p_proc_flag
& P_PR_RUNLCL
)
1371 if (p
->p_proc_flag
& P_PR_KILLCL
)
1373 if (p
->p_proc_flag
& P_PR_ASYNC
)
1375 if (p
->p_proc_flag
& P_PR_BPTADJ
)
1377 if (p
->p_proc_flag
& P_PR_PTRACE
)
1378 flags
|= PR_PCOMPAT
;
1379 if (t
->t_proc_flag
& TP_MSACCT
)
1381 sp
->pr_flags
= flags
;
1383 sp
->pr_why
= PR_REQUESTED
;
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
;
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
;
1457 sp
->pr_instr
= (uint32_t)instr
;
1460 * Drop p_lock while touching the lwp's stack.
1462 mutex_exit(&p
->p_lock
);
1464 sp
->pr_flags
|= PR_STEP
;
1465 if ((flags
& (PR_STOPPED
|PR_ASLEEP
)) && t
->t_sysnum
) {
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]);
1479 if (auxp
->a_type
== AT_SUN_EXECNAME
) {
1482 (uintptr_t)auxp
->a_un
.a_ptr
;
1488 if ((flags
& PR_STOPPED
) || t
== curthread
)
1489 prgetprregs32(lwp
, sp
->pr_reg
);
1490 mutex_enter(&p
->p_lock
);
1494 oprgetpsinfo32(proc_t
*p
, prpsinfo32_t
*psp
, kthread_t
*tp
)
1501 int retval
, niceval
;
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 */
1515 /* kludge: map thread state enum into process state enum */
1520 state
= VSTOPPED(t
) ? TS_STOPPED
: t
->t_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;
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;
1540 case SXBRK
: c
= 'X'; break;
1542 default: c
= '?'; break;
1544 psp
->pr_state
= state
;
1546 psp
->pr_zomb
= (state
== SZOMB
);
1548 * only export SSYS and SMSACCT; everything else is off-limits to
1551 psp
->pr_flag
= p
->p_flag
& (SSYS
| SMSACCT
);
1553 mutex_enter(&p
->p_crlock
);
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
;
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
;
1584 case DATAMODEL_LP64
:
1585 psp
->pr_dmodel
= PR_MODEL_LP64
;
1588 if (state
== SZOMB
|| t
== NULL
) {
1589 int wcode
= p
->p_wcode
; /* must be atomic read */
1592 psp
->pr_wstat
= wstat(wcode
, p
->p_wdata
);
1593 psp
->pr_lttydev
= PRNODEV32
;
1594 psp
->pr_ottydev
= (o_dev_t
)PRNODEV32
;
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
);
1606 psp
->pr_oldpri
= v
.v_maxsyspri
- psp
->pr_pri
;
1607 psp
->pr_nice
= niceval
+ NZERO
;
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
)
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 */
1640 if ((t
= tp
) == NULL
)
1642 cur_time
= gethrtime_unscaled();
1644 pct
+= cpu_update_pct(t
, cur_time
);
1645 if (tp
!= NULL
) /* just do the one lwp */
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)
1654 if ((p
->p_flag
& SSYS
) || (as
= p
->p_as
) == &kas
) {
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
);
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
) {
1679 psp
->pr_byrssize
= 0;
1694 caller_context_t
*ct
)
1696 int nsig
= PROC_IS_BRANDED(curproc
)? BROP(curproc
)->b_nsig
: NSIG
;
1697 caddr_t cmaddr
= (caddr_t
)arg
;
1702 prnode_t
*pnp
= VTOP(vp
);
1704 prnode_t
*xpnp
= NULL
;
1708 size_t thingsize
= 0;
1711 * For copyin()/copyout().
1719 prstatus32_t prstat
;
1725 prfpregset32_t fpregs
;
1730 prusage32_t prusage
;
1731 prhusage_t prhusage
;
1732 ioc_prmap32_t prmap
;
1733 auxv32_t auxv
[__KERN_NAUXV_IMPL
];
1737 * Native objects for internal use.
1756 prhusage_t prhusage
;
1757 auxv_t auxv
[__KERN_NAUXV_IMPL
];
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
;
1770 ASSERT(pnp
->pr_type
== PR_PIDFILE
);
1773 if (pnp
->pr_type
!= PR_PIDFILE
&& pnp
->pr_type
!= PR_LWPIDFILE
)
1777 * Fail ioctls which are logically "write" requests unless
1778 * the user has write permission.
1780 if ((flag
& FWRITE
) == 0 && isprwrioctl(cmd
))
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,
1797 thingsize
= sizeof (proc_t
);
1800 thingsize
= sizeof (user_t
);
1820 case PIOCSXREG
: /* set extra registers */
1821 case PIOCGXREG
: /* get extra registers */
1822 #if defined(__sparc)
1823 thingsize
= sizeof (prxregset_t
);
1829 thingsize
= (nsig
-1) * sizeof (struct sigaction32
);
1843 * We will need this below.
1844 * Allocate it now, before locking the process.
1846 xpnp
= prgetnode(vp
, PR_OPAGEDATA
);
1852 #if defined(__i386) || defined(__i386_COMPAT)
1856 #endif /* __i386 || __i386_COMPAT */
1858 #if defined(__sparc)
1860 thingsize
= sizeof (gwindows32_t
);
1862 #endif /* __sparc */
1864 case PIOCOPENM
: /* open mapped object for reading */
1867 else if (copyin(cmaddr
, &un32
.va
, sizeof (un32
.va
)))
1871 case PIOCRUN
: /* make lwp or process runnable */
1873 un32
.prrun
.pr_flags
= 0;
1874 else if (copyin(cmaddr
, &un32
.prrun
, sizeof (un32
.prrun
)))
1878 case PIOCOPENLWP
: /* return /proc lwp file descriptor */
1879 if (copyin(cmaddr
, &un32
.lwpid
, sizeof (un32
.lwpid
)))
1883 case PIOCSTRACE
: /* set signal trace mask */
1884 if (copyin(cmaddr
, &un32
.smask
, sizeof (un32
.smask
)))
1888 case PIOCSSIG
: /* set current signal */
1890 un32
.info
.si_signo
= 0;
1891 else if (copyin(cmaddr
, &un32
.info
, sizeof (un32
.info
)))
1895 case PIOCKILL
: /* send signal */
1896 case PIOCUNKILL
: /* delete a signal */
1897 if (copyin(cmaddr
, &un32
.signo
, sizeof (un32
.signo
)))
1901 case PIOCNICE
: /* set nice priority */
1902 if (copyin(cmaddr
, &un32
.nice
, sizeof (un32
.nice
)))
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
)))
1912 case PIOCSET
: /* set process flags */
1913 case PIOCRESET
: /* reset process flags */
1914 if (copyin(cmaddr
, &un32
.flags
, sizeof (un32
.flags
)))
1918 case PIOCSREG
: /* set general registers */
1919 if (copyin(cmaddr
, un32
.regs
, sizeof (un32
.regs
)))
1923 case PIOCSFPREG
: /* set floating-point registers */
1924 if (copyin(cmaddr
, &un32
.fpregs
, sizeof (un32
.fpregs
)))
1928 case PIOCSHOLD
: /* set signal-hold mask */
1929 if (copyin(cmaddr
, &un32
.holdmask
, sizeof (un32
.holdmask
)))
1933 case PIOCSFAULT
: /* set mask of traced faults */
1934 if (copyin(cmaddr
, &un32
.fltmask
, sizeof (un32
.fltmask
)))
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.)
1956 ASSERT(thing
== NULL
);
1957 thing
= kmem_alloc(thingsize
, KM_SLEEP
);
1967 case PIOCSXREG
: /* set extra registers */
1969 * perform copyin before grabbing the process lock
1972 if (copyin(cmaddr
, thing
, thingsize
)) {
1973 kmem_free(thing
, thingsize
);
1977 /* fall through... */
1983 if ((error
= prlock(pnp
, zdisp
)) != 0) {
1985 kmem_free(thing
, thingsize
);
1991 pcp
= pnp
->pr_common
;
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
;
2003 t
= prchoose(p
); /* returns locked thread */
2013 case PIOCGETPR
: /* read struct proc */
2015 proc_t
*prp
= thing
;
2019 if (copyout(prp
, cmaddr
, sizeof (proc_t
)))
2021 kmem_free(prp
, sizeof (proc_t
));
2026 case PIOCGETU
: /* read u-area */
2028 user_t
*userp
= thing
;
2033 if (copyout(userp
, cmaddr
, sizeof (user_t
)))
2035 kmem_free(userp
, sizeof (user_t
));
2040 case PIOCOPENM
: /* open mapped object for reading */
2041 if (PROCESS_NOT_32BIT(p
) && cmaddr
!= NULL
) {
2046 error
= propenm(pnp
, cmaddr
,
2047 (caddr_t
)(uintptr_t)un32
.va
, rvalp
, cr
);
2048 /* propenm() called prunlock(pnp) */
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
) {
2062 if (cmd
== PIOCSTOP
)
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
)
2077 if ((error
= pr_wait_stop(pnp
, (time_t)0)) != 0)
2078 break; /* pr_wait_stop() unlocked the process */
2082 else if (PROCESS_NOT_32BIT(p
)) {
2087 * Return process/lwp status information.
2089 t
= pr_thread(pnp
); /* returns locked thread */
2091 oprgetstatus32(t
, &un32
.prstat
, VTOZONE(vp
));
2093 if (copyout(&un32
.prstat
, cmaddr
, sizeof (un32
.prstat
)))
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
))) {
2116 if ((flags
& PRSVADDR
) && PROCESS_NOT_32BIT(p
)) {
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
;
2128 (caddr_t
)(uintptr_t)un32
.prrun
.pr_vaddr
;
2129 prsetrun(t
, &un
.prrun
);
2132 error
= pr_setrun(pnp
, prmaprunflags(flags
));
2138 case PIOCLWPIDS
: /* get array of lwp identifiers */
2145 Nlwp
= nlwp
= p
->p_lwpcnt
;
2147 if (thing
&& thingsize
!= (Nlwp
+1) * sizeof (id_t
)) {
2148 kmem_free(thing
, thingsize
);
2151 if (thing
== NULL
) {
2152 thingsize
= (Nlwp
+1) * sizeof (id_t
);
2153 thing
= kmem_alloc(thingsize
, KM_NOSLEEP
);
2155 if (thing
== NULL
) {
2163 if ((t
= p
->p_tlist
) != NULL
) {
2165 ASSERT(!(t
->t_proc_flag
& TP_LWPEXIT
));
2169 } while ((t
= t
->t_forw
) != p
->p_tlist
);
2174 if (copyout(Bidp
, cmaddr
, (Nlwp
+1) * sizeof (id_t
)))
2176 kmem_free(Bidp
, (Nlwp
+1) * sizeof (id_t
));
2180 case PIOCOPENLWP
: /* return /proc lwp file descriptor */
2186 if ((xvp
= prlwpnode(pnp
, un32
.lwpid
)) == NULL
)
2188 else if (error
= fassign(&xvp
, flag
& (FREAD
|FWRITE
), &n
)) {
2195 case PIOCOPENPD
: /* return /proc page data file descriptor */
2197 vnode_t
*xvp
= PTOV(xpnp
);
2198 vnode_t
*dp
= pnp
->pr_parent
;
2201 if (PROCESS_NOT_32BIT(p
)) {
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
);
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
;
2226 if (error
= fassign(&xvp
, FREAD
, &n
)) {
2235 case PIOCGTRACE
: /* get signal trace mask */
2236 prassignset(&un32
.smask
, &p
->p_sigmask
);
2238 if (copyout(&un32
.smask
, cmaddr
, sizeof (un32
.smask
)))
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
)) {
2249 if (up
->u_systrap
== 0)
2250 p
->p_proc_flag
&= ~P_PR_TRACE
;
2255 case PIOCSSIG
: /* set current signal */
2256 if (un32
.info
.si_signo
!= 0 && PROCESS_NOT_32BIT(p
)) {
2260 bzero(&un
.info
, sizeof (un
.info
));
2261 siginfo_32tok(&un32
.info
, (k_siginfo_t
*)&un
.info
);
2262 error
= pr_setsig(pnp
, &un
.info
);
2264 if (un32
.info
.si_signo
== SIGKILL
&& error
== 0)
2269 case PIOCKILL
: /* send signal */
2270 error
= pr_kill(pnp
, un32
.signo
, cr
);
2272 if (un32
.signo
== SIGKILL
&& error
== 0)
2276 case PIOCUNKILL
: /* delete a signal */
2277 error
= pr_unkill(pnp
, un32
.signo
);
2281 case PIOCNICE
: /* set nice priority */
2282 error
= pr_nice(p
, un32
.nice
, cr
);
2286 case PIOCGENTRY
: /* get syscall entry bit mask */
2287 case PIOCGEXIT
: /* get syscall exit bit mask */
2289 if (cmd
== PIOCGENTRY
) {
2290 prassignset(&un32
.prmask
, &up
->u_entrymask
);
2292 prassignset(&un32
.prmask
, &up
->u_exitmask
);
2295 if (copyout(&un32
.prmask
, cmaddr
, sizeof (un32
.prmask
)))
2299 case PIOCSENTRY
: /* set syscall entry bit mask */
2300 case PIOCSEXIT
: /* set syscall exit bit mask */
2301 pr_setentryexit(p
, &un32
.prmask
, cmd
== PIOCSENTRY
);
2305 case PIOCSRLC
: /* obsolete: set running on last /proc close */
2306 error
= pr_set(p
, prmapsetflags(PR_RLC
));
2310 case PIOCRRLC
: /* obsolete: reset run-on-last-close flag */
2311 error
= pr_unset(p
, prmapsetflags(PR_RLC
));
2315 case PIOCSFORK
: /* obsolete: set inherit-on-fork flag */
2316 error
= pr_set(p
, prmapsetflags(PR_FORK
));
2320 case PIOCRFORK
: /* obsolete: reset inherit-on-fork flag */
2321 error
= pr_unset(p
, prmapsetflags(PR_FORK
));
2325 case PIOCSET
: /* set process flags */
2326 error
= pr_set(p
, prmapsetflags((long)un32
.flags
));
2330 case PIOCRESET
: /* reset process flags */
2331 error
= pr_unset(p
, prmapsetflags((long)un32
.flags
));
2335 case PIOCGREG
: /* get general registers */
2336 if (PROCESS_NOT_32BIT(p
))
2338 else if (t
->t_state
!= TS_STOPPED
&& !VSTOPPED(t
))
2339 bzero(un32
.regs
, sizeof (un32
.regs
));
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
);
2348 copyout(un32
.regs
, cmaddr
, sizeof (un32
.regs
)))
2352 case PIOCSREG
: /* set general registers */
2353 if (PROCESS_NOT_32BIT(p
))
2355 else if (!ISTOPPED(t
) && !VSTOPPED(t
) && !DSTOPPED(t
))
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
);
2367 case PIOCGFPREG
: /* get floating-point registers */
2369 error
= EINVAL
; /* No FP support */
2370 else if (PROCESS_NOT_32BIT(p
))
2372 else if (t
->t_state
!= TS_STOPPED
&& !VSTOPPED(t
))
2373 bzero(&un32
.fpregs
, sizeof (un32
.fpregs
));
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
);
2382 copyout(&un32
.fpregs
, cmaddr
, sizeof (un32
.fpregs
)))
2386 case PIOCSFPREG
: /* set floating-point registers */
2388 error
= EINVAL
; /* No FP support */
2389 else if (PROCESS_NOT_32BIT(p
))
2391 else if (!ISTOPPED(t
) && !VSTOPPED(t
) && !DSTOPPED(t
))
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
);
2402 case PIOCGXREGSIZE
: /* get the size of the extra registers */
2407 xregsize
= prgetprxregsize(p
);
2409 if (copyout(&xregsize
, cmaddr
, sizeof (xregsize
)))
2413 error
= EINVAL
; /* No extra register support */
2418 case PIOCGXREG
: /* get extra registers */
2419 if (PROCESS_NOT_32BIT(p
))
2421 else if (!prhasx(p
))
2422 error
= EINVAL
; /* No extra register support */
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
);
2434 copyout(thing
, cmaddr
, thingsize
))
2437 kmem_free(thing
, thingsize
);
2442 case PIOCSXREG
: /* set extra registers */
2443 if (PROCESS_NOT_32BIT(p
))
2445 else if (!ISTOPPED(t
) && !VSTOPPED(t
) && !DSTOPPED(t
))
2447 else if (!prhasx(p
))
2448 error
= EINVAL
; /* No extra register support */
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
);
2457 kmem_free(thing
, thingsize
);
2462 case PIOCSTATUS
: /* get process/lwp status */
2463 if (PROCESS_NOT_32BIT(p
)) {
2468 oprgetstatus32(t
, &un32
.prstat
, VTOZONE(vp
));
2470 if (copyout(&un32
.prstat
, cmaddr
, sizeof (un32
.prstat
)))
2474 case PIOCLSTATUS
: /* get status for process & all lwps */
2478 prstatus32_t
*Bprsp
;
2481 if (PROCESS_NOT_32BIT(p
)) {
2484 kmem_free(thing
, thingsize
);
2491 nlwp
= Nlwp
= p
->p_lwpcnt
;
2493 if (thing
&& thingsize
!= (Nlwp
+1) * sizeof (prstatus32_t
)) {
2494 kmem_free(thing
, thingsize
);
2497 if (thing
== NULL
) {
2498 thingsize
= (Nlwp
+1) * sizeof (prstatus32_t
);
2499 thing
= kmem_alloc(thingsize
, KM_NOSLEEP
);
2501 if (thing
== NULL
) {
2506 Bprsp
= (prstatus32_t
*)thing
;
2509 oprgetstatus32(t
, prsp
, VTOZONE(vp
));
2512 ASSERT(!(t
->t_proc_flag
& TP_LWPEXIT
));
2515 oprgetstatus32(t
, ++prsp
, VTOZONE(vp
));
2516 } while ((t
= t
->t_forw
) != p
->p_tlist
);
2519 if (copyout(Bprsp
, cmaddr
, (Nlwp
+1) * sizeof (prstatus32_t
)))
2522 kmem_free(Bprsp
, (Nlwp
+ 1) * sizeof (prstatus32_t
));
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
);
2534 if (copyout(&un32
.prps
, cmaddr
, sizeof (un32
.prps
)))
2539 case PIOCMAXSIG
: /* get maximum signal number */
2544 if (copyout(&n
, cmaddr
, sizeof (int)))
2549 case PIOCACTION
: /* get signal action structures */
2552 struct sigaction32
*sap
= thing
;
2554 if (PROCESS_NOT_32BIT(p
))
2558 for (sig
= 1; sig
< nsig
; sig
++)
2559 prgetaction32(p
, up
, sig
, &sap
[sig
-1]);
2563 copyout(sap
, cmaddr
, (nsig
-1)*sizeof (struct sigaction32
)))
2565 kmem_free(sap
, (nsig
-1)*sizeof (struct sigaction32
));
2570 case PIOCGHOLD
: /* get signal-hold mask */
2571 schedctl_finish_sigblock(t
);
2572 sigktou(&t
->t_hold
, &un32
.holdmask
);
2574 if (copyout(&un32
.holdmask
, cmaddr
, sizeof (un32
.holdmask
)))
2578 case PIOCSHOLD
: /* set signal-hold mask */
2579 pr_sethold(pnp
, &un32
.holdmask
);
2583 case PIOCNMAP
: /* get number of memory mappings */
2586 struct as
*as
= p
->p_as
;
2588 if ((p
->p_flag
& SSYS
) || as
== &kas
)
2591 mutex_exit(&p
->p_lock
);
2592 AS_LOCK_ENTER(as
, RW_WRITER
);
2595 mutex_enter(&p
->p_lock
);
2598 if (copyout(&n
, cmaddr
, sizeof (int)))
2603 case PIOCMAP
: /* get memory map information */
2606 struct as
*as
= p
->p_as
;
2608 if ((p
->p_flag
& SSYS
) || as
== &kas
) {
2611 } else if (PROCESS_NOT_32BIT(p
)) {
2615 mutex_exit(&p
->p_lock
);
2616 AS_LOCK_ENTER(as
, RW_WRITER
);
2617 error
= oprgetmap32(p
, &iolhead
);
2619 mutex_enter(&p
->p_lock
);
2622 error
= pr_iol_copyout_and_free(&iolhead
,
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
));
2632 copyout(&un32
.prmap
, cmaddr
, sizeof (un32
.prmap
)))
2637 case PIOCGFAULT
: /* get mask of traced faults */
2638 prassignset(&un32
.fltmask
, &p
->p_fltmask
);
2640 if (copyout(&un32
.fltmask
, cmaddr
, sizeof (un32
.fltmask
)))
2644 case PIOCSFAULT
: /* set mask of traced faults */
2645 pr_setfault(p
, &un32
.fltmask
);
2649 case PIOCCFAULT
: /* clear current fault */
2650 lwp
->lwp_curflt
= 0;
2654 case PIOCCRED
: /* get process credentials */
2658 mutex_enter(&p
->p_crlock
);
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
);
2670 if (copyout(&un32
.prcred
, cmaddr
, sizeof (un32
.prcred
)))
2675 case PIOCGROUPS
: /* get supplementary groups */
2679 mutex_enter(&p
->p_crlock
);
2682 mutex_exit(&p
->p_crlock
);
2685 if (copyout(crgetgroups(cp
), cmaddr
,
2686 MAX(crgetngroups(cp
), 1) * sizeof (gid_t
)))
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
;
2702 bzero(pup
, sizeof (*pup
));
2703 pup
->pr_tstamp
= gethrtime();
2705 if (pnp
->pr_type
== PR_LWPIDFILE
) {
2706 t
= pcp
->prc_thread
;
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
)) {
2747 ASSERT(!(t
->t_proc_flag
& TP_LWPEXIT
));
2750 } while ((t
= t
->t_forw
) != p
->p_tlist
);
2756 upup
= kmem_alloc(sizeof (*upup
), KM_SLEEP
);
2757 prcvtusage32(pup
, upup
);
2758 if (copyout(upup
, cmaddr
, sizeof (*upup
)))
2760 kmem_free(upup
, sizeof (*upup
));
2765 case PIOCLUSAGE
: /* get detailed usage info */
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
);
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
) {
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
)) {
2840 ASSERT(!(t
->t_proc_flag
& TP_LWPEXIT
));
2845 prcvtusage32(pup
, upup
);
2846 } while ((t
= t
->t_forw
) != p
->p_tlist
);
2851 if (copyout(Bupup
, cmaddr
, (Nlwp
+1) * sizeof (prusage32_t
)))
2853 kmem_free(thing
, thingsize
);
2858 case PIOCNAUXV
: /* get number of aux vector entries */
2860 int n
= __KERN_NAUXV_IMPL
;
2863 if (copyout(&n
, cmaddr
, sizeof (int)))
2868 case PIOCAUXV
: /* get aux vector (see sys/auxv.h) */
2872 if (PROCESS_NOT_32BIT(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
;
2883 if (copyout(un32
.auxv
, cmaddr
,
2884 __KERN_NAUXV_IMPL
* sizeof (auxv32_t
)))
2890 #if defined(__i386) || defined(__i386_COMPAT)
2891 case PIOCNLDT
: /* get number of LDT entries */
2895 mutex_exit(&p
->p_lock
);
2896 mutex_enter(&p
->p_ldtlock
);
2898 mutex_exit(&p
->p_ldtlock
);
2899 mutex_enter(&p
->p_lock
);
2901 if (copyout(&n
, cmaddr
, sizeof (n
)))
2906 case PIOCLDT
: /* get LDT entries */
2911 mutex_exit(&p
->p_lock
);
2912 mutex_enter(&p
->p_ldtlock
);
2915 if (thing
&& thingsize
!= (n
+1) * sizeof (*ssd
)) {
2916 kmem_free(thing
, thingsize
);
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
);
2934 mutex_exit(&p
->p_ldtlock
);
2935 mutex_enter(&p
->p_lock
);
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
)))
2942 kmem_free(ssd
, (n
+1) * sizeof (*ssd
));
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
)) {
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
);
2962 if (copyout(gwp
, cmaddr
, sizeof (*gwp
)))
2965 kmem_free(gwp
, sizeof (*gwp
));
2969 #endif /* __sparc */
2978 ASSERT(thing
== NULL
);
2979 ASSERT(xpnp
== NULL
);
2982 #endif /* _SYSCALL32_IMPL */
2985 * Distinguish "writeable" ioctl requests from others.
2988 isprwrioctl(int cmd
)
3018 * Map the ioctl() interface run flags to the new interface run flags.
3021 prmaprunflags(long flags
)
3023 ulong_t newflags
= 0;
3027 if (flags
& PRCFAULT
)
3031 if (flags
& PRSABORT
)
3039 * Map the ioctl() interface settable mode flags to the new interface flags.
3042 prmapsetflags(long flags
)
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);
3054 newflags
|= 0x00200000;
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;
3069 * Apply PIOCRUN options specific to the ioctl() interface.
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.
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
;
3132 * By fiat, a system process has no address space.
3134 if ((p
->p_flag
& SSYS
) || as
== &kas
) {
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
);
3148 seg
->s_ops
== &segvn_ops
&&
3149 SEGOP_GETVP(seg
, va
, &xvp
) == 0 &&
3151 xvp
->v_type
== VREG
) {
3157 mutex_enter(&p
->p_lock
);
3158 } else if ((xvp
= p
->p_exec
) == NULL
) {
3167 if ((error
= VOP_ACCESS(xvp
, VREAD
, 0, cr
, NULL
)) == 0)
3168 error
= fassign(&xvp
, FREAD
, &n
);
3180 * Return old version of process/lwp status.
3181 * The u-block is mapped in by this routine and unmapped at the end.
3184 oprgetstatus(kthread_t
*t
, prstatus_t
*sp
, zone_t
*zp
)
3186 proc_t
*p
= ttoproc(t
);
3187 klwp_t
*lwp
= ttolwp(t
);
3192 ASSERT(MUTEX_HELD(&p
->p_lock
));
3195 bzero(sp
, sizeof (*sp
));
3197 if (t
->t_state
== TS_STOPPED
) {
3198 flags
|= PR_STOPPED
;
3199 if ((t
->t_schedflag
& TS_PSTART
) == 0)
3201 } else if (VSTOPPED(t
)) {
3202 flags
|= PR_STOPPED
|PR_ISTOP
;
3204 if (!(flags
& PR_ISTOP
) && (t
->t_proc_flag
& TP_PRSTOP
))
3206 if (lwp
->lwp_asleep
)
3208 if (p
->p_proc_flag
& P_PR_FORK
)
3210 if (p
->p_proc_flag
& P_PR_RUNLCL
)
3212 if (p
->p_proc_flag
& P_PR_KILLCL
)
3214 if (p
->p_proc_flag
& P_PR_ASYNC
)
3216 if (p
->p_proc_flag
& P_PR_BPTADJ
)
3218 if (p
->p_proc_flag
& P_PR_PTRACE
)
3219 flags
|= PR_PCOMPAT
;
3220 if (t
->t_proc_flag
& TP_MSACCT
)
3222 sp
->pr_flags
= flags
;
3224 sp
->pr_why
= PR_REQUESTED
;
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
;
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
;
3294 sp
->pr_instr
= instr
;
3297 * Drop p_lock while touching the lwp's stack.
3299 mutex_exit(&p
->p_lock
);
3301 sp
->pr_flags
|= PR_STEP
;
3302 if ((flags
& (PR_STOPPED
|PR_ASLEEP
)) && t
->t_sysnum
) {
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]);
3316 if (auxp
->a_type
== AT_SUN_EXECNAME
) {
3318 (uintptr_t)auxp
->a_un
.a_ptr
;
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).
3333 oprgetpsinfo(proc_t
*p
, prpsinfo_t
*psp
, kthread_t
*tp
)
3340 int retval
, niceval
;
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 */
3354 /* kludge: map thread state enum into process state enum */
3359 state
= VSTOPPED(t
) ? TS_STOPPED
: t
->t_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;
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;
3379 case SXBRK
: c
= 'X'; break;
3381 default: c
= '?'; break;
3383 psp
->pr_state
= state
;
3385 psp
->pr_zomb
= (state
== SZOMB
);
3387 * only export SSYS and SMSACCT; everything else is off-limits to
3390 psp
->pr_flag
= p
->p_flag
& (SSYS
| SMSACCT
);
3392 mutex_enter(&p
->p_crlock
);
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
;
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
;
3423 case DATAMODEL_LP64
:
3424 psp
->pr_dmodel
= PR_MODEL_LP64
;
3427 if (state
== SZOMB
|| t
== NULL
) {
3428 int wcode
= p
->p_wcode
; /* must be atomic read */
3431 psp
->pr_wstat
= wstat(wcode
, p
->p_wdata
);
3432 psp
->pr_lttydev
= PRNODEV
;
3433 psp
->pr_ottydev
= (o_dev_t
)PRNODEV
;
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
);
3445 psp
->pr_oldpri
= v
.v_maxsyspri
- psp
->pr_pri
;
3446 psp
->pr_nice
= niceval
+ NZERO
;
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
)
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 */
3479 if ((t
= tp
) == NULL
)
3481 cur_time
= gethrtime_unscaled();
3483 pct
+= cpu_update_pct(t
, cur_time
);
3484 if (tp
!= NULL
) /* just do the one lwp */
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)
3493 if ((p
->p_flag
& SSYS
) || (as
= p
->p_as
) == &kas
) {
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
);
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.
3518 oprgetmap(proc_t
*p
, list_t
*iolhead
)
3520 struct as
*as
= p
->p_as
;
3523 struct seg
*brkseg
, *stkseg
;
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
)
3537 brkseg
= break_seg(p
);
3538 stkseg
= as_segat(as
, prgetstackbase(p
));
3541 caddr_t eaddr
= seg
->s_base
+ pr_getsegsize(seg
, 0);
3542 caddr_t saddr
, naddr
;
3545 for (saddr
= seg
->s_base
; saddr
< eaddr
; saddr
= naddr
) {
3546 prot
= pr_getprot(seg
, 0, &tmp
, &saddr
, &naddr
, eaddr
);
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
);
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
;
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
);
3576 #ifdef _SYSCALL32_IMPL
3578 oprgetmap32(proc_t
*p
, list_t
*iolhead
)
3580 struct as
*as
= p
->p_as
;
3583 struct seg
*brkseg
, *stkseg
;
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
)
3597 brkseg
= break_seg(p
);
3598 stkseg
= as_segat(as
, prgetstackbase(p
));
3601 caddr_t eaddr
= seg
->s_base
+ pr_getsegsize(seg
, 0);
3602 caddr_t saddr
, naddr
;
3605 for (saddr
= seg
->s_base
; saddr
< eaddr
; saddr
= naddr
) {
3606 prot
= pr_getprot(seg
, 0, &tmp
, &saddr
, &naddr
, eaddr
);
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
);
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
;
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
);
3635 #endif /* _SYSCALL32_IMPL */
3638 * Return the size of the old /proc page data file.
3641 oprpdsize(struct as
*as
)
3646 ASSERT(as
!= &kas
&& AS_WRITE_HELD(as
));
3648 if ((seg
= AS_SEGFIRST(as
)) == NULL
)
3651 size
= sizeof (prpageheader_t
);
3653 caddr_t eaddr
= seg
->s_base
+ pr_getsegsize(seg
, 0);
3654 caddr_t saddr
, naddr
;
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
);
3669 #ifdef _SYSCALL32_IMPL
3671 oprpdsize32(struct as
*as
)
3676 ASSERT(as
!= &kas
&& AS_WRITE_HELD(as
));
3678 if ((seg
= AS_SEGFIRST(as
)) == NULL
)
3681 size
= sizeof (ioc_prpageheader32_t
);
3683 caddr_t eaddr
= seg
->s_base
+ pr_getsegsize(seg
, 0);
3684 caddr_t saddr
, naddr
;
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
);
3698 #endif /* _SYSCALL32_IMPL */
3701 * Read old /proc page data information.
3704 oprpdread(struct as
*as
, uint_t hatid
, struct uio
*uiop
)
3708 prpageheader_t
*php
;
3714 AS_LOCK_ENTER(as
, RW_WRITER
);
3716 if ((seg
= AS_SEGFIRST(as
)) == NULL
) {
3720 size
= oprpdsize(as
);
3721 if (uiop
->uio_resid
< size
) {
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
);
3734 caddr_t eaddr
= seg
->s_base
+ pr_getsegsize(seg
, 0);
3735 caddr_t saddr
, naddr
;
3738 for (saddr
= seg
->s_base
; saddr
< eaddr
; saddr
= naddr
) {
3744 prot
= pr_getprot(seg
, 0, &tmp
, &saddr
, &naddr
, eaddr
);
3745 if ((len
= naddr
- saddr
) == 0)
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
);
3770 kmem_free(buf
, size
);
3772 if (ISSIG(curthread
, JUSTLOOKING
))
3779 php
->pr_npage
+= npage
;
3780 pmp
->pr_vaddr
= saddr
;
3781 pmp
->pr_npage
= npage
;
3782 pmp
->pr_off
= SEGOP_GETOFFSET(seg
, saddr
);
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
);
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
);
3809 #ifdef _SYSCALL32_IMPL
3811 oprpdread32(struct as
*as
, uint_t hatid
, struct uio
*uiop
)
3815 ioc_prpageheader32_t
*php
;
3816 ioc_prasmap32_t
*pmp
;
3821 AS_LOCK_ENTER(as
, RW_WRITER
);
3823 if ((seg
= AS_SEGFIRST(as
)) == NULL
) {
3827 size
= oprpdsize32(as
);
3828 if (uiop
->uio_resid
< size
) {
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
);
3841 caddr_t eaddr
= seg
->s_base
+ pr_getsegsize(seg
, 0);
3842 caddr_t saddr
, naddr
;
3845 for (saddr
= seg
->s_base
; saddr
< eaddr
; saddr
= naddr
) {
3851 prot
= pr_getprot(seg
, 0, &tmp
, &saddr
, &naddr
, eaddr
);
3852 if ((len
= naddr
- saddr
) == 0)
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
);
3877 kmem_free(buf
, size
);
3879 if (ISSIG(curthread
, JUSTLOOKING
))
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
);
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
);
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
);
3915 #endif /* _SYSCALL32_IMPL */
3918 #ifdef _SYSCALL32_IMPL
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
));
3938 #endif /* _SYSCALL32_IMPL */