[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

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