Index: head/sys/mips/include/cache_mipsNN.h =================================================================== --- head/sys/mips/include/cache_mipsNN.h (revision 274751) +++ head/sys/mips/include/cache_mipsNN.h (revision 274752) @@ -1,71 +1,81 @@ /* $NetBSD: cache_mipsNN.h,v 1.4 2003/02/17 11:35:02 simonb Exp $ */ /* * 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. * * $FreeBSD$ */ #ifndef _MACHINE_CACHE_MIPSNN_H_ #define _MACHINE_CACHE_MIPSNN_H_ void mipsNN_cache_init(struct mips_cpuinfo *); void mipsNN_icache_sync_all_16(void); void mipsNN_icache_sync_all_32(void); void mipsNN_icache_sync_range_16(vm_offset_t, vm_size_t); void mipsNN_icache_sync_range_32(vm_offset_t, vm_size_t); void mipsNN_icache_sync_range_index_16(vm_offset_t, vm_size_t); void mipsNN_icache_sync_range_index_32(vm_offset_t, vm_size_t); void mipsNN_pdcache_wbinv_all_16(void); void mipsNN_pdcache_wbinv_all_32(void); void mipsNN_pdcache_wbinv_range_16(vm_offset_t, vm_size_t); void mipsNN_pdcache_wbinv_range_32(vm_offset_t, vm_size_t); void mipsNN_pdcache_wbinv_range_index_16(vm_offset_t, vm_size_t); void mipsNN_pdcache_wbinv_range_index_32(vm_offset_t, vm_size_t); void mipsNN_pdcache_inv_range_16(vm_offset_t, vm_size_t); void mipsNN_pdcache_inv_range_32(vm_offset_t, vm_size_t); void mipsNN_pdcache_wb_range_16(vm_offset_t, vm_size_t); void mipsNN_pdcache_wb_range_32(vm_offset_t, vm_size_t); #ifdef CPU_CNMIPS void mipsNN_icache_sync_all_128(void); void mipsNN_icache_sync_range_128(vm_offset_t, vm_size_t); void mipsNN_icache_sync_range_index_128(vm_offset_t, vm_size_t); void mipsNN_pdcache_wbinv_all_128(void); void mipsNN_pdcache_wbinv_range_128(vm_offset_t, vm_size_t); void mipsNN_pdcache_wbinv_range_index_128(vm_offset_t, vm_size_t); void mipsNN_pdcache_inv_range_128(vm_offset_t, vm_size_t); void mipsNN_pdcache_wb_range_128(vm_offset_t, vm_size_t); #endif +void mipsNN_sdcache_wbinv_all_32(void); +void mipsNN_sdcache_wbinv_range_32(vm_paddr_t, vm_size_t); +void mipsNN_sdcache_wbinv_range_index_32(vm_paddr_t, vm_size_t); +void mipsNN_sdcache_inv_range_32(vm_paddr_t, vm_size_t); +void mipsNN_sdcache_wb_range_32(vm_paddr_t, vm_size_t); +void mipsNN_sdcache_wbinv_all_128(void); +void mipsNN_sdcache_wbinv_range_128(vm_paddr_t, vm_size_t); +void mipsNN_sdcache_wbinv_range_index_128(vm_paddr_t, vm_size_t); +void mipsNN_sdcache_inv_range_128(vm_paddr_t, vm_size_t); +void mipsNN_sdcache_wb_range_128(vm_paddr_t, vm_size_t); #endif /* _MACHINE_CACHE_MIPSNN_H_ */ Index: head/sys/mips/include/cpuinfo.h =================================================================== --- head/sys/mips/include/cpuinfo.h (revision 274751) +++ head/sys/mips/include/cpuinfo.h (revision 274752) @@ -1,76 +1,82 @@ /* $NetBSD: cpu.h,v 1.70 2003/01/17 23:36:08 thorpej Exp $ */ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Ralph Campbell and Rick Macklem. * * 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 University of * California, Berkeley and its contributors. * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. * * $FreeBSD$ * @(#)cpu.h 8.4 (Berkeley) 1/4/94 */ #ifndef _CPUINFO_H_ #define _CPUINFO_H_ /* * Exported definitions unique to NetBSD/mips cpu support. */ #ifdef _KERNEL #ifndef LOCORE struct mips_cpuinfo { u_int8_t cpu_vendor; u_int8_t cpu_rev; u_int8_t cpu_impl; u_int8_t tlb_type; u_int16_t tlb_nentries; u_int8_t icache_virtual; boolean_t cache_coherent_dma; struct { u_int32_t ic_size; u_int8_t ic_linesize; u_int8_t ic_nways; u_int16_t ic_nsets; u_int32_t dc_size; u_int8_t dc_linesize; u_int8_t dc_nways; u_int16_t dc_nsets; } l1; + struct { + u_int32_t dc_size; + u_int8_t dc_linesize; + u_int8_t dc_nways; + u_int16_t dc_nsets; + } l2; }; extern struct mips_cpuinfo cpuinfo; #endif /* !LOCORE */ #endif /* _KERNEL */ #endif /* _CPUINFO_H_ */ Index: head/sys/mips/include/cpuregs.h =================================================================== --- head/sys/mips/include/cpuregs.h (revision 274751) +++ head/sys/mips/include/cpuregs.h (revision 274752) @@ -1,630 +1,637 @@ /* $NetBSD: cpuregs.h,v 1.70 2006/05/15 02:26:54 simonb Exp $ */ /* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Ralph Campbell and Rick Macklem. * * 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. Neither the name of the University 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 REGENTS 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 REGENTS 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. * * @(#)machConst.h 8.1 (Berkeley) 6/10/93 * * machConst.h -- * * Machine dependent constants. * * Copyright (C) 1989 Digital Equipment Corporation. * 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 appears in all copies. * Digital Equipment Corporation makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machConst.h, * v 9.2 89/10/21 15:55:22 jhh Exp SPRITE (DECWRL) * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAddrs.h, * v 1.2 89/08/15 18:28:21 rab Exp SPRITE (DECWRL) * from: Header: /sprite/src/kernel/vm/ds3100.md/RCS/vmPmaxConst.h, * v 9.1 89/09/18 17:33:00 shirriff Exp SPRITE (DECWRL) * * $FreeBSD$ */ #ifndef _MIPS_CPUREGS_H_ #define _MIPS_CPUREGS_H_ /* * Address space. * 32-bit mips CPUS partition their 32-bit address space into four segments: * * kuseg 0x00000000 - 0x7fffffff User virtual mem, mapped * kseg0 0x80000000 - 0x9fffffff Physical memory, cached, unmapped * kseg1 0xa0000000 - 0xbfffffff Physical memory, uncached, unmapped * kseg2 0xc0000000 - 0xffffffff kernel-virtual, mapped * * Caching of mapped addresses is controlled by bits in the TLB entry. */ #define MIPS_KSEG0_LARGEST_PHYS (0x20000000) #define MIPS_KSEG0_PHYS_MASK (0x1fffffff) #define MIPS_XKPHYS_LARGEST_PHYS (0x10000000000) /* 40 bit PA */ #define MIPS_XKPHYS_PHYS_MASK (0x0ffffffffff) #ifndef LOCORE #define MIPS_KUSEG_START 0x00000000 #define MIPS_KSEG0_START ((intptr_t)(int32_t)0x80000000) #define MIPS_KSEG0_END ((intptr_t)(int32_t)0x9fffffff) #define MIPS_KSEG1_START ((intptr_t)(int32_t)0xa0000000) #define MIPS_KSEG1_END ((intptr_t)(int32_t)0xbfffffff) #define MIPS_KSSEG_START ((intptr_t)(int32_t)0xc0000000) #define MIPS_KSSEG_END ((intptr_t)(int32_t)0xdfffffff) #define MIPS_KSEG3_START ((intptr_t)(int32_t)0xe0000000) #define MIPS_KSEG3_END ((intptr_t)(int32_t)0xffffffff) #define MIPS_KSEG2_START MIPS_KSSEG_START #define MIPS_KSEG2_END MIPS_KSSEG_END #endif #define MIPS_PHYS_TO_KSEG0(x) ((uintptr_t)(x) | MIPS_KSEG0_START) #define MIPS_PHYS_TO_KSEG1(x) ((uintptr_t)(x) | MIPS_KSEG1_START) #define MIPS_KSEG0_TO_PHYS(x) ((uintptr_t)(x) & MIPS_KSEG0_PHYS_MASK) #define MIPS_KSEG1_TO_PHYS(x) ((uintptr_t)(x) & MIPS_KSEG0_PHYS_MASK) #define MIPS_IS_KSEG0_ADDR(x) \ (((vm_offset_t)(x) >= MIPS_KSEG0_START) && \ ((vm_offset_t)(x) <= MIPS_KSEG0_END)) #define MIPS_IS_KSEG1_ADDR(x) \ (((vm_offset_t)(x) >= MIPS_KSEG1_START) && \ ((vm_offset_t)(x) <= MIPS_KSEG1_END)) #define MIPS_IS_VALID_PTR(x) (MIPS_IS_KSEG0_ADDR(x) || \ MIPS_IS_KSEG1_ADDR(x)) /* * Cache Coherency Attributes: * UC: Uncached. * UA: Uncached accelerated. * C: Cacheable, coherency unspecified. * CNC: Cacheable non-coherent. * CC: Cacheable coherent. * CCE: Cacheable coherent, exclusive read. * CCEW: Cacheable coherent, exclusive write. * CCUOW: Cacheable coherent, update on write. * * Note that some bits vary in meaning across implementations (and that the * listing here is no doubt incomplete) and that the optimal cached mode varies * between implementations. 0x02 is required to be UC and 0x03 is required to * be a least C. * * We define the following logical bits: * UNCACHED: * The optimal uncached mode for the target CPU type. This must * be suitable for use in accessing memory-mapped devices. * CACHED: The optional cached mode for the target CPU type. */ #define MIPS_CCA_UC 0x02 /* Uncached. */ #define MIPS_CCA_C 0x03 /* Cacheable, coherency unspecified. */ #if defined(CPU_R4000) || defined(CPU_R10000) #define MIPS_CCA_CNC 0x03 #define MIPS_CCA_CCE 0x04 #define MIPS_CCA_CCEW 0x05 #ifdef CPU_R4000 #define MIPS_CCA_CCUOW 0x06 #endif #ifdef CPU_R10000 #define MIPS_CCA_UA 0x07 #endif #define MIPS_CCA_CACHED MIPS_CCA_CCEW #endif /* defined(CPU_R4000) || defined(CPU_R10000) */ #if defined(CPU_SB1) #define MIPS_CCA_CC 0x05 /* Cacheable Coherent. */ #endif #if defined(CPU_MIPS74KC) #define MIPS_CCA_UNCACHED 0x02 #define MIPS_CCA_CACHED 0x00 #endif #ifndef MIPS_CCA_UNCACHED #define MIPS_CCA_UNCACHED MIPS_CCA_UC #endif /* * If we don't know which cached mode to use and there is a cache coherent * mode, use it. If there is not a cache coherent mode, use the required * cacheable mode. */ #ifndef MIPS_CCA_CACHED #ifdef MIPS_CCA_CC #define MIPS_CCA_CACHED MIPS_CCA_CC #else #define MIPS_CCA_CACHED MIPS_CCA_C #endif #endif #define MIPS_PHYS_TO_XKPHYS(cca,x) \ ((0x2ULL << 62) | ((unsigned long long)(cca) << 59) | (x)) #define MIPS_PHYS_TO_XKPHYS_CACHED(x) \ ((0x2ULL << 62) | ((unsigned long long)(MIPS_CCA_CACHED) << 59) | (x)) #define MIPS_PHYS_TO_XKPHYS_UNCACHED(x) \ ((0x2ULL << 62) | ((unsigned long long)(MIPS_CCA_UNCACHED) << 59) | (x)) #define MIPS_XKPHYS_TO_PHYS(x) ((uintptr_t)(x) & MIPS_XKPHYS_PHYS_MASK) #define MIPS_XKPHYS_START 0x8000000000000000 #define MIPS_XKPHYS_END 0xbfffffffffffffff #define MIPS_XUSEG_START 0x0000000000000000 #define MIPS_XUSEG_END 0x0000010000000000 #define MIPS_XKSEG_START 0xc000000000000000 #define MIPS_XKSEG_END 0xc00000ff80000000 #define MIPS_XKSEG_COMPAT32_START 0xffffffff80000000 #define MIPS_XKSEG_COMPAT32_END 0xffffffffffffffff #define MIPS_XKSEG_TO_COMPAT32(va) ((va) & 0xffffffff) #ifdef __mips_n64 #define MIPS_DIRECT_MAPPABLE(pa) 1 #define MIPS_PHYS_TO_DIRECT(pa) MIPS_PHYS_TO_XKPHYS_CACHED(pa) #define MIPS_PHYS_TO_DIRECT_UNCACHED(pa) MIPS_PHYS_TO_XKPHYS_UNCACHED(pa) #define MIPS_DIRECT_TO_PHYS(va) MIPS_XKPHYS_TO_PHYS(va) #else #define MIPS_DIRECT_MAPPABLE(pa) ((pa) < MIPS_KSEG0_LARGEST_PHYS) #define MIPS_PHYS_TO_DIRECT(pa) MIPS_PHYS_TO_KSEG0(pa) #define MIPS_PHYS_TO_DIRECT_UNCACHED(pa) MIPS_PHYS_TO_KSEG1(pa) #define MIPS_DIRECT_TO_PHYS(va) MIPS_KSEG0_TO_PHYS(va) #endif /* CPU dependent mtc0 hazard hook */ #if defined(CPU_CNMIPS) || defined(CPU_RMI) #define COP0_SYNC #elif defined(CPU_NLM) #define COP0_SYNC .word 0xc0 /* ehb */ #elif defined(CPU_SB1) #define COP0_SYNC ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop #elif defined(CPU_MIPS74KC) #define COP0_SYNC .word 0xc0 /* ehb */ #else /* * Pick a reasonable default based on the "typical" spacing described in the * "CP0 Hazards" chapter of MIPS Architecture Book Vol III. */ #define COP0_SYNC ssnop; ssnop; ssnop; ssnop; .word 0xc0; #endif #define COP0_HAZARD_FPUENABLE nop; nop; nop; nop; /* * The bits in the cause register. * * Bits common to r3000 and r4000: * * MIPS_CR_BR_DELAY Exception happened in branch delay slot. * MIPS_CR_COP_ERR Coprocessor error. * MIPS_CR_IP Interrupt pending bits defined below. * (same meaning as in CAUSE register). * MIPS_CR_EXC_CODE The exception type (see exception codes below). * * Differences: * r3k has 4 bits of execption type, r4k has 5 bits. */ #define MIPS_CR_BR_DELAY 0x80000000 #define MIPS_CR_COP_ERR 0x30000000 #define MIPS_CR_EXC_CODE 0x0000007C /* five bits */ #define MIPS_CR_IP 0x0000FF00 #define MIPS_CR_EXC_CODE_SHIFT 2 #define MIPS_CR_COP_ERR_SHIFT 28 /* * The bits in the status register. All bits are active when set to 1. * * R3000 status register fields: * MIPS_SR_COP_USABILITY Control the usability of the four coprocessors. * MIPS_SR_TS TLB shutdown. * * MIPS_SR_INT_IE Master (current) interrupt enable bit. * * Differences: * r3k has cache control is via frobbing SR register bits, whereas the * r4k cache control is via explicit instructions. * r3k has a 3-entry stack of kernel/user bits, whereas the * r4k has kernel/supervisor/user. */ #define MIPS_SR_COP_USABILITY 0xf0000000 #define MIPS_SR_COP_0_BIT 0x10000000 #define MIPS_SR_COP_1_BIT 0x20000000 #define MIPS_SR_COP_2_BIT 0x40000000 /* r4k and r3k differences, see below */ #define MIPS_SR_MX 0x01000000 /* MIPS64 */ #define MIPS_SR_PX 0x00800000 /* MIPS64 */ #define MIPS_SR_BEV 0x00400000 /* Use boot exception vector */ #define MIPS_SR_TS 0x00200000 #define MIPS_SR_DE 0x00010000 #define MIPS_SR_INT_IE 0x00000001 /*#define MIPS_SR_MBZ 0x0f8000c0*/ /* Never used, true for r3k */ #define MIPS_SR_INT_MASK 0x0000ff00 /* * R4000 status register bit definitons, * where different from r2000/r3000. */ #define MIPS_SR_XX 0x80000000 #define MIPS_SR_RP 0x08000000 #define MIPS_SR_FR 0x04000000 #define MIPS_SR_RE 0x02000000 #define MIPS_SR_DIAG_DL 0x01000000 /* QED 52xx */ #define MIPS_SR_DIAG_IL 0x00800000 /* QED 52xx */ #define MIPS_SR_SR 0x00100000 #define MIPS_SR_NMI 0x00080000 /* MIPS32/64 */ #define MIPS_SR_DIAG_CH 0x00040000 #define MIPS_SR_DIAG_CE 0x00020000 #define MIPS_SR_DIAG_PE 0x00010000 #define MIPS_SR_EIE 0x00010000 /* TX79/R5900 */ #define MIPS_SR_KX 0x00000080 #define MIPS_SR_SX 0x00000040 #define MIPS_SR_UX 0x00000020 #define MIPS_SR_KSU_MASK 0x00000018 #define MIPS_SR_KSU_USER 0x00000010 #define MIPS_SR_KSU_SUPER 0x00000008 #define MIPS_SR_KSU_KERNEL 0x00000000 #define MIPS_SR_ERL 0x00000004 #define MIPS_SR_EXL 0x00000002 /* * The interrupt masks. * If a bit in the mask is 1 then the interrupt is enabled (or pending). */ #define MIPS_INT_MASK 0xff00 #define MIPS_INT_MASK_5 0x8000 #define MIPS_INT_MASK_4 0x4000 #define MIPS_INT_MASK_3 0x2000 #define MIPS_INT_MASK_2 0x1000 #define MIPS_INT_MASK_1 0x0800 #define MIPS_INT_MASK_0 0x0400 #define MIPS_HARD_INT_MASK 0xfc00 #define MIPS_SOFT_INT_MASK_1 0x0200 #define MIPS_SOFT_INT_MASK_0 0x0100 /* * The bits in the MIPS3 config register. * * bit 0..5: R/W, Bit 6..31: R/O */ /* kseg0 coherency algorithm - see MIPS3_TLB_ATTR values */ #define MIPS_CONFIG_K0_MASK 0x00000007 /* * R/W Update on Store Conditional * 0: Store Conditional uses coherency algorithm specified by TLB * 1: Store Conditional uses cacheable coherent update on write */ #define MIPS_CONFIG_CU 0x00000008 #define MIPS_CONFIG_DB 0x00000010 /* Primary D-cache line size */ #define MIPS_CONFIG_IB 0x00000020 /* Primary I-cache line size */ #define MIPS_CONFIG_CACHE_L1_LSIZE(config, bit) \ (((config) & (bit)) ? 32 : 16) #define MIPS_CONFIG_DC_MASK 0x000001c0 /* Primary D-cache size */ #define MIPS_CONFIG_DC_SHIFT 6 #define MIPS_CONFIG_IC_MASK 0x00000e00 /* Primary I-cache size */ #define MIPS_CONFIG_IC_SHIFT 9 #define MIPS_CONFIG_C_DEFBASE 0x1000 /* default base 2^12 */ /* Cache size mode indication: available only on Vr41xx CPUs */ #define MIPS_CONFIG_CS 0x00001000 #define MIPS_CONFIG_C_4100BASE 0x0400 /* base is 2^10 if CS=1 */ #define MIPS_CONFIG_CACHE_SIZE(config, mask, base, shift) \ ((base) << (((config) & (mask)) >> (shift))) /* External cache enable: Controls L2 for R5000/Rm527x and L3 for Rm7000 */ #define MIPS_CONFIG_SE 0x00001000 /* Block ordering: 0: sequential, 1: sub-block */ #define MIPS_CONFIG_EB 0x00002000 /* ECC mode - 0: ECC mode, 1: parity mode */ #define MIPS_CONFIG_EM 0x00004000 /* BigEndianMem - 0: kernel and memory are little endian, 1: big endian */ #define MIPS_CONFIG_BE 0x00008000 /* Dirty Shared coherency state - 0: enabled, 1: disabled */ #define MIPS_CONFIG_SM 0x00010000 /* Secondary Cache - 0: present, 1: not present */ #define MIPS_CONFIG_SC 0x00020000 /* System Port width - 0: 64-bit, 1: 32-bit (QED RM523x), 2,3: reserved */ #define MIPS_CONFIG_EW_MASK 0x000c0000 #define MIPS_CONFIG_EW_SHIFT 18 /* Secondary Cache port width - 0: 128-bit data path to S-cache, 1: reserved */ #define MIPS_CONFIG_SW 0x00100000 /* Split Secondary Cache Mode - 0: I/D mixed, 1: I/D separated by SCAddr(17) */ #define MIPS_CONFIG_SS 0x00200000 /* Secondary Cache line size */ #define MIPS_CONFIG_SB_MASK 0x00c00000 #define MIPS_CONFIG_SB_SHIFT 22 #define MIPS_CONFIG_CACHE_L2_LSIZE(config) \ (0x10 << (((config) & MIPS_CONFIG_SB_MASK) >> MIPS_CONFIG_SB_SHIFT)) /* Write back data rate */ #define MIPS_CONFIG_EP_MASK 0x0f000000 #define MIPS_CONFIG_EP_SHIFT 24 /* System clock ratio - this value is CPU dependent */ #define MIPS_CONFIG_EC_MASK 0x70000000 #define MIPS_CONFIG_EC_SHIFT 28 /* Master-Checker Mode - 1: enabled */ #define MIPS_CONFIG_CM 0x80000000 /* * The bits in the MIPS4 config register. */ /* * Location of exception vectors. * * Common vectors: reset and UTLB miss. */ #define MIPS_RESET_EXC_VEC ((intptr_t)(int32_t)0xBFC00000) #define MIPS_UTLB_MISS_EXC_VEC ((intptr_t)(int32_t)0x80000000) /* * MIPS-III exception vectors */ #define MIPS_XTLB_MISS_EXC_VEC ((intptr_t)(int32_t)0x80000080) #define MIPS_CACHE_ERR_EXC_VEC ((intptr_t)(int32_t)0x80000100) #define MIPS_GEN_EXC_VEC ((intptr_t)(int32_t)0x80000180) /* * MIPS32/MIPS64 (and some MIPS3) dedicated interrupt vector. */ #define MIPS_INTR_EXC_VEC 0x80000200 /* * Coprocessor 0 registers: * * v--- width for mips I,III,32,64 * (3=32bit, 6=64bit, i=impl dep) * 0 MIPS_COP_0_TLB_INDEX 3333 TLB Index. * 1 MIPS_COP_0_TLB_RANDOM 3333 TLB Random. * 2 MIPS_COP_0_TLB_LO0 .636 r4k TLB entry low. * 3 MIPS_COP_0_TLB_LO1 .636 r4k TLB entry low, extended. * 4 MIPS_COP_0_TLB_CONTEXT 3636 TLB Context. * 5 MIPS_COP_0_TLB_PG_MASK .333 TLB Page Mask register. * 6 MIPS_COP_0_TLB_WIRED .333 Wired TLB number. * 7 MIPS_COP_0_INFO ..33 Info registers * 8 MIPS_COP_0_BAD_VADDR 3636 Bad virtual address. * 9 MIPS_COP_0_COUNT .333 Count register. * 10 MIPS_COP_0_TLB_HI 3636 TLB entry high. * 11 MIPS_COP_0_COMPARE .333 Compare (against Count). * 12 MIPS_COP_0_STATUS 3333 Status register. * 13 MIPS_COP_0_CAUSE 3333 Exception cause register. * 14 MIPS_COP_0_EXC_PC 3636 Exception PC. * 15 MIPS_COP_0_PRID 3333 Processor revision identifier. * 16 MIPS_COP_0_CONFIG 3333 Configuration register. * 16/1 MIPS_COP_0_CONFIG1 ..33 Configuration register 1. * 16/2 MIPS_COP_0_CONFIG2 ..33 Configuration register 2. * 16/3 MIPS_COP_0_CONFIG3 ..33 Configuration register 3. * 16/4 MIPS_COP_0_CONFIG4 ..33 Configuration register 4. * 17 MIPS_COP_0_LLADDR .336 Load Linked Address. * 18 MIPS_COP_0_WATCH_LO .336 WatchLo register. * 19 MIPS_COP_0_WATCH_HI .333 WatchHi register. * 20 MIPS_COP_0_TLB_XCONTEXT .6.6 TLB XContext register. * 23 MIPS_COP_0_DEBUG .... Debug JTAG register. * 24 MIPS_COP_0_DEPC .... DEPC JTAG register. * 25 MIPS_COP_0_PERFCNT ..36 Performance Counter register. * 26 MIPS_COP_0_ECC .3ii ECC / Error Control register. * 27 MIPS_COP_0_CACHE_ERR .3ii Cache Error register. * 28/0 MIPS_COP_0_TAG_LO .3ii Cache TagLo register (instr). * 28/1 MIPS_COP_0_DATA_LO ..ii Cache DataLo register (instr). * 28/2 MIPS_COP_0_TAG_LO ..ii Cache TagLo register (data). * 28/3 MIPS_COP_0_DATA_LO ..ii Cache DataLo register (data). * 29/0 MIPS_COP_0_TAG_HI .3ii Cache TagHi register (instr). * 29/1 MIPS_COP_0_DATA_HI ..ii Cache DataHi register (instr). * 29/2 MIPS_COP_0_TAG_HI ..ii Cache TagHi register (data). * 29/3 MIPS_COP_0_DATA_HI ..ii Cache DataHi register (data). * 30 MIPS_COP_0_ERROR_PC .636 Error EPC register. * 31 MIPS_COP_0_DESAVE .... DESAVE JTAG register. */ /* Deal with inclusion from an assembly file. */ #if defined(_LOCORE) || defined(LOCORE) #define _(n) $n #else #define _(n) n #endif #define MIPS_COP_0_TLB_INDEX _(0) #define MIPS_COP_0_TLB_RANDOM _(1) /* Name and meaning of TLB bits for $2 differ on r3k and r4k. */ #define MIPS_COP_0_TLB_CONTEXT _(4) /* $5 and $6 new with MIPS-III */ #define MIPS_COP_0_BAD_VADDR _(8) #define MIPS_COP_0_TLB_HI _(10) #define MIPS_COP_0_STATUS _(12) #define MIPS_COP_0_CAUSE _(13) #define MIPS_COP_0_EXC_PC _(14) #define MIPS_COP_0_PRID _(15) /* MIPS-III */ #define MIPS_COP_0_TLB_LO0 _(2) #define MIPS_COP_0_TLB_LO1 _(3) #define MIPS_COP_0_TLB_PG_MASK _(5) #define MIPS_COP_0_TLB_WIRED _(6) #define MIPS_COP_0_COUNT _(9) #define MIPS_COP_0_COMPARE _(11) #define MIPS_COP_0_CONFIG _(16) #define MIPS_COP_0_LLADDR _(17) #define MIPS_COP_0_WATCH_LO _(18) #define MIPS_COP_0_WATCH_HI _(19) #define MIPS_COP_0_TLB_XCONTEXT _(20) #define MIPS_COP_0_ECC _(26) #define MIPS_COP_0_CACHE_ERR _(27) #define MIPS_COP_0_TAG_LO _(28) #define MIPS_COP_0_TAG_HI _(29) #define MIPS_COP_0_ERROR_PC _(30) /* MIPS32/64 */ #define MIPS_COP_0_INFO _(7) #define MIPS_COP_0_DEBUG _(23) #define MIPS_COP_0_DEPC _(24) #define MIPS_COP_0_PERFCNT _(25) #define MIPS_COP_0_DATA_LO _(28) #define MIPS_COP_0_DATA_HI _(29) #define MIPS_COP_0_DESAVE _(31) /* MIPS32 Config register definitions */ #define MIPS_MMU_NONE 0x00 /* No MMU present */ #define MIPS_MMU_TLB 0x01 /* Standard TLB */ #define MIPS_MMU_BAT 0x02 /* Standard BAT */ #define MIPS_MMU_FIXED 0x03 /* Standard fixed mapping */ #define MIPS_CONFIG0_MT_MASK 0x00000380 /* bits 9..7 MMU Type */ #define MIPS_CONFIG0_MT_SHIFT 7 #define MIPS_CONFIG0_BE 0x00008000 /* data is big-endian */ #define MIPS_CONFIG0_VI 0x00000004 /* instruction cache is virtual */ #define MIPS_CONFIG1_TLBSZ_MASK 0x7E000000 /* bits 30..25 # tlb entries minus one */ #define MIPS_CONFIG1_TLBSZ_SHIFT 25 #define MIPS_CONFIG1_IS_MASK 0x01C00000 /* bits 24..22 icache sets per way */ #define MIPS_CONFIG1_IS_SHIFT 22 #define MIPS_CONFIG1_IL_MASK 0x00380000 /* bits 21..19 icache line size */ #define MIPS_CONFIG1_IL_SHIFT 19 #define MIPS_CONFIG1_IA_MASK 0x00070000 /* bits 18..16 icache associativity */ #define MIPS_CONFIG1_IA_SHIFT 16 #define MIPS_CONFIG1_DS_MASK 0x0000E000 /* bits 15..13 dcache sets per way */ #define MIPS_CONFIG1_DS_SHIFT 13 #define MIPS_CONFIG1_DL_MASK 0x00001C00 /* bits 12..10 dcache line size */ #define MIPS_CONFIG1_DL_SHIFT 10 #define MIPS_CONFIG1_DA_MASK 0x00000380 /* bits 9.. 7 dcache associativity */ #define MIPS_CONFIG1_DA_SHIFT 7 #define MIPS_CONFIG1_LOWBITS 0x0000007F #define MIPS_CONFIG1_C2 0x00000040 /* Coprocessor 2 implemented */ #define MIPS_CONFIG1_MD 0x00000020 /* MDMX ASE implemented (MIPS64) */ #define MIPS_CONFIG1_PC 0x00000010 /* Performance counters implemented */ #define MIPS_CONFIG1_WR 0x00000008 /* Watch registers implemented */ #define MIPS_CONFIG1_CA 0x00000004 /* MIPS16e ISA implemented */ #define MIPS_CONFIG1_EP 0x00000002 /* EJTAG implemented */ #define MIPS_CONFIG1_FP 0x00000001 /* FPU implemented */ +#define MIPS_CONFIG2_SA_SHIFT 0 /* Secondary cache associativity */ +#define MIPS_CONFIG2_SA_MASK 0xf +#define MIPS_CONFIG2_SL_SHIFT 4 /* Secondary cache line size */ +#define MIPS_CONFIG2_SL_MASK 0xf +#define MIPS_CONFIG2_SS_SHIFT 8 /* Secondary cache sets per way */ +#define MIPS_CONFIG2_SS_MASK 0xf + #define MIPS_CONFIG4_MMUSIZEEXT 0x000000FF /* bits 7.. 0 MMU Size Extension */ #define MIPS_CONFIG4_MMUEXTDEF 0x0000C000 /* bits 15.14 MMU Extension Definition */ #define MIPS_CONFIG4_MMUEXTDEF_MMUSIZEEXT 0x00004000 /* This values denotes CONFIG4 bits */ /* * Values for the code field in a break instruction. */ #define MIPS_BREAK_INSTR 0x0000000d #define MIPS_BREAK_VAL_MASK 0x03ff0000 #define MIPS_BREAK_VAL_SHIFT 16 #define MIPS_BREAK_KDB_VAL 512 #define MIPS_BREAK_SSTEP_VAL 513 #define MIPS_BREAK_BRKPT_VAL 514 #define MIPS_BREAK_SOVER_VAL 515 #define MIPS_BREAK_DDB_VAL 516 #define MIPS_BREAK_KDB (MIPS_BREAK_INSTR | \ (MIPS_BREAK_KDB_VAL << MIPS_BREAK_VAL_SHIFT)) #define MIPS_BREAK_SSTEP (MIPS_BREAK_INSTR | \ (MIPS_BREAK_SSTEP_VAL << MIPS_BREAK_VAL_SHIFT)) #define MIPS_BREAK_BRKPT (MIPS_BREAK_INSTR | \ (MIPS_BREAK_BRKPT_VAL << MIPS_BREAK_VAL_SHIFT)) #define MIPS_BREAK_SOVER (MIPS_BREAK_INSTR | \ (MIPS_BREAK_SOVER_VAL << MIPS_BREAK_VAL_SHIFT)) #define MIPS_BREAK_DDB (MIPS_BREAK_INSTR | \ (MIPS_BREAK_DDB_VAL << MIPS_BREAK_VAL_SHIFT)) /* * Mininum and maximum cache sizes. */ #define MIPS_MIN_CACHE_SIZE (16 * 1024) #define MIPS_MAX_CACHE_SIZE (256 * 1024) #define MIPS_MAX_PCACHE_SIZE (32 * 1024) /* max. primary cache size */ /* * The floating point version and status registers. */ #define MIPS_FPU_ID $0 #define MIPS_FPU_CSR $31 /* * The floating point coprocessor status register bits. */ #define MIPS_FPU_ROUNDING_BITS 0x00000003 #define MIPS_FPU_ROUND_RN 0x00000000 #define MIPS_FPU_ROUND_RZ 0x00000001 #define MIPS_FPU_ROUND_RP 0x00000002 #define MIPS_FPU_ROUND_RM 0x00000003 #define MIPS_FPU_STICKY_BITS 0x0000007c #define MIPS_FPU_STICKY_INEXACT 0x00000004 #define MIPS_FPU_STICKY_UNDERFLOW 0x00000008 #define MIPS_FPU_STICKY_OVERFLOW 0x00000010 #define MIPS_FPU_STICKY_DIV0 0x00000020 #define MIPS_FPU_STICKY_INVALID 0x00000040 #define MIPS_FPU_ENABLE_BITS 0x00000f80 #define MIPS_FPU_ENABLE_INEXACT 0x00000080 #define MIPS_FPU_ENABLE_UNDERFLOW 0x00000100 #define MIPS_FPU_ENABLE_OVERFLOW 0x00000200 #define MIPS_FPU_ENABLE_DIV0 0x00000400 #define MIPS_FPU_ENABLE_INVALID 0x00000800 #define MIPS_FPU_EXCEPTION_BITS 0x0003f000 #define MIPS_FPU_EXCEPTION_INEXACT 0x00001000 #define MIPS_FPU_EXCEPTION_UNDERFLOW 0x00002000 #define MIPS_FPU_EXCEPTION_OVERFLOW 0x00004000 #define MIPS_FPU_EXCEPTION_DIV0 0x00008000 #define MIPS_FPU_EXCEPTION_INVALID 0x00010000 #define MIPS_FPU_EXCEPTION_UNIMPL 0x00020000 #define MIPS_FPU_COND_BIT 0x00800000 #define MIPS_FPU_FLUSH_BIT 0x01000000 /* r4k, MBZ on r3k */ #define MIPS_FPC_MBZ_BITS 0xfe7c0000 /* * Constants to determine if have a floating point instruction. */ #define MIPS_OPCODE_SHIFT 26 #define MIPS_OPCODE_C1 0x11 #endif /* _MIPS_CPUREGS_H_ */ Index: head/sys/mips/mips/cache.c =================================================================== --- head/sys/mips/mips/cache.c (revision 274751) +++ head/sys/mips/mips/cache.c (revision 274752) @@ -1,278 +1,301 @@ /* $NetBSD: cache.c,v 1.33 2005/12/24 23:24:01 perry Exp $ */ /*- * Copyright 2001, 2002 Wasabi Systems, Inc. * All rights reserved. * * Written by Jason R. Thorpe and 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include struct mips_cache_ops mips_cache_ops; #if defined(MIPS_DISABLE_L1_CACHE) || defined(CPU_RMI) || defined(CPU_NLM) static void cache_noop(vm_offset_t va, vm_size_t size) { } #endif void mips_config_cache(struct mips_cpuinfo * cpuinfo) { switch (cpuinfo->l1.ic_linesize) { case 16: mips_cache_ops.mco_icache_sync_all = mipsNN_icache_sync_all_16; mips_cache_ops.mco_icache_sync_range = mipsNN_icache_sync_range_16; mips_cache_ops.mco_icache_sync_range_index = mipsNN_icache_sync_range_index_16; break; case 32: mips_cache_ops.mco_icache_sync_all = mipsNN_icache_sync_all_32; mips_cache_ops.mco_icache_sync_range = mipsNN_icache_sync_range_32; mips_cache_ops.mco_icache_sync_range_index = mipsNN_icache_sync_range_index_32; break; #ifdef CPU_CNMIPS case 128: mips_cache_ops.mco_icache_sync_all = mipsNN_icache_sync_all_128; mips_cache_ops.mco_icache_sync_range = mipsNN_icache_sync_range_128; mips_cache_ops.mco_icache_sync_range_index = mipsNN_icache_sync_range_index_128; break; #endif #ifdef MIPS_DISABLE_L1_CACHE case 0: mips_cache_ops.mco_icache_sync_all = (void (*)(void))cache_noop; mips_cache_ops.mco_icache_sync_range = cache_noop; mips_cache_ops.mco_icache_sync_range_index = cache_noop; break; #endif default: panic("no Icache ops for %d byte lines", cpuinfo->l1.ic_linesize); } switch (cpuinfo->l1.dc_linesize) { case 16: mips_cache_ops.mco_pdcache_wbinv_all = mips_cache_ops.mco_intern_pdcache_wbinv_all = mipsNN_pdcache_wbinv_all_16; mips_cache_ops.mco_pdcache_wbinv_range = mipsNN_pdcache_wbinv_range_16; mips_cache_ops.mco_pdcache_wbinv_range_index = mips_cache_ops.mco_intern_pdcache_wbinv_range_index = mipsNN_pdcache_wbinv_range_index_16; mips_cache_ops.mco_pdcache_inv_range = mipsNN_pdcache_inv_range_16; mips_cache_ops.mco_pdcache_wb_range = mips_cache_ops.mco_intern_pdcache_wb_range = mipsNN_pdcache_wb_range_16; break; case 32: mips_cache_ops.mco_pdcache_wbinv_all = mips_cache_ops.mco_intern_pdcache_wbinv_all = mipsNN_pdcache_wbinv_all_32; #if defined(CPU_RMI) || defined(CPU_NLM) mips_cache_ops.mco_pdcache_wbinv_range = cache_noop; #else mips_cache_ops.mco_pdcache_wbinv_range = mipsNN_pdcache_wbinv_range_32; #endif #if defined(CPU_RMI) || defined(CPU_NLM) mips_cache_ops.mco_pdcache_wbinv_range_index = mips_cache_ops.mco_intern_pdcache_wbinv_range_index = cache_noop; mips_cache_ops.mco_pdcache_inv_range = cache_noop; #else mips_cache_ops.mco_pdcache_wbinv_range_index = mips_cache_ops.mco_intern_pdcache_wbinv_range_index = mipsNN_pdcache_wbinv_range_index_32; mips_cache_ops.mco_pdcache_inv_range = mipsNN_pdcache_inv_range_32; #endif #if defined(CPU_RMI) || defined(CPU_NLM) mips_cache_ops.mco_pdcache_wb_range = mips_cache_ops.mco_intern_pdcache_wb_range = cache_noop; #else mips_cache_ops.mco_pdcache_wb_range = mips_cache_ops.mco_intern_pdcache_wb_range = mipsNN_pdcache_wb_range_32; #endif break; #ifdef CPU_CNMIPS case 128: mips_cache_ops.mco_pdcache_wbinv_all = mips_cache_ops.mco_intern_pdcache_wbinv_all = mipsNN_pdcache_wbinv_all_128; mips_cache_ops.mco_pdcache_wbinv_range = mipsNN_pdcache_wbinv_range_128; mips_cache_ops.mco_pdcache_wbinv_range_index = mips_cache_ops.mco_intern_pdcache_wbinv_range_index = mipsNN_pdcache_wbinv_range_index_128; mips_cache_ops.mco_pdcache_inv_range = mipsNN_pdcache_inv_range_128; mips_cache_ops.mco_pdcache_wb_range = mips_cache_ops.mco_intern_pdcache_wb_range = mipsNN_pdcache_wb_range_128; break; #endif #ifdef MIPS_DISABLE_L1_CACHE case 0: mips_cache_ops.mco_pdcache_wbinv_all = mips_cache_ops.mco_intern_pdcache_wbinv_all = (void (*)(void))cache_noop; mips_cache_ops.mco_pdcache_wbinv_range = cache_noop; mips_cache_ops.mco_pdcache_wbinv_range_index = cache_noop; mips_cache_ops.mco_intern_pdcache_wbinv_range_index = cache_noop; mips_cache_ops.mco_pdcache_inv_range = cache_noop; mips_cache_ops.mco_pdcache_wb_range = cache_noop; mips_cache_ops.mco_intern_pdcache_wb_range = cache_noop; break; #endif default: panic("no Dcache ops for %d byte lines", cpuinfo->l1.dc_linesize); } mipsNN_cache_init(cpuinfo); #if 0 if (mips_cpu_flags & (CPU_MIPS_D_CACHE_COHERENT | CPU_MIPS_I_D_CACHE_COHERENT)) { #ifdef CACHE_DEBUG printf(" Dcache is coherent\n"); #endif mips_cache_ops.mco_pdcache_wbinv_all = (void (*)(void))cache_noop; mips_cache_ops.mco_pdcache_wbinv_range = cache_noop; mips_cache_ops.mco_pdcache_wbinv_range_index = cache_noop; mips_cache_ops.mco_pdcache_inv_range = cache_noop; mips_cache_ops.mco_pdcache_wb_range = cache_noop; } if (mips_cpu_flags & CPU_MIPS_I_D_CACHE_COHERENT) { #ifdef CACHE_DEBUG printf(" Icache is coherent against Dcache\n"); #endif mips_cache_ops.mco_intern_pdcache_wbinv_all = (void (*)(void))cache_noop; mips_cache_ops.mco_intern_pdcache_wbinv_range_index = cache_noop; mips_cache_ops.mco_intern_pdcache_wb_range = cache_noop; } #endif /* Check that all cache ops are set up. */ /* must have primary Icache */ if (cpuinfo->l1.ic_size) { if (!mips_cache_ops.mco_icache_sync_all) panic("no icache_sync_all cache op"); if (!mips_cache_ops.mco_icache_sync_range) panic("no icache_sync_range cache op"); if (!mips_cache_ops.mco_icache_sync_range_index) panic("no icache_sync_range_index cache op"); } /* must have primary Dcache */ if (cpuinfo->l1.dc_size) { if (!mips_cache_ops.mco_pdcache_wbinv_all) panic("no pdcache_wbinv_all"); if (!mips_cache_ops.mco_pdcache_wbinv_range) panic("no pdcache_wbinv_range"); if (!mips_cache_ops.mco_pdcache_wbinv_range_index) panic("no pdcache_wbinv_range_index"); if (!mips_cache_ops.mco_pdcache_inv_range) panic("no pdcache_inv_range"); if (!mips_cache_ops.mco_pdcache_wb_range) panic("no pdcache_wb_range"); } - /* XXXMIPS: No secondary cache handlers yet */ -#ifdef notyet - if (mips_sdcache_size) { - if (!mips_cache_ops.mco_sdcache_wbinv_all) - panic("no sdcache_wbinv_all"); - if (!mips_cache_ops.mco_sdcache_wbinv_range) - panic("no sdcache_wbinv_range"); - if (!mips_cache_ops.mco_sdcache_wbinv_range_index) - panic("no sdcache_wbinv_range_index"); - if (!mips_cache_ops.mco_sdcache_inv_range) - panic("no sdcache_inv_range"); - if (!mips_cache_ops.mco_sdcache_wb_range) - panic("no sdcache_wb_range"); + /* L2 data cache */ + if (!cpuinfo->l2.dc_size) { + /* No L2 found, ignore */ + return; } + + switch (cpuinfo->l2.dc_linesize) { + case 32: + mips_cache_ops.mco_sdcache_wbinv_all = + mipsNN_sdcache_wbinv_all_32; + mips_cache_ops.mco_sdcache_wbinv_range = + mipsNN_sdcache_wbinv_range_32; + mips_cache_ops.mco_sdcache_wbinv_range_index = + mipsNN_sdcache_wbinv_range_index_32; + mips_cache_ops.mco_sdcache_inv_range = + mipsNN_sdcache_inv_range_32; + mips_cache_ops.mco_sdcache_wb_range = + mipsNN_sdcache_wb_range_32; + break; + case 128: + mips_cache_ops.mco_sdcache_wbinv_all = + mipsNN_sdcache_wbinv_all_128; + mips_cache_ops.mco_sdcache_wbinv_range = + mipsNN_sdcache_wbinv_range_128; + mips_cache_ops.mco_sdcache_wbinv_range_index = + mipsNN_sdcache_wbinv_range_index_128; + mips_cache_ops.mco_sdcache_inv_range = + mipsNN_sdcache_inv_range_128; + mips_cache_ops.mco_sdcache_wb_range = + mipsNN_sdcache_wb_range_128; + break; + default: +#ifdef CACHE_DEBUG + printf(" no sdcache ops for %d byte lines", + cpuinfo->l2.dc_linesize); #endif + break; + } } Index: head/sys/mips/mips/cache_mipsNN.c =================================================================== --- head/sys/mips/mips/cache_mipsNN.c (revision 274751) +++ head/sys/mips/mips/cache_mipsNN.c (revision 274752) @@ -1,638 +1,842 @@ /* $NetBSD: cache_mipsNN.c,v 1.10 2005/12/24 20:07:19 perry Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. * All rights reserved. * * Written by Jason R. Thorpe and 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #define round_line16(x) (((x) + 15) & ~15) #define trunc_line16(x) ((x) & ~15) #define round_line32(x) (((x) + 31) & ~31) #define trunc_line32(x) ((x) & ~31) +#define round_line128(x) (((x) + 127) & ~127) +#define trunc_line128(x) ((x) & ~127) + #if defined(CPU_NLM) static __inline void xlp_sync(void) { __asm __volatile ( ".set push \n" ".set noreorder \n" ".set mips64 \n" "dla $8, 1f \n" "/* jr.hb $8 */ \n" ".word 0x1000408 \n" "nop \n" "1: nop \n" ".set pop \n" : : : "$8"); } #endif #if defined(SB1250_PASS1) #define SYNC __asm volatile("sync; sync") #elif defined(CPU_NLM) #define SYNC xlp_sync() #else #define SYNC __asm volatile("sync") #endif #if defined(CPU_CNMIPS) #define SYNCI mips_sync_icache(); #elif defined(CPU_NLM) #define SYNCI xlp_sync() #else #define SYNCI #endif /* * Exported variables for consumers like bus_dma code */ int mips_picache_linesize; int mips_pdcache_linesize; static int picache_size; static int picache_stride; static int picache_loopcount; static int picache_way_mask; static int pdcache_size; static int pdcache_stride; static int pdcache_loopcount; static int pdcache_way_mask; +static int sdcache_size; +static int sdcache_stride; +static int sdcache_loopcount; +static int sdcache_way_mask; void mipsNN_cache_init(struct mips_cpuinfo * cpuinfo) { int flush_multiple_lines_per_way; flush_multiple_lines_per_way = cpuinfo->l1.ic_nsets * cpuinfo->l1.ic_linesize * cpuinfo->l1.ic_linesize > PAGE_SIZE; if (cpuinfo->icache_virtual) { /* * With a virtual Icache we don't need to flush * multiples of the page size with index ops; we just * need to flush one pages' worth. */ flush_multiple_lines_per_way = 0; } if (flush_multiple_lines_per_way) { picache_stride = PAGE_SIZE; picache_loopcount = (cpuinfo->l1.ic_nsets * cpuinfo->l1.ic_linesize / PAGE_SIZE) * cpuinfo->l1.ic_nways; } else { picache_stride = cpuinfo->l1.ic_nsets * cpuinfo->l1.ic_linesize; picache_loopcount = cpuinfo->l1.ic_nways; } if (cpuinfo->l1.dc_nsets * cpuinfo->l1.dc_linesize < PAGE_SIZE) { pdcache_stride = cpuinfo->l1.dc_nsets * cpuinfo->l1.dc_linesize; pdcache_loopcount = cpuinfo->l1.dc_nways; } else { pdcache_stride = PAGE_SIZE; pdcache_loopcount = (cpuinfo->l1.dc_nsets * cpuinfo->l1.dc_linesize / PAGE_SIZE) * cpuinfo->l1.dc_nways; } mips_picache_linesize = cpuinfo->l1.ic_linesize; mips_pdcache_linesize = cpuinfo->l1.dc_linesize; picache_size = cpuinfo->l1.ic_size; picache_way_mask = cpuinfo->l1.ic_nways - 1; pdcache_size = cpuinfo->l1.dc_size; pdcache_way_mask = cpuinfo->l1.dc_nways - 1; + sdcache_stride = cpuinfo->l2.dc_nsets * cpuinfo->l2.dc_linesize; + sdcache_loopcount = cpuinfo->l2.dc_nways; + sdcache_size = cpuinfo->l2.dc_size; + sdcache_way_mask = cpuinfo->l2.dc_nways - 1; + #define CACHE_DEBUG #ifdef CACHE_DEBUG printf("Cache info:\n"); if (cpuinfo->icache_virtual) printf(" icache is virtual\n"); printf(" picache_stride = %d\n", picache_stride); printf(" picache_loopcount = %d\n", picache_loopcount); printf(" pdcache_stride = %d\n", pdcache_stride); printf(" pdcache_loopcount = %d\n", pdcache_loopcount); #endif } void mipsNN_icache_sync_all_16(void) { vm_offset_t va, eva; va = MIPS_PHYS_TO_KSEG0(0); eva = va + picache_size; /* * Since we're hitting the whole thing, we don't have to * worry about the N different "ways". */ mips_intern_dcache_wbinv_all(); while (va < eva) { cache_r4k_op_32lines_16(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); va += (32 * 16); } SYNC; } void mipsNN_icache_sync_all_32(void) { vm_offset_t va, eva; va = MIPS_PHYS_TO_KSEG0(0); eva = va + picache_size; /* * Since we're hitting the whole thing, we don't have to * worry about the N different "ways". */ mips_intern_dcache_wbinv_all(); while (va < eva) { cache_r4k_op_32lines_32(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); va += (32 * 32); } SYNC; } void mipsNN_icache_sync_range_16(vm_offset_t va, vm_size_t size) { vm_offset_t eva; eva = round_line16(va + size); va = trunc_line16(va); mips_intern_dcache_wb_range(va, (eva - va)); while ((eva - va) >= (32 * 16)) { cache_r4k_op_32lines_16(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV); va += (32 * 16); } while (va < eva) { cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV); va += 16; } SYNC; } void mipsNN_icache_sync_range_32(vm_offset_t va, vm_size_t size) { vm_offset_t eva; eva = round_line32(va + size); va = trunc_line32(va); mips_intern_dcache_wb_range(va, (eva - va)); while ((eva - va) >= (32 * 32)) { cache_r4k_op_32lines_32(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV); va += (32 * 32); } while (va < eva) { cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV); va += 32; } SYNC; } void mipsNN_icache_sync_range_index_16(vm_offset_t va, vm_size_t size) { vm_offset_t eva, tmpva; int i, stride, loopcount; /* * Since we're doing Index ops, we expect to not be able * to access the address we've been given. So, get the * bits that determine the cache index, and make a KSEG0 * address out of them. */ va = MIPS_PHYS_TO_KSEG0(va & picache_way_mask); eva = round_line16(va + size); va = trunc_line16(va); /* * GCC generates better code in the loops if we reference local * copies of these global variables. */ stride = picache_stride; loopcount = picache_loopcount; mips_intern_dcache_wbinv_range_index(va, (eva - va)); while ((eva - va) >= (8 * 16)) { tmpva = va; for (i = 0; i < loopcount; i++, tmpva += stride) cache_r4k_op_8lines_16(tmpva, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); va += 8 * 16; } while (va < eva) { tmpva = va; for (i = 0; i < loopcount; i++, tmpva += stride) cache_op_r4k_line(tmpva, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); va += 16; } } void mipsNN_icache_sync_range_index_32(vm_offset_t va, vm_size_t size) { vm_offset_t eva, tmpva; int i, stride, loopcount; /* * Since we're doing Index ops, we expect to not be able * to access the address we've been given. So, get the * bits that determine the cache index, and make a KSEG0 * address out of them. */ va = MIPS_PHYS_TO_KSEG0(va & picache_way_mask); eva = round_line32(va + size); va = trunc_line32(va); /* * GCC generates better code in the loops if we reference local * copies of these global variables. */ stride = picache_stride; loopcount = picache_loopcount; mips_intern_dcache_wbinv_range_index(va, (eva - va)); while ((eva - va) >= (8 * 32)) { tmpva = va; for (i = 0; i < loopcount; i++, tmpva += stride) cache_r4k_op_8lines_32(tmpva, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); va += 8 * 32; } while (va < eva) { tmpva = va; for (i = 0; i < loopcount; i++, tmpva += stride) cache_op_r4k_line(tmpva, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV); va += 32; } } void mipsNN_pdcache_wbinv_all_16(void) { vm_offset_t va, eva; va = MIPS_PHYS_TO_KSEG0(0); eva = va + pdcache_size; /* * Since we're hitting the whole thing, we don't have to * worry about the N different "ways". */ while (va < eva) { cache_r4k_op_32lines_16(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); va += (32 * 16); } SYNC; } void mipsNN_pdcache_wbinv_all_32(void) { vm_offset_t va, eva; va = MIPS_PHYS_TO_KSEG0(0); eva = va + pdcache_size; /* * Since we're hitting the whole thing, we don't have to * worry about the N different "ways". */ while (va < eva) { cache_r4k_op_32lines_32(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); va += (32 * 32); } SYNC; } void mipsNN_pdcache_wbinv_range_16(vm_offset_t va, vm_size_t size) { vm_offset_t eva; eva = round_line16(va + size); va = trunc_line16(va); while ((eva - va) >= (32 * 16)) { cache_r4k_op_32lines_16(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV); va += (32 * 16); } while (va < eva) { cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV); va += 16; } SYNC; } void mipsNN_pdcache_wbinv_range_32(vm_offset_t va, vm_size_t size) { vm_offset_t eva; eva = round_line32(va + size); va = trunc_line32(va); while ((eva - va) >= (32 * 32)) { cache_r4k_op_32lines_32(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV); va += (32 * 32); } while (va < eva) { cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV); va += 32; } SYNC; } void mipsNN_pdcache_wbinv_range_index_16(vm_offset_t va, vm_size_t size) { vm_offset_t eva, tmpva; int i, stride, loopcount; /* * Since we're doing Index ops, we expect to not be able * to access the address we've been given. So, get the * bits that determine the cache index, and make a KSEG0 * address out of them. */ va = MIPS_PHYS_TO_KSEG0(va & pdcache_way_mask); eva = round_line16(va + size); va = trunc_line16(va); /* * GCC generates better code in the loops if we reference local * copies of these global variables. */ stride = pdcache_stride; loopcount = pdcache_loopcount; while ((eva - va) >= (8 * 16)) { tmpva = va; for (i = 0; i < loopcount; i++, tmpva += stride) cache_r4k_op_8lines_16(tmpva, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); va += 8 * 16; } while (va < eva) { tmpva = va; for (i = 0; i < loopcount; i++, tmpva += stride) cache_op_r4k_line(tmpva, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); va += 16; } } void mipsNN_pdcache_wbinv_range_index_32(vm_offset_t va, vm_size_t size) { vm_offset_t eva, tmpva; int i, stride, loopcount; /* * Since we're doing Index ops, we expect to not be able * to access the address we've been given. So, get the * bits that determine the cache index, and make a KSEG0 * address out of them. */ va = MIPS_PHYS_TO_KSEG0(va & pdcache_way_mask); eva = round_line32(va + size); va = trunc_line32(va); /* * GCC generates better code in the loops if we reference local * copies of these global variables. */ stride = pdcache_stride; loopcount = pdcache_loopcount; while ((eva - va) >= (8 * 32)) { tmpva = va; for (i = 0; i < loopcount; i++, tmpva += stride) cache_r4k_op_8lines_32(tmpva, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); va += 8 * 32; } while (va < eva) { tmpva = va; for (i = 0; i < loopcount; i++, tmpva += stride) cache_op_r4k_line(tmpva, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV); va += 32; } } void mipsNN_pdcache_inv_range_16(vm_offset_t va, vm_size_t size) { vm_offset_t eva; eva = round_line16(va + size); va = trunc_line16(va); while ((eva - va) >= (32 * 16)) { cache_r4k_op_32lines_16(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV); va += (32 * 16); } while (va < eva) { cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV); va += 16; } SYNC; } void mipsNN_pdcache_inv_range_32(vm_offset_t va, vm_size_t size) { vm_offset_t eva; eva = round_line32(va + size); va = trunc_line32(va); while ((eva - va) >= (32 * 32)) { cache_r4k_op_32lines_32(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV); va += (32 * 32); } while (va < eva) { cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV); va += 32; } SYNC; } void mipsNN_pdcache_wb_range_16(vm_offset_t va, vm_size_t size) { vm_offset_t eva; eva = round_line16(va + size); va = trunc_line16(va); while ((eva - va) >= (32 * 16)) { cache_r4k_op_32lines_16(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB); va += (32 * 16); } while (va < eva) { cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB); va += 16; } SYNC; } void mipsNN_pdcache_wb_range_32(vm_offset_t va, vm_size_t size) { vm_offset_t eva; eva = round_line32(va + size); va = trunc_line32(va); while ((eva - va) >= (32 * 32)) { cache_r4k_op_32lines_32(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB); va += (32 * 32); } while (va < eva) { cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB); va += 32; } SYNC; } #ifdef CPU_CNMIPS void mipsNN_icache_sync_all_128(void) { SYNCI } void mipsNN_icache_sync_range_128(vm_offset_t va, vm_size_t size) { SYNC; } void mipsNN_icache_sync_range_index_128(vm_offset_t va, vm_size_t size) { } void mipsNN_pdcache_wbinv_all_128(void) { } void mipsNN_pdcache_wbinv_range_128(vm_offset_t va, vm_size_t size) { SYNC; } void mipsNN_pdcache_wbinv_range_index_128(vm_offset_t va, vm_size_t size) { } void mipsNN_pdcache_inv_range_128(vm_offset_t va, vm_size_t size) { } void mipsNN_pdcache_wb_range_128(vm_offset_t va, vm_size_t size) { SYNC; } #endif + +void +mipsNN_sdcache_wbinv_all_32(void) +{ + vm_offset_t va = MIPS_PHYS_TO_KSEG0(0); + vm_offset_t eva = va + sdcache_size; + + while (va < eva) { + cache_r4k_op_32lines_32(va, + CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV); + va += (32 * 32); + } +} + +void +mipsNN_sdcache_wbinv_range_32(vm_offset_t va, vm_size_t size) +{ + vm_offset_t eva = round_line32(va + size); + + va = trunc_line32(va); + + while ((eva - va) >= (32 * 32)) { + cache_r4k_op_32lines_32(va, + CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV); + va += (32 * 32); + } + + while (va < eva) { + cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV); + va += 32; + } +} + +void +mipsNN_sdcache_wbinv_range_index_32(vm_offset_t va, vm_size_t size) +{ + vm_offset_t eva; + + /* + * Since we're doing Index ops, we expect to not be able + * to access the address we've been given. So, get the + * bits that determine the cache index, and make a KSEG0 + * address out of them. + */ + va = MIPS_PHYS_TO_KSEG0(va & (sdcache_size - 1)); + + eva = round_line32(va + size); + va = trunc_line32(va); + + while ((eva - va) >= (32 * 32)) { + cache_r4k_op_32lines_32(va, + CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV); + va += (32 * 32); + } + + while (va < eva) { + cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV); + va += 32; + } +} + +void +mipsNN_sdcache_inv_range_32(vm_offset_t va, vm_size_t size) +{ + vm_offset_t eva = round_line32(va + size); + + va = trunc_line32(va); + + while ((eva - va) >= (32 * 32)) { + cache_r4k_op_32lines_32(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV); + va += (32 * 32); + } + + while (va < eva) { + cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV); + va += 32; + } +} + +void +mipsNN_sdcache_wb_range_32(vm_offset_t va, vm_size_t size) +{ + vm_offset_t eva = round_line32(va + size); + + va = trunc_line32(va); + + while ((eva - va) >= (32 * 32)) { + cache_r4k_op_32lines_32(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB); + va += (32 * 32); + } + + while (va < eva) { + cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB); + va += 32; + } +} + +void +mipsNN_sdcache_wbinv_all_128(void) +{ + vm_offset_t va = MIPS_PHYS_TO_KSEG0(0); + vm_offset_t eva = va + sdcache_size; + + while (va < eva) { + cache_r4k_op_32lines_128(va, + CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV); + va += (32 * 128); + } +} + +void +mipsNN_sdcache_wbinv_range_128(vm_offset_t va, vm_size_t size) +{ + vm_offset_t eva = round_line128(va + size); + + va = trunc_line128(va); + + while ((eva - va) >= (32 * 128)) { + cache_r4k_op_32lines_128(va, + CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV); + va += (32 * 128); + } + + while (va < eva) { + cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV); + va += 128; + } +} + +void +mipsNN_sdcache_wbinv_range_index_128(vm_offset_t va, vm_size_t size) +{ + vm_offset_t eva; + + /* + * Since we're doing Index ops, we expect to not be able + * to access the address we've been given. So, get the + * bits that determine the cache index, and make a KSEG0 + * address out of them. + */ + va = MIPS_PHYS_TO_KSEG0(va & (sdcache_size - 1)); + + eva = round_line128(va + size); + va = trunc_line128(va); + + while ((eva - va) >= (32 * 128)) { + cache_r4k_op_32lines_128(va, + CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV); + va += (32 * 128); + } + + while (va < eva) { + cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV); + va += 128; + } +} + +void +mipsNN_sdcache_inv_range_128(vm_offset_t va, vm_size_t size) +{ + vm_offset_t eva = round_line128(va + size); + + va = trunc_line128(va); + + while ((eva - va) >= (32 * 128)) { + cache_r4k_op_32lines_128(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV); + va += (32 * 128); + } + + while (va < eva) { + cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV); + va += 128; + } +} + +void +mipsNN_sdcache_wb_range_128(vm_offset_t va, vm_size_t size) +{ + vm_offset_t eva = round_line128(va + size); + + va = trunc_line128(va); + + while ((eva - va) >= (32 * 128)) { + cache_r4k_op_32lines_128(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB); + va += (32 * 128); + } + + while (va < eva) { + cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB); + va += 128; + } +} Index: head/sys/mips/mips/cpu.c =================================================================== --- head/sys/mips/mips/cpu.c (revision 274751) +++ head/sys/mips/mips/cpu.c (revision 274752) @@ -1,436 +1,463 @@ /*- * Copyright (c) 2004 Juli Mallett. All rights reserved. * * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(CPU_CNMIPS) #include #include #endif static void cpu_identify(void); struct mips_cpuinfo cpuinfo; /* * Attempt to identify the MIPS CPU as much as possible. * * XXX: Assumes the CPU is MIPS{32,64}{,r2} compliant. * XXX: For now, skip config register selections 2 and 3 * as we don't currently use L2/L3 cache or additional * MIPS32 processor features. */ static void mips_get_identity(struct mips_cpuinfo *cpuinfo) { u_int32_t prid; u_int32_t cfg0; u_int32_t cfg1; + u_int32_t cfg2; #if defined(CPU_CNMIPS) u_int32_t cfg4; #endif u_int32_t tmp; memset(cpuinfo, 0, sizeof(struct mips_cpuinfo)); /* Read and store the PrID ID for CPU identification. */ prid = mips_rd_prid(); cpuinfo->cpu_vendor = MIPS_PRID_CID(prid); cpuinfo->cpu_rev = MIPS_PRID_REV(prid); cpuinfo->cpu_impl = MIPS_PRID_IMPL(prid); /* Read config register selection 0 to learn TLB type. */ cfg0 = mips_rd_config(); cpuinfo->tlb_type = ((cfg0 & MIPS_CONFIG0_MT_MASK) >> MIPS_CONFIG0_MT_SHIFT); cpuinfo->icache_virtual = cfg0 & MIPS_CONFIG0_VI; /* If config register selection 1 does not exist, exit. */ if (!(cfg0 & MIPS_CONFIG_CM)) return; /* Learn TLB size and L1 cache geometry. */ cfg1 = mips_rd_config1(); #if defined(CPU_NLM) /* Account for Extended TLB entries in XLP */ tmp = mips_rd_config6(); cpuinfo->tlb_nentries = ((tmp >> 16) & 0xffff) + 1; #elif defined(BERI_LARGE_TLB) /* Check if we support extended TLB entries and if so activate. */ tmp = mips_rd_config5(); #define BERI_CP5_LTLB_SUPPORTED 0x1 if (tmp & BERI_CP5_LTLB_SUPPORTED) { /* See how many extra TLB entries we have. */ tmp = mips_rd_config6(); cpuinfo->tlb_nentries = (tmp >> 16) + 1; /* Activate the extended entries. */ mips_wr_config6(tmp|0x4); } else #endif #if !defined(CPU_NLM) cpuinfo->tlb_nentries = ((cfg1 & MIPS_CONFIG1_TLBSZ_MASK) >> MIPS_CONFIG1_TLBSZ_SHIFT) + 1; #endif #if defined(CPU_CNMIPS) /* Add extended TLB size information from config4. */ cfg4 = mips_rd_config4(); if ((cfg4 & MIPS_CONFIG4_MMUEXTDEF) == MIPS_CONFIG4_MMUEXTDEF_MMUSIZEEXT) cpuinfo->tlb_nentries += (cfg4 & MIPS_CONFIG4_MMUSIZEEXT) * 0x40; #endif /* L1 instruction cache. */ #ifdef MIPS_DISABLE_L1_CACHE cpuinfo->l1.ic_linesize = 0; #else tmp = (cfg1 & MIPS_CONFIG1_IL_MASK) >> MIPS_CONFIG1_IL_SHIFT; if (tmp != 0) { cpuinfo->l1.ic_linesize = 1 << (tmp + 1); cpuinfo->l1.ic_nways = (((cfg1 & MIPS_CONFIG1_IA_MASK) >> MIPS_CONFIG1_IA_SHIFT)) + 1; cpuinfo->l1.ic_nsets = 1 << (((cfg1 & MIPS_CONFIG1_IS_MASK) >> MIPS_CONFIG1_IS_SHIFT) + 6); } #endif /* L1 data cache. */ #ifdef MIPS_DISABLE_L1_CACHE cpuinfo->l1.dc_linesize = 0; #else #ifndef CPU_CNMIPS tmp = (cfg1 & MIPS_CONFIG1_DL_MASK) >> MIPS_CONFIG1_DL_SHIFT; if (tmp != 0) { cpuinfo->l1.dc_linesize = 1 << (tmp + 1); cpuinfo->l1.dc_nways = (((cfg1 & MIPS_CONFIG1_DA_MASK) >> MIPS_CONFIG1_DA_SHIFT)) + 1; cpuinfo->l1.dc_nsets = 1 << (((cfg1 & MIPS_CONFIG1_DS_MASK) >> MIPS_CONFIG1_DS_SHIFT) + 6); } #else /* * Some Octeon cache configuration parameters are by model family, not * config1. */ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { /* Octeon and Octeon XL. */ cpuinfo->l1.dc_nsets = 1; cpuinfo->l1.dc_nways = 64; } else if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) { /* Octeon Plus. */ cpuinfo->l1.dc_nsets = 2; cpuinfo->l1.dc_nways = 64; } else if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) { /* Octeon II. */ cpuinfo->l1.dc_nsets = 8; cpuinfo->l1.dc_nways = 32; cpuinfo->l1.ic_nsets = 8; cpuinfo->l1.ic_nways = 37; } else { panic("%s: unsupported Cavium Networks CPU.", __func__); } /* All Octeon models use 128 byte line size. */ cpuinfo->l1.dc_linesize = 128; #endif #endif cpuinfo->l1.ic_size = cpuinfo->l1.ic_linesize * cpuinfo->l1.ic_nsets * cpuinfo->l1.ic_nways; cpuinfo->l1.dc_size = cpuinfo->l1.dc_linesize * cpuinfo->l1.dc_nsets * cpuinfo->l1.dc_nways; + +#ifndef CPU_CNMIPS + /* L2 cache */ + if (!(cfg1 & MIPS_CONFIG_CM)) { + /* We don't have valid cfg2 register */ + return; + } + + cfg2 = mips_rd_config2(); + + tmp = (cfg2 >> MIPS_CONFIG2_SL_SHIFT) & MIPS_CONFIG2_SL_MASK; + if (0 < tmp && tmp <= 7) + cpuinfo->l2.dc_linesize = 2 << tmp; + + tmp = (cfg2 >> MIPS_CONFIG2_SS_SHIFT) & MIPS_CONFIG2_SS_MASK; + if (0 <= tmp && tmp <= 7) + cpuinfo->l2.dc_nsets = 64 << tmp; + + tmp = (cfg2 >> MIPS_CONFIG2_SA_SHIFT) & MIPS_CONFIG2_SA_MASK; + if (0 <= tmp && tmp <= 7) + cpuinfo->l2.dc_nways = tmp + 1; + + cpuinfo->l2.dc_size = cpuinfo->l2.dc_linesize + * cpuinfo->l2.dc_nsets * cpuinfo->l2.dc_nways; +#endif } void mips_cpu_init(void) { platform_cpu_init(); mips_get_identity(&cpuinfo); num_tlbentries = cpuinfo.tlb_nentries; mips_wr_wired(0); tlb_invalidate_all(); mips_wr_wired(VMWIRED_ENTRIES); mips_config_cache(&cpuinfo); mips_vector_init(); mips_icache_sync_all(); mips_dcache_wbinv_all(); /* Print some info about CPU */ cpu_identify(); } static void cpu_identify(void) { uint32_t cfg0, cfg1, cfg2, cfg3; printf("cpu%d: ", 0); /* XXX per-cpu */ switch (cpuinfo.cpu_vendor) { case MIPS_PRID_CID_MTI: printf("MIPS Technologies"); break; case MIPS_PRID_CID_BROADCOM: case MIPS_PRID_CID_SIBYTE: printf("Broadcom"); break; case MIPS_PRID_CID_ALCHEMY: printf("AMD"); break; case MIPS_PRID_CID_SANDCRAFT: printf("Sandcraft"); break; case MIPS_PRID_CID_PHILIPS: printf("Philips"); break; case MIPS_PRID_CID_TOSHIBA: printf("Toshiba"); break; case MIPS_PRID_CID_LSI: printf("LSI"); break; case MIPS_PRID_CID_LEXRA: printf("Lexra"); break; case MIPS_PRID_CID_RMI: printf("RMI"); break; case MIPS_PRID_CID_CAVIUM: printf("Cavium"); break; case MIPS_PRID_CID_PREHISTORIC: default: printf("Unknown cid %#x", cpuinfo.cpu_vendor); break; } printf(" processor v%d.%d\n", cpuinfo.cpu_rev, cpuinfo.cpu_impl); printf(" MMU: "); if (cpuinfo.tlb_type == MIPS_MMU_NONE) { printf("none present\n"); } else { if (cpuinfo.tlb_type == MIPS_MMU_TLB) { printf("Standard TLB"); } else if (cpuinfo.tlb_type == MIPS_MMU_BAT) { printf("Standard BAT"); } else if (cpuinfo.tlb_type == MIPS_MMU_FIXED) { printf("Fixed mapping"); } printf(", %d entries\n", cpuinfo.tlb_nentries); } printf(" L1 i-cache: "); if (cpuinfo.l1.ic_linesize == 0) { printf("disabled"); } else { if (cpuinfo.l1.ic_nways == 1) { printf("direct-mapped with"); } else { printf ("%d ways of", cpuinfo.l1.ic_nways); } printf(" %d sets, %d bytes per line\n", cpuinfo.l1.ic_nsets, cpuinfo.l1.ic_linesize); } printf(" L1 d-cache: "); if (cpuinfo.l1.dc_linesize == 0) { printf("disabled"); } else { if (cpuinfo.l1.dc_nways == 1) { printf("direct-mapped with"); } else { printf ("%d ways of", cpuinfo.l1.dc_nways); } printf(" %d sets, %d bytes per line\n", cpuinfo.l1.dc_nsets, cpuinfo.l1.dc_linesize); } cfg0 = mips_rd_config(); /* If config register selection 1 does not exist, exit. */ if (!(cfg0 & MIPS_CONFIG_CM)) return; cfg1 = mips_rd_config1(); printf(" Config1=0x%b\n", cfg1, "\20\7COP2\6MDMX\5PerfCount\4WatchRegs\3MIPS16\2EJTAG\1FPU"); /* If config register selection 2 does not exist, exit. */ if (!(cfg1 & MIPS_CONFIG_CM)) return; cfg2 = mips_rd_config2(); /* * Config2 contains no useful information other then Config3 * existence flag */ /* If config register selection 3 does not exist, exit. */ if (!(cfg2 & MIPS_CONFIG_CM)) return; cfg3 = mips_rd_config3(); /* Print Config3 if it contains any useful info */ if (cfg3 & ~(0x80000000)) printf(" Config3=0x%b\n", cfg3, "\20\2SmartMIPS\1TraceLogic"); } static struct rman cpu_hardirq_rman; static devclass_t cpu_devclass; /* * Device methods */ static int cpu_probe(device_t); static int cpu_attach(device_t); static struct resource *cpu_alloc_resource(device_t, device_t, int, int *, u_long, u_long, u_long, u_int); static int cpu_setup_intr(device_t, device_t, struct resource *, int, driver_filter_t *f, driver_intr_t *, void *, void **); static device_method_t cpu_methods[] = { /* Device interface */ DEVMETHOD(device_probe, cpu_probe), DEVMETHOD(device_attach, cpu_attach), DEVMETHOD(device_detach, bus_generic_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), /* Bus interface */ DEVMETHOD(bus_alloc_resource, cpu_alloc_resource), DEVMETHOD(bus_setup_intr, cpu_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), { 0, 0 } }; static driver_t cpu_driver = { "cpu", cpu_methods, 1 }; static int cpu_probe(device_t dev) { + return (0); } static int cpu_attach(device_t dev) { int error; #ifdef notyet device_t clock; #endif cpu_hardirq_rman.rm_start = 0; cpu_hardirq_rman.rm_end = 5; cpu_hardirq_rman.rm_type = RMAN_ARRAY; cpu_hardirq_rman.rm_descr = "CPU Hard Interrupts"; error = rman_init(&cpu_hardirq_rman); if (error != 0) { device_printf(dev, "failed to initialize irq resources\n"); return (error); } /* XXX rman_manage_all. */ error = rman_manage_region(&cpu_hardirq_rman, cpu_hardirq_rman.rm_start, cpu_hardirq_rman.rm_end); if (error != 0) { device_printf(dev, "failed to manage irq resources\n"); return (error); } if (device_get_unit(dev) != 0) panic("can't attach more cpus"); device_set_desc(dev, "MIPS32 processor"); #ifdef notyet clock = device_add_child(dev, "clock", device_get_unit(dev)); if (clock == NULL) device_printf(dev, "clock failed to attach"); #endif return (bus_generic_attach(dev)); } static struct resource * cpu_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct resource *res; if (type != SYS_RES_IRQ) return (NULL); res = rman_reserve_resource(&cpu_hardirq_rman, start, end, count, 0, child); return (res); } static int cpu_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *handler, void *arg, void **cookiep) { int error; int intr; error = rman_activate_resource(res); if (error != 0) { device_printf(child, "could not activate irq\n"); return (error); } intr = rman_get_start(res); cpu_establish_hardintr(device_get_nameunit(child), filt, handler, arg, intr, flags, cookiep); device_printf(child, "established CPU interrupt %d\n", intr); return (0); } DRIVER_MODULE(cpu, root, cpu_driver, cpu_devclass, 0, 0);