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