10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52789Sfrankho * Common Development and Distribution License (the "License").
62789Sfrankho * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*11940SRoger.Faulkner@Sun.COM
220Sstevel@tonic-gate /*
2311798SRoger.Faulkner@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
280Sstevel@tonic-gate /* All rights reserved. */
290Sstevel@tonic-gate
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <sys/param.h>
320Sstevel@tonic-gate #include <sys/vmparam.h>
330Sstevel@tonic-gate #include <sys/var.h>
340Sstevel@tonic-gate #include <sys/cmn_err.h>
350Sstevel@tonic-gate #include <sys/cred.h>
360Sstevel@tonic-gate #include <sys/debug.h>
370Sstevel@tonic-gate #include <sys/errno.h>
380Sstevel@tonic-gate #include <sys/file.h>
390Sstevel@tonic-gate #include <sys/inline.h>
400Sstevel@tonic-gate #include <sys/kmem.h>
410Sstevel@tonic-gate #include <sys/proc.h>
42*11940SRoger.Faulkner@Sun.COM #include <sys/brand.h>
430Sstevel@tonic-gate #include <sys/sysmacros.h>
440Sstevel@tonic-gate #include <sys/systm.h>
450Sstevel@tonic-gate #include <sys/vfs.h>
460Sstevel@tonic-gate #include <sys/vnode.h>
470Sstevel@tonic-gate #include <sys/cpuvar.h>
480Sstevel@tonic-gate #include <sys/session.h>
490Sstevel@tonic-gate #include <sys/signal.h>
500Sstevel@tonic-gate #include <sys/auxv.h>
510Sstevel@tonic-gate #include <sys/user.h>
520Sstevel@tonic-gate #include <sys/disp.h>
530Sstevel@tonic-gate #include <sys/class.h>
540Sstevel@tonic-gate #include <sys/ts.h>
550Sstevel@tonic-gate #include <sys/mman.h>
560Sstevel@tonic-gate #include <sys/fault.h>
570Sstevel@tonic-gate #include <sys/syscall.h>
580Sstevel@tonic-gate #include <sys/schedctl.h>
590Sstevel@tonic-gate #include <sys/pset.h>
600Sstevel@tonic-gate #include <sys/old_procfs.h>
610Sstevel@tonic-gate #include <sys/zone.h>
620Sstevel@tonic-gate #include <sys/time.h>
630Sstevel@tonic-gate #include <sys/msacct.h>
640Sstevel@tonic-gate #include <vm/rm.h>
650Sstevel@tonic-gate #include <vm/as.h>
660Sstevel@tonic-gate #include <vm/rm.h>
670Sstevel@tonic-gate #include <vm/seg.h>
680Sstevel@tonic-gate #include <vm/seg_vn.h>
690Sstevel@tonic-gate #include <sys/contract_impl.h>
700Sstevel@tonic-gate #include <sys/ctfs_impl.h>
710Sstevel@tonic-gate #include <sys/ctfs.h>
720Sstevel@tonic-gate
730Sstevel@tonic-gate #if defined(__i386) || defined(__i386_COMPAT)
740Sstevel@tonic-gate #include <sys/sysi86.h>
750Sstevel@tonic-gate #endif
760Sstevel@tonic-gate
770Sstevel@tonic-gate #include <fs/proc/prdata.h>
780Sstevel@tonic-gate
790Sstevel@tonic-gate static int isprwrioctl(int);
800Sstevel@tonic-gate static ulong_t prmaprunflags(long);
810Sstevel@tonic-gate static long prmapsetflags(long);
820Sstevel@tonic-gate static void prsetrun(kthread_t *, prrun_t *);
830Sstevel@tonic-gate static int propenm(prnode_t *, caddr_t, caddr_t, int *, cred_t *);
840Sstevel@tonic-gate extern void oprgetstatus(kthread_t *, prstatus_t *, zone_t *);
850Sstevel@tonic-gate extern void oprgetpsinfo(proc_t *, prpsinfo_t *, kthread_t *);
862789Sfrankho static int oprgetmap(proc_t *, list_t *);
870Sstevel@tonic-gate
880Sstevel@tonic-gate static int
prctioctl(prnode_t * pnp,int cmd,intptr_t arg,int flag,cred_t * cr)890Sstevel@tonic-gate prctioctl(prnode_t *pnp, int cmd, intptr_t arg, int flag, cred_t *cr)
900Sstevel@tonic-gate {
910Sstevel@tonic-gate int error = 0;
927937SAntonello.Cruz@Sun.COM ct_kparam_t kparam;
937937SAntonello.Cruz@Sun.COM ct_param_t *param = &kparam.param;
940Sstevel@tonic-gate ct_template_t *tmpl;
950Sstevel@tonic-gate
960Sstevel@tonic-gate if (cmd != CT_TSET && cmd != CT_TGET)
970Sstevel@tonic-gate return (EINVAL);
980Sstevel@tonic-gate
997937SAntonello.Cruz@Sun.COM error = ctparam_copyin((void *)arg, &kparam, flag, cmd);
1007937SAntonello.Cruz@Sun.COM if (error != 0)
1010Sstevel@tonic-gate return (error);
1020Sstevel@tonic-gate
1037937SAntonello.Cruz@Sun.COM if ((error = prlock(pnp, ZNO)) != 0) {
1047937SAntonello.Cruz@Sun.COM kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
1057937SAntonello.Cruz@Sun.COM return (error);
1067937SAntonello.Cruz@Sun.COM }
1077937SAntonello.Cruz@Sun.COM
1080Sstevel@tonic-gate tmpl = pnp->pr_common->prc_thread->t_lwp->lwp_ct_active[pnp->pr_cttype];
1090Sstevel@tonic-gate if (tmpl == NULL) {
1100Sstevel@tonic-gate prunlock(pnp);
1117937SAntonello.Cruz@Sun.COM kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
1120Sstevel@tonic-gate return (ESTALE);
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate if (cmd == CT_TSET)
1167937SAntonello.Cruz@Sun.COM error = ctmpl_set(tmpl, &kparam, cr);
1170Sstevel@tonic-gate else
1187937SAntonello.Cruz@Sun.COM error = ctmpl_get(tmpl, &kparam);
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate prunlock(pnp);
1210Sstevel@tonic-gate
1227937SAntonello.Cruz@Sun.COM if (cmd == CT_TGET && error == 0) {
1237937SAntonello.Cruz@Sun.COM error = ctparam_copyout(&kparam, (void *)arg, flag);
1247937SAntonello.Cruz@Sun.COM } else {
1257937SAntonello.Cruz@Sun.COM kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
1267937SAntonello.Cruz@Sun.COM }
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate return (error);
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate /*
1330Sstevel@tonic-gate * Control operations (lots).
1340Sstevel@tonic-gate */
1355331Samw /*ARGSUSED*/
1360Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1370Sstevel@tonic-gate static int
prioctl64(struct vnode * vp,int cmd,intptr_t arg,int flag,cred_t * cr,int * rvalp,caller_context_t * ct)1385331Samw prioctl64(
1395331Samw struct vnode *vp,
1405331Samw int cmd,
1415331Samw intptr_t arg,
1425331Samw int flag,
1435331Samw cred_t *cr,
1445331Samw int *rvalp,
1455331Samw caller_context_t *ct)
1460Sstevel@tonic-gate #else
1470Sstevel@tonic-gate int
1485331Samw prioctl(
1495331Samw struct vnode *vp,
1505331Samw int cmd,
1515331Samw intptr_t arg,
1525331Samw int flag,
1535331Samw cred_t *cr,
1545331Samw int *rvalp,
1555331Samw caller_context_t *ct)
1560Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
1570Sstevel@tonic-gate {
158*11940SRoger.Faulkner@Sun.COM int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
1590Sstevel@tonic-gate caddr_t cmaddr = (caddr_t)arg;
1600Sstevel@tonic-gate proc_t *p;
1610Sstevel@tonic-gate user_t *up;
1620Sstevel@tonic-gate kthread_t *t;
1630Sstevel@tonic-gate klwp_t *lwp;
1640Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
1650Sstevel@tonic-gate prcommon_t *pcp;
1660Sstevel@tonic-gate prnode_t *xpnp = NULL;
1670Sstevel@tonic-gate int error;
1680Sstevel@tonic-gate int zdisp;
1690Sstevel@tonic-gate void *thing = NULL;
1700Sstevel@tonic-gate size_t thingsize = 0;
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate /*
1730Sstevel@tonic-gate * For copyin()/copyout().
1740Sstevel@tonic-gate */
1750Sstevel@tonic-gate union {
1760Sstevel@tonic-gate caddr_t va;
1770Sstevel@tonic-gate int signo;
1780Sstevel@tonic-gate int nice;
1790Sstevel@tonic-gate uint_t lwpid;
1800Sstevel@tonic-gate long flags;
1810Sstevel@tonic-gate prstatus_t prstat;
1820Sstevel@tonic-gate prrun_t prrun;
1830Sstevel@tonic-gate sigset_t smask;
1840Sstevel@tonic-gate siginfo_t info;
1850Sstevel@tonic-gate sysset_t prmask;
1860Sstevel@tonic-gate prgregset_t regs;
1870Sstevel@tonic-gate prfpregset_t fpregs;
1880Sstevel@tonic-gate prpsinfo_t prps;
1890Sstevel@tonic-gate sigset_t holdmask;
1900Sstevel@tonic-gate fltset_t fltmask;
1910Sstevel@tonic-gate prcred_t prcred;
1920Sstevel@tonic-gate prhusage_t prhusage;
1930Sstevel@tonic-gate prmap_t prmap;
1940Sstevel@tonic-gate auxv_t auxv[__KERN_NAUXV_IMPL];
1950Sstevel@tonic-gate } un;
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate if (pnp->pr_type == PR_TMPL)
1980Sstevel@tonic-gate return (prctioctl(pnp, cmd, arg, flag, cr));
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate /*
2010Sstevel@tonic-gate * Support for old /proc interface.
2020Sstevel@tonic-gate */
2030Sstevel@tonic-gate if (pnp->pr_pidfile != NULL) {
2040Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDDIR);
2050Sstevel@tonic-gate vp = pnp->pr_pidfile;
2060Sstevel@tonic-gate pnp = VTOP(vp);
2070Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDFILE);
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate if (pnp->pr_type != PR_PIDFILE && pnp->pr_type != PR_LWPIDFILE)
2110Sstevel@tonic-gate return (ENOTTY);
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate /*
2140Sstevel@tonic-gate * Fail ioctls which are logically "write" requests unless
2150Sstevel@tonic-gate * the user has write permission.
2160Sstevel@tonic-gate */
2170Sstevel@tonic-gate if ((flag & FWRITE) == 0 && isprwrioctl(cmd))
2180Sstevel@tonic-gate return (EBADF);
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate /*
2210Sstevel@tonic-gate * Perform any necessary copyin() operations before
2220Sstevel@tonic-gate * locking the process. Helps avoid deadlocks and
2230Sstevel@tonic-gate * improves performance.
2240Sstevel@tonic-gate *
2250Sstevel@tonic-gate * Also, detect invalid ioctl codes here to avoid
2260Sstevel@tonic-gate * locking a process unnnecessarily.
2270Sstevel@tonic-gate *
2280Sstevel@tonic-gate * Also, prepare to allocate space that will be needed below,
2290Sstevel@tonic-gate * case by case.
2300Sstevel@tonic-gate */
2310Sstevel@tonic-gate error = 0;
2320Sstevel@tonic-gate switch (cmd) {
2330Sstevel@tonic-gate case PIOCGETPR:
2340Sstevel@tonic-gate thingsize = sizeof (proc_t);
2350Sstevel@tonic-gate break;
2360Sstevel@tonic-gate case PIOCGETU:
2370Sstevel@tonic-gate thingsize = sizeof (user_t);
2380Sstevel@tonic-gate break;
2390Sstevel@tonic-gate case PIOCSTOP:
2400Sstevel@tonic-gate case PIOCWSTOP:
2410Sstevel@tonic-gate case PIOCLWPIDS:
2420Sstevel@tonic-gate case PIOCGTRACE:
2430Sstevel@tonic-gate case PIOCGENTRY:
2440Sstevel@tonic-gate case PIOCGEXIT:
2450Sstevel@tonic-gate case PIOCSRLC:
2460Sstevel@tonic-gate case PIOCRRLC:
2470Sstevel@tonic-gate case PIOCSFORK:
2480Sstevel@tonic-gate case PIOCRFORK:
2490Sstevel@tonic-gate case PIOCGREG:
2500Sstevel@tonic-gate case PIOCGFPREG:
2510Sstevel@tonic-gate case PIOCSTATUS:
2520Sstevel@tonic-gate case PIOCLSTATUS:
2530Sstevel@tonic-gate case PIOCPSINFO:
2540Sstevel@tonic-gate case PIOCMAXSIG:
2550Sstevel@tonic-gate case PIOCGXREGSIZE:
2560Sstevel@tonic-gate break;
2570Sstevel@tonic-gate case PIOCSXREG: /* set extra registers */
2580Sstevel@tonic-gate case PIOCGXREG: /* get extra registers */
2590Sstevel@tonic-gate #if defined(__sparc)
2600Sstevel@tonic-gate thingsize = sizeof (prxregset_t);
2610Sstevel@tonic-gate #else
2620Sstevel@tonic-gate thingsize = 0;
2630Sstevel@tonic-gate #endif
2640Sstevel@tonic-gate break;
2650Sstevel@tonic-gate case PIOCACTION:
266*11940SRoger.Faulkner@Sun.COM thingsize = (nsig-1) * sizeof (struct sigaction);
2670Sstevel@tonic-gate break;
2680Sstevel@tonic-gate case PIOCGHOLD:
2690Sstevel@tonic-gate case PIOCNMAP:
2700Sstevel@tonic-gate case PIOCMAP:
2710Sstevel@tonic-gate case PIOCGFAULT:
2720Sstevel@tonic-gate case PIOCCFAULT:
2730Sstevel@tonic-gate case PIOCCRED:
2740Sstevel@tonic-gate case PIOCGROUPS:
2750Sstevel@tonic-gate case PIOCUSAGE:
2760Sstevel@tonic-gate case PIOCLUSAGE:
2770Sstevel@tonic-gate break;
2780Sstevel@tonic-gate case PIOCOPENPD:
2790Sstevel@tonic-gate /*
2800Sstevel@tonic-gate * We will need this below.
2810Sstevel@tonic-gate * Allocate it now, before locking the process.
2820Sstevel@tonic-gate */
2830Sstevel@tonic-gate xpnp = prgetnode(vp, PR_OPAGEDATA);
2840Sstevel@tonic-gate break;
2850Sstevel@tonic-gate case PIOCNAUXV:
2860Sstevel@tonic-gate case PIOCAUXV:
2870Sstevel@tonic-gate break;
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
2900Sstevel@tonic-gate case PIOCNLDT:
2910Sstevel@tonic-gate case PIOCLDT:
2920Sstevel@tonic-gate break;
2930Sstevel@tonic-gate #endif /* __i386 || __amd64 */
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate #if defined(__sparc)
2960Sstevel@tonic-gate case PIOCGWIN:
2970Sstevel@tonic-gate thingsize = sizeof (gwindows_t);
2980Sstevel@tonic-gate break;
2990Sstevel@tonic-gate #endif /* __sparc */
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate case PIOCOPENM: /* open mapped object for reading */
3020Sstevel@tonic-gate if (cmaddr == NULL)
3030Sstevel@tonic-gate un.va = NULL;
3040Sstevel@tonic-gate else if (copyin(cmaddr, &un.va, sizeof (un.va)))
3050Sstevel@tonic-gate error = EFAULT;
3060Sstevel@tonic-gate break;
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate case PIOCRUN: /* make lwp or process runnable */
3090Sstevel@tonic-gate if (cmaddr == NULL)
3100Sstevel@tonic-gate un.prrun.pr_flags = 0;
3110Sstevel@tonic-gate else if (copyin(cmaddr, &un.prrun, sizeof (un.prrun)))
3120Sstevel@tonic-gate error = EFAULT;
3130Sstevel@tonic-gate break;
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate case PIOCOPENLWP: /* return /proc lwp file descriptor */
3160Sstevel@tonic-gate if (copyin(cmaddr, &un.lwpid, sizeof (un.lwpid)))
3170Sstevel@tonic-gate error = EFAULT;
3180Sstevel@tonic-gate break;
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate case PIOCSTRACE: /* set signal trace mask */
3210Sstevel@tonic-gate if (copyin(cmaddr, &un.smask, sizeof (un.smask)))
3220Sstevel@tonic-gate error = EFAULT;
3230Sstevel@tonic-gate break;
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate case PIOCSSIG: /* set current signal */
3260Sstevel@tonic-gate if (cmaddr == NULL)
3270Sstevel@tonic-gate un.info.si_signo = 0;
3280Sstevel@tonic-gate else if (copyin(cmaddr, &un.info, sizeof (un.info)))
3290Sstevel@tonic-gate error = EFAULT;
3300Sstevel@tonic-gate break;
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate case PIOCKILL: /* send signal */
3330Sstevel@tonic-gate case PIOCUNKILL: /* delete a signal */
3340Sstevel@tonic-gate if (copyin(cmaddr, &un.signo, sizeof (un.signo)))
3350Sstevel@tonic-gate error = EFAULT;
3360Sstevel@tonic-gate break;
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate case PIOCNICE: /* set nice priority */
3390Sstevel@tonic-gate if (copyin(cmaddr, &un.nice, sizeof (un.nice)))
3400Sstevel@tonic-gate error = EFAULT;
3410Sstevel@tonic-gate break;
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate case PIOCSENTRY: /* set syscall entry bit mask */
3440Sstevel@tonic-gate case PIOCSEXIT: /* set syscall exit bit mask */
3450Sstevel@tonic-gate if (copyin(cmaddr, &un.prmask, sizeof (un.prmask)))
3460Sstevel@tonic-gate error = EFAULT;
3470Sstevel@tonic-gate break;
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate case PIOCSET: /* set process flags */
3500Sstevel@tonic-gate case PIOCRESET: /* reset process flags */
3510Sstevel@tonic-gate if (copyin(cmaddr, &un.flags, sizeof (un.flags)))
3520Sstevel@tonic-gate error = EFAULT;
3530Sstevel@tonic-gate break;
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate case PIOCSREG: /* set general registers */
3560Sstevel@tonic-gate if (copyin(cmaddr, un.regs, sizeof (un.regs)))
3570Sstevel@tonic-gate error = EFAULT;
3580Sstevel@tonic-gate break;
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate case PIOCSFPREG: /* set floating-point registers */
3610Sstevel@tonic-gate if (copyin(cmaddr, &un.fpregs, sizeof (un.fpregs)))
3620Sstevel@tonic-gate error = EFAULT;
3630Sstevel@tonic-gate break;
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate case PIOCSHOLD: /* set signal-hold mask */
3660Sstevel@tonic-gate if (copyin(cmaddr, &un.holdmask, sizeof (un.holdmask)))
3670Sstevel@tonic-gate error = EFAULT;
3680Sstevel@tonic-gate break;
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate case PIOCSFAULT: /* set mask of traced faults */
3710Sstevel@tonic-gate if (copyin(cmaddr, &un.fltmask, sizeof (un.fltmask)))
3720Sstevel@tonic-gate error = EFAULT;
3730Sstevel@tonic-gate break;
3740Sstevel@tonic-gate
3750Sstevel@tonic-gate default:
3760Sstevel@tonic-gate error = EINVAL;
3770Sstevel@tonic-gate break;
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate if (error)
3810Sstevel@tonic-gate return (error);
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate startover:
3840Sstevel@tonic-gate /*
3850Sstevel@tonic-gate * If we need kmem_alloc()d space then we allocate it now, before
3860Sstevel@tonic-gate * grabbing the process lock. Using kmem_alloc(KM_SLEEP) while
3870Sstevel@tonic-gate * holding the process lock leads to deadlock with the clock thread.
3880Sstevel@tonic-gate * (The clock thread wakes up the pageout daemon to free up space.
3890Sstevel@tonic-gate * If the clock thread blocks behind us and we are sleeping waiting
3900Sstevel@tonic-gate * for space, then space may never become available.)
3910Sstevel@tonic-gate */
3920Sstevel@tonic-gate if (thingsize) {
3930Sstevel@tonic-gate ASSERT(thing == NULL);
3940Sstevel@tonic-gate thing = kmem_alloc(thingsize, KM_SLEEP);
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate switch (cmd) {
3980Sstevel@tonic-gate case PIOCPSINFO:
3990Sstevel@tonic-gate case PIOCGETPR:
4000Sstevel@tonic-gate case PIOCUSAGE:
4010Sstevel@tonic-gate case PIOCLUSAGE:
4020Sstevel@tonic-gate zdisp = ZYES;
4030Sstevel@tonic-gate break;
4040Sstevel@tonic-gate case PIOCSXREG: /* set extra registers */
4050Sstevel@tonic-gate /*
4060Sstevel@tonic-gate * perform copyin before grabbing the process lock
4070Sstevel@tonic-gate */
4080Sstevel@tonic-gate if (thing) {
4090Sstevel@tonic-gate if (copyin(cmaddr, thing, thingsize)) {
4100Sstevel@tonic-gate kmem_free(thing, thingsize);
4110Sstevel@tonic-gate return (EFAULT);
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate /* fall through... */
4150Sstevel@tonic-gate default:
4160Sstevel@tonic-gate zdisp = ZNO;
4170Sstevel@tonic-gate break;
4180Sstevel@tonic-gate }
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate if ((error = prlock(pnp, zdisp)) != 0) {
4210Sstevel@tonic-gate if (thing != NULL)
4220Sstevel@tonic-gate kmem_free(thing, thingsize);
4230Sstevel@tonic-gate if (xpnp)
4240Sstevel@tonic-gate prfreenode(xpnp);
4250Sstevel@tonic-gate return (error);
4260Sstevel@tonic-gate }
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate pcp = pnp->pr_common;
4290Sstevel@tonic-gate p = pcp->prc_proc;
4300Sstevel@tonic-gate ASSERT(p != NULL);
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate /*
4330Sstevel@tonic-gate * Choose a thread/lwp for the operation.
4340Sstevel@tonic-gate */
4350Sstevel@tonic-gate if (zdisp == ZNO && cmd != PIOCSTOP && cmd != PIOCWSTOP) {
4360Sstevel@tonic-gate if (pnp->pr_type == PR_LWPIDFILE && cmd != PIOCLSTATUS) {
4370Sstevel@tonic-gate t = pcp->prc_thread;
4380Sstevel@tonic-gate ASSERT(t != NULL);
4390Sstevel@tonic-gate } else {
4400Sstevel@tonic-gate t = prchoose(p); /* returns locked thread */
4410Sstevel@tonic-gate ASSERT(t != NULL);
4420Sstevel@tonic-gate thread_unlock(t);
4430Sstevel@tonic-gate }
4440Sstevel@tonic-gate lwp = ttolwp(t);
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate
4470Sstevel@tonic-gate error = 0;
4480Sstevel@tonic-gate switch (cmd) {
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate case PIOCGETPR: /* read struct proc */
4510Sstevel@tonic-gate {
4520Sstevel@tonic-gate proc_t *prp = thing;
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate *prp = *p;
4550Sstevel@tonic-gate prunlock(pnp);
4560Sstevel@tonic-gate if (copyout(prp, cmaddr, sizeof (proc_t)))
4570Sstevel@tonic-gate error = EFAULT;
4580Sstevel@tonic-gate kmem_free(prp, sizeof (proc_t));
4590Sstevel@tonic-gate thing = NULL;
4600Sstevel@tonic-gate break;
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate case PIOCGETU: /* read u-area */
4640Sstevel@tonic-gate {
4650Sstevel@tonic-gate user_t *userp = thing;
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate up = PTOU(p);
4680Sstevel@tonic-gate *userp = *up;
4690Sstevel@tonic-gate prunlock(pnp);
4700Sstevel@tonic-gate if (copyout(userp, cmaddr, sizeof (user_t)))
4710Sstevel@tonic-gate error = EFAULT;
4720Sstevel@tonic-gate kmem_free(userp, sizeof (user_t));
4730Sstevel@tonic-gate thing = NULL;
4740Sstevel@tonic-gate break;
4750Sstevel@tonic-gate }
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate case PIOCOPENM: /* open mapped object for reading */
4780Sstevel@tonic-gate error = propenm(pnp, cmaddr, un.va, rvalp, cr);
4790Sstevel@tonic-gate /* propenm() called prunlock(pnp) */
4800Sstevel@tonic-gate break;
4810Sstevel@tonic-gate
4820Sstevel@tonic-gate case PIOCSTOP: /* stop process or lwp from running */
4830Sstevel@tonic-gate case PIOCWSTOP: /* wait for process or lwp to stop */
4840Sstevel@tonic-gate /*
4850Sstevel@tonic-gate * Can't apply to a system process.
4860Sstevel@tonic-gate */
4870Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas) {
4880Sstevel@tonic-gate prunlock(pnp);
4890Sstevel@tonic-gate error = EBUSY;
4900Sstevel@tonic-gate break;
4910Sstevel@tonic-gate }
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate if (cmd == PIOCSTOP)
4940Sstevel@tonic-gate pr_stop(pnp);
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate /*
4970Sstevel@tonic-gate * If an lwp is waiting for itself or its process, don't wait.
4980Sstevel@tonic-gate * The stopped lwp would never see the fact that it is stopped.
4990Sstevel@tonic-gate */
5000Sstevel@tonic-gate if ((pnp->pr_type == PR_LWPIDFILE)?
5010Sstevel@tonic-gate (pcp->prc_thread == curthread) : (p == curproc)) {
5020Sstevel@tonic-gate if (cmd == PIOCWSTOP)
5030Sstevel@tonic-gate error = EBUSY;
5040Sstevel@tonic-gate prunlock(pnp);
5050Sstevel@tonic-gate break;
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate if ((error = pr_wait_stop(pnp, (time_t)0)) != 0)
5090Sstevel@tonic-gate break; /* pr_wait_stop() unlocked the process */
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate if (cmaddr == NULL)
5120Sstevel@tonic-gate prunlock(pnp);
5130Sstevel@tonic-gate else {
5140Sstevel@tonic-gate /*
5150Sstevel@tonic-gate * Return process/lwp status information.
5160Sstevel@tonic-gate */
5170Sstevel@tonic-gate t = pr_thread(pnp); /* returns locked thread */
5180Sstevel@tonic-gate thread_unlock(t);
519789Sahrens oprgetstatus(t, &un.prstat, VTOZONE(vp));
5200Sstevel@tonic-gate prunlock(pnp);
5210Sstevel@tonic-gate if (copyout(&un.prstat, cmaddr, sizeof (un.prstat)))
5220Sstevel@tonic-gate error = EFAULT;
5230Sstevel@tonic-gate }
5240Sstevel@tonic-gate break;
5250Sstevel@tonic-gate
5260Sstevel@tonic-gate case PIOCRUN: /* make lwp or process runnable */
5270Sstevel@tonic-gate {
5280Sstevel@tonic-gate long flags = un.prrun.pr_flags;
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate /*
5310Sstevel@tonic-gate * Cannot set an lwp running is it is not stopped.
5320Sstevel@tonic-gate * Also, no lwp other than the /proc agent lwp can
5330Sstevel@tonic-gate * be set running so long as the /proc agent lwp exists.
5340Sstevel@tonic-gate */
5350Sstevel@tonic-gate if ((!ISTOPPED(t) && !VSTOPPED(t) &&
5360Sstevel@tonic-gate !(t->t_proc_flag & TP_PRSTOP)) ||
5370Sstevel@tonic-gate (p->p_agenttp != NULL &&
5380Sstevel@tonic-gate (t != p->p_agenttp || pnp->pr_type != PR_LWPIDFILE))) {
5390Sstevel@tonic-gate prunlock(pnp);
5400Sstevel@tonic-gate error = EBUSY;
5410Sstevel@tonic-gate break;
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate if (flags & (PRSHOLD|PRSTRACE|PRSFAULT|PRSVADDR))
5450Sstevel@tonic-gate prsetrun(t, &un.prrun);
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate error = pr_setrun(pnp, prmaprunflags(flags));
5480Sstevel@tonic-gate
5490Sstevel@tonic-gate prunlock(pnp);
5500Sstevel@tonic-gate break;
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate
5530Sstevel@tonic-gate case PIOCLWPIDS: /* get array of lwp identifiers */
5540Sstevel@tonic-gate {
5550Sstevel@tonic-gate int nlwp;
5560Sstevel@tonic-gate int Nlwp;
5570Sstevel@tonic-gate id_t *idp;
5580Sstevel@tonic-gate id_t *Bidp;
5590Sstevel@tonic-gate
5600Sstevel@tonic-gate Nlwp = nlwp = p->p_lwpcnt;
5610Sstevel@tonic-gate
5620Sstevel@tonic-gate if (thing && thingsize != (Nlwp+1) * sizeof (id_t)) {
5630Sstevel@tonic-gate kmem_free(thing, thingsize);
5640Sstevel@tonic-gate thing = NULL;
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate if (thing == NULL) {
5670Sstevel@tonic-gate thingsize = (Nlwp+1) * sizeof (id_t);
5680Sstevel@tonic-gate thing = kmem_alloc(thingsize, KM_NOSLEEP);
5690Sstevel@tonic-gate }
5700Sstevel@tonic-gate if (thing == NULL) {
5710Sstevel@tonic-gate prunlock(pnp);
5720Sstevel@tonic-gate goto startover;
5730Sstevel@tonic-gate }
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate idp = thing;
5760Sstevel@tonic-gate thing = NULL;
5770Sstevel@tonic-gate Bidp = idp;
5780Sstevel@tonic-gate if ((t = p->p_tlist) != NULL) {
5790Sstevel@tonic-gate do {
5800Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
5810Sstevel@tonic-gate ASSERT(nlwp > 0);
5820Sstevel@tonic-gate --nlwp;
5830Sstevel@tonic-gate *idp++ = t->t_tid;
5840Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate *idp = 0;
5870Sstevel@tonic-gate ASSERT(nlwp == 0);
5880Sstevel@tonic-gate prunlock(pnp);
5890Sstevel@tonic-gate if (copyout(Bidp, cmaddr, (Nlwp+1) * sizeof (id_t)))
5900Sstevel@tonic-gate error = EFAULT;
5910Sstevel@tonic-gate kmem_free(Bidp, (Nlwp+1) * sizeof (id_t));
5920Sstevel@tonic-gate break;
5930Sstevel@tonic-gate }
5940Sstevel@tonic-gate
5950Sstevel@tonic-gate case PIOCOPENLWP: /* return /proc lwp file descriptor */
5960Sstevel@tonic-gate {
5970Sstevel@tonic-gate vnode_t *xvp;
5980Sstevel@tonic-gate int n;
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate prunlock(pnp);
6010Sstevel@tonic-gate if ((xvp = prlwpnode(pnp, un.lwpid)) == NULL)
6020Sstevel@tonic-gate error = ENOENT;
6030Sstevel@tonic-gate else if (error = fassign(&xvp, flag & (FREAD|FWRITE), &n)) {
6040Sstevel@tonic-gate VN_RELE(xvp);
6050Sstevel@tonic-gate } else
6060Sstevel@tonic-gate *rvalp = n;
6070Sstevel@tonic-gate break;
6080Sstevel@tonic-gate }
6090Sstevel@tonic-gate
6100Sstevel@tonic-gate case PIOCOPENPD: /* return /proc page data file descriptor */
6110Sstevel@tonic-gate {
6120Sstevel@tonic-gate vnode_t *xvp = PTOV(xpnp);
6130Sstevel@tonic-gate vnode_t *dp = pnp->pr_parent;
6140Sstevel@tonic-gate int n;
6150Sstevel@tonic-gate
6160Sstevel@tonic-gate if (pnp->pr_type == PR_LWPIDFILE) {
6170Sstevel@tonic-gate dp = VTOP(dp)->pr_parent;
6180Sstevel@tonic-gate dp = VTOP(dp)->pr_parent;
6190Sstevel@tonic-gate }
6200Sstevel@tonic-gate ASSERT(VTOP(dp)->pr_type == PR_PIDDIR);
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate VN_HOLD(dp);
6230Sstevel@tonic-gate pcp = pnp->pr_pcommon;
6240Sstevel@tonic-gate xpnp->pr_ino = ptoi(pcp->prc_pid);
6250Sstevel@tonic-gate xpnp->pr_common = pcp;
6260Sstevel@tonic-gate xpnp->pr_pcommon = pcp;
6270Sstevel@tonic-gate xpnp->pr_parent = dp;
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate xpnp->pr_next = p->p_plist;
6300Sstevel@tonic-gate p->p_plist = xvp;
6310Sstevel@tonic-gate
6320Sstevel@tonic-gate prunlock(pnp);
6330Sstevel@tonic-gate if (error = fassign(&xvp, FREAD, &n)) {
6340Sstevel@tonic-gate VN_RELE(xvp);
6350Sstevel@tonic-gate } else
6360Sstevel@tonic-gate *rvalp = n;
6370Sstevel@tonic-gate
6380Sstevel@tonic-gate xpnp = NULL;
6390Sstevel@tonic-gate break;
6400Sstevel@tonic-gate }
6410Sstevel@tonic-gate
6420Sstevel@tonic-gate case PIOCGTRACE: /* get signal trace mask */
6430Sstevel@tonic-gate prassignset(&un.smask, &p->p_sigmask);
6440Sstevel@tonic-gate prunlock(pnp);
6450Sstevel@tonic-gate if (copyout(&un.smask, cmaddr, sizeof (un.smask)))
6460Sstevel@tonic-gate error = EFAULT;
6470Sstevel@tonic-gate break;
6480Sstevel@tonic-gate
6490Sstevel@tonic-gate case PIOCSTRACE: /* set signal trace mask */
6500Sstevel@tonic-gate prdelset(&un.smask, SIGKILL);
6510Sstevel@tonic-gate prassignset(&p->p_sigmask, &un.smask);
6520Sstevel@tonic-gate if (!sigisempty(&p->p_sigmask))
6530Sstevel@tonic-gate p->p_proc_flag |= P_PR_TRACE;
6540Sstevel@tonic-gate else if (prisempty(&p->p_fltmask)) {
6550Sstevel@tonic-gate up = PTOU(p);
6560Sstevel@tonic-gate if (up->u_systrap == 0)
6570Sstevel@tonic-gate p->p_proc_flag &= ~P_PR_TRACE;
6580Sstevel@tonic-gate }
6590Sstevel@tonic-gate prunlock(pnp);
6600Sstevel@tonic-gate break;
6610Sstevel@tonic-gate
6620Sstevel@tonic-gate case PIOCSSIG: /* set current signal */
6630Sstevel@tonic-gate error = pr_setsig(pnp, &un.info);
6640Sstevel@tonic-gate prunlock(pnp);
6650Sstevel@tonic-gate if (un.info.si_signo == SIGKILL && error == 0)
6660Sstevel@tonic-gate pr_wait_die(pnp);
6670Sstevel@tonic-gate break;
6680Sstevel@tonic-gate
6690Sstevel@tonic-gate case PIOCKILL: /* send signal */
6700Sstevel@tonic-gate {
6710Sstevel@tonic-gate int sig = (int)un.signo;
6720Sstevel@tonic-gate
6730Sstevel@tonic-gate error = pr_kill(pnp, sig, cr);
6740Sstevel@tonic-gate prunlock(pnp);
6750Sstevel@tonic-gate if (sig == SIGKILL && error == 0)
6760Sstevel@tonic-gate pr_wait_die(pnp);
6770Sstevel@tonic-gate break;
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate
6800Sstevel@tonic-gate case PIOCUNKILL: /* delete a signal */
6810Sstevel@tonic-gate error = pr_unkill(pnp, (int)un.signo);
6820Sstevel@tonic-gate prunlock(pnp);
6830Sstevel@tonic-gate break;
6840Sstevel@tonic-gate
6850Sstevel@tonic-gate case PIOCNICE: /* set nice priority */
6860Sstevel@tonic-gate error = pr_nice(p, (int)un.nice, cr);
6870Sstevel@tonic-gate prunlock(pnp);
6880Sstevel@tonic-gate break;
6890Sstevel@tonic-gate
6900Sstevel@tonic-gate case PIOCGENTRY: /* get syscall entry bit mask */
6910Sstevel@tonic-gate case PIOCGEXIT: /* get syscall exit bit mask */
6920Sstevel@tonic-gate up = PTOU(p);
6930Sstevel@tonic-gate if (cmd == PIOCGENTRY) {
6940Sstevel@tonic-gate prassignset(&un.prmask, &up->u_entrymask);
6950Sstevel@tonic-gate } else {
6960Sstevel@tonic-gate prassignset(&un.prmask, &up->u_exitmask);
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate prunlock(pnp);
6990Sstevel@tonic-gate if (copyout(&un.prmask, cmaddr, sizeof (un.prmask)))
7000Sstevel@tonic-gate error = EFAULT;
7010Sstevel@tonic-gate break;
7020Sstevel@tonic-gate
7030Sstevel@tonic-gate case PIOCSENTRY: /* set syscall entry bit mask */
7040Sstevel@tonic-gate case PIOCSEXIT: /* set syscall exit bit mask */
7050Sstevel@tonic-gate pr_setentryexit(p, &un.prmask, cmd == PIOCSENTRY);
7060Sstevel@tonic-gate prunlock(pnp);
7070Sstevel@tonic-gate break;
7080Sstevel@tonic-gate
7090Sstevel@tonic-gate case PIOCSRLC: /* obsolete: set running on last /proc close */
7100Sstevel@tonic-gate error = pr_set(p, prmapsetflags(PR_RLC));
7110Sstevel@tonic-gate prunlock(pnp);
7120Sstevel@tonic-gate break;
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate case PIOCRRLC: /* obsolete: reset run-on-last-close flag */
7150Sstevel@tonic-gate error = pr_unset(p, prmapsetflags(PR_RLC));
7160Sstevel@tonic-gate prunlock(pnp);
7170Sstevel@tonic-gate break;
7180Sstevel@tonic-gate
7190Sstevel@tonic-gate case PIOCSFORK: /* obsolete: set inherit-on-fork flag */
7200Sstevel@tonic-gate error = pr_set(p, prmapsetflags(PR_FORK));
7210Sstevel@tonic-gate prunlock(pnp);
7220Sstevel@tonic-gate break;
7230Sstevel@tonic-gate
7240Sstevel@tonic-gate case PIOCRFORK: /* obsolete: reset inherit-on-fork flag */
7250Sstevel@tonic-gate error = pr_unset(p, prmapsetflags(PR_FORK));
7260Sstevel@tonic-gate prunlock(pnp);
7270Sstevel@tonic-gate break;
7280Sstevel@tonic-gate
7290Sstevel@tonic-gate case PIOCSET: /* set process flags */
7300Sstevel@tonic-gate error = pr_set(p, prmapsetflags(un.flags));
7310Sstevel@tonic-gate prunlock(pnp);
7320Sstevel@tonic-gate break;
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate case PIOCRESET: /* reset process flags */
7350Sstevel@tonic-gate error = pr_unset(p, prmapsetflags(un.flags));
7360Sstevel@tonic-gate prunlock(pnp);
7370Sstevel@tonic-gate break;
7380Sstevel@tonic-gate
7390Sstevel@tonic-gate case PIOCGREG: /* get general registers */
7400Sstevel@tonic-gate if (t->t_state != TS_STOPPED && !VSTOPPED(t))
7410Sstevel@tonic-gate bzero(un.regs, sizeof (un.regs));
7420Sstevel@tonic-gate else {
7430Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
7440Sstevel@tonic-gate mutex_exit(&p->p_lock);
7450Sstevel@tonic-gate prgetprregs(lwp, un.regs);
7460Sstevel@tonic-gate mutex_enter(&p->p_lock);
7470Sstevel@tonic-gate }
7480Sstevel@tonic-gate prunlock(pnp);
7490Sstevel@tonic-gate if (copyout(un.regs, cmaddr, sizeof (un.regs)))
7500Sstevel@tonic-gate error = EFAULT;
7510Sstevel@tonic-gate break;
7520Sstevel@tonic-gate
7530Sstevel@tonic-gate case PIOCSREG: /* set general registers */
7540Sstevel@tonic-gate if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
7550Sstevel@tonic-gate error = EBUSY;
7560Sstevel@tonic-gate else {
7570Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
7580Sstevel@tonic-gate mutex_exit(&p->p_lock);
7590Sstevel@tonic-gate prsetprregs(lwp, un.regs, 0);
7600Sstevel@tonic-gate mutex_enter(&p->p_lock);
7610Sstevel@tonic-gate }
7620Sstevel@tonic-gate prunlock(pnp);
7630Sstevel@tonic-gate break;
7640Sstevel@tonic-gate
7650Sstevel@tonic-gate case PIOCGFPREG: /* get floating-point registers */
7660Sstevel@tonic-gate if (!prhasfp()) {
7670Sstevel@tonic-gate prunlock(pnp);
7680Sstevel@tonic-gate error = EINVAL; /* No FP support */
7690Sstevel@tonic-gate break;
7700Sstevel@tonic-gate }
7710Sstevel@tonic-gate
7720Sstevel@tonic-gate if (t->t_state != TS_STOPPED && !VSTOPPED(t))
7730Sstevel@tonic-gate bzero(&un.fpregs, sizeof (un.fpregs));
7740Sstevel@tonic-gate else {
7750Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
7760Sstevel@tonic-gate mutex_exit(&p->p_lock);
7770Sstevel@tonic-gate prgetprfpregs(lwp, &un.fpregs);
7780Sstevel@tonic-gate mutex_enter(&p->p_lock);
7790Sstevel@tonic-gate }
7800Sstevel@tonic-gate prunlock(pnp);
7810Sstevel@tonic-gate if (copyout(&un.fpregs, cmaddr, sizeof (un.fpregs)))
7820Sstevel@tonic-gate error = EFAULT;
7830Sstevel@tonic-gate break;
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate case PIOCSFPREG: /* set floating-point registers */
7860Sstevel@tonic-gate if (!prhasfp())
7870Sstevel@tonic-gate error = EINVAL; /* No FP support */
7880Sstevel@tonic-gate else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
7890Sstevel@tonic-gate error = EBUSY;
7900Sstevel@tonic-gate else {
7910Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
7920Sstevel@tonic-gate mutex_exit(&p->p_lock);
7930Sstevel@tonic-gate prsetprfpregs(lwp, &un.fpregs);
7940Sstevel@tonic-gate mutex_enter(&p->p_lock);
7950Sstevel@tonic-gate }
7960Sstevel@tonic-gate prunlock(pnp);
7970Sstevel@tonic-gate break;
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate case PIOCGXREGSIZE: /* get the size of the extra registers */
8000Sstevel@tonic-gate {
8010Sstevel@tonic-gate int xregsize;
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate if (prhasx(p)) {
8040Sstevel@tonic-gate xregsize = prgetprxregsize(p);
8050Sstevel@tonic-gate prunlock(pnp);
8060Sstevel@tonic-gate if (copyout(&xregsize, cmaddr, sizeof (xregsize)))
8070Sstevel@tonic-gate error = EFAULT;
8080Sstevel@tonic-gate } else {
8090Sstevel@tonic-gate prunlock(pnp);
8100Sstevel@tonic-gate error = EINVAL; /* No extra register support */
8110Sstevel@tonic-gate }
8120Sstevel@tonic-gate break;
8130Sstevel@tonic-gate }
8140Sstevel@tonic-gate
8150Sstevel@tonic-gate case PIOCGXREG: /* get extra registers */
8160Sstevel@tonic-gate if (prhasx(p)) {
8170Sstevel@tonic-gate bzero(thing, thingsize);
8180Sstevel@tonic-gate if (t->t_state == TS_STOPPED || VSTOPPED(t)) {
8190Sstevel@tonic-gate /* drop p_lock to touch the stack */
8200Sstevel@tonic-gate mutex_exit(&p->p_lock);
8210Sstevel@tonic-gate prgetprxregs(lwp, thing);
8220Sstevel@tonic-gate mutex_enter(&p->p_lock);
8230Sstevel@tonic-gate }
8240Sstevel@tonic-gate prunlock(pnp);
8250Sstevel@tonic-gate if (copyout(thing, cmaddr, thingsize))
8260Sstevel@tonic-gate error = EFAULT;
8270Sstevel@tonic-gate } else {
8280Sstevel@tonic-gate prunlock(pnp);
8290Sstevel@tonic-gate error = EINVAL; /* No extra register support */
8300Sstevel@tonic-gate }
8310Sstevel@tonic-gate if (thing) {
8320Sstevel@tonic-gate kmem_free(thing, thingsize);
8330Sstevel@tonic-gate thing = NULL;
8340Sstevel@tonic-gate }
8350Sstevel@tonic-gate break;
8360Sstevel@tonic-gate
8370Sstevel@tonic-gate case PIOCSXREG: /* set extra registers */
8380Sstevel@tonic-gate if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
8390Sstevel@tonic-gate error = EBUSY;
8400Sstevel@tonic-gate else if (!prhasx(p))
8410Sstevel@tonic-gate error = EINVAL; /* No extra register support */
8420Sstevel@tonic-gate else if (thing) {
8430Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
8440Sstevel@tonic-gate mutex_exit(&p->p_lock);
8450Sstevel@tonic-gate prsetprxregs(lwp, thing);
8460Sstevel@tonic-gate mutex_enter(&p->p_lock);
8470Sstevel@tonic-gate }
8480Sstevel@tonic-gate prunlock(pnp);
8490Sstevel@tonic-gate if (thing) {
8500Sstevel@tonic-gate kmem_free(thing, thingsize);
8510Sstevel@tonic-gate thing = NULL;
8520Sstevel@tonic-gate }
8530Sstevel@tonic-gate break;
8540Sstevel@tonic-gate
8550Sstevel@tonic-gate case PIOCSTATUS: /* get process/lwp status */
856789Sahrens oprgetstatus(t, &un.prstat, VTOZONE(vp));
8570Sstevel@tonic-gate prunlock(pnp);
8580Sstevel@tonic-gate if (copyout(&un.prstat, cmaddr, sizeof (un.prstat)))
8590Sstevel@tonic-gate error = EFAULT;
8600Sstevel@tonic-gate break;
8610Sstevel@tonic-gate
8620Sstevel@tonic-gate case PIOCLSTATUS: /* get status for process & all lwps */
8630Sstevel@tonic-gate {
8640Sstevel@tonic-gate int Nlwp;
8650Sstevel@tonic-gate int nlwp;
8660Sstevel@tonic-gate prstatus_t *Bprsp;
8670Sstevel@tonic-gate prstatus_t *prsp;
8680Sstevel@tonic-gate
8690Sstevel@tonic-gate nlwp = Nlwp = p->p_lwpcnt;
8700Sstevel@tonic-gate
8710Sstevel@tonic-gate if (thing && thingsize != (Nlwp+1) * sizeof (prstatus_t)) {
8720Sstevel@tonic-gate kmem_free(thing, thingsize);
8730Sstevel@tonic-gate thing = NULL;
8740Sstevel@tonic-gate }
8750Sstevel@tonic-gate if (thing == NULL) {
8760Sstevel@tonic-gate thingsize = (Nlwp+1) * sizeof (prstatus_t);
8770Sstevel@tonic-gate thing = kmem_alloc(thingsize, KM_NOSLEEP);
8780Sstevel@tonic-gate }
8790Sstevel@tonic-gate if (thing == NULL) {
8800Sstevel@tonic-gate prunlock(pnp);
8810Sstevel@tonic-gate goto startover;
8820Sstevel@tonic-gate }
8830Sstevel@tonic-gate
8840Sstevel@tonic-gate Bprsp = thing;
8850Sstevel@tonic-gate thing = NULL;
8860Sstevel@tonic-gate prsp = Bprsp;
887789Sahrens oprgetstatus(t, prsp, VTOZONE(vp));
8880Sstevel@tonic-gate t = p->p_tlist;
8890Sstevel@tonic-gate do {
8900Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
8910Sstevel@tonic-gate ASSERT(nlwp > 0);
8920Sstevel@tonic-gate --nlwp;
893789Sahrens oprgetstatus(t, ++prsp, VTOZONE(vp));
8940Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
8950Sstevel@tonic-gate ASSERT(nlwp == 0);
8960Sstevel@tonic-gate prunlock(pnp);
8970Sstevel@tonic-gate if (copyout(Bprsp, cmaddr, (Nlwp+1) * sizeof (prstatus_t)))
8980Sstevel@tonic-gate error = EFAULT;
8990Sstevel@tonic-gate
9000Sstevel@tonic-gate kmem_free(Bprsp, (Nlwp+1) * sizeof (prstatus_t));
9010Sstevel@tonic-gate break;
9020Sstevel@tonic-gate }
9030Sstevel@tonic-gate
9040Sstevel@tonic-gate case PIOCPSINFO: /* get ps(1) information */
9050Sstevel@tonic-gate {
9060Sstevel@tonic-gate prpsinfo_t *psp = &un.prps;
9070Sstevel@tonic-gate
9080Sstevel@tonic-gate oprgetpsinfo(p, psp,
9090Sstevel@tonic-gate (pnp->pr_type == PR_LWPIDFILE)? pcp->prc_thread : NULL);
9100Sstevel@tonic-gate
9110Sstevel@tonic-gate prunlock(pnp);
9120Sstevel@tonic-gate if (copyout(&un.prps, cmaddr, sizeof (un.prps)))
9130Sstevel@tonic-gate error = EFAULT;
9140Sstevel@tonic-gate break;
9150Sstevel@tonic-gate }
9160Sstevel@tonic-gate
9170Sstevel@tonic-gate case PIOCMAXSIG: /* get maximum signal number */
9180Sstevel@tonic-gate {
919*11940SRoger.Faulkner@Sun.COM int n = nsig-1;
9200Sstevel@tonic-gate
9210Sstevel@tonic-gate prunlock(pnp);
9220Sstevel@tonic-gate if (copyout(&n, cmaddr, sizeof (n)))
9230Sstevel@tonic-gate error = EFAULT;
9240Sstevel@tonic-gate break;
9250Sstevel@tonic-gate }
9260Sstevel@tonic-gate
9270Sstevel@tonic-gate case PIOCACTION: /* get signal action structures */
9280Sstevel@tonic-gate {
9290Sstevel@tonic-gate uint_t sig;
9300Sstevel@tonic-gate struct sigaction *sap = thing;
9310Sstevel@tonic-gate
9320Sstevel@tonic-gate up = PTOU(p);
933*11940SRoger.Faulkner@Sun.COM for (sig = 1; sig < nsig; sig++)
9340Sstevel@tonic-gate prgetaction(p, up, sig, &sap[sig-1]);
9350Sstevel@tonic-gate prunlock(pnp);
936*11940SRoger.Faulkner@Sun.COM if (copyout(sap, cmaddr, (nsig-1) * sizeof (struct sigaction)))
9370Sstevel@tonic-gate error = EFAULT;
938*11940SRoger.Faulkner@Sun.COM kmem_free(sap, (nsig-1) * sizeof (struct sigaction));
9390Sstevel@tonic-gate thing = NULL;
9400Sstevel@tonic-gate break;
9410Sstevel@tonic-gate }
9420Sstevel@tonic-gate
9430Sstevel@tonic-gate case PIOCGHOLD: /* get signal-hold mask */
9440Sstevel@tonic-gate schedctl_finish_sigblock(t);
9450Sstevel@tonic-gate sigktou(&t->t_hold, &un.holdmask);
9460Sstevel@tonic-gate prunlock(pnp);
9470Sstevel@tonic-gate if (copyout(&un.holdmask, cmaddr, sizeof (un.holdmask)))
9480Sstevel@tonic-gate error = EFAULT;
9490Sstevel@tonic-gate break;
9500Sstevel@tonic-gate
9510Sstevel@tonic-gate case PIOCSHOLD: /* set signal-hold mask */
9520Sstevel@tonic-gate pr_sethold(pnp, &un.holdmask);
9530Sstevel@tonic-gate prunlock(pnp);
9540Sstevel@tonic-gate break;
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate case PIOCNMAP: /* get number of memory mappings */
9570Sstevel@tonic-gate {
9580Sstevel@tonic-gate int n;
9590Sstevel@tonic-gate struct as *as = p->p_as;
9600Sstevel@tonic-gate
9610Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas)
9620Sstevel@tonic-gate n = 0;
9630Sstevel@tonic-gate else {
9640Sstevel@tonic-gate mutex_exit(&p->p_lock);
9650Sstevel@tonic-gate AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
9660Sstevel@tonic-gate n = prnsegs(as, 0);
9670Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
9680Sstevel@tonic-gate mutex_enter(&p->p_lock);
9690Sstevel@tonic-gate }
9700Sstevel@tonic-gate prunlock(pnp);
9710Sstevel@tonic-gate if (copyout(&n, cmaddr, sizeof (int)))
9720Sstevel@tonic-gate error = EFAULT;
9730Sstevel@tonic-gate break;
9740Sstevel@tonic-gate }
9750Sstevel@tonic-gate
9760Sstevel@tonic-gate case PIOCMAP: /* get memory map information */
9770Sstevel@tonic-gate {
9782789Sfrankho list_t iolhead;
9790Sstevel@tonic-gate struct as *as = p->p_as;
9802789Sfrankho
9812789Sfrankho if ((p->p_flag & SSYS) || as == &kas) {
9822789Sfrankho error = 0;
9832789Sfrankho prunlock(pnp);
9840Sstevel@tonic-gate } else {
9850Sstevel@tonic-gate mutex_exit(&p->p_lock);
9860Sstevel@tonic-gate AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
9872789Sfrankho error = oprgetmap(p, &iolhead);
9880Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
9890Sstevel@tonic-gate mutex_enter(&p->p_lock);
9902789Sfrankho prunlock(pnp);
9912789Sfrankho
9922789Sfrankho error = pr_iol_copyout_and_free(&iolhead,
9932789Sfrankho &cmaddr, error);
9940Sstevel@tonic-gate }
9952789Sfrankho /*
9962789Sfrankho * The procfs PIOCMAP ioctl returns an all-zero buffer
9972789Sfrankho * to indicate the end of the prmap[] array.
9982789Sfrankho * Append it to whatever has already been copied out.
9992789Sfrankho */
10002789Sfrankho bzero(&un.prmap, sizeof (un.prmap));
10012789Sfrankho if (!error && copyout(&un.prmap, cmaddr, sizeof (un.prmap)))
10020Sstevel@tonic-gate error = EFAULT;
10032789Sfrankho
10040Sstevel@tonic-gate break;
10050Sstevel@tonic-gate }
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate case PIOCGFAULT: /* get mask of traced faults */
10080Sstevel@tonic-gate prassignset(&un.fltmask, &p->p_fltmask);
10090Sstevel@tonic-gate prunlock(pnp);
10100Sstevel@tonic-gate if (copyout(&un.fltmask, cmaddr, sizeof (un.fltmask)))
10110Sstevel@tonic-gate error = EFAULT;
10120Sstevel@tonic-gate break;
10130Sstevel@tonic-gate
10140Sstevel@tonic-gate case PIOCSFAULT: /* set mask of traced faults */
10150Sstevel@tonic-gate pr_setfault(p, &un.fltmask);
10160Sstevel@tonic-gate prunlock(pnp);
10170Sstevel@tonic-gate break;
10180Sstevel@tonic-gate
10190Sstevel@tonic-gate case PIOCCFAULT: /* clear current fault */
10200Sstevel@tonic-gate lwp->lwp_curflt = 0;
10210Sstevel@tonic-gate prunlock(pnp);
10220Sstevel@tonic-gate break;
10230Sstevel@tonic-gate
10240Sstevel@tonic-gate case PIOCCRED: /* get process credentials */
10250Sstevel@tonic-gate {
10260Sstevel@tonic-gate cred_t *cp;
10270Sstevel@tonic-gate
10280Sstevel@tonic-gate mutex_enter(&p->p_crlock);
10290Sstevel@tonic-gate cp = p->p_cred;
10300Sstevel@tonic-gate un.prcred.pr_euid = crgetuid(cp);
10310Sstevel@tonic-gate un.prcred.pr_ruid = crgetruid(cp);
10320Sstevel@tonic-gate un.prcred.pr_suid = crgetsuid(cp);
10330Sstevel@tonic-gate un.prcred.pr_egid = crgetgid(cp);
10340Sstevel@tonic-gate un.prcred.pr_rgid = crgetrgid(cp);
10350Sstevel@tonic-gate un.prcred.pr_sgid = crgetsgid(cp);
10360Sstevel@tonic-gate un.prcred.pr_ngroups = crgetngroups(cp);
10370Sstevel@tonic-gate mutex_exit(&p->p_crlock);
10380Sstevel@tonic-gate
10390Sstevel@tonic-gate prunlock(pnp);
10400Sstevel@tonic-gate if (copyout(&un.prcred, cmaddr, sizeof (un.prcred)))
10410Sstevel@tonic-gate error = EFAULT;
10420Sstevel@tonic-gate break;
10430Sstevel@tonic-gate }
10440Sstevel@tonic-gate
10450Sstevel@tonic-gate case PIOCGROUPS: /* get supplementary groups */
10460Sstevel@tonic-gate {
10470Sstevel@tonic-gate cred_t *cp;
10480Sstevel@tonic-gate
10490Sstevel@tonic-gate mutex_enter(&p->p_crlock);
10500Sstevel@tonic-gate cp = p->p_cred;
10510Sstevel@tonic-gate crhold(cp);
10520Sstevel@tonic-gate mutex_exit(&p->p_crlock);
10530Sstevel@tonic-gate
10540Sstevel@tonic-gate prunlock(pnp);
10550Sstevel@tonic-gate if (copyout(crgetgroups(cp), cmaddr,
10560Sstevel@tonic-gate MAX(crgetngroups(cp), 1) * sizeof (gid_t)))
10570Sstevel@tonic-gate error = EFAULT;
10580Sstevel@tonic-gate crfree(cp);
10590Sstevel@tonic-gate break;
10600Sstevel@tonic-gate }
10610Sstevel@tonic-gate
10620Sstevel@tonic-gate case PIOCUSAGE: /* get usage info */
10630Sstevel@tonic-gate {
10640Sstevel@tonic-gate /*
10650Sstevel@tonic-gate * For an lwp file descriptor, return just the lwp usage.
10660Sstevel@tonic-gate * For a process file descriptor, return total usage,
10670Sstevel@tonic-gate * all current lwps plus all defunct lwps.
10680Sstevel@tonic-gate */
10690Sstevel@tonic-gate prhusage_t *pup = &un.prhusage;
10700Sstevel@tonic-gate prusage_t *upup;
10710Sstevel@tonic-gate
10720Sstevel@tonic-gate bzero(pup, sizeof (*pup));
10730Sstevel@tonic-gate pup->pr_tstamp = gethrtime();
10740Sstevel@tonic-gate
10750Sstevel@tonic-gate if (pnp->pr_type == PR_LWPIDFILE) {
10760Sstevel@tonic-gate t = pcp->prc_thread;
10770Sstevel@tonic-gate if (t != NULL)
10780Sstevel@tonic-gate prgetusage(t, pup);
10790Sstevel@tonic-gate else
10800Sstevel@tonic-gate error = ENOENT;
10810Sstevel@tonic-gate } else {
10820Sstevel@tonic-gate pup->pr_count = p->p_defunct;
10830Sstevel@tonic-gate pup->pr_create = p->p_mstart;
10840Sstevel@tonic-gate pup->pr_term = p->p_mterm;
10850Sstevel@tonic-gate
10860Sstevel@tonic-gate pup->pr_rtime = p->p_mlreal;
10870Sstevel@tonic-gate pup->pr_utime = p->p_acct[LMS_USER];
10880Sstevel@tonic-gate pup->pr_stime = p->p_acct[LMS_SYSTEM];
10890Sstevel@tonic-gate pup->pr_ttime = p->p_acct[LMS_TRAP];
10900Sstevel@tonic-gate pup->pr_tftime = p->p_acct[LMS_TFAULT];
10910Sstevel@tonic-gate pup->pr_dftime = p->p_acct[LMS_DFAULT];
10920Sstevel@tonic-gate pup->pr_kftime = p->p_acct[LMS_KFAULT];
10930Sstevel@tonic-gate pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
10940Sstevel@tonic-gate pup->pr_slptime = p->p_acct[LMS_SLEEP];
10950Sstevel@tonic-gate pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
10960Sstevel@tonic-gate pup->pr_stoptime = p->p_acct[LMS_STOPPED];
10970Sstevel@tonic-gate
10980Sstevel@tonic-gate pup->pr_minf = p->p_ru.minflt;
10990Sstevel@tonic-gate pup->pr_majf = p->p_ru.majflt;
11000Sstevel@tonic-gate pup->pr_nswap = p->p_ru.nswap;
11010Sstevel@tonic-gate pup->pr_inblk = p->p_ru.inblock;
11020Sstevel@tonic-gate pup->pr_oublk = p->p_ru.oublock;
11030Sstevel@tonic-gate pup->pr_msnd = p->p_ru.msgsnd;
11040Sstevel@tonic-gate pup->pr_mrcv = p->p_ru.msgrcv;
11050Sstevel@tonic-gate pup->pr_sigs = p->p_ru.nsignals;
11060Sstevel@tonic-gate pup->pr_vctx = p->p_ru.nvcsw;
11070Sstevel@tonic-gate pup->pr_ictx = p->p_ru.nivcsw;
11080Sstevel@tonic-gate pup->pr_sysc = p->p_ru.sysc;
11090Sstevel@tonic-gate pup->pr_ioch = p->p_ru.ioch;
11100Sstevel@tonic-gate
11110Sstevel@tonic-gate /*
11120Sstevel@tonic-gate * Add the usage information for each active lwp.
11130Sstevel@tonic-gate */
11140Sstevel@tonic-gate if ((t = p->p_tlist) != NULL &&
11150Sstevel@tonic-gate !(pcp->prc_flags & PRC_DESTROY)) {
11160Sstevel@tonic-gate do {
11170Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
11180Sstevel@tonic-gate pup->pr_count++;
11190Sstevel@tonic-gate praddusage(t, pup);
11200Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
11210Sstevel@tonic-gate }
11220Sstevel@tonic-gate }
11230Sstevel@tonic-gate
11240Sstevel@tonic-gate prunlock(pnp);
11250Sstevel@tonic-gate
11260Sstevel@tonic-gate upup = kmem_zalloc(sizeof (*upup), KM_SLEEP);
11270Sstevel@tonic-gate prcvtusage(&un.prhusage, upup);
11280Sstevel@tonic-gate if (copyout(upup, cmaddr, sizeof (*upup)))
11290Sstevel@tonic-gate error = EFAULT;
11300Sstevel@tonic-gate kmem_free(upup, sizeof (*upup));
11310Sstevel@tonic-gate
11320Sstevel@tonic-gate break;
11330Sstevel@tonic-gate }
11340Sstevel@tonic-gate
11350Sstevel@tonic-gate case PIOCLUSAGE: /* get detailed usage info */
11360Sstevel@tonic-gate {
11370Sstevel@tonic-gate int Nlwp;
11380Sstevel@tonic-gate int nlwp;
11390Sstevel@tonic-gate prusage_t *upup;
11400Sstevel@tonic-gate prusage_t *Bupup;
11410Sstevel@tonic-gate prhusage_t *pup;
11420Sstevel@tonic-gate hrtime_t curtime;
11430Sstevel@tonic-gate
11440Sstevel@tonic-gate nlwp = Nlwp = (pcp->prc_flags & PRC_DESTROY)? 0 : p->p_lwpcnt;
11450Sstevel@tonic-gate
11460Sstevel@tonic-gate if (thing && thingsize !=
11470Sstevel@tonic-gate sizeof (prhusage_t) + (Nlwp+1) * sizeof (prusage_t)) {
11480Sstevel@tonic-gate kmem_free(thing, thingsize);
11490Sstevel@tonic-gate thing = NULL;
11500Sstevel@tonic-gate }
11510Sstevel@tonic-gate if (thing == NULL) {
11520Sstevel@tonic-gate thingsize = sizeof (prhusage_t) +
11530Sstevel@tonic-gate (Nlwp+1) * sizeof (prusage_t);
11540Sstevel@tonic-gate thing = kmem_alloc(thingsize, KM_NOSLEEP);
11550Sstevel@tonic-gate }
11560Sstevel@tonic-gate if (thing == NULL) {
11570Sstevel@tonic-gate prunlock(pnp);
11580Sstevel@tonic-gate goto startover;
11590Sstevel@tonic-gate }
11600Sstevel@tonic-gate
11610Sstevel@tonic-gate pup = thing;
11620Sstevel@tonic-gate upup = Bupup = (prusage_t *)(pup + 1);
11630Sstevel@tonic-gate
11640Sstevel@tonic-gate ASSERT(p == pcp->prc_proc);
11650Sstevel@tonic-gate
11660Sstevel@tonic-gate curtime = gethrtime();
11670Sstevel@tonic-gate
11680Sstevel@tonic-gate /*
11690Sstevel@tonic-gate * First the summation over defunct lwps.
11700Sstevel@tonic-gate */
11710Sstevel@tonic-gate bzero(pup, sizeof (*pup));
11720Sstevel@tonic-gate pup->pr_count = p->p_defunct;
11730Sstevel@tonic-gate pup->pr_tstamp = curtime;
11740Sstevel@tonic-gate pup->pr_create = p->p_mstart;
11750Sstevel@tonic-gate pup->pr_term = p->p_mterm;
11760Sstevel@tonic-gate
11770Sstevel@tonic-gate pup->pr_rtime = p->p_mlreal;
11780Sstevel@tonic-gate pup->pr_utime = p->p_acct[LMS_USER];
11790Sstevel@tonic-gate pup->pr_stime = p->p_acct[LMS_SYSTEM];
11800Sstevel@tonic-gate pup->pr_ttime = p->p_acct[LMS_TRAP];
11810Sstevel@tonic-gate pup->pr_tftime = p->p_acct[LMS_TFAULT];
11820Sstevel@tonic-gate pup->pr_dftime = p->p_acct[LMS_DFAULT];
11830Sstevel@tonic-gate pup->pr_kftime = p->p_acct[LMS_KFAULT];
11840Sstevel@tonic-gate pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
11850Sstevel@tonic-gate pup->pr_slptime = p->p_acct[LMS_SLEEP];
11860Sstevel@tonic-gate pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
11870Sstevel@tonic-gate pup->pr_stoptime = p->p_acct[LMS_STOPPED];
11880Sstevel@tonic-gate
11890Sstevel@tonic-gate pup->pr_minf = p->p_ru.minflt;
11900Sstevel@tonic-gate pup->pr_majf = p->p_ru.majflt;
11910Sstevel@tonic-gate pup->pr_nswap = p->p_ru.nswap;
11920Sstevel@tonic-gate pup->pr_inblk = p->p_ru.inblock;
11930Sstevel@tonic-gate pup->pr_oublk = p->p_ru.oublock;
11940Sstevel@tonic-gate pup->pr_msnd = p->p_ru.msgsnd;
11950Sstevel@tonic-gate pup->pr_mrcv = p->p_ru.msgrcv;
11960Sstevel@tonic-gate pup->pr_sigs = p->p_ru.nsignals;
11970Sstevel@tonic-gate pup->pr_vctx = p->p_ru.nvcsw;
11980Sstevel@tonic-gate pup->pr_ictx = p->p_ru.nivcsw;
11990Sstevel@tonic-gate pup->pr_sysc = p->p_ru.sysc;
12000Sstevel@tonic-gate pup->pr_ioch = p->p_ru.ioch;
12010Sstevel@tonic-gate
12020Sstevel@tonic-gate prcvtusage(pup, upup);
12030Sstevel@tonic-gate
12040Sstevel@tonic-gate /*
12050Sstevel@tonic-gate * Fill one prusage struct for each active lwp.
12060Sstevel@tonic-gate */
12070Sstevel@tonic-gate if ((t = p->p_tlist) != NULL &&
12080Sstevel@tonic-gate !(pcp->prc_flags & PRC_DESTROY)) {
12090Sstevel@tonic-gate do {
12100Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
12110Sstevel@tonic-gate ASSERT(nlwp > 0);
12120Sstevel@tonic-gate --nlwp;
12130Sstevel@tonic-gate upup++;
12140Sstevel@tonic-gate prgetusage(t, pup);
12150Sstevel@tonic-gate prcvtusage(pup, upup);
12160Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
12170Sstevel@tonic-gate }
12180Sstevel@tonic-gate ASSERT(nlwp == 0);
12190Sstevel@tonic-gate
12200Sstevel@tonic-gate prunlock(pnp);
12210Sstevel@tonic-gate if (copyout(Bupup, cmaddr, (Nlwp+1) * sizeof (prusage_t)))
12220Sstevel@tonic-gate error = EFAULT;
12230Sstevel@tonic-gate kmem_free(thing, thingsize);
12240Sstevel@tonic-gate thing = NULL;
12250Sstevel@tonic-gate break;
12260Sstevel@tonic-gate }
12270Sstevel@tonic-gate
12280Sstevel@tonic-gate case PIOCNAUXV: /* get number of aux vector entries */
12290Sstevel@tonic-gate {
12300Sstevel@tonic-gate int n = __KERN_NAUXV_IMPL;
12310Sstevel@tonic-gate
12320Sstevel@tonic-gate prunlock(pnp);
12330Sstevel@tonic-gate if (copyout(&n, cmaddr, sizeof (int)))
12340Sstevel@tonic-gate error = EFAULT;
12350Sstevel@tonic-gate break;
12360Sstevel@tonic-gate }
12370Sstevel@tonic-gate
12380Sstevel@tonic-gate case PIOCAUXV: /* get aux vector (see sys/auxv.h) */
12390Sstevel@tonic-gate {
12400Sstevel@tonic-gate up = PTOU(p);
12410Sstevel@tonic-gate bcopy(up->u_auxv, un.auxv,
12420Sstevel@tonic-gate __KERN_NAUXV_IMPL * sizeof (auxv_t));
12430Sstevel@tonic-gate prunlock(pnp);
12440Sstevel@tonic-gate if (copyout(un.auxv, cmaddr,
12450Sstevel@tonic-gate __KERN_NAUXV_IMPL * sizeof (auxv_t)))
12460Sstevel@tonic-gate error = EFAULT;
12470Sstevel@tonic-gate break;
12480Sstevel@tonic-gate }
12490Sstevel@tonic-gate
12500Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
12510Sstevel@tonic-gate case PIOCNLDT: /* get number of LDT entries */
12520Sstevel@tonic-gate {
12530Sstevel@tonic-gate int n;
12540Sstevel@tonic-gate
12558921SVamsi.Krishna@Sun.COM mutex_exit(&p->p_lock);
12560Sstevel@tonic-gate mutex_enter(&p->p_ldtlock);
12570Sstevel@tonic-gate n = prnldt(p);
12580Sstevel@tonic-gate mutex_exit(&p->p_ldtlock);
12598921SVamsi.Krishna@Sun.COM mutex_enter(&p->p_lock);
12600Sstevel@tonic-gate prunlock(pnp);
12610Sstevel@tonic-gate if (copyout(&n, cmaddr, sizeof (n)))
12620Sstevel@tonic-gate error = EFAULT;
12630Sstevel@tonic-gate break;
12640Sstevel@tonic-gate }
12650Sstevel@tonic-gate
12660Sstevel@tonic-gate case PIOCLDT: /* get LDT entries */
12670Sstevel@tonic-gate {
12680Sstevel@tonic-gate struct ssd *ssd;
12690Sstevel@tonic-gate int n;
12700Sstevel@tonic-gate
12718921SVamsi.Krishna@Sun.COM mutex_exit(&p->p_lock);
12720Sstevel@tonic-gate mutex_enter(&p->p_ldtlock);
12730Sstevel@tonic-gate n = prnldt(p);
12740Sstevel@tonic-gate
12750Sstevel@tonic-gate if (thing && thingsize != (n+1) * sizeof (*ssd)) {
12760Sstevel@tonic-gate kmem_free(thing, thingsize);
12770Sstevel@tonic-gate thing = NULL;
12780Sstevel@tonic-gate }
12790Sstevel@tonic-gate if (thing == NULL) {
12800Sstevel@tonic-gate thingsize = (n+1) * sizeof (*ssd);
12810Sstevel@tonic-gate thing = kmem_alloc(thingsize, KM_NOSLEEP);
12820Sstevel@tonic-gate }
12830Sstevel@tonic-gate if (thing == NULL) {
12840Sstevel@tonic-gate mutex_exit(&p->p_ldtlock);
12858921SVamsi.Krishna@Sun.COM mutex_enter(&p->p_lock);
12860Sstevel@tonic-gate prunlock(pnp);
12870Sstevel@tonic-gate goto startover;
12880Sstevel@tonic-gate }
12890Sstevel@tonic-gate
12900Sstevel@tonic-gate ssd = thing;
12910Sstevel@tonic-gate thing = NULL;
12920Sstevel@tonic-gate if (n != 0)
12930Sstevel@tonic-gate prgetldt(p, ssd);
12940Sstevel@tonic-gate mutex_exit(&p->p_ldtlock);
12958921SVamsi.Krishna@Sun.COM mutex_enter(&p->p_lock);
12960Sstevel@tonic-gate prunlock(pnp);
12970Sstevel@tonic-gate
12980Sstevel@tonic-gate /* mark the end of the list with a null entry */
12990Sstevel@tonic-gate bzero(&ssd[n], sizeof (*ssd));
13000Sstevel@tonic-gate if (copyout(ssd, cmaddr, (n+1) * sizeof (*ssd)))
13010Sstevel@tonic-gate error = EFAULT;
13020Sstevel@tonic-gate kmem_free(ssd, (n+1) * sizeof (*ssd));
13030Sstevel@tonic-gate break;
13040Sstevel@tonic-gate }
13050Sstevel@tonic-gate #endif /* __i386 || __amd64 */
13060Sstevel@tonic-gate
13070Sstevel@tonic-gate #if defined(__sparc)
13080Sstevel@tonic-gate case PIOCGWIN: /* get gwindows_t (see sys/reg.h) */
13090Sstevel@tonic-gate {
13100Sstevel@tonic-gate gwindows_t *gwp = thing;
13110Sstevel@tonic-gate
13120Sstevel@tonic-gate /* drop p->p_lock while touching the stack */
13130Sstevel@tonic-gate mutex_exit(&p->p_lock);
13140Sstevel@tonic-gate bzero(gwp, sizeof (*gwp));
13150Sstevel@tonic-gate prgetwindows(lwp, gwp);
13160Sstevel@tonic-gate mutex_enter(&p->p_lock);
13170Sstevel@tonic-gate prunlock(pnp);
13180Sstevel@tonic-gate if (copyout(gwp, cmaddr, sizeof (*gwp)))
13190Sstevel@tonic-gate error = EFAULT;
13200Sstevel@tonic-gate kmem_free(gwp, sizeof (gwindows_t));
13210Sstevel@tonic-gate thing = NULL;
13220Sstevel@tonic-gate break;
13230Sstevel@tonic-gate }
13240Sstevel@tonic-gate #endif /* __sparc */
13250Sstevel@tonic-gate
13260Sstevel@tonic-gate default:
13270Sstevel@tonic-gate prunlock(pnp);
13280Sstevel@tonic-gate error = EINVAL;
13290Sstevel@tonic-gate break;
13300Sstevel@tonic-gate
13310Sstevel@tonic-gate }
13320Sstevel@tonic-gate
13330Sstevel@tonic-gate ASSERT(thing == NULL);
13340Sstevel@tonic-gate ASSERT(xpnp == NULL);
13350Sstevel@tonic-gate return (error);
13360Sstevel@tonic-gate }
13370Sstevel@tonic-gate
13380Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
13390Sstevel@tonic-gate
13402789Sfrankho static int oprgetmap32(proc_t *, list_t *);
13410Sstevel@tonic-gate
13420Sstevel@tonic-gate void
oprgetstatus32(kthread_t * t,prstatus32_t * sp,zone_t * zp)13430Sstevel@tonic-gate oprgetstatus32(kthread_t *t, prstatus32_t *sp, zone_t *zp)
13440Sstevel@tonic-gate {
13450Sstevel@tonic-gate proc_t *p = ttoproc(t);
13460Sstevel@tonic-gate klwp_t *lwp = ttolwp(t);
13470Sstevel@tonic-gate int32_t flags;
13480Sstevel@tonic-gate user_t *up;
13490Sstevel@tonic-gate ulong_t instr;
13500Sstevel@tonic-gate
13510Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock));
13520Sstevel@tonic-gate
13530Sstevel@tonic-gate up = PTOU(p);
13540Sstevel@tonic-gate bzero(sp, sizeof (*sp));
13550Sstevel@tonic-gate flags = 0L;
13560Sstevel@tonic-gate if (t->t_state == TS_STOPPED) {
13570Sstevel@tonic-gate flags |= PR_STOPPED;
13580Sstevel@tonic-gate if ((t->t_schedflag & TS_PSTART) == 0)
13590Sstevel@tonic-gate flags |= PR_ISTOP;
13600Sstevel@tonic-gate } else if (VSTOPPED(t)) {
13610Sstevel@tonic-gate flags |= PR_STOPPED|PR_ISTOP;
13620Sstevel@tonic-gate }
13630Sstevel@tonic-gate if (!(flags & PR_ISTOP) && (t->t_proc_flag & TP_PRSTOP))
13640Sstevel@tonic-gate flags |= PR_DSTOP;
13650Sstevel@tonic-gate if (lwp->lwp_asleep)
13660Sstevel@tonic-gate flags |= PR_ASLEEP;
13670Sstevel@tonic-gate if (p->p_proc_flag & P_PR_FORK)
13680Sstevel@tonic-gate flags |= PR_FORK;
13690Sstevel@tonic-gate if (p->p_proc_flag & P_PR_RUNLCL)
13700Sstevel@tonic-gate flags |= PR_RLC;
13710Sstevel@tonic-gate if (p->p_proc_flag & P_PR_KILLCL)
13720Sstevel@tonic-gate flags |= PR_KLC;
13730Sstevel@tonic-gate if (p->p_proc_flag & P_PR_ASYNC)
13740Sstevel@tonic-gate flags |= PR_ASYNC;
13750Sstevel@tonic-gate if (p->p_proc_flag & P_PR_BPTADJ)
13760Sstevel@tonic-gate flags |= PR_BPTADJ;
13770Sstevel@tonic-gate if (p->p_proc_flag & P_PR_PTRACE)
13780Sstevel@tonic-gate flags |= PR_PCOMPAT;
13790Sstevel@tonic-gate if (t->t_proc_flag & TP_MSACCT)
13800Sstevel@tonic-gate flags |= PR_MSACCT;
13810Sstevel@tonic-gate sp->pr_flags = flags;
13820Sstevel@tonic-gate if (VSTOPPED(t)) {
13830Sstevel@tonic-gate sp->pr_why = PR_REQUESTED;
13840Sstevel@tonic-gate sp->pr_what = 0;
13850Sstevel@tonic-gate } else {
13860Sstevel@tonic-gate sp->pr_why = t->t_whystop;
13870Sstevel@tonic-gate sp->pr_what = t->t_whatstop;
13880Sstevel@tonic-gate }
13890Sstevel@tonic-gate
13900Sstevel@tonic-gate if (t->t_whystop == PR_FAULTED) {
13910Sstevel@tonic-gate siginfo_kto32(&lwp->lwp_siginfo, &sp->pr_info);
13920Sstevel@tonic-gate if (t->t_whatstop == FLTPAGE)
13930Sstevel@tonic-gate sp->pr_info.si_addr =
13940Sstevel@tonic-gate (caddr32_t)(uintptr_t)lwp->lwp_siginfo.si_addr;
13950Sstevel@tonic-gate } else if (lwp->lwp_curinfo)
13960Sstevel@tonic-gate siginfo_kto32(&lwp->lwp_curinfo->sq_info, &sp->pr_info);
13970Sstevel@tonic-gate
13980Sstevel@tonic-gate if (SI_FROMUSER(&lwp->lwp_siginfo) && zp->zone_id != GLOBAL_ZONEID &&
13990Sstevel@tonic-gate sp->pr_info.si_zoneid != zp->zone_id) {
14000Sstevel@tonic-gate sp->pr_info.si_pid = zp->zone_zsched->p_pid;
14010Sstevel@tonic-gate sp->pr_info.si_uid = 0;
14020Sstevel@tonic-gate sp->pr_info.si_ctid = -1;
14030Sstevel@tonic-gate sp->pr_info.si_zoneid = zp->zone_id;
14040Sstevel@tonic-gate }
14050Sstevel@tonic-gate
14060Sstevel@tonic-gate sp->pr_cursig = lwp->lwp_cursig;
14070Sstevel@tonic-gate prassignset(&sp->pr_sigpend, &p->p_sig);
14080Sstevel@tonic-gate prassignset(&sp->pr_lwppend, &t->t_sig);
14090Sstevel@tonic-gate schedctl_finish_sigblock(t);
14100Sstevel@tonic-gate prassignset(&sp->pr_sighold, &t->t_hold);
14110Sstevel@tonic-gate sp->pr_altstack.ss_sp =
14120Sstevel@tonic-gate (caddr32_t)(uintptr_t)lwp->lwp_sigaltstack.ss_sp;
14130Sstevel@tonic-gate sp->pr_altstack.ss_size = (size32_t)lwp->lwp_sigaltstack.ss_size;
14140Sstevel@tonic-gate sp->pr_altstack.ss_flags = (int32_t)lwp->lwp_sigaltstack.ss_flags;
14150Sstevel@tonic-gate prgetaction32(p, up, lwp->lwp_cursig, &sp->pr_action);
14160Sstevel@tonic-gate sp->pr_pid = p->p_pid;
14170Sstevel@tonic-gate if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
14180Sstevel@tonic-gate (p->p_flag & SZONETOP)) {
14190Sstevel@tonic-gate ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
14200Sstevel@tonic-gate /*
14210Sstevel@tonic-gate * Inside local zones, fake zsched's pid as parent pids for
14220Sstevel@tonic-gate * processes which reference processes outside of the zone.
14230Sstevel@tonic-gate */
14240Sstevel@tonic-gate sp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
14250Sstevel@tonic-gate } else {
14260Sstevel@tonic-gate sp->pr_ppid = p->p_ppid;
14270Sstevel@tonic-gate }
14280Sstevel@tonic-gate sp->pr_pgrp = p->p_pgrp;
14290Sstevel@tonic-gate sp->pr_sid = p->p_sessp->s_sid;
14300Sstevel@tonic-gate hrt2ts32(mstate_aggr_state(p, LMS_USER), &sp->pr_utime);
14310Sstevel@tonic-gate hrt2ts32(mstate_aggr_state(p, LMS_SYSTEM), &sp->pr_stime);
14320Sstevel@tonic-gate TICK_TO_TIMESTRUC32(p->p_cutime, &sp->pr_cutime);
14330Sstevel@tonic-gate TICK_TO_TIMESTRUC32(p->p_cstime, &sp->pr_cstime);
14340Sstevel@tonic-gate (void) strncpy(sp->pr_clname, sclass[t->t_cid].cl_name,
14356409Sethindra sizeof (sp->pr_clname) - 1);
14360Sstevel@tonic-gate sp->pr_who = t->t_tid;
14370Sstevel@tonic-gate sp->pr_nlwp = p->p_lwpcnt;
14380Sstevel@tonic-gate sp->pr_brkbase = (caddr32_t)(uintptr_t)p->p_brkbase;
14390Sstevel@tonic-gate sp->pr_brksize = (size32_t)p->p_brksize;
14400Sstevel@tonic-gate sp->pr_stkbase = (caddr32_t)(uintptr_t)prgetstackbase(p);
14410Sstevel@tonic-gate sp->pr_stksize = (size32_t)p->p_stksize;
14420Sstevel@tonic-gate sp->pr_oldcontext = (caddr32_t)lwp->lwp_oldcontext;
14430Sstevel@tonic-gate sp->pr_processor = t->t_cpu->cpu_id;
14440Sstevel@tonic-gate sp->pr_bind = t->t_bind_cpu;
14450Sstevel@tonic-gate
14460Sstevel@tonic-gate /*
14470Sstevel@tonic-gate * Fetch the current instruction, if not a system process.
14480Sstevel@tonic-gate * We don't attempt this unless the lwp is stopped.
14490Sstevel@tonic-gate */
14500Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
14510Sstevel@tonic-gate sp->pr_flags |= (PR_ISSYS|PR_PCINVAL);
14520Sstevel@tonic-gate else if (!(flags & PR_STOPPED))
14530Sstevel@tonic-gate sp->pr_flags |= PR_PCINVAL;
14540Sstevel@tonic-gate else if (!prfetchinstr(lwp, &instr))
14550Sstevel@tonic-gate sp->pr_flags |= PR_PCINVAL;
14560Sstevel@tonic-gate else
14570Sstevel@tonic-gate sp->pr_instr = (uint32_t)instr;
14580Sstevel@tonic-gate
14590Sstevel@tonic-gate /*
14600Sstevel@tonic-gate * Drop p_lock while touching the lwp's stack.
14610Sstevel@tonic-gate */
14620Sstevel@tonic-gate mutex_exit(&p->p_lock);
14630Sstevel@tonic-gate if (prisstep(lwp))
14640Sstevel@tonic-gate sp->pr_flags |= PR_STEP;
14650Sstevel@tonic-gate if ((flags & (PR_STOPPED|PR_ASLEEP)) && t->t_sysnum) {
14660Sstevel@tonic-gate int i;
14670Sstevel@tonic-gate auxv_t *auxp;
14680Sstevel@tonic-gate
14690Sstevel@tonic-gate sp->pr_syscall = get_syscall32_args(lwp,
14706409Sethindra (int *)sp->pr_sysarg, &i);
14710Sstevel@tonic-gate sp->pr_nsysarg = (short)i;
147211798SRoger.Faulkner@Sun.COM if (t->t_whystop == PR_SYSEXIT && t->t_sysnum == SYS_execve) {
14730Sstevel@tonic-gate sp->pr_sysarg[0] = 0;
14740Sstevel@tonic-gate sp->pr_sysarg[1] = (caddr32_t)up->u_argv;
14750Sstevel@tonic-gate sp->pr_sysarg[2] = (caddr32_t)up->u_envp;
14760Sstevel@tonic-gate for (i = 0, auxp = up->u_auxv;
14770Sstevel@tonic-gate i < sizeof (up->u_auxv) / sizeof (up->u_auxv[0]);
14780Sstevel@tonic-gate i++, auxp++) {
14790Sstevel@tonic-gate if (auxp->a_type == AT_SUN_EXECNAME) {
14800Sstevel@tonic-gate sp->pr_sysarg[0] =
14816409Sethindra (caddr32_t)
14826409Sethindra (uintptr_t)auxp->a_un.a_ptr;
14830Sstevel@tonic-gate break;
14840Sstevel@tonic-gate }
14850Sstevel@tonic-gate }
14860Sstevel@tonic-gate }
14870Sstevel@tonic-gate }
14880Sstevel@tonic-gate if ((flags & PR_STOPPED) || t == curthread)
14890Sstevel@tonic-gate prgetprregs32(lwp, sp->pr_reg);
14900Sstevel@tonic-gate mutex_enter(&p->p_lock);
14910Sstevel@tonic-gate }
14920Sstevel@tonic-gate
14930Sstevel@tonic-gate void
oprgetpsinfo32(proc_t * p,prpsinfo32_t * psp,kthread_t * tp)14940Sstevel@tonic-gate oprgetpsinfo32(proc_t *p, prpsinfo32_t *psp, kthread_t *tp)
14950Sstevel@tonic-gate {
14960Sstevel@tonic-gate kthread_t *t;
14970Sstevel@tonic-gate char c, state;
14980Sstevel@tonic-gate user_t *up;
14990Sstevel@tonic-gate dev_t d;
15000Sstevel@tonic-gate uint64_t pct;
15010Sstevel@tonic-gate int retval, niceval;
15020Sstevel@tonic-gate cred_t *cred;
15030Sstevel@tonic-gate struct as *as;
15040Sstevel@tonic-gate hrtime_t hrutime, hrstime, cur_time;
15050Sstevel@tonic-gate
15060Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock));
15070Sstevel@tonic-gate
15080Sstevel@tonic-gate bzero(psp, sizeof (*psp));
15090Sstevel@tonic-gate
15100Sstevel@tonic-gate if ((t = tp) == NULL)
15110Sstevel@tonic-gate t = prchoose(p); /* returns locked thread */
15120Sstevel@tonic-gate else
15130Sstevel@tonic-gate thread_lock(t);
15140Sstevel@tonic-gate
15150Sstevel@tonic-gate /* kludge: map thread state enum into process state enum */
15160Sstevel@tonic-gate
15170Sstevel@tonic-gate if (t == NULL) {
15180Sstevel@tonic-gate state = TS_ZOMB;
15190Sstevel@tonic-gate } else {
15200Sstevel@tonic-gate state = VSTOPPED(t) ? TS_STOPPED : t->t_state;
15210Sstevel@tonic-gate thread_unlock(t);
15220Sstevel@tonic-gate }
15230Sstevel@tonic-gate
15240Sstevel@tonic-gate switch (state) {
15250Sstevel@tonic-gate case TS_SLEEP: state = SSLEEP; break;
15260Sstevel@tonic-gate case TS_RUN: state = SRUN; break;
15270Sstevel@tonic-gate case TS_ONPROC: state = SONPROC; break;
15280Sstevel@tonic-gate case TS_ZOMB: state = SZOMB; break;
15290Sstevel@tonic-gate case TS_STOPPED: state = SSTOP; break;
15300Sstevel@tonic-gate default: state = 0; break;
15310Sstevel@tonic-gate }
15320Sstevel@tonic-gate switch (state) {
15330Sstevel@tonic-gate case SSLEEP: c = 'S'; break;
15340Sstevel@tonic-gate case SRUN: c = 'R'; break;
15350Sstevel@tonic-gate case SZOMB: c = 'Z'; break;
15360Sstevel@tonic-gate case SSTOP: c = 'T'; break;
15370Sstevel@tonic-gate case SIDL: c = 'I'; break;
15380Sstevel@tonic-gate case SONPROC: c = 'O'; break;
15390Sstevel@tonic-gate #ifdef SXBRK
15400Sstevel@tonic-gate case SXBRK: c = 'X'; break;
15410Sstevel@tonic-gate #endif
15420Sstevel@tonic-gate default: c = '?'; break;
15430Sstevel@tonic-gate }
15440Sstevel@tonic-gate psp->pr_state = state;
15450Sstevel@tonic-gate psp->pr_sname = c;
15460Sstevel@tonic-gate psp->pr_zomb = (state == SZOMB);
15470Sstevel@tonic-gate /*
15480Sstevel@tonic-gate * only export SSYS and SMSACCT; everything else is off-limits to
15490Sstevel@tonic-gate * userland apps.
15500Sstevel@tonic-gate */
15510Sstevel@tonic-gate psp->pr_flag = p->p_flag & (SSYS | SMSACCT);
15520Sstevel@tonic-gate
15530Sstevel@tonic-gate mutex_enter(&p->p_crlock);
15540Sstevel@tonic-gate cred = p->p_cred;
15550Sstevel@tonic-gate psp->pr_uid = crgetruid(cred);
15560Sstevel@tonic-gate psp->pr_gid = crgetrgid(cred);
15570Sstevel@tonic-gate psp->pr_euid = crgetuid(cred);
15580Sstevel@tonic-gate psp->pr_egid = crgetgid(cred);
15590Sstevel@tonic-gate mutex_exit(&p->p_crlock);
15600Sstevel@tonic-gate
15610Sstevel@tonic-gate psp->pr_pid = p->p_pid;
15620Sstevel@tonic-gate if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
15630Sstevel@tonic-gate (p->p_flag & SZONETOP)) {
15640Sstevel@tonic-gate ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
15650Sstevel@tonic-gate /*
15660Sstevel@tonic-gate * Inside local zones, fake zsched's pid as parent pids for
15670Sstevel@tonic-gate * processes which reference processes outside of the zone.
15680Sstevel@tonic-gate */
15690Sstevel@tonic-gate psp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
15700Sstevel@tonic-gate } else {
15710Sstevel@tonic-gate psp->pr_ppid = p->p_ppid;
15720Sstevel@tonic-gate }
15730Sstevel@tonic-gate psp->pr_pgrp = p->p_pgrp;
15740Sstevel@tonic-gate psp->pr_sid = p->p_sessp->s_sid;
15750Sstevel@tonic-gate psp->pr_addr = 0; /* cannot represent 64-bit addr in 32 bits */
15760Sstevel@tonic-gate hrutime = mstate_aggr_state(p, LMS_USER);
15770Sstevel@tonic-gate hrstime = mstate_aggr_state(p, LMS_SYSTEM);
15780Sstevel@tonic-gate hrt2ts32(hrutime + hrstime, &psp->pr_time);
15790Sstevel@tonic-gate TICK_TO_TIMESTRUC32(p->p_cutime + p->p_cstime, &psp->pr_ctime);
15800Sstevel@tonic-gate switch (p->p_model) {
15810Sstevel@tonic-gate case DATAMODEL_ILP32:
15820Sstevel@tonic-gate psp->pr_dmodel = PR_MODEL_ILP32;
15830Sstevel@tonic-gate break;
15840Sstevel@tonic-gate case DATAMODEL_LP64:
15850Sstevel@tonic-gate psp->pr_dmodel = PR_MODEL_LP64;
15860Sstevel@tonic-gate break;
15870Sstevel@tonic-gate }
15880Sstevel@tonic-gate if (state == SZOMB || t == NULL) {
15890Sstevel@tonic-gate int wcode = p->p_wcode; /* must be atomic read */
15900Sstevel@tonic-gate
15910Sstevel@tonic-gate if (wcode)
15920Sstevel@tonic-gate psp->pr_wstat = wstat(wcode, p->p_wdata);
15930Sstevel@tonic-gate psp->pr_lttydev = PRNODEV32;
15940Sstevel@tonic-gate psp->pr_ottydev = (o_dev_t)PRNODEV32;
15950Sstevel@tonic-gate psp->pr_size = 0;
15960Sstevel@tonic-gate psp->pr_rssize = 0;
15970Sstevel@tonic-gate psp->pr_pctmem = 0;
15980Sstevel@tonic-gate } else {
15990Sstevel@tonic-gate up = PTOU(p);
16000Sstevel@tonic-gate psp->pr_wchan = 0; /* cannot represent in 32 bits */
16010Sstevel@tonic-gate psp->pr_pri = t->t_pri;
16020Sstevel@tonic-gate (void) strncpy(psp->pr_clname, sclass[t->t_cid].cl_name,
16036409Sethindra sizeof (psp->pr_clname) - 1);
16040Sstevel@tonic-gate retval = CL_DONICE(t, NULL, 0, &niceval);
16050Sstevel@tonic-gate if (retval == 0) {
16060Sstevel@tonic-gate psp->pr_oldpri = v.v_maxsyspri - psp->pr_pri;
16070Sstevel@tonic-gate psp->pr_nice = niceval + NZERO;
16080Sstevel@tonic-gate } else {
16090Sstevel@tonic-gate psp->pr_oldpri = 0;
16100Sstevel@tonic-gate psp->pr_nice = 0;
16110Sstevel@tonic-gate }
16120Sstevel@tonic-gate d = cttydev(p);
16130Sstevel@tonic-gate #ifdef sun
16140Sstevel@tonic-gate {
16150Sstevel@tonic-gate extern dev_t rwsconsdev, rconsdev, uconsdev;
16160Sstevel@tonic-gate /*
16170Sstevel@tonic-gate * If the controlling terminal is the real
16180Sstevel@tonic-gate * or workstation console device, map to what the
16196409Sethindra * user thinks is the console device. Handle case when
16206409Sethindra * rwsconsdev or rconsdev is set to NODEV for Starfire.
16210Sstevel@tonic-gate */
16226409Sethindra if ((d == rwsconsdev || d == rconsdev) && d != NODEV)
16230Sstevel@tonic-gate d = uconsdev;
16240Sstevel@tonic-gate }
16250Sstevel@tonic-gate #endif
16260Sstevel@tonic-gate (void) cmpldev(&psp->pr_lttydev, d);
16270Sstevel@tonic-gate psp->pr_ottydev = cmpdev(d);
16280Sstevel@tonic-gate TIMESPEC_TO_TIMESPEC32(&psp->pr_start, &up->u_start);
16290Sstevel@tonic-gate bcopy(up->u_comm, psp->pr_fname,
16300Sstevel@tonic-gate MIN(sizeof (up->u_comm), sizeof (psp->pr_fname)-1));
16310Sstevel@tonic-gate bcopy(up->u_psargs, psp->pr_psargs,
16320Sstevel@tonic-gate MIN(PRARGSZ-1, PSARGSZ));
16330Sstevel@tonic-gate psp->pr_syscall = t->t_sysnum;
16340Sstevel@tonic-gate psp->pr_argc = up->u_argc;
16350Sstevel@tonic-gate psp->pr_argv = (caddr32_t)up->u_argv;
16360Sstevel@tonic-gate psp->pr_envp = (caddr32_t)up->u_envp;
16370Sstevel@tonic-gate
16380Sstevel@tonic-gate /* compute %cpu for the lwp or process */
16390Sstevel@tonic-gate pct = 0;
16400Sstevel@tonic-gate if ((t = tp) == NULL)
16410Sstevel@tonic-gate t = p->p_tlist;
16420Sstevel@tonic-gate cur_time = gethrtime_unscaled();
16430Sstevel@tonic-gate do {
16440Sstevel@tonic-gate pct += cpu_update_pct(t, cur_time);
16450Sstevel@tonic-gate if (tp != NULL) /* just do the one lwp */
16460Sstevel@tonic-gate break;
16470Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
16480Sstevel@tonic-gate
16490Sstevel@tonic-gate psp->pr_pctcpu = prgetpctcpu(pct);
16500Sstevel@tonic-gate psp->pr_cpu = (psp->pr_pctcpu*100 + 0x6000) >> 15; /* [0..99] */
16510Sstevel@tonic-gate if (psp->pr_cpu > 99)
16520Sstevel@tonic-gate psp->pr_cpu = 99;
16530Sstevel@tonic-gate
16540Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
16550Sstevel@tonic-gate psp->pr_size = 0;
16560Sstevel@tonic-gate psp->pr_rssize = 0;
16570Sstevel@tonic-gate psp->pr_pctmem = 0;
16580Sstevel@tonic-gate } else {
16590Sstevel@tonic-gate mutex_exit(&p->p_lock);
16600Sstevel@tonic-gate AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
166110169SSudheer.Abdul-Salam@Sun.COM psp->pr_size = (size32_t)btopr(as->a_resvsize);
16620Sstevel@tonic-gate psp->pr_rssize = (size32_t)rm_asrss(as);
16630Sstevel@tonic-gate psp->pr_pctmem = rm_pctmemory(as);
16640Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
16650Sstevel@tonic-gate mutex_enter(&p->p_lock);
16660Sstevel@tonic-gate }
16670Sstevel@tonic-gate }
16680Sstevel@tonic-gate psp->pr_bysize = (size32_t)ptob(psp->pr_size);
16690Sstevel@tonic-gate psp->pr_byrssize = (size32_t)ptob(psp->pr_rssize);
16700Sstevel@tonic-gate
16710Sstevel@tonic-gate /*
16720Sstevel@tonic-gate * If we are looking at an LP64 process, zero out
16730Sstevel@tonic-gate * the fields that cannot be represented in ILP32.
16740Sstevel@tonic-gate */
16750Sstevel@tonic-gate if (p->p_model != DATAMODEL_ILP32) {
16760Sstevel@tonic-gate psp->pr_size = 0;
16770Sstevel@tonic-gate psp->pr_rssize = 0;
16780Sstevel@tonic-gate psp->pr_bysize = 0;
16790Sstevel@tonic-gate psp->pr_byrssize = 0;
16800Sstevel@tonic-gate psp->pr_argv = 0;
16810Sstevel@tonic-gate psp->pr_envp = 0;
16820Sstevel@tonic-gate }
16830Sstevel@tonic-gate }
16840Sstevel@tonic-gate
16855331Samw /*ARGSUSED*/
16860Sstevel@tonic-gate static int
prioctl32(struct vnode * vp,int cmd,intptr_t arg,int flag,cred_t * cr,int * rvalp,caller_context_t * ct)16875331Samw prioctl32(
16885331Samw struct vnode *vp,
16895331Samw int cmd,
16905331Samw intptr_t arg,
16915331Samw int flag,
16925331Samw cred_t *cr,
16935331Samw int *rvalp,
16945331Samw caller_context_t *ct)
16950Sstevel@tonic-gate {
1696*11940SRoger.Faulkner@Sun.COM int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
16970Sstevel@tonic-gate caddr_t cmaddr = (caddr_t)arg;
16980Sstevel@tonic-gate proc_t *p;
16990Sstevel@tonic-gate user_t *up;
17000Sstevel@tonic-gate kthread_t *t;
17010Sstevel@tonic-gate klwp_t *lwp;
17020Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
17030Sstevel@tonic-gate prcommon_t *pcp;
17040Sstevel@tonic-gate prnode_t *xpnp = NULL;
17050Sstevel@tonic-gate int error;
17060Sstevel@tonic-gate int zdisp;
17070Sstevel@tonic-gate void *thing = NULL;
17080Sstevel@tonic-gate size_t thingsize = 0;
17090Sstevel@tonic-gate
17100Sstevel@tonic-gate /*
17110Sstevel@tonic-gate * For copyin()/copyout().
17120Sstevel@tonic-gate */
17130Sstevel@tonic-gate union {
17140Sstevel@tonic-gate caddr32_t va;
17150Sstevel@tonic-gate int signo;
17160Sstevel@tonic-gate int nice;
17170Sstevel@tonic-gate uint_t lwpid;
17180Sstevel@tonic-gate int32_t flags;
17190Sstevel@tonic-gate prstatus32_t prstat;
17200Sstevel@tonic-gate prrun32_t prrun;
17210Sstevel@tonic-gate sigset_t smask;
17220Sstevel@tonic-gate siginfo32_t info;
17230Sstevel@tonic-gate sysset_t prmask;
17240Sstevel@tonic-gate prgregset32_t regs;
17250Sstevel@tonic-gate prfpregset32_t fpregs;
17260Sstevel@tonic-gate prpsinfo32_t prps;
17270Sstevel@tonic-gate sigset_t holdmask;
17280Sstevel@tonic-gate fltset_t fltmask;
17290Sstevel@tonic-gate prcred_t prcred;
17300Sstevel@tonic-gate prusage32_t prusage;
17310Sstevel@tonic-gate prhusage_t prhusage;
17320Sstevel@tonic-gate ioc_prmap32_t prmap;
17330Sstevel@tonic-gate auxv32_t auxv[__KERN_NAUXV_IMPL];
17340Sstevel@tonic-gate } un32;
17350Sstevel@tonic-gate
17360Sstevel@tonic-gate /*
17370Sstevel@tonic-gate * Native objects for internal use.
17380Sstevel@tonic-gate */
17390Sstevel@tonic-gate union {
17400Sstevel@tonic-gate caddr_t va;
17410Sstevel@tonic-gate int signo;
17420Sstevel@tonic-gate int nice;
17430Sstevel@tonic-gate uint_t lwpid;
17440Sstevel@tonic-gate long flags;
17450Sstevel@tonic-gate prstatus_t prstat;
17460Sstevel@tonic-gate prrun_t prrun;
17470Sstevel@tonic-gate sigset_t smask;
17480Sstevel@tonic-gate siginfo_t info;
17490Sstevel@tonic-gate sysset_t prmask;
17500Sstevel@tonic-gate prgregset_t regs;
17510Sstevel@tonic-gate prpsinfo_t prps;
17520Sstevel@tonic-gate sigset_t holdmask;
17530Sstevel@tonic-gate fltset_t fltmask;
17540Sstevel@tonic-gate prcred_t prcred;
17550Sstevel@tonic-gate prusage_t prusage;
17560Sstevel@tonic-gate prhusage_t prhusage;
17570Sstevel@tonic-gate auxv_t auxv[__KERN_NAUXV_IMPL];
17580Sstevel@tonic-gate } un;
17590Sstevel@tonic-gate
17600Sstevel@tonic-gate if (pnp->pr_type == PR_TMPL)
17610Sstevel@tonic-gate return (prctioctl(pnp, cmd, arg, flag, cr));
17620Sstevel@tonic-gate
17630Sstevel@tonic-gate /*
17640Sstevel@tonic-gate * Support for old /proc interface.
17650Sstevel@tonic-gate */
17660Sstevel@tonic-gate if (pnp->pr_pidfile != NULL) {
17670Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDDIR);
17680Sstevel@tonic-gate vp = pnp->pr_pidfile;
17690Sstevel@tonic-gate pnp = VTOP(vp);
17700Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDFILE);
17710Sstevel@tonic-gate }
17720Sstevel@tonic-gate
17730Sstevel@tonic-gate if (pnp->pr_type != PR_PIDFILE && pnp->pr_type != PR_LWPIDFILE)
17740Sstevel@tonic-gate return (ENOTTY);
17750Sstevel@tonic-gate
17760Sstevel@tonic-gate /*
17770Sstevel@tonic-gate * Fail ioctls which are logically "write" requests unless
17780Sstevel@tonic-gate * the user has write permission.
17790Sstevel@tonic-gate */
17800Sstevel@tonic-gate if ((flag & FWRITE) == 0 && isprwrioctl(cmd))
17810Sstevel@tonic-gate return (EBADF);
17820Sstevel@tonic-gate
17830Sstevel@tonic-gate /*
17840Sstevel@tonic-gate * Perform any necessary copyin() operations before
17850Sstevel@tonic-gate * locking the process. Helps avoid deadlocks and
17860Sstevel@tonic-gate * improves performance.
17870Sstevel@tonic-gate *
17880Sstevel@tonic-gate * Also, detect invalid ioctl codes here to avoid
17890Sstevel@tonic-gate * locking a process unnnecessarily.
17900Sstevel@tonic-gate *
17910Sstevel@tonic-gate * Also, prepare to allocate space that will be needed below,
17920Sstevel@tonic-gate * case by case.
17930Sstevel@tonic-gate */
17940Sstevel@tonic-gate error = 0;
17950Sstevel@tonic-gate switch (cmd) {
17960Sstevel@tonic-gate case PIOCGETPR:
17970Sstevel@tonic-gate thingsize = sizeof (proc_t);
17980Sstevel@tonic-gate break;
17990Sstevel@tonic-gate case PIOCGETU:
18000Sstevel@tonic-gate thingsize = sizeof (user_t);
18010Sstevel@tonic-gate break;
18020Sstevel@tonic-gate case PIOCSTOP:
18030Sstevel@tonic-gate case PIOCWSTOP:
18040Sstevel@tonic-gate case PIOCLWPIDS:
18050Sstevel@tonic-gate case PIOCGTRACE:
18060Sstevel@tonic-gate case PIOCGENTRY:
18070Sstevel@tonic-gate case PIOCGEXIT:
18080Sstevel@tonic-gate case PIOCSRLC:
18090Sstevel@tonic-gate case PIOCRRLC:
18100Sstevel@tonic-gate case PIOCSFORK:
18110Sstevel@tonic-gate case PIOCRFORK:
18120Sstevel@tonic-gate case PIOCGREG:
18130Sstevel@tonic-gate case PIOCGFPREG:
18140Sstevel@tonic-gate case PIOCSTATUS:
18150Sstevel@tonic-gate case PIOCLSTATUS:
18160Sstevel@tonic-gate case PIOCPSINFO:
18170Sstevel@tonic-gate case PIOCMAXSIG:
18180Sstevel@tonic-gate case PIOCGXREGSIZE:
18190Sstevel@tonic-gate break;
18200Sstevel@tonic-gate case PIOCSXREG: /* set extra registers */
18210Sstevel@tonic-gate case PIOCGXREG: /* get extra registers */
18220Sstevel@tonic-gate #if defined(__sparc)
18230Sstevel@tonic-gate thingsize = sizeof (prxregset_t);
18240Sstevel@tonic-gate #else
18250Sstevel@tonic-gate thingsize = 0;
18260Sstevel@tonic-gate #endif
18270Sstevel@tonic-gate break;
18280Sstevel@tonic-gate case PIOCACTION:
1829*11940SRoger.Faulkner@Sun.COM thingsize = (nsig-1) * sizeof (struct sigaction32);
18300Sstevel@tonic-gate break;
18310Sstevel@tonic-gate case PIOCGHOLD:
18320Sstevel@tonic-gate case PIOCNMAP:
18330Sstevel@tonic-gate case PIOCMAP:
18340Sstevel@tonic-gate case PIOCGFAULT:
18350Sstevel@tonic-gate case PIOCCFAULT:
18360Sstevel@tonic-gate case PIOCCRED:
18370Sstevel@tonic-gate case PIOCGROUPS:
18380Sstevel@tonic-gate case PIOCUSAGE:
18390Sstevel@tonic-gate case PIOCLUSAGE:
18400Sstevel@tonic-gate break;
18410Sstevel@tonic-gate case PIOCOPENPD:
18420Sstevel@tonic-gate /*
18430Sstevel@tonic-gate * We will need this below.
18440Sstevel@tonic-gate * Allocate it now, before locking the process.
18450Sstevel@tonic-gate */
18460Sstevel@tonic-gate xpnp = prgetnode(vp, PR_OPAGEDATA);
18470Sstevel@tonic-gate break;
18480Sstevel@tonic-gate case PIOCNAUXV:
18490Sstevel@tonic-gate case PIOCAUXV:
18500Sstevel@tonic-gate break;
18510Sstevel@tonic-gate
18520Sstevel@tonic-gate #if defined(__i386) || defined(__i386_COMPAT)
18530Sstevel@tonic-gate case PIOCNLDT:
18540Sstevel@tonic-gate case PIOCLDT:
18550Sstevel@tonic-gate break;
18560Sstevel@tonic-gate #endif /* __i386 || __i386_COMPAT */
18570Sstevel@tonic-gate
18580Sstevel@tonic-gate #if defined(__sparc)
18590Sstevel@tonic-gate case PIOCGWIN:
18600Sstevel@tonic-gate thingsize = sizeof (gwindows32_t);
18610Sstevel@tonic-gate break;
18620Sstevel@tonic-gate #endif /* __sparc */
18630Sstevel@tonic-gate
18640Sstevel@tonic-gate case PIOCOPENM: /* open mapped object for reading */
18650Sstevel@tonic-gate if (cmaddr == NULL)
18660Sstevel@tonic-gate un32.va = NULL;
18670Sstevel@tonic-gate else if (copyin(cmaddr, &un32.va, sizeof (un32.va)))
18680Sstevel@tonic-gate error = EFAULT;
18690Sstevel@tonic-gate break;
18700Sstevel@tonic-gate
18710Sstevel@tonic-gate case PIOCRUN: /* make lwp or process runnable */
18720Sstevel@tonic-gate if (cmaddr == NULL)
18730Sstevel@tonic-gate un32.prrun.pr_flags = 0;
18740Sstevel@tonic-gate else if (copyin(cmaddr, &un32.prrun, sizeof (un32.prrun)))
18750Sstevel@tonic-gate error = EFAULT;
18760Sstevel@tonic-gate break;
18770Sstevel@tonic-gate
18780Sstevel@tonic-gate case PIOCOPENLWP: /* return /proc lwp file descriptor */
18790Sstevel@tonic-gate if (copyin(cmaddr, &un32.lwpid, sizeof (un32.lwpid)))
18800Sstevel@tonic-gate error = EFAULT;
18810Sstevel@tonic-gate break;
18820Sstevel@tonic-gate
18830Sstevel@tonic-gate case PIOCSTRACE: /* set signal trace mask */
18840Sstevel@tonic-gate if (copyin(cmaddr, &un32.smask, sizeof (un32.smask)))
18850Sstevel@tonic-gate error = EFAULT;
18860Sstevel@tonic-gate break;
18870Sstevel@tonic-gate
18880Sstevel@tonic-gate case PIOCSSIG: /* set current signal */
18890Sstevel@tonic-gate if (cmaddr == NULL)
18900Sstevel@tonic-gate un32.info.si_signo = 0;
18910Sstevel@tonic-gate else if (copyin(cmaddr, &un32.info, sizeof (un32.info)))
18920Sstevel@tonic-gate error = EFAULT;
18930Sstevel@tonic-gate break;
18940Sstevel@tonic-gate
18950Sstevel@tonic-gate case PIOCKILL: /* send signal */
18960Sstevel@tonic-gate case PIOCUNKILL: /* delete a signal */
18970Sstevel@tonic-gate if (copyin(cmaddr, &un32.signo, sizeof (un32.signo)))
18980Sstevel@tonic-gate error = EFAULT;
18990Sstevel@tonic-gate break;
19000Sstevel@tonic-gate
19010Sstevel@tonic-gate case PIOCNICE: /* set nice priority */
19020Sstevel@tonic-gate if (copyin(cmaddr, &un32.nice, sizeof (un32.nice)))
19030Sstevel@tonic-gate error = EFAULT;
19040Sstevel@tonic-gate break;
19050Sstevel@tonic-gate
19060Sstevel@tonic-gate case PIOCSENTRY: /* set syscall entry bit mask */
19070Sstevel@tonic-gate case PIOCSEXIT: /* set syscall exit bit mask */
19080Sstevel@tonic-gate if (copyin(cmaddr, &un32.prmask, sizeof (un32.prmask)))
19090Sstevel@tonic-gate error = EFAULT;
19100Sstevel@tonic-gate break;
19110Sstevel@tonic-gate
19120Sstevel@tonic-gate case PIOCSET: /* set process flags */
19130Sstevel@tonic-gate case PIOCRESET: /* reset process flags */
19140Sstevel@tonic-gate if (copyin(cmaddr, &un32.flags, sizeof (un32.flags)))
19150Sstevel@tonic-gate error = EFAULT;
19160Sstevel@tonic-gate break;
19170Sstevel@tonic-gate
19180Sstevel@tonic-gate case PIOCSREG: /* set general registers */
19190Sstevel@tonic-gate if (copyin(cmaddr, un32.regs, sizeof (un32.regs)))
19200Sstevel@tonic-gate error = EFAULT;
19210Sstevel@tonic-gate break;
19220Sstevel@tonic-gate
19230Sstevel@tonic-gate case PIOCSFPREG: /* set floating-point registers */
19240Sstevel@tonic-gate if (copyin(cmaddr, &un32.fpregs, sizeof (un32.fpregs)))
19250Sstevel@tonic-gate error = EFAULT;
19260Sstevel@tonic-gate break;
19270Sstevel@tonic-gate
19280Sstevel@tonic-gate case PIOCSHOLD: /* set signal-hold mask */
19290Sstevel@tonic-gate if (copyin(cmaddr, &un32.holdmask, sizeof (un32.holdmask)))
19300Sstevel@tonic-gate error = EFAULT;
19310Sstevel@tonic-gate break;
19320Sstevel@tonic-gate
19330Sstevel@tonic-gate case PIOCSFAULT: /* set mask of traced faults */
19340Sstevel@tonic-gate if (copyin(cmaddr, &un32.fltmask, sizeof (un32.fltmask)))
19350Sstevel@tonic-gate error = EFAULT;
19360Sstevel@tonic-gate break;
19370Sstevel@tonic-gate
19380Sstevel@tonic-gate default:
19390Sstevel@tonic-gate error = EINVAL;
19400Sstevel@tonic-gate break;
19410Sstevel@tonic-gate }
19420Sstevel@tonic-gate
19430Sstevel@tonic-gate if (error)
19440Sstevel@tonic-gate return (error);
19450Sstevel@tonic-gate
19460Sstevel@tonic-gate startover:
19470Sstevel@tonic-gate /*
19480Sstevel@tonic-gate * If we need kmem_alloc()d space then we allocate it now, before
19490Sstevel@tonic-gate * grabbing the process lock. Using kmem_alloc(KM_SLEEP) while
19500Sstevel@tonic-gate * holding the process lock leads to deadlock with the clock thread.
19510Sstevel@tonic-gate * (The clock thread wakes up the pageout daemon to free up space.
19520Sstevel@tonic-gate * If the clock thread blocks behind us and we are sleeping waiting
19530Sstevel@tonic-gate * for space, then space may never become available.)
19540Sstevel@tonic-gate */
19550Sstevel@tonic-gate if (thingsize) {
19560Sstevel@tonic-gate ASSERT(thing == NULL);
19570Sstevel@tonic-gate thing = kmem_alloc(thingsize, KM_SLEEP);
19580Sstevel@tonic-gate }
19590Sstevel@tonic-gate
19600Sstevel@tonic-gate switch (cmd) {
19610Sstevel@tonic-gate case PIOCPSINFO:
19620Sstevel@tonic-gate case PIOCGETPR:
19630Sstevel@tonic-gate case PIOCUSAGE:
19640Sstevel@tonic-gate case PIOCLUSAGE:
19650Sstevel@tonic-gate zdisp = ZYES;
19660Sstevel@tonic-gate break;
19670Sstevel@tonic-gate case PIOCSXREG: /* set extra registers */
19680Sstevel@tonic-gate /*
19690Sstevel@tonic-gate * perform copyin before grabbing the process lock
19700Sstevel@tonic-gate */
19710Sstevel@tonic-gate if (thing) {
19720Sstevel@tonic-gate if (copyin(cmaddr, thing, thingsize)) {
19730Sstevel@tonic-gate kmem_free(thing, thingsize);
19740Sstevel@tonic-gate return (EFAULT);
19750Sstevel@tonic-gate }
19760Sstevel@tonic-gate }
19770Sstevel@tonic-gate /* fall through... */
19780Sstevel@tonic-gate default:
19790Sstevel@tonic-gate zdisp = ZNO;
19800Sstevel@tonic-gate break;
19810Sstevel@tonic-gate }
19820Sstevel@tonic-gate
19830Sstevel@tonic-gate if ((error = prlock(pnp, zdisp)) != 0) {
19840Sstevel@tonic-gate if (thing != NULL)
19850Sstevel@tonic-gate kmem_free(thing, thingsize);
19860Sstevel@tonic-gate if (xpnp)
19870Sstevel@tonic-gate prfreenode(xpnp);
19880Sstevel@tonic-gate return (error);
19890Sstevel@tonic-gate }
19900Sstevel@tonic-gate
19910Sstevel@tonic-gate pcp = pnp->pr_common;
19920Sstevel@tonic-gate p = pcp->prc_proc;
19930Sstevel@tonic-gate ASSERT(p != NULL);
19940Sstevel@tonic-gate
19950Sstevel@tonic-gate /*
19960Sstevel@tonic-gate * Choose a thread/lwp for the operation.
19970Sstevel@tonic-gate */
19980Sstevel@tonic-gate if (zdisp == ZNO && cmd != PIOCSTOP && cmd != PIOCWSTOP) {
19990Sstevel@tonic-gate if (pnp->pr_type == PR_LWPIDFILE && cmd != PIOCLSTATUS) {
20000Sstevel@tonic-gate t = pcp->prc_thread;
20010Sstevel@tonic-gate ASSERT(t != NULL);
20020Sstevel@tonic-gate } else {
20030Sstevel@tonic-gate t = prchoose(p); /* returns locked thread */
20040Sstevel@tonic-gate ASSERT(t != NULL);
20050Sstevel@tonic-gate thread_unlock(t);
20060Sstevel@tonic-gate }
20070Sstevel@tonic-gate lwp = ttolwp(t);
20080Sstevel@tonic-gate }
20090Sstevel@tonic-gate
20100Sstevel@tonic-gate error = 0;
20110Sstevel@tonic-gate switch (cmd) {
20120Sstevel@tonic-gate
20130Sstevel@tonic-gate case PIOCGETPR: /* read struct proc */
20140Sstevel@tonic-gate {
20150Sstevel@tonic-gate proc_t *prp = thing;
20160Sstevel@tonic-gate
20170Sstevel@tonic-gate *prp = *p;
20180Sstevel@tonic-gate prunlock(pnp);
20190Sstevel@tonic-gate if (copyout(prp, cmaddr, sizeof (proc_t)))
20200Sstevel@tonic-gate error = EFAULT;
20210Sstevel@tonic-gate kmem_free(prp, sizeof (proc_t));
20220Sstevel@tonic-gate thing = NULL;
20230Sstevel@tonic-gate break;
20240Sstevel@tonic-gate }
20250Sstevel@tonic-gate
20260Sstevel@tonic-gate case PIOCGETU: /* read u-area */
20270Sstevel@tonic-gate {
20280Sstevel@tonic-gate user_t *userp = thing;
20290Sstevel@tonic-gate
20300Sstevel@tonic-gate up = PTOU(p);
20310Sstevel@tonic-gate *userp = *up;
20320Sstevel@tonic-gate prunlock(pnp);
20330Sstevel@tonic-gate if (copyout(userp, cmaddr, sizeof (user_t)))
20340Sstevel@tonic-gate error = EFAULT;
20350Sstevel@tonic-gate kmem_free(userp, sizeof (user_t));
20360Sstevel@tonic-gate thing = NULL;
20370Sstevel@tonic-gate break;
20380Sstevel@tonic-gate }
20390Sstevel@tonic-gate
20400Sstevel@tonic-gate case PIOCOPENM: /* open mapped object for reading */
20410Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p) && cmaddr != NULL) {
20420Sstevel@tonic-gate prunlock(pnp);
20430Sstevel@tonic-gate error = EOVERFLOW;
20440Sstevel@tonic-gate break;
20450Sstevel@tonic-gate }
20460Sstevel@tonic-gate error = propenm(pnp, cmaddr,
20470Sstevel@tonic-gate (caddr_t)(uintptr_t)un32.va, rvalp, cr);
20480Sstevel@tonic-gate /* propenm() called prunlock(pnp) */
20490Sstevel@tonic-gate break;
20500Sstevel@tonic-gate
20510Sstevel@tonic-gate case PIOCSTOP: /* stop process or lwp from running */
20520Sstevel@tonic-gate case PIOCWSTOP: /* wait for process or lwp to stop */
20530Sstevel@tonic-gate /*
20540Sstevel@tonic-gate * Can't apply to a system process.
20550Sstevel@tonic-gate */
20560Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas) {
20570Sstevel@tonic-gate prunlock(pnp);
20580Sstevel@tonic-gate error = EBUSY;
20590Sstevel@tonic-gate break;
20600Sstevel@tonic-gate }
20610Sstevel@tonic-gate
20620Sstevel@tonic-gate if (cmd == PIOCSTOP)
20630Sstevel@tonic-gate pr_stop(pnp);
20640Sstevel@tonic-gate
20650Sstevel@tonic-gate /*
20660Sstevel@tonic-gate * If an lwp is waiting for itself or its process, don't wait.
20670Sstevel@tonic-gate * The lwp will never see the fact that itself is stopped.
20680Sstevel@tonic-gate */
20690Sstevel@tonic-gate if ((pnp->pr_type == PR_LWPIDFILE)?
20700Sstevel@tonic-gate (pcp->prc_thread == curthread) : (p == curproc)) {
20710Sstevel@tonic-gate if (cmd == PIOCWSTOP)
20720Sstevel@tonic-gate error = EBUSY;
20730Sstevel@tonic-gate prunlock(pnp);
20740Sstevel@tonic-gate break;
20750Sstevel@tonic-gate }
20760Sstevel@tonic-gate
20770Sstevel@tonic-gate if ((error = pr_wait_stop(pnp, (time_t)0)) != 0)
20780Sstevel@tonic-gate break; /* pr_wait_stop() unlocked the process */
20790Sstevel@tonic-gate
20800Sstevel@tonic-gate if (cmaddr == NULL)
20810Sstevel@tonic-gate prunlock(pnp);
20820Sstevel@tonic-gate else if (PROCESS_NOT_32BIT(p)) {
20830Sstevel@tonic-gate prunlock(pnp);
20840Sstevel@tonic-gate error = EOVERFLOW;
20850Sstevel@tonic-gate } else {
20860Sstevel@tonic-gate /*
20870Sstevel@tonic-gate * Return process/lwp status information.
20880Sstevel@tonic-gate */
20890Sstevel@tonic-gate t = pr_thread(pnp); /* returns locked thread */
20900Sstevel@tonic-gate thread_unlock(t);
2091789Sahrens oprgetstatus32(t, &un32.prstat, VTOZONE(vp));
20920Sstevel@tonic-gate prunlock(pnp);
20930Sstevel@tonic-gate if (copyout(&un32.prstat, cmaddr, sizeof (un32.prstat)))
20940Sstevel@tonic-gate error = EFAULT;
20950Sstevel@tonic-gate }
20960Sstevel@tonic-gate break;
20970Sstevel@tonic-gate
20980Sstevel@tonic-gate case PIOCRUN: /* make lwp or process runnable */
20990Sstevel@tonic-gate {
21000Sstevel@tonic-gate long flags = un32.prrun.pr_flags;
21010Sstevel@tonic-gate
21020Sstevel@tonic-gate /*
21030Sstevel@tonic-gate * Cannot set an lwp running is it is not stopped.
21040Sstevel@tonic-gate * Also, no lwp other than the /proc agent lwp can
21050Sstevel@tonic-gate * be set running so long as the /proc agent lwp exists.
21060Sstevel@tonic-gate */
21070Sstevel@tonic-gate if ((!ISTOPPED(t) && !VSTOPPED(t) &&
21080Sstevel@tonic-gate !(t->t_proc_flag & TP_PRSTOP)) ||
21090Sstevel@tonic-gate (p->p_agenttp != NULL &&
21100Sstevel@tonic-gate (t != p->p_agenttp || pnp->pr_type != PR_LWPIDFILE))) {
21110Sstevel@tonic-gate prunlock(pnp);
21120Sstevel@tonic-gate error = EBUSY;
21130Sstevel@tonic-gate break;
21140Sstevel@tonic-gate }
21150Sstevel@tonic-gate
21160Sstevel@tonic-gate if ((flags & PRSVADDR) && PROCESS_NOT_32BIT(p)) {
21170Sstevel@tonic-gate prunlock(pnp);
21180Sstevel@tonic-gate error = EOVERFLOW;
21190Sstevel@tonic-gate break;
21200Sstevel@tonic-gate }
21210Sstevel@tonic-gate
21220Sstevel@tonic-gate if (flags & (PRSHOLD|PRSTRACE|PRSFAULT|PRSVADDR)) {
21230Sstevel@tonic-gate un.prrun.pr_flags = (int)flags;
21240Sstevel@tonic-gate un.prrun.pr_trace = un32.prrun.pr_trace;
21250Sstevel@tonic-gate un.prrun.pr_sighold = un32.prrun.pr_sighold;
21260Sstevel@tonic-gate un.prrun.pr_fault = un32.prrun.pr_fault;
21270Sstevel@tonic-gate un.prrun.pr_vaddr =
21280Sstevel@tonic-gate (caddr_t)(uintptr_t)un32.prrun.pr_vaddr;
21290Sstevel@tonic-gate prsetrun(t, &un.prrun);
21300Sstevel@tonic-gate }
21310Sstevel@tonic-gate
21320Sstevel@tonic-gate error = pr_setrun(pnp, prmaprunflags(flags));
21330Sstevel@tonic-gate
21340Sstevel@tonic-gate prunlock(pnp);
21350Sstevel@tonic-gate break;
21360Sstevel@tonic-gate }
21370Sstevel@tonic-gate
21380Sstevel@tonic-gate case PIOCLWPIDS: /* get array of lwp identifiers */
21390Sstevel@tonic-gate {
21400Sstevel@tonic-gate int nlwp;
21410Sstevel@tonic-gate int Nlwp;
21420Sstevel@tonic-gate id_t *idp;
21430Sstevel@tonic-gate id_t *Bidp;
21440Sstevel@tonic-gate
21450Sstevel@tonic-gate Nlwp = nlwp = p->p_lwpcnt;
21460Sstevel@tonic-gate
21470Sstevel@tonic-gate if (thing && thingsize != (Nlwp+1) * sizeof (id_t)) {
21480Sstevel@tonic-gate kmem_free(thing, thingsize);
21490Sstevel@tonic-gate thing = NULL;
21500Sstevel@tonic-gate }
21510Sstevel@tonic-gate if (thing == NULL) {
21520Sstevel@tonic-gate thingsize = (Nlwp+1) * sizeof (id_t);
21530Sstevel@tonic-gate thing = kmem_alloc(thingsize, KM_NOSLEEP);
21540Sstevel@tonic-gate }
21550Sstevel@tonic-gate if (thing == NULL) {
21560Sstevel@tonic-gate prunlock(pnp);
21570Sstevel@tonic-gate goto startover;
21580Sstevel@tonic-gate }
21590Sstevel@tonic-gate
21600Sstevel@tonic-gate idp = thing;
21610Sstevel@tonic-gate thing = NULL;
21620Sstevel@tonic-gate Bidp = idp;
21630Sstevel@tonic-gate if ((t = p->p_tlist) != NULL) {
21640Sstevel@tonic-gate do {
21650Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
21660Sstevel@tonic-gate ASSERT(nlwp > 0);
21670Sstevel@tonic-gate --nlwp;
21680Sstevel@tonic-gate *idp++ = t->t_tid;
21690Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
21700Sstevel@tonic-gate }
21710Sstevel@tonic-gate *idp = 0;
21720Sstevel@tonic-gate ASSERT(nlwp == 0);
21730Sstevel@tonic-gate prunlock(pnp);
21740Sstevel@tonic-gate if (copyout(Bidp, cmaddr, (Nlwp+1) * sizeof (id_t)))
21750Sstevel@tonic-gate error = EFAULT;
21760Sstevel@tonic-gate kmem_free(Bidp, (Nlwp+1) * sizeof (id_t));
21770Sstevel@tonic-gate break;
21780Sstevel@tonic-gate }
21790Sstevel@tonic-gate
21800Sstevel@tonic-gate case PIOCOPENLWP: /* return /proc lwp file descriptor */
21810Sstevel@tonic-gate {
21820Sstevel@tonic-gate vnode_t *xvp;
21830Sstevel@tonic-gate int n;
21840Sstevel@tonic-gate
21850Sstevel@tonic-gate prunlock(pnp);
21860Sstevel@tonic-gate if ((xvp = prlwpnode(pnp, un32.lwpid)) == NULL)
21870Sstevel@tonic-gate error = ENOENT;
21880Sstevel@tonic-gate else if (error = fassign(&xvp, flag & (FREAD|FWRITE), &n)) {
21890Sstevel@tonic-gate VN_RELE(xvp);
21900Sstevel@tonic-gate } else
21910Sstevel@tonic-gate *rvalp = n;
21920Sstevel@tonic-gate break;
21930Sstevel@tonic-gate }
21940Sstevel@tonic-gate
21950Sstevel@tonic-gate case PIOCOPENPD: /* return /proc page data file descriptor */
21960Sstevel@tonic-gate {
21970Sstevel@tonic-gate vnode_t *xvp = PTOV(xpnp);
21980Sstevel@tonic-gate vnode_t *dp = pnp->pr_parent;
21990Sstevel@tonic-gate int n;
22000Sstevel@tonic-gate
22010Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
22020Sstevel@tonic-gate prunlock(pnp);
22030Sstevel@tonic-gate prfreenode(xpnp);
22040Sstevel@tonic-gate xpnp = NULL;
22050Sstevel@tonic-gate error = EOVERFLOW;
22060Sstevel@tonic-gate break;
22070Sstevel@tonic-gate }
22080Sstevel@tonic-gate
22090Sstevel@tonic-gate if (pnp->pr_type == PR_LWPIDFILE) {
22100Sstevel@tonic-gate dp = VTOP(dp)->pr_parent;
22110Sstevel@tonic-gate dp = VTOP(dp)->pr_parent;
22120Sstevel@tonic-gate }
22130Sstevel@tonic-gate ASSERT(VTOP(dp)->pr_type == PR_PIDDIR);
22140Sstevel@tonic-gate
22150Sstevel@tonic-gate VN_HOLD(dp);
22160Sstevel@tonic-gate pcp = pnp->pr_pcommon;
22170Sstevel@tonic-gate xpnp->pr_ino = ptoi(pcp->prc_pid);
22180Sstevel@tonic-gate xpnp->pr_common = pcp;
22190Sstevel@tonic-gate xpnp->pr_pcommon = pcp;
22200Sstevel@tonic-gate xpnp->pr_parent = dp;
22210Sstevel@tonic-gate
22220Sstevel@tonic-gate xpnp->pr_next = p->p_plist;
22230Sstevel@tonic-gate p->p_plist = xvp;
22240Sstevel@tonic-gate
22250Sstevel@tonic-gate prunlock(pnp);
22260Sstevel@tonic-gate if (error = fassign(&xvp, FREAD, &n)) {
22270Sstevel@tonic-gate VN_RELE(xvp);
22280Sstevel@tonic-gate } else
22290Sstevel@tonic-gate *rvalp = n;
22300Sstevel@tonic-gate
22310Sstevel@tonic-gate xpnp = NULL;
22320Sstevel@tonic-gate break;
22330Sstevel@tonic-gate }
22340Sstevel@tonic-gate
22350Sstevel@tonic-gate case PIOCGTRACE: /* get signal trace mask */
22360Sstevel@tonic-gate prassignset(&un32.smask, &p->p_sigmask);
22370Sstevel@tonic-gate prunlock(pnp);
22380Sstevel@tonic-gate if (copyout(&un32.smask, cmaddr, sizeof (un32.smask)))
22390Sstevel@tonic-gate error = EFAULT;
22400Sstevel@tonic-gate break;
22410Sstevel@tonic-gate
22420Sstevel@tonic-gate case PIOCSTRACE: /* set signal trace mask */
22430Sstevel@tonic-gate prdelset(&un32.smask, SIGKILL);
22440Sstevel@tonic-gate prassignset(&p->p_sigmask, &un32.smask);
22450Sstevel@tonic-gate if (!sigisempty(&p->p_sigmask))
22460Sstevel@tonic-gate p->p_proc_flag |= P_PR_TRACE;
22470Sstevel@tonic-gate else if (prisempty(&p->p_fltmask)) {
22480Sstevel@tonic-gate up = PTOU(p);
22490Sstevel@tonic-gate if (up->u_systrap == 0)
22500Sstevel@tonic-gate p->p_proc_flag &= ~P_PR_TRACE;
22510Sstevel@tonic-gate }
22520Sstevel@tonic-gate prunlock(pnp);
22530Sstevel@tonic-gate break;
22540Sstevel@tonic-gate
22550Sstevel@tonic-gate case PIOCSSIG: /* set current signal */
22560Sstevel@tonic-gate if (un32.info.si_signo != 0 && PROCESS_NOT_32BIT(p)) {
22570Sstevel@tonic-gate prunlock(pnp);
22580Sstevel@tonic-gate error = EOVERFLOW;
22590Sstevel@tonic-gate } else {
22600Sstevel@tonic-gate bzero(&un.info, sizeof (un.info));
22610Sstevel@tonic-gate siginfo_32tok(&un32.info, (k_siginfo_t *)&un.info);
22620Sstevel@tonic-gate error = pr_setsig(pnp, &un.info);
22630Sstevel@tonic-gate prunlock(pnp);
22640Sstevel@tonic-gate if (un32.info.si_signo == SIGKILL && error == 0)
22650Sstevel@tonic-gate pr_wait_die(pnp);
22660Sstevel@tonic-gate }
22670Sstevel@tonic-gate break;
22680Sstevel@tonic-gate
22690Sstevel@tonic-gate case PIOCKILL: /* send signal */
22700Sstevel@tonic-gate error = pr_kill(pnp, un32.signo, cr);
22710Sstevel@tonic-gate prunlock(pnp);
22720Sstevel@tonic-gate if (un32.signo == SIGKILL && error == 0)
22730Sstevel@tonic-gate pr_wait_die(pnp);
22740Sstevel@tonic-gate break;
22750Sstevel@tonic-gate
22760Sstevel@tonic-gate case PIOCUNKILL: /* delete a signal */
22770Sstevel@tonic-gate error = pr_unkill(pnp, un32.signo);
22780Sstevel@tonic-gate prunlock(pnp);
22790Sstevel@tonic-gate break;
22800Sstevel@tonic-gate
22810Sstevel@tonic-gate case PIOCNICE: /* set nice priority */
22820Sstevel@tonic-gate error = pr_nice(p, un32.nice, cr);
22830Sstevel@tonic-gate prunlock(pnp);
22840Sstevel@tonic-gate break;
22850Sstevel@tonic-gate
22860Sstevel@tonic-gate case PIOCGENTRY: /* get syscall entry bit mask */
22870Sstevel@tonic-gate case PIOCGEXIT: /* get syscall exit bit mask */
22880Sstevel@tonic-gate up = PTOU(p);
22890Sstevel@tonic-gate if (cmd == PIOCGENTRY) {
22900Sstevel@tonic-gate prassignset(&un32.prmask, &up->u_entrymask);
22910Sstevel@tonic-gate } else {
22920Sstevel@tonic-gate prassignset(&un32.prmask, &up->u_exitmask);
22930Sstevel@tonic-gate }
22940Sstevel@tonic-gate prunlock(pnp);
22950Sstevel@tonic-gate if (copyout(&un32.prmask, cmaddr, sizeof (un32.prmask)))
22960Sstevel@tonic-gate error = EFAULT;
22970Sstevel@tonic-gate break;
22980Sstevel@tonic-gate
22990Sstevel@tonic-gate case PIOCSENTRY: /* set syscall entry bit mask */
23000Sstevel@tonic-gate case PIOCSEXIT: /* set syscall exit bit mask */
23010Sstevel@tonic-gate pr_setentryexit(p, &un32.prmask, cmd == PIOCSENTRY);
23020Sstevel@tonic-gate prunlock(pnp);
23030Sstevel@tonic-gate break;
23040Sstevel@tonic-gate
23050Sstevel@tonic-gate case PIOCSRLC: /* obsolete: set running on last /proc close */
23060Sstevel@tonic-gate error = pr_set(p, prmapsetflags(PR_RLC));
23070Sstevel@tonic-gate prunlock(pnp);
23080Sstevel@tonic-gate break;
23090Sstevel@tonic-gate
23100Sstevel@tonic-gate case PIOCRRLC: /* obsolete: reset run-on-last-close flag */
23110Sstevel@tonic-gate error = pr_unset(p, prmapsetflags(PR_RLC));
23120Sstevel@tonic-gate prunlock(pnp);
23130Sstevel@tonic-gate break;
23140Sstevel@tonic-gate
23150Sstevel@tonic-gate case PIOCSFORK: /* obsolete: set inherit-on-fork flag */
23160Sstevel@tonic-gate error = pr_set(p, prmapsetflags(PR_FORK));
23170Sstevel@tonic-gate prunlock(pnp);
23180Sstevel@tonic-gate break;
23190Sstevel@tonic-gate
23200Sstevel@tonic-gate case PIOCRFORK: /* obsolete: reset inherit-on-fork flag */
23210Sstevel@tonic-gate error = pr_unset(p, prmapsetflags(PR_FORK));
23220Sstevel@tonic-gate prunlock(pnp);
23230Sstevel@tonic-gate break;
23240Sstevel@tonic-gate
23250Sstevel@tonic-gate case PIOCSET: /* set process flags */
23260Sstevel@tonic-gate error = pr_set(p, prmapsetflags((long)un32.flags));
23270Sstevel@tonic-gate prunlock(pnp);
23280Sstevel@tonic-gate break;
23290Sstevel@tonic-gate
23300Sstevel@tonic-gate case PIOCRESET: /* reset process flags */
23310Sstevel@tonic-gate error = pr_unset(p, prmapsetflags((long)un32.flags));
23320Sstevel@tonic-gate prunlock(pnp);
23330Sstevel@tonic-gate break;
23340Sstevel@tonic-gate
23350Sstevel@tonic-gate case PIOCGREG: /* get general registers */
23360Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p))
23370Sstevel@tonic-gate error = EOVERFLOW;
23380Sstevel@tonic-gate else if (t->t_state != TS_STOPPED && !VSTOPPED(t))
23390Sstevel@tonic-gate bzero(un32.regs, sizeof (un32.regs));
23400Sstevel@tonic-gate else {
23410Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
23420Sstevel@tonic-gate mutex_exit(&p->p_lock);
23430Sstevel@tonic-gate prgetprregs32(lwp, un32.regs);
23440Sstevel@tonic-gate mutex_enter(&p->p_lock);
23450Sstevel@tonic-gate }
23460Sstevel@tonic-gate prunlock(pnp);
23470Sstevel@tonic-gate if (error == 0 &&
23480Sstevel@tonic-gate copyout(un32.regs, cmaddr, sizeof (un32.regs)))
23490Sstevel@tonic-gate error = EFAULT;
23500Sstevel@tonic-gate break;
23510Sstevel@tonic-gate
23520Sstevel@tonic-gate case PIOCSREG: /* set general registers */
23530Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p))
23540Sstevel@tonic-gate error = EOVERFLOW;
23550Sstevel@tonic-gate else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
23560Sstevel@tonic-gate error = EBUSY;
23570Sstevel@tonic-gate else {
23580Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
23590Sstevel@tonic-gate mutex_exit(&p->p_lock);
23600Sstevel@tonic-gate prgregset_32ton(lwp, un32.regs, un.regs);
23610Sstevel@tonic-gate prsetprregs(lwp, un.regs, 0);
23620Sstevel@tonic-gate mutex_enter(&p->p_lock);
23630Sstevel@tonic-gate }
23640Sstevel@tonic-gate prunlock(pnp);
23650Sstevel@tonic-gate break;
23660Sstevel@tonic-gate
23670Sstevel@tonic-gate case PIOCGFPREG: /* get floating-point registers */
23680Sstevel@tonic-gate if (!prhasfp())
23690Sstevel@tonic-gate error = EINVAL; /* No FP support */
23700Sstevel@tonic-gate else if (PROCESS_NOT_32BIT(p))
23710Sstevel@tonic-gate error = EOVERFLOW;
23720Sstevel@tonic-gate else if (t->t_state != TS_STOPPED && !VSTOPPED(t))
23730Sstevel@tonic-gate bzero(&un32.fpregs, sizeof (un32.fpregs));
23740Sstevel@tonic-gate else {
23750Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
23760Sstevel@tonic-gate mutex_exit(&p->p_lock);
23770Sstevel@tonic-gate prgetprfpregs32(lwp, &un32.fpregs);
23780Sstevel@tonic-gate mutex_enter(&p->p_lock);
23790Sstevel@tonic-gate }
23800Sstevel@tonic-gate prunlock(pnp);
23810Sstevel@tonic-gate if (error == 0 &&
23820Sstevel@tonic-gate copyout(&un32.fpregs, cmaddr, sizeof (un32.fpregs)))
23830Sstevel@tonic-gate error = EFAULT;
23840Sstevel@tonic-gate break;
23850Sstevel@tonic-gate
23860Sstevel@tonic-gate case PIOCSFPREG: /* set floating-point registers */
23870Sstevel@tonic-gate if (!prhasfp())
23880Sstevel@tonic-gate error = EINVAL; /* No FP support */
23890Sstevel@tonic-gate else if (PROCESS_NOT_32BIT(p))
23900Sstevel@tonic-gate error = EOVERFLOW;
23910Sstevel@tonic-gate else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
23920Sstevel@tonic-gate error = EBUSY;
23930Sstevel@tonic-gate else {
23940Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
23950Sstevel@tonic-gate mutex_exit(&p->p_lock);
23960Sstevel@tonic-gate prsetprfpregs32(lwp, &un32.fpregs);
23970Sstevel@tonic-gate mutex_enter(&p->p_lock);
23980Sstevel@tonic-gate }
23990Sstevel@tonic-gate prunlock(pnp);
24000Sstevel@tonic-gate break;
24010Sstevel@tonic-gate
24020Sstevel@tonic-gate case PIOCGXREGSIZE: /* get the size of the extra registers */
24030Sstevel@tonic-gate {
24040Sstevel@tonic-gate int xregsize;
24050Sstevel@tonic-gate
24060Sstevel@tonic-gate if (prhasx(p)) {
24070Sstevel@tonic-gate xregsize = prgetprxregsize(p);
24080Sstevel@tonic-gate prunlock(pnp);
24090Sstevel@tonic-gate if (copyout(&xregsize, cmaddr, sizeof (xregsize)))
24100Sstevel@tonic-gate error = EFAULT;
24110Sstevel@tonic-gate } else {
24120Sstevel@tonic-gate prunlock(pnp);
24130Sstevel@tonic-gate error = EINVAL; /* No extra register support */
24140Sstevel@tonic-gate }
24150Sstevel@tonic-gate break;
24160Sstevel@tonic-gate }
24170Sstevel@tonic-gate
24180Sstevel@tonic-gate case PIOCGXREG: /* get extra registers */
24190Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p))
24200Sstevel@tonic-gate error = EOVERFLOW;
24210Sstevel@tonic-gate else if (!prhasx(p))
24220Sstevel@tonic-gate error = EINVAL; /* No extra register support */
24230Sstevel@tonic-gate else {
24240Sstevel@tonic-gate bzero(thing, thingsize);
24250Sstevel@tonic-gate if (t->t_state == TS_STOPPED || VSTOPPED(t)) {
24260Sstevel@tonic-gate /* drop p_lock to touch the stack */
24270Sstevel@tonic-gate mutex_exit(&p->p_lock);
24280Sstevel@tonic-gate prgetprxregs(lwp, thing);
24290Sstevel@tonic-gate mutex_enter(&p->p_lock);
24300Sstevel@tonic-gate }
24310Sstevel@tonic-gate }
24320Sstevel@tonic-gate prunlock(pnp);
24330Sstevel@tonic-gate if (error == 0 &&
24340Sstevel@tonic-gate copyout(thing, cmaddr, thingsize))
24350Sstevel@tonic-gate error = EFAULT;
24360Sstevel@tonic-gate if (thing) {
24370Sstevel@tonic-gate kmem_free(thing, thingsize);
24380Sstevel@tonic-gate thing = NULL;
24390Sstevel@tonic-gate }
24400Sstevel@tonic-gate break;
24410Sstevel@tonic-gate
24420Sstevel@tonic-gate case PIOCSXREG: /* set extra registers */
24430Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p))
24440Sstevel@tonic-gate error = EOVERFLOW;
24450Sstevel@tonic-gate else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
24460Sstevel@tonic-gate error = EBUSY;
24470Sstevel@tonic-gate else if (!prhasx(p))
24480Sstevel@tonic-gate error = EINVAL; /* No extra register support */
24490Sstevel@tonic-gate else if (thing) {
24500Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
24510Sstevel@tonic-gate mutex_exit(&p->p_lock);
24520Sstevel@tonic-gate prsetprxregs(lwp, thing);
24530Sstevel@tonic-gate mutex_enter(&p->p_lock);
24540Sstevel@tonic-gate }
24550Sstevel@tonic-gate prunlock(pnp);
24560Sstevel@tonic-gate if (thing) {
24570Sstevel@tonic-gate kmem_free(thing, thingsize);
24580Sstevel@tonic-gate thing = NULL;
24590Sstevel@tonic-gate }
24600Sstevel@tonic-gate break;
24610Sstevel@tonic-gate
24620Sstevel@tonic-gate case PIOCSTATUS: /* get process/lwp status */
24630Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
24640Sstevel@tonic-gate prunlock(pnp);
24650Sstevel@tonic-gate error = EOVERFLOW;
24660Sstevel@tonic-gate break;
24670Sstevel@tonic-gate }
2468789Sahrens oprgetstatus32(t, &un32.prstat, VTOZONE(vp));
24690Sstevel@tonic-gate prunlock(pnp);
24700Sstevel@tonic-gate if (copyout(&un32.prstat, cmaddr, sizeof (un32.prstat)))
24710Sstevel@tonic-gate error = EFAULT;
24720Sstevel@tonic-gate break;
24730Sstevel@tonic-gate
24740Sstevel@tonic-gate case PIOCLSTATUS: /* get status for process & all lwps */
24750Sstevel@tonic-gate {
24760Sstevel@tonic-gate int Nlwp;
24770Sstevel@tonic-gate int nlwp;
24780Sstevel@tonic-gate prstatus32_t *Bprsp;
24790Sstevel@tonic-gate prstatus32_t *prsp;
24800Sstevel@tonic-gate
24810Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
24820Sstevel@tonic-gate prunlock(pnp);
24830Sstevel@tonic-gate if (thing) {
24840Sstevel@tonic-gate kmem_free(thing, thingsize);
24850Sstevel@tonic-gate thing = NULL;
24860Sstevel@tonic-gate }
24870Sstevel@tonic-gate error = EOVERFLOW;
24880Sstevel@tonic-gate break;
24890Sstevel@tonic-gate }
24900Sstevel@tonic-gate
24910Sstevel@tonic-gate nlwp = Nlwp = p->p_lwpcnt;
24920Sstevel@tonic-gate
24930Sstevel@tonic-gate if (thing && thingsize != (Nlwp+1) * sizeof (prstatus32_t)) {
24940Sstevel@tonic-gate kmem_free(thing, thingsize);
24950Sstevel@tonic-gate thing = NULL;
24960Sstevel@tonic-gate }
24970Sstevel@tonic-gate if (thing == NULL) {
24980Sstevel@tonic-gate thingsize = (Nlwp+1) * sizeof (prstatus32_t);
24990Sstevel@tonic-gate thing = kmem_alloc(thingsize, KM_NOSLEEP);
25000Sstevel@tonic-gate }
25010Sstevel@tonic-gate if (thing == NULL) {
25020Sstevel@tonic-gate prunlock(pnp);
25030Sstevel@tonic-gate goto startover;
25040Sstevel@tonic-gate }
25050Sstevel@tonic-gate
25060Sstevel@tonic-gate Bprsp = (prstatus32_t *)thing;
25070Sstevel@tonic-gate thing = NULL;
25080Sstevel@tonic-gate prsp = Bprsp;
2509789Sahrens oprgetstatus32(t, prsp, VTOZONE(vp));
25100Sstevel@tonic-gate t = p->p_tlist;
25110Sstevel@tonic-gate do {
25120Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
25130Sstevel@tonic-gate ASSERT(nlwp > 0);
25140Sstevel@tonic-gate --nlwp;
2515789Sahrens oprgetstatus32(t, ++prsp, VTOZONE(vp));
25160Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
25170Sstevel@tonic-gate ASSERT(nlwp == 0);
25180Sstevel@tonic-gate prunlock(pnp);
25190Sstevel@tonic-gate if (copyout(Bprsp, cmaddr, (Nlwp+1) * sizeof (prstatus32_t)))
25200Sstevel@tonic-gate error = EFAULT;
25210Sstevel@tonic-gate
25220Sstevel@tonic-gate kmem_free(Bprsp, (Nlwp + 1) * sizeof (prstatus32_t));
25230Sstevel@tonic-gate break;
25240Sstevel@tonic-gate }
25250Sstevel@tonic-gate
25260Sstevel@tonic-gate case PIOCPSINFO: /* get ps(1) information */
25270Sstevel@tonic-gate {
25280Sstevel@tonic-gate prpsinfo32_t *psp = &un32.prps;
25290Sstevel@tonic-gate
25300Sstevel@tonic-gate oprgetpsinfo32(p, psp,
25310Sstevel@tonic-gate (pnp->pr_type == PR_LWPIDFILE)? pcp->prc_thread : NULL);
25320Sstevel@tonic-gate
25330Sstevel@tonic-gate prunlock(pnp);
25340Sstevel@tonic-gate if (copyout(&un32.prps, cmaddr, sizeof (un32.prps)))
25350Sstevel@tonic-gate error = EFAULT;
25360Sstevel@tonic-gate break;
25370Sstevel@tonic-gate }
25380Sstevel@tonic-gate
25390Sstevel@tonic-gate case PIOCMAXSIG: /* get maximum signal number */
25400Sstevel@tonic-gate {
2541*11940SRoger.Faulkner@Sun.COM int n = nsig-1;
25420Sstevel@tonic-gate
25430Sstevel@tonic-gate prunlock(pnp);
25440Sstevel@tonic-gate if (copyout(&n, cmaddr, sizeof (int)))
25450Sstevel@tonic-gate error = EFAULT;
25460Sstevel@tonic-gate break;
25470Sstevel@tonic-gate }
25480Sstevel@tonic-gate
25490Sstevel@tonic-gate case PIOCACTION: /* get signal action structures */
25500Sstevel@tonic-gate {
25510Sstevel@tonic-gate uint_t sig;
25520Sstevel@tonic-gate struct sigaction32 *sap = thing;
25530Sstevel@tonic-gate
25540Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p))
25550Sstevel@tonic-gate error = EOVERFLOW;
25560Sstevel@tonic-gate else {
25570Sstevel@tonic-gate up = PTOU(p);
2558*11940SRoger.Faulkner@Sun.COM for (sig = 1; sig < nsig; sig++)
25590Sstevel@tonic-gate prgetaction32(p, up, sig, &sap[sig-1]);
25600Sstevel@tonic-gate }
25610Sstevel@tonic-gate prunlock(pnp);
25620Sstevel@tonic-gate if (error == 0 &&
2563*11940SRoger.Faulkner@Sun.COM copyout(sap, cmaddr, (nsig-1)*sizeof (struct sigaction32)))
25640Sstevel@tonic-gate error = EFAULT;
2565*11940SRoger.Faulkner@Sun.COM kmem_free(sap, (nsig-1)*sizeof (struct sigaction32));
25660Sstevel@tonic-gate thing = NULL;
25670Sstevel@tonic-gate break;
25680Sstevel@tonic-gate }
25690Sstevel@tonic-gate
25700Sstevel@tonic-gate case PIOCGHOLD: /* get signal-hold mask */
25710Sstevel@tonic-gate schedctl_finish_sigblock(t);
25720Sstevel@tonic-gate sigktou(&t->t_hold, &un32.holdmask);
25730Sstevel@tonic-gate prunlock(pnp);
25740Sstevel@tonic-gate if (copyout(&un32.holdmask, cmaddr, sizeof (un32.holdmask)))
25750Sstevel@tonic-gate error = EFAULT;
25760Sstevel@tonic-gate break;
25770Sstevel@tonic-gate
25780Sstevel@tonic-gate case PIOCSHOLD: /* set signal-hold mask */
25790Sstevel@tonic-gate pr_sethold(pnp, &un32.holdmask);
25800Sstevel@tonic-gate prunlock(pnp);
25810Sstevel@tonic-gate break;
25820Sstevel@tonic-gate
25830Sstevel@tonic-gate case PIOCNMAP: /* get number of memory mappings */
25840Sstevel@tonic-gate {
25850Sstevel@tonic-gate int n;
25860Sstevel@tonic-gate struct as *as = p->p_as;
25870Sstevel@tonic-gate
25880Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas)
25890Sstevel@tonic-gate n = 0;
25900Sstevel@tonic-gate else {
25910Sstevel@tonic-gate mutex_exit(&p->p_lock);
25920Sstevel@tonic-gate AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
25930Sstevel@tonic-gate n = prnsegs(as, 0);
25940Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
25950Sstevel@tonic-gate mutex_enter(&p->p_lock);
25960Sstevel@tonic-gate }
25970Sstevel@tonic-gate prunlock(pnp);
25980Sstevel@tonic-gate if (copyout(&n, cmaddr, sizeof (int)))
25990Sstevel@tonic-gate error = EFAULT;
26000Sstevel@tonic-gate break;
26010Sstevel@tonic-gate }
26020Sstevel@tonic-gate
26030Sstevel@tonic-gate case PIOCMAP: /* get memory map information */
26040Sstevel@tonic-gate {
26052789Sfrankho list_t iolhead;
26060Sstevel@tonic-gate struct as *as = p->p_as;
26072789Sfrankho
26082789Sfrankho if ((p->p_flag & SSYS) || as == &kas) {
26092789Sfrankho error = 0;
26102789Sfrankho prunlock(pnp);
26110Sstevel@tonic-gate } else if (PROCESS_NOT_32BIT(p)) {
26120Sstevel@tonic-gate error = EOVERFLOW;
26130Sstevel@tonic-gate prunlock(pnp);
26140Sstevel@tonic-gate } else {
26150Sstevel@tonic-gate mutex_exit(&p->p_lock);
26160Sstevel@tonic-gate AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
26172789Sfrankho error = oprgetmap32(p, &iolhead);
26180Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
26190Sstevel@tonic-gate mutex_enter(&p->p_lock);
26202789Sfrankho prunlock(pnp);
26212789Sfrankho
26222789Sfrankho error = pr_iol_copyout_and_free(&iolhead,
26232789Sfrankho &cmaddr, error);
26240Sstevel@tonic-gate }
26252789Sfrankho /*
26262789Sfrankho * The procfs PIOCMAP ioctl returns an all-zero buffer
26272789Sfrankho * to indicate the end of the prmap[] array.
26282789Sfrankho * Append it to whatever has already been copied out.
26292789Sfrankho */
26302789Sfrankho bzero(&un32.prmap, sizeof (un32.prmap));
26312789Sfrankho if (!error &&
26322789Sfrankho copyout(&un32.prmap, cmaddr, sizeof (un32.prmap)))
26332789Sfrankho error = EFAULT;
26340Sstevel@tonic-gate break;
26350Sstevel@tonic-gate }
26360Sstevel@tonic-gate
26370Sstevel@tonic-gate case PIOCGFAULT: /* get mask of traced faults */
26380Sstevel@tonic-gate prassignset(&un32.fltmask, &p->p_fltmask);
26390Sstevel@tonic-gate prunlock(pnp);
26400Sstevel@tonic-gate if (copyout(&un32.fltmask, cmaddr, sizeof (un32.fltmask)))
26410Sstevel@tonic-gate error = EFAULT;
26420Sstevel@tonic-gate break;
26430Sstevel@tonic-gate
26440Sstevel@tonic-gate case PIOCSFAULT: /* set mask of traced faults */
26450Sstevel@tonic-gate pr_setfault(p, &un32.fltmask);
26460Sstevel@tonic-gate prunlock(pnp);
26470Sstevel@tonic-gate break;
26480Sstevel@tonic-gate
26490Sstevel@tonic-gate case PIOCCFAULT: /* clear current fault */
26500Sstevel@tonic-gate lwp->lwp_curflt = 0;
26510Sstevel@tonic-gate prunlock(pnp);
26520Sstevel@tonic-gate break;
26530Sstevel@tonic-gate
26540Sstevel@tonic-gate case PIOCCRED: /* get process credentials */
26550Sstevel@tonic-gate {
26560Sstevel@tonic-gate cred_t *cp;
26570Sstevel@tonic-gate
26580Sstevel@tonic-gate mutex_enter(&p->p_crlock);
26590Sstevel@tonic-gate cp = p->p_cred;
26600Sstevel@tonic-gate un32.prcred.pr_euid = crgetuid(cp);
26610Sstevel@tonic-gate un32.prcred.pr_ruid = crgetruid(cp);
26620Sstevel@tonic-gate un32.prcred.pr_suid = crgetsuid(cp);
26630Sstevel@tonic-gate un32.prcred.pr_egid = crgetgid(cp);
26640Sstevel@tonic-gate un32.prcred.pr_rgid = crgetrgid(cp);
26650Sstevel@tonic-gate un32.prcred.pr_sgid = crgetsgid(cp);
26660Sstevel@tonic-gate un32.prcred.pr_ngroups = crgetngroups(cp);
26670Sstevel@tonic-gate mutex_exit(&p->p_crlock);
26680Sstevel@tonic-gate
26690Sstevel@tonic-gate prunlock(pnp);
26700Sstevel@tonic-gate if (copyout(&un32.prcred, cmaddr, sizeof (un32.prcred)))
26710Sstevel@tonic-gate error = EFAULT;
26720Sstevel@tonic-gate break;
26730Sstevel@tonic-gate }
26740Sstevel@tonic-gate
26750Sstevel@tonic-gate case PIOCGROUPS: /* get supplementary groups */
26760Sstevel@tonic-gate {
26770Sstevel@tonic-gate cred_t *cp;
26780Sstevel@tonic-gate
26790Sstevel@tonic-gate mutex_enter(&p->p_crlock);
26800Sstevel@tonic-gate cp = p->p_cred;
26810Sstevel@tonic-gate crhold(cp);
26820Sstevel@tonic-gate mutex_exit(&p->p_crlock);
26830Sstevel@tonic-gate
26840Sstevel@tonic-gate prunlock(pnp);
26850Sstevel@tonic-gate if (copyout(crgetgroups(cp), cmaddr,
26860Sstevel@tonic-gate MAX(crgetngroups(cp), 1) * sizeof (gid_t)))
26870Sstevel@tonic-gate error = EFAULT;
26880Sstevel@tonic-gate crfree(cp);
26890Sstevel@tonic-gate break;
26900Sstevel@tonic-gate }
26910Sstevel@tonic-gate
26920Sstevel@tonic-gate case PIOCUSAGE: /* get usage info */
26930Sstevel@tonic-gate {
26940Sstevel@tonic-gate /*
26950Sstevel@tonic-gate * For an lwp file descriptor, return just the lwp usage.
26960Sstevel@tonic-gate * For a process file descriptor, return total usage,
26970Sstevel@tonic-gate * all current lwps plus all defunct lwps.
26980Sstevel@tonic-gate */
26990Sstevel@tonic-gate prhusage_t *pup = &un32.prhusage;
27000Sstevel@tonic-gate prusage32_t *upup;
27010Sstevel@tonic-gate
27020Sstevel@tonic-gate bzero(pup, sizeof (*pup));
27030Sstevel@tonic-gate pup->pr_tstamp = gethrtime();
27040Sstevel@tonic-gate
27050Sstevel@tonic-gate if (pnp->pr_type == PR_LWPIDFILE) {
27060Sstevel@tonic-gate t = pcp->prc_thread;
27070Sstevel@tonic-gate if (t != NULL)
27080Sstevel@tonic-gate prgetusage(t, pup);
27090Sstevel@tonic-gate else
27100Sstevel@tonic-gate error = ENOENT;
27110Sstevel@tonic-gate } else {
27120Sstevel@tonic-gate pup->pr_count = p->p_defunct;
27130Sstevel@tonic-gate pup->pr_create = p->p_mstart;
27140Sstevel@tonic-gate pup->pr_term = p->p_mterm;
27150Sstevel@tonic-gate
27160Sstevel@tonic-gate pup->pr_rtime = p->p_mlreal;
27170Sstevel@tonic-gate pup->pr_utime = p->p_acct[LMS_USER];
27180Sstevel@tonic-gate pup->pr_stime = p->p_acct[LMS_SYSTEM];
27190Sstevel@tonic-gate pup->pr_ttime = p->p_acct[LMS_TRAP];
27200Sstevel@tonic-gate pup->pr_tftime = p->p_acct[LMS_TFAULT];
27210Sstevel@tonic-gate pup->pr_dftime = p->p_acct[LMS_DFAULT];
27220Sstevel@tonic-gate pup->pr_kftime = p->p_acct[LMS_KFAULT];
27230Sstevel@tonic-gate pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
27240Sstevel@tonic-gate pup->pr_slptime = p->p_acct[LMS_SLEEP];
27250Sstevel@tonic-gate pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
27260Sstevel@tonic-gate pup->pr_stoptime = p->p_acct[LMS_STOPPED];
27270Sstevel@tonic-gate
27280Sstevel@tonic-gate pup->pr_minf = p->p_ru.minflt;
27290Sstevel@tonic-gate pup->pr_majf = p->p_ru.majflt;
27300Sstevel@tonic-gate pup->pr_nswap = p->p_ru.nswap;
27310Sstevel@tonic-gate pup->pr_inblk = p->p_ru.inblock;
27320Sstevel@tonic-gate pup->pr_oublk = p->p_ru.oublock;
27330Sstevel@tonic-gate pup->pr_msnd = p->p_ru.msgsnd;
27340Sstevel@tonic-gate pup->pr_mrcv = p->p_ru.msgrcv;
27350Sstevel@tonic-gate pup->pr_sigs = p->p_ru.nsignals;
27360Sstevel@tonic-gate pup->pr_vctx = p->p_ru.nvcsw;
27370Sstevel@tonic-gate pup->pr_ictx = p->p_ru.nivcsw;
27380Sstevel@tonic-gate pup->pr_sysc = p->p_ru.sysc;
27390Sstevel@tonic-gate pup->pr_ioch = p->p_ru.ioch;
27400Sstevel@tonic-gate
27410Sstevel@tonic-gate /*
27420Sstevel@tonic-gate * Add the usage information for each active lwp.
27430Sstevel@tonic-gate */
27440Sstevel@tonic-gate if ((t = p->p_tlist) != NULL &&
27450Sstevel@tonic-gate !(pcp->prc_flags & PRC_DESTROY)) {
27460Sstevel@tonic-gate do {
27470Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
27480Sstevel@tonic-gate pup->pr_count++;
27490Sstevel@tonic-gate praddusage(t, pup);
27500Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
27510Sstevel@tonic-gate }
27520Sstevel@tonic-gate }
27530Sstevel@tonic-gate
27540Sstevel@tonic-gate prunlock(pnp);
27550Sstevel@tonic-gate
27560Sstevel@tonic-gate upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
27570Sstevel@tonic-gate prcvtusage32(pup, upup);
27580Sstevel@tonic-gate if (copyout(upup, cmaddr, sizeof (*upup)))
27590Sstevel@tonic-gate error = EFAULT;
27600Sstevel@tonic-gate kmem_free(upup, sizeof (*upup));
27610Sstevel@tonic-gate
27620Sstevel@tonic-gate break;
27630Sstevel@tonic-gate }
27640Sstevel@tonic-gate
27650Sstevel@tonic-gate case PIOCLUSAGE: /* get detailed usage info */
27660Sstevel@tonic-gate {
27670Sstevel@tonic-gate int Nlwp;
27680Sstevel@tonic-gate int nlwp;
27690Sstevel@tonic-gate prusage32_t *upup;
27700Sstevel@tonic-gate prusage32_t *Bupup;
27710Sstevel@tonic-gate prhusage_t *pup;
27720Sstevel@tonic-gate hrtime_t curtime;
27730Sstevel@tonic-gate
27740Sstevel@tonic-gate nlwp = Nlwp = (pcp->prc_flags & PRC_DESTROY)? 0 : p->p_lwpcnt;
27750Sstevel@tonic-gate
27760Sstevel@tonic-gate if (thing && thingsize !=
27770Sstevel@tonic-gate sizeof (prhusage_t) + (Nlwp+1) * sizeof (prusage32_t)) {
27780Sstevel@tonic-gate kmem_free(thing, thingsize);
27790Sstevel@tonic-gate thing = NULL;
27800Sstevel@tonic-gate }
27810Sstevel@tonic-gate if (thing == NULL) {
27820Sstevel@tonic-gate thingsize = sizeof (prhusage_t) +
27830Sstevel@tonic-gate (Nlwp+1) * sizeof (prusage32_t);
27840Sstevel@tonic-gate thing = kmem_alloc(thingsize, KM_NOSLEEP);
27850Sstevel@tonic-gate }
27860Sstevel@tonic-gate if (thing == NULL) {
27870Sstevel@tonic-gate prunlock(pnp);
27880Sstevel@tonic-gate goto startover;
27890Sstevel@tonic-gate }
27900Sstevel@tonic-gate
27910Sstevel@tonic-gate pup = (prhusage_t *)thing;
27920Sstevel@tonic-gate upup = Bupup = (prusage32_t *)(pup + 1);
27930Sstevel@tonic-gate
27940Sstevel@tonic-gate ASSERT(p == pcp->prc_proc);
27950Sstevel@tonic-gate
27960Sstevel@tonic-gate curtime = gethrtime();
27970Sstevel@tonic-gate
27980Sstevel@tonic-gate /*
27990Sstevel@tonic-gate * First the summation over defunct lwps.
28000Sstevel@tonic-gate */
28010Sstevel@tonic-gate bzero(pup, sizeof (*pup));
28020Sstevel@tonic-gate pup->pr_count = p->p_defunct;
28030Sstevel@tonic-gate pup->pr_tstamp = curtime;
28040Sstevel@tonic-gate pup->pr_create = p->p_mstart;
28050Sstevel@tonic-gate pup->pr_term = p->p_mterm;
28060Sstevel@tonic-gate
28070Sstevel@tonic-gate pup->pr_rtime = p->p_mlreal;
28080Sstevel@tonic-gate pup->pr_utime = p->p_acct[LMS_USER];
28090Sstevel@tonic-gate pup->pr_stime = p->p_acct[LMS_SYSTEM];
28100Sstevel@tonic-gate pup->pr_ttime = p->p_acct[LMS_TRAP];
28110Sstevel@tonic-gate pup->pr_tftime = p->p_acct[LMS_TFAULT];
28120Sstevel@tonic-gate pup->pr_dftime = p->p_acct[LMS_DFAULT];
28130Sstevel@tonic-gate pup->pr_kftime = p->p_acct[LMS_KFAULT];
28140Sstevel@tonic-gate pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
28150Sstevel@tonic-gate pup->pr_slptime = p->p_acct[LMS_SLEEP];
28160Sstevel@tonic-gate pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
28170Sstevel@tonic-gate pup->pr_stoptime = p->p_acct[LMS_STOPPED];
28180Sstevel@tonic-gate
28190Sstevel@tonic-gate pup->pr_minf = p->p_ru.minflt;
28200Sstevel@tonic-gate pup->pr_majf = p->p_ru.majflt;
28210Sstevel@tonic-gate pup->pr_nswap = p->p_ru.nswap;
28220Sstevel@tonic-gate pup->pr_inblk = p->p_ru.inblock;
28230Sstevel@tonic-gate pup->pr_oublk = p->p_ru.oublock;
28240Sstevel@tonic-gate pup->pr_msnd = p->p_ru.msgsnd;
28250Sstevel@tonic-gate pup->pr_mrcv = p->p_ru.msgrcv;
28260Sstevel@tonic-gate pup->pr_sigs = p->p_ru.nsignals;
28270Sstevel@tonic-gate pup->pr_vctx = p->p_ru.nvcsw;
28280Sstevel@tonic-gate pup->pr_ictx = p->p_ru.nivcsw;
28290Sstevel@tonic-gate pup->pr_sysc = p->p_ru.sysc;
28300Sstevel@tonic-gate pup->pr_ioch = p->p_ru.ioch;
28310Sstevel@tonic-gate
28320Sstevel@tonic-gate prcvtusage32(pup, upup);
28330Sstevel@tonic-gate
28340Sstevel@tonic-gate /*
28350Sstevel@tonic-gate * Fill one prusage struct for each active lwp.
28360Sstevel@tonic-gate */
28370Sstevel@tonic-gate if ((t = p->p_tlist) != NULL &&
28380Sstevel@tonic-gate !(pcp->prc_flags & PRC_DESTROY)) {
28390Sstevel@tonic-gate do {
28400Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
28410Sstevel@tonic-gate ASSERT(nlwp > 0);
28420Sstevel@tonic-gate --nlwp;
28430Sstevel@tonic-gate upup++;
28440Sstevel@tonic-gate prgetusage(t, pup);
28450Sstevel@tonic-gate prcvtusage32(pup, upup);
28460Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
28470Sstevel@tonic-gate }
28480Sstevel@tonic-gate ASSERT(nlwp == 0);
28490Sstevel@tonic-gate
28500Sstevel@tonic-gate prunlock(pnp);
28510Sstevel@tonic-gate if (copyout(Bupup, cmaddr, (Nlwp+1) * sizeof (prusage32_t)))
28520Sstevel@tonic-gate error = EFAULT;
28530Sstevel@tonic-gate kmem_free(thing, thingsize);
28540Sstevel@tonic-gate thing = NULL;
28550Sstevel@tonic-gate break;
28560Sstevel@tonic-gate }
28570Sstevel@tonic-gate
28580Sstevel@tonic-gate case PIOCNAUXV: /* get number of aux vector entries */
28590Sstevel@tonic-gate {
28600Sstevel@tonic-gate int n = __KERN_NAUXV_IMPL;
28610Sstevel@tonic-gate
28620Sstevel@tonic-gate prunlock(pnp);
28630Sstevel@tonic-gate if (copyout(&n, cmaddr, sizeof (int)))
28640Sstevel@tonic-gate error = EFAULT;
28650Sstevel@tonic-gate break;
28660Sstevel@tonic-gate }
28670Sstevel@tonic-gate
28680Sstevel@tonic-gate case PIOCAUXV: /* get aux vector (see sys/auxv.h) */
28690Sstevel@tonic-gate {
28700Sstevel@tonic-gate int i;
28710Sstevel@tonic-gate
28720Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
28730Sstevel@tonic-gate prunlock(pnp);
28740Sstevel@tonic-gate error = EOVERFLOW;
28750Sstevel@tonic-gate } else {
28760Sstevel@tonic-gate up = PTOU(p);
28770Sstevel@tonic-gate for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
28780Sstevel@tonic-gate un32.auxv[i].a_type = up->u_auxv[i].a_type;
28790Sstevel@tonic-gate un32.auxv[i].a_un.a_val =
28806409Sethindra (int32_t)up->u_auxv[i].a_un.a_val;
28810Sstevel@tonic-gate }
28820Sstevel@tonic-gate prunlock(pnp);
28830Sstevel@tonic-gate if (copyout(un32.auxv, cmaddr,
28840Sstevel@tonic-gate __KERN_NAUXV_IMPL * sizeof (auxv32_t)))
28850Sstevel@tonic-gate error = EFAULT;
28860Sstevel@tonic-gate }
28870Sstevel@tonic-gate break;
28880Sstevel@tonic-gate }
28890Sstevel@tonic-gate
28900Sstevel@tonic-gate #if defined(__i386) || defined(__i386_COMPAT)
28910Sstevel@tonic-gate case PIOCNLDT: /* get number of LDT entries */
28920Sstevel@tonic-gate {
28930Sstevel@tonic-gate int n;
28940Sstevel@tonic-gate
28958921SVamsi.Krishna@Sun.COM mutex_exit(&p->p_lock);
28960Sstevel@tonic-gate mutex_enter(&p->p_ldtlock);
28970Sstevel@tonic-gate n = prnldt(p);
28980Sstevel@tonic-gate mutex_exit(&p->p_ldtlock);
28998921SVamsi.Krishna@Sun.COM mutex_enter(&p->p_lock);
29000Sstevel@tonic-gate prunlock(pnp);
29010Sstevel@tonic-gate if (copyout(&n, cmaddr, sizeof (n)))
29020Sstevel@tonic-gate error = EFAULT;
29030Sstevel@tonic-gate break;
29040Sstevel@tonic-gate }
29050Sstevel@tonic-gate
29060Sstevel@tonic-gate case PIOCLDT: /* get LDT entries */
29070Sstevel@tonic-gate {
29080Sstevel@tonic-gate struct ssd *ssd;
29090Sstevel@tonic-gate int n;
29100Sstevel@tonic-gate
29118921SVamsi.Krishna@Sun.COM mutex_exit(&p->p_lock);
29120Sstevel@tonic-gate mutex_enter(&p->p_ldtlock);
29130Sstevel@tonic-gate n = prnldt(p);
29140Sstevel@tonic-gate
29150Sstevel@tonic-gate if (thing && thingsize != (n+1) * sizeof (*ssd)) {
29160Sstevel@tonic-gate kmem_free(thing, thingsize);
29170Sstevel@tonic-gate thing = NULL;
29180Sstevel@tonic-gate }
29190Sstevel@tonic-gate if (thing == NULL) {
29200Sstevel@tonic-gate thingsize = (n+1) * sizeof (*ssd);
29210Sstevel@tonic-gate thing = kmem_alloc(thingsize, KM_NOSLEEP);
29220Sstevel@tonic-gate }
29230Sstevel@tonic-gate if (thing == NULL) {
29240Sstevel@tonic-gate mutex_exit(&p->p_ldtlock);
29258921SVamsi.Krishna@Sun.COM mutex_enter(&p->p_lock);
29260Sstevel@tonic-gate prunlock(pnp);
29270Sstevel@tonic-gate goto startover;
29280Sstevel@tonic-gate }
29290Sstevel@tonic-gate
29300Sstevel@tonic-gate ssd = thing;
29310Sstevel@tonic-gate thing = NULL;
29320Sstevel@tonic-gate if (n != 0)
29330Sstevel@tonic-gate prgetldt(p, ssd);
29340Sstevel@tonic-gate mutex_exit(&p->p_ldtlock);
29358921SVamsi.Krishna@Sun.COM mutex_enter(&p->p_lock);
29360Sstevel@tonic-gate prunlock(pnp);
29370Sstevel@tonic-gate
29380Sstevel@tonic-gate /* mark the end of the list with a null entry */
29390Sstevel@tonic-gate bzero(&ssd[n], sizeof (*ssd));
29400Sstevel@tonic-gate if (copyout(ssd, cmaddr, (n+1) * sizeof (*ssd)))
29410Sstevel@tonic-gate error = EFAULT;
29420Sstevel@tonic-gate kmem_free(ssd, (n+1) * sizeof (*ssd));
29430Sstevel@tonic-gate break;
29440Sstevel@tonic-gate }
29450Sstevel@tonic-gate #endif /* __i386 || __i386_COMPAT */
29460Sstevel@tonic-gate
29470Sstevel@tonic-gate #if defined(__sparc)
29480Sstevel@tonic-gate case PIOCGWIN: /* get gwindows_t (see sys/reg.h) */
29490Sstevel@tonic-gate {
29500Sstevel@tonic-gate gwindows32_t *gwp = thing;
29510Sstevel@tonic-gate
29520Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
29530Sstevel@tonic-gate prunlock(pnp);
29540Sstevel@tonic-gate error = EOVERFLOW;
29550Sstevel@tonic-gate } else {
29560Sstevel@tonic-gate /* drop p->p_lock while touching the stack */
29570Sstevel@tonic-gate mutex_exit(&p->p_lock);
29580Sstevel@tonic-gate bzero(gwp, sizeof (*gwp));
29590Sstevel@tonic-gate prgetwindows32(lwp, gwp);
29600Sstevel@tonic-gate mutex_enter(&p->p_lock);
29610Sstevel@tonic-gate prunlock(pnp);
29620Sstevel@tonic-gate if (copyout(gwp, cmaddr, sizeof (*gwp)))
29630Sstevel@tonic-gate error = EFAULT;
29640Sstevel@tonic-gate }
29650Sstevel@tonic-gate kmem_free(gwp, sizeof (*gwp));
29660Sstevel@tonic-gate thing = NULL;
29670Sstevel@tonic-gate break;
29680Sstevel@tonic-gate }
29690Sstevel@tonic-gate #endif /* __sparc */
29700Sstevel@tonic-gate
29710Sstevel@tonic-gate default:
29720Sstevel@tonic-gate prunlock(pnp);
29730Sstevel@tonic-gate error = EINVAL;
29740Sstevel@tonic-gate break;
29750Sstevel@tonic-gate
29760Sstevel@tonic-gate }
29770Sstevel@tonic-gate
29780Sstevel@tonic-gate ASSERT(thing == NULL);
29790Sstevel@tonic-gate ASSERT(xpnp == NULL);
29800Sstevel@tonic-gate return (error);
29810Sstevel@tonic-gate }
29820Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
29830Sstevel@tonic-gate
29840Sstevel@tonic-gate /*
29850Sstevel@tonic-gate * Distinguish "writeable" ioctl requests from others.
29860Sstevel@tonic-gate */
29870Sstevel@tonic-gate static int
isprwrioctl(int cmd)29880Sstevel@tonic-gate isprwrioctl(int cmd)
29890Sstevel@tonic-gate {
29900Sstevel@tonic-gate switch (cmd) {
29910Sstevel@tonic-gate case PIOCSTOP:
29920Sstevel@tonic-gate case PIOCRUN:
29930Sstevel@tonic-gate case PIOCSTRACE:
29940Sstevel@tonic-gate case PIOCSSIG:
29950Sstevel@tonic-gate case PIOCKILL:
29960Sstevel@tonic-gate case PIOCUNKILL:
29970Sstevel@tonic-gate case PIOCNICE:
29980Sstevel@tonic-gate case PIOCSENTRY:
29990Sstevel@tonic-gate case PIOCSEXIT:
30000Sstevel@tonic-gate case PIOCSRLC:
30010Sstevel@tonic-gate case PIOCRRLC:
30020Sstevel@tonic-gate case PIOCSREG:
30030Sstevel@tonic-gate case PIOCSFPREG:
30040Sstevel@tonic-gate case PIOCSXREG:
30050Sstevel@tonic-gate case PIOCSHOLD:
30060Sstevel@tonic-gate case PIOCSFAULT:
30070Sstevel@tonic-gate case PIOCCFAULT:
30080Sstevel@tonic-gate case PIOCSFORK:
30090Sstevel@tonic-gate case PIOCRFORK:
30100Sstevel@tonic-gate case PIOCSET:
30110Sstevel@tonic-gate case PIOCRESET:
30120Sstevel@tonic-gate return (1);
30130Sstevel@tonic-gate }
30140Sstevel@tonic-gate return (0);
30150Sstevel@tonic-gate }
30160Sstevel@tonic-gate
30170Sstevel@tonic-gate /*
30180Sstevel@tonic-gate * Map the ioctl() interface run flags to the new interface run flags.
30190Sstevel@tonic-gate */
30200Sstevel@tonic-gate static ulong_t
prmaprunflags(long flags)30210Sstevel@tonic-gate prmaprunflags(long flags)
30220Sstevel@tonic-gate {
30230Sstevel@tonic-gate ulong_t newflags = 0;
30240Sstevel@tonic-gate
30250Sstevel@tonic-gate if (flags & PRCSIG)
30260Sstevel@tonic-gate newflags |= 0x01;
30270Sstevel@tonic-gate if (flags & PRCFAULT)
30280Sstevel@tonic-gate newflags |= 0x02;
30290Sstevel@tonic-gate if (flags & PRSTEP)
30300Sstevel@tonic-gate newflags |= 0x04;
30310Sstevel@tonic-gate if (flags & PRSABORT)
30320Sstevel@tonic-gate newflags |= 0x08;
30330Sstevel@tonic-gate if (flags & PRSTOP)
30340Sstevel@tonic-gate newflags |= 0x10;
30350Sstevel@tonic-gate return (newflags);
30360Sstevel@tonic-gate }
30370Sstevel@tonic-gate
30380Sstevel@tonic-gate /*
30390Sstevel@tonic-gate * Map the ioctl() interface settable mode flags to the new interface flags.
30400Sstevel@tonic-gate */
30410Sstevel@tonic-gate static long
prmapsetflags(long flags)30420Sstevel@tonic-gate prmapsetflags(long flags)
30430Sstevel@tonic-gate {
30440Sstevel@tonic-gate long newflags = 0;
30450Sstevel@tonic-gate
30460Sstevel@tonic-gate #define ALLFLAGS \
30470Sstevel@tonic-gate (PR_FORK|PR_RLC|PR_KLC|PR_ASYNC|PR_BPTADJ|PR_MSACCT|PR_PCOMPAT)
30480Sstevel@tonic-gate
30490Sstevel@tonic-gate if (flags & ~ALLFLAGS)
30500Sstevel@tonic-gate newflags = 0xffff; /* forces EINVAL */
30510Sstevel@tonic-gate if (flags & PR_FORK)
30520Sstevel@tonic-gate newflags |= (0x00100000 | 0x08000000);
30530Sstevel@tonic-gate if (flags & PR_RLC)
30540Sstevel@tonic-gate newflags |= 0x00200000;
30550Sstevel@tonic-gate if (flags & PR_KLC)
30560Sstevel@tonic-gate newflags |= 0x00400000;
30570Sstevel@tonic-gate if (flags & PR_ASYNC)
30580Sstevel@tonic-gate newflags |= 0x00800000;
30590Sstevel@tonic-gate if (flags & PR_MSACCT)
30600Sstevel@tonic-gate newflags |= 0x01000000;
30610Sstevel@tonic-gate if (flags & PR_BPTADJ)
30620Sstevel@tonic-gate newflags |= 0x02000000;
30630Sstevel@tonic-gate if (flags & PR_PCOMPAT)
30640Sstevel@tonic-gate newflags |= 0x04000000;
30650Sstevel@tonic-gate return (newflags);
30660Sstevel@tonic-gate }
30670Sstevel@tonic-gate
30680Sstevel@tonic-gate /*
30690Sstevel@tonic-gate * Apply PIOCRUN options specific to the ioctl() interface.
30700Sstevel@tonic-gate */
30710Sstevel@tonic-gate static void
prsetrun(kthread_t * t,prrun_t * prp)30720Sstevel@tonic-gate prsetrun(kthread_t *t, prrun_t *prp)
30730Sstevel@tonic-gate {
30740Sstevel@tonic-gate proc_t *p = ttoproc(t);
30750Sstevel@tonic-gate klwp_t *lwp = ttolwp(t);
30760Sstevel@tonic-gate long flags = prp->pr_flags;
30770Sstevel@tonic-gate user_t *up = PTOU(p);
30780Sstevel@tonic-gate
30790Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock));
30800Sstevel@tonic-gate
30810Sstevel@tonic-gate if (flags & PRSHOLD) {
30820Sstevel@tonic-gate schedctl_finish_sigblock(t);
30830Sstevel@tonic-gate sigutok(&prp->pr_sighold, &t->t_hold);
30840Sstevel@tonic-gate t->t_sig_check = 1; /* so ISSIG will be done */
30850Sstevel@tonic-gate }
30860Sstevel@tonic-gate if (flags & PRSTRACE) {
30870Sstevel@tonic-gate prdelset(&prp->pr_trace, SIGKILL);
30880Sstevel@tonic-gate prassignset(&p->p_sigmask, &prp->pr_trace);
30890Sstevel@tonic-gate if (!sigisempty(&p->p_sigmask))
30900Sstevel@tonic-gate p->p_proc_flag |= P_PR_TRACE;
30910Sstevel@tonic-gate else if (prisempty(&p->p_fltmask)) {
30920Sstevel@tonic-gate if (up->u_systrap == 0)
30930Sstevel@tonic-gate p->p_proc_flag &= ~P_PR_TRACE;
30940Sstevel@tonic-gate }
30950Sstevel@tonic-gate }
30960Sstevel@tonic-gate if (flags & PRSFAULT) {
30970Sstevel@tonic-gate prassignset(&p->p_fltmask, &prp->pr_fault);
30980Sstevel@tonic-gate if (!prisempty(&p->p_fltmask))
30990Sstevel@tonic-gate p->p_proc_flag |= P_PR_TRACE;
31000Sstevel@tonic-gate else if (sigisempty(&p->p_sigmask)) {
31010Sstevel@tonic-gate if (up->u_systrap == 0)
31020Sstevel@tonic-gate p->p_proc_flag &= ~P_PR_TRACE;
31030Sstevel@tonic-gate }
31040Sstevel@tonic-gate }
31050Sstevel@tonic-gate /*
31060Sstevel@tonic-gate * prsvaddr() must be called before prstep() because
31070Sstevel@tonic-gate * stepping can depend on the current value of the PC.
31080Sstevel@tonic-gate * We drop p_lock while touching the lwp's registers (on stack).
31090Sstevel@tonic-gate */
31100Sstevel@tonic-gate if (flags & PRSVADDR) {
31110Sstevel@tonic-gate mutex_exit(&p->p_lock);
31120Sstevel@tonic-gate prsvaddr(lwp, prp->pr_vaddr);
31130Sstevel@tonic-gate mutex_enter(&p->p_lock);
31140Sstevel@tonic-gate }
31150Sstevel@tonic-gate }
31160Sstevel@tonic-gate
31170Sstevel@tonic-gate /*
31180Sstevel@tonic-gate * Common code for PIOCOPENM
31190Sstevel@tonic-gate * Returns with the process unlocked.
31200Sstevel@tonic-gate */
31210Sstevel@tonic-gate static int
propenm(prnode_t * pnp,caddr_t cmaddr,caddr_t va,int * rvalp,cred_t * cr)31220Sstevel@tonic-gate propenm(prnode_t *pnp, caddr_t cmaddr, caddr_t va, int *rvalp, cred_t *cr)
31230Sstevel@tonic-gate {
31240Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
31250Sstevel@tonic-gate struct as *as = p->p_as;
31260Sstevel@tonic-gate int error = 0;
31270Sstevel@tonic-gate struct seg *seg;
31280Sstevel@tonic-gate struct vnode *xvp;
31290Sstevel@tonic-gate int n;
31300Sstevel@tonic-gate
31310Sstevel@tonic-gate /*
31320Sstevel@tonic-gate * By fiat, a system process has no address space.
31330Sstevel@tonic-gate */
31340Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
31350Sstevel@tonic-gate error = EINVAL;
31360Sstevel@tonic-gate } else if (cmaddr) {
31370Sstevel@tonic-gate /*
31380Sstevel@tonic-gate * We drop p_lock before grabbing the address
31390Sstevel@tonic-gate * space lock in order to avoid a deadlock with
31400Sstevel@tonic-gate * the clock thread. The process will not
31410Sstevel@tonic-gate * disappear and its address space will not
31420Sstevel@tonic-gate * change because it is marked P_PR_LOCK.
31430Sstevel@tonic-gate */
31440Sstevel@tonic-gate mutex_exit(&p->p_lock);
31450Sstevel@tonic-gate AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
31460Sstevel@tonic-gate seg = as_segat(as, va);
31470Sstevel@tonic-gate if (seg != NULL &&
31480Sstevel@tonic-gate seg->s_ops == &segvn_ops &&
31490Sstevel@tonic-gate SEGOP_GETVP(seg, va, &xvp) == 0 &&
31500Sstevel@tonic-gate xvp != NULL &&
31510Sstevel@tonic-gate xvp->v_type == VREG) {
31520Sstevel@tonic-gate VN_HOLD(xvp);
31530Sstevel@tonic-gate } else {
31540Sstevel@tonic-gate error = EINVAL;
31550Sstevel@tonic-gate }
31560Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
31570Sstevel@tonic-gate mutex_enter(&p->p_lock);
31580Sstevel@tonic-gate } else if ((xvp = p->p_exec) == NULL) {
31590Sstevel@tonic-gate error = EINVAL;
31600Sstevel@tonic-gate } else {
31610Sstevel@tonic-gate VN_HOLD(xvp);
31620Sstevel@tonic-gate }
31630Sstevel@tonic-gate
31640Sstevel@tonic-gate prunlock(pnp);
31650Sstevel@tonic-gate
31660Sstevel@tonic-gate if (error == 0) {
31675331Samw if ((error = VOP_ACCESS(xvp, VREAD, 0, cr, NULL)) == 0)
31680Sstevel@tonic-gate error = fassign(&xvp, FREAD, &n);
31690Sstevel@tonic-gate if (error) {
31700Sstevel@tonic-gate VN_RELE(xvp);
31710Sstevel@tonic-gate } else {
31720Sstevel@tonic-gate *rvalp = n;
31730Sstevel@tonic-gate }
31740Sstevel@tonic-gate }
31750Sstevel@tonic-gate
31760Sstevel@tonic-gate return (error);
31770Sstevel@tonic-gate }
31780Sstevel@tonic-gate
31790Sstevel@tonic-gate /*
31800Sstevel@tonic-gate * Return old version of process/lwp status.
31810Sstevel@tonic-gate * The u-block is mapped in by this routine and unmapped at the end.
31820Sstevel@tonic-gate */
31830Sstevel@tonic-gate void
oprgetstatus(kthread_t * t,prstatus_t * sp,zone_t * zp)31840Sstevel@tonic-gate oprgetstatus(kthread_t *t, prstatus_t *sp, zone_t *zp)
31850Sstevel@tonic-gate {
31860Sstevel@tonic-gate proc_t *p = ttoproc(t);
31870Sstevel@tonic-gate klwp_t *lwp = ttolwp(t);
31880Sstevel@tonic-gate int flags;
31890Sstevel@tonic-gate user_t *up;
31900Sstevel@tonic-gate ulong_t instr;
31910Sstevel@tonic-gate
31920Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock));
31930Sstevel@tonic-gate
31940Sstevel@tonic-gate up = PTOU(p);
31950Sstevel@tonic-gate bzero(sp, sizeof (*sp));
31960Sstevel@tonic-gate flags = 0;
31970Sstevel@tonic-gate if (t->t_state == TS_STOPPED) {
31980Sstevel@tonic-gate flags |= PR_STOPPED;
31990Sstevel@tonic-gate if ((t->t_schedflag & TS_PSTART) == 0)
32000Sstevel@tonic-gate flags |= PR_ISTOP;
32010Sstevel@tonic-gate } else if (VSTOPPED(t)) {
32020Sstevel@tonic-gate flags |= PR_STOPPED|PR_ISTOP;
32030Sstevel@tonic-gate }
32040Sstevel@tonic-gate if (!(flags & PR_ISTOP) && (t->t_proc_flag & TP_PRSTOP))
32050Sstevel@tonic-gate flags |= PR_DSTOP;
32060Sstevel@tonic-gate if (lwp->lwp_asleep)
32070Sstevel@tonic-gate flags |= PR_ASLEEP;
32080Sstevel@tonic-gate if (p->p_proc_flag & P_PR_FORK)
32090Sstevel@tonic-gate flags |= PR_FORK;
32100Sstevel@tonic-gate if (p->p_proc_flag & P_PR_RUNLCL)
32110Sstevel@tonic-gate flags |= PR_RLC;
32120Sstevel@tonic-gate if (p->p_proc_flag & P_PR_KILLCL)
32130Sstevel@tonic-gate flags |= PR_KLC;
32140Sstevel@tonic-gate if (p->p_proc_flag & P_PR_ASYNC)
32150Sstevel@tonic-gate flags |= PR_ASYNC;
32160Sstevel@tonic-gate if (p->p_proc_flag & P_PR_BPTADJ)
32170Sstevel@tonic-gate flags |= PR_BPTADJ;
32180Sstevel@tonic-gate if (p->p_proc_flag & P_PR_PTRACE)
32190Sstevel@tonic-gate flags |= PR_PCOMPAT;
32200Sstevel@tonic-gate if (t->t_proc_flag & TP_MSACCT)
32210Sstevel@tonic-gate flags |= PR_MSACCT;
32220Sstevel@tonic-gate sp->pr_flags = flags;
32230Sstevel@tonic-gate if (VSTOPPED(t)) {
32240Sstevel@tonic-gate sp->pr_why = PR_REQUESTED;
32250Sstevel@tonic-gate sp->pr_what = 0;
32260Sstevel@tonic-gate } else {
32270Sstevel@tonic-gate sp->pr_why = t->t_whystop;
32280Sstevel@tonic-gate sp->pr_what = t->t_whatstop;
32290Sstevel@tonic-gate }
32300Sstevel@tonic-gate
32310Sstevel@tonic-gate if (t->t_whystop == PR_FAULTED)
32320Sstevel@tonic-gate bcopy(&lwp->lwp_siginfo,
32330Sstevel@tonic-gate &sp->pr_info, sizeof (k_siginfo_t));
32340Sstevel@tonic-gate else if (lwp->lwp_curinfo)
32350Sstevel@tonic-gate bcopy(&lwp->lwp_curinfo->sq_info,
32360Sstevel@tonic-gate &sp->pr_info, sizeof (k_siginfo_t));
32370Sstevel@tonic-gate
32380Sstevel@tonic-gate if (SI_FROMUSER(&lwp->lwp_siginfo) && zp->zone_id != GLOBAL_ZONEID &&
32390Sstevel@tonic-gate sp->pr_info.si_zoneid != zp->zone_id) {
32400Sstevel@tonic-gate sp->pr_info.si_pid = zp->zone_zsched->p_pid;
32410Sstevel@tonic-gate sp->pr_info.si_uid = 0;
32420Sstevel@tonic-gate sp->pr_info.si_ctid = -1;
32430Sstevel@tonic-gate sp->pr_info.si_zoneid = zp->zone_id;
32440Sstevel@tonic-gate }
32450Sstevel@tonic-gate
32460Sstevel@tonic-gate sp->pr_cursig = lwp->lwp_cursig;
32470Sstevel@tonic-gate prassignset(&sp->pr_sigpend, &p->p_sig);
32480Sstevel@tonic-gate prassignset(&sp->pr_lwppend, &t->t_sig);
32490Sstevel@tonic-gate schedctl_finish_sigblock(t);
32500Sstevel@tonic-gate prassignset(&sp->pr_sighold, &t->t_hold);
32510Sstevel@tonic-gate sp->pr_altstack = lwp->lwp_sigaltstack;
32520Sstevel@tonic-gate prgetaction(p, up, lwp->lwp_cursig, &sp->pr_action);
32530Sstevel@tonic-gate sp->pr_pid = p->p_pid;
32540Sstevel@tonic-gate if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
32550Sstevel@tonic-gate (p->p_flag & SZONETOP)) {
32560Sstevel@tonic-gate ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
32570Sstevel@tonic-gate /*
32580Sstevel@tonic-gate * Inside local zones, fake zsched's pid as parent pids for
32590Sstevel@tonic-gate * processes which reference processes outside of the zone.
32600Sstevel@tonic-gate */
32610Sstevel@tonic-gate sp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
32620Sstevel@tonic-gate } else {
32630Sstevel@tonic-gate sp->pr_ppid = p->p_ppid;
32640Sstevel@tonic-gate }
32650Sstevel@tonic-gate sp->pr_pgrp = p->p_pgrp;
32660Sstevel@tonic-gate sp->pr_sid = p->p_sessp->s_sid;
32670Sstevel@tonic-gate hrt2ts(mstate_aggr_state(p, LMS_USER), &sp->pr_utime);
32680Sstevel@tonic-gate hrt2ts(mstate_aggr_state(p, LMS_SYSTEM), &sp->pr_stime);
32690Sstevel@tonic-gate TICK_TO_TIMESTRUC(p->p_cutime, &sp->pr_cutime);
32700Sstevel@tonic-gate TICK_TO_TIMESTRUC(p->p_cstime, &sp->pr_cstime);
32710Sstevel@tonic-gate (void) strncpy(sp->pr_clname, sclass[t->t_cid].cl_name,
32726409Sethindra sizeof (sp->pr_clname) - 1);
32730Sstevel@tonic-gate sp->pr_who = t->t_tid;
32740Sstevel@tonic-gate sp->pr_nlwp = p->p_lwpcnt;
32750Sstevel@tonic-gate sp->pr_brkbase = p->p_brkbase;
32760Sstevel@tonic-gate sp->pr_brksize = p->p_brksize;
32770Sstevel@tonic-gate sp->pr_stkbase = prgetstackbase(p);
32780Sstevel@tonic-gate sp->pr_stksize = p->p_stksize;
32790Sstevel@tonic-gate sp->pr_oldcontext = (struct ucontext *)lwp->lwp_oldcontext;
32800Sstevel@tonic-gate sp->pr_processor = t->t_cpu->cpu_id;
32810Sstevel@tonic-gate sp->pr_bind = t->t_bind_cpu;
32820Sstevel@tonic-gate
32830Sstevel@tonic-gate /*
32840Sstevel@tonic-gate * Fetch the current instruction, if not a system process.
32850Sstevel@tonic-gate * We don't attempt this unless the lwp is stopped.
32860Sstevel@tonic-gate */
32870Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
32880Sstevel@tonic-gate sp->pr_flags |= (PR_ISSYS|PR_PCINVAL);
32890Sstevel@tonic-gate else if (!(flags & PR_STOPPED))
32900Sstevel@tonic-gate sp->pr_flags |= PR_PCINVAL;
32910Sstevel@tonic-gate else if (!prfetchinstr(lwp, &instr))
32920Sstevel@tonic-gate sp->pr_flags |= PR_PCINVAL;
32930Sstevel@tonic-gate else
32940Sstevel@tonic-gate sp->pr_instr = instr;
32950Sstevel@tonic-gate
32960Sstevel@tonic-gate /*
32970Sstevel@tonic-gate * Drop p_lock while touching the lwp's stack.
32980Sstevel@tonic-gate */
32990Sstevel@tonic-gate mutex_exit(&p->p_lock);
33000Sstevel@tonic-gate if (prisstep(lwp))
33010Sstevel@tonic-gate sp->pr_flags |= PR_STEP;
33020Sstevel@tonic-gate if ((flags & (PR_STOPPED|PR_ASLEEP)) && t->t_sysnum) {
33030Sstevel@tonic-gate int i;
33040Sstevel@tonic-gate auxv_t *auxp;
33050Sstevel@tonic-gate
33060Sstevel@tonic-gate sp->pr_syscall = get_syscall_args(lwp,
33076409Sethindra (long *)sp->pr_sysarg, &i);
33080Sstevel@tonic-gate sp->pr_nsysarg = (short)i;
330911798SRoger.Faulkner@Sun.COM if (t->t_whystop == PR_SYSEXIT && t->t_sysnum == SYS_execve) {
33100Sstevel@tonic-gate sp->pr_sysarg[0] = 0;
33110Sstevel@tonic-gate sp->pr_sysarg[1] = (uintptr_t)up->u_argv;
33120Sstevel@tonic-gate sp->pr_sysarg[2] = (uintptr_t)up->u_envp;
33130Sstevel@tonic-gate for (i = 0, auxp = up->u_auxv;
33140Sstevel@tonic-gate i < sizeof (up->u_auxv) / sizeof (up->u_auxv[0]);
33150Sstevel@tonic-gate i++, auxp++) {
33160Sstevel@tonic-gate if (auxp->a_type == AT_SUN_EXECNAME) {
33170Sstevel@tonic-gate sp->pr_sysarg[0] =
33186409Sethindra (uintptr_t)auxp->a_un.a_ptr;
33190Sstevel@tonic-gate break;
33200Sstevel@tonic-gate }
33210Sstevel@tonic-gate }
33220Sstevel@tonic-gate }
33230Sstevel@tonic-gate }
33240Sstevel@tonic-gate if ((flags & PR_STOPPED) || t == curthread)
33250Sstevel@tonic-gate prgetprregs(lwp, sp->pr_reg);
33260Sstevel@tonic-gate mutex_enter(&p->p_lock);
33270Sstevel@tonic-gate }
33280Sstevel@tonic-gate
33290Sstevel@tonic-gate /*
33300Sstevel@tonic-gate * Return old version of information used by ps(1).
33310Sstevel@tonic-gate */
33320Sstevel@tonic-gate void
oprgetpsinfo(proc_t * p,prpsinfo_t * psp,kthread_t * tp)33330Sstevel@tonic-gate oprgetpsinfo(proc_t *p, prpsinfo_t *psp, kthread_t *tp)
33340Sstevel@tonic-gate {
33350Sstevel@tonic-gate kthread_t *t;
33360Sstevel@tonic-gate char c, state;
33370Sstevel@tonic-gate user_t *up;
33380Sstevel@tonic-gate dev_t d;
33390Sstevel@tonic-gate uint64_t pct;
33400Sstevel@tonic-gate int retval, niceval;
33410Sstevel@tonic-gate cred_t *cred;
33420Sstevel@tonic-gate struct as *as;
33430Sstevel@tonic-gate hrtime_t hrutime, hrstime, cur_time;
33440Sstevel@tonic-gate
33450Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock));
33460Sstevel@tonic-gate
33470Sstevel@tonic-gate bzero(psp, sizeof (*psp));
33480Sstevel@tonic-gate
33490Sstevel@tonic-gate if ((t = tp) == NULL)
33500Sstevel@tonic-gate t = prchoose(p); /* returns locked thread */
33510Sstevel@tonic-gate else
33520Sstevel@tonic-gate thread_lock(t);
33530Sstevel@tonic-gate
33540Sstevel@tonic-gate /* kludge: map thread state enum into process state enum */
33550Sstevel@tonic-gate
33560Sstevel@tonic-gate if (t == NULL) {
33570Sstevel@tonic-gate state = TS_ZOMB;
33580Sstevel@tonic-gate } else {
33590Sstevel@tonic-gate state = VSTOPPED(t) ? TS_STOPPED : t->t_state;
33600Sstevel@tonic-gate thread_unlock(t);
33610Sstevel@tonic-gate }
33620Sstevel@tonic-gate
33630Sstevel@tonic-gate switch (state) {
33640Sstevel@tonic-gate case TS_SLEEP: state = SSLEEP; break;
33650Sstevel@tonic-gate case TS_RUN: state = SRUN; break;
33660Sstevel@tonic-gate case TS_ONPROC: state = SONPROC; break;
33670Sstevel@tonic-gate case TS_ZOMB: state = SZOMB; break;
33680Sstevel@tonic-gate case TS_STOPPED: state = SSTOP; break;
33690Sstevel@tonic-gate default: state = 0; break;
33700Sstevel@tonic-gate }
33710Sstevel@tonic-gate switch (state) {
33720Sstevel@tonic-gate case SSLEEP: c = 'S'; break;
33730Sstevel@tonic-gate case SRUN: c = 'R'; break;
33740Sstevel@tonic-gate case SZOMB: c = 'Z'; break;
33750Sstevel@tonic-gate case SSTOP: c = 'T'; break;
33760Sstevel@tonic-gate case SIDL: c = 'I'; break;
33770Sstevel@tonic-gate case SONPROC: c = 'O'; break;
33780Sstevel@tonic-gate #ifdef SXBRK
33790Sstevel@tonic-gate case SXBRK: c = 'X'; break;
33800Sstevel@tonic-gate #endif
33810Sstevel@tonic-gate default: c = '?'; break;
33820Sstevel@tonic-gate }
33830Sstevel@tonic-gate psp->pr_state = state;
33840Sstevel@tonic-gate psp->pr_sname = c;
33850Sstevel@tonic-gate psp->pr_zomb = (state == SZOMB);
33860Sstevel@tonic-gate /*
33870Sstevel@tonic-gate * only export SSYS and SMSACCT; everything else is off-limits to
33880Sstevel@tonic-gate * userland apps.
33890Sstevel@tonic-gate */
33900Sstevel@tonic-gate psp->pr_flag = p->p_flag & (SSYS | SMSACCT);
33910Sstevel@tonic-gate
33920Sstevel@tonic-gate mutex_enter(&p->p_crlock);
33930Sstevel@tonic-gate cred = p->p_cred;
33940Sstevel@tonic-gate psp->pr_uid = crgetruid(cred);
33950Sstevel@tonic-gate psp->pr_gid = crgetrgid(cred);
33960Sstevel@tonic-gate psp->pr_euid = crgetuid(cred);
33970Sstevel@tonic-gate psp->pr_egid = crgetgid(cred);
33980Sstevel@tonic-gate mutex_exit(&p->p_crlock);
33990Sstevel@tonic-gate
34000Sstevel@tonic-gate psp->pr_pid = p->p_pid;
34010Sstevel@tonic-gate if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
34020Sstevel@tonic-gate (p->p_flag & SZONETOP)) {
34030Sstevel@tonic-gate ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
34040Sstevel@tonic-gate /*
34050Sstevel@tonic-gate * Inside local zones, fake zsched's pid as parent pids for
34060Sstevel@tonic-gate * processes which reference processes outside of the zone.
34070Sstevel@tonic-gate */
34080Sstevel@tonic-gate psp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
34090Sstevel@tonic-gate } else {
34100Sstevel@tonic-gate psp->pr_ppid = p->p_ppid;
34110Sstevel@tonic-gate }
34120Sstevel@tonic-gate psp->pr_pgrp = p->p_pgrp;
34130Sstevel@tonic-gate psp->pr_sid = p->p_sessp->s_sid;
34140Sstevel@tonic-gate psp->pr_addr = prgetpsaddr(p);
34150Sstevel@tonic-gate hrutime = mstate_aggr_state(p, LMS_USER);
34160Sstevel@tonic-gate hrstime = mstate_aggr_state(p, LMS_SYSTEM);
34170Sstevel@tonic-gate hrt2ts(hrutime + hrstime, &psp->pr_time);
34180Sstevel@tonic-gate TICK_TO_TIMESTRUC(p->p_cutime + p->p_cstime, &psp->pr_ctime);
34190Sstevel@tonic-gate switch (p->p_model) {
34200Sstevel@tonic-gate case DATAMODEL_ILP32:
34210Sstevel@tonic-gate psp->pr_dmodel = PR_MODEL_ILP32;
34220Sstevel@tonic-gate break;
34230Sstevel@tonic-gate case DATAMODEL_LP64:
34240Sstevel@tonic-gate psp->pr_dmodel = PR_MODEL_LP64;
34250Sstevel@tonic-gate break;
34260Sstevel@tonic-gate }
34270Sstevel@tonic-gate if (state == SZOMB || t == NULL) {
34280Sstevel@tonic-gate int wcode = p->p_wcode; /* must be atomic read */
34290Sstevel@tonic-gate
34300Sstevel@tonic-gate if (wcode)
34310Sstevel@tonic-gate psp->pr_wstat = wstat(wcode, p->p_wdata);
34320Sstevel@tonic-gate psp->pr_lttydev = PRNODEV;
34330Sstevel@tonic-gate psp->pr_ottydev = (o_dev_t)PRNODEV;
34340Sstevel@tonic-gate psp->pr_size = 0;
34350Sstevel@tonic-gate psp->pr_rssize = 0;
34360Sstevel@tonic-gate psp->pr_pctmem = 0;
34370Sstevel@tonic-gate } else {
34380Sstevel@tonic-gate up = PTOU(p);
34390Sstevel@tonic-gate psp->pr_wchan = t->t_wchan;
34400Sstevel@tonic-gate psp->pr_pri = t->t_pri;
34410Sstevel@tonic-gate (void) strncpy(psp->pr_clname, sclass[t->t_cid].cl_name,
34426409Sethindra sizeof (psp->pr_clname) - 1);
34430Sstevel@tonic-gate retval = CL_DONICE(t, NULL, 0, &niceval);
34440Sstevel@tonic-gate if (retval == 0) {
34450Sstevel@tonic-gate psp->pr_oldpri = v.v_maxsyspri - psp->pr_pri;
34460Sstevel@tonic-gate psp->pr_nice = niceval + NZERO;
34470Sstevel@tonic-gate } else {
34480Sstevel@tonic-gate psp->pr_oldpri = 0;
34490Sstevel@tonic-gate psp->pr_nice = 0;
34500Sstevel@tonic-gate }
34510Sstevel@tonic-gate d = cttydev(p);
34520Sstevel@tonic-gate #ifdef sun
34530Sstevel@tonic-gate {
34540Sstevel@tonic-gate extern dev_t rwsconsdev, rconsdev, uconsdev;
34550Sstevel@tonic-gate /*
34560Sstevel@tonic-gate * If the controlling terminal is the real
34570Sstevel@tonic-gate * or workstation console device, map to what the
34586409Sethindra * user thinks is the console device. Handle case when
34596409Sethindra * rwsconsdev or rconsdev is set to NODEV for Starfire.
34600Sstevel@tonic-gate */
34616409Sethindra if ((d == rwsconsdev || d == rconsdev) && d != NODEV)
34620Sstevel@tonic-gate d = uconsdev;
34630Sstevel@tonic-gate }
34640Sstevel@tonic-gate #endif
34650Sstevel@tonic-gate psp->pr_lttydev = (d == NODEV) ? PRNODEV : d;
34660Sstevel@tonic-gate psp->pr_ottydev = cmpdev(d);
34670Sstevel@tonic-gate psp->pr_start = up->u_start;
34680Sstevel@tonic-gate bcopy(up->u_comm, psp->pr_fname,
34690Sstevel@tonic-gate MIN(sizeof (up->u_comm), sizeof (psp->pr_fname)-1));
34700Sstevel@tonic-gate bcopy(up->u_psargs, psp->pr_psargs,
34710Sstevel@tonic-gate MIN(PRARGSZ-1, PSARGSZ));
34720Sstevel@tonic-gate psp->pr_syscall = t->t_sysnum;
34730Sstevel@tonic-gate psp->pr_argc = up->u_argc;
34740Sstevel@tonic-gate psp->pr_argv = (char **)up->u_argv;
34750Sstevel@tonic-gate psp->pr_envp = (char **)up->u_envp;
34760Sstevel@tonic-gate
34770Sstevel@tonic-gate /* compute %cpu for the lwp or process */
34780Sstevel@tonic-gate pct = 0;
34790Sstevel@tonic-gate if ((t = tp) == NULL)
34800Sstevel@tonic-gate t = p->p_tlist;
34810Sstevel@tonic-gate cur_time = gethrtime_unscaled();
34820Sstevel@tonic-gate do {
34830Sstevel@tonic-gate pct += cpu_update_pct(t, cur_time);
34840Sstevel@tonic-gate if (tp != NULL) /* just do the one lwp */
34850Sstevel@tonic-gate break;
34860Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
34870Sstevel@tonic-gate
34880Sstevel@tonic-gate psp->pr_pctcpu = prgetpctcpu(pct);
34890Sstevel@tonic-gate psp->pr_cpu = (psp->pr_pctcpu*100 + 0x6000) >> 15; /* [0..99] */
34900Sstevel@tonic-gate if (psp->pr_cpu > 99)
34910Sstevel@tonic-gate psp->pr_cpu = 99;
34920Sstevel@tonic-gate
34930Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
34940Sstevel@tonic-gate psp->pr_size = 0;
34950Sstevel@tonic-gate psp->pr_rssize = 0;
34960Sstevel@tonic-gate psp->pr_pctmem = 0;
34970Sstevel@tonic-gate } else {
34980Sstevel@tonic-gate mutex_exit(&p->p_lock);
34990Sstevel@tonic-gate AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
350010169SSudheer.Abdul-Salam@Sun.COM psp->pr_size = btopr(as->a_resvsize);
35010Sstevel@tonic-gate psp->pr_rssize = rm_asrss(as);
35020Sstevel@tonic-gate psp->pr_pctmem = rm_pctmemory(as);
35030Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
35040Sstevel@tonic-gate mutex_enter(&p->p_lock);
35050Sstevel@tonic-gate }
35060Sstevel@tonic-gate }
35070Sstevel@tonic-gate psp->pr_bysize = ptob(psp->pr_size);
35080Sstevel@tonic-gate psp->pr_byrssize = ptob(psp->pr_rssize);
35090Sstevel@tonic-gate }
35100Sstevel@tonic-gate
35110Sstevel@tonic-gate /*
35120Sstevel@tonic-gate * Return an array of structures with memory map information.
35130Sstevel@tonic-gate * We allocate here; the caller must deallocate.
35142789Sfrankho * The caller is also responsible to append the zero-filled entry
35152789Sfrankho * that terminates the PIOCMAP output buffer.
35160Sstevel@tonic-gate */
35170Sstevel@tonic-gate static int
oprgetmap(proc_t * p,list_t * iolhead)35182789Sfrankho oprgetmap(proc_t *p, list_t *iolhead)
35190Sstevel@tonic-gate {
35200Sstevel@tonic-gate struct as *as = p->p_as;
35210Sstevel@tonic-gate prmap_t *mp;
35220Sstevel@tonic-gate struct seg *seg;
35230Sstevel@tonic-gate struct seg *brkseg, *stkseg;
35240Sstevel@tonic-gate uint_t prot;
35250Sstevel@tonic-gate
35260Sstevel@tonic-gate ASSERT(as != &kas && AS_WRITE_HELD(as, &as->a_lock));
35270Sstevel@tonic-gate
35282789Sfrankho /*
35292789Sfrankho * Request an initial buffer size that doesn't waste memory
35302789Sfrankho * if the address space has only a small number of segments.
35312789Sfrankho */
35322789Sfrankho pr_iol_initlist(iolhead, sizeof (*mp), avl_numnodes(&as->a_segtree));
35332789Sfrankho
35342789Sfrankho if ((seg = AS_SEGFIRST(as)) == NULL)
35352789Sfrankho return (0);
35360Sstevel@tonic-gate
35370Sstevel@tonic-gate brkseg = break_seg(p);
35380Sstevel@tonic-gate stkseg = as_segat(as, prgetstackbase(p));
35390Sstevel@tonic-gate
35400Sstevel@tonic-gate do {
35410Sstevel@tonic-gate caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
35420Sstevel@tonic-gate caddr_t saddr, naddr;
35430Sstevel@tonic-gate void *tmp = NULL;
35440Sstevel@tonic-gate
35450Sstevel@tonic-gate for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
35460Sstevel@tonic-gate prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
35470Sstevel@tonic-gate if (saddr == naddr)
35480Sstevel@tonic-gate continue;
35492789Sfrankho
35502789Sfrankho mp = pr_iol_newbuf(iolhead, sizeof (*mp));
35512789Sfrankho
35520Sstevel@tonic-gate mp->pr_vaddr = saddr;
35530Sstevel@tonic-gate mp->pr_size = naddr - saddr;
35540Sstevel@tonic-gate mp->pr_off = SEGOP_GETOFFSET(seg, saddr);
35550Sstevel@tonic-gate mp->pr_mflags = 0;
35560Sstevel@tonic-gate if (prot & PROT_READ)
35570Sstevel@tonic-gate mp->pr_mflags |= MA_READ;
35580Sstevel@tonic-gate if (prot & PROT_WRITE)
35590Sstevel@tonic-gate mp->pr_mflags |= MA_WRITE;
35600Sstevel@tonic-gate if (prot & PROT_EXEC)
35610Sstevel@tonic-gate mp->pr_mflags |= MA_EXEC;
35620Sstevel@tonic-gate if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
35630Sstevel@tonic-gate mp->pr_mflags |= MA_SHARED;
35640Sstevel@tonic-gate if (seg == brkseg)
35650Sstevel@tonic-gate mp->pr_mflags |= MA_BREAK;
35660Sstevel@tonic-gate else if (seg == stkseg)
35670Sstevel@tonic-gate mp->pr_mflags |= MA_STACK;
35680Sstevel@tonic-gate mp->pr_pagesize = PAGESIZE;
35690Sstevel@tonic-gate }
35700Sstevel@tonic-gate ASSERT(tmp == NULL);
35710Sstevel@tonic-gate } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
35720Sstevel@tonic-gate
35732789Sfrankho return (0);
35740Sstevel@tonic-gate }
35750Sstevel@tonic-gate
35760Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
35770Sstevel@tonic-gate static int
oprgetmap32(proc_t * p,list_t * iolhead)35782789Sfrankho oprgetmap32(proc_t *p, list_t *iolhead)
35790Sstevel@tonic-gate {
35800Sstevel@tonic-gate struct as *as = p->p_as;
35810Sstevel@tonic-gate ioc_prmap32_t *mp;
35820Sstevel@tonic-gate struct seg *seg;
35830Sstevel@tonic-gate struct seg *brkseg, *stkseg;
35840Sstevel@tonic-gate uint_t prot;
35850Sstevel@tonic-gate
35860Sstevel@tonic-gate ASSERT(as != &kas && AS_WRITE_HELD(as, &as->a_lock));
35870Sstevel@tonic-gate
35882789Sfrankho /*
35892789Sfrankho * Request an initial buffer size that doesn't waste memory
35902789Sfrankho * if the address space has only a small number of segments.
35912789Sfrankho */
35922789Sfrankho pr_iol_initlist(iolhead, sizeof (*mp), avl_numnodes(&as->a_segtree));
35932789Sfrankho
35942789Sfrankho if ((seg = AS_SEGFIRST(as)) == NULL)
35952789Sfrankho return (0);
35960Sstevel@tonic-gate
35970Sstevel@tonic-gate brkseg = break_seg(p);
35980Sstevel@tonic-gate stkseg = as_segat(as, prgetstackbase(p));
35990Sstevel@tonic-gate
36000Sstevel@tonic-gate do {
36010Sstevel@tonic-gate caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
36020Sstevel@tonic-gate caddr_t saddr, naddr;
36030Sstevel@tonic-gate void *tmp = NULL;
36040Sstevel@tonic-gate
36050Sstevel@tonic-gate for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
36060Sstevel@tonic-gate prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
36070Sstevel@tonic-gate if (saddr == naddr)
36080Sstevel@tonic-gate continue;
36092789Sfrankho
36102789Sfrankho mp = pr_iol_newbuf(iolhead, sizeof (*mp));
36112789Sfrankho
36120Sstevel@tonic-gate mp->pr_vaddr = (caddr32_t)(uintptr_t)saddr;
36130Sstevel@tonic-gate mp->pr_size = (size32_t)(naddr - saddr);
36140Sstevel@tonic-gate mp->pr_off = (off32_t)SEGOP_GETOFFSET(seg, saddr);
36150Sstevel@tonic-gate mp->pr_mflags = 0;
36160Sstevel@tonic-gate if (prot & PROT_READ)
36170Sstevel@tonic-gate mp->pr_mflags |= MA_READ;
36180Sstevel@tonic-gate if (prot & PROT_WRITE)
36190Sstevel@tonic-gate mp->pr_mflags |= MA_WRITE;
36200Sstevel@tonic-gate if (prot & PROT_EXEC)
36210Sstevel@tonic-gate mp->pr_mflags |= MA_EXEC;
36220Sstevel@tonic-gate if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
36230Sstevel@tonic-gate mp->pr_mflags |= MA_SHARED;
36240Sstevel@tonic-gate if (seg == brkseg)
36250Sstevel@tonic-gate mp->pr_mflags |= MA_BREAK;
36260Sstevel@tonic-gate else if (seg == stkseg)
36270Sstevel@tonic-gate mp->pr_mflags |= MA_STACK;
36280Sstevel@tonic-gate mp->pr_pagesize = PAGESIZE;
36290Sstevel@tonic-gate }
36300Sstevel@tonic-gate ASSERT(tmp == NULL);
36310Sstevel@tonic-gate } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
36320Sstevel@tonic-gate
36332789Sfrankho return (0);
36340Sstevel@tonic-gate }
36350Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
36360Sstevel@tonic-gate
36370Sstevel@tonic-gate /*
36380Sstevel@tonic-gate * Return the size of the old /proc page data file.
36390Sstevel@tonic-gate */
36400Sstevel@tonic-gate size_t
oprpdsize(struct as * as)36410Sstevel@tonic-gate oprpdsize(struct as *as)
36420Sstevel@tonic-gate {
36430Sstevel@tonic-gate struct seg *seg;
36440Sstevel@tonic-gate size_t size;
36450Sstevel@tonic-gate
36460Sstevel@tonic-gate ASSERT(as != &kas && AS_WRITE_HELD(as, &as->a_lock));
36470Sstevel@tonic-gate
36480Sstevel@tonic-gate if ((seg = AS_SEGFIRST(as)) == NULL)
36490Sstevel@tonic-gate return (0);
36500Sstevel@tonic-gate
36510Sstevel@tonic-gate size = sizeof (prpageheader_t);
36520Sstevel@tonic-gate do {
36530Sstevel@tonic-gate caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
36540Sstevel@tonic-gate caddr_t saddr, naddr;
36550Sstevel@tonic-gate void *tmp = NULL;
36560Sstevel@tonic-gate size_t npage;
36570Sstevel@tonic-gate
36580Sstevel@tonic-gate for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
36590Sstevel@tonic-gate (void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
36600Sstevel@tonic-gate if ((npage = (naddr - saddr) / PAGESIZE) != 0)
36610Sstevel@tonic-gate size += sizeof (prasmap_t) + roundlong(npage);
36620Sstevel@tonic-gate }
36630Sstevel@tonic-gate ASSERT(tmp == NULL);
36640Sstevel@tonic-gate } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
36650Sstevel@tonic-gate
36660Sstevel@tonic-gate return (size);
36670Sstevel@tonic-gate }
36680Sstevel@tonic-gate
36690Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
36700Sstevel@tonic-gate size_t
oprpdsize32(struct as * as)36710Sstevel@tonic-gate oprpdsize32(struct as *as)
36720Sstevel@tonic-gate {
36730Sstevel@tonic-gate struct seg *seg;
36740Sstevel@tonic-gate size_t size;
36750Sstevel@tonic-gate
36760Sstevel@tonic-gate ASSERT(as != &kas && AS_WRITE_HELD(as, &as->a_lock));
36770Sstevel@tonic-gate
36780Sstevel@tonic-gate if ((seg = AS_SEGFIRST(as)) == NULL)
36790Sstevel@tonic-gate return (0);
36800Sstevel@tonic-gate
36810Sstevel@tonic-gate size = sizeof (ioc_prpageheader32_t);
36820Sstevel@tonic-gate do {
36830Sstevel@tonic-gate caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
36840Sstevel@tonic-gate caddr_t saddr, naddr;
36850Sstevel@tonic-gate void *tmp = NULL;
36860Sstevel@tonic-gate size_t npage;
36870Sstevel@tonic-gate
36880Sstevel@tonic-gate for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
36890Sstevel@tonic-gate (void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
36900Sstevel@tonic-gate if ((npage = (naddr - saddr) / PAGESIZE) != 0)
36910Sstevel@tonic-gate size += sizeof (ioc_prmap32_t) + round4(npage);
36920Sstevel@tonic-gate }
36930Sstevel@tonic-gate ASSERT(tmp == NULL);
36940Sstevel@tonic-gate } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
36950Sstevel@tonic-gate
36960Sstevel@tonic-gate return (size);
36970Sstevel@tonic-gate }
36980Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
36990Sstevel@tonic-gate
37000Sstevel@tonic-gate /*
37010Sstevel@tonic-gate * Read old /proc page data information.
37020Sstevel@tonic-gate */
37030Sstevel@tonic-gate int
oprpdread(struct as * as,uint_t hatid,struct uio * uiop)37040Sstevel@tonic-gate oprpdread(struct as *as, uint_t hatid, struct uio *uiop)
37050Sstevel@tonic-gate {
37060Sstevel@tonic-gate caddr_t buf;
37070Sstevel@tonic-gate size_t size;
37080Sstevel@tonic-gate prpageheader_t *php;
37090Sstevel@tonic-gate prasmap_t *pmp;
37100Sstevel@tonic-gate struct seg *seg;
37110Sstevel@tonic-gate int error;
37120Sstevel@tonic-gate
37130Sstevel@tonic-gate again:
37140Sstevel@tonic-gate AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
37150Sstevel@tonic-gate
37160Sstevel@tonic-gate if ((seg = AS_SEGFIRST(as)) == NULL) {
37170Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
37180Sstevel@tonic-gate return (0);
37190Sstevel@tonic-gate }
37200Sstevel@tonic-gate size = oprpdsize(as);
37210Sstevel@tonic-gate if (uiop->uio_resid < size) {
37220Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
37230Sstevel@tonic-gate return (E2BIG);
37240Sstevel@tonic-gate }
37250Sstevel@tonic-gate
37260Sstevel@tonic-gate buf = kmem_zalloc(size, KM_SLEEP);
37270Sstevel@tonic-gate php = (prpageheader_t *)buf;
37280Sstevel@tonic-gate pmp = (prasmap_t *)(buf + sizeof (prpageheader_t));
37290Sstevel@tonic-gate
37300Sstevel@tonic-gate hrt2ts(gethrtime(), &php->pr_tstamp);
37310Sstevel@tonic-gate php->pr_nmap = 0;
37320Sstevel@tonic-gate php->pr_npage = 0;
37330Sstevel@tonic-gate do {
37340Sstevel@tonic-gate caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
37350Sstevel@tonic-gate caddr_t saddr, naddr;
37360Sstevel@tonic-gate void *tmp = NULL;
37370Sstevel@tonic-gate
37380Sstevel@tonic-gate for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
37390Sstevel@tonic-gate size_t len;
37400Sstevel@tonic-gate size_t npage;
37410Sstevel@tonic-gate uint_t prot;
37420Sstevel@tonic-gate uintptr_t next;
37430Sstevel@tonic-gate
37440Sstevel@tonic-gate prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
37450Sstevel@tonic-gate if ((len = naddr - saddr) == 0)
37460Sstevel@tonic-gate continue;
37470Sstevel@tonic-gate npage = len / PAGESIZE;
37480Sstevel@tonic-gate next = (uintptr_t)(pmp + 1) + roundlong(npage);
37490Sstevel@tonic-gate /*
37500Sstevel@tonic-gate * It's possible that the address space can change
37510Sstevel@tonic-gate * subtlely even though we're holding as->a_lock
37520Sstevel@tonic-gate * due to the nondeterminism of page_exists() in
37530Sstevel@tonic-gate * the presence of asychronously flushed pages or
37540Sstevel@tonic-gate * mapped files whose sizes are changing.
37550Sstevel@tonic-gate * page_exists() may be called indirectly from
37560Sstevel@tonic-gate * pr_getprot() by a SEGOP_INCORE() routine.
37570Sstevel@tonic-gate * If this happens we need to make sure we don't
37580Sstevel@tonic-gate * overrun the buffer whose size we computed based
37590Sstevel@tonic-gate * on the initial iteration through the segments.
37600Sstevel@tonic-gate * Once we've detected an overflow, we need to clean
37610Sstevel@tonic-gate * up the temporary memory allocated in pr_getprot()
37620Sstevel@tonic-gate * and retry. If there's a pending signal, we return
37630Sstevel@tonic-gate * EINTR so that this thread can be dislodged if
37640Sstevel@tonic-gate * a latent bug causes us to spin indefinitely.
37650Sstevel@tonic-gate */
37660Sstevel@tonic-gate if (next > (uintptr_t)buf + size) {
37670Sstevel@tonic-gate pr_getprot_done(&tmp);
37680Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
37690Sstevel@tonic-gate
37700Sstevel@tonic-gate kmem_free(buf, size);
37710Sstevel@tonic-gate
37720Sstevel@tonic-gate if (ISSIG(curthread, JUSTLOOKING))
37730Sstevel@tonic-gate return (EINTR);
37740Sstevel@tonic-gate
37750Sstevel@tonic-gate goto again;
37760Sstevel@tonic-gate }
37770Sstevel@tonic-gate
37780Sstevel@tonic-gate php->pr_nmap++;
37790Sstevel@tonic-gate php->pr_npage += npage;
37800Sstevel@tonic-gate pmp->pr_vaddr = saddr;
37810Sstevel@tonic-gate pmp->pr_npage = npage;
37820Sstevel@tonic-gate pmp->pr_off = SEGOP_GETOFFSET(seg, saddr);
37830Sstevel@tonic-gate pmp->pr_mflags = 0;
37840Sstevel@tonic-gate if (prot & PROT_READ)
37850Sstevel@tonic-gate pmp->pr_mflags |= MA_READ;
37860Sstevel@tonic-gate if (prot & PROT_WRITE)
37870Sstevel@tonic-gate pmp->pr_mflags |= MA_WRITE;
37880Sstevel@tonic-gate if (prot & PROT_EXEC)
37890Sstevel@tonic-gate pmp->pr_mflags |= MA_EXEC;
37900Sstevel@tonic-gate if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
37910Sstevel@tonic-gate pmp->pr_mflags |= MA_SHARED;
37920Sstevel@tonic-gate pmp->pr_pagesize = PAGESIZE;
37930Sstevel@tonic-gate hat_getstat(as, saddr, len, hatid,
37940Sstevel@tonic-gate (char *)(pmp + 1), HAT_SYNC_ZERORM);
37950Sstevel@tonic-gate pmp = (prasmap_t *)next;
37960Sstevel@tonic-gate }
37970Sstevel@tonic-gate ASSERT(tmp == NULL);
37980Sstevel@tonic-gate } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
37990Sstevel@tonic-gate
38000Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
38010Sstevel@tonic-gate
38020Sstevel@tonic-gate ASSERT((uintptr_t)pmp <= (uintptr_t)buf + size);
38030Sstevel@tonic-gate error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
38040Sstevel@tonic-gate kmem_free(buf, size);
38050Sstevel@tonic-gate
38060Sstevel@tonic-gate return (error);
38070Sstevel@tonic-gate }
38080Sstevel@tonic-gate
38090Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
38100Sstevel@tonic-gate int
oprpdread32(struct as * as,uint_t hatid,struct uio * uiop)38110Sstevel@tonic-gate oprpdread32(struct as *as, uint_t hatid, struct uio *uiop)
38120Sstevel@tonic-gate {
38130Sstevel@tonic-gate caddr_t buf;
38140Sstevel@tonic-gate size_t size;
38150Sstevel@tonic-gate ioc_prpageheader32_t *php;
38160Sstevel@tonic-gate ioc_prasmap32_t *pmp;
38170Sstevel@tonic-gate struct seg *seg;
38180Sstevel@tonic-gate int error;
38190Sstevel@tonic-gate
38200Sstevel@tonic-gate again:
38210Sstevel@tonic-gate AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
38220Sstevel@tonic-gate
38230Sstevel@tonic-gate if ((seg = AS_SEGFIRST(as)) == NULL) {
38240Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
38250Sstevel@tonic-gate return (0);
38260Sstevel@tonic-gate }
38270Sstevel@tonic-gate size = oprpdsize32(as);
38280Sstevel@tonic-gate if (uiop->uio_resid < size) {
38290Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
38300Sstevel@tonic-gate return (E2BIG);
38310Sstevel@tonic-gate }
38320Sstevel@tonic-gate
38330Sstevel@tonic-gate buf = kmem_zalloc(size, KM_SLEEP);
38340Sstevel@tonic-gate php = (ioc_prpageheader32_t *)buf;
38350Sstevel@tonic-gate pmp = (ioc_prasmap32_t *)(buf + sizeof (ioc_prpageheader32_t));
38360Sstevel@tonic-gate
38370Sstevel@tonic-gate hrt2ts32(gethrtime(), &php->pr_tstamp);
38380Sstevel@tonic-gate php->pr_nmap = 0;
38390Sstevel@tonic-gate php->pr_npage = 0;
38400Sstevel@tonic-gate do {
38410Sstevel@tonic-gate caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
38420Sstevel@tonic-gate caddr_t saddr, naddr;
38430Sstevel@tonic-gate void *tmp = NULL;
38440Sstevel@tonic-gate
38450Sstevel@tonic-gate for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
38460Sstevel@tonic-gate size_t len;
38470Sstevel@tonic-gate size_t npage;
38480Sstevel@tonic-gate uint_t prot;
38490Sstevel@tonic-gate uintptr_t next;
38500Sstevel@tonic-gate
38510Sstevel@tonic-gate prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
38520Sstevel@tonic-gate if ((len = naddr - saddr) == 0)
38530Sstevel@tonic-gate continue;
38540Sstevel@tonic-gate npage = len / PAGESIZE;
38550Sstevel@tonic-gate next = (uintptr_t)(pmp + 1) + round4(npage);
38560Sstevel@tonic-gate /*
38570Sstevel@tonic-gate * It's possible that the address space can change
38580Sstevel@tonic-gate * subtlely even though we're holding as->a_lock
38590Sstevel@tonic-gate * due to the nondeterminism of page_exists() in
38600Sstevel@tonic-gate * the presence of asychronously flushed pages or
38610Sstevel@tonic-gate * mapped files whose sizes are changing.
38620Sstevel@tonic-gate * page_exists() may be called indirectly from
38630Sstevel@tonic-gate * pr_getprot() by a SEGOP_INCORE() routine.
38640Sstevel@tonic-gate * If this happens we need to make sure we don't
38650Sstevel@tonic-gate * overrun the buffer whose size we computed based
38660Sstevel@tonic-gate * on the initial iteration through the segments.
38670Sstevel@tonic-gate * Once we've detected an overflow, we need to clean
38680Sstevel@tonic-gate * up the temporary memory allocated in pr_getprot()
38690Sstevel@tonic-gate * and retry. If there's a pending signal, we return
38700Sstevel@tonic-gate * EINTR so that this thread can be dislodged if
38710Sstevel@tonic-gate * a latent bug causes us to spin indefinitely.
38720Sstevel@tonic-gate */
38730Sstevel@tonic-gate if (next > (uintptr_t)buf + size) {
38740Sstevel@tonic-gate pr_getprot_done(&tmp);
38750Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
38760Sstevel@tonic-gate
38770Sstevel@tonic-gate kmem_free(buf, size);
38780Sstevel@tonic-gate
38790Sstevel@tonic-gate if (ISSIG(curthread, JUSTLOOKING))
38800Sstevel@tonic-gate return (EINTR);
38810Sstevel@tonic-gate
38820Sstevel@tonic-gate goto again;
38830Sstevel@tonic-gate }
38840Sstevel@tonic-gate
38850Sstevel@tonic-gate php->pr_nmap++;
38860Sstevel@tonic-gate php->pr_npage += npage;
38870Sstevel@tonic-gate pmp->pr_vaddr = (uint32_t)(uintptr_t)saddr;
38880Sstevel@tonic-gate pmp->pr_npage = (uint32_t)npage;
38890Sstevel@tonic-gate pmp->pr_off = (int32_t)SEGOP_GETOFFSET(seg, saddr);
38900Sstevel@tonic-gate pmp->pr_mflags = 0;
38910Sstevel@tonic-gate if (prot & PROT_READ)
38920Sstevel@tonic-gate pmp->pr_mflags |= MA_READ;
38930Sstevel@tonic-gate if (prot & PROT_WRITE)
38940Sstevel@tonic-gate pmp->pr_mflags |= MA_WRITE;
38950Sstevel@tonic-gate if (prot & PROT_EXEC)
38960Sstevel@tonic-gate pmp->pr_mflags |= MA_EXEC;
38970Sstevel@tonic-gate if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
38980Sstevel@tonic-gate pmp->pr_mflags |= MA_SHARED;
38990Sstevel@tonic-gate pmp->pr_pagesize = PAGESIZE;
39000Sstevel@tonic-gate hat_getstat(as, saddr, len, hatid,
39010Sstevel@tonic-gate (char *)(pmp + 1), HAT_SYNC_ZERORM);
39020Sstevel@tonic-gate pmp = (ioc_prasmap32_t *)next;
39030Sstevel@tonic-gate }
39040Sstevel@tonic-gate ASSERT(tmp == NULL);
39050Sstevel@tonic-gate } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
39060Sstevel@tonic-gate
39070Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
39080Sstevel@tonic-gate
39090Sstevel@tonic-gate ASSERT((uintptr_t)pmp == (uintptr_t)buf + size);
39100Sstevel@tonic-gate error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
39110Sstevel@tonic-gate kmem_free(buf, size);
39120Sstevel@tonic-gate
39130Sstevel@tonic-gate return (error);
39140Sstevel@tonic-gate }
39150Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
39160Sstevel@tonic-gate
39175331Samw /*ARGSUSED*/
39180Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
39190Sstevel@tonic-gate int
prioctl(struct vnode * vp,int cmd,intptr_t arg,int flag,cred_t * cr,int * rvalp,caller_context_t * ct)39205331Samw prioctl(
39215331Samw struct vnode *vp,
39225331Samw int cmd,
39235331Samw intptr_t arg,
39245331Samw int flag,
39255331Samw cred_t *cr,
39265331Samw int *rvalp,
39275331Samw caller_context_t *ct)
39280Sstevel@tonic-gate {
39290Sstevel@tonic-gate switch (curproc->p_model) {
39300Sstevel@tonic-gate case DATAMODEL_ILP32:
39315331Samw return (prioctl32(vp, cmd, arg, flag, cr, rvalp, ct));
39320Sstevel@tonic-gate case DATAMODEL_LP64:
39335331Samw return (prioctl64(vp, cmd, arg, flag, cr, rvalp, ct));
39340Sstevel@tonic-gate default:
39350Sstevel@tonic-gate return (ENOSYS);
39360Sstevel@tonic-gate }
39370Sstevel@tonic-gate }
39380Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
3939