Annotation of src/lib/libkvm/kvm.c, Revision 1.32
1.1 cgd 1: /*-
1.24 mycroft 2: * Copyright (c) 1994 Charles Hannum.
1.9 cgd 3: * Copyright (c) 1993 Christopher G. Demetriou
1.1 cgd 4: * Copyright (c) 1989 The Regents of the University of California.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #if defined(LIBC_SCCS) && !defined(lint)
1.12 mycroft 37: /*static char sccsid[] = "from: @(#)kvm.c 5.18 (Berkeley) 5/7/91";*/
1.32 ! briggs 38: static char rcsid[] = "$Id: kvm.c,v 1.31 1994/04/17 04:48:31 cgd Exp $";
1.1 cgd 39: #endif /* LIBC_SCCS and not lint */
40:
41: #include <sys/param.h>
42: #include <sys/user.h>
43: #include <sys/proc.h>
44: #include <sys/ioctl.h>
45: #include <sys/kinfo.h>
46: #include <sys/tty.h>
1.8 cgd 47: #include <sys/exec.h>
1.1 cgd 48: #include <machine/vmparam.h>
49: #include <fcntl.h>
50: #include <nlist.h>
51: #include <kvm.h>
52: #include <ndbm.h>
53: #include <limits.h>
54: #include <paths.h>
55: #include <stdio.h>
56: #include <string.h>
57:
58: #define btop(x) (((unsigned)(x)) >> PGSHIFT) /* XXX */
59: #define ptob(x) ((caddr_t)((x) << PGSHIFT)) /* XXX */
60: #include <vm/vm.h> /* ??? kinfo_proc currently includes this*/
1.3 cgd 61: #include <vm/vm_page.h>
62: #include <vm/swap_pager.h>
1.1 cgd 63: #include <sys/kinfo_proc.h>
1.21 cgd 64: #if defined(m68k)
1.13 mycroft 65: #include <machine/pte.h>
1.16 mycroft 66: #define btos(x) (((unsigned)(x)) >> SEGSHIFT) /* XXX */
1.1 cgd 67: #endif
68:
69: /*
70: * files
71: */
72: static const char *unixf, *memf, *kmemf, *swapf;
73: static int unixx, mem, kmem, swap;
74: static DBM *db;
75: /*
76: * flags
77: */
78: static int deadkernel;
79: static int kvminit = 0;
80: static int kvmfilesopen = 0;
81: /*
82: * state
83: */
84: static struct kinfo_proc *kvmprocbase, *kvmprocptr;
85: static int kvmnprocs;
86: /*
87: * u. buffer
88: */
89: static union {
90: struct user user;
91: char upages[UPAGES][NBPG];
92: } user;
1.3 cgd 93:
94: struct swapblk {
95: long offset; /* offset in swap device */
96: long size; /* remaining size of block in swap device */
97: };
1.19 mycroft 98:
1.1 cgd 99: /*
100: * random other stuff
101: */
102: static int dmmin, dmmax;
103: static int pcbpf;
104: static int nswap;
1.19 mycroft 105: static long vm_page_hash_mask;
106: static long vm_page_buckets;
107: static long page_shift;
1.1 cgd 108: static char *tmp;
1.21 cgd 109: #if defined(m68k)
1.32 ! briggs 110: #if defined(amiga) || defined(mac68k)
1.25 chopps 111: static int cpu040;
112: #endif
1.1 cgd 113: static int lowram;
114: static struct ste *Sysseg;
115: #endif
116: #if defined(i386)
117: static struct pde *PTD;
118: #endif
119:
1.19 mycroft 120: #define atop(x) (((unsigned)(x)) >> page_shift)
121: #define vm_page_hash(object, offset) \
122: (((unsigned)object+(unsigned)atop(offset))&vm_page_hash_mask)
123:
1.1 cgd 124: #define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp))
125: #define MAXSYMSIZE 256
126:
127: static struct nlist nl[] = {
128: { "_Usrptmap" },
129: #define X_USRPTMAP 0
130: { "_usrpt" },
131: #define X_USRPT 1
132: { "_nswap" },
133: #define X_NSWAP 2
134: { "_dmmin" },
135: #define X_DMMIN 3
136: { "_dmmax" },
137: #define X_DMMAX 4
1.3 cgd 138: { "_vm_page_buckets" },
139: #define X_VM_PAGE_BUCKETS 5
140: { "_vm_page_hash_mask" },
141: #define X_VM_PAGE_HASH_MASK 6
142: { "_page_shift" },
143: #define X_PAGE_SHIFT 7
1.26 pk 144:
145: #if defined(m68k)
146: #define X_DEADKERNEL 8
147: #endif
148:
149: #if defined(i386)
1.27 phil 150: #define X_DEADKERNEL 8
151: #endif
152:
153: #if defined(ns32k)
1.26 pk 154: #define X_DEADKERNEL 8
155: #endif
156:
157: #if defined(sparc)
158: { "_pmap_dtos" },
159: #define X_PMAP_DTOS 8
160: #define X_DEADKERNEL 9
161: #endif
162:
1.1 cgd 163: /*
164: * everything here and down, only if a dead kernel
165: */
166: { "_Sysmap" },
1.26 pk 167: #define X_SYSMAP (X_DEADKERNEL + 0)
1.1 cgd 168: { "_Syssize" },
1.26 pk 169: #define X_SYSSIZE (X_DEADKERNEL + 1)
1.1 cgd 170: { "_allproc" },
1.26 pk 171: #define X_ALLPROC (X_DEADKERNEL + 2)
1.1 cgd 172: { "_zombproc" },
1.26 pk 173: #define X_ZOMBPROC (X_DEADKERNEL + 3)
1.1 cgd 174: { "_nproc" },
1.26 pk 175: #define X_NPROC (X_DEADKERNEL + 4)
176: #define X_LAST (X_DEADKERNEL + 5)
177:
1.21 cgd 178: #if defined(m68k)
1.1 cgd 179: { "_Sysseg" },
1.26 pk 180: #define X_SYSSEG (X_LAST+0)
1.1 cgd 181: { "_lowram" },
1.26 pk 182: #define X_LOWRAM (X_LAST+1)
1.32 ! briggs 183: #if defined(amiga) || defined(mac68k)
1.25 chopps 184: { "_cpu040" },
1.26 pk 185: #define X_CPU040 (X_LAST+2)
1.25 chopps 186: #endif
1.1 cgd 187: #endif
1.26 pk 188:
1.1 cgd 189: #if defined(i386)
190: { "_IdlePTD" },
1.26 pk 191: #define X_IdlePTD (X_LAST+0)
1.1 cgd 192: #endif
1.26 pk 193:
1.1 cgd 194: { "" },
195: };
196:
197: static off_t Vtophys();
198: static void klseek(), seterr(), setsyserr(), vstodb();
199: static int getkvars(), kvm_doprocs(), kvm_init();
1.3 cgd 200: static int vatosw();
1.19 mycroft 201: static int pager_get();
1.3 cgd 202: static int findpage();
1.26 pk 203: #if defined(sparc)
204: static vm_offset_t phys2realphys();
205: #endif
1.1 cgd 206:
207: /*
208: * returns 0 if files were opened now,
209: * 1 if files were already opened,
210: * -1 if files could not be opened.
211: */
212: kvm_openfiles(uf, mf, sf)
213: const char *uf, *mf, *sf;
214: {
215: if (kvmfilesopen)
216: return (1);
217: unixx = mem = kmem = swap = -1;
218: unixf = (uf == NULL) ? _PATH_UNIX : uf;
219: memf = (mf == NULL) ? _PATH_MEM : mf;
220:
221: if ((unixx = open(unixf, O_RDONLY, 0)) == -1) {
222: setsyserr("can't open %s", unixf);
223: goto failed;
224: }
225: if ((mem = open(memf, O_RDONLY, 0)) == -1) {
226: setsyserr("can't open %s", memf);
227: goto failed;
228: }
229: if (sf != NULL)
230: swapf = sf;
231: if (mf != NULL) {
232: deadkernel++;
233: kmemf = mf;
234: kmem = mem;
235: swap = -1;
236: } else {
237: kmemf = _PATH_KMEM;
238: if ((kmem = open(kmemf, O_RDONLY, 0)) == -1) {
239: setsyserr("can't open %s", kmemf);
240: goto failed;
241: }
242: swapf = (sf == NULL) ? _PATH_DRUM : sf;
243: /*
244: * live kernel - avoid looking up nlist entries
245: * past X_DEADKERNEL.
246: */
247: nl[X_DEADKERNEL].n_name = "";
248: }
249: if (swapf != NULL && ((swap = open(swapf, O_RDONLY, 0)) == -1)) {
250: seterr("can't open %s", swapf);
251: goto failed;
252: }
253: kvmfilesopen++;
254: if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) /*XXX*/
255: return (-1);
256: return (0);
257: failed:
258: kvm_close();
259: return (-1);
260: }
261:
262: static
263: kvm_init(uf, mf, sf)
264: char *uf, *mf, *sf;
265: {
266: if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
267: return (-1);
268: if (getkvars() == -1)
269: return (-1);
270: kvminit = 1;
271:
272: return (0);
273: }
274:
275: kvm_close()
276: {
277: if (unixx != -1) {
278: close(unixx);
279: unixx = -1;
280: }
281: if (kmem != -1) {
282: if (kmem != mem)
283: close(kmem);
284: /* otherwise kmem is a copy of mem, and will be closed below */
285: kmem = -1;
286: }
287: if (mem != -1) {
288: close(mem);
289: mem = -1;
290: }
291: if (swap != -1) {
292: close(swap);
293: swap = -1;
294: }
295: if (db != NULL) {
296: dbm_close(db);
297: db = NULL;
298: }
299: kvminit = 0;
300: kvmfilesopen = 0;
301: deadkernel = 0;
302: }
303:
304: kvm_nlist(nl)
305: struct nlist *nl;
306: {
307: datum key, data;
308: char dbname[MAXPATHLEN];
309: char dbversion[_POSIX2_LINE_MAX];
310: char kversion[_POSIX2_LINE_MAX];
311: int dbversionlen;
312: char symbuf[MAXSYMSIZE];
313: struct nlist nbuf, *n;
314: int num, did;
315:
316: if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
317: return (-1);
318: if (deadkernel)
319: goto hard2;
320: /*
321: * initialize key datum
322: */
323: key.dptr = symbuf;
324:
325: if (db != NULL)
326: goto win; /* off to the races */
327: /*
328: * open database
329: */
330: sprintf(dbname, "%s/kvm_%s", _PATH_VARRUN, basename(unixf));
331: if ((db = dbm_open(dbname, O_RDONLY, 0)) == NULL)
332: goto hard2;
333: /*
334: * read version out of database
335: */
336: bcopy("VERSION", symbuf, sizeof ("VERSION")-1);
1.2 cgd 337: key.dsize = (sizeof ("VERSION") - 1);
1.1 cgd 338: data = dbm_fetch(db, key);
339: if (data.dptr == NULL)
340: goto hard1;
341: bcopy(data.dptr, dbversion, data.dsize);
342: dbversionlen = data.dsize;
343: /*
344: * read version string from kernel memory
345: */
346: bcopy("_version", symbuf, sizeof ("_version")-1);
1.2 cgd 347: key.dsize = (sizeof ("_version")-1);
1.1 cgd 348: data = dbm_fetch(db, key);
349: if (data.dptr == NULL)
350: goto hard1;
351: if (data.dsize != sizeof (struct nlist))
352: goto hard1;
353: bcopy(data.dptr, &nbuf, sizeof (struct nlist));
354: lseek(kmem, nbuf.n_value, 0);
355: if (read(kmem, kversion, dbversionlen) != dbversionlen)
356: goto hard1;
357: /*
358: * if they match, we win - otherwise do it the hard way
359: */
360: if (bcmp(dbversion, kversion, dbversionlen) != 0)
361: goto hard1;
362: /*
363: * getem from the database.
364: */
365: win:
366: num = did = 0;
367: for (n = nl; n->n_name && n->n_name[0]; n++, num++) {
368: int len;
369: /*
370: * clear out fields from users buffer
371: */
372: n->n_type = 0;
373: n->n_other = 0;
374: n->n_desc = 0;
375: n->n_value = 0;
376: /*
377: * query db
378: */
379: if ((len = strlen(n->n_name)) > MAXSYMSIZE) {
380: seterr("symbol too large");
381: return (-1);
382: }
383: (void)strcpy(symbuf, n->n_name);
1.2 cgd 384: key.dsize = len;
1.1 cgd 385: data = dbm_fetch(db, key);
386: if (data.dptr == NULL || data.dsize != sizeof (struct nlist))
387: continue;
388: bcopy(data.dptr, &nbuf, sizeof (struct nlist));
389: n->n_value = nbuf.n_value;
390: n->n_type = nbuf.n_type;
391: n->n_desc = nbuf.n_desc;
392: n->n_other = nbuf.n_other;
393: did++;
394: }
395: return (num - did);
396: hard1:
397: dbm_close(db);
398: db = NULL;
399: hard2:
400: num = nlist(unixf, nl);
401: if (num == -1)
402: seterr("nlist (hard way) failed");
403: return (num);
404: }
405:
406: kvm_getprocs(what, arg)
407: int what, arg;
408: {
1.3 cgd 409: static int ocopysize = -1;
410:
1.1 cgd 411: if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
412: return (NULL);
413: if (!deadkernel) {
414: int ret, copysize;
415:
416: if ((ret = getkerninfo(what, NULL, NULL, arg)) == -1) {
417: setsyserr("can't get estimate for kerninfo");
418: return (-1);
419: }
420: copysize = ret;
1.5 cgd 421: if (copysize > ocopysize || !kvmprocbase) {
422: if (ocopysize == -1 || !kvmprocbase)
1.4 mycroft 423: kvmprocbase =
424: (struct kinfo_proc *)malloc(copysize);
425: else
426: kvmprocbase =
427: (struct kinfo_proc *)realloc(kvmprocbase,
428: copysize);
429: if (!kvmprocbase) {
430: seterr("out of memory");
431: return (-1);
432: }
1.1 cgd 433: }
1.3 cgd 434: ocopysize = copysize;
1.1 cgd 435: if ((ret = getkerninfo(what, kvmprocbase, ©size,
436: arg)) == -1) {
437: setsyserr("can't get proc list");
438: return (-1);
439: }
440: if (copysize % sizeof (struct kinfo_proc)) {
441: seterr("proc size mismatch (got %d total, kinfo_proc: %d)",
442: copysize, sizeof (struct kinfo_proc));
443: return (-1);
444: }
445: kvmnprocs = copysize / sizeof (struct kinfo_proc);
446: } else {
447: int nproc;
448:
449: if (kvm_read((void *) nl[X_NPROC].n_value, &nproc,
1.19 mycroft 450: sizeof (int)) == -1) {
1.1 cgd 451: seterr("can't read nproc");
452: return (-1);
453: }
454: if ((kvmprocbase = (struct kinfo_proc *)
455: malloc(nproc * sizeof (struct kinfo_proc))) == NULL) {
456: seterr("out of memory (addr: %x nproc = %d)",
457: nl[X_NPROC].n_value, nproc);
458: return (-1);
459: }
460: kvmnprocs = kvm_doprocs(what, arg, kvmprocbase);
461: realloc(kvmprocbase, kvmnprocs * sizeof (struct kinfo_proc));
462: }
463: kvmprocptr = kvmprocbase;
464:
465: return (kvmnprocs);
466: }
467:
468: /*
469: * XXX - should NOT give up so easily - especially since the kernel
470: * may be corrupt (it died). Should gather as much information as possible.
471: * Follows proc ptrs instead of reading table since table may go
472: * away soon.
473: */
474: static
475: kvm_doprocs(what, arg, buff)
476: int what, arg;
477: char *buff;
478: {
479: struct proc *p, proc;
480: register char *bp = buff;
481: int i = 0;
482: int doingzomb = 0;
483: struct eproc eproc;
484: struct pgrp pgrp;
485: struct session sess;
486: struct tty tty;
487:
488: /* allproc */
489: if (kvm_read((void *) nl[X_ALLPROC].n_value, &p,
1.19 mycroft 490: sizeof (struct proc *)) == -1) {
1.1 cgd 491: seterr("can't read allproc");
492: return (-1);
493: }
494:
495: again:
496: for (; p; p = proc.p_nxt) {
1.19 mycroft 497: if (kvm_read(p, &proc, sizeof (struct proc)) == -1) {
1.1 cgd 498: seterr("can't read proc at %x", p);
499: return (-1);
500: }
501: if (kvm_read(proc.p_cred, &eproc.e_pcred,
1.19 mycroft 502: sizeof (struct pcred)) != -1)
1.1 cgd 503: (void) kvm_read(eproc.e_pcred.pc_ucred, &eproc.e_ucred,
504: sizeof (struct ucred));
1.19 mycroft 505:
1.1 cgd 506: switch(ki_op(what)) {
507:
508: case KINFO_PROC_PID:
509: if (proc.p_pid != (pid_t)arg)
510: continue;
511: break;
512:
513:
514: case KINFO_PROC_UID:
515: if (eproc.e_ucred.cr_uid != (uid_t)arg)
516: continue;
517: break;
518:
519: case KINFO_PROC_RUID:
520: if (eproc.e_pcred.p_ruid != (uid_t)arg)
521: continue;
522: break;
523: }
524: /*
525: * gather eproc
526: */
527: eproc.e_paddr = p;
1.19 mycroft 528: if (kvm_read(proc.p_pgrp, &pgrp, sizeof (struct pgrp)) == -1) {
1.1 cgd 529: seterr("can't read pgrp at %x", proc.p_pgrp);
530: return (-1);
531: }
532: eproc.e_sess = pgrp.pg_session;
533: eproc.e_pgid = pgrp.pg_id;
534: eproc.e_jobc = pgrp.pg_jobc;
535: if (kvm_read(pgrp.pg_session, &sess, sizeof (struct session))
1.19 mycroft 536: == -1) {
1.1 cgd 537: seterr("can't read session at %x", pgrp.pg_session);
538: return (-1);
539: }
540: if ((proc.p_flag&SCTTY) && sess.s_ttyp != NULL) {
541: if (kvm_read(sess.s_ttyp, &tty, sizeof (struct tty))
1.19 mycroft 542: == -1) {
1.1 cgd 543: seterr("can't read tty at %x", sess.s_ttyp);
544: return (-1);
545: }
546: eproc.e_tdev = tty.t_dev;
547: eproc.e_tsess = tty.t_session;
548: if (tty.t_pgrp != NULL) {
549: if (kvm_read(tty.t_pgrp, &pgrp, sizeof (struct
1.19 mycroft 550: pgrp)) == -1) {
1.1 cgd 551: seterr("can't read tpgrp at &x",
552: tty.t_pgrp);
553: return (-1);
554: }
555: eproc.e_tpgid = pgrp.pg_id;
556: } else
557: eproc.e_tpgid = -1;
558: } else
559: eproc.e_tdev = NODEV;
560: if (proc.p_wmesg)
1.19 mycroft 561: (void) kvm_read(proc.p_wmesg, eproc.e_wmesg, WMESGLEN);
1.1 cgd 562: (void) kvm_read(proc.p_vmspace, &eproc.e_vm,
563: sizeof (struct vmspace));
564: eproc.e_xsize = eproc.e_xrssize =
565: eproc.e_xccount = eproc.e_xswrss = 0;
566:
567: switch(ki_op(what)) {
568:
569: case KINFO_PROC_PGRP:
570: if (eproc.e_pgid != (pid_t)arg)
571: continue;
572: break;
573:
574: case KINFO_PROC_TTY:
575: if ((proc.p_flag&SCTTY) == 0 ||
576: eproc.e_tdev != (dev_t)arg)
577: continue;
578: break;
579: }
580:
581: i++;
582: bcopy(&proc, bp, sizeof (struct proc));
583: bp += sizeof (struct proc);
584: bcopy(&eproc, bp, sizeof (struct eproc));
585: bp+= sizeof (struct eproc);
586: }
587: if (!doingzomb) {
588: /* zombproc */
589: if (kvm_read((void *) nl[X_ZOMBPROC].n_value, &p,
1.19 mycroft 590: sizeof (struct proc *)) == -1) {
1.1 cgd 591: seterr("can't read zombproc");
592: return (-1);
593: }
594: doingzomb = 1;
595: goto again;
596: }
597:
598: return (i);
599: }
600:
601: struct proc *
602: kvm_nextproc()
603: {
604:
605: if (!kvmprocbase && kvm_getprocs(0, 0) == -1)
606: return (NULL);
607: if (kvmprocptr >= (kvmprocbase + kvmnprocs)) {
608: seterr("end of proc list");
609: return (NULL);
610: }
611: return((struct proc *)(kvmprocptr++));
612: }
613:
614: struct eproc *
615: kvm_geteproc(p)
616: const struct proc *p;
617: {
618: return ((struct eproc *)(((char *)p) + sizeof (struct proc)));
619: }
620:
621: kvm_setproc()
622: {
623: kvmprocptr = kvmprocbase;
624: }
625:
626: kvm_freeprocs()
627: {
628:
629: if (kvmprocbase) {
630: free(kvmprocbase);
631: kvmprocbase = NULL;
632: }
633: }
634:
635: struct user *
636: kvm_getu(p)
637: const struct proc *p;
638: {
639: register struct kinfo_proc *kp = (struct kinfo_proc *)p;
640: register int i;
641: register char *up;
1.3 cgd 642: u_int vaddr;
643: struct swapblk swb;
1.1 cgd 644:
645: if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
646: return (NULL);
647: if (p->p_stat == SZOMB) {
648: seterr("zombie process");
649: return (NULL);
650: }
1.3 cgd 651:
652: if ((p->p_flag & SLOAD) == 0) {
653: vm_offset_t maddr;
654:
655: if (swap < 0) {
656: seterr("no swap");
657: return (NULL);
658: }
659: /*
660: * Costly operation, better set enable_swap to zero
661: * in vm/vm_glue.c, since paging of user pages isn't
662: * done yet anyway.
663: */
1.19 mycroft 664: if (vatosw(&kp->kp_eproc.e_vm.vm_map, USRSTACK + i * NBPG,
665: &maddr, &swb) == 0)
1.3 cgd 666: return NULL;
667:
668: if (maddr == 0 && swb.size < UPAGES * NBPG)
669: return NULL;
670:
671: for (i = 0; i < UPAGES; i++) {
672: if (maddr) {
673: (void) lseek(mem, maddr + i * NBPG, 0);
674: if (read(mem,
675: (char *)user.upages[i], NBPG) != NBPG) {
1.26 pk 676: setsyserr(
1.3 cgd 677: "can't read u for pid %d from %s",
678: p->p_pid, swapf);
679: return NULL;
680: }
681: } else {
682: (void) lseek(swap, swb.offset + i * NBPG, 0);
683: if (read(swap,
684: (char *)user.upages[i], NBPG) != NBPG) {
1.26 pk 685: setsyserr(
1.3 cgd 686: "can't read u for pid %d from %s",
687: p->p_pid, swapf);
688: return NULL;
689: }
690: }
691: }
692: return(&user.user);
693: }
1.1 cgd 694: /*
695: * Read u-area one page at a time for the benefit of post-mortems
696: */
697: up = (char *) p->p_addr;
698: for (i = 0; i < UPAGES; i++) {
1.29 cgd 699: klseek(kmem, (off_t)(long)up, 0);
1.1 cgd 700: if (read(kmem, user.upages[i], CLBYTES) != CLBYTES) {
1.26 pk 701: setsyserr("cant read page %x of u of pid %d from %s",
1.1 cgd 702: up, p->p_pid, kmemf);
703: return(NULL);
704: }
705: up += CLBYTES;
706: }
707: pcbpf = (int) btop(p->p_addr); /* what should this be really? */
708:
709: return(&user.user);
710: }
711:
1.8 cgd 712: int
713: kvm_procread(p, addr, buf, len)
714: const struct proc *p;
1.19 mycroft 715: const unsigned addr;
716: unsigned len;
1.11 mycroft 717: char *buf;
1.8 cgd 718: {
719: register struct kinfo_proc *kp = (struct kinfo_proc *) p;
720: struct swapblk swb;
721: vm_offset_t swaddr = 0, memaddr = 0;
722: unsigned real_len;
1.24 mycroft 723: static int last_pid = -1;
724: static vm_offset_t last_addr;
725: static char bouncebuf[CLBYTES];
1.8 cgd 726:
727: real_len = len < (CLBYTES - (addr & CLOFSET)) ? len : (CLBYTES - (addr & CLOFSET));
728:
1.24 mycroft 729: if (p->p_pid != last_pid || last_addr != (addr & ~CLOFSET)) {
730: if (vatosw(&kp->kp_eproc.e_vm.vm_map, addr & ~CLOFSET, &memaddr,
731: &swb) == 0)
1.11 mycroft 732: return 0;
1.24 mycroft 733:
734: if (memaddr) {
1.26 pk 735: #if defined(sparc)
736: memaddr = phys2realphys(memaddr);
737: #endif
1.24 mycroft 738: if (lseek(mem, memaddr, 0) == -1) {
1.26 pk 739: setsyserr("kvm_procread: lseek mem");
1.24 mycroft 740: return 0;
741: }
742: len = read(mem, bouncebuf, CLBYTES);
743: if (len == -1 || len < CLBYTES) {
744: last_pid = -1;
1.26 pk 745: setsyserr("kvm_procread: read mem");
1.24 mycroft 746: return 0;
747: }
748: } else {
749: swaddr = swb.offset;
750: if (lseek(swap, swaddr, 0) == -1) {
1.26 pk 751: setsyserr("kvm_procread: lseek swap");
1.24 mycroft 752: return 0;
753: }
754: len = read(swap, bouncebuf, CLBYTES);
755: if (len == -1 || len < CLBYTES) {
756: last_pid = -1;
1.26 pk 757: setsyserr("kvm_procread: read swap");
1.24 mycroft 758: return 0;
759: }
1.8 cgd 760: }
1.19 mycroft 761: }
1.8 cgd 762:
1.24 mycroft 763: memcpy(buf, &bouncebuf[addr & CLOFSET], real_len);
764: last_pid = p->p_pid;
765: last_addr = addr & ~CLOFSET;
766: return real_len;
1.8 cgd 767: }
768:
769: int
770: kvm_procreadstr(p, addr, buf, len)
771: const struct proc *p;
1.11 mycroft 772: const unsigned addr;
773: char *buf;
1.8 cgd 774: unsigned len;
775: {
1.10 deraadt 776: int done, little;
777: char copy[200], *pb;
1.11 mycroft 778: char a;
1.8 cgd 779:
780: done = 0;
1.15 cgd 781: copy[0] = '\0';
1.10 deraadt 782: while (len) {
783: little = kvm_procread(p, addr+done, copy, MIN(len, sizeof copy));
784: if (little<1)
785: break;
786: pb = copy;
787: while (little--) {
788: len--;
1.11 mycroft 789: if( (*buf++ = *pb++) == '\0' )
1.15 cgd 790: return done;
791: done++;
1.10 deraadt 792: }
1.8 cgd 793: }
794: return done;
795: }
796:
1.1 cgd 797: char *
798: kvm_getargs(p, up)
799: const struct proc *p;
800: const struct user *up;
801: {
1.24 mycroft 802: static char *cmdbuf = NULL, ucomm[sizeof(p->p_comm) + 4];
1.8 cgd 803: register char *cp, *acp;
804: int left, rv;
805: struct ps_strings arginfo;
1.1 cgd 806:
1.24 mycroft 807: if (cmdbuf == NULL) {
808: cmdbuf = (char *)malloc(ARG_MAX + sizeof(p->p_comm) + 5);
809: if (cmdbuf == NULL)
810: cmdbuf = ucomm;
811: }
812:
813: if (cmdbuf == ucomm || up == NULL || p->p_pid == 0 || p->p_pid == 2)
1.1 cgd 814: goto retucomm;
1.8 cgd 815:
1.11 mycroft 816: if (kvm_procread(p, PS_STRINGS, (char *)&arginfo, sizeof(arginfo)) !=
1.8 cgd 817: sizeof(arginfo))
818: goto bad;
819:
1.15 cgd 820: cmdbuf[0] = '\0';
1.8 cgd 821: cp = cmdbuf;
822: acp = arginfo.ps_argvstr;
823: left = ARG_MAX + 1;
824: while (arginfo.ps_nargvstr--) {
825: if ((rv = kvm_procreadstr(p, acp, cp, left)) >= 0) {
826: acp += rv + 1;
827: left -= rv + 1;
828: cp += rv;
829: *cp++ = ' ';
830: *cp = '\0';
1.1 cgd 831: } else
832: goto bad;
833: }
1.8 cgd 834: cp-- ; *cp = '\0';
1.2 cgd 835:
1.8 cgd 836: if (cmdbuf[0] == '-' || cmdbuf[0] == '?' || cmdbuf[0] <= ' ') {
1.1 cgd 837: (void) strcat(cmdbuf, " (");
838: (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm));
839: (void) strcat(cmdbuf, ")");
840: }
841: return (cmdbuf);
842:
843: bad:
1.8 cgd 844: seterr("error locating command name for pid %d", p->p_pid);
1.1 cgd 845: retucomm:
1.8 cgd 846: (void) strcpy(cmdbuf, "(");
1.1 cgd 847: (void) strncat(cmdbuf, p->p_comm, sizeof (p->p_comm));
848: (void) strcat(cmdbuf, ")");
849: return (cmdbuf);
850: }
851:
1.8 cgd 852: char *
853: kvm_getenv(p, up)
854: const struct proc *p;
855: const struct user *up;
856: {
1.24 mycroft 857: static char *envbuf = NULL, emptyenv[1];
1.8 cgd 858: register char *cp, *acp;
859: int left, rv;
860: struct ps_strings arginfo;
861:
1.24 mycroft 862: if (envbuf == NULL) {
863: envbuf = (char *)malloc(ARG_MAX + 1);
864: if (envbuf == NULL)
865: envbuf = emptyenv;
866: }
867:
868: if (envbuf == emptyenv || up == NULL || p->p_pid == 0 || p->p_pid == 2)
1.8 cgd 869: goto retemptyenv;
870:
1.11 mycroft 871: if (kvm_procread(p, PS_STRINGS, (char *)&arginfo, sizeof(arginfo)) !=
1.8 cgd 872: sizeof(arginfo))
873: goto bad;
874:
875: cp = envbuf;
876: acp = arginfo.ps_envstr;
877: left = ARG_MAX + 1;
878: while (arginfo.ps_nenvstr--) {
879: if ((rv = kvm_procreadstr(p, acp, cp, left)) >= 0) {
880: acp += rv + 1;
881: left -= rv + 1;
882: cp += rv;
883: *cp++ = ' ';
884: *cp = '\0';
885: } else
886: goto bad;
887: }
888: cp-- ; *cp = '\0';
889: return (envbuf);
890:
891: bad:
892: seterr("error locating environment for pid %d", p->p_pid);
893: retemptyenv:
894: envbuf[0] = '\0';
895: return (envbuf);
896: }
1.1 cgd 897:
898: static
899: getkvars()
900: {
901: if (kvm_nlist(nl) == -1)
902: return (-1);
903: if (deadkernel) {
904: /* We must do the sys map first because klseek uses it */
905: long addr;
906:
1.21 cgd 907: #if defined(m68k)
1.32 ! briggs 908: #if defined(amiga) || defined(mac68k)
1.25 chopps 909: addr = (long) nl[X_CPU040].n_value;
910: (void) lseek(kmem, addr, 0);
911: if (read(kmem, (char *) &cpu040, sizeof (cpu040))
912: != sizeof (cpu040)) {
913: seterr("can't read cpu040");
914: return (-1);
915: }
916: #endif
1.1 cgd 917: addr = (long) nl[X_LOWRAM].n_value;
918: (void) lseek(kmem, addr, 0);
919: if (read(kmem, (char *) &lowram, sizeof (lowram))
920: != sizeof (lowram)) {
921: seterr("can't read lowram");
922: return (-1);
923: }
924: lowram = btop(lowram);
925: Sysseg = (struct ste *) malloc(NBPG);
926: if (Sysseg == NULL) {
927: seterr("out of space for Sysseg");
928: return (-1);
929: }
930: addr = (long) nl[X_SYSSEG].n_value;
931: (void) lseek(kmem, addr, 0);
932: read(kmem, (char *)&addr, sizeof(addr));
933: (void) lseek(kmem, (long)addr, 0);
934: if (read(kmem, (char *) Sysseg, NBPG) != NBPG) {
935: seterr("can't read Sysseg");
936: return (-1);
937: }
938: #endif
939: #if defined(i386)
940: PTD = (struct pde *) malloc(NBPG);
941: if (PTD == NULL) {
942: seterr("out of space for PTD");
943: return (-1);
944: }
945: addr = (long) nl[X_IdlePTD].n_value;
946: (void) lseek(kmem, addr, 0);
947: read(kmem, (char *)&addr, sizeof(addr));
948: (void) lseek(kmem, (long)addr, 0);
949: if (read(kmem, (char *) PTD, NBPG) != NBPG) {
950: seterr("can't read PTD");
951: return (-1);
952: }
953: #endif
954: }
1.19 mycroft 955: if (kvm_read((void *) nl[X_NSWAP].n_value, &nswap, sizeof (long)) == -1) {
1.1 cgd 956: seterr("can't read nswap");
957: return (-1);
958: }
1.19 mycroft 959: if (kvm_read((void *) nl[X_DMMIN].n_value, &dmmin, sizeof (long)) == -1) {
1.1 cgd 960: seterr("can't read dmmin");
961: return (-1);
962: }
1.19 mycroft 963: if (kvm_read((void *) nl[X_DMMAX].n_value, &dmmax, sizeof (long)) == -1) {
1.1 cgd 964: seterr("can't read dmmax");
965: return (-1);
966: }
1.19 mycroft 967: if (kvm_read((void *) nl[X_VM_PAGE_HASH_MASK].n_value,
968: &vm_page_hash_mask, sizeof (long)) == -1) {
969: seterr("can't read vm_page_hash_mask");
970: return (-1);
971: }
972: if (kvm_read((void *) nl[X_VM_PAGE_BUCKETS].n_value,
973: &vm_page_buckets, sizeof (long)) == -1) {
974: seterr("can't read vm_page_buckets");
975: return (-1);
976: }
977: if (kvm_read((void *) nl[X_PAGE_SHIFT].n_value,
978: &page_shift, sizeof (long)) == -1) {
979: seterr("can't read page_shift");
980: return (-1);
981: }
982:
1.1 cgd 983: return (0);
984: }
985:
1.26 pk 986: int
1.1 cgd 987: kvm_read(loc, buf, len)
988: void *loc;
989: void *buf;
990: {
1.26 pk 991: int n;
992:
1.1 cgd 993: if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
994: return (-1);
1.29 cgd 995: klseek(kmem, (off_t)(long)loc, 0);
1.26 pk 996: if ((n = read(kmem, buf, len)) != len) {
997: if (n == -1)
998: setsyserr("error reading kmem at %#x", loc);
999: else
1000: seterr("short read on kmem at %#x", loc);
1.19 mycroft 1001: return (-1);
1.1 cgd 1002: }
1003: return (len);
1004: }
1005:
1006: static void
1007: klseek(fd, loc, off)
1008: int fd;
1009: off_t loc;
1010: int off;
1011: {
1012:
1013: if (deadkernel) {
1014: if ((loc = Vtophys(loc)) == -1)
1015: return;
1016: }
1017: (void) lseek(fd, (off_t)loc, off);
1018: }
1019:
1020: static off_t
1021: Vtophys(loc)
1022: u_long loc;
1023: {
1024: off_t newloc = (off_t) -1;
1.21 cgd 1025: #if defined(m68k)
1.1 cgd 1026: int p, ste, pte;
1027:
1.16 mycroft 1028: ste = *(int *)&Sysseg[btos(loc)];
1.1 cgd 1029: if ((ste & SG_V) == 0) {
1030: seterr("vtophys: segment not valid");
1031: return((off_t) -1);
1032: }
1033: p = btop(loc & SG_PMASK);
1034: newloc = (ste & SG_FRAME) + (p * sizeof(struct pte));
1.16 mycroft 1035: (void) lseek(mem, newloc, 0);
1036: if (read(mem, (char *)&pte, sizeof pte) != sizeof pte) {
1.1 cgd 1037: seterr("vtophys: cannot locate pte");
1038: return((off_t) -1);
1039: }
1040: newloc = pte & PG_FRAME;
1041: if (pte == PG_NV || newloc < (off_t)ptob(lowram)) {
1042: seterr("vtophys: page not valid");
1043: return((off_t) -1);
1044: }
1045: newloc = (newloc - (off_t)ptob(lowram)) + (loc & PGOFSET);
1046: #endif
1.26 pk 1047: #if defined(i386)
1.1 cgd 1048: struct pde pde;
1049: struct pte pte;
1050: int p;
1051:
1.22 mycroft 1052: pde = PTD[loc >> PDSHIFT];
1.1 cgd 1053: if (pde.pd_v == 0) {
1054: seterr("vtophys: page directory entry not valid");
1055: return((off_t) -1);
1056: }
1057: p = btop(loc & PT_MASK);
1058: newloc = pde.pd_pfnum + (p * sizeof(struct pte));
1059: (void) lseek(kmem, (long)newloc, 0);
1060: if (read(kmem, (char *)&pte, sizeof pte) != sizeof pte) {
1061: seterr("vtophys: cannot obtain desired pte");
1062: return((off_t) -1);
1063: }
1064: newloc = pte.pg_pfnum;
1065: if (pte.pg_v == 0) {
1066: seterr("vtophys: page table entry not valid");
1067: return((off_t) -1);
1068: }
1069: newloc += (loc & PGOFSET);
1070: #endif
1071: return((off_t) newloc);
1072: }
1073:
1.3 cgd 1074: /*
1075: * locate address of unwired or swapped page
1076: */
1077:
1078: static int
1.19 mycroft 1079: vatosw(mp, vaddr, maddr, swb)
1080: vm_map_t mp;
1.3 cgd 1081: vm_offset_t vaddr;
1082: vm_offset_t *maddr;
1083: struct swapblk *swb;
1084: {
1085: struct vm_object vm_object;
1086: struct vm_map_entry vm_entry;
1.19 mycroft 1087: long saddr, addr, off;
1.3 cgd 1088: int i;
1089:
1.19 mycroft 1090: saddr = addr = (long)mp->header.next;
1091: #ifdef DEBUG
1092: fprintf(stderr, "vatosw: head=%x\n", &mp->header);
1093: #endif
1094: for (i = 0; ; i++) {
1.3 cgd 1095: /* Weed through map entries until vaddr in range */
1.19 mycroft 1096: if (kvm_read((void *) addr, &vm_entry, sizeof(vm_entry)) == -1) {
1.26 pk 1097: seterr("vatosw: can't read vm_map_entry");
1.3 cgd 1098: return 0;
1099: }
1.19 mycroft 1100: #ifdef DEBUG
1101: fprintf(stderr, "vatosw: %d/%d, vaddr=%x, start=%x, end=%x ",
1102: i, mp->nentries, vaddr, vm_entry.start, vm_entry.end);
1103: fprintf(stderr, "addr=%x, next=%x\n", addr, vm_entry.next);
1.18 mycroft 1104: #endif
1105: if ((vaddr >= vm_entry.start) && (vaddr < vm_entry.end))
1106: if (vm_entry.object.vm_object != 0)
1107: break;
1108: else {
1.19 mycroft 1109: seterr("vatosw: no object\n");
1.18 mycroft 1110: return 0;
1111: }
1.3 cgd 1112:
1113: addr = (long)vm_entry.next;
1.19 mycroft 1114:
1115: if (addr == saddr) {
1116: seterr("vatosw: map not found\n");
1117: return 0;
1118: }
1.3 cgd 1119: }
1120:
1121: if (vm_entry.is_a_map || vm_entry.is_sub_map) {
1.19 mycroft 1122: #ifdef DEBUG
1123: fprintf(stderr, "vatosw: is a %smap\n",
1.18 mycroft 1124: vm_entry.is_sub_map ? "sub " : "");
1125: #endif
1.19 mycroft 1126: seterr("vatosw: is a %smap\n",
1127: vm_entry.is_sub_map ? "sub " : "");
1.3 cgd 1128: return 0;
1129: }
1130:
1131: /* Locate memory object */
1132: off = (vaddr - vm_entry.start) + vm_entry.offset;
1133: addr = (long)vm_entry.object.vm_object;
1134: while (1) {
1.19 mycroft 1135: if (kvm_read((void *) addr, &vm_object, sizeof (vm_object)) == -1) {
1.26 pk 1136: seterr("vatosw: can't read vm_object");
1.3 cgd 1137: return 0;
1138: }
1139:
1.19 mycroft 1140: #ifdef DEBUG
1141: fprintf(stderr, "vatosw: find page: object %#x offset %x\n",
1142: addr, off);
1.3 cgd 1143: #endif
1144:
1145: /* Lookup in page queue */
1.18 mycroft 1146: if ((i = findpage(addr, off, maddr)) != -1)
1147: return i;
1148:
1149: if (vm_object.pager != 0 &&
1150: (i = pager_get(&vm_object, off, swb)) != -1)
1151: return i;
1.3 cgd 1152:
1.18 mycroft 1153: if (vm_object.shadow == 0)
1.3 cgd 1154: break;
1155:
1.19 mycroft 1156: #ifdef DEBUG
1157: fprintf(stderr, "vatosw: shadow obj at %x: offset %x+%x\n",
1158: addr, off, vm_object.shadow_offset);
1.3 cgd 1159: #endif
1160:
1161: addr = (long)vm_object.shadow;
1162: off += vm_object.shadow_offset;
1163: }
1164:
1.19 mycroft 1165: seterr("vatosw: page not found\n");
1.18 mycroft 1166: return 0;
1167: }
1168:
1169:
1170: int
1171: pager_get(object, off, swb)
1172: struct vm_object *object;
1173: long off;
1174: struct swapblk *swb;
1175: {
1176: struct pager_struct pager;
1177: struct swpager swpager;
1178: struct swblock swblock;
1179:
1.3 cgd 1180: /* Find address in swap space */
1.19 mycroft 1181: if (kvm_read(object->pager, &pager, sizeof (pager)) == -1) {
1.26 pk 1182: seterr("pager_get: can't read pager");
1.3 cgd 1183: return 0;
1184: }
1185: if (pager.pg_type != PG_SWAP) {
1.18 mycroft 1186: seterr("pager_get: weird pager\n");
1.3 cgd 1187: return 0;
1188: }
1189:
1190: /* Get swap pager data */
1.19 mycroft 1191: if (kvm_read(pager.pg_data, &swpager, sizeof (swpager)) == -1) {
1.26 pk 1192: seterr("pager_get: can't read swpager");
1.3 cgd 1193: return 0;
1194: }
1195:
1.18 mycroft 1196: off += object->paging_offset;
1.3 cgd 1197:
1198: /* Read swap block array */
1.19 mycroft 1199: if (kvm_read((void *) swpager.sw_blocks +
1.3 cgd 1200: (off/dbtob(swpager.sw_bsize)) * sizeof swblock,
1.19 mycroft 1201: &swblock, sizeof (swblock)) == -1) {
1.26 pk 1202: seterr("pager_get: can't read swblock");
1.3 cgd 1203: return 0;
1204: }
1.18 mycroft 1205:
1206: off %= dbtob(swpager.sw_bsize);
1.3 cgd 1207:
1.18 mycroft 1208: if (swblock.swb_mask & (1 << atop(off))) {
1209: swb->offset = dbtob(swblock.swb_block) + off;
1210: swb->size = dbtob(swpager.sw_bsize) - off;
1211: return 1;
1212: }
1.3 cgd 1213:
1.18 mycroft 1214: return -1;
1215: }
1.3 cgd 1216:
1217: static int
1218: findpage(object, offset, maddr)
1219: long object;
1220: long offset;
1221: vm_offset_t *maddr;
1222: {
1.30 cgd 1223: struct pglist bucket;
1.3 cgd 1224: struct vm_page mem;
1225: long addr, baddr;
1226:
1.19 mycroft 1227: baddr = vm_page_buckets +
1.30 cgd 1228: vm_page_hash(object,offset) * sizeof(struct pglist);
1.3 cgd 1229:
1.19 mycroft 1230: if (kvm_read((void *) baddr, &bucket, sizeof (bucket)) == -1) {
1.3 cgd 1231: seterr("can't read vm_page_bucket");
1232: return 0;
1233: }
1234:
1.30 cgd 1235: addr = (long)bucket.tqh_first;
1.19 mycroft 1236:
1.31 cgd 1237: while (addr != NULL) {
1.19 mycroft 1238: if (kvm_read((void *) addr, &mem, sizeof (mem)) == -1) {
1.3 cgd 1239: seterr("can't read vm_page");
1240: return 0;
1241: }
1.19 mycroft 1242:
1.3 cgd 1243: if ((long)mem.object == object && mem.offset == offset) {
1244: *maddr = (long)mem.phys_addr;
1245: return 1;
1246: }
1.19 mycroft 1247:
1.30 cgd 1248: addr = (long)mem.hashq.tqe_next;
1.3 cgd 1249: }
1.18 mycroft 1250:
1251: return -1;
1.3 cgd 1252: }
1253:
1.26 pk 1254: #if defined(sparc)
1255: /*
1256: * This comes from the bowels of pmap.c
1257: */
1258: #define MAXMEM (128 * 1024 * 1024) /* no more than 128 MB phys mem */
1259: #define NPGBANK 16 /* 2^4 pages per bank (64K / bank) */
1260: #define BSHIFT 4 /* log2(NPGBANK) */
1261: #define BOFFSET (NPGBANK - 1)
1262: #define BTSIZE (MAXMEM / NBPG / NPGBANK)
1263:
1264: static int pmap_dtos[BTSIZE]; /* dense to sparse */
1265: static int pmap_stod[BTSIZE]; /* sparse to dense */
1266:
1267: #define HWTOSW(pg) (pmap_stod[(pg) >> BSHIFT] | ((pg) & BOFFSET))
1268: #define SWTOHW(pg) (pmap_dtos[(pg) >> BSHIFT] | ((pg) & BOFFSET))
1269: /* -- */
1270:
1271: static int pmap_dtos_valid;
1272:
1273: /*
1274: * Translate a VM physical address to a hardware physical address.
1275: */
1276: static vm_offset_t
1277: phys2realphys(memaddr)
1278: vm_offset_t memaddr;
1279: {
1280: if (nl[X_PMAP_DTOS].n_value == 0)
1281: /* This is possibly a sun4 */
1282: return memaddr;
1283:
1284: if (!pmap_dtos_valid) {
1285: if (kvm_read((void *)nl[X_PMAP_DTOS].n_value,
1286: pmap_dtos, sizeof (pmap_dtos)) == -1) {
1287: seterr("can't read pmap_dtos table");
1288: return -1;
1289: }
1290: pmap_dtos_valid = 1;
1291: }
1292: return (SWTOHW(atop(memaddr)) << PGSHIFT) | (memaddr & PGOFSET);
1293: }
1294: #endif
1295:
1.1 cgd 1296: #include <varargs.h>
1297: static char errbuf[_POSIX2_LINE_MAX];
1298:
1299: static void
1300: seterr(va_alist)
1301: va_dcl
1302: {
1303: char *fmt;
1304: va_list ap;
1305:
1306: va_start(ap);
1307: fmt = va_arg(ap, char *);
1308: (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap);
1.19 mycroft 1309: #ifdef DEBUG
1.26 pk 1310: (void) fprintf(stderr, "%s\n", errbuf);
1.3 cgd 1311: #endif
1.1 cgd 1312: va_end(ap);
1313: }
1314:
1315: static void
1316: setsyserr(va_alist)
1317: va_dcl
1318: {
1319: char *fmt, *cp;
1320: va_list ap;
1321: extern int errno;
1322:
1323: va_start(ap);
1324: fmt = va_arg(ap, char *);
1.20 mycroft 1325: (void) vsnprintf(cp = errbuf, _POSIX2_LINE_MAX, fmt, ap);
1.19 mycroft 1326: cp += strlen(cp);
1327: (void) snprintf(cp, _POSIX2_LINE_MAX - (cp - errbuf), ": %s",
1328: strerror(errno));
1329: #ifdef DEBUG
1.26 pk 1330: (void) fprintf(stderr, "%s\n", errbuf);
1.19 mycroft 1331: #endif
1.1 cgd 1332: va_end(ap);
1333: }
1334:
1335: char *
1336: kvm_geterr()
1337: {
1338: return (errbuf);
1339: }
CVSweb <webmaster@jp.NetBSD.org>