1 /*- 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #if defined(LIBC_SCCS) && !defined(lint) 9 static char sccsid[] = "@(#)kvm_hp300.c 5.8 (Berkeley) 06/06/90"; 10 #endif /* LIBC_SCCS and not lint */ 11 12 #include <machine/pte.h> 13 #include <machine/vmparam.h> 14 #include <sys/param.h> 15 #include <sys/user.h> 16 #include <sys/proc.h> 17 #include <sys/file.h> 18 #include <sys/text.h> 19 #include <sys/stat.h> 20 #include <sys/time.h> 21 #include <sys/vmmac.h> 22 #include <sys/ioctl.h> 23 #include <sys/tty.h> 24 #include <kvm.h> 25 #include <ctype.h> 26 #include <vis.h> 27 #include <nlist.h> 28 #include <pwd.h> 29 #include <string.h> 30 #include <ndbm.h> 31 #include <limits.h> 32 #include <paths.h> 33 #include <stdio.h> 34 35 /* 36 * files 37 */ 38 static char *unixf, *memf, *kmemf, *swapf; 39 static int unixx, mem, kmem, swap; 40 static DBM *db; 41 /* 42 * flags 43 */ 44 static int deadkernel; 45 static int kvminit = 0; 46 static int kvmfilesopen = 0; 47 /* 48 * state 49 */ 50 static struct kinfo_proc *kvmprocbase, *kvmprocptr; 51 static int kvmnprocs; 52 /* 53 * u. buffer 54 */ 55 static union { 56 struct user user; 57 char upages[UPAGES][NBPG]; 58 } user; 59 /* 60 * random other stuff 61 */ 62 static struct pte *Usrptmap, *usrpt; 63 static int dmmin, dmmax; 64 static struct pte *Sysmap; 65 static int Syssize; 66 static int pcbpf; 67 static int argaddr0; /* XXX */ 68 static int argaddr1; 69 static int nswap; 70 static char *tmp; 71 #if defined(hp300) 72 static int lowram; 73 #endif 74 75 #define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp)) 76 #define MAXSYMSIZE 256 77 78 #if defined(hp300) 79 #define pftoc(f) ((f) - lowram) 80 #define iskva(v) (1) 81 #endif 82 83 #ifndef pftoc 84 #define pftoc(f) (f) 85 #endif 86 #ifndef iskva 87 #define iskva(v) ((v) & KERNBASE) 88 #endif 89 90 static struct nlist nl[] = { 91 { "_Usrptmap" }, 92 #define X_USRPTMAP 0 93 { "_usrpt" }, 94 #define X_USRPT 1 95 { "_nswap" }, 96 #define X_NSWAP 2 97 { "_dmmin" }, 98 #define X_DMMIN 3 99 { "_dmmax" }, 100 #define X_DMMAX 4 101 /* 102 * everything here and down, only if a dead kernel 103 */ 104 { "_Sysmap" }, 105 #define X_SYSMAP 5 106 #define X_DEADKERNEL X_SYSMAP 107 { "_Syssize" }, 108 #define X_SYSSIZE 6 109 { "_allproc" }, 110 #define X_ALLPROC 7 111 { "_zombproc" }, 112 #define X_ZOMBPROC 8 113 { "_nproc" }, 114 #define X_NPROC 9 115 #define X_LAST 9 116 #if defined(hp300) 117 { "_lowram" }, 118 #define X_LOWRAM (X_LAST+1) 119 #endif 120 { "" }, 121 }; 122 123 /* 124 * returns 0 if files were opened now, 125 * 1 if files were already opened, 126 * -1 if files could not be opened. 127 */ 128 kvm_openfiles(uf, mf, sf) 129 char *uf, *mf, *sf; 130 { 131 if (kvmfilesopen) 132 return (1); 133 unixx = mem = kmem = swap = -1; 134 unixf = (uf == NULL) ? _PATH_UNIX : uf; 135 memf = (mf == NULL) ? _PATH_MEM : mf; 136 137 if ((unixx = open(unixf, O_RDONLY, 0)) == -1) { 138 setsyserr("can't open %s", unixf); 139 goto failed; 140 } 141 if ((mem = open(memf, O_RDONLY, 0)) == -1) { 142 setsyserr("can't open %s", memf); 143 goto failed; 144 } 145 if (sf != NULL) 146 swapf = sf; 147 if (mf != NULL) { 148 deadkernel++; 149 kmemf = mf; 150 kmem = mem; 151 swap = -1; 152 } else { 153 kmemf = _PATH_KMEM; 154 if ((kmem = open(kmemf, O_RDONLY, 0)) == -1) { 155 setsyserr("can't open %s", kmemf); 156 goto failed; 157 } 158 swapf = (sf == NULL) ? _PATH_DRUM : sf; 159 /* 160 * live kernel - avoid looking up nlist entries 161 * past X_DEADKERNEL. 162 */ 163 nl[X_DEADKERNEL].n_name = ""; 164 } 165 if (swapf != NULL && ((swap = open(swapf, O_RDONLY, 0)) == -1)) { 166 seterr("can't open %s", swapf); 167 goto failed; 168 } 169 kvmfilesopen++; 170 return (0); 171 failed: 172 kvm_close(); 173 return (-1); 174 } 175 176 static 177 kvm_init(uf, mf, sf) 178 char *uf, *mf, *sf; 179 { 180 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) 181 return (-1); 182 if (getkvars() == -1) 183 return (-1); 184 kvminit = 1; 185 186 return (0); 187 } 188 189 kvm_close() 190 { 191 if (unixx != -1) { 192 close(unixx); 193 unixx = -1; 194 } 195 if (kmem != -1) { 196 if (kmem != mem) 197 close(kmem); 198 /* otherwise kmem is a copy of mem, and will be closed below */ 199 kmem = -1; 200 } 201 if (mem != -1) { 202 close(mem); 203 mem = -1; 204 } 205 if (swap != -1) { 206 close(swap); 207 swap = -1; 208 } 209 if (db != NULL) { 210 dbm_close(db); 211 db = NULL; 212 } 213 kvminit = 0; 214 kvmfilesopen = 0; 215 deadkernel = 0; 216 if (Sysmap) { 217 free(Sysmap); 218 Sysmap = NULL; 219 } 220 } 221 222 kvm_nlist(nl) 223 struct nlist *nl; 224 { 225 datum key, data; 226 char dbname[MAXPATHLEN]; 227 char dbversion[LINE_MAX]; 228 char kversion[LINE_MAX]; 229 int dbversionlen; 230 char symbuf[MAXSYMSIZE+1]; 231 struct nlist nbuf, *n; 232 int num, did; 233 234 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) 235 return (-1); 236 if (deadkernel) 237 goto hard2; 238 /* 239 * initialize key datum 240 */ 241 key.dptr = symbuf; 242 symbuf[0] = KVMDB_NLIST; 243 244 if (db != NULL) 245 goto win; /* off to the races */ 246 /* 247 * open database 248 */ 249 sprintf(dbname, "%s/kvm_%s", KVMDBDIR, basename(unixf)); 250 if ((db = dbm_open(dbname, O_RDONLY, 0)) == NULL) 251 goto hard2; 252 /* 253 * read version out of database 254 */ 255 bcopy("VERSION", symbuf+1, sizeof ("VERSION")-1); 256 key.dsize = (sizeof ("VERSION") - 1) + 1; 257 data = dbm_fetch(db, key); 258 if (data.dptr == NULL) 259 goto hard1; 260 bcopy(data.dptr, dbversion, data.dsize); 261 dbversionlen = data.dsize; 262 /* 263 * read version string from kernel memory 264 */ 265 bcopy("_version", symbuf+1, sizeof ("_version")-1); 266 key.dsize = (sizeof ("_version")-1) + 1; 267 data = dbm_fetch(db, key); 268 if (data.dptr == NULL) 269 goto hard1; 270 if (data.dsize != sizeof (struct nlist)) 271 goto hard1; 272 bcopy(data.dptr, &nbuf, sizeof (struct nlist)); 273 lseek(kmem, nbuf.n_value, 0); 274 if (read(kmem, kversion, dbversionlen) != dbversionlen) 275 goto hard1; 276 /* 277 * if they match, we win - otherwise do it the hard way 278 */ 279 if (bcmp(dbversion, kversion, dbversionlen) != 0) 280 goto hard1; 281 /* 282 * getem from the database. 283 */ 284 win: 285 num = did = 0; 286 for (n = nl; n->n_name && n->n_name[0]; n++, num++) { 287 int len; 288 /* 289 * clear out fields from users buffer 290 */ 291 n->n_type = 0; 292 n->n_other = 0; 293 n->n_desc = 0; 294 n->n_value = 0; 295 /* 296 * query db 297 */ 298 if ((len = strlen(n->n_name)) > MAXSYMSIZE) { 299 seterr("kvm_nlist: symbol too large"); 300 return (-1); 301 } 302 strcpy(symbuf+1, n->n_name); 303 key.dsize = len + 1; 304 data = dbm_fetch(db, key); 305 if (data.dptr == NULL || data.dsize != sizeof (struct nlist)) 306 continue; 307 bcopy(data.dptr, &nbuf, sizeof (struct nlist)); 308 n->n_value = nbuf.n_value; 309 n->n_type = nbuf.n_type; 310 n->n_desc = nbuf.n_desc; 311 n->n_other = nbuf.n_other; 312 did++; 313 } 314 return (num - did); 315 hard1: 316 dbm_close(db); 317 db = NULL; 318 hard2: 319 return (nlist(unixf, nl)); /* XXX seterr if -1 */ 320 } 321 322 kvm_getprocs(what, arg) 323 { 324 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) 325 return (NULL); 326 if (!deadkernel) { 327 int ret, copysize; 328 329 if ((ret = getkerninfo(what, NULL, NULL, arg)) == -1) { 330 setsyserr("can't get estimate for kerninfo"); 331 return (-1); 332 } 333 copysize = ret; 334 if ((kvmprocbase = (struct kinfo_proc *)malloc(copysize)) 335 == NULL) { 336 seterr("out of memory"); 337 return (-1); 338 } 339 if ((ret = getkerninfo(what, kvmprocbase, ©size, 340 arg)) == -1) { 341 setsyserr("can't get proc list"); 342 return (-1); 343 } 344 if (copysize % sizeof (struct kinfo_proc)) { 345 seterr("proc size mismatch (kinfo_proc: %d)", 346 sizeof (struct kinfo_proc)); 347 return (-1); 348 } 349 kvmnprocs = copysize / sizeof (struct kinfo_proc); 350 } else { 351 int nproc; 352 353 if (kvm_read(nl[X_NPROC].n_value, &nproc, sizeof (int)) != 354 sizeof (int)) { 355 seterr("can't read nproc"); 356 return (-1); 357 } 358 if ((kvmprocbase = (struct kinfo_proc *) 359 malloc(nproc * sizeof (struct kinfo_proc))) == NULL) { 360 seterr("out of memory (addr: %x nproc = %d)", 361 nl[X_NPROC].n_value, nproc); 362 return (-1); 363 } 364 kvmnprocs = kvm_doprocs(what, arg, kvmprocbase); 365 realloc(kvmprocbase, kvmnprocs * sizeof (struct kinfo_proc)); 366 } 367 kvmprocptr = kvmprocbase; 368 369 return (kvmnprocs); 370 } 371 372 /* 373 * XXX - should NOT give up so easily - especially since the kernel 374 * may be corrupt (it died). Should gather as much information as possible. 375 * Follows proc ptrs instead of reading table since table may go 376 * away soon. 377 */ 378 static 379 kvm_doprocs(what, arg, buff) 380 int what, arg; 381 char *buff; 382 { 383 struct proc *p, proc; 384 register char *bp = buff; 385 int i = 0; 386 int doingzomb = 0; 387 struct eproc eproc; 388 struct pgrp pgrp; 389 struct session sess; 390 struct tty tty; 391 struct text text; 392 393 /* allproc */ 394 if (kvm_read(nl[X_ALLPROC].n_value, &p, 395 sizeof (struct proc *)) != sizeof (struct proc *)) { 396 seterr("can't read allproc"); 397 return (-1); 398 } 399 400 again: 401 for (; p; p = proc.p_nxt) { 402 if (kvm_read(p, &proc, sizeof (struct proc)) != 403 sizeof (struct proc)) { 404 seterr("can't read proc at %x", p); 405 return (-1); 406 } 407 switch(ki_op(what)) { 408 409 case KINFO_PROC_PID: 410 if (proc.p_pid != (pid_t)arg) 411 continue; 412 break; 413 414 415 case KINFO_PROC_UID: 416 if (proc.p_uid != (uid_t)arg) 417 continue; 418 break; 419 420 case KINFO_PROC_RUID: 421 if (proc.p_ruid != (uid_t)arg) 422 continue; 423 break; 424 } 425 /* 426 * gather eproc 427 */ 428 eproc.e_paddr = p; 429 if (kvm_read(proc.p_pgrp, &pgrp, sizeof (struct pgrp)) != 430 sizeof (struct pgrp)) { 431 seterr("can't read pgrp at %x", proc.p_pgrp); 432 return (-1); 433 } 434 eproc.e_sess = pgrp.pg_session; 435 eproc.e_pgid = pgrp.pg_id; 436 eproc.e_jobc = pgrp.pg_jobc; 437 if (kvm_read(pgrp.pg_session, &sess, sizeof (struct session)) 438 != sizeof (struct session)) { 439 seterr("can't read session at %x", pgrp.pg_session); 440 return (-1); 441 } 442 if ((proc.p_flag&SCTTY) && sess.s_ttyp != NULL) { 443 if (kvm_read(sess.s_ttyp, &tty, sizeof (struct tty)) 444 != sizeof (struct tty)) { 445 seterr("can't read tty at %x", sess.s_ttyp); 446 return (-1); 447 } 448 eproc.e_tdev = tty.t_dev; 449 eproc.e_tsess = tty.t_session; 450 if (tty.t_pgrp != NULL) { 451 if (kvm_read(tty.t_pgrp, &pgrp, sizeof (struct 452 pgrp)) != sizeof (struct pgrp)) { 453 seterr("can't read tpgrp at &x", 454 tty.t_pgrp); 455 return (-1); 456 } 457 eproc.e_tpgid = pgrp.pg_id; 458 } else 459 eproc.e_tpgid = -1; 460 } else 461 eproc.e_tdev = NODEV; 462 if (proc.p_wmesg) 463 kvm_read(proc.p_wmesg, eproc.e_wmesg, WMESGLEN); 464 if (proc.p_textp) { 465 kvm_read(proc.p_textp, &text, sizeof (text)); 466 eproc.e_xsize = text.x_size; 467 eproc.e_xrssize = text.x_rssize; 468 eproc.e_xccount = text.x_ccount; 469 eproc.e_xswrss = text.x_swrss; 470 } else { 471 eproc.e_xsize = eproc.e_xrssize = 472 eproc.e_xccount = eproc.e_xswrss = 0; 473 } 474 475 switch(ki_op(what)) { 476 477 case KINFO_PROC_PGRP: 478 if (eproc.e_pgid != (pid_t)arg) 479 continue; 480 break; 481 482 case KINFO_PROC_TTY: 483 if ((proc.p_flag&SCTTY) == 0 || 484 eproc.e_tdev != (dev_t)arg) 485 continue; 486 break; 487 } 488 489 i++; 490 bcopy(&proc, bp, sizeof (struct proc)); 491 bp += sizeof (struct proc); 492 bcopy(&eproc, bp, sizeof (struct eproc)); 493 bp+= sizeof (struct eproc); 494 } 495 if (!doingzomb) { 496 /* zombproc */ 497 if (kvm_read(nl[X_ZOMBPROC].n_value, &p, 498 sizeof (struct proc *)) != sizeof (struct proc *)) { 499 seterr("can't read zombproc"); 500 return (-1); 501 } 502 doingzomb = 1; 503 goto again; 504 } 505 506 return (i); 507 } 508 509 struct proc * 510 kvm_nextproc() 511 { 512 513 if (!kvmprocbase && kvm_getprocs(0, 0) == -1) 514 return (NULL); 515 if (kvmprocptr >= (kvmprocbase + kvmnprocs)) { 516 seterr("end of proc list"); 517 return (NULL); 518 } 519 return((struct proc *)(kvmprocptr++)); 520 } 521 522 struct eproc * 523 kvm_geteproc(p) 524 struct proc *p; 525 { 526 return ((struct eproc *)(((char *)p) + sizeof (struct proc))); 527 } 528 529 kvm_setproc() 530 { 531 532 kvmprocptr = kvmprocbase; 533 } 534 535 kvm_freeprocs() 536 { 537 538 if (kvmprocbase) { 539 free(kvmprocbase); 540 kvmprocbase = NULL; 541 } 542 } 543 544 struct user * 545 kvm_getu(p) 546 struct proc *p; 547 { 548 struct pte *pteaddr, apte; 549 struct pte arguutl[HIGHPAGES+(CLSIZE*2)]; 550 register int i; 551 int ncl; 552 553 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) 554 return (NULL); 555 if (p->p_stat == SZOMB) { 556 seterr("zombie process"); 557 return (NULL); 558 } 559 if ((p->p_flag & SLOAD) == 0) { 560 if (swap < 0) { 561 seterr("no swap"); 562 return (NULL); 563 } 564 (void) lseek(swap, (long)dtob(p->p_swaddr), 0); 565 if (read(swap, (char *)&user.user, sizeof (struct user)) != 566 sizeof (struct user)) { 567 seterr("can't read u for pid %d from %s\n", 568 p->p_pid, swapf); 569 return (NULL); 570 } 571 pcbpf = 0; 572 argaddr0 = 0; 573 argaddr1 = 0; 574 return (&user.user); 575 } 576 pteaddr = &Usrptmap[btokmx(p->p_p0br) + p->p_szpt - 1]; 577 klseek(kmem, (long)pteaddr, 0); 578 if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { 579 seterr("can't read indir pte to get u for pid %d from %s", 580 p->p_pid, kmemf); 581 return (NULL); 582 } 583 lseek(mem, (long)ctob(pftoc(apte.pg_pfnum+1)) - sizeof(arguutl), 0); 584 if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) { 585 seterr("can't read page table for u of pid %d from %s", 586 p->p_pid, memf); 587 return (NULL); 588 } 589 if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum) 590 argaddr0 = ctob(pftoc(arguutl[0].pg_pfnum)); 591 else 592 argaddr0 = 0; 593 if (arguutl[CLSIZE*1].pg_fod == 0 && arguutl[CLSIZE*1].pg_pfnum) 594 argaddr1 = ctob(pftoc(arguutl[CLSIZE*1].pg_pfnum)); 595 else 596 argaddr1 = 0; 597 pcbpf = arguutl[CLSIZE*2].pg_pfnum; 598 ncl = (sizeof (struct user) + CLBYTES - 1) / CLBYTES; 599 while (--ncl >= 0) { 600 i = ncl * CLSIZE; 601 lseek(mem, 602 (long)ctob(pftoc(arguutl[(CLSIZE*2)+i].pg_pfnum)), 0); 603 if (read(mem, user.upages[i], CLBYTES) != CLBYTES) { 604 seterr("can't read page %d of u of pid %d from %s", 605 arguutl[(CLSIZE*2)+i].pg_pfnum, p->p_pid, memf); 606 return(NULL); 607 } 608 } 609 return (&user.user); 610 } 611 612 char * 613 kvm_getargs(p, up) 614 struct proc *p; 615 struct user *up; 616 { 617 char cmdbuf[CLBYTES*2]; 618 union { 619 char argc[CLBYTES*2]; 620 int argi[CLBYTES*2/sizeof (int)]; 621 } argspac; 622 register char *cp; 623 register int *ip; 624 char c; 625 int nbad; 626 struct dblock db; 627 char *file; 628 629 if (up == NULL || p->p_pid == 0 || p->p_pid == 2) 630 goto retucomm; 631 if ((p->p_flag & SLOAD) == 0 || argaddr1 == 0) { 632 if (swap < 0 || p->p_ssize == 0) 633 goto retucomm; 634 vstodb(0, CLSIZE, &up->u_smap, &db, 1); 635 (void) lseek(swap, (long)dtob(db.db_base), 0); 636 if (read(swap, (char *)&argspac.argc[CLBYTES], CLBYTES) 637 != CLBYTES) 638 goto bad; 639 vstodb(1, CLSIZE, &up->u_smap, &db, 1); 640 (void) lseek(swap, (long)dtob(db.db_base), 0); 641 if (read(swap, (char *)&argspac.argc[0], CLBYTES) != CLBYTES) 642 goto bad; 643 file = swapf; 644 } else { 645 if (argaddr0) { 646 lseek(mem, (long)argaddr0, 0); 647 if (read(mem, (char *)&argspac, CLBYTES) != CLBYTES) 648 goto bad; 649 } else 650 bzero(&argspac, CLBYTES); 651 lseek(mem, (long)argaddr1, 0); 652 if (read(mem, &argspac.argc[CLBYTES], CLBYTES) != CLBYTES) 653 goto bad; 654 file = memf; 655 } 656 ip = &argspac.argi[CLBYTES*2/sizeof (int)]; 657 ip -= 2; /* last arg word and .long 0 */ 658 while (*--ip) { 659 if (ip == argspac.argi) 660 goto retucomm; 661 } 662 *(char *)ip = ' '; 663 ip++; 664 nbad = 0; 665 for (cp = (char *)ip; cp < &argspac.argc[CLBYTES*2]; cp++) { 666 c = *cp & 0177; 667 if (c == 0) 668 *cp = ' '; 669 else if (c < ' ' || c > 0176) { 670 if (++nbad >= 5*(0+1)) { /* eflg -> 0 XXX */ 671 *cp++ = ' '; 672 break; 673 } 674 *cp = '?'; 675 } else if (0 == 0 && c == '=') { /* eflg -> 0 XXX */ 676 while (*--cp != ' ') 677 if (cp <= (char *)ip) 678 break; 679 break; 680 } 681 } 682 *cp = 0; 683 while (*--cp == ' ') 684 *cp = 0; 685 cp = (char *)ip; 686 (void) strncpy(cmdbuf, cp, &argspac.argc[CLBYTES*2] - cp); 687 if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') { 688 (void) strcat(cmdbuf, " ("); 689 (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm)); 690 (void) strcat(cmdbuf, ")"); 691 } 692 return (cmdbuf); 693 694 bad: 695 seterr("error locating command name for pid %d from %s\n", 696 p->p_pid, file); 697 retucomm: 698 (void) strcpy(cmdbuf, " ("); 699 (void) strncat(cmdbuf, p->p_comm, sizeof (p->p_comm)); 700 (void) strcat(cmdbuf, ")"); 701 return (cmdbuf); 702 } 703 704 705 static 706 getkvars() 707 { 708 709 if (kvm_nlist(nl) == -1) 710 return (-1); 711 if (deadkernel) { 712 /* We must do the sys map first because klseek uses it */ 713 long addr; 714 715 Syssize = nl[X_SYSSIZE].n_value; 716 Sysmap = (struct pte *) 717 calloc((unsigned) Syssize, sizeof (struct pte)); 718 if (Sysmap == NULL) { 719 seterr("out of space for Sysmap"); 720 return (-1); 721 } 722 addr = (long) nl[X_SYSMAP].n_value; 723 addr &= ~KERNBASE; 724 (void) lseek(kmem, addr, 0); 725 if (read(kmem, (char *) Sysmap, Syssize * sizeof (struct pte)) 726 != Syssize * sizeof (struct pte)) { 727 seterr("can't read Sysmap"); 728 return (-1); 729 } 730 #if defined(hp300) 731 addr = (long) nl[X_LOWRAM].n_value; 732 (void) lseek(kmem, addr, 0); 733 if (read(kmem, (char *) &lowram, sizeof (lowram)) 734 != sizeof (lowram)) { 735 seterr("can't read lowram"); 736 return (-1); 737 } 738 lowram = btop(lowram); 739 #endif 740 } 741 usrpt = (struct pte *)nl[X_USRPT].n_value; 742 Usrptmap = (struct pte *)nl[X_USRPTMAP].n_value; 743 if (kvm_read((long)nl[X_NSWAP].n_value, &nswap, sizeof (long)) != 744 sizeof (long)) { 745 seterr("can't read nswap"); 746 return (-1); 747 } 748 if (kvm_read((long)nl[X_DMMIN].n_value, &dmmin, sizeof (long)) != 749 sizeof (long)) { 750 seterr("can't read dmmin"); 751 return (-1); 752 } 753 if (kvm_read((long)nl[X_DMMAX].n_value, &dmmax, sizeof (long)) != 754 sizeof (long)) { 755 seterr("can't read dmmax"); 756 return (-1); 757 } 758 return (0); 759 } 760 761 kvm_read(loc, buf, len) 762 unsigned long loc; 763 char *buf; 764 { 765 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) 766 return (-1); 767 if (iskva(loc)) { 768 klseek(kmem, loc, 0); 769 if (read(kmem, buf, len) != len) { 770 seterr("error reading kmem at %x\n", loc); 771 return (-1); 772 } 773 } else { 774 lseek(mem, loc, 0); 775 if (read(mem, buf, len) != len) { 776 seterr("error reading mem at %x\n", loc); 777 return (-1); 778 } 779 } 780 return (len); 781 } 782 783 static 784 klseek(fd, loc, off) 785 int fd; 786 off_t loc; 787 int off; 788 { 789 790 if (deadkernel) { 791 off_t vtophys(); 792 793 if ((loc = vtophys(loc)) == -1) 794 return; 795 } 796 (void) lseek(fd, (off_t)loc, off); 797 } 798 799 /* 800 * Given a base/size pair in virtual swap area, 801 * return a physical base/size pair which is the 802 * (largest) initial, physically contiguous block. 803 */ 804 static 805 vstodb(vsbase, vssize, dmp, dbp, rev) 806 register int vsbase; 807 int vssize; 808 struct dmap *dmp; 809 register struct dblock *dbp; 810 { 811 register int blk = dmmin; 812 register swblk_t *ip = dmp->dm_map; 813 814 vsbase = ctod(vsbase); 815 vssize = ctod(vssize); 816 if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 817 /*panic("vstodb")*/; 818 while (vsbase >= blk) { 819 vsbase -= blk; 820 if (blk < dmmax) 821 blk *= 2; 822 ip++; 823 } 824 if (*ip <= 0 || *ip + blk > nswap) 825 /*panic("vstodb")*/; 826 dbp->db_size = MIN(vssize, blk - vsbase); 827 dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase); 828 } 829 830 static off_t 831 vtophys(loc) 832 long loc; 833 { 834 int p; 835 off_t newloc; 836 register struct pte *pte; 837 838 newloc = loc & ~KERNBASE; 839 p = btop(newloc); 840 #if defined(vax) || defined(tahoe) 841 if ((loc & KERNBASE) == 0) { 842 seterr("vtophys: translating non-kernel address"); 843 return((off_t) -1); 844 } 845 #endif 846 if (p >= Syssize) { 847 seterr("vtophys: page out of bound (%d>=%d)", p, Syssize); 848 return((off_t) -1); 849 } 850 pte = &Sysmap[p]; 851 if (pte->pg_v == 0 && (pte->pg_fod || pte->pg_pfnum == 0)) { 852 seterr("vtophys: page not valid"); 853 return((off_t) -1); 854 } 855 #if defined(hp300) 856 if (pte->pg_pfnum < lowram) { 857 seterr("vtophys: non-RAM page (%d<%d)", pte->pg_pfnum, lowram); 858 return((off_t) -1); 859 } 860 #endif 861 loc = (long) (ptob(pftoc(pte->pg_pfnum)) + (loc & PGOFSET)); 862 return(loc); 863 } 864 865 #include <varargs.h> 866 static char errbuf[LINE_MAX]; 867 868 static 869 seterr(va_alist) 870 va_dcl 871 { 872 char *fmt; 873 va_list ap; 874 875 va_start(ap); 876 fmt = va_arg(ap, char *); 877 (void) vsprintf(errbuf, fmt, ap); 878 va_end(ap); 879 } 880 881 static 882 setsyserr(va_alist) 883 va_dcl 884 { 885 char *fmt, *cp; 886 va_list ap; 887 extern int errno; 888 889 va_start(ap); 890 fmt = va_arg(ap, char *); 891 (void) vsprintf(errbuf, fmt, ap); 892 for (cp=errbuf; *cp; cp++) 893 ; 894 sprintf(cp, ": %s", strerror(errno)); 895 va_end(ap); 896 } 897 898 char * 899 kvm_geterr() 900 { 901 return (errbuf); 902 } 903