xref: /illumos-gate/usr/src/uts/common/fs/proc/prsubr.c (revision 19ee9cd1f5161e227951200cab5ecbff45fd5d71)
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 (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
25  * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
26  */
27 
28 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
29 /*	  All Rights Reserved	*/
30 
31 #include <sys/types.h>
32 #include <sys/t_lock.h>
33 #include <sys/param.h>
34 #include <sys/cmn_err.h>
35 #include <sys/cred.h>
36 #include <sys/priv.h>
37 #include <sys/debug.h>
38 #include <sys/errno.h>
39 #include <sys/inline.h>
40 #include <sys/kmem.h>
41 #include <sys/mman.h>
42 #include <sys/proc.h>
43 #include <sys/brand.h>
44 #include <sys/sobject.h>
45 #include <sys/sysmacros.h>
46 #include <sys/systm.h>
47 #include <sys/uio.h>
48 #include <sys/var.h>
49 #include <sys/vfs.h>
50 #include <sys/vnode.h>
51 #include <sys/session.h>
52 #include <sys/pcb.h>
53 #include <sys/signal.h>
54 #include <sys/user.h>
55 #include <sys/disp.h>
56 #include <sys/class.h>
57 #include <sys/ts.h>
58 #include <sys/bitmap.h>
59 #include <sys/poll.h>
60 #include <sys/shm_impl.h>
61 #include <sys/fault.h>
62 #include <sys/syscall.h>
63 #include <sys/procfs.h>
64 #include <sys/processor.h>
65 #include <sys/cpuvar.h>
66 #include <sys/copyops.h>
67 #include <sys/time.h>
68 #include <sys/msacct.h>
69 #include <sys/flock_impl.h>
70 #include <sys/stropts.h>
71 #include <sys/strsubr.h>
72 #include <sys/pathname.h>
73 #include <sys/mode.h>
74 #include <sys/socketvar.h>
75 #include <sys/autoconf.h>
76 #include <sys/dtrace.h>
77 #include <sys/timod.h>
78 #include <netinet/udp.h>
79 #include <netinet/tcp.h>
80 #include <inet/cc.h>
81 #include <vm/as.h>
82 #include <vm/rm.h>
83 #include <vm/seg.h>
84 #include <vm/seg_vn.h>
85 #include <vm/seg_dev.h>
86 #include <vm/seg_spt.h>
87 #include <vm/page.h>
88 #include <sys/vmparam.h>
89 #include <sys/swap.h>
90 #include <fs/proc/prdata.h>
91 #include <sys/task.h>
92 #include <sys/project.h>
93 #include <sys/contract_impl.h>
94 #include <sys/contract/process.h>
95 #include <sys/contract/process_impl.h>
96 #include <sys/schedctl.h>
97 #include <sys/pool.h>
98 #include <sys/zone.h>
99 #include <sys/atomic.h>
100 #include <sys/sdt.h>
101 
102 #define	MAX_ITERS_SPIN	5
103 
104 typedef struct prpagev {
105 	uint_t *pg_protv;	/* vector of page permissions */
106 	char *pg_incore;	/* vector of incore flags */
107 	size_t pg_npages;	/* number of pages in protv and incore */
108 	ulong_t pg_pnbase;	/* pn within segment of first protv element */
109 } prpagev_t;
110 
111 size_t pagev_lim = 256 * 1024;	/* limit on number of pages in prpagev_t */
112 
113 extern struct seg_ops segdev_ops;	/* needs a header file */
114 extern struct seg_ops segspt_shmops;	/* needs a header file */
115 
116 static	int	set_watched_page(proc_t *, caddr_t, caddr_t, ulong_t, ulong_t);
117 static	void	clear_watched_page(proc_t *, caddr_t, caddr_t, ulong_t);
118 
119 /*
120  * Choose an lwp from the complete set of lwps for the process.
121  * This is called for any operation applied to the process
122  * file descriptor that requires an lwp to operate upon.
123  *
124  * Returns a pointer to the thread for the selected LWP,
125  * and with the dispatcher lock held for the thread.
126  *
127  * The algorithm for choosing an lwp is critical for /proc semantics;
128  * don't touch this code unless you know all of the implications.
129  */
130 kthread_t *
131 prchoose(proc_t *p)
132 {
133 	kthread_t *t;
134 	kthread_t *t_onproc = NULL;	/* running on processor */
135 	kthread_t *t_run = NULL;	/* runnable, on disp queue */
136 	kthread_t *t_sleep = NULL;	/* sleeping */
137 	kthread_t *t_hold = NULL;	/* sleeping, performing hold */
138 	kthread_t *t_susp = NULL;	/* suspended stop */
139 	kthread_t *t_jstop = NULL;	/* jobcontrol stop, w/o directed stop */
140 	kthread_t *t_jdstop = NULL;	/* jobcontrol stop with directed stop */
141 	kthread_t *t_req = NULL;	/* requested stop */
142 	kthread_t *t_istop = NULL;	/* event-of-interest stop */
143 	kthread_t *t_dtrace = NULL;	/* DTrace stop */
144 
145 	ASSERT(MUTEX_HELD(&p->p_lock));
146 
147 	/*
148 	 * If the agent lwp exists, it takes precedence over all others.
149 	 */
150 	if ((t = p->p_agenttp) != NULL) {
151 		thread_lock(t);
152 		return (t);
153 	}
154 
155 	if ((t = p->p_tlist) == NULL)	/* start at the head of the list */
156 		return (t);
157 	do {		/* for eacn lwp in the process */
158 		if (VSTOPPED(t)) {	/* virtually stopped */
159 			if (t_req == NULL)
160 				t_req = t;
161 			continue;
162 		}
163 
164 		thread_lock(t);		/* make sure thread is in good state */
165 		switch (t->t_state) {
166 		default:
167 			panic("prchoose: bad thread state %d, thread 0x%p",
168 			    t->t_state, (void *)t);
169 			/*NOTREACHED*/
170 		case TS_SLEEP:
171 			/* this is filthy */
172 			if (t->t_wchan == (caddr_t)&p->p_holdlwps &&
173 			    t->t_wchan0 == NULL) {
174 				if (t_hold == NULL)
175 					t_hold = t;
176 			} else {
177 				if (t_sleep == NULL)
178 					t_sleep = t;
179 			}
180 			break;
181 		case TS_RUN:
182 		case TS_WAIT:
183 			if (t_run == NULL)
184 				t_run = t;
185 			break;
186 		case TS_ONPROC:
187 			if (t_onproc == NULL)
188 				t_onproc = t;
189 			break;
190 		case TS_ZOMB:		/* last possible choice */
191 			break;
192 		case TS_STOPPED:
193 			switch (t->t_whystop) {
194 			case PR_SUSPENDED:
195 				if (t_susp == NULL)
196 					t_susp = t;
197 				break;
198 			case PR_JOBCONTROL:
199 				if (t->t_proc_flag & TP_PRSTOP) {
200 					if (t_jdstop == NULL)
201 						t_jdstop = t;
202 				} else {
203 					if (t_jstop == NULL)
204 						t_jstop = t;
205 				}
206 				break;
207 			case PR_REQUESTED:
208 				if (t->t_dtrace_stop && t_dtrace == NULL)
209 					t_dtrace = t;
210 				else if (t_req == NULL)
211 					t_req = t;
212 				break;
213 			case PR_SYSENTRY:
214 			case PR_SYSEXIT:
215 			case PR_SIGNALLED:
216 			case PR_FAULTED:
217 				/*
218 				 * Make an lwp calling exit() be the
219 				 * last lwp seen in the process.
220 				 */
221 				if (t_istop == NULL ||
222 				    (t_istop->t_whystop == PR_SYSENTRY &&
223 				    t_istop->t_whatstop == SYS_exit))
224 					t_istop = t;
225 				break;
226 			case PR_CHECKPOINT:	/* can't happen? */
227 				break;
228 			default:
229 				panic("prchoose: bad t_whystop %d, thread 0x%p",
230 				    t->t_whystop, (void *)t);
231 				/*NOTREACHED*/
232 			}
233 			break;
234 		}
235 		thread_unlock(t);
236 	} while ((t = t->t_forw) != p->p_tlist);
237 
238 	if (t_onproc)
239 		t = t_onproc;
240 	else if (t_run)
241 		t = t_run;
242 	else if (t_sleep)
243 		t = t_sleep;
244 	else if (t_jstop)
245 		t = t_jstop;
246 	else if (t_jdstop)
247 		t = t_jdstop;
248 	else if (t_istop)
249 		t = t_istop;
250 	else if (t_dtrace)
251 		t = t_dtrace;
252 	else if (t_req)
253 		t = t_req;
254 	else if (t_hold)
255 		t = t_hold;
256 	else if (t_susp)
257 		t = t_susp;
258 	else			/* TS_ZOMB */
259 		t = p->p_tlist;
260 
261 	if (t != NULL)
262 		thread_lock(t);
263 	return (t);
264 }
265 
266 /*
267  * Wakeup anyone sleeping on the /proc vnode for the process/lwp to stop.
268  * Also call pollwakeup() if any lwps are waiting in poll() for POLLPRI
269  * on the /proc file descriptor.  Called from stop() when a traced
270  * process stops on an event of interest.  Also called from exit()
271  * and prinvalidate() to indicate POLLHUP and POLLERR respectively.
272  */
273 void
274 prnotify(struct vnode *vp)
275 {
276 	prcommon_t *pcp = VTOP(vp)->pr_common;
277 
278 	mutex_enter(&pcp->prc_mutex);
279 	cv_broadcast(&pcp->prc_wait);
280 	mutex_exit(&pcp->prc_mutex);
281 	if (pcp->prc_flags & PRC_POLL) {
282 		/*
283 		 * We call pollwakeup() with POLLHUP to ensure that
284 		 * the pollers are awakened even if they are polling
285 		 * for nothing (i.e., waiting for the process to exit).
286 		 * This enables the use of the PRC_POLL flag for optimization
287 		 * (we can turn off PRC_POLL only if we know no pollers remain).
288 		 */
289 		pcp->prc_flags &= ~PRC_POLL;
290 		pollwakeup(&pcp->prc_pollhead, POLLHUP);
291 	}
292 }
293 
294 /* called immediately below, in prfree() */
295 static void
296 prfreenotify(vnode_t *vp)
297 {
298 	prnode_t *pnp;
299 	prcommon_t *pcp;
300 
301 	while (vp != NULL) {
302 		pnp = VTOP(vp);
303 		pcp = pnp->pr_common;
304 		ASSERT(pcp->prc_thread == NULL);
305 		pcp->prc_proc = NULL;
306 		/*
307 		 * We can't call prnotify() here because we are holding
308 		 * pidlock.  We assert that there is no need to.
309 		 */
310 		mutex_enter(&pcp->prc_mutex);
311 		cv_broadcast(&pcp->prc_wait);
312 		mutex_exit(&pcp->prc_mutex);
313 		ASSERT(!(pcp->prc_flags & PRC_POLL));
314 
315 		vp = pnp->pr_next;
316 		pnp->pr_next = NULL;
317 	}
318 }
319 
320 /*
321  * Called from a hook in freeproc() when a traced process is removed
322  * from the process table.  The proc-table pointers of all associated
323  * /proc vnodes are cleared to indicate that the process has gone away.
324  */
325 void
326 prfree(proc_t *p)
327 {
328 	uint_t slot = p->p_slot;
329 
330 	ASSERT(MUTEX_HELD(&pidlock));
331 
332 	/*
333 	 * Block the process against /proc so it can be freed.
334 	 * It cannot be freed while locked by some controlling process.
335 	 * Lock ordering:
336 	 *	pidlock -> pr_pidlock -> p->p_lock -> pcp->prc_mutex
337 	 */
338 	mutex_enter(&pr_pidlock);	/* protects pcp->prc_proc */
339 	mutex_enter(&p->p_lock);
340 	while (p->p_proc_flag & P_PR_LOCK) {
341 		mutex_exit(&pr_pidlock);
342 		cv_wait(&pr_pid_cv[slot], &p->p_lock);
343 		mutex_exit(&p->p_lock);
344 		mutex_enter(&pr_pidlock);
345 		mutex_enter(&p->p_lock);
346 	}
347 
348 	ASSERT(p->p_tlist == NULL);
349 
350 	prfreenotify(p->p_plist);
351 	p->p_plist = NULL;
352 
353 	prfreenotify(p->p_trace);
354 	p->p_trace = NULL;
355 
356 	/*
357 	 * We broadcast to wake up everyone waiting for this process.
358 	 * No one can reach this process from this point on.
359 	 */
360 	cv_broadcast(&pr_pid_cv[slot]);
361 
362 	mutex_exit(&p->p_lock);
363 	mutex_exit(&pr_pidlock);
364 }
365 
366 /*
367  * Called from a hook in exit() when a traced process is becoming a zombie.
368  */
369 void
370 prexit(proc_t *p)
371 {
372 	ASSERT(MUTEX_HELD(&p->p_lock));
373 
374 	if (pr_watch_active(p)) {
375 		pr_free_watchpoints(p);
376 		watch_disable(curthread);
377 	}
378 	/* pr_free_watched_pages() is called in exit(), after dropping p_lock */
379 	if (p->p_trace) {
380 		VTOP(p->p_trace)->pr_common->prc_flags |= PRC_DESTROY;
381 		prnotify(p->p_trace);
382 	}
383 	cv_broadcast(&pr_pid_cv[p->p_slot]);	/* pauselwps() */
384 }
385 
386 /*
387  * Called when a thread calls lwp_exit().
388  */
389 void
390 prlwpexit(kthread_t *t)
391 {
392 	vnode_t *vp;
393 	prnode_t *pnp;
394 	prcommon_t *pcp;
395 	proc_t *p = ttoproc(t);
396 	lwpent_t *lep = p->p_lwpdir[t->t_dslot].ld_entry;
397 
398 	ASSERT(t == curthread);
399 	ASSERT(MUTEX_HELD(&p->p_lock));
400 
401 	/*
402 	 * The process must be blocked against /proc to do this safely.
403 	 * The lwp must not disappear while the process is marked P_PR_LOCK.
404 	 * It is the caller's responsibility to have called prbarrier(p).
405 	 */
406 	ASSERT(!(p->p_proc_flag & P_PR_LOCK));
407 
408 	for (vp = p->p_plist; vp != NULL; vp = pnp->pr_next) {
409 		pnp = VTOP(vp);
410 		pcp = pnp->pr_common;
411 		if (pcp->prc_thread == t) {
412 			pcp->prc_thread = NULL;
413 			pcp->prc_flags |= PRC_DESTROY;
414 		}
415 	}
416 
417 	for (vp = lep->le_trace; vp != NULL; vp = pnp->pr_next) {
418 		pnp = VTOP(vp);
419 		pcp = pnp->pr_common;
420 		pcp->prc_thread = NULL;
421 		pcp->prc_flags |= PRC_DESTROY;
422 		prnotify(vp);
423 	}
424 
425 	if (p->p_trace)
426 		prnotify(p->p_trace);
427 }
428 
429 /*
430  * Called when a zombie thread is joined or when a
431  * detached lwp exits.  Called from lwp_hash_out().
432  */
433 void
434 prlwpfree(proc_t *p, lwpent_t *lep)
435 {
436 	vnode_t *vp;
437 	prnode_t *pnp;
438 	prcommon_t *pcp;
439 
440 	ASSERT(MUTEX_HELD(&p->p_lock));
441 
442 	/*
443 	 * The process must be blocked against /proc to do this safely.
444 	 * The lwp must not disappear while the process is marked P_PR_LOCK.
445 	 * It is the caller's responsibility to have called prbarrier(p).
446 	 */
447 	ASSERT(!(p->p_proc_flag & P_PR_LOCK));
448 
449 	vp = lep->le_trace;
450 	lep->le_trace = NULL;
451 	while (vp) {
452 		prnotify(vp);
453 		pnp = VTOP(vp);
454 		pcp = pnp->pr_common;
455 		ASSERT(pcp->prc_thread == NULL &&
456 		    (pcp->prc_flags & PRC_DESTROY));
457 		pcp->prc_tslot = -1;
458 		vp = pnp->pr_next;
459 		pnp->pr_next = NULL;
460 	}
461 
462 	if (p->p_trace)
463 		prnotify(p->p_trace);
464 }
465 
466 /*
467  * Called from a hook in exec() when a thread starts exec().
468  */
469 void
470 prexecstart(void)
471 {
472 	proc_t *p = ttoproc(curthread);
473 	klwp_t *lwp = ttolwp(curthread);
474 
475 	/*
476 	 * The P_PR_EXEC flag blocks /proc operations for
477 	 * the duration of the exec().
478 	 * We can't start exec() while the process is
479 	 * locked by /proc, so we call prbarrier().
480 	 * lwp_nostop keeps the process from being stopped
481 	 * via job control for the duration of the exec().
482 	 */
483 
484 	ASSERT(MUTEX_HELD(&p->p_lock));
485 	prbarrier(p);
486 	lwp->lwp_nostop++;
487 	p->p_proc_flag |= P_PR_EXEC;
488 }
489 
490 /*
491  * Called from a hook in exec() when a thread finishes exec().
492  * The thread may or may not have succeeded.  Some other thread
493  * may have beat it to the punch.
494  */
495 void
496 prexecend(void)
497 {
498 	proc_t *p = ttoproc(curthread);
499 	klwp_t *lwp = ttolwp(curthread);
500 	vnode_t *vp;
501 	prnode_t *pnp;
502 	prcommon_t *pcp;
503 	model_t model = p->p_model;
504 	id_t tid = curthread->t_tid;
505 	int tslot = curthread->t_dslot;
506 
507 	ASSERT(MUTEX_HELD(&p->p_lock));
508 
509 	lwp->lwp_nostop--;
510 	if (p->p_flag & SEXITLWPS) {
511 		/*
512 		 * We are on our way to exiting because some
513 		 * other thread beat us in the race to exec().
514 		 * Don't clear the P_PR_EXEC flag in this case.
515 		 */
516 		return;
517 	}
518 
519 	/*
520 	 * Wake up anyone waiting in /proc for the process to complete exec().
521 	 */
522 	p->p_proc_flag &= ~P_PR_EXEC;
523 	if ((vp = p->p_trace) != NULL) {
524 		pcp = VTOP(vp)->pr_common;
525 		mutex_enter(&pcp->prc_mutex);
526 		cv_broadcast(&pcp->prc_wait);
527 		mutex_exit(&pcp->prc_mutex);
528 		for (; vp != NULL; vp = pnp->pr_next) {
529 			pnp = VTOP(vp);
530 			pnp->pr_common->prc_datamodel = model;
531 		}
532 	}
533 	if ((vp = p->p_lwpdir[tslot].ld_entry->le_trace) != NULL) {
534 		/*
535 		 * We dealt with the process common above.
536 		 */
537 		ASSERT(p->p_trace != NULL);
538 		pcp = VTOP(vp)->pr_common;
539 		mutex_enter(&pcp->prc_mutex);
540 		cv_broadcast(&pcp->prc_wait);
541 		mutex_exit(&pcp->prc_mutex);
542 		for (; vp != NULL; vp = pnp->pr_next) {
543 			pnp = VTOP(vp);
544 			pcp = pnp->pr_common;
545 			pcp->prc_datamodel = model;
546 			pcp->prc_tid = tid;
547 			pcp->prc_tslot = tslot;
548 		}
549 	}
550 }
551 
552 /*
553  * Called from a hook in relvm() just before freeing the address space.
554  * We free all the watched areas now.
555  */
556 void
557 prrelvm(void)
558 {
559 	proc_t *p = ttoproc(curthread);
560 
561 	mutex_enter(&p->p_lock);
562 	prbarrier(p);	/* block all other /proc operations */
563 	if (pr_watch_active(p)) {
564 		pr_free_watchpoints(p);
565 		watch_disable(curthread);
566 	}
567 	mutex_exit(&p->p_lock);
568 	pr_free_watched_pages(p);
569 }
570 
571 /*
572  * Called from hooks in exec-related code when a traced process
573  * attempts to exec(2) a setuid/setgid program or an unreadable
574  * file.  Rather than fail the exec we invalidate the associated
575  * /proc vnodes so that subsequent attempts to use them will fail.
576  *
577  * All /proc vnodes, except directory vnodes, are retained on a linked
578  * list (rooted at p_plist in the process structure) until last close.
579  *
580  * A controlling process must re-open the /proc files in order to
581  * regain control.
582  */
583 void
584 prinvalidate(struct user *up)
585 {
586 	kthread_t *t = curthread;
587 	proc_t *p = ttoproc(t);
588 	vnode_t *vp;
589 	prnode_t *pnp;
590 	int writers = 0;
591 
592 	mutex_enter(&p->p_lock);
593 	prbarrier(p);	/* block all other /proc operations */
594 
595 	/*
596 	 * At this moment, there can be only one lwp in the process.
597 	 */
598 	ASSERT(p->p_lwpcnt == 1 && p->p_zombcnt == 0);
599 
600 	/*
601 	 * Invalidate any currently active /proc vnodes.
602 	 */
603 	for (vp = p->p_plist; vp != NULL; vp = pnp->pr_next) {
604 		pnp = VTOP(vp);
605 		switch (pnp->pr_type) {
606 		case PR_PSINFO:		/* these files can read by anyone */
607 		case PR_LPSINFO:
608 		case PR_LWPSINFO:
609 		case PR_LWPDIR:
610 		case PR_LWPIDDIR:
611 		case PR_USAGE:
612 		case PR_LUSAGE:
613 		case PR_LWPUSAGE:
614 			break;
615 		default:
616 			pnp->pr_flags |= PR_INVAL;
617 			break;
618 		}
619 	}
620 	/*
621 	 * Wake up anyone waiting for the process or lwp.
622 	 * p->p_trace is guaranteed to be non-NULL if there
623 	 * are any open /proc files for this process.
624 	 */
625 	if ((vp = p->p_trace) != NULL) {
626 		prcommon_t *pcp = VTOP(vp)->pr_pcommon;
627 
628 		prnotify(vp);
629 		/*
630 		 * Are there any writers?
631 		 */
632 		if ((writers = pcp->prc_writers) != 0) {
633 			/*
634 			 * Clear the exclusive open flag (old /proc interface).
635 			 * Set prc_selfopens equal to prc_writers so that
636 			 * the next O_EXCL|O_WRITE open will succeed
637 			 * even with existing (though invalid) writers.
638 			 * prclose() must decrement prc_selfopens when
639 			 * the invalid files are closed.
640 			 */
641 			pcp->prc_flags &= ~PRC_EXCL;
642 			ASSERT(pcp->prc_selfopens <= writers);
643 			pcp->prc_selfopens = writers;
644 		}
645 	}
646 	vp = p->p_lwpdir[t->t_dslot].ld_entry->le_trace;
647 	while (vp != NULL) {
648 		/*
649 		 * We should not invalidate the lwpiddir vnodes,
650 		 * but the necessities of maintaining the old
651 		 * ioctl()-based version of /proc require it.
652 		 */
653 		pnp = VTOP(vp);
654 		pnp->pr_flags |= PR_INVAL;
655 		prnotify(vp);
656 		vp = pnp->pr_next;
657 	}
658 
659 	/*
660 	 * If any tracing flags are in effect and any vnodes are open for
661 	 * writing then set the requested-stop and run-on-last-close flags.
662 	 * Otherwise, clear all tracing flags.
663 	 */
664 	t->t_proc_flag &= ~TP_PAUSE;
665 	if ((p->p_proc_flag & P_PR_TRACE) && writers) {
666 		t->t_proc_flag |= TP_PRSTOP;
667 		aston(t);		/* so ISSIG will see the flag */
668 		p->p_proc_flag |= P_PR_RUNLCL;
669 	} else {
670 		premptyset(&up->u_entrymask);		/* syscalls */
671 		premptyset(&up->u_exitmask);
672 		up->u_systrap = 0;
673 		premptyset(&p->p_sigmask);		/* signals */
674 		premptyset(&p->p_fltmask);		/* faults */
675 		t->t_proc_flag &= ~(TP_PRSTOP|TP_PRVSTOP|TP_STOPPING);
676 		p->p_proc_flag &= ~(P_PR_RUNLCL|P_PR_KILLCL|P_PR_TRACE);
677 		prnostep(ttolwp(t));
678 	}
679 
680 	mutex_exit(&p->p_lock);
681 }
682 
683 /*
684  * Acquire the controlled process's p_lock and mark it P_PR_LOCK.
685  * Return with pr_pidlock held in all cases.
686  * Return with p_lock held if the the process still exists.
687  * Return value is the process pointer if the process still exists, else NULL.
688  * If we lock the process, give ourself kernel priority to avoid deadlocks;
689  * this is undone in prunlock().
690  */
691 proc_t *
692 pr_p_lock(prnode_t *pnp)
693 {
694 	proc_t *p;
695 	prcommon_t *pcp;
696 
697 	mutex_enter(&pr_pidlock);
698 	if ((pcp = pnp->pr_pcommon) == NULL || (p = pcp->prc_proc) == NULL)
699 		return (NULL);
700 	mutex_enter(&p->p_lock);
701 	while (p->p_proc_flag & P_PR_LOCK) {
702 		/*
703 		 * This cv/mutex pair is persistent even if
704 		 * the process disappears while we sleep.
705 		 */
706 		kcondvar_t *cv = &pr_pid_cv[p->p_slot];
707 		kmutex_t *mp = &p->p_lock;
708 
709 		mutex_exit(&pr_pidlock);
710 		cv_wait(cv, mp);
711 		mutex_exit(mp);
712 		mutex_enter(&pr_pidlock);
713 		if (pcp->prc_proc == NULL)
714 			return (NULL);
715 		ASSERT(p == pcp->prc_proc);
716 		mutex_enter(&p->p_lock);
717 	}
718 	p->p_proc_flag |= P_PR_LOCK;
719 	THREAD_KPRI_REQUEST();
720 	return (p);
721 }
722 
723 /*
724  * Lock the target process by setting P_PR_LOCK and grabbing p->p_lock.
725  * This prevents any lwp of the process from disappearing and
726  * blocks most operations that a process can perform on itself.
727  * Returns 0 on success, a non-zero error number on failure.
728  *
729  * 'zdisp' is ZYES or ZNO to indicate whether prlock() should succeed when
730  * the subject process is a zombie (ZYES) or fail for zombies (ZNO).
731  *
732  * error returns:
733  *	ENOENT: process or lwp has disappeared or process is exiting
734  *		(or has become a zombie and zdisp == ZNO).
735  *	EAGAIN: procfs vnode has become invalid.
736  *	EINTR:  signal arrived while waiting for exec to complete.
737  */
738 int
739 prlock(prnode_t *pnp, int zdisp)
740 {
741 	prcommon_t *pcp;
742 	proc_t *p;
743 
744 again:
745 	pcp = pnp->pr_common;
746 	p = pr_p_lock(pnp);
747 	mutex_exit(&pr_pidlock);
748 
749 	/*
750 	 * Return ENOENT immediately if there is no process.
751 	 */
752 	if (p == NULL)
753 		return (ENOENT);
754 
755 	ASSERT(p == pcp->prc_proc && p->p_stat != 0 && p->p_stat != SIDL);
756 
757 	/*
758 	 * Return ENOENT if process entered zombie state or is exiting
759 	 * and the 'zdisp' flag is set to ZNO indicating not to lock zombies.
760 	 */
761 	if (zdisp == ZNO &&
762 	    ((pcp->prc_flags & PRC_DESTROY) || (p->p_flag & SEXITING))) {
763 		prunlock(pnp);
764 		return (ENOENT);
765 	}
766 
767 	/*
768 	 * If lwp-specific, check to see if lwp has disappeared.
769 	 */
770 	if (pcp->prc_flags & PRC_LWP) {
771 		if ((zdisp == ZNO && (pcp->prc_flags & PRC_DESTROY)) ||
772 		    pcp->prc_tslot == -1) {
773 			prunlock(pnp);
774 			return (ENOENT);
775 		}
776 	}
777 
778 	/*
779 	 * Return EAGAIN if we have encountered a security violation.
780 	 * (The process exec'd a set-id or unreadable executable file.)
781 	 */
782 	if (pnp->pr_flags & PR_INVAL) {
783 		prunlock(pnp);
784 		return (EAGAIN);
785 	}
786 
787 	/*
788 	 * If process is undergoing an exec(), wait for
789 	 * completion and then start all over again.
790 	 */
791 	if (p->p_proc_flag & P_PR_EXEC) {
792 		pcp = pnp->pr_pcommon;	/* Put on the correct sleep queue */
793 		mutex_enter(&pcp->prc_mutex);
794 		prunlock(pnp);
795 		if (!cv_wait_sig(&pcp->prc_wait, &pcp->prc_mutex)) {
796 			mutex_exit(&pcp->prc_mutex);
797 			return (EINTR);
798 		}
799 		mutex_exit(&pcp->prc_mutex);
800 		goto again;
801 	}
802 
803 	/*
804 	 * We return holding p->p_lock.
805 	 */
806 	return (0);
807 }
808 
809 /*
810  * Undo prlock() and pr_p_lock().
811  * p->p_lock is still held; pr_pidlock is no longer held.
812  *
813  * prunmark() drops the P_PR_LOCK flag and wakes up another thread,
814  * if any, waiting for the flag to be dropped; it retains p->p_lock.
815  *
816  * prunlock() calls prunmark() and then drops p->p_lock.
817  */
818 void
819 prunmark(proc_t *p)
820 {
821 	ASSERT(p->p_proc_flag & P_PR_LOCK);
822 	ASSERT(MUTEX_HELD(&p->p_lock));
823 
824 	cv_signal(&pr_pid_cv[p->p_slot]);
825 	p->p_proc_flag &= ~P_PR_LOCK;
826 	THREAD_KPRI_RELEASE();
827 }
828 
829 void
830 prunlock(prnode_t *pnp)
831 {
832 	prcommon_t *pcp = pnp->pr_common;
833 	proc_t *p = pcp->prc_proc;
834 
835 	/*
836 	 * If we (or someone) gave it a SIGKILL, and it is not
837 	 * already a zombie, set it running unconditionally.
838 	 */
839 	if ((p->p_flag & SKILLED) &&
840 	    !(p->p_flag & SEXITING) &&
841 	    !(pcp->prc_flags & PRC_DESTROY) &&
842 	    !((pcp->prc_flags & PRC_LWP) && pcp->prc_tslot == -1))
843 		(void) pr_setrun(pnp, 0);
844 	prunmark(p);
845 	mutex_exit(&p->p_lock);
846 }
847 
848 /*
849  * Called while holding p->p_lock to delay until the process is unlocked.
850  * We enter holding p->p_lock; p->p_lock is dropped and reacquired.
851  * The process cannot become locked again until p->p_lock is dropped.
852  */
853 void
854 prbarrier(proc_t *p)
855 {
856 	ASSERT(MUTEX_HELD(&p->p_lock));
857 
858 	if (p->p_proc_flag & P_PR_LOCK) {
859 		/* The process is locked; delay until not locked */
860 		uint_t slot = p->p_slot;
861 
862 		while (p->p_proc_flag & P_PR_LOCK)
863 			cv_wait(&pr_pid_cv[slot], &p->p_lock);
864 		cv_signal(&pr_pid_cv[slot]);
865 	}
866 }
867 
868 /*
869  * Return process/lwp status.
870  * The u-block is mapped in by this routine and unmapped at the end.
871  */
872 void
873 prgetstatus(proc_t *p, pstatus_t *sp, zone_t *zp)
874 {
875 	kthread_t *t;
876 
877 	ASSERT(MUTEX_HELD(&p->p_lock));
878 
879 	t = prchoose(p);	/* returns locked thread */
880 	ASSERT(t != NULL);
881 	thread_unlock(t);
882 
883 	/* just bzero the process part, prgetlwpstatus() does the rest */
884 	bzero(sp, sizeof (pstatus_t) - sizeof (lwpstatus_t));
885 	sp->pr_nlwp = p->p_lwpcnt;
886 	sp->pr_nzomb = p->p_zombcnt;
887 	prassignset(&sp->pr_sigpend, &p->p_sig);
888 	sp->pr_brkbase = (uintptr_t)p->p_brkbase;
889 	sp->pr_brksize = p->p_brksize;
890 	sp->pr_stkbase = (uintptr_t)prgetstackbase(p);
891 	sp->pr_stksize = p->p_stksize;
892 	sp->pr_pid = p->p_pid;
893 	if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
894 	    (p->p_flag & SZONETOP)) {
895 		ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
896 		/*
897 		 * Inside local zones, fake zsched's pid as parent pids for
898 		 * processes which reference processes outside of the zone.
899 		 */
900 		sp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
901 	} else {
902 		sp->pr_ppid = p->p_ppid;
903 	}
904 	sp->pr_pgid  = p->p_pgrp;
905 	sp->pr_sid   = p->p_sessp->s_sid;
906 	sp->pr_taskid = p->p_task->tk_tkid;
907 	sp->pr_projid = p->p_task->tk_proj->kpj_id;
908 	sp->pr_zoneid = p->p_zone->zone_id;
909 	hrt2ts(mstate_aggr_state(p, LMS_USER), &sp->pr_utime);
910 	hrt2ts(mstate_aggr_state(p, LMS_SYSTEM), &sp->pr_stime);
911 	TICK_TO_TIMESTRUC(p->p_cutime, &sp->pr_cutime);
912 	TICK_TO_TIMESTRUC(p->p_cstime, &sp->pr_cstime);
913 	prassignset(&sp->pr_sigtrace, &p->p_sigmask);
914 	prassignset(&sp->pr_flttrace, &p->p_fltmask);
915 	prassignset(&sp->pr_sysentry, &PTOU(p)->u_entrymask);
916 	prassignset(&sp->pr_sysexit, &PTOU(p)->u_exitmask);
917 	switch (p->p_model) {
918 	case DATAMODEL_ILP32:
919 		sp->pr_dmodel = PR_MODEL_ILP32;
920 		break;
921 	case DATAMODEL_LP64:
922 		sp->pr_dmodel = PR_MODEL_LP64;
923 		break;
924 	}
925 	if (p->p_agenttp)
926 		sp->pr_agentid = p->p_agenttp->t_tid;
927 
928 	/* get the chosen lwp's status */
929 	prgetlwpstatus(t, &sp->pr_lwp, zp);
930 
931 	/* replicate the flags */
932 	sp->pr_flags = sp->pr_lwp.pr_flags;
933 }
934 
935 #ifdef _SYSCALL32_IMPL
936 void
937 prgetlwpstatus32(kthread_t *t, lwpstatus32_t *sp, zone_t *zp)
938 {
939 	proc_t *p = ttoproc(t);
940 	klwp_t *lwp = ttolwp(t);
941 	struct mstate *ms = &lwp->lwp_mstate;
942 	hrtime_t usr, sys;
943 	int flags;
944 	ulong_t instr;
945 
946 	ASSERT(MUTEX_HELD(&p->p_lock));
947 
948 	bzero(sp, sizeof (*sp));
949 	flags = 0L;
950 	if (t->t_state == TS_STOPPED) {
951 		flags |= PR_STOPPED;
952 		if ((t->t_schedflag & TS_PSTART) == 0)
953 			flags |= PR_ISTOP;
954 	} else if (VSTOPPED(t)) {
955 		flags |= PR_STOPPED|PR_ISTOP;
956 	}
957 	if (!(flags & PR_ISTOP) && (t->t_proc_flag & TP_PRSTOP))
958 		flags |= PR_DSTOP;
959 	if (lwp->lwp_asleep)
960 		flags |= PR_ASLEEP;
961 	if (t == p->p_agenttp)
962 		flags |= PR_AGENT;
963 	if (!(t->t_proc_flag & TP_TWAIT))
964 		flags |= PR_DETACH;
965 	if (t->t_proc_flag & TP_DAEMON)
966 		flags |= PR_DAEMON;
967 	if (p->p_proc_flag & P_PR_FORK)
968 		flags |= PR_FORK;
969 	if (p->p_proc_flag & P_PR_RUNLCL)
970 		flags |= PR_RLC;
971 	if (p->p_proc_flag & P_PR_KILLCL)
972 		flags |= PR_KLC;
973 	if (p->p_proc_flag & P_PR_ASYNC)
974 		flags |= PR_ASYNC;
975 	if (p->p_proc_flag & P_PR_BPTADJ)
976 		flags |= PR_BPTADJ;
977 	if (p->p_proc_flag & P_PR_PTRACE)
978 		flags |= PR_PTRACE;
979 	if (p->p_flag & SMSACCT)
980 		flags |= PR_MSACCT;
981 	if (p->p_flag & SMSFORK)
982 		flags |= PR_MSFORK;
983 	if (p->p_flag & SVFWAIT)
984 		flags |= PR_VFORKP;
985 	sp->pr_flags = flags;
986 	if (VSTOPPED(t)) {
987 		sp->pr_why   = PR_REQUESTED;
988 		sp->pr_what  = 0;
989 	} else {
990 		sp->pr_why   = t->t_whystop;
991 		sp->pr_what  = t->t_whatstop;
992 	}
993 	sp->pr_lwpid = t->t_tid;
994 	sp->pr_cursig  = lwp->lwp_cursig;
995 	prassignset(&sp->pr_lwppend, &t->t_sig);
996 	schedctl_finish_sigblock(t);
997 	prassignset(&sp->pr_lwphold, &t->t_hold);
998 	if (t->t_whystop == PR_FAULTED) {
999 		siginfo_kto32(&lwp->lwp_siginfo, &sp->pr_info);
1000 		if (t->t_whatstop == FLTPAGE)
1001 			sp->pr_info.si_addr =
1002 			    (caddr32_t)(uintptr_t)lwp->lwp_siginfo.si_addr;
1003 	} else if (lwp->lwp_curinfo)
1004 		siginfo_kto32(&lwp->lwp_curinfo->sq_info, &sp->pr_info);
1005 	if (SI_FROMUSER(&lwp->lwp_siginfo) && zp->zone_id != GLOBAL_ZONEID &&
1006 	    sp->pr_info.si_zoneid != zp->zone_id) {
1007 		sp->pr_info.si_pid = zp->zone_zsched->p_pid;
1008 		sp->pr_info.si_uid = 0;
1009 		sp->pr_info.si_ctid = -1;
1010 		sp->pr_info.si_zoneid = zp->zone_id;
1011 	}
1012 	sp->pr_altstack.ss_sp =
1013 	    (caddr32_t)(uintptr_t)lwp->lwp_sigaltstack.ss_sp;
1014 	sp->pr_altstack.ss_size = (size32_t)lwp->lwp_sigaltstack.ss_size;
1015 	sp->pr_altstack.ss_flags = (int32_t)lwp->lwp_sigaltstack.ss_flags;
1016 	prgetaction32(p, PTOU(p), lwp->lwp_cursig, &sp->pr_action);
1017 	sp->pr_oldcontext = (caddr32_t)lwp->lwp_oldcontext;
1018 	sp->pr_ustack = (caddr32_t)lwp->lwp_ustack;
1019 	(void) strncpy(sp->pr_clname, sclass[t->t_cid].cl_name,
1020 	    sizeof (sp->pr_clname) - 1);
1021 	if (flags & PR_STOPPED)
1022 		hrt2ts32(t->t_stoptime, &sp->pr_tstamp);
1023 	usr = ms->ms_acct[LMS_USER];
1024 	sys = ms->ms_acct[LMS_SYSTEM] + ms->ms_acct[LMS_TRAP];
1025 	scalehrtime(&usr);
1026 	scalehrtime(&sys);
1027 	hrt2ts32(usr, &sp->pr_utime);
1028 	hrt2ts32(sys, &sp->pr_stime);
1029 
1030 	/*
1031 	 * Fetch the current instruction, if not a system process.
1032 	 * We don't attempt this unless the lwp is stopped.
1033 	 */
1034 	if ((p->p_flag & SSYS) || p->p_as == &kas)
1035 		sp->pr_flags |= (PR_ISSYS|PR_PCINVAL);
1036 	else if (!(flags & PR_STOPPED))
1037 		sp->pr_flags |= PR_PCINVAL;
1038 	else if (!prfetchinstr(lwp, &instr))
1039 		sp->pr_flags |= PR_PCINVAL;
1040 	else
1041 		sp->pr_instr = (uint32_t)instr;
1042 
1043 	/*
1044 	 * Drop p_lock while touching the lwp's stack.
1045 	 */
1046 	mutex_exit(&p->p_lock);
1047 	if (prisstep(lwp))
1048 		sp->pr_flags |= PR_STEP;
1049 	if ((flags & (PR_STOPPED|PR_ASLEEP)) && t->t_sysnum) {
1050 		int i;
1051 
1052 		sp->pr_syscall = get_syscall32_args(lwp,
1053 		    (int *)sp->pr_sysarg, &i);
1054 		sp->pr_nsysarg = (ushort_t)i;
1055 	}
1056 	if ((flags & PR_STOPPED) || t == curthread)
1057 		prgetprregs32(lwp, sp->pr_reg);
1058 	if ((t->t_state == TS_STOPPED && t->t_whystop == PR_SYSEXIT) ||
1059 	    (flags & PR_VFORKP)) {
1060 		long r1, r2;
1061 		user_t *up;
1062 		auxv_t *auxp;
1063 		int i;
1064 
1065 		sp->pr_errno = prgetrvals(lwp, &r1, &r2);
1066 		if (sp->pr_errno == 0) {
1067 			sp->pr_rval1 = (int32_t)r1;
1068 			sp->pr_rval2 = (int32_t)r2;
1069 			sp->pr_errpriv = PRIV_NONE;
1070 		} else
1071 			sp->pr_errpriv = lwp->lwp_badpriv;
1072 
1073 		if (t->t_sysnum == SYS_execve) {
1074 			up = PTOU(p);
1075 			sp->pr_sysarg[0] = 0;
1076 			sp->pr_sysarg[1] = (caddr32_t)up->u_argv;
1077 			sp->pr_sysarg[2] = (caddr32_t)up->u_envp;
1078 			for (i = 0, auxp = up->u_auxv;
1079 			    i < sizeof (up->u_auxv) / sizeof (up->u_auxv[0]);
1080 			    i++, auxp++) {
1081 				if (auxp->a_type == AT_SUN_EXECNAME) {
1082 					sp->pr_sysarg[0] =
1083 					    (caddr32_t)
1084 					    (uintptr_t)auxp->a_un.a_ptr;
1085 					break;
1086 				}
1087 			}
1088 		}
1089 	}
1090 	if (prhasfp())
1091 		prgetprfpregs32(lwp, &sp->pr_fpreg);
1092 	mutex_enter(&p->p_lock);
1093 }
1094 
1095 void
1096 prgetstatus32(proc_t *p, pstatus32_t *sp, zone_t *zp)
1097 {
1098 	kthread_t *t;
1099 
1100 	ASSERT(MUTEX_HELD(&p->p_lock));
1101 
1102 	t = prchoose(p);	/* returns locked thread */
1103 	ASSERT(t != NULL);
1104 	thread_unlock(t);
1105 
1106 	/* just bzero the process part, prgetlwpstatus32() does the rest */
1107 	bzero(sp, sizeof (pstatus32_t) - sizeof (lwpstatus32_t));
1108 	sp->pr_nlwp = p->p_lwpcnt;
1109 	sp->pr_nzomb = p->p_zombcnt;
1110 	prassignset(&sp->pr_sigpend, &p->p_sig);
1111 	sp->pr_brkbase = (uint32_t)(uintptr_t)p->p_brkbase;
1112 	sp->pr_brksize = (uint32_t)p->p_brksize;
1113 	sp->pr_stkbase = (uint32_t)(uintptr_t)prgetstackbase(p);
1114 	sp->pr_stksize = (uint32_t)p->p_stksize;
1115 	sp->pr_pid   = p->p_pid;
1116 	if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
1117 	    (p->p_flag & SZONETOP)) {
1118 		ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
1119 		/*
1120 		 * Inside local zones, fake zsched's pid as parent pids for
1121 		 * processes which reference processes outside of the zone.
1122 		 */
1123 		sp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
1124 	} else {
1125 		sp->pr_ppid = p->p_ppid;
1126 	}
1127 	sp->pr_pgid  = p->p_pgrp;
1128 	sp->pr_sid   = p->p_sessp->s_sid;
1129 	sp->pr_taskid = p->p_task->tk_tkid;
1130 	sp->pr_projid = p->p_task->tk_proj->kpj_id;
1131 	sp->pr_zoneid = p->p_zone->zone_id;
1132 	hrt2ts32(mstate_aggr_state(p, LMS_USER), &sp->pr_utime);
1133 	hrt2ts32(mstate_aggr_state(p, LMS_SYSTEM), &sp->pr_stime);
1134 	TICK_TO_TIMESTRUC32(p->p_cutime, &sp->pr_cutime);
1135 	TICK_TO_TIMESTRUC32(p->p_cstime, &sp->pr_cstime);
1136 	prassignset(&sp->pr_sigtrace, &p->p_sigmask);
1137 	prassignset(&sp->pr_flttrace, &p->p_fltmask);
1138 	prassignset(&sp->pr_sysentry, &PTOU(p)->u_entrymask);
1139 	prassignset(&sp->pr_sysexit, &PTOU(p)->u_exitmask);
1140 	switch (p->p_model) {
1141 	case DATAMODEL_ILP32:
1142 		sp->pr_dmodel = PR_MODEL_ILP32;
1143 		break;
1144 	case DATAMODEL_LP64:
1145 		sp->pr_dmodel = PR_MODEL_LP64;
1146 		break;
1147 	}
1148 	if (p->p_agenttp)
1149 		sp->pr_agentid = p->p_agenttp->t_tid;
1150 
1151 	/* get the chosen lwp's status */
1152 	prgetlwpstatus32(t, &sp->pr_lwp, zp);
1153 
1154 	/* replicate the flags */
1155 	sp->pr_flags = sp->pr_lwp.pr_flags;
1156 }
1157 #endif	/* _SYSCALL32_IMPL */
1158 
1159 /*
1160  * Return lwp status.
1161  */
1162 void
1163 prgetlwpstatus(kthread_t *t, lwpstatus_t *sp, zone_t *zp)
1164 {
1165 	proc_t *p = ttoproc(t);
1166 	klwp_t *lwp = ttolwp(t);
1167 	struct mstate *ms = &lwp->lwp_mstate;
1168 	hrtime_t usr, sys;
1169 	int flags;
1170 	ulong_t instr;
1171 
1172 	ASSERT(MUTEX_HELD(&p->p_lock));
1173 
1174 	bzero(sp, sizeof (*sp));
1175 	flags = 0L;
1176 	if (t->t_state == TS_STOPPED) {
1177 		flags |= PR_STOPPED;
1178 		if ((t->t_schedflag & TS_PSTART) == 0)
1179 			flags |= PR_ISTOP;
1180 	} else if (VSTOPPED(t)) {
1181 		flags |= PR_STOPPED|PR_ISTOP;
1182 	}
1183 	if (!(flags & PR_ISTOP) && (t->t_proc_flag & TP_PRSTOP))
1184 		flags |= PR_DSTOP;
1185 	if (lwp->lwp_asleep)
1186 		flags |= PR_ASLEEP;
1187 	if (t == p->p_agenttp)
1188 		flags |= PR_AGENT;
1189 	if (!(t->t_proc_flag & TP_TWAIT))
1190 		flags |= PR_DETACH;
1191 	if (t->t_proc_flag & TP_DAEMON)
1192 		flags |= PR_DAEMON;
1193 	if (p->p_proc_flag & P_PR_FORK)
1194 		flags |= PR_FORK;
1195 	if (p->p_proc_flag & P_PR_RUNLCL)
1196 		flags |= PR_RLC;
1197 	if (p->p_proc_flag & P_PR_KILLCL)
1198 		flags |= PR_KLC;
1199 	if (p->p_proc_flag & P_PR_ASYNC)
1200 		flags |= PR_ASYNC;
1201 	if (p->p_proc_flag & P_PR_BPTADJ)
1202 		flags |= PR_BPTADJ;
1203 	if (p->p_proc_flag & P_PR_PTRACE)
1204 		flags |= PR_PTRACE;
1205 	if (p->p_flag & SMSACCT)
1206 		flags |= PR_MSACCT;
1207 	if (p->p_flag & SMSFORK)
1208 		flags |= PR_MSFORK;
1209 	if (p->p_flag & SVFWAIT)
1210 		flags |= PR_VFORKP;
1211 	if (p->p_pgidp->pid_pgorphaned)
1212 		flags |= PR_ORPHAN;
1213 	if (p->p_pidflag & CLDNOSIGCHLD)
1214 		flags |= PR_NOSIGCHLD;
1215 	if (p->p_pidflag & CLDWAITPID)
1216 		flags |= PR_WAITPID;
1217 	sp->pr_flags = flags;
1218 	if (VSTOPPED(t)) {
1219 		sp->pr_why   = PR_REQUESTED;
1220 		sp->pr_what  = 0;
1221 	} else {
1222 		sp->pr_why   = t->t_whystop;
1223 		sp->pr_what  = t->t_whatstop;
1224 	}
1225 	sp->pr_lwpid = t->t_tid;
1226 	sp->pr_cursig  = lwp->lwp_cursig;
1227 	prassignset(&sp->pr_lwppend, &t->t_sig);
1228 	schedctl_finish_sigblock(t);
1229 	prassignset(&sp->pr_lwphold, &t->t_hold);
1230 	if (t->t_whystop == PR_FAULTED)
1231 		bcopy(&lwp->lwp_siginfo,
1232 		    &sp->pr_info, sizeof (k_siginfo_t));
1233 	else if (lwp->lwp_curinfo)
1234 		bcopy(&lwp->lwp_curinfo->sq_info,
1235 		    &sp->pr_info, sizeof (k_siginfo_t));
1236 	if (SI_FROMUSER(&lwp->lwp_siginfo) && zp->zone_id != GLOBAL_ZONEID &&
1237 	    sp->pr_info.si_zoneid != zp->zone_id) {
1238 		sp->pr_info.si_pid = zp->zone_zsched->p_pid;
1239 		sp->pr_info.si_uid = 0;
1240 		sp->pr_info.si_ctid = -1;
1241 		sp->pr_info.si_zoneid = zp->zone_id;
1242 	}
1243 	sp->pr_altstack = lwp->lwp_sigaltstack;
1244 	prgetaction(p, PTOU(p), lwp->lwp_cursig, &sp->pr_action);
1245 	sp->pr_oldcontext = (uintptr_t)lwp->lwp_oldcontext;
1246 	sp->pr_ustack = lwp->lwp_ustack;
1247 	(void) strncpy(sp->pr_clname, sclass[t->t_cid].cl_name,
1248 	    sizeof (sp->pr_clname) - 1);
1249 	if (flags & PR_STOPPED)
1250 		hrt2ts(t->t_stoptime, &sp->pr_tstamp);
1251 	usr = ms->ms_acct[LMS_USER];
1252 	sys = ms->ms_acct[LMS_SYSTEM] + ms->ms_acct[LMS_TRAP];
1253 	scalehrtime(&usr);
1254 	scalehrtime(&sys);
1255 	hrt2ts(usr, &sp->pr_utime);
1256 	hrt2ts(sys, &sp->pr_stime);
1257 
1258 	/*
1259 	 * Fetch the current instruction, if not a system process.
1260 	 * We don't attempt this unless the lwp is stopped.
1261 	 */
1262 	if ((p->p_flag & SSYS) || p->p_as == &kas)
1263 		sp->pr_flags |= (PR_ISSYS|PR_PCINVAL);
1264 	else if (!(flags & PR_STOPPED))
1265 		sp->pr_flags |= PR_PCINVAL;
1266 	else if (!prfetchinstr(lwp, &instr))
1267 		sp->pr_flags |= PR_PCINVAL;
1268 	else
1269 		sp->pr_instr = instr;
1270 
1271 	/*
1272 	 * Drop p_lock while touching the lwp's stack.
1273 	 */
1274 	mutex_exit(&p->p_lock);
1275 	if (prisstep(lwp))
1276 		sp->pr_flags |= PR_STEP;
1277 	if ((flags & (PR_STOPPED|PR_ASLEEP)) && t->t_sysnum) {
1278 		int i;
1279 
1280 		sp->pr_syscall = get_syscall_args(lwp,
1281 		    (long *)sp->pr_sysarg, &i);
1282 		sp->pr_nsysarg = (ushort_t)i;
1283 	}
1284 	if ((flags & PR_STOPPED) || t == curthread)
1285 		prgetprregs(lwp, sp->pr_reg);
1286 	if ((t->t_state == TS_STOPPED && t->t_whystop == PR_SYSEXIT) ||
1287 	    (flags & PR_VFORKP)) {
1288 		user_t *up;
1289 		auxv_t *auxp;
1290 		int i;
1291 
1292 		sp->pr_errno = prgetrvals(lwp, &sp->pr_rval1, &sp->pr_rval2);
1293 		if (sp->pr_errno == 0)
1294 			sp->pr_errpriv = PRIV_NONE;
1295 		else
1296 			sp->pr_errpriv = lwp->lwp_badpriv;
1297 
1298 		if (t->t_sysnum == SYS_execve) {
1299 			up = PTOU(p);
1300 			sp->pr_sysarg[0] = 0;
1301 			sp->pr_sysarg[1] = (uintptr_t)up->u_argv;
1302 			sp->pr_sysarg[2] = (uintptr_t)up->u_envp;
1303 			for (i = 0, auxp = up->u_auxv;
1304 			    i < sizeof (up->u_auxv) / sizeof (up->u_auxv[0]);
1305 			    i++, auxp++) {
1306 				if (auxp->a_type == AT_SUN_EXECNAME) {
1307 					sp->pr_sysarg[0] =
1308 					    (uintptr_t)auxp->a_un.a_ptr;
1309 					break;
1310 				}
1311 			}
1312 		}
1313 	}
1314 	if (prhasfp())
1315 		prgetprfpregs(lwp, &sp->pr_fpreg);
1316 	mutex_enter(&p->p_lock);
1317 }
1318 
1319 /*
1320  * Get the sigaction structure for the specified signal.  The u-block
1321  * must already have been mapped in by the caller.
1322  */
1323 void
1324 prgetaction(proc_t *p, user_t *up, uint_t sig, struct sigaction *sp)
1325 {
1326 	int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
1327 
1328 	bzero(sp, sizeof (*sp));
1329 
1330 	if (sig != 0 && (unsigned)sig < nsig) {
1331 		sp->sa_handler = up->u_signal[sig-1];
1332 		prassignset(&sp->sa_mask, &up->u_sigmask[sig-1]);
1333 		if (sigismember(&up->u_sigonstack, sig))
1334 			sp->sa_flags |= SA_ONSTACK;
1335 		if (sigismember(&up->u_sigresethand, sig))
1336 			sp->sa_flags |= SA_RESETHAND;
1337 		if (sigismember(&up->u_sigrestart, sig))
1338 			sp->sa_flags |= SA_RESTART;
1339 		if (sigismember(&p->p_siginfo, sig))
1340 			sp->sa_flags |= SA_SIGINFO;
1341 		if (sigismember(&up->u_signodefer, sig))
1342 			sp->sa_flags |= SA_NODEFER;
1343 		if (sig == SIGCLD) {
1344 			if (p->p_flag & SNOWAIT)
1345 				sp->sa_flags |= SA_NOCLDWAIT;
1346 			if ((p->p_flag & SJCTL) == 0)
1347 				sp->sa_flags |= SA_NOCLDSTOP;
1348 		}
1349 	}
1350 }
1351 
1352 #ifdef _SYSCALL32_IMPL
1353 void
1354 prgetaction32(proc_t *p, user_t *up, uint_t sig, struct sigaction32 *sp)
1355 {
1356 	int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
1357 
1358 	bzero(sp, sizeof (*sp));
1359 
1360 	if (sig != 0 && (unsigned)sig < nsig) {
1361 		sp->sa_handler = (caddr32_t)(uintptr_t)up->u_signal[sig-1];
1362 		prassignset(&sp->sa_mask, &up->u_sigmask[sig-1]);
1363 		if (sigismember(&up->u_sigonstack, sig))
1364 			sp->sa_flags |= SA_ONSTACK;
1365 		if (sigismember(&up->u_sigresethand, sig))
1366 			sp->sa_flags |= SA_RESETHAND;
1367 		if (sigismember(&up->u_sigrestart, sig))
1368 			sp->sa_flags |= SA_RESTART;
1369 		if (sigismember(&p->p_siginfo, sig))
1370 			sp->sa_flags |= SA_SIGINFO;
1371 		if (sigismember(&up->u_signodefer, sig))
1372 			sp->sa_flags |= SA_NODEFER;
1373 		if (sig == SIGCLD) {
1374 			if (p->p_flag & SNOWAIT)
1375 				sp->sa_flags |= SA_NOCLDWAIT;
1376 			if ((p->p_flag & SJCTL) == 0)
1377 				sp->sa_flags |= SA_NOCLDSTOP;
1378 		}
1379 	}
1380 }
1381 #endif	/* _SYSCALL32_IMPL */
1382 
1383 /*
1384  * Count the number of segments in this process's address space.
1385  */
1386 int
1387 prnsegs(struct as *as, int reserved)
1388 {
1389 	int n = 0;
1390 	struct seg *seg;
1391 
1392 	ASSERT(as != &kas && AS_WRITE_HELD(as));
1393 
1394 	for (seg = AS_SEGFIRST(as); seg != NULL; seg = AS_SEGNEXT(as, seg)) {
1395 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, reserved);
1396 		caddr_t saddr, naddr;
1397 		void *tmp = NULL;
1398 
1399 		if ((seg->s_flags & S_HOLE) != 0) {
1400 			continue;
1401 		}
1402 
1403 		for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
1404 			(void) pr_getprot(seg, reserved, &tmp,
1405 			    &saddr, &naddr, eaddr);
1406 			if (saddr != naddr)
1407 				n++;
1408 		}
1409 
1410 		ASSERT(tmp == NULL);
1411 	}
1412 
1413 	return (n);
1414 }
1415 
1416 /*
1417  * Convert uint32_t to decimal string w/o leading zeros.
1418  * Add trailing null characters if 'len' is greater than string length.
1419  * Return the string length.
1420  */
1421 int
1422 pr_u32tos(uint32_t n, char *s, int len)
1423 {
1424 	char cbuf[11];		/* 32-bit unsigned integer fits in 10 digits */
1425 	char *cp = cbuf;
1426 	char *end = s + len;
1427 
1428 	do {
1429 		*cp++ = (char)(n % 10 + '0');
1430 		n /= 10;
1431 	} while (n);
1432 
1433 	len = (int)(cp - cbuf);
1434 
1435 	do {
1436 		*s++ = *--cp;
1437 	} while (cp > cbuf);
1438 
1439 	while (s < end)		/* optional pad */
1440 		*s++ = '\0';
1441 
1442 	return (len);
1443 }
1444 
1445 /*
1446  * Convert uint64_t to decimal string w/o leading zeros.
1447  * Return the string length.
1448  */
1449 static int
1450 pr_u64tos(uint64_t n, char *s)
1451 {
1452 	char cbuf[21];		/* 64-bit unsigned integer fits in 20 digits */
1453 	char *cp = cbuf;
1454 	int len;
1455 
1456 	do {
1457 		*cp++ = (char)(n % 10 + '0');
1458 		n /= 10;
1459 	} while (n);
1460 
1461 	len = (int)(cp - cbuf);
1462 
1463 	do {
1464 		*s++ = *--cp;
1465 	} while (cp > cbuf);
1466 
1467 	return (len);
1468 }
1469 
1470 file_t *
1471 pr_getf(proc_t *p, uint_t fd, short *flag)
1472 {
1473 	uf_entry_t *ufp;
1474 	uf_info_t *fip;
1475 	file_t *fp;
1476 
1477 	ASSERT(MUTEX_HELD(&p->p_lock) && (p->p_proc_flag & P_PR_LOCK));
1478 
1479 	fip = P_FINFO(p);
1480 
1481 	if (fd >= fip->fi_nfiles)
1482 		return (NULL);
1483 
1484 	mutex_exit(&p->p_lock);
1485 	mutex_enter(&fip->fi_lock);
1486 	UF_ENTER(ufp, fip, fd);
1487 	if ((fp = ufp->uf_file) != NULL && fp->f_count > 0) {
1488 		if (flag != NULL)
1489 			*flag = ufp->uf_flag;
1490 		ufp->uf_refcnt++;
1491 	} else {
1492 		fp = NULL;
1493 	}
1494 	UF_EXIT(ufp);
1495 	mutex_exit(&fip->fi_lock);
1496 	mutex_enter(&p->p_lock);
1497 
1498 	return (fp);
1499 }
1500 
1501 void
1502 pr_releasef(proc_t *p, uint_t fd)
1503 {
1504 	uf_entry_t *ufp;
1505 	uf_info_t *fip;
1506 
1507 	ASSERT(MUTEX_HELD(&p->p_lock) && (p->p_proc_flag & P_PR_LOCK));
1508 
1509 	fip = P_FINFO(p);
1510 
1511 	mutex_exit(&p->p_lock);
1512 	mutex_enter(&fip->fi_lock);
1513 	UF_ENTER(ufp, fip, fd);
1514 	ASSERT3U(ufp->uf_refcnt, >, 0);
1515 	ufp->uf_refcnt--;
1516 	UF_EXIT(ufp);
1517 	mutex_exit(&fip->fi_lock);
1518 	mutex_enter(&p->p_lock);
1519 }
1520 
1521 void
1522 pr_object_name(char *name, vnode_t *vp, struct vattr *vattr)
1523 {
1524 	char *s = name;
1525 	struct vfs *vfsp;
1526 	struct vfssw *vfsswp;
1527 
1528 	if ((vfsp = vp->v_vfsp) != NULL &&
1529 	    ((vfsswp = vfssw + vfsp->vfs_fstype), vfsswp->vsw_name) &&
1530 	    *vfsswp->vsw_name) {
1531 		(void) strcpy(s, vfsswp->vsw_name);
1532 		s += strlen(s);
1533 		*s++ = '.';
1534 	}
1535 	s += pr_u32tos(getmajor(vattr->va_fsid), s, 0);
1536 	*s++ = '.';
1537 	s += pr_u32tos(getminor(vattr->va_fsid), s, 0);
1538 	*s++ = '.';
1539 	s += pr_u64tos(vattr->va_nodeid, s);
1540 	*s++ = '\0';
1541 }
1542 
1543 struct seg *
1544 break_seg(proc_t *p)
1545 {
1546 	caddr_t addr = p->p_brkbase;
1547 	struct seg *seg;
1548 	struct vnode *vp;
1549 
1550 	if (p->p_brksize != 0)
1551 		addr += p->p_brksize - 1;
1552 	seg = as_segat(p->p_as, addr);
1553 	if (seg != NULL && seg->s_ops == &segvn_ops &&
1554 	    (SEGOP_GETVP(seg, seg->s_base, &vp) != 0 || vp == NULL))
1555 		return (seg);
1556 	return (NULL);
1557 }
1558 
1559 /*
1560  * Implementation of service functions to handle procfs generic chained
1561  * copyout buffers.
1562  */
1563 typedef struct pr_iobuf_list {
1564 	list_node_t	piol_link;	/* buffer linkage */
1565 	size_t		piol_size;	/* total size (header + data) */
1566 	size_t		piol_usedsize;	/* amount to copy out from this buf */
1567 } piol_t;
1568 
1569 #define	MAPSIZE	(64 * 1024)
1570 #define	PIOL_DATABUF(iol)	((void *)(&(iol)[1]))
1571 
1572 void
1573 pr_iol_initlist(list_t *iolhead, size_t itemsize, int n)
1574 {
1575 	piol_t	*iol;
1576 	size_t	initial_size = MIN(1, n) * itemsize;
1577 
1578 	list_create(iolhead, sizeof (piol_t), offsetof(piol_t, piol_link));
1579 
1580 	ASSERT(list_head(iolhead) == NULL);
1581 	ASSERT(itemsize < MAPSIZE - sizeof (*iol));
1582 	ASSERT(initial_size > 0);
1583 
1584 	/*
1585 	 * Someone creating chained copyout buffers may ask for less than
1586 	 * MAPSIZE if the amount of data to be buffered is known to be
1587 	 * smaller than that.
1588 	 * But in order to prevent involuntary self-denial of service,
1589 	 * the requested input size is clamped at MAPSIZE.
1590 	 */
1591 	initial_size = MIN(MAPSIZE, initial_size + sizeof (*iol));
1592 	iol = kmem_alloc(initial_size, KM_SLEEP);
1593 	list_insert_head(iolhead, iol);
1594 	iol->piol_usedsize = 0;
1595 	iol->piol_size = initial_size;
1596 }
1597 
1598 void *
1599 pr_iol_newbuf(list_t *iolhead, size_t itemsize)
1600 {
1601 	piol_t	*iol;
1602 	char	*new;
1603 
1604 	ASSERT(itemsize < MAPSIZE - sizeof (*iol));
1605 	ASSERT(list_head(iolhead) != NULL);
1606 
1607 	iol = (piol_t *)list_tail(iolhead);
1608 
1609 	if (iol->piol_size <
1610 	    iol->piol_usedsize + sizeof (*iol) + itemsize) {
1611 		/*
1612 		 * Out of space in the current buffer. Allocate more.
1613 		 */
1614 		piol_t *newiol;
1615 
1616 		newiol = kmem_alloc(MAPSIZE, KM_SLEEP);
1617 		newiol->piol_size = MAPSIZE;
1618 		newiol->piol_usedsize = 0;
1619 
1620 		list_insert_after(iolhead, iol, newiol);
1621 		iol = list_next(iolhead, iol);
1622 		ASSERT(iol == newiol);
1623 	}
1624 	new = (char *)PIOL_DATABUF(iol) + iol->piol_usedsize;
1625 	iol->piol_usedsize += itemsize;
1626 	bzero(new, itemsize);
1627 	return (new);
1628 }
1629 
1630 void
1631 pr_iol_freelist(list_t *iolhead)
1632 {
1633 	piol_t	*iol;
1634 
1635 	while ((iol = list_head(iolhead)) != NULL) {
1636 		list_remove(iolhead, iol);
1637 		kmem_free(iol, iol->piol_size);
1638 	}
1639 	list_destroy(iolhead);
1640 }
1641 
1642 int
1643 pr_iol_copyout_and_free(list_t *iolhead, caddr_t *tgt, int errin)
1644 {
1645 	int error = errin;
1646 	piol_t	*iol;
1647 
1648 	while ((iol = list_head(iolhead)) != NULL) {
1649 		list_remove(iolhead, iol);
1650 		if (!error) {
1651 			if (copyout(PIOL_DATABUF(iol), *tgt,
1652 			    iol->piol_usedsize))
1653 				error = EFAULT;
1654 			*tgt += iol->piol_usedsize;
1655 		}
1656 		kmem_free(iol, iol->piol_size);
1657 	}
1658 	list_destroy(iolhead);
1659 
1660 	return (error);
1661 }
1662 
1663 int
1664 pr_iol_uiomove_and_free(list_t *iolhead, uio_t *uiop, int errin)
1665 {
1666 	offset_t	off = uiop->uio_offset;
1667 	char		*base;
1668 	size_t		size;
1669 	piol_t		*iol;
1670 	int		error = errin;
1671 
1672 	while ((iol = list_head(iolhead)) != NULL) {
1673 		list_remove(iolhead, iol);
1674 		base = PIOL_DATABUF(iol);
1675 		size = iol->piol_usedsize;
1676 		if (off <= size && error == 0 && uiop->uio_resid > 0)
1677 			error = uiomove(base + off, size - off,
1678 			    UIO_READ, uiop);
1679 		off = MAX(0, off - (offset_t)size);
1680 		kmem_free(iol, iol->piol_size);
1681 	}
1682 	list_destroy(iolhead);
1683 
1684 	return (error);
1685 }
1686 
1687 /*
1688  * Return an array of structures with memory map information.
1689  * We allocate here; the caller must deallocate.
1690  */
1691 int
1692 prgetmap(proc_t *p, int reserved, list_t *iolhead)
1693 {
1694 	struct as *as = p->p_as;
1695 	prmap_t *mp;
1696 	struct seg *seg;
1697 	struct seg *brkseg, *stkseg;
1698 	struct vnode *vp;
1699 	struct vattr vattr;
1700 	uint_t prot;
1701 
1702 	ASSERT(as != &kas && AS_WRITE_HELD(as));
1703 
1704 	/*
1705 	 * Request an initial buffer size that doesn't waste memory
1706 	 * if the address space has only a small number of segments.
1707 	 */
1708 	pr_iol_initlist(iolhead, sizeof (*mp), avl_numnodes(&as->a_segtree));
1709 
1710 	if ((seg = AS_SEGFIRST(as)) == NULL)
1711 		return (0);
1712 
1713 	brkseg = break_seg(p);
1714 	stkseg = as_segat(as, prgetstackbase(p));
1715 
1716 	do {
1717 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, reserved);
1718 		caddr_t saddr, naddr;
1719 		void *tmp = NULL;
1720 
1721 		if ((seg->s_flags & S_HOLE) != 0) {
1722 			continue;
1723 		}
1724 
1725 		for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
1726 			prot = pr_getprot(seg, reserved, &tmp,
1727 			    &saddr, &naddr, eaddr);
1728 			if (saddr == naddr)
1729 				continue;
1730 
1731 			mp = pr_iol_newbuf(iolhead, sizeof (*mp));
1732 
1733 			mp->pr_vaddr = (uintptr_t)saddr;
1734 			mp->pr_size = naddr - saddr;
1735 			mp->pr_offset = SEGOP_GETOFFSET(seg, saddr);
1736 			mp->pr_mflags = 0;
1737 			if (prot & PROT_READ)
1738 				mp->pr_mflags |= MA_READ;
1739 			if (prot & PROT_WRITE)
1740 				mp->pr_mflags |= MA_WRITE;
1741 			if (prot & PROT_EXEC)
1742 				mp->pr_mflags |= MA_EXEC;
1743 			if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
1744 				mp->pr_mflags |= MA_SHARED;
1745 			if (SEGOP_GETTYPE(seg, saddr) & MAP_NORESERVE)
1746 				mp->pr_mflags |= MA_NORESERVE;
1747 			if (seg->s_ops == &segspt_shmops ||
1748 			    (seg->s_ops == &segvn_ops &&
1749 			    (SEGOP_GETVP(seg, saddr, &vp) != 0 || vp == NULL)))
1750 				mp->pr_mflags |= MA_ANON;
1751 			if (seg == brkseg)
1752 				mp->pr_mflags |= MA_BREAK;
1753 			else if (seg == stkseg) {
1754 				mp->pr_mflags |= MA_STACK;
1755 				if (reserved) {
1756 					size_t maxstack =
1757 					    ((size_t)p->p_stk_ctl +
1758 					    PAGEOFFSET) & PAGEMASK;
1759 					mp->pr_vaddr =
1760 					    (uintptr_t)prgetstackbase(p) +
1761 					    p->p_stksize - maxstack;
1762 					mp->pr_size = (uintptr_t)naddr -
1763 					    mp->pr_vaddr;
1764 				}
1765 			}
1766 			if (seg->s_ops == &segspt_shmops)
1767 				mp->pr_mflags |= MA_ISM | MA_SHM;
1768 			mp->pr_pagesize = PAGESIZE;
1769 
1770 			/*
1771 			 * Manufacture a filename for the "object" directory.
1772 			 */
1773 			vattr.va_mask = AT_FSID|AT_NODEID;
1774 			if (seg->s_ops == &segvn_ops &&
1775 			    SEGOP_GETVP(seg, saddr, &vp) == 0 &&
1776 			    vp != NULL && vp->v_type == VREG &&
1777 			    VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
1778 				if (vp == p->p_exec)
1779 					(void) strcpy(mp->pr_mapname, "a.out");
1780 				else
1781 					pr_object_name(mp->pr_mapname,
1782 					    vp, &vattr);
1783 			}
1784 
1785 			/*
1786 			 * Get the SysV shared memory id, if any.
1787 			 */
1788 			if ((mp->pr_mflags & MA_SHARED) && p->p_segacct &&
1789 			    (mp->pr_shmid = shmgetid(p, seg->s_base)) !=
1790 			    SHMID_NONE) {
1791 				if (mp->pr_shmid == SHMID_FREE)
1792 					mp->pr_shmid = -1;
1793 
1794 				mp->pr_mflags |= MA_SHM;
1795 			} else {
1796 				mp->pr_shmid = -1;
1797 			}
1798 		}
1799 		ASSERT(tmp == NULL);
1800 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
1801 
1802 	return (0);
1803 }
1804 
1805 #ifdef _SYSCALL32_IMPL
1806 int
1807 prgetmap32(proc_t *p, int reserved, list_t *iolhead)
1808 {
1809 	struct as *as = p->p_as;
1810 	prmap32_t *mp;
1811 	struct seg *seg;
1812 	struct seg *brkseg, *stkseg;
1813 	struct vnode *vp;
1814 	struct vattr vattr;
1815 	uint_t prot;
1816 
1817 	ASSERT(as != &kas && AS_WRITE_HELD(as));
1818 
1819 	/*
1820 	 * Request an initial buffer size that doesn't waste memory
1821 	 * if the address space has only a small number of segments.
1822 	 */
1823 	pr_iol_initlist(iolhead, sizeof (*mp), avl_numnodes(&as->a_segtree));
1824 
1825 	if ((seg = AS_SEGFIRST(as)) == NULL)
1826 		return (0);
1827 
1828 	brkseg = break_seg(p);
1829 	stkseg = as_segat(as, prgetstackbase(p));
1830 
1831 	do {
1832 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, reserved);
1833 		caddr_t saddr, naddr;
1834 		void *tmp = NULL;
1835 
1836 		if ((seg->s_flags & S_HOLE) != 0) {
1837 			continue;
1838 		}
1839 
1840 		for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
1841 			prot = pr_getprot(seg, reserved, &tmp,
1842 			    &saddr, &naddr, eaddr);
1843 			if (saddr == naddr)
1844 				continue;
1845 
1846 			mp = pr_iol_newbuf(iolhead, sizeof (*mp));
1847 
1848 			mp->pr_vaddr = (caddr32_t)(uintptr_t)saddr;
1849 			mp->pr_size = (size32_t)(naddr - saddr);
1850 			mp->pr_offset = SEGOP_GETOFFSET(seg, saddr);
1851 			mp->pr_mflags = 0;
1852 			if (prot & PROT_READ)
1853 				mp->pr_mflags |= MA_READ;
1854 			if (prot & PROT_WRITE)
1855 				mp->pr_mflags |= MA_WRITE;
1856 			if (prot & PROT_EXEC)
1857 				mp->pr_mflags |= MA_EXEC;
1858 			if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
1859 				mp->pr_mflags |= MA_SHARED;
1860 			if (SEGOP_GETTYPE(seg, saddr) & MAP_NORESERVE)
1861 				mp->pr_mflags |= MA_NORESERVE;
1862 			if (seg->s_ops == &segspt_shmops ||
1863 			    (seg->s_ops == &segvn_ops &&
1864 			    (SEGOP_GETVP(seg, saddr, &vp) != 0 || vp == NULL)))
1865 				mp->pr_mflags |= MA_ANON;
1866 			if (seg == brkseg)
1867 				mp->pr_mflags |= MA_BREAK;
1868 			else if (seg == stkseg) {
1869 				mp->pr_mflags |= MA_STACK;
1870 				if (reserved) {
1871 					size_t maxstack =
1872 					    ((size_t)p->p_stk_ctl +
1873 					    PAGEOFFSET) & PAGEMASK;
1874 					uintptr_t vaddr =
1875 					    (uintptr_t)prgetstackbase(p) +
1876 					    p->p_stksize - maxstack;
1877 					mp->pr_vaddr = (caddr32_t)vaddr;
1878 					mp->pr_size = (size32_t)
1879 					    ((uintptr_t)naddr - vaddr);
1880 				}
1881 			}
1882 			if (seg->s_ops == &segspt_shmops)
1883 				mp->pr_mflags |= MA_ISM | MA_SHM;
1884 			mp->pr_pagesize = PAGESIZE;
1885 
1886 			/*
1887 			 * Manufacture a filename for the "object" directory.
1888 			 */
1889 			vattr.va_mask = AT_FSID|AT_NODEID;
1890 			if (seg->s_ops == &segvn_ops &&
1891 			    SEGOP_GETVP(seg, saddr, &vp) == 0 &&
1892 			    vp != NULL && vp->v_type == VREG &&
1893 			    VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
1894 				if (vp == p->p_exec)
1895 					(void) strcpy(mp->pr_mapname, "a.out");
1896 				else
1897 					pr_object_name(mp->pr_mapname,
1898 					    vp, &vattr);
1899 			}
1900 
1901 			/*
1902 			 * Get the SysV shared memory id, if any.
1903 			 */
1904 			if ((mp->pr_mflags & MA_SHARED) && p->p_segacct &&
1905 			    (mp->pr_shmid = shmgetid(p, seg->s_base)) !=
1906 			    SHMID_NONE) {
1907 				if (mp->pr_shmid == SHMID_FREE)
1908 					mp->pr_shmid = -1;
1909 
1910 				mp->pr_mflags |= MA_SHM;
1911 			} else {
1912 				mp->pr_shmid = -1;
1913 			}
1914 		}
1915 		ASSERT(tmp == NULL);
1916 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
1917 
1918 	return (0);
1919 }
1920 #endif	/* _SYSCALL32_IMPL */
1921 
1922 /*
1923  * Return the size of the /proc page data file.
1924  */
1925 size_t
1926 prpdsize(struct as *as)
1927 {
1928 	struct seg *seg;
1929 	size_t size;
1930 
1931 	ASSERT(as != &kas && AS_WRITE_HELD(as));
1932 
1933 	if ((seg = AS_SEGFIRST(as)) == NULL)
1934 		return (0);
1935 
1936 	size = sizeof (prpageheader_t);
1937 	do {
1938 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
1939 		caddr_t saddr, naddr;
1940 		void *tmp = NULL;
1941 		size_t npage;
1942 
1943 		if ((seg->s_flags & S_HOLE) != 0) {
1944 			continue;
1945 		}
1946 
1947 		for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
1948 			(void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
1949 			if ((npage = (naddr - saddr) / PAGESIZE) != 0)
1950 				size += sizeof (prasmap_t) + round8(npage);
1951 		}
1952 		ASSERT(tmp == NULL);
1953 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
1954 
1955 	return (size);
1956 }
1957 
1958 #ifdef _SYSCALL32_IMPL
1959 size_t
1960 prpdsize32(struct as *as)
1961 {
1962 	struct seg *seg;
1963 	size_t size;
1964 
1965 	ASSERT(as != &kas && AS_WRITE_HELD(as));
1966 
1967 	if ((seg = AS_SEGFIRST(as)) == NULL)
1968 		return (0);
1969 
1970 	size = sizeof (prpageheader32_t);
1971 	do {
1972 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
1973 		caddr_t saddr, naddr;
1974 		void *tmp = NULL;
1975 		size_t npage;
1976 
1977 		if ((seg->s_flags & S_HOLE) != 0) {
1978 			continue;
1979 		}
1980 
1981 		for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
1982 			(void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
1983 			if ((npage = (naddr - saddr) / PAGESIZE) != 0)
1984 				size += sizeof (prasmap32_t) + round8(npage);
1985 		}
1986 		ASSERT(tmp == NULL);
1987 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
1988 
1989 	return (size);
1990 }
1991 #endif	/* _SYSCALL32_IMPL */
1992 
1993 /*
1994  * Read page data information.
1995  */
1996 int
1997 prpdread(proc_t *p, uint_t hatid, struct uio *uiop)
1998 {
1999 	struct as *as = p->p_as;
2000 	caddr_t buf;
2001 	size_t size;
2002 	prpageheader_t *php;
2003 	prasmap_t *pmp;
2004 	struct seg *seg;
2005 	int error;
2006 
2007 again:
2008 	AS_LOCK_ENTER(as, RW_WRITER);
2009 
2010 	if ((seg = AS_SEGFIRST(as)) == NULL) {
2011 		AS_LOCK_EXIT(as);
2012 		return (0);
2013 	}
2014 	size = prpdsize(as);
2015 	if (uiop->uio_resid < size) {
2016 		AS_LOCK_EXIT(as);
2017 		return (E2BIG);
2018 	}
2019 
2020 	buf = kmem_zalloc(size, KM_SLEEP);
2021 	php = (prpageheader_t *)buf;
2022 	pmp = (prasmap_t *)(buf + sizeof (prpageheader_t));
2023 
2024 	hrt2ts(gethrtime(), &php->pr_tstamp);
2025 	php->pr_nmap = 0;
2026 	php->pr_npage = 0;
2027 	do {
2028 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
2029 		caddr_t saddr, naddr;
2030 		void *tmp = NULL;
2031 
2032 		if ((seg->s_flags & S_HOLE) != 0) {
2033 			continue;
2034 		}
2035 
2036 		for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
2037 			struct vnode *vp;
2038 			struct vattr vattr;
2039 			size_t len;
2040 			size_t npage;
2041 			uint_t prot;
2042 			uintptr_t next;
2043 
2044 			prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
2045 			if ((len = (size_t)(naddr - saddr)) == 0)
2046 				continue;
2047 			npage = len / PAGESIZE;
2048 			next = (uintptr_t)(pmp + 1) + round8(npage);
2049 			/*
2050 			 * It's possible that the address space can change
2051 			 * subtlely even though we're holding as->a_lock
2052 			 * due to the nondeterminism of page_exists() in
2053 			 * the presence of asychronously flushed pages or
2054 			 * mapped files whose sizes are changing.
2055 			 * page_exists() may be called indirectly from
2056 			 * pr_getprot() by a SEGOP_INCORE() routine.
2057 			 * If this happens we need to make sure we don't
2058 			 * overrun the buffer whose size we computed based
2059 			 * on the initial iteration through the segments.
2060 			 * Once we've detected an overflow, we need to clean
2061 			 * up the temporary memory allocated in pr_getprot()
2062 			 * and retry. If there's a pending signal, we return
2063 			 * EINTR so that this thread can be dislodged if
2064 			 * a latent bug causes us to spin indefinitely.
2065 			 */
2066 			if (next > (uintptr_t)buf + size) {
2067 				pr_getprot_done(&tmp);
2068 				AS_LOCK_EXIT(as);
2069 
2070 				kmem_free(buf, size);
2071 
2072 				if (ISSIG(curthread, JUSTLOOKING))
2073 					return (EINTR);
2074 
2075 				goto again;
2076 			}
2077 
2078 			php->pr_nmap++;
2079 			php->pr_npage += npage;
2080 			pmp->pr_vaddr = (uintptr_t)saddr;
2081 			pmp->pr_npage = npage;
2082 			pmp->pr_offset = SEGOP_GETOFFSET(seg, saddr);
2083 			pmp->pr_mflags = 0;
2084 			if (prot & PROT_READ)
2085 				pmp->pr_mflags |= MA_READ;
2086 			if (prot & PROT_WRITE)
2087 				pmp->pr_mflags |= MA_WRITE;
2088 			if (prot & PROT_EXEC)
2089 				pmp->pr_mflags |= MA_EXEC;
2090 			if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
2091 				pmp->pr_mflags |= MA_SHARED;
2092 			if (SEGOP_GETTYPE(seg, saddr) & MAP_NORESERVE)
2093 				pmp->pr_mflags |= MA_NORESERVE;
2094 			if (seg->s_ops == &segspt_shmops ||
2095 			    (seg->s_ops == &segvn_ops &&
2096 			    (SEGOP_GETVP(seg, saddr, &vp) != 0 || vp == NULL)))
2097 				pmp->pr_mflags |= MA_ANON;
2098 			if (seg->s_ops == &segspt_shmops)
2099 				pmp->pr_mflags |= MA_ISM | MA_SHM;
2100 			pmp->pr_pagesize = PAGESIZE;
2101 			/*
2102 			 * Manufacture a filename for the "object" directory.
2103 			 */
2104 			vattr.va_mask = AT_FSID|AT_NODEID;
2105 			if (seg->s_ops == &segvn_ops &&
2106 			    SEGOP_GETVP(seg, saddr, &vp) == 0 &&
2107 			    vp != NULL && vp->v_type == VREG &&
2108 			    VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
2109 				if (vp == p->p_exec)
2110 					(void) strcpy(pmp->pr_mapname, "a.out");
2111 				else
2112 					pr_object_name(pmp->pr_mapname,
2113 					    vp, &vattr);
2114 			}
2115 
2116 			/*
2117 			 * Get the SysV shared memory id, if any.
2118 			 */
2119 			if ((pmp->pr_mflags & MA_SHARED) && p->p_segacct &&
2120 			    (pmp->pr_shmid = shmgetid(p, seg->s_base)) !=
2121 			    SHMID_NONE) {
2122 				if (pmp->pr_shmid == SHMID_FREE)
2123 					pmp->pr_shmid = -1;
2124 
2125 				pmp->pr_mflags |= MA_SHM;
2126 			} else {
2127 				pmp->pr_shmid = -1;
2128 			}
2129 
2130 			hat_getstat(as, saddr, len, hatid,
2131 			    (char *)(pmp + 1), HAT_SYNC_ZERORM);
2132 			pmp = (prasmap_t *)next;
2133 		}
2134 		ASSERT(tmp == NULL);
2135 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
2136 
2137 	AS_LOCK_EXIT(as);
2138 
2139 	ASSERT((uintptr_t)pmp <= (uintptr_t)buf + size);
2140 	error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
2141 	kmem_free(buf, size);
2142 
2143 	return (error);
2144 }
2145 
2146 #ifdef _SYSCALL32_IMPL
2147 int
2148 prpdread32(proc_t *p, uint_t hatid, struct uio *uiop)
2149 {
2150 	struct as *as = p->p_as;
2151 	caddr_t buf;
2152 	size_t size;
2153 	prpageheader32_t *php;
2154 	prasmap32_t *pmp;
2155 	struct seg *seg;
2156 	int error;
2157 
2158 again:
2159 	AS_LOCK_ENTER(as, RW_WRITER);
2160 
2161 	if ((seg = AS_SEGFIRST(as)) == NULL) {
2162 		AS_LOCK_EXIT(as);
2163 		return (0);
2164 	}
2165 	size = prpdsize32(as);
2166 	if (uiop->uio_resid < size) {
2167 		AS_LOCK_EXIT(as);
2168 		return (E2BIG);
2169 	}
2170 
2171 	buf = kmem_zalloc(size, KM_SLEEP);
2172 	php = (prpageheader32_t *)buf;
2173 	pmp = (prasmap32_t *)(buf + sizeof (prpageheader32_t));
2174 
2175 	hrt2ts32(gethrtime(), &php->pr_tstamp);
2176 	php->pr_nmap = 0;
2177 	php->pr_npage = 0;
2178 	do {
2179 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
2180 		caddr_t saddr, naddr;
2181 		void *tmp = NULL;
2182 
2183 		if ((seg->s_flags & S_HOLE) != 0) {
2184 			continue;
2185 		}
2186 
2187 		for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
2188 			struct vnode *vp;
2189 			struct vattr vattr;
2190 			size_t len;
2191 			size_t npage;
2192 			uint_t prot;
2193 			uintptr_t next;
2194 
2195 			prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
2196 			if ((len = (size_t)(naddr - saddr)) == 0)
2197 				continue;
2198 			npage = len / PAGESIZE;
2199 			next = (uintptr_t)(pmp + 1) + round8(npage);
2200 			/*
2201 			 * It's possible that the address space can change
2202 			 * subtlely even though we're holding as->a_lock
2203 			 * due to the nondeterminism of page_exists() in
2204 			 * the presence of asychronously flushed pages or
2205 			 * mapped files whose sizes are changing.
2206 			 * page_exists() may be called indirectly from
2207 			 * pr_getprot() by a SEGOP_INCORE() routine.
2208 			 * If this happens we need to make sure we don't
2209 			 * overrun the buffer whose size we computed based
2210 			 * on the initial iteration through the segments.
2211 			 * Once we've detected an overflow, we need to clean
2212 			 * up the temporary memory allocated in pr_getprot()
2213 			 * and retry. If there's a pending signal, we return
2214 			 * EINTR so that this thread can be dislodged if
2215 			 * a latent bug causes us to spin indefinitely.
2216 			 */
2217 			if (next > (uintptr_t)buf + size) {
2218 				pr_getprot_done(&tmp);
2219 				AS_LOCK_EXIT(as);
2220 
2221 				kmem_free(buf, size);
2222 
2223 				if (ISSIG(curthread, JUSTLOOKING))
2224 					return (EINTR);
2225 
2226 				goto again;
2227 			}
2228 
2229 			php->pr_nmap++;
2230 			php->pr_npage += npage;
2231 			pmp->pr_vaddr = (caddr32_t)(uintptr_t)saddr;
2232 			pmp->pr_npage = (size32_t)npage;
2233 			pmp->pr_offset = SEGOP_GETOFFSET(seg, saddr);
2234 			pmp->pr_mflags = 0;
2235 			if (prot & PROT_READ)
2236 				pmp->pr_mflags |= MA_READ;
2237 			if (prot & PROT_WRITE)
2238 				pmp->pr_mflags |= MA_WRITE;
2239 			if (prot & PROT_EXEC)
2240 				pmp->pr_mflags |= MA_EXEC;
2241 			if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
2242 				pmp->pr_mflags |= MA_SHARED;
2243 			if (SEGOP_GETTYPE(seg, saddr) & MAP_NORESERVE)
2244 				pmp->pr_mflags |= MA_NORESERVE;
2245 			if (seg->s_ops == &segspt_shmops ||
2246 			    (seg->s_ops == &segvn_ops &&
2247 			    (SEGOP_GETVP(seg, saddr, &vp) != 0 || vp == NULL)))
2248 				pmp->pr_mflags |= MA_ANON;
2249 			if (seg->s_ops == &segspt_shmops)
2250 				pmp->pr_mflags |= MA_ISM | MA_SHM;
2251 			pmp->pr_pagesize = PAGESIZE;
2252 			/*
2253 			 * Manufacture a filename for the "object" directory.
2254 			 */
2255 			vattr.va_mask = AT_FSID|AT_NODEID;
2256 			if (seg->s_ops == &segvn_ops &&
2257 			    SEGOP_GETVP(seg, saddr, &vp) == 0 &&
2258 			    vp != NULL && vp->v_type == VREG &&
2259 			    VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
2260 				if (vp == p->p_exec)
2261 					(void) strcpy(pmp->pr_mapname, "a.out");
2262 				else
2263 					pr_object_name(pmp->pr_mapname,
2264 					    vp, &vattr);
2265 			}
2266 
2267 			/*
2268 			 * Get the SysV shared memory id, if any.
2269 			 */
2270 			if ((pmp->pr_mflags & MA_SHARED) && p->p_segacct &&
2271 			    (pmp->pr_shmid = shmgetid(p, seg->s_base)) !=
2272 			    SHMID_NONE) {
2273 				if (pmp->pr_shmid == SHMID_FREE)
2274 					pmp->pr_shmid = -1;
2275 
2276 				pmp->pr_mflags |= MA_SHM;
2277 			} else {
2278 				pmp->pr_shmid = -1;
2279 			}
2280 
2281 			hat_getstat(as, saddr, len, hatid,
2282 			    (char *)(pmp + 1), HAT_SYNC_ZERORM);
2283 			pmp = (prasmap32_t *)next;
2284 		}
2285 		ASSERT(tmp == NULL);
2286 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
2287 
2288 	AS_LOCK_EXIT(as);
2289 
2290 	ASSERT((uintptr_t)pmp <= (uintptr_t)buf + size);
2291 	error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
2292 	kmem_free(buf, size);
2293 
2294 	return (error);
2295 }
2296 #endif	/* _SYSCALL32_IMPL */
2297 
2298 ushort_t
2299 prgetpctcpu(uint64_t pct)
2300 {
2301 	/*
2302 	 * The value returned will be relevant in the zone of the examiner,
2303 	 * which may not be the same as the zone which performed the procfs
2304 	 * mount.
2305 	 */
2306 	int nonline = zone_ncpus_online_get(curproc->p_zone);
2307 
2308 	/*
2309 	 * Prorate over online cpus so we don't exceed 100%
2310 	 */
2311 	if (nonline > 1)
2312 		pct /= nonline;
2313 	pct >>= 16;		/* convert to 16-bit scaled integer */
2314 	if (pct > 0x8000)	/* might happen, due to rounding */
2315 		pct = 0x8000;
2316 	return ((ushort_t)pct);
2317 }
2318 
2319 /*
2320  * Return information used by ps(1).
2321  */
2322 void
2323 prgetpsinfo(proc_t *p, psinfo_t *psp)
2324 {
2325 	kthread_t *t;
2326 	struct cred *cred;
2327 	hrtime_t hrutime, hrstime;
2328 
2329 	ASSERT(MUTEX_HELD(&p->p_lock));
2330 
2331 	if ((t = prchoose(p)) == NULL)	/* returns locked thread */
2332 		bzero(psp, sizeof (*psp));
2333 	else {
2334 		thread_unlock(t);
2335 		bzero(psp, sizeof (*psp) - sizeof (psp->pr_lwp));
2336 	}
2337 
2338 	/*
2339 	 * only export SSYS and SMSACCT; everything else is off-limits to
2340 	 * userland apps.
2341 	 */
2342 	psp->pr_flag = p->p_flag & (SSYS | SMSACCT);
2343 	psp->pr_nlwp = p->p_lwpcnt;
2344 	psp->pr_nzomb = p->p_zombcnt;
2345 	mutex_enter(&p->p_crlock);
2346 	cred = p->p_cred;
2347 	psp->pr_uid = crgetruid(cred);
2348 	psp->pr_euid = crgetuid(cred);
2349 	psp->pr_gid = crgetrgid(cred);
2350 	psp->pr_egid = crgetgid(cred);
2351 	mutex_exit(&p->p_crlock);
2352 	psp->pr_pid = p->p_pid;
2353 	if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
2354 	    (p->p_flag & SZONETOP)) {
2355 		ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
2356 		/*
2357 		 * Inside local zones, fake zsched's pid as parent pids for
2358 		 * processes which reference processes outside of the zone.
2359 		 */
2360 		psp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
2361 	} else {
2362 		psp->pr_ppid = p->p_ppid;
2363 	}
2364 	psp->pr_pgid = p->p_pgrp;
2365 	psp->pr_sid = p->p_sessp->s_sid;
2366 	psp->pr_taskid = p->p_task->tk_tkid;
2367 	psp->pr_projid = p->p_task->tk_proj->kpj_id;
2368 	psp->pr_poolid = p->p_pool->pool_id;
2369 	psp->pr_zoneid = p->p_zone->zone_id;
2370 	if ((psp->pr_contract = PRCTID(p)) == 0)
2371 		psp->pr_contract = -1;
2372 	psp->pr_addr = (uintptr_t)prgetpsaddr(p);
2373 	switch (p->p_model) {
2374 	case DATAMODEL_ILP32:
2375 		psp->pr_dmodel = PR_MODEL_ILP32;
2376 		break;
2377 	case DATAMODEL_LP64:
2378 		psp->pr_dmodel = PR_MODEL_LP64;
2379 		break;
2380 	}
2381 	hrutime = mstate_aggr_state(p, LMS_USER);
2382 	hrstime = mstate_aggr_state(p, LMS_SYSTEM);
2383 	hrt2ts((hrutime + hrstime), &psp->pr_time);
2384 	TICK_TO_TIMESTRUC(p->p_cutime + p->p_cstime, &psp->pr_ctime);
2385 
2386 	if (t == NULL) {
2387 		int wcode = p->p_wcode;		/* must be atomic read */
2388 
2389 		if (wcode)
2390 			psp->pr_wstat = wstat(wcode, p->p_wdata);
2391 		psp->pr_ttydev = PRNODEV;
2392 		psp->pr_lwp.pr_state = SZOMB;
2393 		psp->pr_lwp.pr_sname = 'Z';
2394 		psp->pr_lwp.pr_bindpro = PBIND_NONE;
2395 		psp->pr_lwp.pr_bindpset = PS_NONE;
2396 	} else {
2397 		user_t *up = PTOU(p);
2398 		struct as *as;
2399 		dev_t d;
2400 		extern dev_t rwsconsdev, rconsdev, uconsdev;
2401 
2402 		d = cttydev(p);
2403 		/*
2404 		 * If the controlling terminal is the real
2405 		 * or workstation console device, map to what the
2406 		 * user thinks is the console device. Handle case when
2407 		 * rwsconsdev or rconsdev is set to NODEV for Starfire.
2408 		 */
2409 		if ((d == rwsconsdev || d == rconsdev) && d != NODEV)
2410 			d = uconsdev;
2411 		psp->pr_ttydev = (d == NODEV) ? PRNODEV : d;
2412 		psp->pr_start = up->u_start;
2413 		bcopy(up->u_comm, psp->pr_fname,
2414 		    MIN(sizeof (up->u_comm), sizeof (psp->pr_fname)-1));
2415 		bcopy(up->u_psargs, psp->pr_psargs,
2416 		    MIN(PRARGSZ-1, PSARGSZ));
2417 		psp->pr_argc = up->u_argc;
2418 		psp->pr_argv = up->u_argv;
2419 		psp->pr_envp = up->u_envp;
2420 
2421 		/* get the chosen lwp's lwpsinfo */
2422 		prgetlwpsinfo(t, &psp->pr_lwp);
2423 
2424 		/* compute %cpu for the process */
2425 		if (p->p_lwpcnt == 1)
2426 			psp->pr_pctcpu = psp->pr_lwp.pr_pctcpu;
2427 		else {
2428 			uint64_t pct = 0;
2429 			hrtime_t cur_time = gethrtime_unscaled();
2430 
2431 			t = p->p_tlist;
2432 			do {
2433 				pct += cpu_update_pct(t, cur_time);
2434 			} while ((t = t->t_forw) != p->p_tlist);
2435 
2436 			psp->pr_pctcpu = prgetpctcpu(pct);
2437 		}
2438 		if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
2439 			psp->pr_size = 0;
2440 			psp->pr_rssize = 0;
2441 		} else {
2442 			mutex_exit(&p->p_lock);
2443 			AS_LOCK_ENTER(as, RW_READER);
2444 			psp->pr_size = btopr(as->a_resvsize) *
2445 			    (PAGESIZE / 1024);
2446 			psp->pr_rssize = rm_asrss(as) * (PAGESIZE / 1024);
2447 			psp->pr_pctmem = rm_pctmemory(as);
2448 			AS_LOCK_EXIT(as);
2449 			mutex_enter(&p->p_lock);
2450 		}
2451 	}
2452 }
2453 
2454 static size_t
2455 prfdinfomisc(list_t *data, uint_t type, const void *val, size_t vlen)
2456 {
2457 	pr_misc_header_t *misc;
2458 	size_t len;
2459 
2460 	len = PRFDINFO_ROUNDUP(sizeof (*misc) + vlen);
2461 
2462 	if (data != NULL) {
2463 		misc = pr_iol_newbuf(data, len);
2464 		misc->pr_misc_type = type;
2465 		misc->pr_misc_size = len;
2466 		misc++;
2467 		bcopy((char *)val, (char *)misc, vlen);
2468 	}
2469 
2470 	return (len);
2471 }
2472 
2473 /*
2474  * There's no elegant way to determine if a character device
2475  * supports TLI, so just check a hardcoded list of known TLI
2476  * devices.
2477  */
2478 
2479 static boolean_t
2480 pristli(vnode_t *vp)
2481 {
2482 	static const char *tlidevs[] = {
2483 	    "udp", "udp6", "tcp", "tcp6"
2484 	};
2485 	char *devname;
2486 	uint_t i;
2487 
2488 	ASSERT(vp != NULL);
2489 
2490 	if (vp->v_type != VCHR || vp->v_stream == NULL || vp->v_rdev == 0)
2491 		return (B_FALSE);
2492 
2493 	if ((devname = mod_major_to_name(getmajor(vp->v_rdev))) == NULL)
2494 		return (B_FALSE);
2495 
2496 	for (i = 0; i < ARRAY_SIZE(tlidevs); i++) {
2497 		if (strcmp(devname, tlidevs[i]) == 0)
2498 			return (B_TRUE);
2499 	}
2500 
2501 	return (B_FALSE);
2502 }
2503 
2504 static size_t
2505 prfdinfopath(proc_t *p, vnode_t *vp, list_t *data, cred_t *cred)
2506 {
2507 	char *pathname;
2508 	size_t pathlen;
2509 	size_t sz = 0;
2510 
2511 	pathlen = MAXPATHLEN + 1;
2512 	pathname = kmem_alloc(pathlen, KM_SLEEP);
2513 
2514 	if (vnodetopath(NULL, vp, pathname, pathlen, cred) == 0) {
2515 		sz += prfdinfomisc(data, PR_PATHNAME,
2516 		    pathname, strlen(pathname) + 1);
2517 	}
2518 
2519 	kmem_free(pathname, pathlen);
2520 	return (sz);
2521 }
2522 
2523 static size_t
2524 prfdinfotlisockopt(vnode_t *vp, list_t *data, cred_t *cred)
2525 {
2526 	strcmd_t strcmd;
2527 	int32_t rval;
2528 	size_t sz = 0;
2529 
2530 	strcmd.sc_cmd = TI_GETMYNAME;
2531 	strcmd.sc_timeout = 1;
2532 	strcmd.sc_len = STRCMDBUFSIZE;
2533 
2534 	if (VOP_IOCTL(vp, _I_CMD, (intptr_t)&strcmd, FKIOCTL, cred,
2535 	    &rval, NULL) == 0 && strcmd.sc_len > 0) {
2536 		sz += prfdinfomisc(data, PR_SOCKETNAME, strcmd.sc_buf,
2537 		    strcmd.sc_len);
2538 	}
2539 
2540 	strcmd.sc_cmd = TI_GETPEERNAME;
2541 	strcmd.sc_timeout = 1;
2542 	strcmd.sc_len = STRCMDBUFSIZE;
2543 
2544 	if (VOP_IOCTL(vp, _I_CMD, (intptr_t)&strcmd, FKIOCTL, cred,
2545 	    &rval, NULL) == 0 && strcmd.sc_len > 0) {
2546 		sz += prfdinfomisc(data, PR_PEERSOCKNAME, strcmd.sc_buf,
2547 		    strcmd.sc_len);
2548 	}
2549 
2550 	return (sz);
2551 }
2552 
2553 static size_t
2554 prfdinfosockopt(vnode_t *vp, list_t *data, cred_t *cred)
2555 {
2556 	sonode_t *so;
2557 	socklen_t vlen;
2558 	size_t sz = 0;
2559 	uint_t i;
2560 
2561 	if (vp->v_stream != NULL) {
2562 		so = VTOSO(vp->v_stream->sd_vnode);
2563 
2564 		if (so->so_version == SOV_STREAM)
2565 			so = NULL;
2566 	} else {
2567 		so = VTOSO(vp);
2568 	}
2569 
2570 	if (so == NULL)
2571 		return (0);
2572 
2573 	DTRACE_PROBE1(sonode, sonode_t *, so);
2574 
2575 	/* prmisc - PR_SOCKETNAME */
2576 
2577 	struct sockaddr_storage buf;
2578 	struct sockaddr *name = (struct sockaddr *)&buf;
2579 
2580 	vlen = sizeof (buf);
2581 	if (SOP_GETSOCKNAME(so, name, &vlen, cred) == 0 && vlen > 0)
2582 		sz += prfdinfomisc(data, PR_SOCKETNAME, name, vlen);
2583 
2584 	/* prmisc - PR_PEERSOCKNAME */
2585 
2586 	vlen = sizeof (buf);
2587 	if (SOP_GETPEERNAME(so, name, &vlen, B_FALSE, cred) == 0 && vlen > 0)
2588 		sz += prfdinfomisc(data, PR_PEERSOCKNAME, name, vlen);
2589 
2590 	/* prmisc - PR_SOCKOPTS_BOOL_OPTS */
2591 
2592 	static struct boolopt {
2593 		int		level;
2594 		int		opt;
2595 		int		bopt;
2596 	} boolopts[] = {
2597 		{ SOL_SOCKET, SO_DEBUG,		PR_SO_DEBUG },
2598 		{ SOL_SOCKET, SO_REUSEADDR,	PR_SO_REUSEADDR },
2599 #ifdef SO_REUSEPORT
2600 		/* SmartOS and OmniOS have SO_REUSEPORT */
2601 		{ SOL_SOCKET, SO_REUSEPORT,	PR_SO_REUSEPORT },
2602 #endif
2603 		{ SOL_SOCKET, SO_KEEPALIVE,	PR_SO_KEEPALIVE },
2604 		{ SOL_SOCKET, SO_DONTROUTE,	PR_SO_DONTROUTE },
2605 		{ SOL_SOCKET, SO_BROADCAST,	PR_SO_BROADCAST },
2606 		{ SOL_SOCKET, SO_OOBINLINE,	PR_SO_OOBINLINE },
2607 		{ SOL_SOCKET, SO_DGRAM_ERRIND,	PR_SO_DGRAM_ERRIND },
2608 		{ SOL_SOCKET, SO_ALLZONES,	PR_SO_ALLZONES },
2609 		{ SOL_SOCKET, SO_MAC_EXEMPT,	PR_SO_MAC_EXEMPT },
2610 		{ SOL_SOCKET, SO_MAC_IMPLICIT,	PR_SO_MAC_IMPLICIT },
2611 		{ SOL_SOCKET, SO_EXCLBIND,	PR_SO_EXCLBIND },
2612 		{ SOL_SOCKET, SO_VRRP,		PR_SO_VRRP },
2613 		{ IPPROTO_UDP, UDP_NAT_T_ENDPOINT,
2614 		    PR_UDP_NAT_T_ENDPOINT }
2615 	};
2616 	prsockopts_bool_opts_t opts;
2617 	int val;
2618 
2619 	if (data != NULL) {
2620 		opts.prsock_bool_opts = 0;
2621 
2622 		for (i = 0; i < ARRAY_SIZE(boolopts); i++) {
2623 			vlen = sizeof (val);
2624 			if (SOP_GETSOCKOPT(so, boolopts[i].level,
2625 			    boolopts[i].opt, &val, &vlen, 0, cred) == 0 &&
2626 			    val != 0) {
2627 				opts.prsock_bool_opts |= boolopts[i].bopt;
2628 			}
2629 		}
2630 	}
2631 
2632 	sz += prfdinfomisc(data, PR_SOCKOPTS_BOOL_OPTS, &opts, sizeof (opts));
2633 
2634 	/* prmisc - PR_SOCKOPT_LINGER */
2635 
2636 	struct linger l;
2637 
2638 	vlen = sizeof (l);
2639 	if (SOP_GETSOCKOPT(so, SOL_SOCKET, SO_LINGER, &l, &vlen,
2640 	    0, cred) == 0 && vlen > 0) {
2641 		sz += prfdinfomisc(data, PR_SOCKOPT_LINGER, &l, vlen);
2642 	}
2643 
2644 	/* prmisc - PR_SOCKOPT_* int types */
2645 
2646 	static struct sopt {
2647 		int		level;
2648 		int		opt;
2649 		int		bopt;
2650 	} sopts[] = {
2651 		{ SOL_SOCKET, SO_TYPE,		PR_SOCKOPT_TYPE },
2652 		{ SOL_SOCKET, SO_SNDBUF,	PR_SOCKOPT_SNDBUF },
2653 		{ SOL_SOCKET, SO_RCVBUF,	PR_SOCKOPT_RCVBUF }
2654 	};
2655 
2656 	for (i = 0; i < ARRAY_SIZE(sopts); i++) {
2657 		vlen = sizeof (val);
2658 		if (SOP_GETSOCKOPT(so, sopts[i].level, sopts[i].opt,
2659 		    &val, &vlen, 0, cred) == 0 && vlen > 0) {
2660 			sz += prfdinfomisc(data, sopts[i].bopt, &val, vlen);
2661 		}
2662 	}
2663 
2664 	/* prmisc - PR_SOCKOPT_IP_NEXTHOP */
2665 
2666 	in_addr_t nexthop_val;
2667 
2668 	vlen = sizeof (nexthop_val);
2669 	if (SOP_GETSOCKOPT(so, IPPROTO_IP, IP_NEXTHOP,
2670 	    &nexthop_val, &vlen, 0, cred) == 0 && vlen > 0) {
2671 		sz += prfdinfomisc(data, PR_SOCKOPT_IP_NEXTHOP,
2672 		    &nexthop_val, vlen);
2673 	}
2674 
2675 	/* prmisc - PR_SOCKOPT_IPV6_NEXTHOP */
2676 
2677 	struct sockaddr_in6 nexthop6_val;
2678 
2679 	vlen = sizeof (nexthop6_val);
2680 	if (SOP_GETSOCKOPT(so, IPPROTO_IPV6, IPV6_NEXTHOP,
2681 	    &nexthop6_val, &vlen, 0, cred) == 0 && vlen > 0) {
2682 		sz += prfdinfomisc(data, PR_SOCKOPT_IPV6_NEXTHOP,
2683 		    &nexthop6_val, vlen);
2684 	}
2685 
2686 	/* prmisc - PR_SOCKOPT_TCP_CONGESTION */
2687 
2688 	char cong[CC_ALGO_NAME_MAX];
2689 
2690 	vlen = sizeof (cong);
2691 	if (SOP_GETSOCKOPT(so, IPPROTO_TCP, TCP_CONGESTION,
2692 	    &cong, &vlen, 0, cred) == 0 && vlen > 0) {
2693 		sz += prfdinfomisc(data, PR_SOCKOPT_TCP_CONGESTION, cong, vlen);
2694 	}
2695 
2696 	/* prmisc - PR_SOCKFILTERS_PRIV */
2697 
2698 	struct fil_info fi;
2699 
2700 	vlen = sizeof (fi);
2701 	if (SOP_GETSOCKOPT(so, SOL_FILTER, FIL_LIST,
2702 	    &fi, &vlen, 0, cred) == 0 && vlen != 0) {
2703 		pr_misc_header_t *misc;
2704 		size_t len;
2705 
2706 		/*
2707 		 * We limit the number of returned filters to 32.
2708 		 * This is the maximum number that pfiles will print
2709 		 * anyway.
2710 		 */
2711 		vlen = MIN(32, fi.fi_pos + 1);
2712 		vlen *= sizeof (fi);
2713 
2714 		len = PRFDINFO_ROUNDUP(sizeof (*misc) + vlen);
2715 		sz += len;
2716 
2717 		if (data != NULL) {
2718 			/*
2719 			 * So that the filter list can be built incrementally,
2720 			 * prfdinfomisc() is not used here. Instead we
2721 			 * allocate a buffer directly on the copyout list using
2722 			 * pr_iol_newbuf()
2723 			 */
2724 			misc = pr_iol_newbuf(data, len);
2725 			misc->pr_misc_type = PR_SOCKFILTERS_PRIV;
2726 			misc->pr_misc_size = len;
2727 			misc++;
2728 			len = vlen;
2729 			if (SOP_GETSOCKOPT(so, SOL_FILTER, FIL_LIST,
2730 			    misc, &vlen, 0, cred) == 0) {
2731 				/*
2732 				 * In case the number of filters has reduced
2733 				 * since the first call, explicitly zero out
2734 				 * any unpopulated space.
2735 				 */
2736 				if (vlen < len)
2737 					bzero(misc + vlen, len - vlen);
2738 			} else {
2739 				/* Something went wrong, zero out the result */
2740 				bzero(misc, vlen);
2741 			}
2742 		}
2743 	}
2744 
2745 	return (sz);
2746 }
2747 
2748 u_offset_t
2749 prgetfdinfosize(proc_t *p, vnode_t *vp, cred_t *cred)
2750 {
2751 	u_offset_t sz;
2752 
2753 	/*
2754 	 * All fdinfo files will be at least this big -
2755 	 * sizeof fdinfo struct + zero length trailer
2756 	 */
2757 	sz = offsetof(prfdinfo_t, pr_misc) + sizeof (pr_misc_header_t);
2758 
2759 	/* Pathname */
2760 	if (vp->v_type != VSOCK && vp->v_type != VDOOR)
2761 		sz += prfdinfopath(p, vp, NULL, cred);
2762 
2763 	/* Socket options */
2764 	if (vp->v_type == VSOCK)
2765 		sz += prfdinfosockopt(vp, NULL, cred);
2766 
2767 	/* TLI/XTI sockets */
2768 	if (pristli(vp))
2769 		sz += prfdinfotlisockopt(vp, NULL, cred);
2770 
2771 	return (sz);
2772 }
2773 
2774 int
2775 prgetfdinfo(proc_t *p, vnode_t *vp, prfdinfo_t *fdinfo, cred_t *cred,
2776     cred_t *file_cred, list_t *data)
2777 {
2778 	vattr_t vattr;
2779 	int error;
2780 
2781 	/*
2782 	 * The buffer has been initialised to zero by pr_iol_newbuf().
2783 	 * Initialise defaults for any values that should not default to zero.
2784 	 */
2785 	fdinfo->pr_uid = (uid_t)-1;
2786 	fdinfo->pr_gid = (gid_t)-1;
2787 	fdinfo->pr_size = -1;
2788 	fdinfo->pr_locktype = F_UNLCK;
2789 	fdinfo->pr_lockpid = -1;
2790 	fdinfo->pr_locksysid = -1;
2791 	fdinfo->pr_peerpid = -1;
2792 
2793 	/* Offset */
2794 
2795 	/*
2796 	 * pr_offset has already been set from the underlying file_t.
2797 	 * Check if it is plausible and reset to -1 if not.
2798 	 */
2799 	if (fdinfo->pr_offset != -1 &&
2800 	    VOP_SEEK(vp, 0, (offset_t *)&fdinfo->pr_offset, NULL) != 0)
2801 		fdinfo->pr_offset = -1;
2802 
2803 	/*
2804 	 * Attributes
2805 	 *
2806 	 * We have two cred_t structures available here.
2807 	 * 'cred' is the caller's credential, and 'file_cred' is the credential
2808 	 * for the file being inspected.
2809 	 *
2810 	 * When looking up the file attributes, file_cred is used in order
2811 	 * that the correct ownership is set for doors and FIFOs. Since the
2812 	 * caller has permission to read the fdinfo file in proc, this does
2813 	 * not expose any additional information.
2814 	 */
2815 	vattr.va_mask = AT_STAT;
2816 	if (VOP_GETATTR(vp, &vattr, 0, file_cred, NULL) == 0) {
2817 		fdinfo->pr_major = getmajor(vattr.va_fsid);
2818 		fdinfo->pr_minor = getminor(vattr.va_fsid);
2819 		fdinfo->pr_rmajor = getmajor(vattr.va_rdev);
2820 		fdinfo->pr_rminor = getminor(vattr.va_rdev);
2821 		fdinfo->pr_ino = (ino64_t)vattr.va_nodeid;
2822 		fdinfo->pr_size = (off64_t)vattr.va_size;
2823 		fdinfo->pr_mode = VTTOIF(vattr.va_type) | vattr.va_mode;
2824 		fdinfo->pr_uid = vattr.va_uid;
2825 		fdinfo->pr_gid = vattr.va_gid;
2826 		if (vp->v_type == VSOCK)
2827 			fdinfo->pr_fileflags |= sock_getfasync(vp);
2828 	}
2829 
2830 	/* locks */
2831 
2832 	flock64_t bf;
2833 
2834 	bzero(&bf, sizeof (bf));
2835 	bf.l_type = F_WRLCK;
2836 
2837 	if (VOP_FRLOCK(vp, F_GETLK, &bf,
2838 	    (uint16_t)(fdinfo->pr_fileflags & 0xffff), 0, NULL,
2839 	    cred, NULL) == 0 && bf.l_type != F_UNLCK) {
2840 		fdinfo->pr_locktype = bf.l_type;
2841 		fdinfo->pr_lockpid = bf.l_pid;
2842 		fdinfo->pr_locksysid = bf.l_sysid;
2843 	}
2844 
2845 	/* peer cred */
2846 
2847 	k_peercred_t kpc;
2848 
2849 	switch (vp->v_type) {
2850 	case VFIFO:
2851 	case VSOCK: {
2852 		int32_t rval;
2853 
2854 		error = VOP_IOCTL(vp, _I_GETPEERCRED, (intptr_t)&kpc,
2855 		    FKIOCTL, cred, &rval, NULL);
2856 		break;
2857 	}
2858 	case VCHR: {
2859 		struct strioctl strioc;
2860 		int32_t rval;
2861 
2862 		if (vp->v_stream == NULL) {
2863 			error = ENOTSUP;
2864 			break;
2865 		}
2866 		strioc.ic_cmd = _I_GETPEERCRED;
2867 		strioc.ic_timout = INFTIM;
2868 		strioc.ic_len = (int)sizeof (k_peercred_t);
2869 		strioc.ic_dp = (char *)&kpc;
2870 
2871 		error = strdoioctl(vp->v_stream, &strioc, FNATIVE | FKIOCTL,
2872 		    STR_NOSIG | K_TO_K, cred, &rval);
2873 		break;
2874 	}
2875 	default:
2876 		error = ENOTSUP;
2877 		break;
2878 	}
2879 
2880 	if (error == 0 && kpc.pc_cr != NULL) {
2881 		proc_t *peerp;
2882 
2883 		fdinfo->pr_peerpid = kpc.pc_cpid;
2884 
2885 		crfree(kpc.pc_cr);
2886 
2887 		mutex_enter(&pidlock);
2888 		if ((peerp = prfind(fdinfo->pr_peerpid)) != NULL) {
2889 			user_t *up;
2890 
2891 			mutex_enter(&peerp->p_lock);
2892 			mutex_exit(&pidlock);
2893 
2894 			up = PTOU(peerp);
2895 			bcopy(up->u_comm, fdinfo->pr_peername,
2896 			    MIN(sizeof (up->u_comm),
2897 			    sizeof (fdinfo->pr_peername) - 1));
2898 
2899 			mutex_exit(&peerp->p_lock);
2900 		} else {
2901 			mutex_exit(&pidlock);
2902 		}
2903 	}
2904 
2905 	/*
2906 	 * Don't attempt to determine the vnode path for a socket or a door
2907 	 * as it will cause a linear scan of the dnlc table given there is no
2908 	 * v_path associated with the vnode.
2909 	 */
2910 	if (vp->v_type != VSOCK && vp->v_type != VDOOR)
2911 		(void) prfdinfopath(p, vp, data, cred);
2912 
2913 	if (vp->v_type == VSOCK)
2914 		(void) prfdinfosockopt(vp, data, cred);
2915 
2916 	/* TLI/XTI stream sockets */
2917 	if (pristli(vp))
2918 		(void) prfdinfotlisockopt(vp, data, cred);
2919 
2920 	/*
2921 	 * Add a terminating header with a zero size.
2922 	 */
2923 	pr_misc_header_t *misc;
2924 
2925 	misc = pr_iol_newbuf(data, sizeof (*misc));
2926 	misc->pr_misc_size = 0;
2927 	misc->pr_misc_type = (uint_t)-1;
2928 
2929 	return (0);
2930 }
2931 
2932 #ifdef _SYSCALL32_IMPL
2933 void
2934 prgetpsinfo32(proc_t *p, psinfo32_t *psp)
2935 {
2936 	kthread_t *t;
2937 	struct cred *cred;
2938 	hrtime_t hrutime, hrstime;
2939 
2940 	ASSERT(MUTEX_HELD(&p->p_lock));
2941 
2942 	if ((t = prchoose(p)) == NULL)	/* returns locked thread */
2943 		bzero(psp, sizeof (*psp));
2944 	else {
2945 		thread_unlock(t);
2946 		bzero(psp, sizeof (*psp) - sizeof (psp->pr_lwp));
2947 	}
2948 
2949 	/*
2950 	 * only export SSYS and SMSACCT; everything else is off-limits to
2951 	 * userland apps.
2952 	 */
2953 	psp->pr_flag = p->p_flag & (SSYS | SMSACCT);
2954 	psp->pr_nlwp = p->p_lwpcnt;
2955 	psp->pr_nzomb = p->p_zombcnt;
2956 	mutex_enter(&p->p_crlock);
2957 	cred = p->p_cred;
2958 	psp->pr_uid = crgetruid(cred);
2959 	psp->pr_euid = crgetuid(cred);
2960 	psp->pr_gid = crgetrgid(cred);
2961 	psp->pr_egid = crgetgid(cred);
2962 	mutex_exit(&p->p_crlock);
2963 	psp->pr_pid = p->p_pid;
2964 	if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
2965 	    (p->p_flag & SZONETOP)) {
2966 		ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
2967 		/*
2968 		 * Inside local zones, fake zsched's pid as parent pids for
2969 		 * processes which reference processes outside of the zone.
2970 		 */
2971 		psp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
2972 	} else {
2973 		psp->pr_ppid = p->p_ppid;
2974 	}
2975 	psp->pr_pgid = p->p_pgrp;
2976 	psp->pr_sid = p->p_sessp->s_sid;
2977 	psp->pr_taskid = p->p_task->tk_tkid;
2978 	psp->pr_projid = p->p_task->tk_proj->kpj_id;
2979 	psp->pr_poolid = p->p_pool->pool_id;
2980 	psp->pr_zoneid = p->p_zone->zone_id;
2981 	if ((psp->pr_contract = PRCTID(p)) == 0)
2982 		psp->pr_contract = -1;
2983 	psp->pr_addr = 0;	/* cannot represent 64-bit addr in 32 bits */
2984 	switch (p->p_model) {
2985 	case DATAMODEL_ILP32:
2986 		psp->pr_dmodel = PR_MODEL_ILP32;
2987 		break;
2988 	case DATAMODEL_LP64:
2989 		psp->pr_dmodel = PR_MODEL_LP64;
2990 		break;
2991 	}
2992 	hrutime = mstate_aggr_state(p, LMS_USER);
2993 	hrstime = mstate_aggr_state(p, LMS_SYSTEM);
2994 	hrt2ts32(hrutime + hrstime, &psp->pr_time);
2995 	TICK_TO_TIMESTRUC32(p->p_cutime + p->p_cstime, &psp->pr_ctime);
2996 
2997 	if (t == NULL) {
2998 		extern int wstat(int, int);	/* needs a header file */
2999 		int wcode = p->p_wcode;		/* must be atomic read */
3000 
3001 		if (wcode)
3002 			psp->pr_wstat = wstat(wcode, p->p_wdata);
3003 		psp->pr_ttydev = PRNODEV32;
3004 		psp->pr_lwp.pr_state = SZOMB;
3005 		psp->pr_lwp.pr_sname = 'Z';
3006 	} else {
3007 		user_t *up = PTOU(p);
3008 		struct as *as;
3009 		dev_t d;
3010 		extern dev_t rwsconsdev, rconsdev, uconsdev;
3011 
3012 		d = cttydev(p);
3013 		/*
3014 		 * If the controlling terminal is the real
3015 		 * or workstation console device, map to what the
3016 		 * user thinks is the console device. Handle case when
3017 		 * rwsconsdev or rconsdev is set to NODEV for Starfire.
3018 		 */
3019 		if ((d == rwsconsdev || d == rconsdev) && d != NODEV)
3020 			d = uconsdev;
3021 		(void) cmpldev(&psp->pr_ttydev, d);
3022 		TIMESPEC_TO_TIMESPEC32(&psp->pr_start, &up->u_start);
3023 		bcopy(up->u_comm, psp->pr_fname,
3024 		    MIN(sizeof (up->u_comm), sizeof (psp->pr_fname)-1));
3025 		bcopy(up->u_psargs, psp->pr_psargs,
3026 		    MIN(PRARGSZ-1, PSARGSZ));
3027 		psp->pr_argc = up->u_argc;
3028 		psp->pr_argv = (caddr32_t)up->u_argv;
3029 		psp->pr_envp = (caddr32_t)up->u_envp;
3030 
3031 		/* get the chosen lwp's lwpsinfo */
3032 		prgetlwpsinfo32(t, &psp->pr_lwp);
3033 
3034 		/* compute %cpu for the process */
3035 		if (p->p_lwpcnt == 1)
3036 			psp->pr_pctcpu = psp->pr_lwp.pr_pctcpu;
3037 		else {
3038 			uint64_t pct = 0;
3039 			hrtime_t cur_time;
3040 
3041 			t = p->p_tlist;
3042 			cur_time = gethrtime_unscaled();
3043 			do {
3044 				pct += cpu_update_pct(t, cur_time);
3045 			} while ((t = t->t_forw) != p->p_tlist);
3046 
3047 			psp->pr_pctcpu = prgetpctcpu(pct);
3048 		}
3049 		if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
3050 			psp->pr_size = 0;
3051 			psp->pr_rssize = 0;
3052 		} else {
3053 			mutex_exit(&p->p_lock);
3054 			AS_LOCK_ENTER(as, RW_READER);
3055 			psp->pr_size = (size32_t)
3056 			    (btopr(as->a_resvsize) * (PAGESIZE / 1024));
3057 			psp->pr_rssize = (size32_t)
3058 			    (rm_asrss(as) * (PAGESIZE / 1024));
3059 			psp->pr_pctmem = rm_pctmemory(as);
3060 			AS_LOCK_EXIT(as);
3061 			mutex_enter(&p->p_lock);
3062 		}
3063 	}
3064 
3065 	/*
3066 	 * If we are looking at an LP64 process, zero out
3067 	 * the fields that cannot be represented in ILP32.
3068 	 */
3069 	if (p->p_model != DATAMODEL_ILP32) {
3070 		psp->pr_size = 0;
3071 		psp->pr_rssize = 0;
3072 		psp->pr_argv = 0;
3073 		psp->pr_envp = 0;
3074 	}
3075 }
3076 
3077 #endif	/* _SYSCALL32_IMPL */
3078 
3079 void
3080 prgetlwpsinfo(kthread_t *t, lwpsinfo_t *psp)
3081 {
3082 	klwp_t *lwp = ttolwp(t);
3083 	sobj_ops_t *sobj;
3084 	char c, state;
3085 	uint64_t pct;
3086 	int retval, niceval;
3087 	hrtime_t hrutime, hrstime;
3088 
3089 	ASSERT(MUTEX_HELD(&ttoproc(t)->p_lock));
3090 
3091 	bzero(psp, sizeof (*psp));
3092 
3093 	psp->pr_flag = 0;	/* lwpsinfo_t.pr_flag is deprecated */
3094 	psp->pr_lwpid = t->t_tid;
3095 	psp->pr_addr = (uintptr_t)t;
3096 	psp->pr_wchan = (uintptr_t)t->t_wchan;
3097 
3098 	/* map the thread state enum into a process state enum */
3099 	state = VSTOPPED(t) ? TS_STOPPED : t->t_state;
3100 	switch (state) {
3101 	case TS_SLEEP:		state = SSLEEP;		c = 'S';	break;
3102 	case TS_RUN:		state = SRUN;		c = 'R';	break;
3103 	case TS_ONPROC:		state = SONPROC;	c = 'O';	break;
3104 	case TS_ZOMB:		state = SZOMB;		c = 'Z';	break;
3105 	case TS_STOPPED:	state = SSTOP;		c = 'T';	break;
3106 	case TS_WAIT:		state = SWAIT;		c = 'W';	break;
3107 	default:		state = 0;		c = '?';	break;
3108 	}
3109 	psp->pr_state = state;
3110 	psp->pr_sname = c;
3111 	if ((sobj = t->t_sobj_ops) != NULL)
3112 		psp->pr_stype = SOBJ_TYPE(sobj);
3113 	retval = CL_DONICE(t, NULL, 0, &niceval);
3114 	if (retval == 0) {
3115 		psp->pr_oldpri = v.v_maxsyspri - t->t_pri;
3116 		psp->pr_nice = niceval + NZERO;
3117 	}
3118 	psp->pr_syscall = t->t_sysnum;
3119 	psp->pr_pri = t->t_pri;
3120 	psp->pr_start.tv_sec = t->t_start;
3121 	psp->pr_start.tv_nsec = 0L;
3122 	hrutime = lwp->lwp_mstate.ms_acct[LMS_USER];
3123 	scalehrtime(&hrutime);
3124 	hrstime = lwp->lwp_mstate.ms_acct[LMS_SYSTEM] +
3125 	    lwp->lwp_mstate.ms_acct[LMS_TRAP];
3126 	scalehrtime(&hrstime);
3127 	hrt2ts(hrutime + hrstime, &psp->pr_time);
3128 	/* compute %cpu for the lwp */
3129 	pct = cpu_update_pct(t, gethrtime_unscaled());
3130 	psp->pr_pctcpu = prgetpctcpu(pct);
3131 	psp->pr_cpu = (psp->pr_pctcpu*100 + 0x6000) >> 15;	/* [0..99] */
3132 	if (psp->pr_cpu > 99)
3133 		psp->pr_cpu = 99;
3134 
3135 	(void) strncpy(psp->pr_clname, sclass[t->t_cid].cl_name,
3136 	    sizeof (psp->pr_clname) - 1);
3137 	bzero(psp->pr_name, sizeof (psp->pr_name));	/* XXX ??? */
3138 	psp->pr_onpro = t->t_cpu->cpu_id;
3139 	psp->pr_bindpro = t->t_bind_cpu;
3140 	psp->pr_bindpset = t->t_bind_pset;
3141 	psp->pr_lgrp = t->t_lpl->lpl_lgrpid;
3142 }
3143 
3144 #ifdef _SYSCALL32_IMPL
3145 void
3146 prgetlwpsinfo32(kthread_t *t, lwpsinfo32_t *psp)
3147 {
3148 	proc_t *p = ttoproc(t);
3149 	klwp_t *lwp = ttolwp(t);
3150 	sobj_ops_t *sobj;
3151 	char c, state;
3152 	uint64_t pct;
3153 	int retval, niceval;
3154 	hrtime_t hrutime, hrstime;
3155 
3156 	ASSERT(MUTEX_HELD(&p->p_lock));
3157 
3158 	bzero(psp, sizeof (*psp));
3159 
3160 	psp->pr_flag = 0;	/* lwpsinfo_t.pr_flag is deprecated */
3161 	psp->pr_lwpid = t->t_tid;
3162 	psp->pr_addr = 0;	/* cannot represent 64-bit addr in 32 bits */
3163 	psp->pr_wchan = 0;	/* cannot represent 64-bit addr in 32 bits */
3164 
3165 	/* map the thread state enum into a process state enum */
3166 	state = VSTOPPED(t) ? TS_STOPPED : t->t_state;
3167 	switch (state) {
3168 	case TS_SLEEP:		state = SSLEEP;		c = 'S';	break;
3169 	case TS_RUN:		state = SRUN;		c = 'R';	break;
3170 	case TS_ONPROC:		state = SONPROC;	c = 'O';	break;
3171 	case TS_ZOMB:		state = SZOMB;		c = 'Z';	break;
3172 	case TS_STOPPED:	state = SSTOP;		c = 'T';	break;
3173 	case TS_WAIT:		state = SWAIT;		c = 'W';	break;
3174 	default:		state = 0;		c = '?';	break;
3175 	}
3176 	psp->pr_state = state;
3177 	psp->pr_sname = c;
3178 	if ((sobj = t->t_sobj_ops) != NULL)
3179 		psp->pr_stype = SOBJ_TYPE(sobj);
3180 	retval = CL_DONICE(t, NULL, 0, &niceval);
3181 	if (retval == 0) {
3182 		psp->pr_oldpri = v.v_maxsyspri - t->t_pri;
3183 		psp->pr_nice = niceval + NZERO;
3184 	} else {
3185 		psp->pr_oldpri = 0;
3186 		psp->pr_nice = 0;
3187 	}
3188 	psp->pr_syscall = t->t_sysnum;
3189 	psp->pr_pri = t->t_pri;
3190 	psp->pr_start.tv_sec = (time32_t)t->t_start;
3191 	psp->pr_start.tv_nsec = 0L;
3192 	hrutime = lwp->lwp_mstate.ms_acct[LMS_USER];
3193 	scalehrtime(&hrutime);
3194 	hrstime = lwp->lwp_mstate.ms_acct[LMS_SYSTEM] +
3195 	    lwp->lwp_mstate.ms_acct[LMS_TRAP];
3196 	scalehrtime(&hrstime);
3197 	hrt2ts32(hrutime + hrstime, &psp->pr_time);
3198 	/* compute %cpu for the lwp */
3199 	pct = cpu_update_pct(t, gethrtime_unscaled());
3200 	psp->pr_pctcpu = prgetpctcpu(pct);
3201 	psp->pr_cpu = (psp->pr_pctcpu*100 + 0x6000) >> 15;	/* [0..99] */
3202 	if (psp->pr_cpu > 99)
3203 		psp->pr_cpu = 99;
3204 
3205 	(void) strncpy(psp->pr_clname, sclass[t->t_cid].cl_name,
3206 	    sizeof (psp->pr_clname) - 1);
3207 	bzero(psp->pr_name, sizeof (psp->pr_name));	/* XXX ??? */
3208 	psp->pr_onpro = t->t_cpu->cpu_id;
3209 	psp->pr_bindpro = t->t_bind_cpu;
3210 	psp->pr_bindpset = t->t_bind_pset;
3211 	psp->pr_lgrp = t->t_lpl->lpl_lgrpid;
3212 }
3213 #endif	/* _SYSCALL32_IMPL */
3214 
3215 #ifdef _SYSCALL32_IMPL
3216 
3217 #define	PR_COPY_FIELD(s, d, field)	 d->field = s->field
3218 
3219 #define	PR_COPY_FIELD_ILP32(s, d, field)				\
3220 	if (s->pr_dmodel == PR_MODEL_ILP32) {			\
3221 		d->field = s->field;				\
3222 	}
3223 
3224 #define	PR_COPY_TIMESPEC(s, d, field)				\
3225 	TIMESPEC_TO_TIMESPEC32(&d->field, &s->field);
3226 
3227 #define	PR_COPY_BUF(s, d, field)				\
3228 	bcopy(s->field, d->field, sizeof (d->field));
3229 
3230 #define	PR_IGNORE_FIELD(s, d, field)
3231 
3232 void
3233 lwpsinfo_kto32(const struct lwpsinfo *src, struct lwpsinfo32 *dest)
3234 {
3235 	bzero(dest, sizeof (*dest));
3236 
3237 	PR_COPY_FIELD(src, dest, pr_flag);
3238 	PR_COPY_FIELD(src, dest, pr_lwpid);
3239 	PR_IGNORE_FIELD(src, dest, pr_addr);
3240 	PR_IGNORE_FIELD(src, dest, pr_wchan);
3241 	PR_COPY_FIELD(src, dest, pr_stype);
3242 	PR_COPY_FIELD(src, dest, pr_state);
3243 	PR_COPY_FIELD(src, dest, pr_sname);
3244 	PR_COPY_FIELD(src, dest, pr_nice);
3245 	PR_COPY_FIELD(src, dest, pr_syscall);
3246 	PR_COPY_FIELD(src, dest, pr_oldpri);
3247 	PR_COPY_FIELD(src, dest, pr_cpu);
3248 	PR_COPY_FIELD(src, dest, pr_pri);
3249 	PR_COPY_FIELD(src, dest, pr_pctcpu);
3250 	PR_COPY_TIMESPEC(src, dest, pr_start);
3251 	PR_COPY_BUF(src, dest, pr_clname);
3252 	PR_COPY_BUF(src, dest, pr_name);
3253 	PR_COPY_FIELD(src, dest, pr_onpro);
3254 	PR_COPY_FIELD(src, dest, pr_bindpro);
3255 	PR_COPY_FIELD(src, dest, pr_bindpset);
3256 	PR_COPY_FIELD(src, dest, pr_lgrp);
3257 }
3258 
3259 void
3260 psinfo_kto32(const struct psinfo *src, struct psinfo32 *dest)
3261 {
3262 	bzero(dest, sizeof (*dest));
3263 
3264 	PR_COPY_FIELD(src, dest, pr_flag);
3265 	PR_COPY_FIELD(src, dest, pr_nlwp);
3266 	PR_COPY_FIELD(src, dest, pr_pid);
3267 	PR_COPY_FIELD(src, dest, pr_ppid);
3268 	PR_COPY_FIELD(src, dest, pr_pgid);
3269 	PR_COPY_FIELD(src, dest, pr_sid);
3270 	PR_COPY_FIELD(src, dest, pr_uid);
3271 	PR_COPY_FIELD(src, dest, pr_euid);
3272 	PR_COPY_FIELD(src, dest, pr_gid);
3273 	PR_COPY_FIELD(src, dest, pr_egid);
3274 	PR_IGNORE_FIELD(src, dest, pr_addr);
3275 	PR_COPY_FIELD_ILP32(src, dest, pr_size);
3276 	PR_COPY_FIELD_ILP32(src, dest, pr_rssize);
3277 	PR_COPY_FIELD(src, dest, pr_ttydev);
3278 	PR_COPY_FIELD(src, dest, pr_pctcpu);
3279 	PR_COPY_FIELD(src, dest, pr_pctmem);
3280 	PR_COPY_TIMESPEC(src, dest, pr_start);
3281 	PR_COPY_TIMESPEC(src, dest, pr_time);
3282 	PR_COPY_TIMESPEC(src, dest, pr_ctime);
3283 	PR_COPY_BUF(src, dest, pr_fname);
3284 	PR_COPY_BUF(src, dest, pr_psargs);
3285 	PR_COPY_FIELD(src, dest, pr_wstat);
3286 	PR_COPY_FIELD(src, dest, pr_argc);
3287 	PR_COPY_FIELD_ILP32(src, dest, pr_argv);
3288 	PR_COPY_FIELD_ILP32(src, dest, pr_envp);
3289 	PR_COPY_FIELD(src, dest, pr_dmodel);
3290 	PR_COPY_FIELD(src, dest, pr_taskid);
3291 	PR_COPY_FIELD(src, dest, pr_projid);
3292 	PR_COPY_FIELD(src, dest, pr_nzomb);
3293 	PR_COPY_FIELD(src, dest, pr_poolid);
3294 	PR_COPY_FIELD(src, dest, pr_contract);
3295 	PR_COPY_FIELD(src, dest, pr_poolid);
3296 	PR_COPY_FIELD(src, dest, pr_poolid);
3297 
3298 	lwpsinfo_kto32(&src->pr_lwp, &dest->pr_lwp);
3299 }
3300 
3301 #undef	PR_COPY_FIELD
3302 #undef	PR_COPY_FIELD_ILP32
3303 #undef	PR_COPY_TIMESPEC
3304 #undef	PR_COPY_BUF
3305 #undef	PR_IGNORE_FIELD
3306 
3307 #endif	/* _SYSCALL32_IMPL */
3308 
3309 /*
3310  * This used to get called when microstate accounting was disabled but
3311  * microstate information was requested.  Since Microstate accounting is on
3312  * regardless of the proc flags, this simply makes it appear to procfs that
3313  * microstate accounting is on.  This is relatively meaningless since you
3314  * can't turn it off, but this is here for the sake of appearances.
3315  */
3316 
3317 /*ARGSUSED*/
3318 void
3319 estimate_msacct(kthread_t *t, hrtime_t curtime)
3320 {
3321 	proc_t *p;
3322 
3323 	if (t == NULL)
3324 		return;
3325 
3326 	p = ttoproc(t);
3327 	ASSERT(MUTEX_HELD(&p->p_lock));
3328 
3329 	/*
3330 	 * A system process (p0) could be referenced if the thread is
3331 	 * in the process of exiting.  Don't turn on microstate accounting
3332 	 * in that case.
3333 	 */
3334 	if (p->p_flag & SSYS)
3335 		return;
3336 
3337 	/*
3338 	 * Loop through all the LWPs (kernel threads) in the process.
3339 	 */
3340 	t = p->p_tlist;
3341 	do {
3342 		t->t_proc_flag |= TP_MSACCT;
3343 	} while ((t = t->t_forw) != p->p_tlist);
3344 
3345 	p->p_flag |= SMSACCT;			/* set process-wide MSACCT */
3346 }
3347 
3348 /*
3349  * It's not really possible to disable microstate accounting anymore.
3350  * However, this routine simply turns off the ms accounting flags in a process
3351  * This way procfs can still pretend to turn microstate accounting on and
3352  * off for a process, but it actually doesn't do anything.  This is
3353  * a neutered form of preemptive idiot-proofing.
3354  */
3355 void
3356 disable_msacct(proc_t *p)
3357 {
3358 	kthread_t *t;
3359 
3360 	ASSERT(MUTEX_HELD(&p->p_lock));
3361 
3362 	p->p_flag &= ~SMSACCT;		/* clear process-wide MSACCT */
3363 	/*
3364 	 * Loop through all the LWPs (kernel threads) in the process.
3365 	 */
3366 	if ((t = p->p_tlist) != NULL) {
3367 		do {
3368 			/* clear per-thread flag */
3369 			t->t_proc_flag &= ~TP_MSACCT;
3370 		} while ((t = t->t_forw) != p->p_tlist);
3371 	}
3372 }
3373 
3374 /*
3375  * Return resource usage information.
3376  */
3377 void
3378 prgetusage(kthread_t *t, prhusage_t *pup)
3379 {
3380 	klwp_t *lwp = ttolwp(t);
3381 	hrtime_t *mstimep;
3382 	struct mstate *ms = &lwp->lwp_mstate;
3383 	int state;
3384 	int i;
3385 	hrtime_t curtime;
3386 	hrtime_t waitrq;
3387 	hrtime_t tmp1;
3388 
3389 	curtime = gethrtime_unscaled();
3390 
3391 	pup->pr_lwpid	= t->t_tid;
3392 	pup->pr_count	= 1;
3393 	pup->pr_create	= ms->ms_start;
3394 	pup->pr_term    = ms->ms_term;
3395 	scalehrtime(&pup->pr_create);
3396 	scalehrtime(&pup->pr_term);
3397 	if (ms->ms_term == 0) {
3398 		pup->pr_rtime = curtime - ms->ms_start;
3399 		scalehrtime(&pup->pr_rtime);
3400 	} else {
3401 		pup->pr_rtime = ms->ms_term - ms->ms_start;
3402 		scalehrtime(&pup->pr_rtime);
3403 	}
3404 
3405 
3406 	pup->pr_utime    = ms->ms_acct[LMS_USER];
3407 	pup->pr_stime    = ms->ms_acct[LMS_SYSTEM];
3408 	pup->pr_ttime    = ms->ms_acct[LMS_TRAP];
3409 	pup->pr_tftime   = ms->ms_acct[LMS_TFAULT];
3410 	pup->pr_dftime   = ms->ms_acct[LMS_DFAULT];
3411 	pup->pr_kftime   = ms->ms_acct[LMS_KFAULT];
3412 	pup->pr_ltime    = ms->ms_acct[LMS_USER_LOCK];
3413 	pup->pr_slptime  = ms->ms_acct[LMS_SLEEP];
3414 	pup->pr_wtime    = ms->ms_acct[LMS_WAIT_CPU];
3415 	pup->pr_stoptime = ms->ms_acct[LMS_STOPPED];
3416 
3417 	prscaleusage(pup);
3418 
3419 	/*
3420 	 * Adjust for time waiting in the dispatcher queue.
3421 	 */
3422 	waitrq = t->t_waitrq;	/* hopefully atomic */
3423 	if (waitrq != 0) {
3424 		if (waitrq > curtime) {
3425 			curtime = gethrtime_unscaled();
3426 		}
3427 		tmp1 = curtime - waitrq;
3428 		scalehrtime(&tmp1);
3429 		pup->pr_wtime += tmp1;
3430 		curtime = waitrq;
3431 	}
3432 
3433 	/*
3434 	 * Adjust for time spent in current microstate.
3435 	 */
3436 	if (ms->ms_state_start > curtime) {
3437 		curtime = gethrtime_unscaled();
3438 	}
3439 
3440 	i = 0;
3441 	do {
3442 		switch (state = t->t_mstate) {
3443 		case LMS_SLEEP:
3444 			/*
3445 			 * Update the timer for the current sleep state.
3446 			 */
3447 			switch (state = ms->ms_prev) {
3448 			case LMS_TFAULT:
3449 			case LMS_DFAULT:
3450 			case LMS_KFAULT:
3451 			case LMS_USER_LOCK:
3452 				break;
3453 			default:
3454 				state = LMS_SLEEP;
3455 				break;
3456 			}
3457 			break;
3458 		case LMS_TFAULT:
3459 		case LMS_DFAULT:
3460 		case LMS_KFAULT:
3461 		case LMS_USER_LOCK:
3462 			state = LMS_SYSTEM;
3463 			break;
3464 		}
3465 		switch (state) {
3466 		case LMS_USER:		mstimep = &pup->pr_utime;	break;
3467 		case LMS_SYSTEM:	mstimep = &pup->pr_stime;	break;
3468 		case LMS_TRAP:		mstimep = &pup->pr_ttime;	break;
3469 		case LMS_TFAULT:	mstimep = &pup->pr_tftime;	break;
3470 		case LMS_DFAULT:	mstimep = &pup->pr_dftime;	break;
3471 		case LMS_KFAULT:	mstimep = &pup->pr_kftime;	break;
3472 		case LMS_USER_LOCK:	mstimep = &pup->pr_ltime;	break;
3473 		case LMS_SLEEP:		mstimep = &pup->pr_slptime;	break;
3474 		case LMS_WAIT_CPU:	mstimep = &pup->pr_wtime;	break;
3475 		case LMS_STOPPED:	mstimep = &pup->pr_stoptime;	break;
3476 		default:		panic("prgetusage: unknown microstate");
3477 		}
3478 		tmp1 = curtime - ms->ms_state_start;
3479 		if (tmp1 < 0) {
3480 			curtime = gethrtime_unscaled();
3481 			i++;
3482 			continue;
3483 		}
3484 		scalehrtime(&tmp1);
3485 	} while (tmp1 < 0 && i < MAX_ITERS_SPIN);
3486 
3487 	*mstimep += tmp1;
3488 
3489 	/* update pup timestamp */
3490 	pup->pr_tstamp = curtime;
3491 	scalehrtime(&pup->pr_tstamp);
3492 
3493 	/*
3494 	 * Resource usage counters.
3495 	 */
3496 	pup->pr_minf  = lwp->lwp_ru.minflt;
3497 	pup->pr_majf  = lwp->lwp_ru.majflt;
3498 	pup->pr_nswap = lwp->lwp_ru.nswap;
3499 	pup->pr_inblk = lwp->lwp_ru.inblock;
3500 	pup->pr_oublk = lwp->lwp_ru.oublock;
3501 	pup->pr_msnd  = lwp->lwp_ru.msgsnd;
3502 	pup->pr_mrcv  = lwp->lwp_ru.msgrcv;
3503 	pup->pr_sigs  = lwp->lwp_ru.nsignals;
3504 	pup->pr_vctx  = lwp->lwp_ru.nvcsw;
3505 	pup->pr_ictx  = lwp->lwp_ru.nivcsw;
3506 	pup->pr_sysc  = lwp->lwp_ru.sysc;
3507 	pup->pr_ioch  = lwp->lwp_ru.ioch;
3508 }
3509 
3510 /*
3511  * Convert ms_acct stats from unscaled high-res time to nanoseconds
3512  */
3513 void
3514 prscaleusage(prhusage_t *usg)
3515 {
3516 	scalehrtime(&usg->pr_utime);
3517 	scalehrtime(&usg->pr_stime);
3518 	scalehrtime(&usg->pr_ttime);
3519 	scalehrtime(&usg->pr_tftime);
3520 	scalehrtime(&usg->pr_dftime);
3521 	scalehrtime(&usg->pr_kftime);
3522 	scalehrtime(&usg->pr_ltime);
3523 	scalehrtime(&usg->pr_slptime);
3524 	scalehrtime(&usg->pr_wtime);
3525 	scalehrtime(&usg->pr_stoptime);
3526 }
3527 
3528 
3529 /*
3530  * Sum resource usage information.
3531  */
3532 void
3533 praddusage(kthread_t *t, prhusage_t *pup)
3534 {
3535 	klwp_t *lwp = ttolwp(t);
3536 	hrtime_t *mstimep;
3537 	struct mstate *ms = &lwp->lwp_mstate;
3538 	int state;
3539 	int i;
3540 	hrtime_t curtime;
3541 	hrtime_t waitrq;
3542 	hrtime_t tmp;
3543 	prhusage_t conv;
3544 
3545 	curtime = gethrtime_unscaled();
3546 
3547 	if (ms->ms_term == 0) {
3548 		tmp = curtime - ms->ms_start;
3549 		scalehrtime(&tmp);
3550 		pup->pr_rtime += tmp;
3551 	} else {
3552 		tmp = ms->ms_term - ms->ms_start;
3553 		scalehrtime(&tmp);
3554 		pup->pr_rtime += tmp;
3555 	}
3556 
3557 	conv.pr_utime = ms->ms_acct[LMS_USER];
3558 	conv.pr_stime = ms->ms_acct[LMS_SYSTEM];
3559 	conv.pr_ttime = ms->ms_acct[LMS_TRAP];
3560 	conv.pr_tftime = ms->ms_acct[LMS_TFAULT];
3561 	conv.pr_dftime = ms->ms_acct[LMS_DFAULT];
3562 	conv.pr_kftime = ms->ms_acct[LMS_KFAULT];
3563 	conv.pr_ltime = ms->ms_acct[LMS_USER_LOCK];
3564 	conv.pr_slptime = ms->ms_acct[LMS_SLEEP];
3565 	conv.pr_wtime = ms->ms_acct[LMS_WAIT_CPU];
3566 	conv.pr_stoptime = ms->ms_acct[LMS_STOPPED];
3567 
3568 	prscaleusage(&conv);
3569 
3570 	pup->pr_utime	+= conv.pr_utime;
3571 	pup->pr_stime	+= conv.pr_stime;
3572 	pup->pr_ttime	+= conv.pr_ttime;
3573 	pup->pr_tftime	+= conv.pr_tftime;
3574 	pup->pr_dftime	+= conv.pr_dftime;
3575 	pup->pr_kftime	+= conv.pr_kftime;
3576 	pup->pr_ltime	+= conv.pr_ltime;
3577 	pup->pr_slptime	+= conv.pr_slptime;
3578 	pup->pr_wtime	+= conv.pr_wtime;
3579 	pup->pr_stoptime += conv.pr_stoptime;
3580 
3581 	/*
3582 	 * Adjust for time waiting in the dispatcher queue.
3583 	 */
3584 	waitrq = t->t_waitrq;	/* hopefully atomic */
3585 	if (waitrq != 0) {
3586 		if (waitrq > curtime) {
3587 			curtime = gethrtime_unscaled();
3588 		}
3589 		tmp = curtime - waitrq;
3590 		scalehrtime(&tmp);
3591 		pup->pr_wtime += tmp;
3592 		curtime = waitrq;
3593 	}
3594 
3595 	/*
3596 	 * Adjust for time spent in current microstate.
3597 	 */
3598 	if (ms->ms_state_start > curtime) {
3599 		curtime = gethrtime_unscaled();
3600 	}
3601 
3602 	i = 0;
3603 	do {
3604 		switch (state = t->t_mstate) {
3605 		case LMS_SLEEP:
3606 			/*
3607 			 * Update the timer for the current sleep state.
3608 			 */
3609 			switch (state = ms->ms_prev) {
3610 			case LMS_TFAULT:
3611 			case LMS_DFAULT:
3612 			case LMS_KFAULT:
3613 			case LMS_USER_LOCK:
3614 				break;
3615 			default:
3616 				state = LMS_SLEEP;
3617 				break;
3618 			}
3619 			break;
3620 		case LMS_TFAULT:
3621 		case LMS_DFAULT:
3622 		case LMS_KFAULT:
3623 		case LMS_USER_LOCK:
3624 			state = LMS_SYSTEM;
3625 			break;
3626 		}
3627 		switch (state) {
3628 		case LMS_USER:		mstimep = &pup->pr_utime;	break;
3629 		case LMS_SYSTEM:	mstimep = &pup->pr_stime;	break;
3630 		case LMS_TRAP:		mstimep = &pup->pr_ttime;	break;
3631 		case LMS_TFAULT:	mstimep = &pup->pr_tftime;	break;
3632 		case LMS_DFAULT:	mstimep = &pup->pr_dftime;	break;
3633 		case LMS_KFAULT:	mstimep = &pup->pr_kftime;	break;
3634 		case LMS_USER_LOCK:	mstimep = &pup->pr_ltime;	break;
3635 		case LMS_SLEEP:		mstimep = &pup->pr_slptime;	break;
3636 		case LMS_WAIT_CPU:	mstimep = &pup->pr_wtime;	break;
3637 		case LMS_STOPPED:	mstimep = &pup->pr_stoptime;	break;
3638 		default:		panic("praddusage: unknown microstate");
3639 		}
3640 		tmp = curtime - ms->ms_state_start;
3641 		if (tmp < 0) {
3642 			curtime = gethrtime_unscaled();
3643 			i++;
3644 			continue;
3645 		}
3646 		scalehrtime(&tmp);
3647 	} while (tmp < 0 && i < MAX_ITERS_SPIN);
3648 
3649 	*mstimep += tmp;
3650 
3651 	/* update pup timestamp */
3652 	pup->pr_tstamp = curtime;
3653 	scalehrtime(&pup->pr_tstamp);
3654 
3655 	/*
3656 	 * Resource usage counters.
3657 	 */
3658 	pup->pr_minf  += lwp->lwp_ru.minflt;
3659 	pup->pr_majf  += lwp->lwp_ru.majflt;
3660 	pup->pr_nswap += lwp->lwp_ru.nswap;
3661 	pup->pr_inblk += lwp->lwp_ru.inblock;
3662 	pup->pr_oublk += lwp->lwp_ru.oublock;
3663 	pup->pr_msnd  += lwp->lwp_ru.msgsnd;
3664 	pup->pr_mrcv  += lwp->lwp_ru.msgrcv;
3665 	pup->pr_sigs  += lwp->lwp_ru.nsignals;
3666 	pup->pr_vctx  += lwp->lwp_ru.nvcsw;
3667 	pup->pr_ictx  += lwp->lwp_ru.nivcsw;
3668 	pup->pr_sysc  += lwp->lwp_ru.sysc;
3669 	pup->pr_ioch  += lwp->lwp_ru.ioch;
3670 }
3671 
3672 /*
3673  * Convert a prhusage_t to a prusage_t.
3674  * This means convert each hrtime_t to a timestruc_t
3675  * and copy the count fields uint64_t => ulong_t.
3676  */
3677 void
3678 prcvtusage(prhusage_t *pup, prusage_t *upup)
3679 {
3680 	uint64_t *ullp;
3681 	ulong_t *ulp;
3682 	int i;
3683 
3684 	upup->pr_lwpid = pup->pr_lwpid;
3685 	upup->pr_count = pup->pr_count;
3686 
3687 	hrt2ts(pup->pr_tstamp,	&upup->pr_tstamp);
3688 	hrt2ts(pup->pr_create,	&upup->pr_create);
3689 	hrt2ts(pup->pr_term,	&upup->pr_term);
3690 	hrt2ts(pup->pr_rtime,	&upup->pr_rtime);
3691 	hrt2ts(pup->pr_utime,	&upup->pr_utime);
3692 	hrt2ts(pup->pr_stime,	&upup->pr_stime);
3693 	hrt2ts(pup->pr_ttime,	&upup->pr_ttime);
3694 	hrt2ts(pup->pr_tftime,	&upup->pr_tftime);
3695 	hrt2ts(pup->pr_dftime,	&upup->pr_dftime);
3696 	hrt2ts(pup->pr_kftime,	&upup->pr_kftime);
3697 	hrt2ts(pup->pr_ltime,	&upup->pr_ltime);
3698 	hrt2ts(pup->pr_slptime,	&upup->pr_slptime);
3699 	hrt2ts(pup->pr_wtime,	&upup->pr_wtime);
3700 	hrt2ts(pup->pr_stoptime, &upup->pr_stoptime);
3701 	bzero(upup->filltime, sizeof (upup->filltime));
3702 
3703 	ullp = &pup->pr_minf;
3704 	ulp = &upup->pr_minf;
3705 	for (i = 0; i < 22; i++)
3706 		*ulp++ = (ulong_t)*ullp++;
3707 }
3708 
3709 #ifdef _SYSCALL32_IMPL
3710 void
3711 prcvtusage32(prhusage_t *pup, prusage32_t *upup)
3712 {
3713 	uint64_t *ullp;
3714 	uint32_t *ulp;
3715 	int i;
3716 
3717 	upup->pr_lwpid = pup->pr_lwpid;
3718 	upup->pr_count = pup->pr_count;
3719 
3720 	hrt2ts32(pup->pr_tstamp,	&upup->pr_tstamp);
3721 	hrt2ts32(pup->pr_create,	&upup->pr_create);
3722 	hrt2ts32(pup->pr_term,		&upup->pr_term);
3723 	hrt2ts32(pup->pr_rtime,		&upup->pr_rtime);
3724 	hrt2ts32(pup->pr_utime,		&upup->pr_utime);
3725 	hrt2ts32(pup->pr_stime,		&upup->pr_stime);
3726 	hrt2ts32(pup->pr_ttime,		&upup->pr_ttime);
3727 	hrt2ts32(pup->pr_tftime,	&upup->pr_tftime);
3728 	hrt2ts32(pup->pr_dftime,	&upup->pr_dftime);
3729 	hrt2ts32(pup->pr_kftime,	&upup->pr_kftime);
3730 	hrt2ts32(pup->pr_ltime,		&upup->pr_ltime);
3731 	hrt2ts32(pup->pr_slptime,	&upup->pr_slptime);
3732 	hrt2ts32(pup->pr_wtime,		&upup->pr_wtime);
3733 	hrt2ts32(pup->pr_stoptime,	&upup->pr_stoptime);
3734 	bzero(upup->filltime, sizeof (upup->filltime));
3735 
3736 	ullp = &pup->pr_minf;
3737 	ulp = &upup->pr_minf;
3738 	for (i = 0; i < 22; i++)
3739 		*ulp++ = (uint32_t)*ullp++;
3740 }
3741 #endif	/* _SYSCALL32_IMPL */
3742 
3743 /*
3744  * Determine whether a set is empty.
3745  */
3746 int
3747 setisempty(uint32_t *sp, uint_t n)
3748 {
3749 	while (n--)
3750 		if (*sp++)
3751 			return (0);
3752 	return (1);
3753 }
3754 
3755 /*
3756  * Utility routine for establishing a watched area in the process.
3757  * Keep the list of watched areas sorted by virtual address.
3758  */
3759 int
3760 set_watched_area(proc_t *p, struct watched_area *pwa)
3761 {
3762 	caddr_t vaddr = pwa->wa_vaddr;
3763 	caddr_t eaddr = pwa->wa_eaddr;
3764 	ulong_t flags = pwa->wa_flags;
3765 	struct watched_area *target;
3766 	avl_index_t where;
3767 	int error = 0;
3768 
3769 	/* we must not be holding p->p_lock, but the process must be locked */
3770 	ASSERT(MUTEX_NOT_HELD(&p->p_lock));
3771 	ASSERT(p->p_proc_flag & P_PR_LOCK);
3772 
3773 	/*
3774 	 * If this is our first watchpoint, enable watchpoints for the process.
3775 	 */
3776 	if (!pr_watch_active(p)) {
3777 		kthread_t *t;
3778 
3779 		mutex_enter(&p->p_lock);
3780 		if ((t = p->p_tlist) != NULL) {
3781 			do {
3782 				watch_enable(t);
3783 			} while ((t = t->t_forw) != p->p_tlist);
3784 		}
3785 		mutex_exit(&p->p_lock);
3786 	}
3787 
3788 	target = pr_find_watched_area(p, pwa, &where);
3789 	if (target != NULL) {
3790 		/*
3791 		 * We discovered an existing, overlapping watched area.
3792 		 * Allow it only if it is an exact match.
3793 		 */
3794 		if (target->wa_vaddr != vaddr ||
3795 		    target->wa_eaddr != eaddr)
3796 			error = EINVAL;
3797 		else if (target->wa_flags != flags) {
3798 			error = set_watched_page(p, vaddr, eaddr,
3799 			    flags, target->wa_flags);
3800 			target->wa_flags = flags;
3801 		}
3802 		kmem_free(pwa, sizeof (struct watched_area));
3803 	} else {
3804 		avl_insert(&p->p_warea, pwa, where);
3805 		error = set_watched_page(p, vaddr, eaddr, flags, 0);
3806 	}
3807 
3808 	return (error);
3809 }
3810 
3811 /*
3812  * Utility routine for clearing a watched area in the process.
3813  * Must be an exact match of the virtual address.
3814  * size and flags don't matter.
3815  */
3816 int
3817 clear_watched_area(proc_t *p, struct watched_area *pwa)
3818 {
3819 	struct watched_area *found;
3820 
3821 	/* we must not be holding p->p_lock, but the process must be locked */
3822 	ASSERT(MUTEX_NOT_HELD(&p->p_lock));
3823 	ASSERT(p->p_proc_flag & P_PR_LOCK);
3824 
3825 
3826 	if (!pr_watch_active(p)) {
3827 		kmem_free(pwa, sizeof (struct watched_area));
3828 		return (0);
3829 	}
3830 
3831 	/*
3832 	 * Look for a matching address in the watched areas.  If a match is
3833 	 * found, clear the old watched area and adjust the watched page(s).  It
3834 	 * is not an error if there is no match.
3835 	 */
3836 	if ((found = pr_find_watched_area(p, pwa, NULL)) != NULL &&
3837 	    found->wa_vaddr == pwa->wa_vaddr) {
3838 		clear_watched_page(p, found->wa_vaddr, found->wa_eaddr,
3839 		    found->wa_flags);
3840 		avl_remove(&p->p_warea, found);
3841 		kmem_free(found, sizeof (struct watched_area));
3842 	}
3843 
3844 	kmem_free(pwa, sizeof (struct watched_area));
3845 
3846 	/*
3847 	 * If we removed the last watched area from the process, disable
3848 	 * watchpoints.
3849 	 */
3850 	if (!pr_watch_active(p)) {
3851 		kthread_t *t;
3852 
3853 		mutex_enter(&p->p_lock);
3854 		if ((t = p->p_tlist) != NULL) {
3855 			do {
3856 				watch_disable(t);
3857 			} while ((t = t->t_forw) != p->p_tlist);
3858 		}
3859 		mutex_exit(&p->p_lock);
3860 	}
3861 
3862 	return (0);
3863 }
3864 
3865 /*
3866  * Frees all the watched_area structures
3867  */
3868 void
3869 pr_free_watchpoints(proc_t *p)
3870 {
3871 	struct watched_area *delp;
3872 	void *cookie;
3873 
3874 	cookie = NULL;
3875 	while ((delp = avl_destroy_nodes(&p->p_warea, &cookie)) != NULL)
3876 		kmem_free(delp, sizeof (struct watched_area));
3877 
3878 	avl_destroy(&p->p_warea);
3879 }
3880 
3881 /*
3882  * This one is called by the traced process to unwatch all the
3883  * pages while deallocating the list of watched_page structs.
3884  */
3885 void
3886 pr_free_watched_pages(proc_t *p)
3887 {
3888 	struct as *as = p->p_as;
3889 	struct watched_page *pwp;
3890 	uint_t prot;
3891 	int    retrycnt, err;
3892 	void *cookie;
3893 
3894 	if (as == NULL || avl_numnodes(&as->a_wpage) == 0)
3895 		return;
3896 
3897 	ASSERT(MUTEX_NOT_HELD(&curproc->p_lock));
3898 	AS_LOCK_ENTER(as, RW_WRITER);
3899 
3900 	pwp = avl_first(&as->a_wpage);
3901 
3902 	cookie = NULL;
3903 	while ((pwp = avl_destroy_nodes(&as->a_wpage, &cookie)) != NULL) {
3904 		retrycnt = 0;
3905 		if ((prot = pwp->wp_oprot) != 0) {
3906 			caddr_t addr = pwp->wp_vaddr;
3907 			struct seg *seg;
3908 		retry:
3909 
3910 			if ((pwp->wp_prot != prot ||
3911 			    (pwp->wp_flags & WP_NOWATCH)) &&
3912 			    (seg = as_segat(as, addr)) != NULL) {
3913 				err = SEGOP_SETPROT(seg, addr, PAGESIZE, prot);
3914 				if (err == IE_RETRY) {
3915 					ASSERT(retrycnt == 0);
3916 					retrycnt++;
3917 					goto retry;
3918 				}
3919 			}
3920 		}
3921 		kmem_free(pwp, sizeof (struct watched_page));
3922 	}
3923 
3924 	avl_destroy(&as->a_wpage);
3925 	p->p_wprot = NULL;
3926 
3927 	AS_LOCK_EXIT(as);
3928 }
3929 
3930 /*
3931  * Insert a watched area into the list of watched pages.
3932  * If oflags is zero then we are adding a new watched area.
3933  * Otherwise we are changing the flags of an existing watched area.
3934  */
3935 static int
3936 set_watched_page(proc_t *p, caddr_t vaddr, caddr_t eaddr,
3937     ulong_t flags, ulong_t oflags)
3938 {
3939 	struct as *as = p->p_as;
3940 	avl_tree_t *pwp_tree;
3941 	struct watched_page *pwp, *newpwp;
3942 	struct watched_page tpw;
3943 	avl_index_t where;
3944 	struct seg *seg;
3945 	uint_t prot;
3946 	caddr_t addr;
3947 
3948 	/*
3949 	 * We need to pre-allocate a list of structures before we grab the
3950 	 * address space lock to avoid calling kmem_alloc(KM_SLEEP) with locks
3951 	 * held.
3952 	 */
3953 	newpwp = NULL;
3954 	for (addr = (caddr_t)((uintptr_t)vaddr & (uintptr_t)PAGEMASK);
3955 	    addr < eaddr; addr += PAGESIZE) {
3956 		pwp = kmem_zalloc(sizeof (struct watched_page), KM_SLEEP);
3957 		pwp->wp_list = newpwp;
3958 		newpwp = pwp;
3959 	}
3960 
3961 	AS_LOCK_ENTER(as, RW_WRITER);
3962 
3963 	/*
3964 	 * Search for an existing watched page to contain the watched area.
3965 	 * If none is found, grab a new one from the available list
3966 	 * and insert it in the active list, keeping the list sorted
3967 	 * by user-level virtual address.
3968 	 */
3969 	if (p->p_flag & SVFWAIT)
3970 		pwp_tree = &p->p_wpage;
3971 	else
3972 		pwp_tree = &as->a_wpage;
3973 
3974 again:
3975 	if (avl_numnodes(pwp_tree) > prnwatch) {
3976 		AS_LOCK_EXIT(as);
3977 		while (newpwp != NULL) {
3978 			pwp = newpwp->wp_list;
3979 			kmem_free(newpwp, sizeof (struct watched_page));
3980 			newpwp = pwp;
3981 		}
3982 		return (E2BIG);
3983 	}
3984 
3985 	tpw.wp_vaddr = (caddr_t)((uintptr_t)vaddr & (uintptr_t)PAGEMASK);
3986 	if ((pwp = avl_find(pwp_tree, &tpw, &where)) == NULL) {
3987 		pwp = newpwp;
3988 		newpwp = newpwp->wp_list;
3989 		pwp->wp_list = NULL;
3990 		pwp->wp_vaddr = (caddr_t)((uintptr_t)vaddr &
3991 		    (uintptr_t)PAGEMASK);
3992 		avl_insert(pwp_tree, pwp, where);
3993 	}
3994 
3995 	ASSERT(vaddr >= pwp->wp_vaddr && vaddr < pwp->wp_vaddr + PAGESIZE);
3996 
3997 	if (oflags & WA_READ)
3998 		pwp->wp_read--;
3999 	if (oflags & WA_WRITE)
4000 		pwp->wp_write--;
4001 	if (oflags & WA_EXEC)
4002 		pwp->wp_exec--;
4003 
4004 	ASSERT(pwp->wp_read >= 0);
4005 	ASSERT(pwp->wp_write >= 0);
4006 	ASSERT(pwp->wp_exec >= 0);
4007 
4008 	if (flags & WA_READ)
4009 		pwp->wp_read++;
4010 	if (flags & WA_WRITE)
4011 		pwp->wp_write++;
4012 	if (flags & WA_EXEC)
4013 		pwp->wp_exec++;
4014 
4015 	if (!(p->p_flag & SVFWAIT)) {
4016 		vaddr = pwp->wp_vaddr;
4017 		if (pwp->wp_oprot == 0 &&
4018 		    (seg = as_segat(as, vaddr)) != NULL) {
4019 			SEGOP_GETPROT(seg, vaddr, 0, &prot);
4020 			pwp->wp_oprot = (uchar_t)prot;
4021 			pwp->wp_prot = (uchar_t)prot;
4022 		}
4023 		if (pwp->wp_oprot != 0) {
4024 			prot = pwp->wp_oprot;
4025 			if (pwp->wp_read)
4026 				prot &= ~(PROT_READ|PROT_WRITE|PROT_EXEC);
4027 			if (pwp->wp_write)
4028 				prot &= ~PROT_WRITE;
4029 			if (pwp->wp_exec)
4030 				prot &= ~(PROT_READ|PROT_WRITE|PROT_EXEC);
4031 			if (!(pwp->wp_flags & WP_NOWATCH) &&
4032 			    pwp->wp_prot != prot &&
4033 			    (pwp->wp_flags & WP_SETPROT) == 0) {
4034 				pwp->wp_flags |= WP_SETPROT;
4035 				pwp->wp_list = p->p_wprot;
4036 				p->p_wprot = pwp;
4037 			}
4038 			pwp->wp_prot = (uchar_t)prot;
4039 		}
4040 	}
4041 
4042 	/*
4043 	 * If the watched area extends into the next page then do
4044 	 * it over again with the virtual address of the next page.
4045 	 */
4046 	if ((vaddr = pwp->wp_vaddr + PAGESIZE) < eaddr)
4047 		goto again;
4048 
4049 	AS_LOCK_EXIT(as);
4050 
4051 	/*
4052 	 * Free any pages we may have over-allocated
4053 	 */
4054 	while (newpwp != NULL) {
4055 		pwp = newpwp->wp_list;
4056 		kmem_free(newpwp, sizeof (struct watched_page));
4057 		newpwp = pwp;
4058 	}
4059 
4060 	return (0);
4061 }
4062 
4063 /*
4064  * Remove a watched area from the list of watched pages.
4065  * A watched area may extend over more than one page.
4066  */
4067 static void
4068 clear_watched_page(proc_t *p, caddr_t vaddr, caddr_t eaddr, ulong_t flags)
4069 {
4070 	struct as *as = p->p_as;
4071 	struct watched_page *pwp;
4072 	struct watched_page tpw;
4073 	avl_tree_t *tree;
4074 	avl_index_t where;
4075 
4076 	AS_LOCK_ENTER(as, RW_WRITER);
4077 
4078 	if (p->p_flag & SVFWAIT)
4079 		tree = &p->p_wpage;
4080 	else
4081 		tree = &as->a_wpage;
4082 
4083 	tpw.wp_vaddr = vaddr =
4084 	    (caddr_t)((uintptr_t)vaddr & (uintptr_t)PAGEMASK);
4085 	pwp = avl_find(tree, &tpw, &where);
4086 	if (pwp == NULL)
4087 		pwp = avl_nearest(tree, where, AVL_AFTER);
4088 
4089 	while (pwp != NULL && pwp->wp_vaddr < eaddr) {
4090 		ASSERT(vaddr <=  pwp->wp_vaddr);
4091 
4092 		if (flags & WA_READ)
4093 			pwp->wp_read--;
4094 		if (flags & WA_WRITE)
4095 			pwp->wp_write--;
4096 		if (flags & WA_EXEC)
4097 			pwp->wp_exec--;
4098 
4099 		if (pwp->wp_read + pwp->wp_write + pwp->wp_exec != 0) {
4100 			/*
4101 			 * Reset the hat layer's protections on this page.
4102 			 */
4103 			if (pwp->wp_oprot != 0) {
4104 				uint_t prot = pwp->wp_oprot;
4105 
4106 				if (pwp->wp_read)
4107 					prot &=
4108 					    ~(PROT_READ|PROT_WRITE|PROT_EXEC);
4109 				if (pwp->wp_write)
4110 					prot &= ~PROT_WRITE;
4111 				if (pwp->wp_exec)
4112 					prot &=
4113 					    ~(PROT_READ|PROT_WRITE|PROT_EXEC);
4114 				if (!(pwp->wp_flags & WP_NOWATCH) &&
4115 				    pwp->wp_prot != prot &&
4116 				    (pwp->wp_flags & WP_SETPROT) == 0) {
4117 					pwp->wp_flags |= WP_SETPROT;
4118 					pwp->wp_list = p->p_wprot;
4119 					p->p_wprot = pwp;
4120 				}
4121 				pwp->wp_prot = (uchar_t)prot;
4122 			}
4123 		} else {
4124 			/*
4125 			 * No watched areas remain in this page.
4126 			 * Reset everything to normal.
4127 			 */
4128 			if (pwp->wp_oprot != 0) {
4129 				pwp->wp_prot = pwp->wp_oprot;
4130 				if ((pwp->wp_flags & WP_SETPROT) == 0) {
4131 					pwp->wp_flags |= WP_SETPROT;
4132 					pwp->wp_list = p->p_wprot;
4133 					p->p_wprot = pwp;
4134 				}
4135 			}
4136 		}
4137 
4138 		pwp = AVL_NEXT(tree, pwp);
4139 	}
4140 
4141 	AS_LOCK_EXIT(as);
4142 }
4143 
4144 /*
4145  * Return the original protections for the specified page.
4146  */
4147 static void
4148 getwatchprot(struct as *as, caddr_t addr, uint_t *prot)
4149 {
4150 	struct watched_page *pwp;
4151 	struct watched_page tpw;
4152 
4153 	ASSERT(AS_LOCK_HELD(as));
4154 
4155 	tpw.wp_vaddr = (caddr_t)((uintptr_t)addr & (uintptr_t)PAGEMASK);
4156 	if ((pwp = avl_find(&as->a_wpage, &tpw, NULL)) != NULL)
4157 		*prot = pwp->wp_oprot;
4158 }
4159 
4160 static prpagev_t *
4161 pr_pagev_create(struct seg *seg, int check_noreserve)
4162 {
4163 	prpagev_t *pagev = kmem_alloc(sizeof (prpagev_t), KM_SLEEP);
4164 	size_t total_pages = seg_pages(seg);
4165 
4166 	/*
4167 	 * Limit the size of our vectors to pagev_lim pages at a time.  We need
4168 	 * 4 or 5 bytes of storage per page, so this means we limit ourself
4169 	 * to about a megabyte of kernel heap by default.
4170 	 */
4171 	pagev->pg_npages = MIN(total_pages, pagev_lim);
4172 	pagev->pg_pnbase = 0;
4173 
4174 	pagev->pg_protv =
4175 	    kmem_alloc(pagev->pg_npages * sizeof (uint_t), KM_SLEEP);
4176 
4177 	if (check_noreserve)
4178 		pagev->pg_incore =
4179 		    kmem_alloc(pagev->pg_npages * sizeof (char), KM_SLEEP);
4180 	else
4181 		pagev->pg_incore = NULL;
4182 
4183 	return (pagev);
4184 }
4185 
4186 static void
4187 pr_pagev_destroy(prpagev_t *pagev)
4188 {
4189 	if (pagev->pg_incore != NULL)
4190 		kmem_free(pagev->pg_incore, pagev->pg_npages * sizeof (char));
4191 
4192 	kmem_free(pagev->pg_protv, pagev->pg_npages * sizeof (uint_t));
4193 	kmem_free(pagev, sizeof (prpagev_t));
4194 }
4195 
4196 static caddr_t
4197 pr_pagev_fill(prpagev_t *pagev, struct seg *seg, caddr_t addr, caddr_t eaddr)
4198 {
4199 	ulong_t lastpg = seg_page(seg, eaddr - 1);
4200 	ulong_t pn, pnlim;
4201 	caddr_t saddr;
4202 	size_t len;
4203 
4204 	ASSERT(addr >= seg->s_base && addr <= eaddr);
4205 
4206 	if (addr == eaddr)
4207 		return (eaddr);
4208 
4209 refill:
4210 	ASSERT(addr < eaddr);
4211 	pagev->pg_pnbase = seg_page(seg, addr);
4212 	pnlim = pagev->pg_pnbase + pagev->pg_npages;
4213 	saddr = addr;
4214 
4215 	if (lastpg < pnlim)
4216 		len = (size_t)(eaddr - addr);
4217 	else
4218 		len = pagev->pg_npages * PAGESIZE;
4219 
4220 	if (pagev->pg_incore != NULL) {
4221 		/*
4222 		 * INCORE cleverly has different semantics than GETPROT:
4223 		 * it returns info on pages up to but NOT including addr + len.
4224 		 */
4225 		SEGOP_INCORE(seg, addr, len, pagev->pg_incore);
4226 		pn = pagev->pg_pnbase;
4227 
4228 		do {
4229 			/*
4230 			 * Guilty knowledge here:  We know that segvn_incore
4231 			 * returns more than just the low-order bit that
4232 			 * indicates the page is actually in memory.  If any
4233 			 * bits are set, then the page has backing store.
4234 			 */
4235 			if (pagev->pg_incore[pn++ - pagev->pg_pnbase])
4236 				goto out;
4237 
4238 		} while ((addr += PAGESIZE) < eaddr && pn < pnlim);
4239 
4240 		/*
4241 		 * If we examined all the pages in the vector but we're not
4242 		 * at the end of the segment, take another lap.
4243 		 */
4244 		if (addr < eaddr)
4245 			goto refill;
4246 	}
4247 
4248 	/*
4249 	 * Need to take len - 1 because addr + len is the address of the
4250 	 * first byte of the page just past the end of what we want.
4251 	 */
4252 out:
4253 	SEGOP_GETPROT(seg, saddr, len - 1, pagev->pg_protv);
4254 	return (addr);
4255 }
4256 
4257 static caddr_t
4258 pr_pagev_nextprot(prpagev_t *pagev, struct seg *seg,
4259     caddr_t *saddrp, caddr_t eaddr, uint_t *protp)
4260 {
4261 	/*
4262 	 * Our starting address is either the specified address, or the base
4263 	 * address from the start of the pagev.  If the latter is greater,
4264 	 * this means a previous call to pr_pagev_fill has already scanned
4265 	 * further than the end of the previous mapping.
4266 	 */
4267 	caddr_t base = seg->s_base + pagev->pg_pnbase * PAGESIZE;
4268 	caddr_t addr = MAX(*saddrp, base);
4269 	ulong_t pn = seg_page(seg, addr);
4270 	uint_t prot, nprot;
4271 
4272 	/*
4273 	 * If we're dealing with noreserve pages, then advance addr to
4274 	 * the address of the next page which has backing store.
4275 	 */
4276 	if (pagev->pg_incore != NULL) {
4277 		while (pagev->pg_incore[pn - pagev->pg_pnbase] == 0) {
4278 			if ((addr += PAGESIZE) == eaddr) {
4279 				*saddrp = addr;
4280 				prot = 0;
4281 				goto out;
4282 			}
4283 			if (++pn == pagev->pg_pnbase + pagev->pg_npages) {
4284 				addr = pr_pagev_fill(pagev, seg, addr, eaddr);
4285 				if (addr == eaddr) {
4286 					*saddrp = addr;
4287 					prot = 0;
4288 					goto out;
4289 				}
4290 				pn = seg_page(seg, addr);
4291 			}
4292 		}
4293 	}
4294 
4295 	/*
4296 	 * Get the protections on the page corresponding to addr.
4297 	 */
4298 	pn = seg_page(seg, addr);
4299 	ASSERT(pn >= pagev->pg_pnbase);
4300 	ASSERT(pn < (pagev->pg_pnbase + pagev->pg_npages));
4301 
4302 	prot = pagev->pg_protv[pn - pagev->pg_pnbase];
4303 	getwatchprot(seg->s_as, addr, &prot);
4304 	*saddrp = addr;
4305 
4306 	/*
4307 	 * Now loop until we find a backed page with different protections
4308 	 * or we reach the end of this segment.
4309 	 */
4310 	while ((addr += PAGESIZE) < eaddr) {
4311 		/*
4312 		 * If pn has advanced to the page number following what we
4313 		 * have information on, refill the page vector and reset
4314 		 * addr and pn.  If pr_pagev_fill does not return the
4315 		 * address of the next page, we have a discontiguity and
4316 		 * thus have reached the end of the current mapping.
4317 		 */
4318 		if (++pn == pagev->pg_pnbase + pagev->pg_npages) {
4319 			caddr_t naddr = pr_pagev_fill(pagev, seg, addr, eaddr);
4320 			if (naddr != addr)
4321 				goto out;
4322 			pn = seg_page(seg, addr);
4323 		}
4324 
4325 		/*
4326 		 * The previous page's protections are in prot, and it has
4327 		 * backing.  If this page is MAP_NORESERVE and has no backing,
4328 		 * then end this mapping and return the previous protections.
4329 		 */
4330 		if (pagev->pg_incore != NULL &&
4331 		    pagev->pg_incore[pn - pagev->pg_pnbase] == 0)
4332 			break;
4333 
4334 		/*
4335 		 * Otherwise end the mapping if this page's protections (nprot)
4336 		 * are different than those in the previous page (prot).
4337 		 */
4338 		nprot = pagev->pg_protv[pn - pagev->pg_pnbase];
4339 		getwatchprot(seg->s_as, addr, &nprot);
4340 
4341 		if (nprot != prot)
4342 			break;
4343 	}
4344 
4345 out:
4346 	*protp = prot;
4347 	return (addr);
4348 }
4349 
4350 size_t
4351 pr_getsegsize(struct seg *seg, int reserved)
4352 {
4353 	size_t size = seg->s_size;
4354 
4355 	/*
4356 	 * If we're interested in the reserved space, return the size of the
4357 	 * segment itself.  Everything else in this function is a special case
4358 	 * to determine the actual underlying size of various segment types.
4359 	 */
4360 	if (reserved)
4361 		return (size);
4362 
4363 	/*
4364 	 * If this is a segvn mapping of a regular file, return the smaller
4365 	 * of the segment size and the remaining size of the file beyond
4366 	 * the file offset corresponding to seg->s_base.
4367 	 */
4368 	if (seg->s_ops == &segvn_ops) {
4369 		vattr_t vattr;
4370 		vnode_t *vp;
4371 
4372 		vattr.va_mask = AT_SIZE;
4373 
4374 		if (SEGOP_GETVP(seg, seg->s_base, &vp) == 0 &&
4375 		    vp != NULL && vp->v_type == VREG &&
4376 		    VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
4377 
4378 			u_offset_t fsize = vattr.va_size;
4379 			u_offset_t offset = SEGOP_GETOFFSET(seg, seg->s_base);
4380 
4381 			if (fsize < offset)
4382 				fsize = 0;
4383 			else
4384 				fsize -= offset;
4385 
4386 			fsize = roundup(fsize, (u_offset_t)PAGESIZE);
4387 
4388 			if (fsize < (u_offset_t)size)
4389 				size = (size_t)fsize;
4390 		}
4391 
4392 		return (size);
4393 	}
4394 
4395 	/*
4396 	 * If this is an ISM shared segment, don't include pages that are
4397 	 * beyond the real size of the spt segment that backs it.
4398 	 */
4399 	if (seg->s_ops == &segspt_shmops)
4400 		return (MIN(spt_realsize(seg), size));
4401 
4402 	/*
4403 	 * If this is segment is a mapping from /dev/null, then this is a
4404 	 * reservation of virtual address space and has no actual size.
4405 	 * Such segments are backed by segdev and have type set to neither
4406 	 * MAP_SHARED nor MAP_PRIVATE.
4407 	 */
4408 	if (seg->s_ops == &segdev_ops &&
4409 	    ((SEGOP_GETTYPE(seg, seg->s_base) &
4410 	    (MAP_SHARED | MAP_PRIVATE)) == 0))
4411 		return (0);
4412 
4413 	/*
4414 	 * If this segment doesn't match one of the special types we handle,
4415 	 * just return the size of the segment itself.
4416 	 */
4417 	return (size);
4418 }
4419 
4420 uint_t
4421 pr_getprot(struct seg *seg, int reserved, void **tmp,
4422     caddr_t *saddrp, caddr_t *naddrp, caddr_t eaddr)
4423 {
4424 	struct as *as = seg->s_as;
4425 
4426 	caddr_t saddr = *saddrp;
4427 	caddr_t naddr;
4428 
4429 	int check_noreserve;
4430 	uint_t prot;
4431 
4432 	union {
4433 		struct segvn_data *svd;
4434 		struct segdev_data *sdp;
4435 		void *data;
4436 	} s;
4437 
4438 	s.data = seg->s_data;
4439 
4440 	ASSERT(AS_WRITE_HELD(as));
4441 	ASSERT(saddr >= seg->s_base && saddr < eaddr);
4442 	ASSERT(eaddr <= seg->s_base + seg->s_size);
4443 
4444 	/*
4445 	 * Don't include MAP_NORESERVE pages in the address range
4446 	 * unless their mappings have actually materialized.
4447 	 * We cheat by knowing that segvn is the only segment
4448 	 * driver that supports MAP_NORESERVE.
4449 	 */
4450 	check_noreserve =
4451 	    (!reserved && seg->s_ops == &segvn_ops && s.svd != NULL &&
4452 	    (s.svd->vp == NULL || s.svd->vp->v_type != VREG) &&
4453 	    (s.svd->flags & MAP_NORESERVE));
4454 
4455 	/*
4456 	 * Examine every page only as a last resort.  We use guilty knowledge
4457 	 * of segvn and segdev to avoid this: if there are no per-page
4458 	 * protections present in the segment and we don't care about
4459 	 * MAP_NORESERVE, then s_data->prot is the prot for the whole segment.
4460 	 */
4461 	if (!check_noreserve && saddr == seg->s_base &&
4462 	    seg->s_ops == &segvn_ops && s.svd != NULL && s.svd->pageprot == 0) {
4463 		prot = s.svd->prot;
4464 		getwatchprot(as, saddr, &prot);
4465 		naddr = eaddr;
4466 
4467 	} else if (saddr == seg->s_base && seg->s_ops == &segdev_ops &&
4468 	    s.sdp != NULL && s.sdp->pageprot == 0) {
4469 		prot = s.sdp->prot;
4470 		getwatchprot(as, saddr, &prot);
4471 		naddr = eaddr;
4472 
4473 	} else {
4474 		prpagev_t *pagev;
4475 
4476 		/*
4477 		 * If addr is sitting at the start of the segment, then
4478 		 * create a page vector to store protection and incore
4479 		 * information for pages in the segment, and fill it.
4480 		 * Otherwise, we expect *tmp to address the prpagev_t
4481 		 * allocated by a previous call to this function.
4482 		 */
4483 		if (saddr == seg->s_base) {
4484 			pagev = pr_pagev_create(seg, check_noreserve);
4485 			saddr = pr_pagev_fill(pagev, seg, saddr, eaddr);
4486 
4487 			ASSERT(*tmp == NULL);
4488 			*tmp = pagev;
4489 
4490 			ASSERT(saddr <= eaddr);
4491 			*saddrp = saddr;
4492 
4493 			if (saddr == eaddr) {
4494 				naddr = saddr;
4495 				prot = 0;
4496 				goto out;
4497 			}
4498 
4499 		} else {
4500 			ASSERT(*tmp != NULL);
4501 			pagev = (prpagev_t *)*tmp;
4502 		}
4503 
4504 		naddr = pr_pagev_nextprot(pagev, seg, saddrp, eaddr, &prot);
4505 		ASSERT(naddr <= eaddr);
4506 	}
4507 
4508 out:
4509 	if (naddr == eaddr)
4510 		pr_getprot_done(tmp);
4511 	*naddrp = naddr;
4512 	return (prot);
4513 }
4514 
4515 void
4516 pr_getprot_done(void **tmp)
4517 {
4518 	if (*tmp != NULL) {
4519 		pr_pagev_destroy((prpagev_t *)*tmp);
4520 		*tmp = NULL;
4521 	}
4522 }
4523 
4524 /*
4525  * Return true iff the vnode is a /proc file from the object directory.
4526  */
4527 int
4528 pr_isobject(vnode_t *vp)
4529 {
4530 	return (vn_matchops(vp, prvnodeops) && VTOP(vp)->pr_type == PR_OBJECT);
4531 }
4532 
4533 /*
4534  * Return true iff the vnode is a /proc file opened by the process itself.
4535  */
4536 int
4537 pr_isself(vnode_t *vp)
4538 {
4539 	/*
4540 	 * XXX: To retain binary compatibility with the old
4541 	 * ioctl()-based version of /proc, we exempt self-opens
4542 	 * of /proc/<pid> from being marked close-on-exec.
4543 	 */
4544 	return (vn_matchops(vp, prvnodeops) &&
4545 	    (VTOP(vp)->pr_flags & PR_ISSELF) &&
4546 	    VTOP(vp)->pr_type != PR_PIDDIR);
4547 }
4548 
4549 static ssize_t
4550 pr_getpagesize(struct seg *seg, caddr_t saddr, caddr_t *naddrp, caddr_t eaddr)
4551 {
4552 	ssize_t pagesize, hatsize;
4553 
4554 	ASSERT(AS_WRITE_HELD(seg->s_as));
4555 	ASSERT(IS_P2ALIGNED(saddr, PAGESIZE));
4556 	ASSERT(IS_P2ALIGNED(eaddr, PAGESIZE));
4557 	ASSERT(saddr < eaddr);
4558 
4559 	pagesize = hatsize = hat_getpagesize(seg->s_as->a_hat, saddr);
4560 	ASSERT(pagesize == -1 || IS_P2ALIGNED(pagesize, pagesize));
4561 	ASSERT(pagesize != 0);
4562 
4563 	if (pagesize == -1)
4564 		pagesize = PAGESIZE;
4565 
4566 	saddr += P2NPHASE((uintptr_t)saddr, pagesize);
4567 
4568 	while (saddr < eaddr) {
4569 		if (hatsize != hat_getpagesize(seg->s_as->a_hat, saddr))
4570 			break;
4571 		ASSERT(IS_P2ALIGNED(saddr, pagesize));
4572 		saddr += pagesize;
4573 	}
4574 
4575 	*naddrp = ((saddr < eaddr) ? saddr : eaddr);
4576 	return (hatsize);
4577 }
4578 
4579 /*
4580  * Return an array of structures with extended memory map information.
4581  * We allocate here; the caller must deallocate.
4582  */
4583 int
4584 prgetxmap(proc_t *p, list_t *iolhead)
4585 {
4586 	struct as *as = p->p_as;
4587 	prxmap_t *mp;
4588 	struct seg *seg;
4589 	struct seg *brkseg, *stkseg;
4590 	struct vnode *vp;
4591 	struct vattr vattr;
4592 	uint_t prot;
4593 
4594 	ASSERT(as != &kas && AS_WRITE_HELD(as));
4595 
4596 	/*
4597 	 * Request an initial buffer size that doesn't waste memory
4598 	 * if the address space has only a small number of segments.
4599 	 */
4600 	pr_iol_initlist(iolhead, sizeof (*mp), avl_numnodes(&as->a_segtree));
4601 
4602 	if ((seg = AS_SEGFIRST(as)) == NULL)
4603 		return (0);
4604 
4605 	brkseg = break_seg(p);
4606 	stkseg = as_segat(as, prgetstackbase(p));
4607 
4608 	do {
4609 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
4610 		caddr_t saddr, naddr, baddr;
4611 		void *tmp = NULL;
4612 		ssize_t psz;
4613 		char *parr;
4614 		uint64_t npages;
4615 		uint64_t pagenum;
4616 
4617 		if ((seg->s_flags & S_HOLE) != 0) {
4618 			continue;
4619 		}
4620 		/*
4621 		 * Segment loop part one: iterate from the base of the segment
4622 		 * to its end, pausing at each address boundary (baddr) between
4623 		 * ranges that have different virtual memory protections.
4624 		 */
4625 		for (saddr = seg->s_base; saddr < eaddr; saddr = baddr) {
4626 			prot = pr_getprot(seg, 0, &tmp, &saddr, &baddr, eaddr);
4627 			ASSERT(baddr >= saddr && baddr <= eaddr);
4628 
4629 			/*
4630 			 * Segment loop part two: iterate from the current
4631 			 * position to the end of the protection boundary,
4632 			 * pausing at each address boundary (naddr) between
4633 			 * ranges that have different underlying page sizes.
4634 			 */
4635 			for (; saddr < baddr; saddr = naddr) {
4636 				psz = pr_getpagesize(seg, saddr, &naddr, baddr);
4637 				ASSERT(naddr >= saddr && naddr <= baddr);
4638 
4639 				mp = pr_iol_newbuf(iolhead, sizeof (*mp));
4640 
4641 				mp->pr_vaddr = (uintptr_t)saddr;
4642 				mp->pr_size = naddr - saddr;
4643 				mp->pr_offset = SEGOP_GETOFFSET(seg, saddr);
4644 				mp->pr_mflags = 0;
4645 				if (prot & PROT_READ)
4646 					mp->pr_mflags |= MA_READ;
4647 				if (prot & PROT_WRITE)
4648 					mp->pr_mflags |= MA_WRITE;
4649 				if (prot & PROT_EXEC)
4650 					mp->pr_mflags |= MA_EXEC;
4651 				if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
4652 					mp->pr_mflags |= MA_SHARED;
4653 				if (SEGOP_GETTYPE(seg, saddr) & MAP_NORESERVE)
4654 					mp->pr_mflags |= MA_NORESERVE;
4655 				if (seg->s_ops == &segspt_shmops ||
4656 				    (seg->s_ops == &segvn_ops &&
4657 				    (SEGOP_GETVP(seg, saddr, &vp) != 0 ||
4658 				    vp == NULL)))
4659 					mp->pr_mflags |= MA_ANON;
4660 				if (seg == brkseg)
4661 					mp->pr_mflags |= MA_BREAK;
4662 				else if (seg == stkseg)
4663 					mp->pr_mflags |= MA_STACK;
4664 				if (seg->s_ops == &segspt_shmops)
4665 					mp->pr_mflags |= MA_ISM | MA_SHM;
4666 
4667 				mp->pr_pagesize = PAGESIZE;
4668 				if (psz == -1) {
4669 					mp->pr_hatpagesize = 0;
4670 				} else {
4671 					mp->pr_hatpagesize = psz;
4672 				}
4673 
4674 				/*
4675 				 * Manufacture a filename for the "object" dir.
4676 				 */
4677 				mp->pr_dev = PRNODEV;
4678 				vattr.va_mask = AT_FSID|AT_NODEID;
4679 				if (seg->s_ops == &segvn_ops &&
4680 				    SEGOP_GETVP(seg, saddr, &vp) == 0 &&
4681 				    vp != NULL && vp->v_type == VREG &&
4682 				    VOP_GETATTR(vp, &vattr, 0, CRED(),
4683 				    NULL) == 0) {
4684 					mp->pr_dev = vattr.va_fsid;
4685 					mp->pr_ino = vattr.va_nodeid;
4686 					if (vp == p->p_exec)
4687 						(void) strcpy(mp->pr_mapname,
4688 						    "a.out");
4689 					else
4690 						pr_object_name(mp->pr_mapname,
4691 						    vp, &vattr);
4692 				}
4693 
4694 				/*
4695 				 * Get the SysV shared memory id, if any.
4696 				 */
4697 				if ((mp->pr_mflags & MA_SHARED) &&
4698 				    p->p_segacct && (mp->pr_shmid = shmgetid(p,
4699 				    seg->s_base)) != SHMID_NONE) {
4700 					if (mp->pr_shmid == SHMID_FREE)
4701 						mp->pr_shmid = -1;
4702 
4703 					mp->pr_mflags |= MA_SHM;
4704 				} else {
4705 					mp->pr_shmid = -1;
4706 				}
4707 
4708 				npages = ((uintptr_t)(naddr - saddr)) >>
4709 				    PAGESHIFT;
4710 				parr = kmem_zalloc(npages, KM_SLEEP);
4711 
4712 				SEGOP_INCORE(seg, saddr, naddr - saddr, parr);
4713 
4714 				for (pagenum = 0; pagenum < npages; pagenum++) {
4715 					if (parr[pagenum] & SEG_PAGE_INCORE)
4716 						mp->pr_rss++;
4717 					if (parr[pagenum] & SEG_PAGE_ANON)
4718 						mp->pr_anon++;
4719 					if (parr[pagenum] & SEG_PAGE_LOCKED)
4720 						mp->pr_locked++;
4721 				}
4722 				kmem_free(parr, npages);
4723 			}
4724 		}
4725 		ASSERT(tmp == NULL);
4726 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
4727 
4728 	return (0);
4729 }
4730 
4731 /*
4732  * Return the process's credentials.  We don't need a 32-bit equivalent of
4733  * this function because prcred_t and prcred32_t are actually the same.
4734  */
4735 void
4736 prgetcred(proc_t *p, prcred_t *pcrp)
4737 {
4738 	mutex_enter(&p->p_crlock);
4739 	cred2prcred(p->p_cred, pcrp);
4740 	mutex_exit(&p->p_crlock);
4741 }
4742 
4743 void
4744 prgetsecflags(proc_t *p, prsecflags_t *psfp)
4745 {
4746 	ASSERT(psfp != NULL);
4747 
4748 	psfp->pr_version = PRSECFLAGS_VERSION_CURRENT;
4749 	psfp->pr_lower = p->p_secflags.psf_lower;
4750 	psfp->pr_upper = p->p_secflags.psf_upper;
4751 	psfp->pr_effective = p->p_secflags.psf_effective;
4752 	psfp->pr_inherit = p->p_secflags.psf_inherit;
4753 }
4754 
4755 /*
4756  * Compute actual size of the prpriv_t structure.
4757  */
4758 
4759 size_t
4760 prgetprivsize(void)
4761 {
4762 	return (priv_prgetprivsize(NULL));
4763 }
4764 
4765 /*
4766  * Return the process's privileges.  We don't need a 32-bit equivalent of
4767  * this function because prpriv_t and prpriv32_t are actually the same.
4768  */
4769 void
4770 prgetpriv(proc_t *p, prpriv_t *pprp)
4771 {
4772 	mutex_enter(&p->p_crlock);
4773 	cred2prpriv(p->p_cred, pprp);
4774 	mutex_exit(&p->p_crlock);
4775 }
4776 
4777 #ifdef _SYSCALL32_IMPL
4778 /*
4779  * Return an array of structures with HAT memory map information.
4780  * We allocate here; the caller must deallocate.
4781  */
4782 int
4783 prgetxmap32(proc_t *p, list_t *iolhead)
4784 {
4785 	struct as *as = p->p_as;
4786 	prxmap32_t *mp;
4787 	struct seg *seg;
4788 	struct seg *brkseg, *stkseg;
4789 	struct vnode *vp;
4790 	struct vattr vattr;
4791 	uint_t prot;
4792 
4793 	ASSERT(as != &kas && AS_WRITE_HELD(as));
4794 
4795 	/*
4796 	 * Request an initial buffer size that doesn't waste memory
4797 	 * if the address space has only a small number of segments.
4798 	 */
4799 	pr_iol_initlist(iolhead, sizeof (*mp), avl_numnodes(&as->a_segtree));
4800 
4801 	if ((seg = AS_SEGFIRST(as)) == NULL)
4802 		return (0);
4803 
4804 	brkseg = break_seg(p);
4805 	stkseg = as_segat(as, prgetstackbase(p));
4806 
4807 	do {
4808 		caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
4809 		caddr_t saddr, naddr, baddr;
4810 		void *tmp = NULL;
4811 		ssize_t psz;
4812 		char *parr;
4813 		uint64_t npages;
4814 		uint64_t pagenum;
4815 
4816 		if ((seg->s_flags & S_HOLE) != 0) {
4817 			continue;
4818 		}
4819 
4820 		/*
4821 		 * Segment loop part one: iterate from the base of the segment
4822 		 * to its end, pausing at each address boundary (baddr) between
4823 		 * ranges that have different virtual memory protections.
4824 		 */
4825 		for (saddr = seg->s_base; saddr < eaddr; saddr = baddr) {
4826 			prot = pr_getprot(seg, 0, &tmp, &saddr, &baddr, eaddr);
4827 			ASSERT(baddr >= saddr && baddr <= eaddr);
4828 
4829 			/*
4830 			 * Segment loop part two: iterate from the current
4831 			 * position to the end of the protection boundary,
4832 			 * pausing at each address boundary (naddr) between
4833 			 * ranges that have different underlying page sizes.
4834 			 */
4835 			for (; saddr < baddr; saddr = naddr) {
4836 				psz = pr_getpagesize(seg, saddr, &naddr, baddr);
4837 				ASSERT(naddr >= saddr && naddr <= baddr);
4838 
4839 				mp = pr_iol_newbuf(iolhead, sizeof (*mp));
4840 
4841 				mp->pr_vaddr = (caddr32_t)(uintptr_t)saddr;
4842 				mp->pr_size = (size32_t)(naddr - saddr);
4843 				mp->pr_offset = SEGOP_GETOFFSET(seg, saddr);
4844 				mp->pr_mflags = 0;
4845 				if (prot & PROT_READ)
4846 					mp->pr_mflags |= MA_READ;
4847 				if (prot & PROT_WRITE)
4848 					mp->pr_mflags |= MA_WRITE;
4849 				if (prot & PROT_EXEC)
4850 					mp->pr_mflags |= MA_EXEC;
4851 				if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
4852 					mp->pr_mflags |= MA_SHARED;
4853 				if (SEGOP_GETTYPE(seg, saddr) & MAP_NORESERVE)
4854 					mp->pr_mflags |= MA_NORESERVE;
4855 				if (seg->s_ops == &segspt_shmops ||
4856 				    (seg->s_ops == &segvn_ops &&
4857 				    (SEGOP_GETVP(seg, saddr, &vp) != 0 ||
4858 				    vp == NULL)))
4859 					mp->pr_mflags |= MA_ANON;
4860 				if (seg == brkseg)
4861 					mp->pr_mflags |= MA_BREAK;
4862 				else if (seg == stkseg)
4863 					mp->pr_mflags |= MA_STACK;
4864 				if (seg->s_ops == &segspt_shmops)
4865 					mp->pr_mflags |= MA_ISM | MA_SHM;
4866 
4867 				mp->pr_pagesize = PAGESIZE;
4868 				if (psz == -1) {
4869 					mp->pr_hatpagesize = 0;
4870 				} else {
4871 					mp->pr_hatpagesize = psz;
4872 				}
4873 
4874 				/*
4875 				 * Manufacture a filename for the "object" dir.
4876 				 */
4877 				mp->pr_dev = PRNODEV32;
4878 				vattr.va_mask = AT_FSID|AT_NODEID;
4879 				if (seg->s_ops == &segvn_ops &&
4880 				    SEGOP_GETVP(seg, saddr, &vp) == 0 &&
4881 				    vp != NULL && vp->v_type == VREG &&
4882 				    VOP_GETATTR(vp, &vattr, 0, CRED(),
4883 				    NULL) == 0) {
4884 					(void) cmpldev(&mp->pr_dev,
4885 					    vattr.va_fsid);
4886 					mp->pr_ino = vattr.va_nodeid;
4887 					if (vp == p->p_exec)
4888 						(void) strcpy(mp->pr_mapname,
4889 						    "a.out");
4890 					else
4891 						pr_object_name(mp->pr_mapname,
4892 						    vp, &vattr);
4893 				}
4894 
4895 				/*
4896 				 * Get the SysV shared memory id, if any.
4897 				 */
4898 				if ((mp->pr_mflags & MA_SHARED) &&
4899 				    p->p_segacct && (mp->pr_shmid = shmgetid(p,
4900 				    seg->s_base)) != SHMID_NONE) {
4901 					if (mp->pr_shmid == SHMID_FREE)
4902 						mp->pr_shmid = -1;
4903 
4904 					mp->pr_mflags |= MA_SHM;
4905 				} else {
4906 					mp->pr_shmid = -1;
4907 				}
4908 
4909 				npages = ((uintptr_t)(naddr - saddr)) >>
4910 				    PAGESHIFT;
4911 				parr = kmem_zalloc(npages, KM_SLEEP);
4912 
4913 				SEGOP_INCORE(seg, saddr, naddr - saddr, parr);
4914 
4915 				for (pagenum = 0; pagenum < npages; pagenum++) {
4916 					if (parr[pagenum] & SEG_PAGE_INCORE)
4917 						mp->pr_rss++;
4918 					if (parr[pagenum] & SEG_PAGE_ANON)
4919 						mp->pr_anon++;
4920 					if (parr[pagenum] & SEG_PAGE_LOCKED)
4921 						mp->pr_locked++;
4922 				}
4923 				kmem_free(parr, npages);
4924 			}
4925 		}
4926 		ASSERT(tmp == NULL);
4927 	} while ((seg = AS_SEGNEXT(as, seg)) != NULL);
4928 
4929 	return (0);
4930 }
4931 #endif	/* _SYSCALL32_IMPL */
4932