From owner-p4-projects@FreeBSD.ORG Sun Apr 27 21:22:41 2003 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 24C6737B404; Sun, 27 Apr 2003 21:22:40 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id B152B37B401 for ; Sun, 27 Apr 2003 21:22:39 -0700 (PDT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9D7CE43F93 for ; Sun, 27 Apr 2003 21:22:38 -0700 (PDT) (envelope-from jmallett@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.6/8.12.6) with ESMTP id h3S4Mc0U028117 for ; Sun, 27 Apr 2003 21:22:38 -0700 (PDT) (envelope-from jmallett@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.6/8.12.6/Submit) id h3S4Mc0p028110 for perforce@freebsd.org; Sun, 27 Apr 2003 21:22:38 -0700 (PDT) Date: Sun, 27 Apr 2003 21:22:38 -0700 (PDT) Message-Id: <200304280422.h3S4Mc0p028110@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jmallett@freebsd.org using -f From: Juli Mallett To: Perforce Change Reviews Subject: PERFORCE change 29929 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Apr 2003 04:22:41 -0000 http://perforce.freebsd.org/chv.cgi?CH=29929 Change 29929 by jmallett@jmallett_dalek on 2003/04/27 21:21:59 Add cpu_identify and related. Protected code to set up exception vectors with the preprocessor. Will use it once I bother to get the exception stuff in place. Affected files ... .. //depot/projects/mips/sys/mips/include/cpu.h#7 edit .. //depot/projects/mips/sys/mips/mips/machdep.c#15 edit Differences ... ==== //depot/projects/mips/sys/mips/include/cpu.h#7 (text+ko) ==== @@ -75,6 +75,20 @@ return (++now); } +/* + * Macros to find the CPU architecture we're on at run-time, + * or if possible, at compile-time. + */ + +#define CPU_ARCH_MIPSx 0 /* XXX unknown */ +#define CPU_ARCH_MIPS1 (1 << 0) +#define CPU_ARCH_MIPS2 (1 << 1) +#define CPU_ARCH_MIPS3 (1 << 2) +#define CPU_ARCH_MIPS4 (1 << 3) +#define CPU_ARCH_MIPS5 (1 << 4) +#define CPU_ARCH_MIPS32 (1 << 5) +#define CPU_ARCH_MIPS64 (1 << 6) + #ifndef LOCORE /* XXX simonb * Should the following be in a cpu_info type structure? ==== //depot/projects/mips/sys/mips/mips/machdep.c#15 (text+ko) ==== @@ -1,4 +1,121 @@ +/* + * Copyright 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Simon Burge for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright 2000, 2001 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and copied only + * in accordance with the following terms and conditions. Subject to these + * conditions, you may download, copy, install, use, modify and distribute + * modified or unmodified copies of this software in source and/or binary + * form. No title or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce and + * retain this copyright notice and list of conditions as they appear in + * the source file. + * + * 2) No right is granted to use any trade name, trademark, or logo of + * Broadcom Corporation. The "Broadcom Corporation" name may not be + * used to endorse or promote products derived from this software + * without the prior written permission of Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE + * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE + * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + /*- + * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center and by Chris Demetriou. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright 1996 The Board of Trustees of The Leland Stanford + * Junior University. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. Stanford University + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +/*- * Copyright (c) 2002 Juli Mallett * All rights reserved. * @@ -35,9 +152,15 @@ #include #include +#include +#include #include +#include #include +#include #include +#include +#include int cpu_arch; int mips_cpu_flags; @@ -60,6 +183,8 @@ { struct pcpu *pc; + mips_vector_init(); + cpu_identify(); proc_linkup(&proc0, &ksegrp0, &kse0, &thread0); thread0.td_kstack = kstack0; pc = &pcpu0; @@ -171,3 +296,568 @@ { return (-1); } + +#if 0 +mips_locore_jumpvec_t mips_locore_jumpvec; + +long *mips_locoresw[3]; +#endif + +struct pridtab { + int cpu_cid; + int cpu_pid; + int cpu_rev; /* -1 == wildcard */ + int cpu_copts; /* -1 == wildcard */ + int cpu_isa; /* -1 == probed (mips32/mips64) */ + int cpu_ntlb; /* -1 == unknown, 0 == probed */ + int cpu_flags; + char *cpu_name; +}; + +/* + * Assumptions: + * - All MIPS3+ have an r4k-style MMU. _Many_ assumptions throughout + * much of the mips code about this. Includes overloaded usage of + * MIPS3_PLUS. + * - All MIPS3+ use the same exception model (cp0 status, cause bits, + * etc). _Many_ assumptions throughout much of the mips code about + * this. Includes overloaded usage of MIPS3_PLUS. + * - All MIPS3+ have a count register. MIPS_HAS_CLOCK in + * will need to be revised if this is false. + */ +#define MIPS32_FLAGS CPU_MIPS_R4K_MMU | CPU_MIPS_CAUSE_IV | CPU_MIPS_USE_WAIT +#define MIPS64_FLAGS MIPS32_FLAGS /* same as MIPS32 flags (for now) */ + +static const struct pridtab *mycpu; + +static const struct pridtab cputab[] = { + { 0, MIPS_R2000, -1, -1, CPU_ARCH_MIPS1, 64, + CPU_MIPS_NO_LLSC, "MIPS R2000 CPU" }, + { 0, MIPS_R3000, MIPS_REV_R3000, -1, CPU_ARCH_MIPS1, 64, + CPU_MIPS_NO_LLSC, "MIPS R3000 CPU" }, + { 0, MIPS_R3000, MIPS_REV_R3000A, -1, CPU_ARCH_MIPS1, 64, + CPU_MIPS_NO_LLSC, "MIPS R3000A CPU" }, + { 0, MIPS_R6000, -1, -1, CPU_ARCH_MIPS2, 32, + MIPS_NOT_SUPP, "MIPS R6000 CPU" }, + + /* + * rev 0x00 and 0x30 are R4000, 0x40, 0x50 and 0x60 are R4400. + * should we allow ranges and use 0x00 - 0x3f for R4000 and + * 0x40 - 0xff for R4400? + */ + { 0, MIPS_R4000, MIPS_REV_R4000_A, -1, CPU_ARCH_MIPS3, 48, + CPU_MIPS_R4K_MMU | CPU_MIPS_DOUBLE_COUNT, + "MIPS R4000 CPU" }, + { 0, MIPS_R4000, MIPS_REV_R4000_B, -1, CPU_ARCH_MIPS3, 48, + CPU_MIPS_R4K_MMU | CPU_MIPS_DOUBLE_COUNT, + "MIPS R4000 CPU" }, + { 0, MIPS_R4000, MIPS_REV_R4400_A, -1, CPU_ARCH_MIPS3, 48, + CPU_MIPS_R4K_MMU | CPU_MIPS_DOUBLE_COUNT, + "MIPS R4400 CPU" }, + { 0, MIPS_R4000, MIPS_REV_R4400_B, -1, CPU_ARCH_MIPS3, 48, + CPU_MIPS_R4K_MMU | CPU_MIPS_DOUBLE_COUNT, + "MIPS R4400 CPU" }, + { 0, MIPS_R4000, MIPS_REV_R4400_C, -1, CPU_ARCH_MIPS3, 48, + CPU_MIPS_R4K_MMU | CPU_MIPS_DOUBLE_COUNT, + "MIPS R4400 CPU" }, + + { 0, MIPS_R3LSI, -1, -1, CPU_ARCH_MIPS1, -1, + MIPS_NOT_SUPP, "LSI Logic R3000 derivative" }, + { 0, MIPS_R6000A, -1, -1, CPU_ARCH_MIPS2, 32, + MIPS_NOT_SUPP, "MIPS R6000A CPU" }, + { 0, MIPS_R3IDT, -1, -1, CPU_ARCH_MIPS1, -1, + MIPS_NOT_SUPP, "IDT R3041 or RC36100 CPU" }, + { 0, MIPS_R4100, -1, -1, CPU_ARCH_MIPS3, 32, + CPU_MIPS_R4K_MMU | CPU_MIPS_NO_LLSC, "NEC VR4100 CPU" }, + { 0, MIPS_R4200, -1, -1, CPU_ARCH_MIPS3, -1, + MIPS_NOT_SUPP | CPU_MIPS_R4K_MMU, "NEC VR4200 CPU" }, + { 0, MIPS_R4300, -1, -1, CPU_ARCH_MIPS3, 32, + CPU_MIPS_R4K_MMU, "NEC VR4300 CPU" }, + { 0, MIPS_R4600, -1, -1, CPU_ARCH_MIPS3, 48, + CPU_MIPS_R4K_MMU | CPU_MIPS_DOUBLE_COUNT, + "QED R4600 Orion CPU" }, + { 0, MIPS_R4700, -1, -1, CPU_ARCH_MIPS3, 48, + CPU_MIPS_R4K_MMU, "QED R4700 Orion CPU" }, + + { 0, MIPS_R8000, -1, -1, CPU_ARCH_MIPS4, 384, + MIPS_NOT_SUPP | CPU_MIPS_R4K_MMU, "MIPS R8000 Blackbird/TFP CPU" }, + { 0, MIPS_R10000, -1, -1, CPU_ARCH_MIPS4, 64, + MIPS_NOT_SUPP | CPU_MIPS_R4K_MMU, "MIPS R10000 CPU" }, + { 0, MIPS_R12000, -1, -1, CPU_ARCH_MIPS4, 64, + MIPS_NOT_SUPP | CPU_MIPS_R4K_MMU, "MIPS R12000 CPU" }, + { 0, MIPS_R14000, -1, -1, CPU_ARCH_MIPS4, 64, + MIPS_NOT_SUPP | CPU_MIPS_R4K_MMU, "MIPS R14000 CPU" }, + + /* XXX + * If the Processor Revision ID of the 4650 isn't 0, the following + * entry needs to be adjusted. Can't use a wildcard match because + * the TX39 series processors share the same Processor ID value. + * Or maybe put TX39 CPUs first if the revid doesn't overlap with + * the 4650... + */ + { 0, MIPS_R4650, 0, -1, CPU_ARCH_MIPS3, -1, + MIPS_NOT_SUPP /* no MMU! */, "QED R4650 CPU" }, + { 0, MIPS_TX3900, MIPS_REV_TX3912, -1, CPU_ARCH_MIPS1, 32, + CPU_MIPS_NO_LLSC, "Toshiba TX3912 CPU" }, + { 0, MIPS_TX3900, MIPS_REV_TX3922, -1, CPU_ARCH_MIPS1, 64, + CPU_MIPS_NO_LLSC, "Toshiba TX3922 CPU" }, + { 0, MIPS_TX3900, MIPS_REV_TX3927, -1, CPU_ARCH_MIPS1, 64, + CPU_MIPS_NO_LLSC, "Toshiba TX3927 CPU" }, + { 0, MIPS_R5000, -1, -1, CPU_ARCH_MIPS4, 48, + CPU_MIPS_R4K_MMU | CPU_MIPS_DOUBLE_COUNT, + "MIPS R5000 CPU" }, + { 0, MIPS_RM5200, -1, -1, CPU_ARCH_MIPS4, 48, + CPU_MIPS_R4K_MMU | CPU_MIPS_CAUSE_IV | CPU_MIPS_DOUBLE_COUNT | + CPU_MIPS_USE_WAIT, "QED RM5200 CPU" }, + + /* XXX + * The rm7000 rev 2.0 can have 64 tlbs, and has 6 extra interrupts. See + * "Migrating to the RM7000 from other MIPS Microprocessors" + * for more details. + */ + { 0, MIPS_RM7000, -1, -1, CPU_ARCH_MIPS4, 48, + MIPS_NOT_SUPP | CPU_MIPS_CAUSE_IV | CPU_MIPS_DOUBLE_COUNT | + CPU_MIPS_USE_WAIT, "QED RM7000 CPU" }, + + /* + * IDT RC32300 core is a 32 bit MIPS2 processor with + * MIPS3/MIPS4 extensions. It has an R4000-style TLB, + * while all registers are 32 bits and any 64 bit + * instructions like ld/sd/dmfc0/dmtc0 are not allowed. + * + * note that the Config register has a non-standard base + * for IC and DC (2^9 instead of 2^12). + * + */ + { 0, MIPS_RC32300, -1, -1, CPU_ARCH_MIPS3, 16, + MIPS_NOT_SUPP | CPU_MIPS_R4K_MMU, "IDT RC32300 CPU" }, + { 0, MIPS_RC32364, -1, -1, CPU_ARCH_MIPS3, 16, + MIPS_NOT_SUPP | CPU_MIPS_R4K_MMU, "IDT RC32364 CPU" }, + { 0, MIPS_RC64470, -1, -1, CPU_ARCH_MIPSx, -1, + MIPS_NOT_SUPP | CPU_MIPS_R4K_MMU, "IDT RC64474/RC64475 CPU" }, + + { 0, MIPS_R5400, -1, -1, CPU_ARCH_MIPSx, -1, + MIPS_NOT_SUPP | CPU_MIPS_R4K_MMU, "NEC VR5400 CPU" }, + { 0, MIPS_R5900, -1, -1, CPU_ARCH_MIPS3, 48, + CPU_MIPS_NO_LLSC | CPU_MIPS_R4K_MMU, "Toshiba R5900 CPU" }, + + { 0, MIPS_TX4900, MIPS_REV_TX4927, -1, CPU_ARCH_MIPS3, 48, + CPU_MIPS_R4K_MMU | CPU_MIPS_DOUBLE_COUNT, + "Toshiba TX4927 CPU" }, + { 0, MIPS_TX4900, -1, -1, CPU_ARCH_MIPS3, 48, + CPU_MIPS_R4K_MMU | CPU_MIPS_DOUBLE_COUNT, + "Toshiba TX4900 CPU" }, + +#if 0 /* ID collisions : can we use a CU1 test or similar? */ + { 0, MIPS_R3SONY, -1, -1, CPU_ARCH_MIPS1, -1, + MIPS_NOT_SUPP, "SONY R3000 derivative" }, /* 0x21; crash R4700? */ + { 0, MIPS_R3NKK, -1, -1, CPU_ARCH_MIPS1, -1, + MIPS_NOT_SUPP, "NKK R3000 derivative" }, /* 0x23; crash R5000? */ +#endif + + { MIPS_PRID_CID_MTI, MIPS_4Kc, -1, -1, -1, 0, + MIPS32_FLAGS | CPU_MIPS_DOUBLE_COUNT, "4Kc" }, + { MIPS_PRID_CID_MTI, MIPS_4KEc, -1, -1, -1, 0, + MIPS32_FLAGS | CPU_MIPS_DOUBLE_COUNT, "4KEc" }, + { MIPS_PRID_CID_MTI, MIPS_4KSc, -1, -1, -1, 0, + MIPS32_FLAGS | CPU_MIPS_DOUBLE_COUNT, "4KSc" }, + { MIPS_PRID_CID_MTI, MIPS_5Kc, -1, -1, -1, 0, + MIPS64_FLAGS | CPU_MIPS_DOUBLE_COUNT, "5Kc" }, + { MIPS_PRID_CID_MTI, MIPS_20Kc, -1, -1, -1, 0, + MIPS64_FLAGS, "20Kc" }, + + { MIPS_PRID_CID_ALCHEMY, MIPS_AU_REV1, -1, MIPS_AU1000, -1, 0, + MIPS32_FLAGS | CPU_MIPS_NO_WAIT | CPU_MIPS_I_D_CACHE_COHERENT, + "Au1000 (Rev 1 core)" }, + { MIPS_PRID_CID_ALCHEMY, MIPS_AU_REV2, -1, MIPS_AU1000, -1, 0, + MIPS32_FLAGS | CPU_MIPS_NO_WAIT | CPU_MIPS_I_D_CACHE_COHERENT, + "Au1000 (Rev 2 core)" }, + + { MIPS_PRID_CID_ALCHEMY, MIPS_AU_REV1, -1, MIPS_AU1500, -1, 0, + MIPS32_FLAGS | CPU_MIPS_NO_WAIT | CPU_MIPS_I_D_CACHE_COHERENT, + "Au1500 (Rev 1 core)" }, + { MIPS_PRID_CID_ALCHEMY, MIPS_AU_REV2, -1, MIPS_AU1500, -1, 0, + MIPS32_FLAGS | CPU_MIPS_NO_WAIT | CPU_MIPS_I_D_CACHE_COHERENT, + "Au1500 (Rev 2 core)" }, + + { MIPS_PRID_CID_ALCHEMY, MIPS_AU_REV1, -1, MIPS_AU1100, -1, 0, + MIPS32_FLAGS | CPU_MIPS_NO_WAIT | CPU_MIPS_I_D_CACHE_COHERENT, + "Au1100 (Rev 1 core)" }, + { MIPS_PRID_CID_ALCHEMY, MIPS_AU_REV2, -1, MIPS_AU1100, -1, 0, + MIPS32_FLAGS | CPU_MIPS_NO_WAIT | CPU_MIPS_I_D_CACHE_COHERENT, + "Au1100 (Rev 2 core)" }, + + /* The SB1 CPUs use a CCA of 5 - "Cacheable Coherent Shareable" */ + { MIPS_PRID_CID_SIBYTE, MIPS_SB1, -1, -1, -1, 0, + MIPS64_FLAGS | CPU_MIPS_D_CACHE_COHERENT | + CPU_MIPS_HAVE_SPECIAL_CCA | (5 << CPU_MIPS_CACHED_CCA_SHIFT), + "SB1" }, + + { 0, 0, 0, 0, 0, 0, + 0, NULL } +}; + +static const struct pridtab fputab[] = { + { 0, MIPS_SOFT, -1, 0, 0, 0, 0, "software emulated floating point" }, + { 0, MIPS_R2360, -1, 0, 0, 0, 0, "MIPS R2360 Floating Point Board" }, + { 0, MIPS_R2010, -1, 0, 0, 0, 0, "MIPS R2010 FPC" }, + { 0, MIPS_R3010, -1, 0, 0, 0, 0, "MIPS R3010 FPC" }, + { 0, MIPS_R6010, -1, 0, 0, 0, 0, "MIPS R6010 FPC" }, + { 0, MIPS_R4010, -1, 0, 0, 0, 0, "MIPS R4010 FPC" }, +}; + +/* + * Company ID's are not sparse (yet), this array is indexed directly + * by pridtab->cpu_cid. + */ +static const char *cidnames[] = { + "Prehistoric", + "MIPS", /* or "MIPS Technologies, Inc. */ + "Broadcom", /* or "Broadcom Corp." */ + "Alchemy", /* or "Alchemy Semiconductor" */ + "SiByte", /* or "Broadcom Corp. (SiByte)" */ + "SandCraft", +}; +#define ncidnames (sizeof(cidnames) / sizeof(cidnames[0])) + +#ifdef notyet +/* + * MIPS64 locore function vector + */ +const mips_locore_jumpvec_t mips64_locore_vec = +{ + mips64_SetPID, + mips64_TBIAP, + mips64_TBIS, + mips64_TLBUpdate, + mips64_wbflush, +}; + +static void +mips64_vector_init(void) +{ + /* r4000 exception handler address and end */ + extern char mips64_exception[], mips64_exceptionEnd[]; + + /* TLB miss handler address and end */ + extern char mips64_TLBMiss[], mips64_TLBMissEnd[]; + extern char mips64_XTLBMiss[], mips64_XTLBMissEnd[]; + + /* Cache error handler */ + extern char mips64_cache[], mips64_cacheEnd[]; + + /* MIPS32/MIPS64 interrupt exception handler */ + extern char mips64_intr[], mips64_intrEnd[]; + + /* + * Copy down exception vector code. + */ + + if (mips64_TLBMissEnd - mips64_TLBMiss > 0x80) + panic("startup: UTLB vector code too large"); + memcpy((void *)MIPS_UTLB_MISS_EXC_VEC, mips64_TLBMiss, + mips64_TLBMissEnd - mips64_TLBMiss); + + if (mips64_XTLBMissEnd - mips64_XTLBMiss > 0x80) + panic("startup: XTLB vector code too large"); + memcpy((void *)MIPS3_XTLB_MISS_EXC_VEC, mips64_XTLBMiss, + mips64_XTLBMissEnd - mips64_XTLBMiss); + + if (mips64_cacheEnd - mips64_cache > 0x80) + panic("startup: Cache error vector code too large"); + memcpy((void *)MIPS3_CACHE_ERR_EXC_VEC, mips64_cache, + mips64_cacheEnd - mips64_cache); + + if (mips64_exceptionEnd - mips64_exception > 0x80) + panic("startup: General exception vector code too large"); + memcpy((void *)MIPS3_GEN_EXC_VEC, mips64_exception, + mips64_exceptionEnd - mips64_exception); + + if (mips64_intrEnd - mips64_intr > 0x80) + panic("startup: interrupt exception vector code too large"); +#if 0 /* XXX - why doesn't mipsNN_intr() work? */ + memcpy((void *)MIPS3_INTR_EXC_VEC, mips64_intr, + mips64_intrEnd - mips64_intr); +#else + memcpy((void *)MIPS3_INTR_EXC_VEC, mips64_exception, + mips64_exceptionEnd - mips64_exception); +#endif + + /* + * Copy locore-function vector. + */ + memcpy(&mips_locore_jumpvec, &mips64_locore_vec, + sizeof(mips_locore_jumpvec_t)); + + mips_icache_sync_all(); + mips_dcache_wbinv_all(); + + /* Clear BEV in SR so we start handling our own exceptions */ + mips_cp0_status_write(mips_cp0_status_read() & ~MIPS_SR_BEV); +} +#endif /* notyet */ + +/* + * Do all the stuff that locore normally does before calling main(), + * that is common to all mips-CPU NetBSD ports. + * + * The principal purpose of this function is to examine the + * variable cpu_id, into which the kernel locore start code + * writes the cpu ID register, and to then copy appropriate + * code into the CPU exception-vector entries and the jump tables + * used to hide the differences in cache and TLB handling in + * different MIPS CPUs. + * + * This should be the very first thing called by each port's + * init_main() function. + */ + +/* + * Initialize the hardware exception vectors, and the jump table used to + * call locore cache and TLB management functions, based on the kind + * of CPU the kernel is running on. + */ +void +mips_vector_init(void) +{ + const struct pridtab *ct; + + mycpu = NULL; + for (ct = cputab; ct->cpu_name != NULL; ct++) { + if (MIPS_PRID_CID(cpu_id) != ct->cpu_cid || + MIPS_PRID_IMPL(cpu_id) != ct->cpu_pid) + continue; + if (ct->cpu_rev >= 0 && + MIPS_PRID_REV(cpu_id) != ct->cpu_rev) + continue; + if (ct->cpu_copts >= 0 && + MIPS_PRID_COPTS(cpu_id) != ct->cpu_copts) + continue; + + mycpu = ct; + cpu_arch = ct->cpu_isa; + mips_num_tlb_entries = ct->cpu_ntlb; + break; + } + + if (mycpu == NULL) + panic("CPU type (0x%x) not supported", cpu_id); + + if (MIPS_PRID_CID(cpu_id) != 0) { + /* MIPS32/MIPS64, use coprocessor 0 config registers */ + uint32_t cfg, cfg1; + + cfg = mips3_cp0_config_read(); + cfg1 = mipsNN_cp0_config1_read(); + + /* pick CPU type */ + switch (MIPSNN_GET(CFG_AT, cfg)) { + case MIPSNN_CFG_AT_MIPS32: + cpu_arch = CPU_ARCH_MIPS32; + break; + case MIPSNN_CFG_AT_MIPS64: + cpu_arch = CPU_ARCH_MIPS64; + break; + case MIPSNN_CFG_AT_MIPS64S: + default: + panic("MIPS32/64 architecture type %d not supported", + MIPSNN_GET(CFG_AT, cfg)); + } + + if (MIPSNN_GET(CFG_AR, cfg) != MIPSNN_CFG_AR_REV1) + printf("WARNING: MIPS32/64 arch revision != revision 1!\n"); + + /* figure out MMU type (and number of TLB entries) */ + switch (MIPSNN_GET(CFG_MT, cfg)) { + case MIPSNN_CFG_MT_TLB: + mips_num_tlb_entries = MIPSNN_CFG1_MS(cfg1); + break; + case MIPSNN_CFG_MT_NONE: + case MIPSNN_CFG_MT_BAT: + case MIPSNN_CFG_MT_FIXED: + default: + panic("MIPS32/64 MMU type %d not supported", + MIPSNN_GET(CFG_MT, cfg)); + } + } + + if (cpu_arch < 1) + panic("Unknown CPU ISA for CPU type 0x%x", cpu_id); + if (mips_num_tlb_entries < 1) + panic("Unknown number of TLBs for CPU type 0x%x", cpu_id); + + /* + * Check cpu-specific flags. + */ + mips_cpu_flags = mycpu->cpu_flags; + mips_has_r4k_mmu = mips_cpu_flags & CPU_MIPS_R4K_MMU; + mips_has_llsc = (mips_cpu_flags & CPU_MIPS_NO_LLSC) == 0; + + if (mycpu->cpu_flags & CPU_MIPS_HAVE_SPECIAL_CCA) { + uint32_t cca; + + cca = (ct->cpu_flags & CPU_MIPS_CACHED_CCA_MASK) >> + CPU_MIPS_CACHED_CCA_SHIFT; + mips3_pg_cached = MIPS3_CCA_TO_PG(cca); + } else + mips3_pg_cached = MIPS3_DEFAULT_PG_CACHED; + +#ifdef __HAVE_MIPS_MACHDEP_CACHE_CONFIG + mips_machdep_cache_config(); +#endif + + /* + * Determine cache configuration and initialize our cache + * frobbing routine function pointers. + */ + mips_config_cache(); + +#if notyet + /* + * Now initialize our ISA-dependent function vector. + */ + switch (cpu_arch) { + case CPU_ARCH_MIPS64: + mips3_cp0_wired_write(0); + mips64_TBIA(mips_num_tlb_entries); + mips3_cp0_wired_write(MIPS3_TLB_WIRED_UPAGES); + mips64_vector_init(); + memcpy(mips_locoresw, mips64_locoresw, sizeof(mips_locoresw)); + break; + default: + printf("cpu_arch 0x%x: not supported\n", cpu_arch); + cpu_reboot(RB_HALT, NULL); + } + +/* XXX simonb: ugg, another ugly #ifdef check... */ + /* + * Install power-saving idle routines. + */ + if ((mips_cpu_flags & CPU_MIPS_USE_WAIT) && + !(mips_cpu_flags & CPU_MIPS_NO_WAIT)) + CPU_IDLE = (long *)mips_wait_idle; +#endif /* notyet */ +} + +#if notyet +void +mips_set_wbflush(flush_fn) + void (*flush_fn)(void); +{ +#undef wbflush + mips_locore_jumpvec.wbflush = flush_fn; + (*flush_fn)(); +} +#endif + +/* + * Identify product revision IDs of cpu and fpu. + */ +void +cpu_identify(void) +{ + static const char * const waynames[] = { + "fully set-associative", /* 0 */ + "direct-mapped", /* 1 */ + "2-way set-associative", /* 2 */ + NULL, /* 3 */ + "4-way set-associative", /* 4 */ + }; +#define nwaynames (sizeof(waynames) / sizeof(waynames[0])) + static const char * const wtnames[] = { + "write-back", + "write-through", + }; + static const char * const label = "cpu0"; /* XXX */ + char *cpuname, *fpuname; + int i; + + cpuname = mycpu->cpu_name; + + fpuname = NULL; + for (i = 0; i < sizeof(fputab)/sizeof(fputab[0]); i++) { + if (MIPS_PRID_CID(fpu_id) == fputab[i].cpu_cid && + MIPS_PRID_IMPL(fpu_id) == fputab[i].cpu_pid) { + fpuname = fputab[i].cpu_name; + break; + } + } + if (fpuname == NULL && MIPS_PRID_IMPL(fpu_id) == MIPS_PRID_IMPL(cpu_id)) + fpuname = "built-in FPU"; + if (MIPS_PRID_IMPL(cpu_id) == MIPS_R4700) /* FPU PRid is 0x20 */ + fpuname = "built-in FPU"; + if (MIPS_PRID_IMPL(cpu_id) == MIPS_RC64470) /* FPU PRid is 0x21 */ + fpuname = "built-in FPU"; + + if (mycpu->cpu_cid != 0) { + if (mycpu->cpu_cid <= ncidnames) + printf("%s ", cidnames[mycpu->cpu_cid]); + else { + printf("Unknown Company ID - 0x%x", mycpu->cpu_cid); + printf("%s: ", label); + } + } + if (cpuname != NULL) + printf("%s (0x%x)", cpuname, cpu_id); + else + printf("unknown CPU type (0x%x)", cpu_id); + if (MIPS_PRID_CID(cpu_id) == MIPS_PRID_CID_PREHISTORIC) + printf(" Rev. %d.%d", MIPS_PRID_REV_MAJ(cpu_id), + MIPS_PRID_REV_MIN(cpu_id)); + else + printf(" Rev. %d", MIPS_PRID_REV(cpu_id)); + + if (fpuname != NULL) + printf(" with %s", fpuname); + else + printf(" with unknown FPC type (0x%x)", fpu_id); + if (fpu_id != 0) { + if (MIPS_PRID_CID(cpu_id) == MIPS_PRID_CID_PREHISTORIC) + printf(" Rev. %d.%d", MIPS_PRID_REV_MAJ(fpu_id), + MIPS_PRID_REV_MIN(fpu_id)); + else + printf(" Rev. %d", MIPS_PRID_REV(fpu_id)); + } + printf("\n"); + + if (MIPS_PRID_CID(cpu_id) == MIPS_PRID_CID_PREHISTORIC && + MIPS_PRID_RSVD(cpu_id) != 0) { + printf("%s: NOTE: top 8 bits of prehistoric PRID not 0!\n", + label); + printf("%s: Please mail port-mips@netbsd.org with cpu0 " + "dmesg lines.\n", label); + } + + KASSERT(mips_picache_ways < nwaynames, "picache ways < nwaynames"); + KASSERT(mips_pdcache_ways < nwaynames, "pdcache ways < nwaynames"); + KASSERT(mips_sicache_ways < nwaynames, "sicache ways < nwaynames"); + KASSERT(mips_sdcache_ways < nwaynames, "sdcache ways < nwaynames"); + + switch (cpu_arch) { + case CPU_ARCH_MIPS3: + case CPU_ARCH_MIPS4: + case CPU_ARCH_MIPS32: + case CPU_ARCH_MIPS64: + if (mips_picache_size) + printf("%s: %dKB/%dB %s L1 Instruction cache, " + "%d TLB entries\n", label, mips_picache_size / 1024, + mips_picache_line_size, waynames[mips_picache_ways], + mips_num_tlb_entries); + else + printf("%s: %d TLB entries\n", label, mips_num_tlb_entries); + if (mips_pdcache_size) + printf("%s: %dKB/%dB %s %s L1 Data cache\n", label, + mips_pdcache_size / 1024, mips_pdcache_line_size, + waynames[mips_pdcache_ways], + wtnames[mips_pdcache_write_through]); + if (mips_sdcache_line_size) + printf("%s: %dKB/%dB %s %s L2 %s cache\n", label, + mips_sdcache_size / 1024, mips_sdcache_line_size, + waynames[mips_sdcache_ways], + wtnames[mips_sdcache_write_through], + mips_scache_unified ? "Unified" : "Data"); + break; + default: + panic("cpu_identify: impossible"); + } +}