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