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