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

Annotation of src/lib/libkvm/kvm_sparc.c, Revision 1.28

1.28    ! agc         1: /*     $NetBSD: kvm_sparc.c,v 1.27 2003/05/16 10:24:56 wiz Exp $       */
1.8       thorpej     2:
1.1       cgd         3: /*-
                      4:  * Copyright (c) 1992, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  *
                      7:  * This code is derived from software developed by the Computer Systems
                      8:  * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
                      9:  * BG 91-66 and contributed to Berkeley.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
1.28    ! agc        19:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        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:
1.13      mikel      36: #include <sys/cdefs.h>
1.1       cgd        37: #if defined(LIBC_SCCS) && !defined(lint)
1.8       thorpej    38: #if 0
1.1       cgd        39: static char sccsid[] = "@(#)kvm_sparc.c        8.1 (Berkeley) 6/4/93";
1.8       thorpej    40: #else
1.28    ! agc        41: __RCSID("$NetBSD: kvm_sparc.c,v 1.27 2003/05/16 10:24:56 wiz Exp $");
1.8       thorpej    42: #endif
1.1       cgd        43: #endif /* LIBC_SCCS and not lint */
                     44:
                     45: /*
1.21      simonb     46:  * Sparc machine dependent routines for kvm.  Hopefully, the forthcoming
1.1       cgd        47:  * vm code will one day obsolete this module.
                     48:  */
                     49:
                     50: #include <sys/param.h>
1.14      pk         51: #include <sys/exec.h>
1.1       cgd        52: #include <sys/user.h>
                     53: #include <sys/proc.h>
                     54: #include <sys/stat.h>
1.10      pk         55: #include <sys/core.h>
                     56: #include <sys/kcore.h>
1.1       cgd        57: #include <unistd.h>
                     58: #include <nlist.h>
                     59: #include <kvm.h>
                     60:
1.23      mrg        61: #include <uvm/uvm_extern.h>
1.22      mrg        62:
1.25      matt       63: #include <machine/pmap.h>
1.10      pk         64: #include <machine/kcore.h>
1.1       cgd        65:
                     66: #include <limits.h>
                     67: #include <db.h>
                     68:
                     69: #include "kvm_private.h"
                     70:
                     71:
1.4       deraadt    72: static int cputyp = -1;
1.10      pk         73: static int pgshift;
                     74: static int nptesg;     /* [sun4/sun4c] only */
1.3       deraadt    75:
1.26      mrg        76: #undef VA_VPG
1.9       cgd        77: #define VA_VPG(va)     ((cputyp == CPU_SUN4C || cputyp == CPU_SUN4M) \
                     78:                                ? VA_SUN4C_VPG(va) \
                     79:                                : VA_SUN4_VPG(va))
1.4       deraadt    80:
1.26      mrg        81: #undef VA_OFF
1.10      pk         82: #define VA_OFF(va) (va & (kd->nbpg - 1))
                     83:
1.15      mrg        84: int _kvm_kvatop44c __P((kvm_t *, u_long, u_long *));
                     85: int _kvm_kvatop4m __P((kvm_t *, u_long, u_long *));
1.20      mrg        86: int _kvm_kvatop4u __P((kvm_t *, u_long, u_long *));
                     87:
                     88: /*
                     89:  * XXX
1.21      simonb     90:  * taken from /sys/arch/sparc64/include/kcore.h.
1.20      mrg        91:  * this is the same as the sparc one, except for the kphys addition,
                     92:  * so luckily we can use this here...
                     93:  */
                     94: typedef struct sparc64_cpu_kcore_hdr {
                     95:        int     cputype;                /* CPU type associated with this dump */
                     96:        u_long  kernbase;               /* copy of KERNBASE goes here */
                     97:        int     nmemseg;                /* # of physical memory segments */
                     98:        u_long  memsegoffset;           /* start of memseg array (relative */
                     99:                                        /*  to the start of this header) */
                    100:        int     nsegmap;                /* # of segmaps following */
                    101:        u_long  segmapoffset;           /* start of segmap array (relative */
                    102:                                        /*  to the start of this header) */
                    103:        int     npmeg;                  /* # of PMEGs; [sun4/sun4c] only */
                    104:        u_long  pmegoffset;             /* start of pmeg array (relative */
                    105:                                        /*  to the start of this header) */
                    106: /* SPARC64 stuff */
                    107:        paddr_t kphys;                  /* Physical address of 4MB locked TLB */
                    108: } sparc64_cpu_kcore_hdr_t;
1.9       cgd       109:
1.10      pk        110: void
                    111: _kvm_freevtop(kd)
                    112:        kvm_t *kd;
1.9       cgd       113: {
1.10      pk        114:        if (kd->vmst != 0) {
                    115:                _kvm_err(kd, kd->program, "_kvm_freevtop: internal error");
                    116:                kd->vmst = 0;
                    117:        }
1.9       cgd       118: }
                    119:
1.10      pk        120: /*
                    121:  * Prepare for translation of kernel virtual addresses into offsets
                    122:  * into crash dump files. We use the MMU specific goop written at the
                    123:  * front of the crash dump by pmap_dumpmmu().
                    124:  */
                    125: int
                    126: _kvm_initvtop(kd)
1.3       deraadt   127:        kvm_t *kd;
                    128: {
1.20      mrg       129:        sparc64_cpu_kcore_hdr_t *cpup = kd->cpu_data;
1.9       cgd       130:
1.10      pk        131:        switch (cputyp = cpup->cputype) {
                    132:        case CPU_SUN4:
1.19      eeh       133:        case CPU_SUN4U:
1.10      pk        134:                kd->nbpg = 8196;
                    135:                pgshift = 13;
                    136:                break;
                    137:        case CPU_SUN4C:
                    138:        case CPU_SUN4M:
                    139:                kd->nbpg = 4096;
                    140:                pgshift = 12;
                    141:                break;
                    142:        default:
                    143:                _kvm_err(kd, kd->program, "Unsupported CPU type");
1.9       cgd       144:                return (-1);
                    145:        }
1.10      pk        146:        nptesg = NBPSG / kd->nbpg;
1.9       cgd       147:        return (0);
1.3       deraadt   148: }
                    149:
1.7       pk        150: /*
1.9       cgd       151:  * Translate a kernel virtual address to a physical address using the
                    152:  * mapping information in kd->vm.  Returns the result in pa, and returns
1.21      simonb    153:  * the number of bytes that are contiguously available from this
1.27      wiz       154:  * physical address.  This routine is used only for crash dumps.
1.9       cgd       155:  */
                    156: int
                    157: _kvm_kvatop(kd, va, pa)
                    158:        kvm_t *kd;
                    159:        u_long va;
                    160:        u_long *pa;
                    161: {
1.10      pk        162:        if (cputyp == -1)
                    163:                if (_kvm_initvtop(kd) != 0)
                    164:                        return (-1);
1.9       cgd       165:
1.19      eeh       166:        switch (cputyp) {
                    167:        case CPU_SUN4:
                    168:        case CPU_SUN4C:
                    169:                return _kvm_kvatop44c(kd, va, pa);
                    170:                break;
                    171:        case CPU_SUN4M:
                    172:                return _kvm_kvatop4m(kd, va, pa);
                    173:                break;
                    174:        case CPU_SUN4U:
                    175:        default:
                    176:                return _kvm_kvatop4u(kd, va, pa);
                    177:        }
1.9       cgd       178: }
                    179:
                    180: /*
                    181:  * (note: sun4 3-level MMU not yet supported)
                    182:  */
                    183: int
                    184: _kvm_kvatop44c(kd, va, pa)
1.1       cgd       185:        kvm_t *kd;
                    186:        u_long va;
                    187:        u_long *pa;
                    188: {
1.16      perry     189:        int vr, vs, pte;
1.20      mrg       190:        sparc64_cpu_kcore_hdr_t *cpup = kd->cpu_data;
1.14      pk        191:        struct segmap *sp, *segmaps;
1.10      pk        192:        int *ptes;
1.14      pk        193:        int nkreg, nureg;
                    194:        u_long kernbase = cpup->kernbase;
1.1       cgd       195:
1.14      pk        196:        if (va < kernbase)
1.7       pk        197:                goto err;
                    198:
1.10      pk        199:        /*
                    200:         * Layout of CPU segment:
                    201:         *      cpu_kcore_hdr_t;
                    202:         *      [alignment]
                    203:         *      phys_ram_seg_t[cpup->nmemseg];
1.14      pk        204:         *      segmap[cpup->nsegmap];
1.10      pk        205:         *      ptes[cpup->npmegs];
                    206:         */
1.14      pk        207:        segmaps = (struct segmap *)((long)kd->cpu_data + cpup->segmapoffset);
1.10      pk        208:        ptes = (int *)((int)kd->cpu_data + cpup->pmegoffset);
1.14      pk        209:        nkreg = ((int)((-(unsigned)kernbase) / NBPRG));
                    210:        nureg = 256 - nkreg;
1.10      pk        211:
1.7       pk        212:        vr = VA_VREG(va);
                    213:        vs = VA_VSEG(va);
1.1       cgd       214:
1.14      pk        215:        sp = &segmaps[(vr-nureg)*NSEGRG + vs];
1.7       pk        216:        if (sp->sg_npte == 0)
                    217:                goto err;
1.11      pk        218:        if (sp->sg_pmeg == cpup->npmeg - 1) /* =seginval */
1.7       pk        219:                goto err;
1.10      pk        220:        pte = ptes[sp->sg_pmeg * nptesg + VA_VPG(va)];
1.7       pk        221:        if ((pte & PG_V) != 0) {
1.16      perry     222:                long p, off = VA_OFF(va);
1.7       pk        223:
                    224:                p = (pte & PG_PFNUM) << pgshift;
1.10      pk        225:                *pa = p + off;
1.7       pk        226:                return (kd->nbpg - off);
1.1       cgd       227:        }
1.7       pk        228: err:
1.24      sommerfe  229:        _kvm_err(kd, 0, "invalid address (%lx)", va);
1.1       cgd       230:        return (0);
                    231: }
1.4       deraadt   232:
1.9       cgd       233: int
                    234: _kvm_kvatop4m(kd, va, pa)
                    235:        kvm_t *kd;
                    236:        u_long va;
                    237:        u_long *pa;
                    238: {
1.20      mrg       239:        sparc64_cpu_kcore_hdr_t *cpup = kd->cpu_data;
1.16      perry     240:        int vr, vs;
1.9       cgd       241:        int pte;
                    242:        off_t foff;
1.14      pk        243:        struct segmap *sp, *segmaps;
                    244:        int nkreg, nureg;
                    245:        u_long kernbase = cpup->kernbase;
1.9       cgd       246:
1.14      pk        247:        if (va < kernbase)
1.9       cgd       248:                goto err;
                    249:
1.10      pk        250:        /*
                    251:         * Layout of CPU segment:
                    252:         *      cpu_kcore_hdr_t;
                    253:         *      [alignment]
                    254:         *      phys_ram_seg_t[cpup->nmemseg];
1.14      pk        255:         *      segmap[cpup->nsegmap];
1.10      pk        256:         */
1.14      pk        257:        segmaps = (struct segmap *)((long)kd->cpu_data + cpup->segmapoffset);
                    258:        nkreg = ((int)((-(unsigned)kernbase) / NBPRG));
                    259:        nureg = 256 - nkreg;
1.10      pk        260:
1.9       cgd       261:        vr = VA_VREG(va);
                    262:        vs = VA_VSEG(va);
                    263:
1.14      pk        264:        sp = &segmaps[(vr-nureg)*NSEGRG + vs];
1.9       cgd       265:        if (sp->sg_npte == 0)
                    266:                goto err;
                    267:
1.10      pk        268:        /* XXX - assume page tables in initial kernel DATA or BSS. */
1.14      pk        269:        foff = _kvm_pa2off(kd, (u_long)&sp->sg_pte[VA_VPG(va)] - kernbase);
1.10      pk        270:        if (foff == (off_t)-1)
                    271:                return (0);
                    272:
1.18      thorpej   273:        if (pread(kd->pmfd, &pte, sizeof(pte), foff) != sizeof(pte)) {
1.24      sommerfe  274:                _kvm_syserr(kd, kd->program, "cannot read pte for %lx", va);
1.10      pk        275:                return (0);
1.9       cgd       276:        }
                    277:
                    278:        if ((pte & SRMMU_TETYPE) == SRMMU_TEPTE) {
1.16      perry     279:                long p, off = VA_OFF(va);
1.9       cgd       280:
                    281:                p = (pte & SRMMU_PPNMASK) << SRMMU_PPNPASHIFT;
1.10      pk        282:                *pa = p + off;
1.9       cgd       283:                return (kd->nbpg - off);
                    284:        }
                    285: err:
1.24      sommerfe  286:        _kvm_err(kd, 0, "invalid address (%lx)", va);
1.9       cgd       287:        return (0);
1.10      pk        288: }
1.19      eeh       289:
                    290: /*
1.20      mrg       291:  * sparc64 pmap's 32-bit page table format
1.19      eeh       292:  */
                    293: int
                    294: _kvm_kvatop4u(kd, va, pa)
                    295:        kvm_t *kd;
                    296:        u_long va;
                    297:        u_long *pa;
                    298: {
1.20      mrg       299:        sparc64_cpu_kcore_hdr_t *cpup = kd->cpu_data;
1.19      eeh       300:        int64_t **segmaps;
                    301:        int64_t *ptes;
                    302:        int64_t pte;
1.20      mrg       303:        int64_t kphys = cpup->kphys;
1.19      eeh       304:        u_long kernbase = cpup->kernbase;
                    305:
                    306:        if (va < kernbase)
                    307:                goto err;
                    308:
1.21      simonb    309:        /*
1.19      eeh       310:         * Kernel layout:
                    311:         *
                    312:         * kernbase:
                    313:         *      4MB locked TLB (text+data+BSS)
1.21      simonb    314:         *      Random other stuff.
1.19      eeh       315:         */
1.20      mrg       316:        if (va >= kernbase && va < kernbase + 4*1024*1024)
1.19      eeh       317:                return (va - kernbase) + kphys;
                    318:
1.20      mrg       319: /* XXX: from sparc64/include/pmap.h */
                    320: #define        SPARC64_PTSZ            (kd->nbpg/8)
                    321: #define        SPARC64_STSZ            (SPARC64_PTSZ)
                    322: #define        SPARC64_PTMASK          (SPARC64_PTSZ-1)
                    323: #define        SPARC64_PTSHIFT         (13)
                    324: #define        SPARC64_PDSHIFT         (10+SPARC64_PTSHIFT)
                    325: #define        SPARC64_STSHIFT         (10+SPARC64_PDSHIFT)
                    326: #define        SPARC64_STMASK          (SPARC64_STSZ-1)
                    327: #define        sparc64_va_to_seg(v)    (int)((((int64_t)(v))>>SPARC64_STSHIFT)&SPARC64_STMASK)
                    328: #define        sparc64_va_to_pte(v)    (int)((((int64_t)(v))>>SPARC64_PTSHIFT)&SPARC64_PTMASK)
                    329:
                    330: /* XXX: from sparc64/include/pte.h */
                    331: #define        SPARC64_TLB_V                   0x8000000000000000LL
                    332: #define        SPARC64_TLB_PA_MASK             0x000001ffffffe000LL
                    333:
1.19      eeh       334:        /*
                    335:         * Layout of CPU segment:
                    336:         *      cpu_kcore_hdr_t;
                    337:         *      [alignment]
                    338:         *      phys_ram_seg_t[cpup->nmemseg];
                    339:         *      segmap[cpup->nsegmap];
                    340:         */
1.20      mrg       341:        segmaps = (int64_t **)((long)kd->cpu_data + cpup->segmapoffset);
                    342:        /* XXX XXX XXX _kvm_pa2off takes u_long and returns off_t..
                    343:           should take off_t also!! */
                    344:
                    345:        ptes = (int64_t *)(int)_kvm_pa2off(kd, (u_long)segmaps[sparc64_va_to_seg(va)]);
                    346:        pte = ptes[sparc64_va_to_pte(va)];
                    347:        if ((pte & SPARC64_TLB_V) != 0)
                    348:                return ((pte & SPARC64_TLB_PA_MASK) | (va & (kd->nbpg - 1)));
1.19      eeh       349: err:
1.24      sommerfe  350:        _kvm_err(kd, 0, "invalid address (%lx)", va);
1.19      eeh       351:        return (0);
                    352: }
                    353:
1.10      pk        354:
1.21      simonb    355: /*
1.27      wiz       356:  * Translate a physical address to a file-offset in the crash dump.
1.21      simonb    357:  */
1.10      pk        358: off_t
                    359: _kvm_pa2off(kd, pa)
                    360:        kvm_t   *kd;
                    361:        u_long  pa;
                    362: {
1.20      mrg       363:        sparc64_cpu_kcore_hdr_t *cpup = kd->cpu_data;
1.10      pk        364:        phys_ram_seg_t *mp;
                    365:        off_t off;
                    366:        int nmem;
                    367:
                    368:        /*
                    369:         * Layout of CPU segment:
                    370:         *      cpu_kcore_hdr_t;
                    371:         *      [alignment]
                    372:         *      phys_ram_seg_t[cpup->nmemseg];
                    373:         */
                    374:        mp = (phys_ram_seg_t *)((int)kd->cpu_data + cpup->memsegoffset);
                    375:        off = 0;
                    376:
                    377:        /* Translate (sparse) pfnum to (packed) dump offset */
                    378:        for (nmem = cpup->nmemseg; --nmem >= 0; mp++) {
                    379:                if (mp->start <= pa && pa < mp->start + mp->size)
                    380:                        break;
                    381:                off += mp->size;
                    382:        }
                    383:        if (nmem < 0) {
1.24      sommerfe  384:                _kvm_err(kd, 0, "invalid address (%lx)", pa);
1.10      pk        385:                return (-1);
                    386:        }
                    387:
                    388:        return (kd->dump_off + off + pa - mp->start);
1.12      gwr       389: }
                    390:
                    391: /*
                    392:  * Machine-dependent initialization for ALL open kvm descriptors,
                    393:  * not just those for a kernel crash dump.  Some architectures
                    394:  * have to deal with these NOT being constants!  (i.e. m68k)
                    395:  */
                    396: int
                    397: _kvm_mdopen(kd)
                    398:        kvm_t   *kd;
                    399: {
1.14      pk        400:        u_long max_uva;
                    401:        extern struct ps_strings *__ps_strings;
1.12      gwr       402:
1.14      pk        403:        max_uva = (u_long) (__ps_strings + 1);
                    404:        kd->usrstack = max_uva;
                    405:        kd->max_uva  = max_uva;
                    406:        kd->min_uva  = 0;
1.12      gwr       407:
                    408:        return (0);
1.4       deraadt   409: }

CVSweb <webmaster@jp.NetBSD.org>