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

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