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