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