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