[BACK]Return to kvm.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libkvm

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, &copysize,
                    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>