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