Annotation of sys/arch/sparc64/sparc64/cpu.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: cpu.c,v 1.20 2007/05/02 18:46:07 kettenis Exp $ */
! 2: /* $NetBSD: cpu.c,v 1.13 2001/05/26 21:27:15 chs 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/trap.h>
! 65: #include <machine/pmap.h>
! 66:
! 67: #include <sparc64/sparc64/cache.h>
! 68:
! 69: /* This is declared here so that you must include a CPU for the cache code. */
! 70: struct cacheinfo cacheinfo = {
! 71: us_dcache_flush_page
! 72: };
! 73:
! 74: /* Linked list of all CPUs in system. */
! 75: struct cpu_info *cpus = NULL;
! 76:
! 77: /* The following are used externally (sysctl_hw). */
! 78: char machine[] = MACHINE; /* from <machine/param.h> */
! 79: char cpu_model[100];
! 80:
! 81: struct proc *fpproc;
! 82: int foundfpu;
! 83: int want_ast;
! 84: extern int want_resched;
! 85:
! 86: /* The CPU configuration driver. */
! 87: static void cpu_attach(struct device *, struct device *, void *);
! 88: int cpu_match(struct device *, void *, void *);
! 89:
! 90: struct cfattach cpu_ca = {
! 91: sizeof(struct device), cpu_match, cpu_attach
! 92: };
! 93:
! 94: extern struct cfdriver cpu_cd;
! 95:
! 96: static char *fsrtoname(int, int, int, char *, size_t);
! 97:
! 98: #define IU_IMPL(v) ((((u_int64_t)(v))&VER_IMPL) >> VER_IMPL_SHIFT)
! 99: #define IU_VERS(v) ((((u_int64_t)(v))&VER_MASK) >> VER_MASK_SHIFT)
! 100:
! 101: int
! 102: cpu_match(parent, vcf, aux)
! 103: struct device *parent;
! 104: void *vcf;
! 105: void *aux;
! 106: {
! 107: struct mainbus_attach_args *ma = aux;
! 108: struct cfdata *cf = (struct cfdata *)vcf;
! 109:
! 110: return (strcmp(cf->cf_driver->cd_name, ma->ma_name) == 0);
! 111: }
! 112:
! 113: /*
! 114: * Attach the CPU.
! 115: * Discover interesting goop about the virtual address cache
! 116: * (slightly funny place to do it, but this is where it is to be found).
! 117: */
! 118: static void
! 119: cpu_attach(parent, dev, aux)
! 120: struct device *parent;
! 121: struct device *dev;
! 122: void *aux;
! 123: {
! 124: int node;
! 125: long clk;
! 126: int impl, vers, fver;
! 127: char *cpuname;
! 128: char *fpuname;
! 129: struct mainbus_attach_args *ma = aux;
! 130: struct fpstate64 *fpstate;
! 131: struct fpstate64 fps[2];
! 132: char *sep;
! 133: char fpbuf[40];
! 134: register int i, l;
! 135: u_int64_t ver;
! 136: extern u_int64_t cpu_clockrate[];
! 137:
! 138: /* This needs to be 64-bit aligned */
! 139: fpstate = ALIGNFPSTATE(&fps[1]);
! 140: /*
! 141: * Get the FSR and clear any exceptions. If we do not unload
! 142: * the queue here and it is left over from a previous crash, we
! 143: * will panic in the first loadfpstate(), due to a sequence error,
! 144: * so we need to dump the whole state anyway.
! 145: *
! 146: * If there is no FPU, trap.c will advance over all the stores,
! 147: * so we initialize fs_fsr here.
! 148: */
! 149: fpstate->fs_fsr = 7 << FSR_VER_SHIFT; /* 7 is reserved for "none" */
! 150: savefpstate(fpstate);
! 151: fver = (fpstate->fs_fsr >> FSR_VER_SHIFT) & (FSR_VER >> FSR_VER_SHIFT);
! 152: ver = getver();
! 153: impl = IU_IMPL(ver);
! 154: vers = IU_VERS(ver);
! 155: if (fver != 7) {
! 156: foundfpu = 1;
! 157: fpuname = fsrtoname(impl, vers, fver, fpbuf, sizeof fpbuf);
! 158: } else
! 159: fpuname = "no";
! 160:
! 161: /* tell them what we have */
! 162: node = ma->ma_node;
! 163:
! 164: clk = getpropint(node, "clock-frequency", 0);
! 165: if (clk == 0) {
! 166: /*
! 167: * Try to find it in the OpenPROM root...
! 168: */
! 169: clk = getpropint(findroot(), "clock-frequency", 0);
! 170: }
! 171: if (clk) {
! 172: cpu_clockrate[0] = clk; /* Tell OS what frequency we run on */
! 173: cpu_clockrate[1] = clk/1000000;
! 174: }
! 175: cpuname = getpropstring(node, "name");
! 176: if (strcmp(cpuname, "cpu") == 0)
! 177: cpuname = getpropstring(node, "compatible");
! 178: snprintf(cpu_model, sizeof cpu_model,
! 179: "%s (rev %d.%d) @ %s MHz, %s FPU", cpuname,
! 180: vers >> 4, vers & 0xf, clockfreq(clk), fpuname);
! 181: printf(": %s\n", cpu_model);
! 182:
! 183: cacheinfo.c_physical = 1; /* Dunno... */
! 184: cacheinfo.c_split = 1;
! 185: l = getpropint(node, "icache-line-size", 0);
! 186: if (l == 0)
! 187: l = getpropint(node, "l1-icache-line-size", 0);
! 188: cacheinfo.ic_linesize = l;
! 189: for (i = 0; (1 << i) < l && l; i++)
! 190: /* void */;
! 191: if ((1 << i) != l && l)
! 192: panic("bad icache line size %d", l);
! 193: cacheinfo.ic_l2linesize = i;
! 194: cacheinfo.ic_totalsize = getpropint(node, "icache-size", 0);
! 195: if (cacheinfo.ic_totalsize == 0)
! 196: cacheinfo.ic_totalsize = getpropint(node, "l1-icache-size", 0);
! 197: if (cacheinfo.ic_totalsize == 0)
! 198: cacheinfo.ic_totalsize = l *
! 199: getpropint(node, "icache-nlines", 64) *
! 200: getpropint(node, "icache-associativity", 1);
! 201:
! 202: l = getpropint(node, "dcache-line-size", 0);
! 203: if (l == 0)
! 204: l = getpropint(node, "l1-dcache-line-size", 0);
! 205: cacheinfo.dc_linesize = l;
! 206: for (i = 0; (1 << i) < l && l; i++)
! 207: /* void */;
! 208: if ((1 << i) != l && l)
! 209: panic("bad dcache line size %d", l);
! 210: cacheinfo.dc_l2linesize = i;
! 211: cacheinfo.dc_totalsize = getpropint(node, "dcache-size", 0);
! 212: if (cacheinfo.dc_totalsize == 0)
! 213: cacheinfo.dc_totalsize = getpropint(node, "l1-dcache-size", 0);
! 214: if (cacheinfo.dc_totalsize == 0)
! 215: cacheinfo.dc_totalsize = l *
! 216: getpropint(node, "dcache-nlines", 128) *
! 217: getpropint(node, "dcache-associativity", 1);
! 218:
! 219: l = getpropint(node, "ecache-line-size", 0);
! 220: if (l == 0)
! 221: l = getpropint(node, "l2-cache-line-size", 0);
! 222: cacheinfo.ec_linesize = l;
! 223: for (i = 0; (1 << i) < l && l; i++)
! 224: /* void */;
! 225: if ((1 << i) != l && l)
! 226: panic("bad ecache line size %d", l);
! 227: cacheinfo.ec_l2linesize = i;
! 228: cacheinfo.ec_totalsize = getpropint(node, "ecache-size", 0);
! 229: if (cacheinfo.ec_totalsize == 0)
! 230: cacheinfo.ec_totalsize = getpropint(node, "l2-cache-size", 0);
! 231: if (cacheinfo.ec_totalsize == 0)
! 232: cacheinfo.ec_totalsize = l *
! 233: getpropint(node, "ecache-nlines", 32768) *
! 234: getpropint(node, "ecache-associativity", 1);
! 235:
! 236: /*
! 237: * XXX - The following will have to do until
! 238: * we have per-cpu cache handling.
! 239: */
! 240: cacheinfo.c_l2linesize =
! 241: min(cacheinfo.ic_l2linesize,
! 242: cacheinfo.dc_l2linesize);
! 243: cacheinfo.c_linesize =
! 244: min(cacheinfo.ic_linesize,
! 245: cacheinfo.dc_linesize);
! 246: cacheinfo.c_totalsize =
! 247: cacheinfo.ic_totalsize +
! 248: cacheinfo.dc_totalsize;
! 249:
! 250: if (cacheinfo.c_totalsize == 0)
! 251: return;
! 252:
! 253: sep = " ";
! 254: printf("%s: physical", dev->dv_xname);
! 255: if (cacheinfo.ic_totalsize > 0) {
! 256: printf("%s%ldK instruction (%ld b/l)", sep,
! 257: (long)cacheinfo.ic_totalsize/1024,
! 258: (long)cacheinfo.ic_linesize);
! 259: sep = ", ";
! 260: }
! 261: if (cacheinfo.dc_totalsize > 0) {
! 262: printf("%s%ldK data (%ld b/l)", sep,
! 263: (long)cacheinfo.dc_totalsize/1024,
! 264: (long)cacheinfo.dc_linesize);
! 265: sep = ", ";
! 266: }
! 267: if (cacheinfo.ec_totalsize > 0) {
! 268: printf("%s%ldK external (%ld b/l)", sep,
! 269: (long)cacheinfo.ec_totalsize/1024,
! 270: (long)cacheinfo.ec_linesize);
! 271: }
! 272: printf("\n");
! 273: cache_enable();
! 274:
! 275: if (impl >= IMPL_CHEETAH) {
! 276: extern vaddr_t ktext, dlflush_start;
! 277: extern paddr_t ktextp;
! 278: vaddr_t *pva;
! 279: paddr_t pa;
! 280: u_int32_t inst;
! 281:
! 282: for (pva = &dlflush_start; *pva; pva++) {
! 283: inst = *(u_int32_t *)(*pva);
! 284: inst &= ~(ASI_DCACHE_TAG << 5);
! 285: inst |= (ASI_DCACHE_INVALIDATE << 5);
! 286: pa = (paddr_t) (ktextp - ktext + *pva);
! 287: stwa(pa, ASI_PHYS_CACHED, inst);
! 288: flush((void *)KERNBASE);
! 289: }
! 290:
! 291: cacheinfo.c_dcache_flush_page = us3_dcache_flush_page;
! 292: }
! 293: }
! 294:
! 295: /*
! 296: * The following tables convert <IU impl, IU version, FPU version> triples
! 297: * into names for the CPU and FPU chip. In most cases we do not need to
! 298: * inspect the FPU version to name the IU chip, but there is one exception
! 299: * (for Tsunami), and this makes the tables the same.
! 300: *
! 301: * The table contents (and much of the structure here) are from Guy Harris.
! 302: *
! 303: */
! 304: struct info {
! 305: u_char valid;
! 306: u_char iu_impl;
! 307: u_char iu_vers;
! 308: u_char fpu_vers;
! 309: char *name;
! 310: };
! 311:
! 312: #define ANY 0xff /* match any FPU version (or, later, IU version) */
! 313:
! 314:
! 315: /* NB: table order matters here; specific numbers must appear before ANY. */
! 316: static struct info fpu_types[] = {
! 317: /*
! 318: * Vendor 0, IU Fujitsu0.
! 319: */
! 320: { 1, 0x0, ANY, 0, "MB86910 or WTL1164/5" },
! 321: { 1, 0x0, ANY, 1, "MB86911 or WTL1164/5" },
! 322: { 1, 0x0, ANY, 2, "L64802 or ACT8847" },
! 323: { 1, 0x0, ANY, 3, "WTL3170/2" },
! 324: { 1, 0x0, 4, 4, "on-chip" }, /* Swift */
! 325: { 1, 0x0, ANY, 4, "L64804" },
! 326:
! 327: /*
! 328: * Vendor 1, IU ROSS0/1 or Pinnacle.
! 329: */
! 330: { 1, 0x1, 0xf, 0, "on-chip" }, /* Pinnacle */
! 331: { 1, 0x1, ANY, 0, "L64812 or ACT8847" },
! 332: { 1, 0x1, ANY, 1, "L64814" },
! 333: { 1, 0x1, ANY, 2, "TMS390C602A" },
! 334: { 1, 0x1, ANY, 3, "RT602 or WTL3171" },
! 335:
! 336: /*
! 337: * Vendor 2, IU BIT0.
! 338: */
! 339: { 1, 0x2, ANY, 0, "B5010 or B5110/20 or B5210" },
! 340:
! 341: /*
! 342: * Vendor 4, Texas Instruments.
! 343: */
! 344: { 1, 0x4, ANY, 0, "on-chip" }, /* Viking */
! 345: { 1, 0x4, ANY, 4, "on-chip" }, /* Tsunami */
! 346:
! 347: /*
! 348: * Vendor 5, IU Matsushita0.
! 349: */
! 350: { 1, 0x5, ANY, 0, "on-chip" },
! 351:
! 352: /*
! 353: * Vendor 9, Weitek.
! 354: */
! 355: { 1, 0x9, ANY, 3, "on-chip" },
! 356:
! 357: { 0 }
! 358: };
! 359:
! 360: static char *
! 361: fsrtoname(impl, vers, fver, buf, buflen)
! 362: register int impl, vers, fver;
! 363: char *buf;
! 364: size_t buflen;
! 365: {
! 366: register struct info *p;
! 367:
! 368: for (p = fpu_types; p->valid; p++)
! 369: if (p->iu_impl == impl &&
! 370: (p->iu_vers == vers || p->iu_vers == ANY) &&
! 371: (p->fpu_vers == fver))
! 372: return (p->name);
! 373: snprintf(buf, buflen, "version %x", fver);
! 374: return (buf);
! 375: }
! 376:
! 377: struct cfdriver cpu_cd = {
! 378: NULL, "cpu", DV_DULL
! 379: };
CVSweb