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