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