summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-08-06 21:11:40 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-08-06 21:11:40 +0000
commitfeb56279b5746ffb588937f722b9644f732a7941 (patch)
tree0a2ffc7a955bb2dc83f755937af9f251b1b9badd
parent5b4cb6fccc3045f34fae9a21c38dee82e0843b13 (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.mips643
-rw-r--r--sys/arch/mips64/include/archtype.h25
-rw-r--r--sys/arch/mips64/include/cpu.h17
-rw-r--r--sys/arch/mips64/include/loongson2.h60
-rw-r--r--sys/arch/mips64/mips64/cache_loongson2.S607
-rw-r--r--sys/arch/mips64/mips64/context.S18
-rw-r--r--sys/arch/mips64/mips64/cpu.c31
-rw-r--r--sys/arch/mips64/mips64/tlbhandler.S89
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