diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-08-06 21:11:40 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-08-06 21:11:40 +0000 |
commit | feb56279b5746ffb588937f722b9644f732a7941 (patch) | |
tree | 0a2ffc7a955bb2dc83f755937af9f251b1b9badd | |
parent | 5b4cb6fccc3045f34fae9a21c38dee82e0843b13 (diff) |
Work in progress support for Loongson2E/2F processors; need option CPU_LOONGSON2
in the kernel to be brought in, due to invasive differences in tlb operation.
Comes with a separate cache operations file due to the cache being R5k-style
with R10k-style way number encoding.
-rw-r--r-- | sys/arch/mips64/conf/files.mips64 | 3 | ||||
-rw-r--r-- | sys/arch/mips64/include/archtype.h | 25 | ||||
-rw-r--r-- | sys/arch/mips64/include/cpu.h | 17 | ||||
-rw-r--r-- | sys/arch/mips64/include/loongson2.h | 60 | ||||
-rw-r--r-- | sys/arch/mips64/mips64/cache_loongson2.S | 607 | ||||
-rw-r--r-- | sys/arch/mips64/mips64/context.S | 18 | ||||
-rw-r--r-- | sys/arch/mips64/mips64/cpu.c | 31 | ||||
-rw-r--r-- | sys/arch/mips64/mips64/tlbhandler.S | 89 |
8 files changed, 824 insertions, 26 deletions
diff --git a/sys/arch/mips64/conf/files.mips64 b/sys/arch/mips64/conf/files.mips64 index 251518297f7..2c90943b4bb 100644 --- a/sys/arch/mips64/conf/files.mips64 +++ b/sys/arch/mips64/conf/files.mips64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.mips64,v 1.11 2009/06/13 21:48:01 miod Exp $ +# $OpenBSD: files.mips64,v 1.12 2009/08/06 21:11:37 miod Exp $ file arch/mips64/mips64/arcbios.c arcbios file arch/mips64/mips64/clock.c @@ -13,6 +13,7 @@ file arch/mips64/mips64/sys_machdep.c file arch/mips64/mips64/trap.c file arch/mips64/mips64/vm_machdep.c +file arch/mips64/mips64/cache_loongson2.S cpu_loongson2 file arch/mips64/mips64/cache_r5k.S file arch/mips64/mips64/cache_r10k.S file arch/mips64/mips64/context.S diff --git a/sys/arch/mips64/include/archtype.h b/sys/arch/mips64/include/archtype.h index 6700ded45a8..7898f297275 100644 --- a/sys/arch/mips64/include/archtype.h +++ b/sys/arch/mips64/include/archtype.h @@ -1,4 +1,4 @@ -/* $OpenBSD: archtype.h,v 1.6 2009/04/19 12:52:31 miod Exp $ */ +/* $OpenBSD: archtype.h,v 1.7 2009/08/06 21:11:38 miod Exp $ */ /* * Copyright (c) 1997-2004 Opsycon AB, Sweden (www.opsycon.se) * @@ -30,16 +30,16 @@ /* * Define architectural identities for the different Mips machines. */ -#define ARC_CLASS 0x0000 /* Arch class ARC */ +#define ARC_CLASS 0x0000 /* ARC class */ #define ACER_PICA_61 0x0001 /* Acer Labs Pica 61 */ #define MAGNUM 0x0002 /* Mips MAGNUM R4000 */ -#define DESKSTATION_RPC44 0x0003 /* Deskstation xxx */ -#define DESKSTATION_TYNE 0x0004 /* Deskstation xxx */ +#define DESKSTATION_RPC44 0x0003 /* Deskstation rPC44 */ +#define DESKSTATION_TYNE 0x0004 /* Deskstation Tyne */ #define NKK_AQUARIUS 0x0005 /* NKK R4{67}00 PC */ #define NEC_R94 0x0006 /* NEC Magnum class */ #define SNI_RM200 0x0007 /* Siemens Nixdorf RM200 */ -#define SGI_CLASS 0x0010 /* Silicon Graphics Class */ +#define SGI_CLASS 0x0010 /* Silicon Graphics class */ #define SGI_CRIMSON 0x0011 /* Crimson */ #define SGI_ONYX 0x0012 /* Onyx (!S model Challenge) */ #define SGI_INDIGO 0x0013 /* Indigo */ @@ -52,18 +52,18 @@ #define SGI_O2000 0x001a /* IP27 Origin2000/Lego */ #define SGI_OCTANE 0x001b /* IP30 Octane/Speedracer */ #define SGI_O300 0x001c /* IP35 Origin300, Onyx3, Fuel */ -#define SGI_O3000 0x001d /* IP35 Origin3000, Tezro */ +#define SGI_O3000 0x001d /* IP35 Origin350, Tezro */ -#define ALGOR_CLASS 0x0020 /* Algorithmics Class */ +#define ALGOR_CLASS 0x0020 /* Algorithmics class */ #define ALGOR_P4032 0x0021 /* ALGORITHMICS P-4032 */ #define ALGOR_P5064 0x0022 /* ALGORITHMICS P-5064 */ -#define GALILEO_CLASS 0x0030 /* Galileo PCI based Class */ +#define GALILEO_CLASS 0x0030 /* Galileo PCI based class */ #define GALILEO_G9 0x0031 /* Galileo GT-64011 Eval board */ #define GALILEO_EV64240 0x0032 /* Galileo EV64240 Eval board */ #define GALILEO_EV64340 0x0033 /* Galileo EV64340 Eval board */ -#define MOMENTUM_CLASS 0x0040 /* Momentum Inc Class */ +#define MOMENTUM_CLASS 0x0040 /* Momentum Inc class */ #define MOMENTUM_CP7000 0x0041 /* Momentum Ocelot */ #define MOMENTUM_CP7000G 0x0042 /* Momentum Ocelot-G */ #define MOMENTUM_JAGUAR 0x0043 /* Momentum Jaguar ATX */ @@ -79,8 +79,11 @@ #define WG8200 0x0059 /* Willowglen CPU-8200 */ #define WG8232 0x005a /* Willowglen CPU-8232 */ -#define MISC_CLASS 0x00F0 /* Misc machines... */ -#define LAGUNA 0x00F1 /* Heurikon Laguna VME board */ +#define LOONGSON_CLASS 0x0060 /* Loongson + PMON2000 class */ +#define LOONGSON_YEELONG 0x0061 /* Lemote Yeelong */ + +#define MISC_CLASS 0x00f0 /* Misc machines... */ +#define LAGUNA 0x00f1 /* Heurikon Laguna VME board */ #define ARCHCLASS(n) ((n) & 0xf0) diff --git a/sys/arch/mips64/include/cpu.h b/sys/arch/mips64/include/cpu.h index f16edec4b76..f78d45326e6 100644 --- a/sys/arch/mips64/include/cpu.h +++ b/sys/arch/mips64/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.33 2009/06/10 18:05:30 miod Exp $ */ +/* $OpenBSD: cpu.h,v 1.34 2009/08/06 21:11:38 miod Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -240,6 +240,7 @@ extern vaddr_t uncached_base; #define COP_0_WATCH_HI $19 #define COP_0_TLB_XCONTEXT $20 #define COP_0_TLB_FR_MASK $21 /* R10000 onwards */ +#define COP_0_DIAG $22 /* Loongson 2F */ #define COP_0_ECC $26 #define COP_0_CACHE_ERR $27 #define COP_0_TAG_LO $28 @@ -467,7 +468,9 @@ extern int int_nest_cntr; #define MIPS_RM7000 0x27 /* PMCS RM7000 CPU ISA IV */ #define MIPS_RM52X0 0x28 /* PMCS RM52X0 CPU ISA IV */ #define MIPS_RM9000 0x34 /* PMCS RM9000 CPU ISA IV */ +#define MIPS_LOONGSON 0x42 /* STC LoongSon CPU ISA III */ #define MIPS_VR5400 0x54 /* NEC Vr5400 CPU ISA IV+ */ +#define MIPS_LOONGSON2 0x63 /* STC LoongSon2 CPU ISA III */ /* * MIPS FPU types. Only soft, rest is the same as cpu type. @@ -509,8 +512,6 @@ void cp0_set_compare(u_int); #define Mips_SyncCache() (*(sys_config._SyncCache))() #define Mips_InvalidateICache(a, l) \ (*(sys_config._InvalidateICache))((a), (l)) -#define Mips_InvalidateICachePage(a) \ - (*(sys_config._InvalidateICachePage))((a)) #define Mips_SyncDCachePage(a) \ (*(sys_config._SyncDCachePage))((a)) #define Mips_HitSyncDCache(a, l) \ @@ -520,10 +521,17 @@ void cp0_set_compare(u_int); #define Mips_HitInvalidateDCache(a, l) \ (*(sys_config._HitInvalidateDCache))((a), (l)) +int Loongson2_ConfigCache(void); +void Loongson2_SyncCache(void); +void Loongson2_InvalidateICache(vaddr_t, int); +void Loongson2_SyncDCachePage(vaddr_t); +void Loongson2_HitSyncDCache(vaddr_t, int); +void Loongson2_IOSyncDCache(vaddr_t, int, int); +void Loongson2_HitInvalidateDCache(vaddr_t, int); + int Mips5k_ConfigCache(void); void Mips5k_SyncCache(void); void Mips5k_InvalidateICache(vaddr_t, int); -void Mips5k_InvalidateICachePage(vaddr_t); void Mips5k_SyncDCachePage(vaddr_t); void Mips5k_HitSyncDCache(vaddr_t, int); void Mips5k_IOSyncDCache(vaddr_t, int, int); @@ -532,7 +540,6 @@ void Mips5k_HitInvalidateDCache(vaddr_t, int); int Mips10k_ConfigCache(void); void Mips10k_SyncCache(void); void Mips10k_InvalidateICache(vaddr_t, int); -void Mips10k_InvalidateICachePage(vaddr_t); void Mips10k_SyncDCachePage(vaddr_t); void Mips10k_HitSyncDCache(vaddr_t, int); void Mips10k_IOSyncDCache(vaddr_t, int, int); diff --git a/sys/arch/mips64/include/loongson2.h b/sys/arch/mips64/include/loongson2.h new file mode 100644 index 00000000000..750658af94f --- /dev/null +++ b/sys/arch/mips64/include/loongson2.h @@ -0,0 +1,60 @@ +/* $OpenBSD: loongson2.h,v 1.1 2009/08/06 21:11:38 miod Exp $ */ + +/* + * Copyright (c) 2009 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_LOONGSON2_H_ +#define _MACHINE_LOONGSON2_H_ + +/* + * Loongson 2E/2F specific defines + */ + +/* + * Address Window registers physical addresses + * + * The Loongson 2F processor has an AXI crossbar with four possible bus + * masters, each one having four programmable address windows. + * + * Each window is defined with three 64-bit registers: + * - a base address register, defining the address in the master address + * space (base register). + * - an address mask register, defining which address bits are valid in this + * window. A given address matches a window if (addr & mask) == base. + * - the location of the window base in the target, as well at the target + * number itself (mmap register). The lower 20 bits of the address are + * forced as zeroes regardless of their value in this register. + * The translated address is thus (addr & ~mask) | (mmap & ~0xfffff). + */ + +#define LOONGSON_AWR_BASE_ADDRESS 0x3ff00000 + +#define LOONGSON_AWR_BASE(master, window) \ + (LOONGSON_AWR_BASE_ADDRESS + (window) * 0x08 + (master) * 0x60 + 0x00) +#define LOONGSON_AWR_SIZE(master, window) \ + (LOONGSON_AWR_BASE_ADDRESS + (window) * 0x08 + (master) * 0x60 + 0x20) +#define LOONGSON_AWR_MMAP(master, window) \ + (LOONGSON_AWR_BASE_ADDRESS + (window) * 0x08 + (master) * 0x60 + 0x40) + +/* + * Bits in the diagnostic register + */ + +#define COP_0_DIAG_ITLB_CLEAR 0x04 +#define COP_0_DIAG_BTB_CLEAR 0x02 +#define COP_0_DIAG_RAS_CLEAR 0x01 + +#endif /* _MACHINE_LOONGSON2_H_ */ diff --git a/sys/arch/mips64/mips64/cache_loongson2.S b/sys/arch/mips64/mips64/cache_loongson2.S new file mode 100644 index 00000000000..8b35fe779e6 --- /dev/null +++ b/sys/arch/mips64/mips64/cache_loongson2.S @@ -0,0 +1,607 @@ +/* $OpenBSD: cache_loongson2.S,v 1.1 2009/08/06 21:11:39 miod Exp $ */ + +/* + * Copyright (c) 2009 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 1998-2004 Opsycon AB (www.opsycon.se) + * + * 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 ``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 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. + * + */ + +/* + * Processors supported: + * Loongson 2E/2F + */ + +#include <sys/syscall.h> + +#include <machine/param.h> +#include <machine/asm.h> +#include <machine/cpu.h> +#include <machine/regnum.h> + +#include "assym.h" + + .set mips3 + +#define LOAD_XKPHYS(reg, cca) \ + li reg, cca | 0x10; \ + dsll reg, reg, 59 + +/* + * Skip the .h file. Noone else need to know! + */ + +#define IndexInvalidate_I 0x00 +#define IndexWBInvalidate_D 0x01 +#define IndexWBInvalidate_S 0x03 + +#define IndexLoadTag_I 0x04 +#define IndexLoadTag_D 0x05 +#define IndexLoadTag_S 0x07 + +#define IndexStoreTag_I 0x08 +#define IndexStoreTag_D 0x09 +#define IndexStoreTag_S 0x0b + +#define HitInvalidate_D 0x11 +#define HitInvalidate_S 0x13 + +#define Fill_I 0x14 +#define HitWBInvalidate_D 0x15 +#define HitWBInvalidate_S 0x17 + +#define HitWB_I 0x18 +#define HitWB_D 0x19 +#define HitWB_S 0x1b + +/* + * Define cache type definition bits. NOTE! the 3 lsb may NOT change! + */ +#define CTYPE_DIR 0x0001 /* Cache is direct mapped */ +#define CTYPE_2WAY 0x0002 /* Cache is TWO way */ +#define CTYPE_4WAY 0x0004 /* Cache is FOUR way */ +#define CTYPE_WAYMASK 0x0007 + +#define CTYPE_HAS_IL2 0x0100 /* Internal L2 Cache present */ +#define CTYPE_HAS_XL2 0x0200 /* External L2 Cache present */ +#define CTYPE_HAS_XL3 0x0400 /* External L3 Cache present */ + + .set noreorder # Noreorder is default style! + +/*---------------------------------------------------------------------------- + * + * Loongson2_ConfigCache -- + * + * Size and configure the caches. + * NOTE: should only be called from mips_init(). + * + * Side effects: + * The size of the data cache is stored into CpuPrimaryDataCacheSize. + * The size of instruction cache is stored into CpuPrimaryInstCacheSize. + * Alignment mask for cache aliasing test is stored in CpuCacheAliasMask. + * CpuSecondaryCacheSize is set to the size of the secondary cache. + * CpuTertiaryCacheSize is set to the size of the tertiary cache. + * CpuNWayCache is set to 0 for direct mapped caches, 2 for two way + * caches and 4 for four way caches. This primarily indicates the + * primary cache associativity. + * + * Allocation: + * ta0, ta1 ta2 used to hold I and D set size and Alias mask. + * + *---------------------------------------------------------------------------- + */ +LEAF(Loongson2_ConfigCache, 0) + .set noreorder + LA v0, 1f + LA v1, KSEG1_BASE + or v0, v1 + jr v0 # Switch to uncached. + nop +1: + mfc0 v0, COP_0_CONFIG # Get configuration register + + srl t1, v0, 9 # Get I cache size. + and t1, 7 + li t2, 4096 + sllv ta0, t2, t1 # ta0 = Initial I set size. + + and t2, v0, 0x20 + srl t2, t2, 1 # Get I cache line size. + addu t2, t2, 16 + sw t2, CpuPrimaryInstCacheLSize + + srl t1, v0, 6 # Get D cache size. + and t1, 7 + li t2, 4096 # Fixed page size. + sllv ta1, t2, t1 + + and t2, v0, 0x10 + addu t2, t2, 16 # Get D cache line size. + sw t2, CpuPrimaryDataCacheLSize + + li ta3, 0 # Tertiary size 0. + + LOAD_XKPHYS(t0, CCA_CACHED) + li ta2, 128 * 1024 # fixed L2 size... + PTR_ADDU t1, t0, ta2 + sll ta2, 2 # ...is 512KB +1: + cache IndexWBInvalidate_S, 0(t0) + cache IndexWBInvalidate_S, 1(t0) + cache IndexWBInvalidate_S, 2(t0) + cache IndexWBInvalidate_S, 3(t0) + PTR_ADDU t0, t0, 32 + bne t0, t1, 1b + nop + + li t2, (CTYPE_4WAY|CTYPE_HAS_IL2) # caches are 4-way, internal L2 + +/* + * Get here with t2 = Cache type, ta0 = L1 I size, ta1 = L1 D size. + * ta2 = secondary size, ta3 = tertiary size. + */ +ConfResult: + sw v0, CpuConfigRegister + mfc0 t3, COP_0_STATUS_REG + sw t2, CpuCacheType # Save cache attributes + sw t3, CpuStatusRegister + and t2, CTYPE_WAYMASK # isolate number of sets. + sw t2, CpuNWayCache + srl t2, 1 # get div shift for set size. + + sw ta2, CpuSecondaryCacheSize + sw ta3, CpuTertiaryCacheSize + + addu t1, ta0, -1 # Use icache for alias mask + srl t1, t2 # Some cpus have different + and t1, ~(NBPG - 1) # i and d cache sizes... + sw t1, CpuCacheAliasMask + + sw ta0, CpuPrimaryInstCacheSize # store cache size. + sw ta1, CpuPrimaryDataCacheSize # store cache size. + + /* Loongson 2E/2F: cache way information is in the lowest bits */ + sw zero, CpuPrimaryInstSetSize + li ta1, 1 + sw ta1, CpuPrimaryDataSetSize + + and v0, ~7 + or v0, CCA_CACHED # set cachable writeback kseg0 + mtc0 v0, COP_0_CONFIG # establish any new config + j ra + nop +END(Loongson2_ConfigCache) + +/*---------------------------------------------------------------------------- + * + * Loongson2_SyncCache -- + * + * Sync ALL caches. + * No need to look at number of sets since we are cleaning out + * the entire cache and thus will address all sets anyway. + * + * Results: + * None. + * + * Side effects: + * The contents of ALL caches are Invalidated or Synched. + * + *---------------------------------------------------------------------------- + */ +LEAF(Loongson2_SyncCache, 0) + .set noreorder + lw t1, CpuPrimaryInstCacheSize + lw t2, CpuPrimaryDataCacheSize + +/* + * Sync the instruction cache. + */ + LOAD_XKPHYS(t0, CCA_CACHED) + PTR_ADDU t1, t0, t1 # Compute end address + PTR_SUBU t1, 128 + +1: + cache IndexInvalidate_I, 0(t0) + cache IndexInvalidate_I, 32(t0) + cache IndexInvalidate_I, 64(t0) + cache IndexInvalidate_I, 96(t0) + + bne t0, t1, 1b + PTR_ADDU t0, t0, 128 + +/* + * Sync the data cache. Do L1 first. Indexed only operate on + * the selected cache and differs from Hit in that sense. + */ + + LOAD_XKPHYS(t0, CCA_CACHED) + PTR_ADDU t1, t0, t2 # End address + PTR_SUBU t1, t1, 128 +1: + cache IndexWBInvalidate_D, 0(t0) + cache IndexWBInvalidate_D, 32(t0) + cache IndexWBInvalidate_D, 64(t0) + cache IndexWBInvalidate_D, 96(t0) + + bne t0, t1, 1b + PTR_ADDU t0, t0, 128 + +/* Do on chip L2 */ + LOAD_XKPHYS(t3, CCA_CACHED) + lw ta0, CpuSecondaryCacheSize + sll ta0, 2 # because cache is 4 way +10: + cache IndexWBInvalidate_S, 0(t3) + cache IndexWBInvalidate_S, 1(t3) + cache IndexWBInvalidate_S, 2(t3) + cache IndexWBInvalidate_S, 3(t3) + PTR_SUBU ta0, 32 # Fixed cache line size. + bgtz ta0, 10b + PTR_ADDU t3, 32 + + j ra + nop +END(Loongson2_SyncCache) + +/*---------------------------------------------------------------------------- + * + * Loongson2_InvalidateICache -- + * + * void Loongson2_SyncICache(addr, len) + * vaddr_t addr, len; + * + * Invalidate the L1 instruction cache for at least range + * of addr to addr + len - 1. + * The address is reduced to a XKPHYS index to avoid TLB faults. + * + * Results: + * None. + * + * Side effects: + * The contents of the L1 Instruction cache is flushed. + * Must not touch v0. + * + *---------------------------------------------------------------------------- + */ +LEAF(Loongson2_InvalidateICache, 0) + /* Loongson2: I$ index ops affect all ways */ + and a0, 0x00ffffff # Reduce addr to cache index + LOAD_XKPHYS(a2, CCA_CACHED) + PTR_ADDU a1, 31 # Round up size + PTR_ADDU a1, a0 # Add extra from address + and a0, -32 # Align start address + PTR_SUBU a1, a1, a0 + PTR_ADDU a0, a2 # a0 now new XKPHYS address + srl a1, a1, 5 # Number of unrolled loops +1: + PTR_ADDU a1, -1 + cache IndexInvalidate_I, 0(a0) + bne a1, zero, 1b + PTR_ADDU a0, 32 + + j ra + move v0, zero +END(Loongson2_InvalidateICache) + +/*---------------------------------------------------------------------------- + * + * Loongson2_SyncDCachePage -- + * + * void Loongson2_SyncDCachePage(addr) + * vaddr_t addr; + * + * Sync the L1 data cache page for address addr. + * The address is reduced to a XKPHYS index to avoid TLB faults. + * + * Results: + * None. + * + * Side effects: + * The contents of the cache is written back to primary memory. + * The cache line is invalidated. + * + *---------------------------------------------------------------------------- + */ +LEAF(Loongson2_SyncDCachePage, 0) + LOAD_XKPHYS(a2, CCA_CACHED) + dsll a0, 34 + dsrl a0, 34 + PTR_ADDU a0, a2 # a0 now new XKPHYS address + and a0, ~PAGE_MASK # Page align start address + PTR_ADDU a1, a0, PAGE_SIZE-128 + +1: + cache IndexWBInvalidate_D, 0(a0) # do set A + cache IndexWBInvalidate_D, 32(a0) + cache IndexWBInvalidate_D, 64(a0) + cache IndexWBInvalidate_D, 96(a0) + + cache IndexWBInvalidate_D, 1(a0) # do set B + cache IndexWBInvalidate_D, 33(a0) + cache IndexWBInvalidate_D, 65(a0) + cache IndexWBInvalidate_D, 97(a0) + + cache IndexWBInvalidate_D, 2(a0) # do set C + cache IndexWBInvalidate_D, 34(a0) + cache IndexWBInvalidate_D, 66(a0) + cache IndexWBInvalidate_D, 98(a0) + + cache IndexWBInvalidate_D, 3(a0) # do set D + cache IndexWBInvalidate_D, 35(a0) + cache IndexWBInvalidate_D, 67(a0) + cache IndexWBInvalidate_D, 99(a0) + + bne a1, a0, 1b + PTR_ADDU a0, 128 + + j ra + nop +END(Loongson2_SyncDCachePage) + +/*---------------------------------------------------------------------------- + * + * Loongson2_HitSyncDCache -- + * + * void Loongson2_HitSyncDCache(addr, len) + * vaddr_t addr, len; + * + * Sync data cache for range of addr to addr + len - 1. + * The address can be any valid virtual address as long + * as no TLB invalid traps occur. Only lines with matching + * addr are flushed. + * + * Results: + * None. + * + * Side effects: + * The contents of the L1 cache is written back to primary memory. + * The cache line is invalidated. + * + * IMPORTANT NOTE: + * Since orphaned L1 cache entries will not be synched it is + * mandatory to pass over the L1 cache once after the L2 is done. + * + *---------------------------------------------------------------------------- + */ +LEAF(Loongson2_HitSyncDCache, 0) + beq a1, zero, 3f # size is zero! + PTR_ADDU a1, 31 # Round up + PTR_ADDU a1, a1, a0 # Add extra from address + and a0, a0, -32 # align address + PTR_SUBU a1, a1, a0 + srl a1, a1, 5 # Compute number of cache lines + +1: + PTR_ADDU a1, -1 + cache HitWBInvalidate_D, 0(a0) + bne a1, zero, 1b + PTR_ADDU a0, 32 + +3: + j ra + nop +END(Loongson2_HitSyncDCache) + + +/*---------------------------------------------------------------------------- + * + * Loongson2_HitSyncSCache -- + * + * void Loongson2_HitSyncSCache(addr, len) + * vaddr_t addr, len; + * + * Sync secondary cache for range of addr to addr + len - 1. + * The address can be any valid virtual address as long + * as no TLB invalid traps occur. Only lines with matching + * addr are flushed. + * + * Results: + * None. + * + * Side effects: + * The contents of the L2 cache is written back to primary memory. + * The cache line is invalidated. + * + * IMPORTANT NOTE: + * Since orphaned L1 cache entries will not be synched it is + * mandatory to pass over the L1 cache once after the L2 is done. + * + *---------------------------------------------------------------------------- + */ +LEAF(Loongson2_HitSyncSCache, 0) + beq a1, zero, 3f # size is zero! + PTR_ADDU a1, a1, a0 # Add in extra from align + and a0, a0, -32 # Align address + PTR_SUBU a1, a1, a0 +1: + PTR_ADDU a1, -32 + + cache HitWBInvalidate_S, 0(a0) + cache HitWBInvalidate_D, 0(a0) # Kill any orphans... + + bgtz a1, 1b + PTR_ADDU a0, 32 + +3: + j ra + nop +END(Loongson2_HitSyncSCache) + +/*---------------------------------------------------------------------------- + * + * Loongson2_HitInvalidateDCache -- + * + * void Loongson2_HitInvalidateDCache(addr, len) + * vaddr_t addr, len; + * + * Invalidate data cache for range of addr to addr + len - 1. + * The address can be any valid address as long as no TLB misses occur. + * (Be sure to use cached K0SEG kernel addresses or mapped addresses) + * Only lines with matching addresses are invalidated. + * + * Results: + * None. + * + * Side effects: + * The L1 cache line is invalidated. + * + *---------------------------------------------------------------------------- + */ +LEAF(Loongson2_HitInvalidateDCache, 0) + beq a1, zero, 3f # size is zero! + PTR_ADDU a1, a1, a0 # Add in extra from align + and a0, a0, -32 # Align address + PTR_SUBU a1, a1, a0 + +1: + PTR_ADDU a1, -32 + + cache HitInvalidate_D, 0(a0) + + bgtz a1, 1b + PTR_ADDU a0, 32 + +3: + j ra + nop +END(Loongson2_HitInvalidateDCache) + + +/*---------------------------------------------------------------------------- + * + * Loongson2_HitInvalidateSCache -- + * + * void Loongson2_HitInvalidateSCache(addr, len) + * vaddr_t addr, len; + * + * Invalidate secondary cache for range of addr to addr + len - 1. + * The address can be any valid address as long as no TLB misses occur. + * (Be sure to use cached K0SEG kernel addresses or mapped addresses) + * Only lines with matching addresses are invalidated. + * + * Results: + * None. + * + * Side effects: + * The L2 cache line is invalidated. + * + *---------------------------------------------------------------------------- + */ +LEAF(Loongson2_HitInvalidateSCache, 0) + beq a1, zero, 3f # size is zero! + PTR_ADDU a1, a1, a0 # Add in extra from align + and a0, a0, -32 # Align address + PTR_SUBU a1, a1, a0 +1: + PTR_ADDU a1, -32 + + cache HitInvalidate_S, 0(a0) + cache HitInvalidate_D, 0(a0) # Orphans in L1 + + bgtz a1, 1b + PTR_ADDU a0, 32 + +3: + j ra + nop +END(Loongson2_HitInvalidateSCache) + +/*---------------------------------------------------------------------------- + * + * Loongson2_IOSyncDCache -- + * + * void Loongson2_IOSyncDCache(addr, len, rw) + * vaddr_t addr; + * int len, rw; + * + * Invalidate or flush data cache for range of addr to addr + len - 1. + * The address can be any valid address as long as no TLB misses occur. + * (Be sure to use cached K0SEG kernel addresses or mapped addresses) + * + * In case of the existence of an external cache we invalidate pages + * which are in the given range ONLY if transfer direction is READ. + * The assumption here is a 'write through' external cache which is + * true for all now supported processors. + * + * Results: + * None. + * + * Side effects: + * If rw == 0 (read), L1 and on-chip L2 caches are invalidated or + * flushed if the area does not match the alignment + * requirements. + * If rw == 1 (write) or rw == 2 (write-read), L1 and on-chip L2 caches + * are written back to memory and invalidated. + * + *---------------------------------------------------------------------------- + */ +NON_LEAF(Loongson2_IOSyncDCache, FRAMESZ(CF_SZ+2*REGSZ), ra) + + PTR_SUBU sp, FRAMESZ(CF_SZ+2*REGSZ) + PTR_S ra, CF_RA_OFFS+2*REGSZ(sp) + REG_S a0, CF_ARGSZ(sp) # save args + beqz a2, SyncRD # Sync PREREAD + REG_S a1, CF_ARGSZ+REGSZ(sp) + +/* + * Sync for unaligned read or write-read. + */ +SyncRDWB: + jal Loongson2_HitSyncSCache # Do internal L2 cache + nop # L1 done in parallel + b SyncDone + PTR_L ra, CF_RA_OFFS+2*REGSZ(sp) + +SyncRD: + and t0, a0, 31 # check if invalidate possible + bnez t0, SyncRDWB # both address and size must + and t0, a1, 31 # be aligned at the cache size + bnez t0, SyncRDWB + nop + +/* + * Sync for aligned read, no writeback required. + */ + jal Loongson2_HitInvalidateSCache # Internal L2 cache + nop # L1 done in parallel + + PTR_L ra, CF_RA_OFFS+2*REGSZ(sp) + +SyncDone: + j ra + PTR_ADDU sp, FRAMESZ(CF_SZ+2*REGSZ) +END(Loongson2_IOSyncDCache) diff --git a/sys/arch/mips64/mips64/context.S b/sys/arch/mips64/mips64/context.S index 0e2e1a380b9..a57db3165d9 100644 --- a/sys/arch/mips64/mips64/context.S +++ b/sys/arch/mips64/mips64/context.S @@ -1,4 +1,4 @@ -/* $OpenBSD: context.S,v 1.22 2009/05/22 20:37:53 miod Exp $ */ +/* $OpenBSD: context.S,v 1.23 2009/08/06 21:11:39 miod Exp $ */ /* * Copyright (c) 2002-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -33,6 +33,9 @@ #include <machine/cpu.h> #include <machine/regnum.h> #include <machine/cpustate.h> +#ifdef CPU_LOONGSON2 +#include <machine/loongson2.h> +#endif #include "assym.h" @@ -252,6 +255,19 @@ ctx2: ctx3: +#ifdef CPU_LOONGSON2 +#if 0 /* enable if Loongson2 + R5K|R10K kernel ever exist... */ + mfc0 v0, COP_0_PRID + and v0, 0xff00 + subi v0, (MIPS_LOONGSON2 << 8) + bnez v0, 7f + nop +#endif + li v0, COP_0_DIAG_ITLB_CLEAR | COP_0_DIAG_BTB_CLEAR | COP_0_DIAG_RAS_CLEAR + mfc0 v0, COP_0_DIAG +7: +#endif + /* * Restore registers and return. */ diff --git a/sys/arch/mips64/mips64/cpu.c b/sys/arch/mips64/mips64/cpu.c index 0d959151934..1fe040d6e13 100644 --- a/sys/arch/mips64/mips64/cpu.c +++ b/sys/arch/mips64/mips64/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.12 2009/06/17 18:18:21 miod Exp $ */ +/* $OpenBSD: cpu.c,v 1.13 2009/08/06 21:11:39 miod Exp $ */ /* * Copyright (c) 1997-2004 Opsycon AB (www.opsycon.se) @@ -85,9 +85,11 @@ cpuattach(struct device *parent, struct device *dev, void *aux) { int cpuno = dev->dv_unit; int isr16k = 0; + int displayver; printf(": "); + displayver = 1; switch (sys_config.cpu[cpuno].type) { case MIPS_R4000: if (CpuPrimaryInstCacheSize == 16384) @@ -139,17 +141,24 @@ cpuattach(struct device *parent, struct device *dev, void *aux) case MIPS_RM9000: printf("PMC-Sierra RM9000 CPU"); break; + case MIPS_LOONGSON2: + printf("STC Loongson2%c CPU", + 'C' + sys_config.cpu[cpuno].vers_min); + displayver = 0; + break; default: printf("Unknown CPU type (0x%x)",sys_config.cpu[cpuno].type); break; } - printf(" rev %d.%d %d MHz with ", sys_config.cpu[cpuno].vers_maj, - sys_config.cpu[cpuno].vers_min, - sys_config.cpu[cpuno].clock / 1000000); + if (displayver != 0) + printf(" rev %d.%d", sys_config.cpu[cpuno].vers_maj, + sys_config.cpu[cpuno].vers_min); + printf(" %d MHz, ", sys_config.cpu[cpuno].clock / 1000000); + displayver = 1; switch (sys_config.cpu[cpuno].fptype) { case MIPS_SOFT: - printf("Software emulation float"); + printf("Software FP emulation"); break; case MIPS_R4000: printf("R4010 FPC"); @@ -184,12 +193,19 @@ cpuattach(struct device *parent, struct device *dev, void *aux) case MIPS_RM9000: printf("RM9000 FPC"); break; + case MIPS_LOONGSON2: + printf("STC Loongson2%c FPU", + 'C' + sys_config.cpu[cpuno].fpvers_min); + displayver = 0; + break; default: printf("Unknown FPU type (0x%x)", sys_config.cpu[cpuno].fptype); break; } - printf(" rev %d.%d\n", sys_config.cpu[cpuno].fpvers_maj, - sys_config.cpu[cpuno].fpvers_min); + if (displayver != 0) + printf(" rev %d.%d", sys_config.cpu[cpuno].fpvers_maj, + sys_config.cpu[cpuno].fpvers_min); + printf("\n"); printf("cpu%d: cache L1-I %dKB", cpuno, CpuPrimaryInstCacheSize / 1024); printf(" D %dKB ", CpuPrimaryDataCacheSize / 1024); @@ -215,6 +231,7 @@ cpuattach(struct device *parent, struct device *dev, void *aux) break; case MIPS_RM7000: case MIPS_RM9000: + case MIPS_LOONGSON2: printf(", L2 %dKB 4 way", CpuSecondaryCacheSize / 1024); break; default: diff --git a/sys/arch/mips64/mips64/tlbhandler.S b/sys/arch/mips64/mips64/tlbhandler.S index 3dce155233e..087a2e0a974 100644 --- a/sys/arch/mips64/mips64/tlbhandler.S +++ b/sys/arch/mips64/mips64/tlbhandler.S @@ -1,4 +1,4 @@ -/* $OpenBSD: tlbhandler.S,v 1.18 2009/05/25 17:10:38 miod Exp $ */ +/* $OpenBSD: tlbhandler.S,v 1.19 2009/08/06 21:11:39 miod Exp $ */ /* * Copyright (c) 1995-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -36,6 +36,9 @@ #include <machine/cpu.h> #include <machine/regnum.h> #include <machine/cpustate.h> +#ifdef CPU_LOONGSON2 +#include <machine/loongson2.h> +#endif #include "assym.h" @@ -219,6 +222,20 @@ NLEAF(k_tlb_inv, 0) nop nop nop + +#ifdef CPU_LOONGSON2 +#if 0 /* enable if Loongson2 + R5K|R10K kernel ever exist... */ + mfc0 v0, COP_0_PRID + and v0, 0xff00 + subi v0, (MIPS_LOONGSON2 << 8) + bnez v0, 7f + nop +#endif + li v0, COP_0_DIAG_ITLB_CLEAR + mfc0 v0, COP_0_DIAG +7: +#endif + eret k_tlb_inv_odd: @@ -244,6 +261,20 @@ k_tlb_inv_odd: nop nop nop + +#ifdef CPU_LOONGSON2 +#if 0 /* enable if Loongson2 + R5K|R10K kernel ever exist... */ + mfc0 v0, COP_0_PRID + and v0, 0xff00 + subi v0, (MIPS_LOONGSON2 << 8) + bnez v0, 7f + nop +#endif + li v0, COP_0_DIAG_ITLB_CLEAR + mfc0 v0, COP_0_DIAG +7: +#endif + eret END(k_tlb_inv) @@ -345,6 +376,7 @@ go_u_general: .set at END(k_tlb_miss) +#if 0 /*---------------------------------------------------------------- tlb_write_i * Write the given entry into the TLB at the given index. */ @@ -375,6 +407,19 @@ LEAF(tlb_write_indexed, 0) nop nop +#ifdef CPU_LOONGSON2 +#if 0 /* enable if Loongson2 + R5K|R10K kernel ever exist... */ + mfc0 v0, COP_0_PRID + and v0, 0xff00 + subi v0, (MIPS_LOONGSON2 << 8) + bnez v0, 7f + nop +#endif + li v0, COP_0_DIAG_ITLB_CLEAR + mfc0 v0, COP_0_DIAG +7: +#endif + dmtc0 ta0, COP_0_TLB_HI # Restore the PID. nop dmtc0 zero, COP_0_TLB_PG_MASK # Default mask value. @@ -383,6 +428,7 @@ LEAF(tlb_write_indexed, 0) j ra nop END(tlb_write_indexed) +#endif /*---------------------------------------------------------------- tlb_flush * Flush the "random" entries from the TLB. @@ -418,6 +464,19 @@ LEAF(tlb_flush, 0) bne ta1, a0, 1b nop +#ifdef CPU_LOONGSON2 +#if 0 /* enable if Loongson2 + R5K|R10K kernel ever exist... */ + mfc0 v0, COP_0_PRID + and v0, 0xff00 + subi v0, (MIPS_LOONGSON2 << 8) + bnez v0, 7f + nop +#endif + li v0, COP_0_DIAG_ITLB_CLEAR + mfc0 v0, COP_0_DIAG +7: +#endif + dmtc0 ta0, COP_0_TLB_HI # Restore the PID mtc0 v1, COP_0_STATUS_REG # Restore the status register ITLBNOPFIX @@ -463,6 +522,20 @@ LEAF(tlb_flush_addr, 0) nop nop nop + +#ifdef CPU_LOONGSON2 +#if 0 /* enable if Loongson2 + R5K|R10K kernel ever exist... */ + mfc0 v0, COP_0_PRID + and v0, 0xff00 + subi v0, (MIPS_LOONGSON2 << 8) + bnez v0, 7f + nop +#endif + li v0, COP_0_DIAG_ITLB_CLEAR + mfc0 v0, COP_0_DIAG +7: +#endif + 1: dmtc0 ta0, COP_0_TLB_HI # restore PID mtc0 v1, COP_0_STATUS_REG # Restore the status register @@ -556,6 +629,20 @@ LEAF(tlb_update, 0) 4: # Make sure pipeline nop # advances before we nop # use the tlb. + +#ifdef CPU_LOONGSON2 +#if 0 /* enable if Loongson2 + R5K|R10K kernel ever exist... */ + mfc0 v0, COP_0_PRID + and v0, 0xff00 + subi v0, (MIPS_LOONGSON2 << 8) + bnez v0, 7f + nop +#endif + li v0, COP_0_DIAG_ITLB_CLEAR + mfc0 v0, COP_0_DIAG +7: +#endif + dmtc0 ta0, COP_0_TLB_HI # restore PID mtc0 v1, COP_0_STATUS_REG # Restore the status register ITLBNOPFIX |