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

Annotation of src/lib/libkvm/kvm_powerpc.c, Revision 1.7

1.7     ! briggs      1: /*     $NetBSD: kvm_powerpc.c,v 1.6 2001/08/05 03:33:15 matt Exp $     */
1.1       thorpej     2:
1.7     ! briggs      3: /*
        !             4:  * Copyright (c) 2005 Wasabi Systems, Inc.
        !             5:  * All rights reserved.
        !             6:  *
        !             7:  * Written by Allen Briggs for Wasabi Systems, Inc.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. All advertising materials mentioning features or use of this software
        !            18:  *    must display the following acknowledgement:
        !            19:  *      This product includes software developed for the NetBSD Project by
        !            20:  *      Wasabi Systems, Inc.
        !            21:  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
        !            22:  *    or promote products derived from this software without specific prior
        !            23:  *    written permission.
        !            24:  *
        !            25:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
        !            26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            27:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            28:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
        !            29:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            30:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            31:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            32:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            33:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            34:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            35:  * POSSIBILITY OF SUCH DAMAGE.
        !            36:  */
1.1       thorpej    37: /*-
                     38:  * Copyright (C) 1996 Wolfgang Solfrank.
                     39:  * Copyright (C) 1996 TooLs GmbH.
                     40:  * All rights reserved.
                     41:  *
                     42:  * Redistribution and use in source and binary forms, with or without
                     43:  * modification, are permitted provided that the following conditions
                     44:  * are met:
                     45:  * 1. Redistributions of source code must retain the above copyright
                     46:  *    notice, this list of conditions and the following disclaimer.
                     47:  * 2. Redistributions in binary form must reproduce the above copyright
                     48:  *    notice, this list of conditions and the following disclaimer in the
                     49:  *    documentation and/or other materials provided with the distribution.
                     50:  * 3. All advertising materials mentioning features or use of this software
                     51:  *    must display the following acknowledgement:
                     52:  *     This product includes software developed by TooLs GmbH.
                     53:  * 4. The name of TooLs GmbH may not be used to endorse or promote products
                     54:  *    derived from this software without specific prior written permission.
                     55:  *
                     56:  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
                     57:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     58:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     59:  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
                     60:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     61:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     62:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     63:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     64:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     65:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     66:  */
                     67:
                     68: /*
                     69:  * PowerPC machine dependent routines for kvm.
                     70:  */
                     71:
                     72: #include <sys/param.h>
1.6       matt       73: #include <sys/exec.h>
1.3       thorpej    74:
1.5       mrg        75: #include <uvm/uvm_extern.h>
1.1       thorpej    76:
                     77: #include <db.h>
                     78: #include <limits.h>
                     79: #include <kvm.h>
1.4       mycroft    80: #include <stdlib.h>
1.7     ! briggs     81: #include <unistd.h>
1.1       thorpej    82:
                     83: #include "kvm_private.h"
                     84:
1.7     ! briggs     85: #include <sys/kcore.h>
        !            86: #include <machine/kcore.h>
        !            87:
        !            88: #include <powerpc/spr.h>
        !            89: #include <powerpc/oea/bat.h>
        !            90: #include <powerpc/oea/pte.h>
        !            91:
        !            92: static int     _kvm_match_601bat(kvm_t *kd, u_long va, u_long *pa, int *off);
        !            93: static int     _kvm_match_bat(kvm_t *kd, u_long va, u_long *pa, int *off);
        !            94: static int     _kvm_match_sr(kvm_t *kd, u_long va, u_long *pa, int *off);
        !            95: static struct pte *_kvm_scan_pteg(struct pteg *pteg, uint32_t vsid,
        !            96:                                  uint32_t api, int secondary);
        !            97:
1.1       thorpej    98: void
                     99: _kvm_freevtop(kd)
                    100:        kvm_t *kd;
                    101: {
                    102:        if (kd->vmst != 0)
                    103:                free(kd->vmst);
                    104: }
                    105:
1.7     ! briggs    106: /*ARGSUSED*/
1.1       thorpej   107: int
                    108: _kvm_initvtop(kd)
                    109:        kvm_t *kd;
                    110: {
1.7     ! briggs    111:
        !           112:        return 0;
        !           113: }
        !           114:
        !           115: #define BAT601_SIZE(b)  ((((b) << 17) | ~BAT601_BLPI) + 1)
        !           116:
        !           117: static int
        !           118: _kvm_match_601bat(kd, va, pa, off)
        !           119:        kvm_t *kd;
        !           120:        u_long va;
        !           121:        u_long *pa;
        !           122:        int *off;
        !           123: {
        !           124:        cpu_kcore_hdr_t *cpu_kh;
        !           125:        u_long          pgoff;
        !           126:        size_t          size;
        !           127:        int             i, nbat;
        !           128:
        !           129:        cpu_kh = kd->cpu_data;
        !           130:        nbat = 4;
        !           131:        for (i=0 ; i<nbat ; i++) {
        !           132:                if (!BAT601_VALID_P(cpu_kh->dbatu[i]))
        !           133:                        continue;
        !           134:                if (BAT601_VA_MATCH_P(cpu_kh->dbatu[i], cpu_kh->dbatl[i], va)) {
        !           135:                        size = BAT601_SIZE(cpu_kh->dbatu[i] & BAT601_BSM);
        !           136:                        pgoff = va & (size-1);
        !           137:                        *pa = (cpu_kh->dbatl[i] & BAT601_PBN) + pgoff;
        !           138:                        *off = size - pgoff;
        !           139:                        return 1;
        !           140:                }
        !           141:        }
1.1       thorpej   142:        return 0;
                    143: }
                    144:
1.7     ! briggs    145: #undef BAT601_SIZE
        !           146:
        !           147: #define BAT_SIZE(b)     ((((b) << 15) | ~BAT_EPI) + 1)
        !           148:
        !           149: static int
        !           150: _kvm_match_bat(kd, va, pa, off)
        !           151:        kvm_t *kd;
        !           152:        u_long va;
        !           153:        u_long *pa;
        !           154:        int *off;
        !           155: {
        !           156:        cpu_kcore_hdr_t *cpu_kh;
        !           157:        u_long          pgoff;
        !           158:        size_t          size;
        !           159:        int             i, nbat;
        !           160:
        !           161:        cpu_kh = kd->cpu_data;
        !           162:        /*
        !           163:         * Assume that we're looking for data and check only the dbats.
        !           164:         */
        !           165:        nbat = 8;
        !           166:        for (i=0 ; i<nbat ; i++) {
        !           167:                if (   ((cpu_kh->dbatu[i] & BAT_Vs) != 0)
        !           168:                    && (BAT_VA_MATCH_P(cpu_kh->dbatu[i], va))) {
        !           169:                        size = BAT_SIZE(cpu_kh->dbatu[i] & BAT_BL);
        !           170:                        pgoff = va & (size-1);
        !           171:                        *pa = (cpu_kh->dbatl[i] & BAT_RPN) + pgoff;
        !           172:                        *off = size - pgoff;
        !           173:                        return 1;
        !           174:                }
        !           175:        }
        !           176:        return 0;
        !           177: }
        !           178:
        !           179: #undef BAT_SIZE
        !           180:
        !           181: #define SR_VSID_HASH_MASK      0x0007ffff
        !           182:
        !           183: static struct pte *
        !           184: _kvm_scan_pteg(pteg, vsid, api, secondary)
        !           185:        struct pteg *pteg;
        !           186:        uint32_t vsid;
        !           187:        uint32_t api;
        !           188:        int secondary;
        !           189: {
        !           190:        struct pte      *pte;
        !           191:        u_long          ptehi;
        !           192:        int             i;
        !           193:
        !           194:        for (i=0 ; i<8 ; i++) {
        !           195:                pte = &pteg->pt[i];
        !           196:                ptehi = (u_long) pte->pte_hi;
        !           197:                if ((ptehi & PTE_VALID) == 0)
        !           198:                        continue;
        !           199:                if ((ptehi & PTE_HID) != secondary)
        !           200:                        continue;
        !           201:                if (((ptehi & PTE_VSID) >> PTE_VSID_SHFT) != vsid)
        !           202:                        continue;
        !           203:                if (((ptehi & PTE_API) >> PTE_API_SHFT) != api)
        !           204:                        continue;
        !           205:                return pte;
        !           206:        }
        !           207:        return NULL;
        !           208: }
        !           209:
        !           210: #define HASH_MASK      0x0007ffff
        !           211:
        !           212: static int
        !           213: _kvm_match_sr(kd, va, pa, off)
        !           214:        kvm_t *kd;
        !           215:        u_long va;
        !           216:        u_long *pa;
        !           217:        int *off;
        !           218: {
        !           219:        cpu_kcore_hdr_t *cpu_kh;
        !           220:        struct pteg     pteg;
        !           221:        struct pte      *pte;
        !           222:        uint32_t        sr, pgoff, vsid, pgidx, api, hash;
        !           223:        uint32_t        htaborg, htabmask, mhash;
        !           224:        u_long          pteg_vaddr;
        !           225:
        !           226:        cpu_kh = kd->cpu_data;
        !           227:
        !           228:        sr = cpu_kh->sr[(va >> 28) & 0xf];
        !           229:        if ((sr & SR_TYPE) != 0) {
        !           230:                /* Direct-store segment (shouldn't be) */
        !           231:                return 0;
        !           232:        }
        !           233:
        !           234:        pgoff = va & ADDR_POFF;
        !           235:        vsid = sr & SR_VSID;
        !           236:        pgidx = (va & ADDR_PIDX) >> ADDR_PIDX_SHFT;
        !           237:        api = pgidx >> 10;
        !           238:        hash = (vsid & HASH_MASK) ^ pgidx;
        !           239:
        !           240:        htaborg = cpu_kh->sdr1 & 0xffff0000;
        !           241:        htabmask = cpu_kh->sdr1 & 0x1ff;
        !           242:
        !           243:        mhash = (hash >> 10) & htabmask;
        !           244:
        !           245:        pteg_vaddr = ( htaborg & 0xfe000000) | ((hash & 0x3ff) << 6)
        !           246:                   | ((htaborg & 0x01ff0000) | (mhash << 16));
        !           247:
        !           248:        if (pread(kd->pmfd, (void *) &pteg, sizeof(pteg),
        !           249:                  _kvm_pa2off(kd, pteg_vaddr)) != sizeof(pteg)) {
        !           250:                _kvm_syserr(kd, 0, "could not read primary PTEG");
        !           251:                return 0;
        !           252:        }
        !           253:
        !           254:        if ((pte = _kvm_scan_pteg(&pteg, vsid, api, 0)) != NULL) {
        !           255:                *pa = (pte->pte_lo & PTE_RPGN) | pgoff;
        !           256:                *off = NBPG - pgoff;
        !           257:                return 1;
        !           258:        }
        !           259:
        !           260:        hash = (~hash) & HASH_MASK;
        !           261:        mhash = (hash >> 10) & htabmask;
        !           262:
        !           263:        pteg_vaddr = ( htaborg & 0xfe000000) | ((hash & 0x3ff) << 6)
        !           264:                   | ((htaborg & 0x01ff0000) | (mhash << 16));
        !           265:
        !           266:        if (pread(kd->pmfd, (void *) &pteg, sizeof(pteg),
        !           267:                  _kvm_pa2off(kd, pteg_vaddr)) != sizeof(pteg)) {
        !           268:                _kvm_syserr(kd, 0, "could not read secondary PTEG");
        !           269:                return 0;
        !           270:        }
        !           271:
        !           272:        if ((pte = _kvm_scan_pteg(&pteg, vsid, api, 0)) != NULL) {
        !           273:                *pa = (pte->pte_lo & PTE_RPGN) | pgoff;
        !           274:                *off = NBPG - pgoff;
        !           275:                return 1;
        !           276:        }
        !           277:
        !           278:        return 0;
        !           279: }
        !           280:
        !           281: /*
        !           282:  * Translate a KVA to a PA
        !           283:  */
1.1       thorpej   284: int
                    285: _kvm_kvatop(kd, va, pa)
                    286:        kvm_t *kd;
                    287:        u_long va;
                    288:        u_long *pa;
                    289: {
1.7     ! briggs    290:        cpu_kcore_hdr_t *cpu_kh;
        !           291:        int             offs;
        !           292:        uint32_t        pvr;
        !           293:
        !           294:        if (ISALIVE(kd)) {
        !           295:                _kvm_err(kd, 0, "vatop called in live kernel!");
        !           296:                return 0;
        !           297:        }
        !           298:
        !           299:        cpu_kh = kd->cpu_data;
        !           300:
        !           301:        pvr = (cpu_kh->pvr >> 16);
        !           302:        if (MPC745X_P(pvr))
        !           303:                pvr = MPC7450;
        !           304:
        !           305:        switch (pvr) {
        !           306:        case MPC601:
        !           307:                /* Check for a BAT hit first */
        !           308:                if (_kvm_match_601bat(kd, va, pa, &offs)) {
        !           309:                        return offs;
        !           310:                }
        !           311:
        !           312:                /* No BAT hit; check page tables */
        !           313:                if (_kvm_match_sr(kd, va, pa, &offs)) {
        !           314:                        return offs;
        !           315:                }
        !           316:                break;
        !           317:
        !           318:        case MPC603:
        !           319:        case MPC603e:
        !           320:        case MPC603ev:
        !           321:        case MPC604:
        !           322:        case MPC604ev:
        !           323:        case MPC750:
        !           324:        case IBM750FX:
        !           325:        case MPC7400:
        !           326:        case MPC7450:
        !           327:        case MPC7410:
        !           328:        case MPC8240:
        !           329:        case MPC8245:
        !           330:                /* Check for a BAT hit first */
        !           331:                if (_kvm_match_bat(kd, va, pa, &offs)) {
        !           332:                        return offs;
        !           333:                }
        !           334:
        !           335:                /* No BAT hit; check page tables */
        !           336:                if (_kvm_match_sr(kd, va, pa, &offs)) {
        !           337:                        return offs;
        !           338:                }
        !           339:                break;
        !           340:
        !           341:        default:
        !           342:                _kvm_err(kd, 0, "Unsupported CPU type (pvr 0x%08lx)!",
        !           343:                    (unsigned long) cpu_kh->pvr);
        !           344:                break;
        !           345:        }
        !           346:
        !           347:        /* No hit -- no translation */
        !           348:        *pa = (u_long)~0UL;
1.1       thorpej   349:        return 0;
                    350: }
                    351:
                    352: off_t
                    353: _kvm_pa2off(kd, pa)
                    354:        kvm_t *kd;
                    355:        u_long pa;
                    356: {
1.7     ! briggs    357:        cpu_kcore_hdr_t *cpu_kh;
        !           358:        phys_ram_seg_t  *ram;
        !           359:        off_t           off;
        !           360:        void            *e;
        !           361:
        !           362:        cpu_kh = kd->cpu_data;
        !           363:        e = (char *) kd->cpu_data + kd->cpu_dsize;
        !           364:         ram = (void *)((char *)(void *)cpu_kh + ALIGN(sizeof *cpu_kh));
        !           365:        off = kd->dump_off;
        !           366:        do {
        !           367:                if (pa >= ram->start && (pa - ram->start) < ram->size) {
        !           368:                        return off + (pa - ram->start);
        !           369:                }
        !           370:                ram++;
        !           371:                off += ram->size;
        !           372:        } while ((void *) ram < e && ram->size);
        !           373:
        !           374:        _kvm_err(kd, 0, "pa2off failed for pa 0x%08lx\n", pa);
        !           375:        return (off_t) -1;
1.2       gwr       376: }
                    377:
                    378: /*
                    379:  * Machine-dependent initialization for ALL open kvm descriptors,
                    380:  * not just those for a kernel crash dump.  Some architectures
                    381:  * have to deal with these NOT being constants!  (i.e. m68k)
                    382:  */
                    383: int
                    384: _kvm_mdopen(kd)
                    385:        kvm_t   *kd;
                    386: {
1.6       matt      387:        uintptr_t max_uva;
                    388:        extern struct ps_strings *__ps_strings;
1.2       gwr       389:
1.6       matt      390: #if 0   /* XXX - These vary across powerpc machines... */
1.2       gwr       391:        kd->usrstack = USRSTACK;
                    392:        kd->min_uva = VM_MIN_ADDRESS;
                    393:        kd->max_uva = VM_MAXUSER_ADDRESS;
1.6       matt      394: #endif
                    395:        /* This is somewhat hack-ish, but it works. */
                    396:        max_uva = (uintptr_t) (__ps_strings + 1);
                    397:        kd->usrstack = max_uva;
                    398:        kd->max_uva  = max_uva;
                    399:        kd->min_uva  = 0;
1.2       gwr       400:
                    401:        return (0);
1.1       thorpej   402: }

CVSweb <webmaster@jp.NetBSD.org>