1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 char copyright[] = 9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10 All rights reserved.\n"; 11 #endif not lint 12 13 #ifndef lint 14 static char sccsid[] = "@(#)pstat.c 5.6 (Berkeley) 11/10/85"; 15 #endif not lint 16 17 /* 18 * Print system stuff 19 */ 20 21 #define mask(x) (x&0377) 22 #define clear(x) ((int)x&0x7fffffff) 23 24 #include <sys/param.h> 25 #include <sys/dir.h> 26 #define KERNEL 27 #include <sys/file.h> 28 #undef KERNEL 29 #include <sys/user.h> 30 #include <sys/proc.h> 31 #include <sys/text.h> 32 #include <sys/inode.h> 33 #include <sys/map.h> 34 #include <sys/ioctl.h> 35 #include <sys/tty.h> 36 #include <sys/conf.h> 37 #include <sys/vm.h> 38 #include <nlist.h> 39 #include <machine/pte.h> 40 41 char *fcore = "/dev/kmem"; 42 char *fmem = "/dev/mem"; 43 char *fnlist = "/vmunix"; 44 int fc, fm; 45 46 struct nlist nl[] = { 47 #define SINODE 0 48 { "_inode" }, 49 #define STEXT 1 50 { "_text" }, 51 #define SPROC 2 52 { "_proc" }, 53 #define SDZ 3 54 { "_dz_tty" }, 55 #define SNDZ 4 56 { "_dz_cnt" }, 57 #define SKL 5 58 { "_cons" }, 59 #define SFIL 6 60 { "_file" }, 61 #define USRPTMA 7 62 { "_Usrptmap" }, 63 #define USRPT 8 64 { "_usrpt" }, 65 #define SWAPMAP 9 66 { "_swapmap" }, 67 #define SDH 10 68 { "_dh11" }, 69 #define SNDH 11 70 { "_ndh11" }, 71 #define SNPROC 12 72 { "_nproc" }, 73 #define SNTEXT 13 74 { "_ntext" }, 75 #define SNFILE 14 76 { "_nfile" }, 77 #define SNINODE 15 78 { "_ninode" }, 79 #define SNSWAPMAP 16 80 { "_nswapmap" }, 81 #define SPTY 17 82 { "_pt_tty" }, 83 #define SDMMIN 18 84 { "_dmmin" }, 85 #define SDMMAX 19 86 { "_dmmax" }, 87 #define SNSWDEV 20 88 { "_nswdev" }, 89 #define SSWDEVT 21 90 { "_swdevt" }, 91 #define SDMF 22 92 { "_dmf_tty" }, 93 #define SNDMF 23 94 { "_ndmf" }, 95 #define SNPTY 24 96 { "_npty" }, 97 #define SDHU 25 98 { "_dhu_tty" }, 99 #define SNDHU 26 100 { "_ndhu" }, 101 #define SYSMAP 27 102 { "_Sysmap" }, 103 #define SDMZ 28 104 { "_dmz_tty" }, 105 #define SNDMZ 29 106 { "_ndmz" }, 107 { "" } 108 }; 109 110 int inof; 111 int txtf; 112 int prcf; 113 int ttyf; 114 int usrf; 115 long ubase; 116 int filf; 117 int swpf; 118 int totflg; 119 char partab[1]; 120 struct cdevsw cdevsw[1]; 121 struct bdevsw bdevsw[1]; 122 int allflg; 123 int kflg; 124 struct pte *Usrptma; 125 struct pte *usrpt; 126 127 main(argc, argv) 128 char **argv; 129 { 130 register char *argp; 131 int allflags; 132 133 argc--, argv++; 134 while (argc > 0 && **argv == '-') { 135 argp = *argv++; 136 argp++; 137 argc--; 138 while (*argp++) 139 switch (argp[-1]) { 140 141 case 'T': 142 totflg++; 143 break; 144 145 case 'a': 146 allflg++; 147 break; 148 149 case 'i': 150 inof++; 151 break; 152 153 case 'k': 154 kflg++; 155 fcore = fmem = "/vmcore"; 156 break; 157 158 case 'x': 159 txtf++; 160 break; 161 162 case 'p': 163 prcf++; 164 break; 165 166 case 't': 167 ttyf++; 168 break; 169 170 case 'u': 171 if (argc == 0) 172 break; 173 argc--; 174 usrf++; 175 sscanf( *argv++, "%x", &ubase); 176 break; 177 178 case 'f': 179 filf++; 180 break; 181 case 's': 182 swpf++; 183 break; 184 default: 185 usage(); 186 exit(1); 187 } 188 } 189 if (argc>1) 190 fcore = fmem = argv[1]; 191 if ((fc = open(fcore, 0)) < 0) { 192 printf("Can't find %s\n", fcore); 193 exit(1); 194 } 195 if ((fm = open(fmem, 0)) < 0) { 196 printf("Can't find %s\n", fmem); 197 exit(1); 198 } 199 if (argc>0) 200 fnlist = argv[0]; 201 nlist(fnlist, nl); 202 usrpt = (struct pte *)nl[USRPT].n_value; 203 Usrptma = (struct pte *)nl[USRPTMA].n_value; 204 if (nl[0].n_type == 0) { 205 printf("no namelist\n"); 206 exit(1); 207 } 208 allflags = filf | totflg | inof | prcf | txtf | ttyf | usrf | swpf; 209 if (allflags == 0) { 210 printf("pstat: one or more of -[aixptfsu] is required\n"); 211 exit(1); 212 } 213 if (filf||totflg) 214 dofile(); 215 if (inof||totflg) 216 doinode(); 217 if (prcf||totflg) 218 doproc(); 219 if (txtf||totflg) 220 dotext(); 221 if (ttyf) 222 dotty(); 223 if (usrf) 224 dousr(); 225 if (swpf||totflg) 226 doswap(); 227 } 228 229 usage() 230 { 231 232 printf("usage: pstat -[aixptfs] [-u [ubase]] [system] [core]\n"); 233 } 234 235 doinode() 236 { 237 register struct inode *ip; 238 struct inode *xinode, *ainode; 239 register int nin; 240 int ninode; 241 242 nin = 0; 243 ninode = getw(nl[SNINODE].n_value); 244 xinode = (struct inode *)calloc(ninode, sizeof (struct inode)); 245 ainode = (struct inode *)getw(nl[SINODE].n_value); 246 lseek(fc, mkphys((int)ainode), 0); 247 read(fc, xinode, ninode * sizeof(struct inode)); 248 for (ip = xinode; ip < &xinode[ninode]; ip++) 249 if (ip->i_count) 250 nin++; 251 if (totflg) { 252 printf("%3d/%3d inodes\n", nin, ninode); 253 return; 254 } 255 printf("%d/%d active inodes\n", nin, ninode); 256 printf(" LOC FLAGS CNT DEVICE RDC WRC INO MODE NLK UID SIZE/DEV\n"); 257 for (ip = xinode; ip < &xinode[ninode]; ip++) { 258 if (ip->i_count == 0) 259 continue; 260 printf("%8.1x ", ainode + (ip - xinode)); 261 putf(ip->i_flag&ILOCKED, 'L'); 262 putf(ip->i_flag&IUPD, 'U'); 263 putf(ip->i_flag&IACC, 'A'); 264 putf(ip->i_flag&IMOUNT, 'M'); 265 putf(ip->i_flag&IWANT, 'W'); 266 putf(ip->i_flag&ITEXT, 'T'); 267 putf(ip->i_flag&ICHG, 'C'); 268 putf(ip->i_flag&ISHLOCK, 'S'); 269 putf(ip->i_flag&IEXLOCK, 'E'); 270 putf(ip->i_flag&ILWAIT, 'Z'); 271 printf("%4d", ip->i_count&0377); 272 printf("%4d,%3d", major(ip->i_dev), minor(ip->i_dev)); 273 printf("%4d", ip->i_shlockc&0377); 274 printf("%4d", ip->i_exlockc&0377); 275 printf("%6d", ip->i_number); 276 printf("%6x", ip->i_mode & 0xffff); 277 printf("%4d", ip->i_nlink); 278 printf("%4d", ip->i_uid); 279 if ((ip->i_mode&IFMT)==IFBLK || (ip->i_mode&IFMT)==IFCHR) 280 printf("%6d,%3d", major(ip->i_rdev), minor(ip->i_rdev)); 281 else 282 printf("%10ld", ip->i_size); 283 printf("\n"); 284 } 285 free(xinode); 286 } 287 288 getw(loc) 289 off_t loc; 290 { 291 int word; 292 293 if (kflg) 294 loc &= 0x7fffffff; 295 lseek(fc, loc, 0); 296 read(fc, &word, sizeof (word)); 297 if (kflg) 298 word &= 0x7fffffff; 299 return (word); 300 } 301 302 putf(v, n) 303 { 304 if (v) 305 printf("%c", n); 306 else 307 printf(" "); 308 } 309 310 dotext() 311 { 312 register struct text *xp; 313 int ntext; 314 struct text *xtext, *atext; 315 int ntx; 316 317 ntx = 0; 318 ntext = getw(nl[SNTEXT].n_value); 319 xtext = (struct text *)calloc(ntext, sizeof (struct text)); 320 atext = (struct text *)getw(nl[STEXT].n_value); 321 lseek(fc, mkphys((int)atext), 0); 322 read(fc, xtext, ntext * sizeof (struct text)); 323 for (xp = xtext; xp < &xtext[ntext]; xp++) 324 if (xp->x_iptr!=NULL) 325 ntx++; 326 if (totflg) { 327 printf("%3d/%3d texts\n", ntx, ntext); 328 return; 329 } 330 printf("%d/%d active texts\n", ntx, ntext); 331 printf(" LOC FLAGS DADDR CADDR RSS SIZE IPTR CNT CCNT\n"); 332 for (xp = xtext; xp < &xtext[ntext]; xp++) { 333 if (xp->x_iptr == NULL) 334 continue; 335 printf("%8.1x", atext + (xp - xtext)); 336 printf(" "); 337 putf(xp->x_flag&XPAGI, 'P'); 338 putf(xp->x_flag&XTRC, 'T'); 339 putf(xp->x_flag&XWRIT, 'W'); 340 putf(xp->x_flag&XLOAD, 'L'); 341 putf(xp->x_flag&XLOCK, 'K'); 342 putf(xp->x_flag&XWANT, 'w'); 343 printf("%5x", xp->x_daddr[0]); 344 printf("%11x", xp->x_caddr); 345 printf("%5d", xp->x_rssize); 346 printf("%5d", xp->x_size); 347 printf("%10.1x", xp->x_iptr); 348 printf("%5d", xp->x_count&0377); 349 printf("%5d", xp->x_ccount); 350 printf("\n"); 351 } 352 free(xtext); 353 } 354 355 doproc() 356 { 357 struct proc *xproc, *aproc; 358 int nproc; 359 register struct proc *pp; 360 register loc, np; 361 struct pte apte; 362 363 nproc = getw(nl[SNPROC].n_value); 364 xproc = (struct proc *)calloc(nproc, sizeof (struct proc)); 365 aproc = (struct proc *)getw(nl[SPROC].n_value); 366 lseek(fc, mkphys((int)aproc), 0); 367 read(fc, xproc, nproc * sizeof (struct proc)); 368 np = 0; 369 for (pp=xproc; pp < &xproc[nproc]; pp++) 370 if (pp->p_stat) 371 np++; 372 if (totflg) { 373 printf("%3d/%3d processes\n", np, nproc); 374 return; 375 } 376 printf("%d/%d processes\n", np, nproc); 377 printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PGRP PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP\n"); 378 for (pp=xproc; pp<&xproc[nproc]; pp++) { 379 if (pp->p_stat==0 && allflg==0) 380 continue; 381 printf("%8x", aproc + (pp - xproc)); 382 printf(" %2d", pp->p_stat); 383 printf(" %4x", pp->p_flag & 0xffff); 384 printf(" %4d", pp->p_poip); 385 printf(" %3d", pp->p_pri); 386 printf(" %8x", pp->p_sig); 387 printf(" %4d", pp->p_uid); 388 printf(" %3d", pp->p_slptime); 389 printf(" %3d", pp->p_time); 390 printf(" %4d", pp->p_cpu&0377); 391 printf(" %3d", pp->p_nice); 392 printf(" %6d", pp->p_pgrp); 393 printf(" %6d", pp->p_pid); 394 printf(" %6d", pp->p_ppid); 395 if (kflg) 396 pp->p_addr = (struct pte *)clear((int)pp->p_addr); 397 if (pp->p_flag & SLOAD) { 398 lseek(fc, (long)pp->p_addr, 0); 399 read(fc, &apte, sizeof(apte)); 400 printf(" %8x", apte.pg_pfnum); 401 } else 402 printf(" %8x", pp->p_swaddr); 403 printf(" %4x", pp->p_rssize); 404 printf(" %4x", pp->p_swrss); 405 printf(" %5x", pp->p_dsize+pp->p_ssize); 406 printf(" %7x", clear(pp->p_wchan)); 407 printf(" %7x", clear(pp->p_link)); 408 printf(" %7x", clear(pp->p_textp)); 409 printf("\n"); 410 } 411 } 412 413 static char mesg[] = 414 " # RAW CAN OUT MODE ADDR DEL COL STATE PGRP DISC\n"; 415 static int ttyspace = 128; 416 static struct tty *tty; 417 418 dotty() 419 { 420 extern char *malloc(); 421 422 if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) { 423 printf("pstat: out of memory\n"); 424 return; 425 } 426 printf("1 cons\n"); 427 if (kflg) 428 nl[SKL].n_value = clear(nl[SKL].n_value); 429 lseek(fc, (long)nl[SKL].n_value, 0); 430 read(fc, tty, sizeof(*tty)); 431 printf(mesg); 432 ttyprt(&tty[0], 0); 433 if (nl[SNDZ].n_type != 0) 434 dottytype("dz", SDZ, SNDZ); 435 if (nl[SNDH].n_type != 0) 436 dottytype("dh", SDH, SNDH); 437 if (nl[SNDMF].n_type != 0) 438 dottytype("dmf", SDMF, SNDMF); 439 if (nl[SNDHU].n_type != 0) 440 dottytype("dhu", SDHU, SNDHU); 441 if (nl[SNDMZ].n_type != 0) 442 dottytype("dmz", SDMZ, SNDMZ); 443 if (nl[SNPTY].n_type != 0) 444 dottytype("pty", SPTY, SNPTY); 445 } 446 447 dottytype(name, type, number) 448 char *name; 449 { 450 int ntty; 451 register struct tty *tp; 452 extern char *realloc(); 453 454 if (tty == (struct tty *)0) 455 return; 456 if (kflg) { 457 nl[number].n_value = clear(nl[number].n_value); 458 nl[type].n_value = clear(nl[type].n_value); 459 } 460 lseek(fc, (long)nl[number].n_value, 0); 461 read(fc, &ntty, sizeof(ntty)); 462 printf("%d %s lines\n", ntty, name); 463 if (ntty > ttyspace) { 464 ttyspace = ntty; 465 if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) { 466 printf("pstat: out of memory\n"); 467 return; 468 } 469 } 470 lseek(fc, (long)nl[type].n_value, 0); 471 read(fc, tty, ntty * sizeof(struct tty)); 472 printf(mesg); 473 for (tp = tty; tp < &tty[ntty]; tp++) 474 ttyprt(tp, tp - tty); 475 } 476 477 ttyprt(atp, line) 478 struct tty *atp; 479 { 480 register struct tty *tp; 481 482 printf("%2d", line); 483 tp = atp; 484 switch (tp->t_line) { 485 486 /* 487 case NETLDISC: 488 if (tp->t_rec) 489 printf("%4d%4d", 0, tp->t_inbuf); 490 else 491 printf("%4d%4d", tp->t_inbuf, 0); 492 break; 493 */ 494 495 default: 496 printf("%4d%4d", tp->t_rawq.c_cc, tp->t_canq.c_cc); 497 } 498 printf("%4d %8x %8x%4d%4d", tp->t_outq.c_cc, tp->t_flags, 499 tp->t_addr, tp->t_delct, tp->t_col); 500 putf(tp->t_state&TS_TIMEOUT, 'T'); 501 putf(tp->t_state&TS_WOPEN, 'W'); 502 putf(tp->t_state&TS_ISOPEN, 'O'); 503 putf(tp->t_state&TS_FLUSH, 'F'); 504 putf(tp->t_state&TS_CARR_ON, 'C'); 505 putf(tp->t_state&TS_BUSY, 'B'); 506 putf(tp->t_state&TS_ASLEEP, 'A'); 507 putf(tp->t_state&TS_XCLUDE, 'X'); 508 putf(tp->t_state&TS_TTSTOP, 'S'); 509 putf(tp->t_state&TS_HUPCLS, 'H'); 510 printf("%6d", tp->t_pgrp); 511 switch (tp->t_line) { 512 513 case OTTYDISC: 514 printf("\n"); 515 break; 516 517 case NTTYDISC: 518 printf(" ntty\n"); 519 break; 520 521 case NETLDISC: 522 printf(" berknet\n"); 523 break; 524 525 case TABLDISC: 526 printf(" tab\n"); 527 break; 528 529 default: 530 printf(" %d\n", tp->t_line); 531 } 532 } 533 534 dousr() 535 { 536 struct user U; 537 register i, j, *ip; 538 register struct nameidata *nd = &U.u_nd; 539 540 /* This wins only if CLBYTES >= sizeof (struct user) */ 541 lseek(fm, ubase * NBPG, 0); 542 read(fm, &U, sizeof(U)); 543 printf("pcb"); 544 ip = (int *)&U.u_pcb; 545 while (ip < &U.u_arg[0]) { 546 if ((ip - (int *)&U.u_pcb) % 4 == 0) 547 printf("\t"); 548 printf("%x ", *ip++); 549 if ((ip - (int *)&U.u_pcb) % 4 == 0) 550 printf("\n"); 551 } 552 if ((ip - (int *)&U.u_pcb) % 4 != 0) 553 printf("\n"); 554 printf("arg"); 555 for (i=0; i<sizeof(U.u_arg)/sizeof(U.u_arg[0]); i++) { 556 if (i%5==0) 557 printf("\t"); 558 printf(" %.1x", U.u_arg[i]); 559 if (i%5==4) 560 printf("\n"); 561 } 562 if (i%5) 563 printf("\n"); 564 printf("segflg\t%d\nerror %d\n", nd->ni_segflg, U.u_error); 565 printf("uids\t%d,%d,%d,%d\n", U.u_uid,U.u_gid,U.u_ruid,U.u_rgid); 566 printf("procp\t%.1x\n", U.u_procp); 567 printf("ap\t%.1x\n", U.u_ap); 568 printf("r_val?\t%.1x %.1x\n", U.u_r.r_val1, U.u_r.r_val2); 569 printf("base, count, offset %.1x %.1x %ld\n", nd->ni_base, 570 nd->ni_count, nd->ni_offset); 571 printf("cdir rdir %.1x %.1x\n", U.u_cdir, U.u_rdir); 572 printf("dirp %.1x\n", nd->ni_dirp); 573 printf("dent %d %.14s\n", nd->ni_dent.d_ino, nd->ni_dent.d_name); 574 printf("pdir %.1o\n", nd->ni_pdir); 575 printf("file"); 576 for (i=0; i<NOFILE; i++) { 577 if (i % 8 == 0) 578 printf("\t"); 579 printf("%9.1x", U.u_ofile[i]); 580 if (i % 8 == 7) 581 printf("\n"); 582 } 583 if (i % 8) 584 printf("\n"); 585 printf("pofile"); 586 for (i=0; i<NOFILE; i++) { 587 if (i % 8 == 0) 588 printf("\t"); 589 printf("%9.1x", U.u_pofile[i]); 590 if (i % 8 == 7) 591 printf("\n"); 592 } 593 if (i % 8) 594 printf("\n"); 595 printf("ssave"); 596 for (i=0; i<sizeof(label_t)/sizeof(int); i++) { 597 if (i%5==0) 598 printf("\t"); 599 printf("%9.1x", U.u_ssave.val[i]); 600 if (i%5==4) 601 printf("\n"); 602 } 603 if (i%5) 604 printf("\n"); 605 printf("sigs"); 606 for (i=0; i<NSIG; i++) { 607 if (i % 8 == 0) 608 printf("\t"); 609 printf("%.1x ", U.u_signal[i]); 610 if (i % 8 == 7) 611 printf("\n"); 612 } 613 if (i % 8) 614 printf("\n"); 615 printf("code\t%.1x\n", U.u_code); 616 printf("ar0\t%.1x\n", U.u_ar0); 617 printf("prof\t%X %X %X %X\n", U.u_prof.pr_base, U.u_prof.pr_size, 618 U.u_prof.pr_off, U.u_prof.pr_scale); 619 printf("\neosys\t%d\n", U.u_eosys); 620 printf("ttyp\t%.1x\n", U.u_ttyp); 621 printf("ttyd\t%d,%d\n", major(U.u_ttyd), minor(U.u_ttyd)); 622 printf("comm %.14s\n", U.u_comm); 623 printf("start\t%D\n", U.u_start); 624 printf("acflag\t%D\n", U.u_acflag); 625 printf("cmask\t%D\n", U.u_cmask); 626 printf("sizes\t%.1x %.1x %.1x\n", U.u_tsize, U.u_dsize, U.u_ssize); 627 printf("ru\t"); 628 ip = (int *)&U.u_ru; 629 for (i = 0; i < sizeof(U.u_ru)/sizeof(int); i++) 630 printf("%D ", ip[i]); 631 printf("\n"); 632 ip = (int *)&U.u_cru; 633 printf("cru\t"); 634 for (i = 0; i < sizeof(U.u_cru)/sizeof(int); i++) 635 printf("%D ", ip[i]); 636 printf("\n"); 637 /* 638 i = U.u_stack - &U; 639 while (U[++i] == 0); 640 i &= ~07; 641 while (i < 512) { 642 printf("%x ", 0140000+2*i); 643 for (j=0; j<8; j++) 644 printf("%9x", U[i++]); 645 printf("\n"); 646 } 647 */ 648 } 649 650 oatoi(s) 651 char *s; 652 { 653 register v; 654 655 v = 0; 656 while (*s) 657 v = (v<<3) + *s++ - '0'; 658 return(v); 659 } 660 661 dofile() 662 { 663 int nfile; 664 struct file *xfile, *afile; 665 register struct file *fp; 666 register nf; 667 int loc; 668 static char *dtypes[] = { "???", "inode", "socket" }; 669 670 nf = 0; 671 nfile = getw(nl[SNFILE].n_value); 672 xfile = (struct file *)calloc(nfile, sizeof (struct file)); 673 afile = (struct file *)getw(nl[SFIL].n_value); 674 lseek(fc, (mkphys((int)afile)), 0); 675 read(fc, xfile, nfile * sizeof (struct file)); 676 for (fp=xfile; fp < &xfile[nfile]; fp++) 677 if (fp->f_count) 678 nf++; 679 if (totflg) { 680 printf("%3d/%3d files\n", nf, nfile); 681 return; 682 } 683 printf("%d/%d open files\n", nf, nfile); 684 printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n"); 685 for (fp=xfile,loc=(int)afile; fp < &xfile[nfile]; fp++,loc+=sizeof(xfile[0])) { 686 if (fp->f_count==0) 687 continue; 688 printf("%8x ", loc); 689 if (fp->f_type <= DTYPE_SOCKET) 690 printf("%-8.8s", dtypes[fp->f_type]); 691 else 692 printf("8d", fp->f_type); 693 putf(fp->f_flag&FREAD, 'R'); 694 putf(fp->f_flag&FWRITE, 'W'); 695 putf(fp->f_flag&FAPPEND, 'A'); 696 putf(fp->f_flag&FSHLOCK, 'S'); 697 putf(fp->f_flag&FEXLOCK, 'X'); 698 putf(fp->f_flag&FASYNC, 'I'); 699 printf(" %3d", mask(fp->f_count)); 700 printf(" %3d", mask(fp->f_msgcount)); 701 printf(" %8.1x", fp->f_data); 702 if (fp->f_offset < 0) 703 printf(" %x\n", fp->f_offset); 704 else 705 printf(" %ld\n", fp->f_offset); 706 } 707 } 708 709 int dmmin, dmmax, nswdev; 710 711 doswap() 712 { 713 struct proc *proc; 714 int nproc; 715 struct text *xtext; 716 int ntext; 717 struct map *swapmap; 718 int nswapmap; 719 struct swdevt *swdevt, *sw; 720 register struct proc *pp; 721 int nswap, used, tused, free, waste; 722 int db, sb; 723 register struct mapent *me; 724 register struct text *xp; 725 int i, j; 726 727 nproc = getw(nl[SNPROC].n_value); 728 proc = (struct proc *)calloc(nproc, sizeof (struct proc)); 729 ntext = getw(nl[SNTEXT].n_value); 730 xtext = (struct text *)calloc(ntext, sizeof (struct text)); 731 nswapmap = getw(nl[SNSWAPMAP].n_value); 732 swapmap = (struct map *)calloc(nswapmap, sizeof (struct map)); 733 nswdev = getw(nl[SNSWDEV].n_value); 734 swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt)); 735 lseek(fc, nl[SSWDEVT].n_value, L_SET); 736 read(fc, swdevt, nswdev * sizeof (struct swdevt)); 737 lseek(fc, getw(nl[SPROC].n_value), 0); 738 read(fc, proc, nproc * sizeof (struct proc)); 739 lseek(fc, getw(nl[STEXT].n_value), 0); 740 read(fc, xtext, ntext * sizeof (struct text)); 741 lseek(fc, getw(nl[SWAPMAP].n_value), 0); 742 read(fc, swapmap, nswapmap * sizeof (struct map)); 743 swapmap->m_name = "swap"; 744 swapmap->m_limit = (struct mapent *)&swapmap[nswapmap]; 745 dmmin = getw(nl[SDMMIN].n_value); 746 dmmax = getw(nl[SDMMAX].n_value); 747 nswap = 0; 748 for (sw = swdevt; sw < &swdevt[nswdev]; sw++) 749 nswap += sw->sw_nblks, 750 free = 0; 751 for (me = (struct mapent *)(swapmap+1); 752 me < (struct mapent *)&swapmap[nswapmap]; me++) 753 free += me->m_size; 754 tused = 0; 755 for (xp = xtext; xp < &xtext[ntext]; xp++) 756 if (xp->x_iptr!=NULL) { 757 tused += ctod(clrnd(xp->x_size)); 758 if (xp->x_flag & XPAGI) 759 tused += ctod(clrnd(ctopt(xp->x_size))); 760 } 761 used = tused; 762 waste = 0; 763 for (pp = proc; pp < &proc[nproc]; pp++) { 764 if (pp->p_stat == 0 || pp->p_stat == SZOMB) 765 continue; 766 if (pp->p_flag & SSYS) 767 continue; 768 db = ctod(pp->p_dsize), sb = up(db); 769 used += sb; 770 waste += sb - db; 771 db = ctod(pp->p_ssize), sb = up(db); 772 used += sb; 773 waste += sb - db; 774 if ((pp->p_flag&SLOAD) == 0) 775 used += ctod(vusize(pp)); 776 } 777 if (totflg) { 778 #define btok(x) ((x) / (1024 / DEV_BSIZE)) 779 printf("%3d/%3d 00k swap\n", 780 btok(used/100), btok((used+free)/100)); 781 return; 782 } 783 printf("%dk used (%dk text), %dk free, %dk wasted, %dk missing\n", 784 btok(used), btok(tused), btok(free), btok(waste), 785 /* a dmmax/2 block goes to argmap */ 786 btok(nswap - dmmax/2 - (used + free))); 787 printf("avail: "); 788 for (i = dmmax; i >= dmmin; i /= 2) { 789 j = 0; 790 while (rmalloc(swapmap, i) != 0) 791 j++; 792 if (j) printf("%d*%dk ", j, btok(i)); 793 } 794 free = 0; 795 for (me = (struct mapent *)(swapmap+1); 796 me < (struct mapent *)&swapmap[nswapmap]; me++) 797 free += me->m_size; 798 printf("%d*1k\n", btok(free)); 799 } 800 801 up(size) 802 register int size; 803 { 804 register int i, block; 805 806 i = 0; 807 block = dmmin; 808 while (i < size) { 809 i += block; 810 if (block < dmmax) 811 block *= 2; 812 } 813 return (i); 814 } 815 816 /* 817 * Compute number of pages to be allocated to the u. area 818 * and data and stack area page tables, which are stored on the 819 * disk immediately after the u. area. 820 */ 821 vusize(p) 822 register struct proc *p; 823 { 824 register int tsz = p->p_tsize / NPTEPG; 825 826 /* 827 * We do not need page table space on the disk for page 828 * table pages wholly containing text. 829 */ 830 return (clrnd(UPAGES + 831 clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz)); 832 } 833 834 /* 835 * Allocate 'size' units from the given 836 * map. Return the base of the allocated space. 837 * In a map, the addresses are increasing and the 838 * list is terminated by a 0 size. 839 * 840 * Algorithm is first-fit. 841 * 842 * This routine knows about the interleaving of the swapmap 843 * and handles that. 844 */ 845 long 846 rmalloc(mp, size) 847 register struct map *mp; 848 long size; 849 { 850 register struct mapent *ep = (struct mapent *)(mp+1); 851 register int addr; 852 register struct mapent *bp; 853 swblk_t first, rest; 854 855 if (size <= 0 || size > dmmax) 856 return (0); 857 /* 858 * Search for a piece of the resource map which has enough 859 * free space to accomodate the request. 860 */ 861 for (bp = ep; bp->m_size; bp++) { 862 if (bp->m_size >= size) { 863 /* 864 * If allocating from swapmap, 865 * then have to respect interleaving 866 * boundaries. 867 */ 868 if (nswdev > 1 && 869 (first = dmmax - bp->m_addr%dmmax) < bp->m_size) { 870 if (bp->m_size - first < size) 871 continue; 872 addr = bp->m_addr + first; 873 rest = bp->m_size - first - size; 874 bp->m_size = first; 875 if (rest) 876 rmfree(mp, rest, addr+size); 877 return (addr); 878 } 879 /* 880 * Allocate from the map. 881 * If there is no space left of the piece 882 * we allocated from, move the rest of 883 * the pieces to the left. 884 */ 885 addr = bp->m_addr; 886 bp->m_addr += size; 887 if ((bp->m_size -= size) == 0) { 888 do { 889 bp++; 890 (bp-1)->m_addr = bp->m_addr; 891 } while ((bp-1)->m_size = bp->m_size); 892 } 893 if (addr % CLSIZE) 894 return (0); 895 return (addr); 896 } 897 } 898 return (0); 899 } 900 901 /* 902 * Free the previously allocated space at addr 903 * of size units into the specified map. 904 * Sort addr into map and combine on 905 * one or both ends if possible. 906 */ 907 rmfree(mp, size, addr) 908 struct map *mp; 909 long size, addr; 910 { 911 struct mapent *firstbp; 912 register struct mapent *bp; 913 register int t; 914 915 /* 916 * Both address and size must be 917 * positive, or the protocol has broken down. 918 */ 919 if (addr <= 0 || size <= 0) 920 goto badrmfree; 921 /* 922 * Locate the piece of the map which starts after the 923 * returned space (or the end of the map). 924 */ 925 firstbp = bp = (struct mapent *)(mp + 1); 926 for (; bp->m_addr <= addr && bp->m_size != 0; bp++) 927 continue; 928 /* 929 * If the piece on the left abuts us, 930 * then we should combine with it. 931 */ 932 if (bp > firstbp && (bp-1)->m_addr+(bp-1)->m_size >= addr) { 933 /* 934 * Check no overlap (internal error). 935 */ 936 if ((bp-1)->m_addr+(bp-1)->m_size > addr) 937 goto badrmfree; 938 /* 939 * Add into piece on the left by increasing its size. 940 */ 941 (bp-1)->m_size += size; 942 /* 943 * If the combined piece abuts the piece on 944 * the right now, compress it in also, 945 * by shifting the remaining pieces of the map over. 946 */ 947 if (bp->m_addr && addr+size >= bp->m_addr) { 948 if (addr+size > bp->m_addr) 949 goto badrmfree; 950 (bp-1)->m_size += bp->m_size; 951 while (bp->m_size) { 952 bp++; 953 (bp-1)->m_addr = bp->m_addr; 954 (bp-1)->m_size = bp->m_size; 955 } 956 } 957 goto done; 958 } 959 /* 960 * Don't abut on the left, check for abutting on 961 * the right. 962 */ 963 if (addr+size >= bp->m_addr && bp->m_size) { 964 if (addr+size > bp->m_addr) 965 goto badrmfree; 966 bp->m_addr -= size; 967 bp->m_size += size; 968 goto done; 969 } 970 /* 971 * Don't abut at all. Make a new entry 972 * and check for map overflow. 973 */ 974 do { 975 t = bp->m_addr; 976 bp->m_addr = addr; 977 addr = t; 978 t = bp->m_size; 979 bp->m_size = size; 980 bp++; 981 } while (size = t); 982 /* 983 * Segment at bp is to be the delimiter; 984 * If there is not room for it 985 * then the table is too full 986 * and we must discard something. 987 */ 988 if (bp+1 > mp->m_limit) { 989 /* 990 * Back bp up to last available segment. 991 * which contains a segment already and must 992 * be made into the delimiter. 993 * Discard second to last entry, 994 * since it is presumably smaller than the last 995 * and move the last entry back one. 996 */ 997 bp--; 998 printf("%s: rmap ovflo, lost [%d,%d)\n", mp->m_name, 999 (bp-1)->m_addr, (bp-1)->m_addr+(bp-1)->m_size); 1000 bp[-1] = bp[0]; 1001 bp[0].m_size = bp[0].m_addr = 0; 1002 } 1003 done: 1004 return; 1005 badrmfree: 1006 printf("bad rmfree\n"); 1007 } 1008 /* 1009 * "addr" is a kern virt addr and does not correspond 1010 * To a phys addr after zipping out the high bit.. 1011 * since it was valloc'd in the kernel. 1012 * 1013 * We return the phys addr by simulating kernel vm (/dev/kmem) 1014 * when we are reading a crash dump. 1015 */ 1016 mkphys(addr) 1017 { 1018 register o; 1019 1020 if (!kflg) 1021 return(addr); 1022 o = addr & PGOFSET; 1023 addr >>= PGSHIFT; 1024 addr &= PG_PFNUM; 1025 addr *= NBPW; 1026 addr = getw(nl[SYSMAP].n_value + addr); 1027 addr = ((addr & PG_PFNUM) << PGSHIFT) | o; 1028 return(addr); 1029 } 1030