[BACK]Return to cpu.c CVS log [TXT][DIR] Up to [local] / sys / arch / sparc / sparc

Annotation of sys/arch/sparc/sparc/cpu.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: cpu.c,v 1.43 2007/05/10 18:06:01 art Exp $    */
        !             2: /*     $NetBSD: cpu.c,v 1.56 1997/09/15 20:52:36 pk Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1996
        !             6:  *     The President and Fellows of Harvard College. All rights reserved.
        !             7:  * Copyright (c) 1992, 1993
        !             8:  *     The Regents of the University of California.  All rights reserved.
        !             9:  *
        !            10:  * This software was developed by the Computer Systems Engineering group
        !            11:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
        !            12:  * contributed to Berkeley.
        !            13:  *
        !            14:  * All advertising materials mentioning features or use of this software
        !            15:  * must display the following acknowledgement:
        !            16:  *     This product includes software developed by Harvard University.
        !            17:  *     This product includes software developed by the University of
        !            18:  *     California, Lawrence Berkeley Laboratory.
        !            19:  *
        !            20:  * Redistribution and use in source and binary forms, with or without
        !            21:  * modification, are permitted provided that the following conditions
        !            22:  * are met:
        !            23:  *
        !            24:  * 1. Redistributions of source code must retain the above copyright
        !            25:  *    notice, this list of conditions and the following disclaimer.
        !            26:  * 2. Redistributions in binary form must reproduce the above copyright
        !            27:  *    notice, this list of conditions and the following disclaimer in the
        !            28:  *    documentation and/or other materials provided with the distribution.
        !            29:  * 3. All advertising materials mentioning features or use of this software
        !            30:  *    must display the following acknowledgement:
        !            31:  *     This product includes software developed by Aaron Brown and
        !            32:  *     Harvard University.
        !            33:  *     This product includes software developed by the University of
        !            34:  *     California, Berkeley and its contributors.
        !            35:  * 4. Neither the name of the University nor the names of its contributors
        !            36:  *    may be used to endorse or promote products derived from this software
        !            37:  *    without specific prior written permission.
        !            38:  *
        !            39:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            40:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            41:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            42:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            43:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            44:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            45:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            46:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            47:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            48:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            49:  * SUCH DAMAGE.
        !            50:  *
        !            51:  *     @(#)cpu.c       8.5 (Berkeley) 11/23/93
        !            52:  *
        !            53:  */
        !            54:
        !            55: #include <sys/param.h>
        !            56: #include <sys/systm.h>
        !            57: #include <sys/device.h>
        !            58:
        !            59: #include <uvm/uvm_extern.h>
        !            60:
        !            61: #include <machine/autoconf.h>
        !            62: #include <machine/cpu.h>
        !            63: #include <machine/reg.h>
        !            64: #include <machine/ctlreg.h>
        !            65: #include <machine/trap.h>
        !            66: #include <machine/pmap.h>
        !            67:
        !            68: #include <machine/oldmon.h>
        !            69: #include <machine/idprom.h>
        !            70:
        !            71: #include <sparc/sparc/cache.h>
        !            72: #include <sparc/sparc/asm.h>
        !            73: #include <sparc/sparc/cpuvar.h>
        !            74: #include <sparc/sparc/memreg.h>
        !            75:
        !            76: #ifdef solbourne
        !            77: #include <machine/idt.h>
        !            78: #include <machine/kap.h>
        !            79: #include <machine/prom.h>
        !            80: #endif
        !            81:
        !            82: /* The following are used externally (sysctl_hw). */
        !            83: char   machine[] = MACHINE;            /* from <machine/param.h> */
        !            84: char   *cpu_class = "sun4";
        !            85: char   cpu_model[130];
        !            86: char   cpu_hotfix[40];
        !            87: extern char mainbus_model[];           /* from autoconf.c */
        !            88:
        !            89: int    foundfpu;                       /* from machine/cpu.h */
        !            90:
        !            91: /* The CPU configuration driver. */
        !            92: void cpu_attach(struct device *, struct device *, void *);
        !            93: int  cpu_match(struct device *, void *, void *);
        !            94:
        !            95: struct cfattach cpu_ca = {
        !            96:        sizeof(struct cpu_softc), cpu_match, cpu_attach
        !            97: };
        !            98:
        !            99: struct cfdriver cpu_cd = {
        !           100:        NULL, "cpu", DV_CPU
        !           101: };
        !           102:
        !           103: char *fsrtoname(int, int, int, char *, size_t);
        !           104: void cache_print(struct cpu_softc *);
        !           105: void cpu_spinup(struct cpu_softc *);
        !           106: void fpu_init(struct cpu_softc *);
        !           107: void replacemul(void);
        !           108:
        !           109: #define        IU_IMPL(psr)    ((u_int)(psr) >> 28)
        !           110: #define        IU_VERS(psr)    (((psr) >> 24) & 0xf)
        !           111:
        !           112: #define SRMMU_IMPL(mmusr)      ((u_int)(mmusr) >> 28)
        !           113: #define SRMMU_VERS(mmusr)      (((mmusr) >> 24) & 0xf)
        !           114:
        !           115:
        !           116: #ifdef notdef
        !           117: /*
        !           118:  * IU implementations are parceled out to vendors (with some slight
        !           119:  * glitches).  Printing these is cute but takes too much space.
        !           120:  */
        !           121: static char *iu_vendor[16] = {
        !           122:        "Fujitsu",      /* and also LSI Logic */
        !           123:        "ROSS",         /* ROSS (ex-Cypress) */
        !           124:        "BIT",
        !           125:        "LSIL",         /* LSI Logic finally got their own */
        !           126:        "TI",           /* Texas Instruments */
        !           127:        "Matsushita",
        !           128:        "Philips",
        !           129:        "Harvest",      /* Harvest VLSI Design Center */
        !           130:        "SPEC",         /* Systems and Processes Engineering Corporation */
        !           131:        "Weitek",
        !           132:        "vendor#10",
        !           133:        "vendor#11",
        !           134:        "vendor#12",
        !           135:        "vendor#13",
        !           136:        "vendor#14",
        !           137:        "vendor#15"
        !           138: };
        !           139: #endif
        !           140:
        !           141: /*
        !           142:  * 4/110 comment: the 4/110 chops off the top 4 bits of an OBIO address.
        !           143:  *     this confuses autoconf.  for example, if you try and map
        !           144:  *     0xfe000000 in obio space on a 4/110 it actually maps 0x0e000000.
        !           145:  *     this is easy to verify with the PROM.   this causes problems
        !           146:  *     with devices like "esp0 at obio0 addr 0xfa000000" because the
        !           147:  *     4/110 treats it as esp0 at obio0 addr 0x0a000000" which is the
        !           148:  *     address of the 4/110's "sw0" scsi chip.   the same thing happens
        !           149:  *     between zs1 and zs2.    since the sun4 line is "closed" and
        !           150:  *     we know all the "obio" devices that will ever be on it we just
        !           151:  *     put in some special case "if"'s in the match routines of esp,
        !           152:  *     dma, and zs.
        !           153:  */
        !           154:
        !           155: int
        !           156: cpu_match(parent, vcf, aux)
        !           157:        struct device *parent;
        !           158:        void *vcf, *aux;
        !           159: {
        !           160:        register struct cfdata *cf = vcf;
        !           161:        register struct confargs *ca = aux;
        !           162:
        !           163:        return (strcmp(cf->cf_driver->cd_name, ca->ca_ra.ra_name) == 0);
        !           164: }
        !           165:
        !           166: /*
        !           167:  * Attach the CPU.
        !           168:  * Discover interesting goop about the virtual address cache
        !           169:  * (slightly funny place to do it, but this is where it is to be found).
        !           170:  */
        !           171: void
        !           172: cpu_attach(parent, self, aux)
        !           173:        struct device *parent;
        !           174:        struct device *self;
        !           175:        void *aux;
        !           176: {
        !           177:        struct cpu_softc *sc = (struct cpu_softc *)self;
        !           178:        register int node;
        !           179:        register char *fpuname;
        !           180:        struct confargs *ca = aux;
        !           181:        char fpbuf[40];
        !           182:        char model[100];
        !           183:
        !           184:        sc->node = node = ca->ca_ra.ra_node;
        !           185:
        !           186:        /*
        !           187:         * First, find out if we're attaching the boot CPU.
        !           188:         */
        !           189:        if (node == 0)
        !           190:                sc->master = 1;
        !           191:        else {
        !           192:                sc->mid = getpropint(node, "mid", 0);
        !           193:                if (sc->mid == 0 || sc->mid == getmid() + 8 /*XXX*/)
        !           194:                        sc->master = 1;
        !           195:        }
        !           196:
        !           197:        if (sc->master) {
        !           198:                /*
        !           199:                 * Gross, but some things in cpuinfo may already have
        !           200:                 * been setup by early routines like pmap_bootstrap().
        !           201:                 */
        !           202:                bcopy(&sc->dv, &cpuinfo, sizeof(sc->dv));
        !           203:                bcopy(&cpuinfo, sc, sizeof(cpuinfo));
        !           204:        }
        !           205:
        !           206: #if defined(SUN4C) || defined(SUN4M)
        !           207:        switch (cputyp) {
        !           208: #if defined(SUN4C)
        !           209:        case CPU_SUN4C:
        !           210:                cpu_class = "sun4c";
        !           211:                break;
        !           212: #endif /* defined(SUN4C) */
        !           213: #if defined(SUN4M)
        !           214:        case CPU_SUN4M:
        !           215:                cpu_class = "sun4m";
        !           216:                break;
        !           217: #endif /* defined(SUN4M) */
        !           218:        }
        !           219: #endif /* defined(SUN4C) || defined(SUN4M) */
        !           220:
        !           221:        getcpuinfo(sc, node);
        !           222:
        !           223:        fpuname = "no";
        !           224:        if (sc->master) {
        !           225:                if (sc->hotfix)
        !           226:                        sc->hotfix(sc);
        !           227:
        !           228:                fpu_init(sc);
        !           229:                if (foundfpu)
        !           230:                        fpuname = fsrtoname(sc->cpu_impl, sc->cpu_vers,
        !           231:                            sc->fpuvers, fpbuf, sizeof fpbuf);
        !           232:        }
        !           233:        /* XXX - multi-processor: take care of `cpu_model' and `foundfpu' */
        !           234:
        !           235:        snprintf(model, sizeof model, "%s @ %s MHz, %s FPU", sc->cpu_name,
        !           236:            clockfreq(sc->hz), fpuname);
        !           237:        printf(": %s", model);
        !           238:        snprintf(cpu_model, sizeof cpu_model, "%s, %s", mainbus_model, model);
        !           239:
        !           240:        if (cpu_hotfix[0])
        !           241:                printf("; %s", cpu_hotfix);
        !           242:        printf("\n");
        !           243:
        !           244:        if (sc->cacheinfo.c_totalsize != 0)
        !           245:                cache_print(sc);
        !           246:
        !           247:        sc->ci.ci_softc = sc;
        !           248:
        !           249:        if (sc->master) {
        !           250:                int s;
        !           251:
        !           252:                bcopy(sc, &cpuinfo, sizeof(cpuinfo));
        !           253:                /*
        !           254:                 * Enable the cache
        !           255:                 *
        !           256:                 * Disable all interrupts because we don't want anything
        !           257:                 * nasty to happen to the pagetables while the cache is
        !           258:                 * enabled and we haven't uncached them yet.
        !           259:                 */
        !           260:                s = splhigh();
        !           261:                sc->cache_enable();
        !           262:                pmap_cache_enable();
        !           263:                splx(s);
        !           264:                return;
        !           265:        }
        !           266:
        !           267:        /* Now start this CPU */
        !           268: }
        !           269:
        !           270: #if 0
        !           271: void
        !           272: cpu_(sc)
        !           273:        struct cpu_softc *sc;
        !           274: {
        !           275:        if (sc->hotfix)
        !           276:                sc->hotfix(sc);
        !           277:
        !           278:        /* Initialize FPU */
        !           279:        fpu_init(sc);
        !           280:
        !           281:        /* Enable the cache */
        !           282:        sc->cache_enable();
        !           283: }
        !           284: #endif
        !           285:
        !           286: void
        !           287: cpu_spinup(sc)
        !           288:        struct cpu_softc *sc;
        !           289: {
        !           290: #if 0
        !           291:        pmap_cpusetup();
        !           292: #endif
        !           293: }
        !           294:
        !           295: void
        !           296: fpu_init(sc)
        !           297:        struct cpu_softc *sc;
        !           298: {
        !           299:        struct fpstate fpstate;
        !           300:
        !           301:        /*
        !           302:         * Get the FSR and clear any exceptions.  If we do not unload
        !           303:         * the queue here and it is left over from a previous crash, we
        !           304:         * will panic in the first loadfpstate(), due to a sequence
        !           305:         * error, so we need to dump the whole state anyway.
        !           306:         *
        !           307:         * If there is no FPU, trap.c will advance over all the stores,
        !           308:         * so we initialize fs_fsr here.
        !           309:         */
        !           310:
        !           311:        /* 7 is reserved for "none" */
        !           312:        fpstate.fs_fsr = 7 << FSR_VER_SHIFT;
        !           313:        savefpstate(&fpstate);
        !           314:        sc->fpuvers =
        !           315:            (fpstate.fs_fsr >> FSR_VER_SHIFT) & (FSR_VER >> FSR_VER_SHIFT);
        !           316:
        !           317:        if (sc->fpuvers != 7)
        !           318:                foundfpu = 1;
        !           319: }
        !           320:
        !           321: void
        !           322: cache_print(sc)
        !           323:        struct cpu_softc *sc;
        !           324: {
        !           325:        struct cacheinfo *ci = &sc->cacheinfo;
        !           326:        char *sep = "";
        !           327:
        !           328:        printf("%s: ", sc->dv.dv_xname);
        !           329:
        !           330:        if (ci->c_split) {
        !           331:                printf("%s", (ci->c_physical ? "physical " : ""));
        !           332:                if (ci->ic_totalsize > 0) {
        !           333:                        printf("%s%dK instruction (%d b/l)", sep,
        !           334:                            ci->ic_totalsize/1024, ci->ic_linesize);
        !           335:                        sep = ", ";
        !           336:                }
        !           337:                if (ci->dc_totalsize > 0) {
        !           338:                        printf("%s%dK data (%d b/l)", sep,
        !           339:                            ci->dc_totalsize/1024, ci->dc_linesize);
        !           340:                        sep = ", ";
        !           341:                }
        !           342:        } else if (ci->c_physical) {
        !           343:                /* combined, physical */
        !           344:                printf("physical %dK combined cache (%d bytes/line)",
        !           345:                    ci->c_totalsize/1024, ci->c_linesize);
        !           346:                sep = ", ";
        !           347:        } else {
        !           348:                /* combined, virtual */
        !           349:                printf("%dK byte write-%s, %d bytes/line, %cw flush",
        !           350:                    ci->c_totalsize/1024,
        !           351:                    (ci->c_vactype == VAC_WRITETHROUGH) ? "through" : "back",
        !           352:                    ci->c_linesize, ci->c_hwflush ? 'h' : 's');
        !           353:                sep = ", ";
        !           354:        }
        !           355:
        !           356:        if (ci->ec_totalsize > 0) {
        !           357:                printf("%s%dK external (%d b/l)", sep,
        !           358:                    ci->ec_totalsize/1024, ci->ec_linesize);
        !           359:        }
        !           360:        if (sep)        /* printed at least one field.. */
        !           361:                printf(" ");
        !           362: }
        !           363:
        !           364:
        !           365: /*------------*/
        !           366:
        !           367:
        !           368: void cpumatch_unknown(struct cpu_softc *, struct module_info *, int);
        !           369: void cpumatch_sun4(struct cpu_softc *, struct module_info *, int);
        !           370: void cpumatch_sun4c(struct cpu_softc *, struct module_info *, int);
        !           371: void cpumatch_ms(struct cpu_softc *, struct module_info *, int);
        !           372: void cpumatch_viking(struct cpu_softc *, struct module_info *, int);
        !           373: void cpumatch_hypersparc(struct cpu_softc *, struct module_info *, int);
        !           374: void cpumatch_turbosparc(struct cpu_softc *, struct module_info *, int);
        !           375: void cpumatch_kap(struct cpu_softc *, struct module_info *, int);
        !           376:
        !           377: void getcacheinfo_sun4(struct cpu_softc *, int node);
        !           378: void getcacheinfo_sun4c(struct cpu_softc *, int node);
        !           379: void getcacheinfo_obp(struct cpu_softc *, int node);
        !           380: void getcacheinfo_kap(struct cpu_softc *, int node);
        !           381:
        !           382: void sun4_hotfix(struct cpu_softc *);
        !           383: void viking_hotfix(struct cpu_softc *);
        !           384: void turbosparc_hotfix(struct cpu_softc *);
        !           385: void swift_hotfix(struct cpu_softc *);
        !           386:
        !           387: void ms1_mmu_enable(void);
        !           388: void viking_mmu_enable(void);
        !           389: void swift_mmu_enable(void);
        !           390: void hypersparc_mmu_enable(void);
        !           391:
        !           392: void srmmu_get_syncflt(void);
        !           393: void ms1_get_syncflt(void);
        !           394: void viking_get_syncflt(void);
        !           395: void swift_get_syncflt(void);
        !           396: void turbosparc_get_syncflt(void);
        !           397: void hypersparc_get_syncflt(void);
        !           398: void cypress_get_syncflt(void);
        !           399:
        !           400: int srmmu_get_asyncflt(u_int *, u_int *);
        !           401: int hypersparc_get_asyncflt(u_int *, u_int *);
        !           402: int cypress_get_asyncflt(u_int *, u_int *);
        !           403: int no_asyncflt_regs(u_int *, u_int *);
        !           404:
        !           405: struct module_info module_unknown = {
        !           406:        CPUTYP_UNKNOWN,
        !           407:        VAC_UNKNOWN,
        !           408:        cpumatch_unknown
        !           409: };
        !           410:
        !           411:
        !           412: void
        !           413: cpumatch_unknown(sc, mp, node)
        !           414:        struct cpu_softc *sc;
        !           415:        struct module_info *mp;
        !           416:        int     node;
        !           417: {
        !           418:        panic("Unknown CPU type: "
        !           419:              "cpu: impl %d, vers %d; mmu: impl %d, vers %d",
        !           420:                sc->cpu_impl, sc->cpu_vers,
        !           421:                sc->mmu_impl, sc->mmu_vers);
        !           422: }
        !           423:
        !           424: #if defined(SUN4)
        !           425: struct module_info module_sun4 = {
        !           426:        CPUTYP_UNKNOWN,
        !           427:        VAC_WRITETHROUGH,
        !           428:        cpumatch_sun4,
        !           429:        getcacheinfo_sun4,
        !           430:        sun4_hotfix,
        !           431:        0,
        !           432:        sun4_cache_enable,
        !           433:        0,                      /* ncontext set in `match' function */
        !           434:        0,                      /* get_syncflt(); unused in sun4 */
        !           435:        0,                      /* get_asyncflt(); unused in sun4 */
        !           436:        sun4_cache_flush,
        !           437:        sun4_vcache_flush_page,
        !           438:        sun4_vcache_flush_segment,
        !           439:        sun4_vcache_flush_region,
        !           440:        sun4_vcache_flush_context,
        !           441:        noop_pcache_flush_line,
        !           442:        noop_pure_vcache_flush,
        !           443:        noop_cache_flush_all,
        !           444:        0
        !           445: };
        !           446:
        !           447: void
        !           448: getcacheinfo_sun4(sc, node)
        !           449:        struct cpu_softc *sc;
        !           450:        int     node;
        !           451: {
        !           452:        struct cacheinfo *ci = &sc->cacheinfo;
        !           453:
        !           454:        switch (sc->cpu_type) {
        !           455:        case CPUTYP_4_100:
        !           456:                ci->c_vactype = VAC_NONE;
        !           457:                ci->c_totalsize = 0;
        !           458:                ci->c_hwflush = 0;
        !           459:                ci->c_linesize = 0;
        !           460:                ci->c_l2linesize = 0;
        !           461:                ci->c_split = 0;
        !           462:                ci->c_nlines = 0;
        !           463:
        !           464:                /* Override cache flush functions */
        !           465:                sc->cache_flush = noop_cache_flush;
        !           466:                sc->vcache_flush_page = noop_vcache_flush_page;
        !           467:                sc->vcache_flush_segment = noop_vcache_flush_segment;
        !           468:                sc->vcache_flush_region = noop_vcache_flush_region;
        !           469:                sc->vcache_flush_context = noop_vcache_flush_context;
        !           470:                break;
        !           471:        case CPUTYP_4_200:
        !           472:                ci->c_vactype = VAC_WRITEBACK;
        !           473:                ci->c_totalsize = 128*1024;
        !           474:                ci->c_hwflush = 0;
        !           475:                ci->c_linesize = 16;
        !           476:                ci->c_l2linesize = 4;
        !           477:                ci->c_split = 0;
        !           478:                ci->c_nlines = ci->c_totalsize << ci->c_l2linesize;
        !           479:                break;
        !           480:        case CPUTYP_4_300:
        !           481:                ci->c_vactype = VAC_WRITEBACK;
        !           482:                ci->c_totalsize = 128*1024;
        !           483:                ci->c_hwflush = 0;
        !           484:                ci->c_linesize = 16;
        !           485:                ci->c_l2linesize = 4;
        !           486:                ci->c_split = 0;
        !           487:                ci->c_nlines = ci->c_totalsize << ci->c_l2linesize;
        !           488:                sc->flags |= CPUFLG_SUN4CACHEBUG;
        !           489:                break;
        !           490:        case CPUTYP_4_400:
        !           491:                ci->c_vactype = VAC_WRITEBACK;
        !           492:                ci->c_totalsize = 128 * 1024;
        !           493:                ci->c_hwflush = 0;
        !           494:                ci->c_linesize = 32;
        !           495:                ci->c_l2linesize = 5;
        !           496:                ci->c_split = 0;
        !           497:                ci->c_nlines = ci->c_totalsize << ci->c_l2linesize;
        !           498:                break;
        !           499:        }
        !           500: }
        !           501:
        !           502: struct idprom idprom;
        !           503: void   getidprom(struct idprom *, int size);
        !           504:
        !           505: void
        !           506: cpumatch_sun4(sc, mp, node)
        !           507:        struct cpu_softc *sc;
        !           508:        struct module_info *mp;
        !           509:        int     node;
        !           510: {
        !           511:
        !           512:        getidprom(&idprom, sizeof(idprom));
        !           513:        switch (idprom.id_machine) {
        !           514:        /* XXX: don't know about Sun4 types */
        !           515:        case ID_SUN4_100:
        !           516:                sc->cpu_type = CPUTYP_4_100;
        !           517:                sc->classlvl = 100;
        !           518:                sc->mmu_ncontext = 8;
        !           519:                sc->mmu_nsegment = 256;
        !           520: /*XXX*/                sc->hz = 14280000;
        !           521:                break;
        !           522:        case ID_SUN4_200:
        !           523:                sc->cpu_type = CPUTYP_4_200;
        !           524:                sc->classlvl = 200;
        !           525:                sc->mmu_nsegment = 512;
        !           526:                sc->mmu_ncontext = 16;
        !           527: /*XXX*/                sc->hz = 16670000;
        !           528:                break;
        !           529:        case ID_SUN4_300:
        !           530:                sc->cpu_type = CPUTYP_4_300;
        !           531:                sc->classlvl = 300;
        !           532:                sc->mmu_nsegment = 256;
        !           533:                sc->mmu_ncontext = 16;
        !           534: /*XXX*/                sc->hz = 25000000;
        !           535:                break;
        !           536:        case ID_SUN4_400:
        !           537:                sc->cpu_type = CPUTYP_4_400;
        !           538:                sc->classlvl = 400;
        !           539:                sc->mmu_nsegment = 1024;
        !           540:                sc->mmu_ncontext = 64;
        !           541:                sc->mmu_nregion = 256;
        !           542: /*XXX*/                sc->hz = 33000000;
        !           543:                sc->sun4_mmu3l = 1;
        !           544:                break;
        !           545:        }
        !           546:
        !           547: }
        !           548: #endif /* SUN4 */
        !           549:
        !           550: #if defined(SUN4C)
        !           551: struct module_info module_sun4c = {
        !           552:        CPUTYP_UNKNOWN,
        !           553:        VAC_WRITETHROUGH,
        !           554:        cpumatch_sun4c,
        !           555:        getcacheinfo_sun4c,
        !           556:        sun4_hotfix,
        !           557:        0,
        !           558:        sun4_cache_enable,
        !           559:        0,                      /* ncontext set in `match' function */
        !           560:        0,                      /* get_syncflt(); unused in sun4c */
        !           561:        0,                      /* get_asyncflt(); unused in sun4c */
        !           562:        sun4_cache_flush,
        !           563:        sun4_vcache_flush_page,
        !           564:        sun4_vcache_flush_segment,
        !           565:        sun4_vcache_flush_region,
        !           566:        sun4_vcache_flush_context,
        !           567:        noop_pcache_flush_line,
        !           568:        noop_pure_vcache_flush,
        !           569:        noop_cache_flush_all,
        !           570:        0
        !           571: };
        !           572:
        !           573: void
        !           574: cpumatch_sun4c(sc, mp, node)
        !           575:        struct cpu_softc *sc;
        !           576:        struct module_info *mp;
        !           577:        int     node;
        !           578: {
        !           579:        int     rnode;
        !           580:
        !           581:        rnode = findroot();
        !           582:        sc->mmu_npmeg = sc->mmu_nsegment =
        !           583:                getpropint(rnode, "mmu-npmg", 128);
        !           584:        sc->mmu_ncontext = getpropint(rnode, "mmu-nctx", 8);
        !           585:
        !           586:        /* Get clock frequency */
        !           587:        sc->hz = getpropint(rnode, "clock-frequency", 0);
        !           588: }
        !           589:
        !           590: void
        !           591: getcacheinfo_sun4c(sc, node)
        !           592:        struct cpu_softc *sc;
        !           593:        int node;
        !           594: {
        !           595:        struct cacheinfo *ci = &sc->cacheinfo;
        !           596:        int i, l;
        !           597:
        !           598:        if (node == 0)
        !           599:                /* Bootstrapping */
        !           600:                return;
        !           601:
        !           602:        /* Sun4c's have only virtually-addressed caches */
        !           603:        ci->c_physical = 0;
        !           604:        ci->c_totalsize = getpropint(node, "vac-size", 65536);
        !           605:        /*
        !           606:         * Note: vac-hwflush is spelled with an underscore
        !           607:         * on the 4/75s.
        !           608:         */
        !           609:        ci->c_hwflush =
        !           610:                getpropint(node, "vac_hwflush", 0) |
        !           611:                getpropint(node, "vac-hwflush", 0);
        !           612:
        !           613:        ci->c_linesize = l = getpropint(node, "vac-linesize", 16);
        !           614:        for (i = 0; (1 << i) < l; i++)
        !           615:                /* void */;
        !           616:        if ((1 << i) != l)
        !           617:                panic("bad cache line size %d", l);
        !           618:        ci->c_l2linesize = i;
        !           619:        ci->c_associativity = 1;
        !           620:        ci->c_nlines = ci->c_totalsize << i;
        !           621:
        !           622:        ci->c_vactype = VAC_WRITETHROUGH;
        !           623:
        !           624:        /*
        !           625:         * Machines with "buserr-type" 1 have a bug in the cache
        !           626:         * chip that affects traps.  (I wish I knew more about this
        !           627:         * mysterious buserr-type variable....)
        !           628:         */
        !           629:        if (getpropint(node, "buserr-type", 0) == 1)
        !           630:                sc->flags |= CPUFLG_SUN4CACHEBUG;
        !           631: }
        !           632: #endif /* SUN4C */
        !           633:
        !           634: #if defined(solbourne)
        !           635: struct module_info module_kap = {
        !           636:        CPUTYP_UNKNOWN,
        !           637:        VAC_WRITEBACK,
        !           638:        cpumatch_kap,
        !           639:        getcacheinfo_kap,
        !           640:        NULL,
        !           641:        0,                              /* mmu_enable */
        !           642:        kap_cache_enable,
        !           643:        0,                              /* ncontext is irrelevant here */
        !           644:        0,
        !           645:        0,
        !           646:        kap_cache_flush,
        !           647:        kap_vcache_flush_page,
        !           648:        noop_vcache_flush_segment,      /* unused */
        !           649:        noop_vcache_flush_region,       /* unused */
        !           650:        kap_vcache_flush_context,
        !           651:        noop_pcache_flush_line,
        !           652:        noop_pure_vcache_flush,
        !           653:        noop_cache_flush_all,
        !           654:        0
        !           655: };
        !           656:
        !           657: void
        !           658: cpumatch_kap(sc, mp, node)
        !           659:        struct cpu_softc *sc;
        !           660:        struct module_info *mp;
        !           661:        int     node;
        !           662: {
        !           663:        extern int timerblurb;
        !           664:
        !           665:        sc->mmu_npmeg = sc->mmu_ncontext = 0;   /* do not matter for idt */
        !           666:
        !           667:        /*
        !           668:         * Check for the clock speed in the board diagnostic register.
        !           669:         * While there, knowing that there are only two possible values,
        !           670:         * fill the delay constant.
        !           671:         */
        !           672:        if ((lda(GLU_DIAG, ASI_PHYS_IO) >> 24) & GD_36MHZ) {
        !           673:                sc->hz = 36000000;
        !           674:                timerblurb = 14;        /* about 14.40 */
        !           675:        } else {
        !           676:                sc->hz = 33000000;
        !           677:                timerblurb = 13;        /* about 13.20 */
        !           678:        }
        !           679:
        !           680:        if (node != 0) {
        !           681:                sysmodel = getpropint(node, "cpu", 0);
        !           682:                switch (sysmodel) {
        !           683:                case SYS_S4000:
        !           684:                        break;
        !           685:                case SYS_S4100:
        !           686:                        /* XXX do something about the L2 cache */
        !           687:                        break;
        !           688:                default:
        !           689:                        panic("cpumatch_kap: unrecognized sysmodel %x",
        !           690:                            sysmodel);
        !           691:                }
        !           692:        }
        !           693: }
        !           694:
        !           695: void
        !           696: getcacheinfo_kap(sc, node)
        !           697:        struct cpu_softc *sc;
        !           698:        int node;
        !           699: {
        !           700:        struct cacheinfo *ci = &sc->cacheinfo;
        !           701:
        !           702:        /*
        !           703:         * The KAP processor has 3KB icache and 2KB dcache.
        !           704:         * It is divided in 3 (icache) or 2 (dcache) banks
        !           705:         * of 256 lines, each line being 4 bytes.
        !           706:         * Both caches are virtually addressed.
        !           707:         */
        !           708:
        !           709:        ci->ic_linesize = 12;
        !           710:        ci->ic_l2linesize = 3;  /* XXX */
        !           711:        ci->ic_nlines = DCACHE_LINES;
        !           712:        ci->ic_associativity = 1;
        !           713:        ci->ic_totalsize =
        !           714:            ci->ic_nlines * ci->ic_linesize * ci->ic_associativity;
        !           715:
        !           716:        ci->dc_enabled = 1;
        !           717:        ci->dc_linesize = 8;
        !           718:        ci->dc_l2linesize = 3;
        !           719:        ci->dc_nlines = DCACHE_LINES;
        !           720:        ci->dc_associativity = 1;
        !           721:        ci->dc_totalsize =
        !           722:            ci->dc_nlines * ci->dc_linesize * ci->dc_associativity;
        !           723:
        !           724:        ci->c_totalsize = ci->ic_totalsize + ci->dc_totalsize;
        !           725:        /* ci->c_enabled */
        !           726:        ci->c_hwflush = 0;
        !           727:        ci->c_linesize = 8;     /* min */
        !           728:        ci->c_l2linesize = 3;   /* min */
        !           729:        ci->c_nlines = DCACHE_LINES;
        !           730:        ci->c_physical = 0;
        !           731:        ci->c_associativity = 1;
        !           732:        ci->c_split = 1;
        !           733:
        !           734:        /* no L2 cache (except on 4100 but we don't handle it yet) */
        !           735:
        !           736:        ci->c_vactype = VAC_WRITEBACK;
        !           737: }
        !           738: #endif
        !           739:
        !           740: void
        !           741: sun4_hotfix(sc)
        !           742:        struct cpu_softc *sc;
        !           743: {
        !           744:        if ((sc->flags & CPUFLG_SUN4CACHEBUG) != 0) {
        !           745:                kvm_uncache((caddr_t)trapbase, 1);
        !           746:                snprintf(cpu_hotfix, sizeof cpu_hotfix,
        !           747:                    "cache chip bug - trap page uncached");
        !           748:        }
        !           749:
        !           750: }
        !           751:
        !           752: #if defined(SUN4M)
        !           753: void
        !           754: getcacheinfo_obp(sc, node)
        !           755:        struct  cpu_softc *sc;
        !           756:        int     node;
        !           757: {
        !           758:        struct cacheinfo *ci = &sc->cacheinfo;
        !           759:        int i, l;
        !           760:
        !           761:        if (node == 0)
        !           762:                /* Bootstrapping */
        !           763:                return;
        !           764:
        !           765:        /*
        !           766:         * Determine the Sun4m cache organization.
        !           767:         */
        !           768:        ci->c_physical = node_has_property(node, "cache-physical?");
        !           769:
        !           770:        if (getpropint(node, "ncaches", 1) == 2)
        !           771:                ci->c_split = 1;
        !           772:        else
        !           773:                ci->c_split = 0;
        !           774:
        !           775:        /* hwflush is used only by sun4/4c code */
        !           776:        ci->c_hwflush = 0;
        !           777:
        !           778:        if (node_has_property(node, "icache-nlines") &&
        !           779:            node_has_property(node, "dcache-nlines") &&
        !           780:            ci->c_split) {
        !           781:                /* Harvard architecture: get I and D cache sizes */
        !           782:                ci->ic_nlines = getpropint(node, "icache-nlines", 0);
        !           783:                ci->ic_linesize = l =
        !           784:                        getpropint(node, "icache-line-size", 0);
        !           785:                for (i = 0; (1 << i) < l && l; i++)
        !           786:                        /* void */;
        !           787:                if ((1 << i) != l && l)
        !           788:                        panic("bad icache line size %d", l);
        !           789:                ci->ic_l2linesize = i;
        !           790:                ci->ic_associativity =
        !           791:                        getpropint(node, "icache-associativity", 1);
        !           792:                ci->ic_totalsize = l * ci->ic_nlines * ci->ic_associativity;
        !           793:
        !           794:                ci->dc_nlines = getpropint(node, "dcache-nlines", 0);
        !           795:                ci->dc_linesize = l =
        !           796:                        getpropint(node, "dcache-line-size",0);
        !           797:                for (i = 0; (1 << i) < l && l; i++)
        !           798:                        /* void */;
        !           799:                if ((1 << i) != l && l)
        !           800:                        panic("bad dcache line size %d", l);
        !           801:                ci->dc_l2linesize = i;
        !           802:                ci->dc_associativity =
        !           803:                        getpropint(node, "dcache-associativity", 1);
        !           804:                ci->dc_totalsize = l * ci->dc_nlines * ci->dc_associativity;
        !           805:
        !           806:                ci->c_l2linesize = min(ci->ic_l2linesize, ci->dc_l2linesize);
        !           807:                ci->c_linesize = min(ci->ic_linesize, ci->dc_linesize);
        !           808:                ci->c_totalsize = ci->ic_totalsize + ci->dc_totalsize;
        !           809:        } else {
        !           810:                /* unified I/D cache */
        !           811:                ci->c_nlines = getpropint(node, "cache-nlines", 128);
        !           812:                ci->c_linesize = l =
        !           813:                        getpropint(node, "cache-line-size", 0);
        !           814:                for (i = 0; (1 << i) < l && l; i++)
        !           815:                        /* void */;
        !           816:                if ((1 << i) != l && l)
        !           817:                        panic("bad cache line size %d", l);
        !           818:                ci->c_l2linesize = i;
        !           819:                ci->c_totalsize = l *
        !           820:                        ci->c_nlines *
        !           821:                        getpropint(node, "cache-associativity", 1);
        !           822:        }
        !           823:
        !           824:        if (node_has_property(node, "ecache-nlines")) {
        !           825:                /* we have a L2 "e"xternal cache */
        !           826:                ci->ec_nlines = getpropint(node, "ecache-nlines", 32768);
        !           827:                ci->ec_linesize = l = getpropint(node, "ecache-line-size", 0);
        !           828:                for (i = 0; (1 << i) < l && l; i++)
        !           829:                        /* void */;
        !           830:                if ((1 << i) != l && l)
        !           831:                        panic("bad ecache line size %d", l);
        !           832:                ci->ec_l2linesize = i;
        !           833:                ci->ec_associativity =
        !           834:                        getpropint(node, "ecache-associativity", 1);
        !           835:                ci->ec_totalsize = l * ci->ec_nlines * ci->ec_associativity;
        !           836:        }
        !           837:        if (ci->c_totalsize == 0)
        !           838:                printf("warning: couldn't identify cache\n");
        !           839: }
        !           840:
        !           841: /*
        !           842:  * We use the max. number of contexts on the micro and
        !           843:  * hyper SPARCs. The SuperSPARC would let us use up to 65536
        !           844:  * contexts (by powers of 2), but we keep it at 4096 since
        !           845:  * the table must be aligned to #context*4. With 4K contexts,
        !           846:  * we waste at most 16K of memory. Note that the context
        !           847:  * table is *always* page-aligned, so there can always be
        !           848:  * 1024 contexts without sacrificing memory space (given
        !           849:  * that the chip supports 1024 contexts).
        !           850:  *
        !           851:  * Currently known limits: MS1=64, MS2=256, HS=4096, SS=65536
        !           852:  *     some old SS's=4096
        !           853:  */
        !           854:
        !           855: /* TI Microsparc I */
        !           856: struct module_info module_ms1 = {
        !           857:        CPUTYP_MS1,
        !           858:        VAC_NONE,
        !           859:        cpumatch_ms,
        !           860:        getcacheinfo_obp,
        !           861:        0,
        !           862:        ms1_mmu_enable,
        !           863:        ms1_cache_enable,
        !           864:        64,
        !           865:        ms1_get_syncflt,
        !           866:        no_asyncflt_regs,
        !           867:        ms1_cache_flush,
        !           868:        noop_vcache_flush_page,
        !           869:        noop_vcache_flush_segment,
        !           870:        noop_vcache_flush_region,
        !           871:        noop_vcache_flush_context,
        !           872:        noop_pcache_flush_line,
        !           873:        noop_pure_vcache_flush,
        !           874:        ms1_cache_flush_all,
        !           875:        memerr4m
        !           876: };
        !           877:
        !           878: void
        !           879: ms1_mmu_enable()
        !           880: {
        !           881: }
        !           882:
        !           883: /* TI Microsparc II */
        !           884: struct module_info module_ms2 = {
        !           885:        CPUTYP_MS2,
        !           886:        VAC_WRITETHROUGH,
        !           887:        cpumatch_ms,
        !           888:        getcacheinfo_obp,
        !           889:        0, /* was swift_hotfix, */
        !           890:        0,
        !           891:        swift_cache_enable,
        !           892:        256,
        !           893:        srmmu_get_syncflt,
        !           894:        srmmu_get_asyncflt,
        !           895:        srmmu_cache_flush,
        !           896:        srmmu_vcache_flush_page,
        !           897:        srmmu_vcache_flush_segment,
        !           898:        srmmu_vcache_flush_region,
        !           899:        srmmu_vcache_flush_context,
        !           900:        noop_pcache_flush_line,
        !           901:        noop_pure_vcache_flush,
        !           902:        srmmu_cache_flush_all,
        !           903:        memerr4m
        !           904: };
        !           905:
        !           906:
        !           907: struct module_info module_swift = {
        !           908:        CPUTYP_MS2,
        !           909:        VAC_WRITETHROUGH,
        !           910:        cpumatch_ms,
        !           911:        getcacheinfo_obp,
        !           912:        swift_hotfix,
        !           913:        0,
        !           914:        swift_cache_enable,
        !           915:        256,
        !           916:        swift_get_syncflt,
        !           917:        no_asyncflt_regs,
        !           918:        srmmu_cache_flush,
        !           919:        srmmu_vcache_flush_page,
        !           920:        srmmu_vcache_flush_segment,
        !           921:        srmmu_vcache_flush_region,
        !           922:        srmmu_vcache_flush_context,
        !           923:        srmmu_pcache_flush_line,
        !           924:        noop_pure_vcache_flush,
        !           925:        srmmu_cache_flush_all,
        !           926:        memerr4m
        !           927: };
        !           928:
        !           929: void
        !           930: cpumatch_ms(sc, mp, node)
        !           931:        struct cpu_softc *sc;
        !           932:        struct module_info *mp;
        !           933:        int     node;
        !           934: {
        !           935:        replacemul();
        !           936: }
        !           937:
        !           938: void
        !           939: swift_hotfix(sc)
        !           940:        struct cpu_softc *sc;
        !           941: {
        !           942:        int pcr = lda(SRMMU_PCR, ASI_SRMMU);
        !           943:
        !           944:        /* Turn off branch prediction */
        !           945:        pcr &= ~SWIFT_PCR_BF;
        !           946:        sta(SRMMU_PCR, ASI_SRMMU, pcr);
        !           947: }
        !           948:
        !           949: void
        !           950: swift_mmu_enable()
        !           951: {
        !           952: }
        !           953:
        !           954: struct module_info module_viking = {
        !           955:        CPUTYP_UNKNOWN,         /* set in cpumatch() */
        !           956:        VAC_NONE,
        !           957:        cpumatch_viking,
        !           958:        getcacheinfo_obp,
        !           959:        viking_hotfix,
        !           960:        viking_mmu_enable,
        !           961:        viking_cache_enable,
        !           962:        4096,
        !           963:        viking_get_syncflt,
        !           964:        no_asyncflt_regs,
        !           965:        /* supersparcs use cached DVMA, no need to flush */
        !           966:        noop_cache_flush,
        !           967:        noop_vcache_flush_page,
        !           968:        noop_vcache_flush_segment,
        !           969:        noop_vcache_flush_region,
        !           970:        noop_vcache_flush_context,
        !           971:        viking_pcache_flush_line,
        !           972:        noop_pure_vcache_flush,
        !           973:        noop_cache_flush_all,
        !           974:        viking_memerr
        !           975: };
        !           976:
        !           977: void
        !           978: cpumatch_viking(sc, mp, node)
        !           979:        struct cpu_softc *sc;
        !           980:        struct module_info *mp;
        !           981:        int     node;
        !           982: {
        !           983:        replacemul();
        !           984:
        !           985:        if (node == 0)
        !           986:                viking_hotfix(sc);
        !           987: }
        !           988:
        !           989: void
        !           990: viking_hotfix(sc)
        !           991:        struct cpu_softc *sc;
        !           992: {
        !           993:        int pcr = lda(SRMMU_PCR, ASI_SRMMU);
        !           994:
        !           995:        /* Test if we're directly on the MBus */
        !           996:        if ((pcr & VIKING_PCR_MB) == 0) {
        !           997:                sc->mxcc = 1;
        !           998:                sc->flags |= CPUFLG_CACHE_MANDATORY;
        !           999:                /*
        !          1000:                 * Ok to cache PTEs; set the flag here, so we don't
        !          1001:                 * uncache in pmap_bootstrap().
        !          1002:                 */
        !          1003:                if ((pcr & VIKING_PCR_TC) == 0)
        !          1004:                        printf("[viking: PCR_TC is off]");
        !          1005:                else
        !          1006:                        sc->flags |= CPUFLG_CACHEPAGETABLES;
        !          1007:        } else {
        !          1008:                sc->cache_flush = viking_cache_flush;
        !          1009:                sc->pcache_flush_line = viking_pcache_flush_line;
        !          1010:        }
        !          1011:
        !          1012:        /* XXX! */
        !          1013:        if (sc->mxcc)
        !          1014:                sc->cpu_type = CPUTYP_SS1_MBUS_MXCC;
        !          1015:        else
        !          1016:                sc->cpu_type = CPUTYP_SS1_MBUS_NOMXCC;
        !          1017: }
        !          1018:
        !          1019: void
        !          1020: viking_mmu_enable()
        !          1021: {
        !          1022:        int pcr;
        !          1023:
        !          1024:        pcr = lda(SRMMU_PCR, ASI_SRMMU);
        !          1025:
        !          1026:        if (cpuinfo.mxcc) {
        !          1027:                if ((pcr & VIKING_PCR_TC) == 0) {
        !          1028:                        printf("[viking: turn on PCR_TC]");
        !          1029:                }
        !          1030:                pcr |= VIKING_PCR_TC;
        !          1031:        } else
        !          1032:                pcr &= ~VIKING_PCR_TC;
        !          1033:        sta(SRMMU_PCR, ASI_SRMMU, pcr);
        !          1034: }
        !          1035:
        !          1036:
        !          1037: /* ROSS Hypersparc */
        !          1038: struct module_info module_hypersparc = {
        !          1039:        CPUTYP_UNKNOWN,
        !          1040:        VAC_WRITEBACK,
        !          1041:        cpumatch_hypersparc,
        !          1042:        getcacheinfo_obp,
        !          1043:        0,
        !          1044:        hypersparc_mmu_enable,
        !          1045:        hypersparc_cache_enable,
        !          1046:        4096,
        !          1047:        hypersparc_get_syncflt,
        !          1048:        hypersparc_get_asyncflt,
        !          1049:        srmmu_cache_flush,
        !          1050:        srmmu_vcache_flush_page,
        !          1051:        srmmu_vcache_flush_segment,
        !          1052:        srmmu_vcache_flush_region,
        !          1053:        srmmu_vcache_flush_context,
        !          1054:        srmmu_pcache_flush_line,
        !          1055:        hypersparc_pure_vcache_flush,
        !          1056:        hypersparc_cache_flush_all,
        !          1057:        hypersparc_memerr
        !          1058: };
        !          1059:
        !          1060: void
        !          1061: cpumatch_hypersparc(sc, mp, node)
        !          1062:        struct cpu_softc *sc;
        !          1063:        struct module_info *mp;
        !          1064:        int     node;
        !          1065: {
        !          1066:        sc->cpu_type = CPUTYP_HS_MBUS;/*XXX*/
        !          1067:
        !          1068:        if (node == 0)
        !          1069:                sta(0, ASI_HICACHECLR, 0);
        !          1070:
        !          1071:        replacemul();
        !          1072: }
        !          1073:
        !          1074: void
        !          1075: hypersparc_mmu_enable()
        !          1076: {
        !          1077: #if 0
        !          1078:        int pcr;
        !          1079:
        !          1080:        pcr = lda(SRMMU_PCR, ASI_SRMMU);
        !          1081:        pcr |= HYPERSPARC_PCR_C;
        !          1082:        pcr &= ~HYPERSPARC_PCR_CE;
        !          1083:
        !          1084:        sta(SRMMU_PCR, ASI_SRMMU, pcr);
        !          1085: #endif
        !          1086: }
        !          1087:
        !          1088: /* Cypress 605 */
        !          1089: struct module_info module_cypress = {
        !          1090:        CPUTYP_CYPRESS,
        !          1091:        VAC_WRITEBACK,
        !          1092:        0,
        !          1093:        getcacheinfo_obp,
        !          1094:        0,
        !          1095:        0,
        !          1096:        cypress_cache_enable,
        !          1097:        4096,
        !          1098:        cypress_get_syncflt,
        !          1099:        cypress_get_asyncflt,
        !          1100:        srmmu_cache_flush,
        !          1101:        srmmu_vcache_flush_page,
        !          1102:        srmmu_vcache_flush_segment,
        !          1103:        srmmu_vcache_flush_region,
        !          1104:        srmmu_vcache_flush_context,
        !          1105:        srmmu_pcache_flush_line,
        !          1106:        noop_pure_vcache_flush,
        !          1107:        cypress_cache_flush_all,
        !          1108:        memerr4m
        !          1109: };
        !          1110:
        !          1111: /* Fujitsu Turbosparc */
        !          1112: struct module_info module_turbosparc = {       /* UNTESTED */
        !          1113:        CPUTYP_MS2,
        !          1114:        VAC_WRITEBACK,
        !          1115:        cpumatch_turbosparc,
        !          1116:        getcacheinfo_obp,
        !          1117:        turbosparc_hotfix,
        !          1118:        0,
        !          1119:        turbosparc_cache_enable,
        !          1120:        256,
        !          1121:        turbosparc_get_syncflt,
        !          1122:        no_asyncflt_regs,
        !          1123:        srmmu_cache_flush,
        !          1124:        srmmu_vcache_flush_page,
        !          1125:        srmmu_vcache_flush_segment,
        !          1126:        srmmu_vcache_flush_region,
        !          1127:        srmmu_vcache_flush_context,
        !          1128:        srmmu_pcache_flush_line,
        !          1129:        noop_pure_vcache_flush,
        !          1130:        srmmu_cache_flush_all,
        !          1131:        memerr4m
        !          1132: };
        !          1133:
        !          1134: void
        !          1135: cpumatch_turbosparc(sc, mp, node)
        !          1136:        struct cpu_softc *sc;
        !          1137:        struct module_info *mp;
        !          1138:        int     node;
        !          1139: {
        !          1140:        int i;
        !          1141:
        !          1142:        if (node == 0 || sc->master == 0)
        !          1143:                return;
        !          1144:
        !          1145:        i = getpsr();
        !          1146:        if (sc->cpu_vers == IU_VERS(i))
        !          1147:                return;
        !          1148:
        !          1149:        /*
        !          1150:         * A cloaked Turbosparc: clear any items in cpuinfo that
        !          1151:         * might have been set to uS2 versions during bootstrap.
        !          1152:         */
        !          1153:        sc->cpu_name = 0;
        !          1154:        sc->mmu_ncontext = 0;
        !          1155:        sc->cpu_type = 0;
        !          1156:        sc->cacheinfo.c_vactype = 0;
        !          1157:        sc->hotfix = 0;
        !          1158:        sc->mmu_enable = 0;
        !          1159:        sc->cache_enable = 0;
        !          1160:        sc->get_syncflt = 0;
        !          1161:        sc->cache_flush = 0;
        !          1162:        sc->vcache_flush_page = 0;
        !          1163:        sc->vcache_flush_segment = 0;
        !          1164:        sc->vcache_flush_region = 0;
        !          1165:        sc->vcache_flush_context = 0;
        !          1166:        sc->pcache_flush_line = 0;
        !          1167:
        !          1168:        replacemul();
        !          1169: }
        !          1170:
        !          1171: void
        !          1172: turbosparc_hotfix(sc)
        !          1173:        struct cpu_softc *sc;
        !          1174: {
        !          1175:        int pcf;
        !          1176:
        !          1177:        pcf = lda(SRMMU_PCFG, ASI_SRMMU);
        !          1178:        if (pcf & TURBOSPARC_PCFG_US2) {
        !          1179:                /* Turn off uS2 emulation bit */
        !          1180:                pcf &= ~TURBOSPARC_PCFG_US2;
        !          1181:                sta(SRMMU_PCFG, ASI_SRMMU, pcf);
        !          1182:        }
        !          1183: }
        !          1184: #endif /* SUN4M */
        !          1185:
        !          1186:
        !          1187: #define        ANY     -1      /* match any version */
        !          1188:
        !          1189: struct cpu_conf {
        !          1190:        int     arch;
        !          1191:        int     cpu_impl;
        !          1192:        int     cpu_vers;
        !          1193:        int     mmu_impl;
        !          1194:        int     mmu_vers;
        !          1195:        char    *name;
        !          1196:        struct  module_info *minfo;
        !          1197: } cpu_conf[] = {
        !          1198: #if defined(SUN4)
        !          1199:        { CPU_SUN4, 0, 0, ANY, ANY, "MB86900/1A or L64801", &module_sun4 },
        !          1200:        { CPU_SUN4, 1, 0, ANY, ANY, "L64811", &module_sun4 },
        !          1201:        { CPU_SUN4, 1, 1, ANY, ANY, "CY7C601", &module_sun4 },
        !          1202: #endif
        !          1203:
        !          1204: #if defined(SUN4C)
        !          1205:        { CPU_SUN4C, 0, 0, ANY, ANY, "MB86900/1A or L64801", &module_sun4c },
        !          1206:        { CPU_SUN4C, 1, 0, ANY, ANY, "L64811", &module_sun4c },
        !          1207:        { CPU_SUN4C, 1, 1, ANY, ANY, "CY7C601", &module_sun4c },
        !          1208:        { CPU_SUN4C, 9, 0, ANY, ANY, "W8601/8701 or MB86903", &module_sun4c },
        !          1209: #endif
        !          1210:
        !          1211: #if defined(SUN4M)
        !          1212:        { CPU_SUN4M, 0, 4, 0, 4, "MB86904", &module_swift },
        !          1213:        { CPU_SUN4M, 0, 5, 0, 5, "MB86907", &module_turbosparc },
        !          1214:        { CPU_SUN4M, 1, 1, 1, 0, "CY7C601/604", &module_cypress },
        !          1215:        { CPU_SUN4M, 1, 1, 1, 0xb, "CY7C601/605 (v.b)", &module_cypress },
        !          1216:        { CPU_SUN4M, 1, 1, 1, 0xc, "CY7C601/605 (v.c)", &module_cypress },
        !          1217:        { CPU_SUN4M, 1, 1, 1, 0xf, "CY7C601/605 (v.f)", &module_cypress },
        !          1218:        { CPU_SUN4M, 1, 3, 1, ANY, "CY7C611", &module_cypress },
        !          1219:        { CPU_SUN4M, 1, 0xe, 1, 7, "RT620/625", &module_hypersparc },
        !          1220:        { CPU_SUN4M, 1, 0xf, 1, 7, "RT620/625", &module_hypersparc },
        !          1221:        { CPU_SUN4M, 4, 0, 0, ANY, "TMS390Z50 v0 or TMS390Z55", &module_viking },
        !          1222:        { CPU_SUN4M, 4, 1, 0, ANY, "TMS390Z50 v1", &module_viking },
        !          1223:        { CPU_SUN4M, 4, 1, 4, ANY, "TMS390S10", &module_ms1 },
        !          1224:        { CPU_SUN4M, 4, 2, 0, ANY, "TI_MS2", &module_ms2 },
        !          1225:        { CPU_SUN4M, 4, 3, ANY, ANY, "TI_4_3", &module_viking },
        !          1226:        { CPU_SUN4M, 4, 4, ANY, ANY, "TI_4_4", &module_viking },
        !          1227: #endif
        !          1228:
        !          1229: #if defined(solbourne)
        !          1230:        { CPU_KAP, 5, 0, ANY, ANY, "KAP", &module_kap },
        !          1231: #endif
        !          1232:
        !          1233:        { ANY, ANY, ANY, ANY, ANY, "Unknown", &module_unknown }
        !          1234: };
        !          1235:
        !          1236: void
        !          1237: getcpuinfo(sc, node)
        !          1238:        struct cpu_softc *sc;
        !          1239:        int     node;
        !          1240: {
        !          1241:        struct cpu_conf *mp;
        !          1242:        int i;
        !          1243:        int cpu_impl, cpu_vers;
        !          1244:        int mmu_impl, mmu_vers;
        !          1245:
        !          1246:        /*
        !          1247:         * Set up main criteria for selection from the CPU configuration
        !          1248:         * table: the CPU implementation/version fields from the PSR
        !          1249:         * register, and -- on sun4m machines -- the MMU
        !          1250:         * implementation/version from the SCR register.
        !          1251:         */
        !          1252:        if (sc->master) {
        !          1253:                i = getpsr();
        !          1254:                if (node == 0 ||
        !          1255:                    (cpu_impl =
        !          1256:                     getpropint(node, "psr-implementation", -1)) == -1)
        !          1257:                        cpu_impl = IU_IMPL(i);
        !          1258:
        !          1259:                if (node == 0 ||
        !          1260:                    (cpu_vers = getpropint(node, "psr-version", -1)) == -1)
        !          1261:                        cpu_vers = IU_VERS(i);
        !          1262:
        !          1263:                if (CPU_ISSUN4M) {
        !          1264:                        i = lda(SRMMU_PCR, ASI_SRMMU);
        !          1265:                        if (node == 0 ||
        !          1266:                            (mmu_impl =
        !          1267:                             getpropint(node, "implementation", -1)) == -1)
        !          1268:                                mmu_impl = SRMMU_IMPL(i);
        !          1269:
        !          1270:                        if (node == 0 ||
        !          1271:                            (mmu_vers = getpropint(node, "version", -1)) == -1)
        !          1272:                                mmu_vers = SRMMU_VERS(i);
        !          1273:                } else {
        !          1274:                        mmu_impl = ANY;
        !          1275:                        mmu_vers = ANY;
        !          1276:                }
        !          1277:        } else {
        !          1278:                /*
        !          1279:                 * Get CPU version/implementation from ROM. If not
        !          1280:                 * available, assume same as boot CPU.
        !          1281:                 */
        !          1282:                cpu_impl = getpropint(node, "psr-implementation", -1);
        !          1283:                if (cpu_impl == -1)
        !          1284:                        cpu_impl = cpuinfo.cpu_impl;
        !          1285:                cpu_vers = getpropint(node, "psr-version", -1);
        !          1286:                if (cpu_vers == -1)
        !          1287:                        cpu_vers = cpuinfo.cpu_vers;
        !          1288:
        !          1289:                /* Get MMU version/implementation from ROM always */
        !          1290:                mmu_impl = getpropint(node, "implementation", -1);
        !          1291:                mmu_vers = getpropint(node, "version", -1);
        !          1292:        }
        !          1293:
        !          1294:        for (mp = cpu_conf; ; mp++) {
        !          1295:                if (mp->arch != cputyp && mp->arch != ANY)
        !          1296:                        continue;
        !          1297:
        !          1298: #define MATCH(x)       (mp->x == x || mp->x == ANY)
        !          1299:                if (!MATCH(cpu_impl) ||
        !          1300:                    !MATCH(cpu_vers) ||
        !          1301:                    !MATCH(mmu_impl) ||
        !          1302:                    !MATCH(mmu_vers))
        !          1303:                        continue;
        !          1304: #undef MATCH
        !          1305:
        !          1306:                /*
        !          1307:                 * Got CPU type.
        !          1308:                 */
        !          1309:                sc->cpu_impl = cpu_impl;
        !          1310:                sc->cpu_vers = cpu_vers;
        !          1311:                sc->mmu_impl = mmu_impl;
        !          1312:                sc->mmu_vers = mmu_vers;
        !          1313:
        !          1314:                if (mp->minfo->cpu_match) {
        !          1315:                        /* Additional fixups */
        !          1316:                        mp->minfo->cpu_match(sc, mp->minfo, node);
        !          1317:                }
        !          1318:                if (sc->cpu_name == 0)
        !          1319:                        sc->cpu_name = mp->name;
        !          1320:
        !          1321:                if (sc->mmu_ncontext == 0)
        !          1322:                        sc->mmu_ncontext = mp->minfo->ncontext;
        !          1323:
        !          1324:                if (sc->cpu_type == 0)
        !          1325:                        sc->cpu_type = mp->minfo->cpu_type;
        !          1326:
        !          1327:                if (sc->cacheinfo.c_vactype == VAC_UNKNOWN)
        !          1328:                        sc->cacheinfo.c_vactype = mp->minfo->vactype;
        !          1329:
        !          1330:                mp->minfo->getcacheinfo(sc, node);
        !          1331:
        !          1332:                if (node && sc->hz == 0 && !CPU_ISSUN4/*XXX*/) {
        !          1333:                        sc->hz = getpropint(node, "clock-frequency", 0);
        !          1334:                        if (sc->hz == 0) {
        !          1335:                                /*
        !          1336:                                 * Try to find it in the OpenPROM root...
        !          1337:                                 */
        !          1338:                                sc->hz = getpropint(findroot(),
        !          1339:                                                    "clock-frequency", 0);
        !          1340:                        }
        !          1341:                }
        !          1342:
        !          1343:                /*
        !          1344:                 * Copy CPU/MMU/Cache specific routines into cpu_softc.
        !          1345:                 */
        !          1346: #define MPCOPY(x)      if (sc->x == 0) sc->x = mp->minfo->x;
        !          1347:                MPCOPY(hotfix);
        !          1348:                MPCOPY(mmu_enable);
        !          1349:                MPCOPY(cache_enable);
        !          1350:                MPCOPY(get_syncflt);
        !          1351:                MPCOPY(get_asyncflt);
        !          1352:                MPCOPY(cache_flush);
        !          1353:                MPCOPY(vcache_flush_page);
        !          1354:                MPCOPY(vcache_flush_segment);
        !          1355:                MPCOPY(vcache_flush_region);
        !          1356:                MPCOPY(vcache_flush_context);
        !          1357:                MPCOPY(pcache_flush_line);
        !          1358:                MPCOPY(pure_vcache_flush);
        !          1359:                MPCOPY(cache_flush_all);
        !          1360:                MPCOPY(memerr);
        !          1361: #undef MPCOPY
        !          1362:                return;
        !          1363:        }
        !          1364:        panic("Out of CPUs");
        !          1365: }
        !          1366:
        !          1367: /*
        !          1368:  * The following tables convert <IU impl, IU version, FPU version> triples
        !          1369:  * into names for the CPU and FPU chip.  In most cases we do not need to
        !          1370:  * inspect the FPU version to name the IU chip, but there is one exception
        !          1371:  * (for Tsunami), and this makes the tables the same.
        !          1372:  *
        !          1373:  * The table contents (and much of the structure here) are from Guy Harris.
        !          1374:  *
        !          1375:  */
        !          1376: struct info {
        !          1377:        int     valid;
        !          1378:        int     iu_impl;
        !          1379:        int     iu_vers;
        !          1380:        int     fpu_vers;
        !          1381:        char    *name;
        !          1382: };
        !          1383:
        !          1384: /* NB: table order matters here; specific numbers must appear before ANY. */
        !          1385: static struct info fpu_types[] = {
        !          1386:        /*
        !          1387:         * Vendor 0, IU Fujitsu0.
        !          1388:         */
        !          1389:        { 1, 0x0, ANY, 0, "MB86910 or WTL1164/5" },
        !          1390:        { 1, 0x0, ANY, 1, "MB86911 or WTL1164/5" },
        !          1391:        { 1, 0x0, ANY, 2, "L64802 or ACT8847" },
        !          1392:        { 1, 0x0, ANY, 3, "WTL3170/2" },
        !          1393:        { 1, 0x0, 4,   4, "on-chip" },          /* Swift */
        !          1394:        { 1, 0x0, 5,   5, "on-chip" },          /* TurboSparc */
        !          1395:        { 1, 0x0, ANY, 4, "L64804" },
        !          1396:
        !          1397:        /*
        !          1398:         * Vendor 1, IU ROSS0/1 or Pinnacle.
        !          1399:         */
        !          1400:        { 1, 0x1, 0xf, 0, "on-chip" },          /* Pinnacle */
        !          1401:        { 1, 0x1, 0xe, 0, "on-chip" },          /* Hypersparc RT 625/626 */
        !          1402:        { 1, 0x1, ANY, 0, "L64812 or ACT8847" },
        !          1403:        { 1, 0x1, ANY, 1, "L64814" },
        !          1404:        { 1, 0x1, ANY, 2, "TMS390C602A" },
        !          1405:        { 1, 0x1, ANY, 3, "RT602 or WTL3171" },
        !          1406:
        !          1407:        /*
        !          1408:         * Vendor 2, IU BIT0.
        !          1409:         */
        !          1410:        { 1, 0x2, ANY, 0, "B5010 or B5110/20 or B5210" },
        !          1411:
        !          1412:        /*
        !          1413:         * Vendor 4, Texas Instruments.
        !          1414:         */
        !          1415:        { 1, 0x4, ANY, 0, "on-chip" },          /* Viking */
        !          1416:        { 1, 0x4, ANY, 4, "on-chip" },          /* Tsunami */
        !          1417:
        !          1418:        /*
        !          1419:         * Vendor 5, IU Matsushita0.
        !          1420:         */
        !          1421:        { 1, 0x5, ANY, 0, "on-chip" },
        !          1422:
        !          1423:        /*
        !          1424:         * Vendor 9, Weitek.
        !          1425:         */
        !          1426:        { 1, 0x9, ANY, 3, "on-chip" },
        !          1427:
        !          1428:        { 0 }
        !          1429: };
        !          1430:
        !          1431: char *
        !          1432: fsrtoname(impl, vers, fver, buf, buflen)
        !          1433:        register int impl, vers, fver;
        !          1434:        char *buf;
        !          1435:        size_t buflen;
        !          1436: {
        !          1437:        register struct info *p;
        !          1438:
        !          1439:        for (p = fpu_types; p->valid; p++)
        !          1440:                if (p->iu_impl == impl &&
        !          1441:                    (p->iu_vers == vers || p->iu_vers == ANY) &&
        !          1442:                    (p->fpu_vers == fver))
        !          1443:                        return (p->name);
        !          1444:        snprintf(buf, buflen, "version 0x%x", fver);
        !          1445:        return (buf);
        !          1446: }
        !          1447:
        !          1448: /*
        !          1449:  * Whack the slow sun4/sun4c {,u}{mul,div,rem} functions with
        !          1450:  * fast V8 ones
        !          1451:  * We are called once before pmap_bootstrap and once after. We only do stuff
        !          1452:  * in the "before" case. We happen to know that the kernel text is not
        !          1453:  * write-protected then.
        !          1454:  * XXX - investigate cache flushing, right now we can't do it because the
        !          1455:  *       flushes try to do va -> pa conversions.
        !          1456:  */
        !          1457: extern int _mulreplace, _mulreplace_end, _mul;
        !          1458: extern int _umulreplace, _umulreplace_end, _umul;
        !          1459: extern int _divreplace, _divreplace_end, _div;
        !          1460: extern int _udivreplace, _udivreplace_end, _udiv;
        !          1461: extern int _remreplace, _remreplace_end, _rem;
        !          1462: extern int _uremreplace, _uremreplace_end, _urem;
        !          1463: int    v8mul;  /* flag whether cpu has hardware mul, div, and rem */
        !          1464:
        !          1465: struct replace {
        !          1466:        void *from, *frome, *to;
        !          1467: } ireplace[] = {
        !          1468:        { &_mulreplace, &_mulreplace_end, &_mul },
        !          1469:        { &_umulreplace, &_umulreplace_end, &_umul },
        !          1470:        { &_divreplace, &_divreplace_end, &_div },
        !          1471:        { &_udivreplace, &_udivreplace_end, &_udiv },
        !          1472:        { &_remreplace, &_remreplace_end, &_rem },
        !          1473:        { &_uremreplace, &_uremreplace_end, &_urem },
        !          1474: };
        !          1475:
        !          1476: void
        !          1477: replacemul()
        !          1478: {
        !          1479:        static int replacedone = 0;
        !          1480:        int i, s;
        !          1481:
        !          1482:        if (replacedone)
        !          1483:                return;
        !          1484:        replacedone = 1;
        !          1485:
        !          1486:        s = splhigh();
        !          1487:        for (i = 0; i < sizeof(ireplace)/sizeof(ireplace[0]); i++)
        !          1488:                bcopy(ireplace[i].from, ireplace[i].to,
        !          1489:                    ireplace[i].frome - ireplace[i].from);
        !          1490:        splx(s);
        !          1491:        v8mul = 1;
        !          1492: }

CVSweb