summaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/kernel/entry.S4
-rw-r--r--arch/mips/kernel/head.S49
-rw-r--r--arch/mips/kernel/proc.c7
-rw-r--r--arch/mips/kernel/traps.c45
-rw-r--r--arch/mips/mm/r4xx0.c641
5 files changed, 417 insertions, 329 deletions
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index fb2b6a552..281ba0f2a 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -7,7 +7,7 @@
*
* Copyright (C) 1994, 1995 by Ralf Baechle
*
- * $Id: entry.S,v 1.11 1998/08/25 09:14:38 ralf Exp $
+ * $Id: entry.S,v 1.12 1998/09/19 19:16:15 ralf Exp $
*/
/*
@@ -152,10 +152,8 @@ EXPORT(exception_count_##exception); \
BUILD_HANDLER(cpu,cpu,sti,silent) /* #11 */
BUILD_HANDLER(ov,ov,sti,silent) /* #12 */
BUILD_HANDLER(tr,tr,sti,silent) /* #13 */
- BUILD_HANDLER(vcei,vcei,sti,verbose) /* #14 */
BUILD_HANDLER(fpe,fpe,fpe,silent) /* #15 */
BUILD_HANDLER(watch,watch,sti,verbose) /* #23 */
- BUILD_HANDLER(vced,vced,sti,verbose) /* #31 */
BUILD_HANDLER(reserved,reserved,sti,verbose) /* others */
/*
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 0a20d9b1a..b147b96bd 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.12 1998/05/26 06:16:52 ralf Exp $
+/* $Id: head.S,v 1.9 1998/08/25 09:14:38 ralf Exp $
*
* arch/mips/kernel/head.S
*
@@ -19,6 +19,7 @@
#include <linux/tasks.h>
#include <asm/asm.h>
+#include <asm/cacheops.h>
#include <asm/current.h>
#include <asm/offset.h>
#include <asm/processor.h>
@@ -34,10 +35,10 @@
/*
* Reserved space for exception handlers.
* Necessary for machines which link their kernels at KSEG0.
- * FIXME: We could overwrite some of the useless handlers
- * with those actually being used.
+ * FIXME: Use the initcode feature to get rid of unused handler
+ * variants.
*/
- .fill 520
+ .fill 0x280
/*
* This is space for the interrupt handlers.
* After trap_init() they are located at virtual address KSEG0.
@@ -322,16 +323,48 @@
NESTED(except_vec3_r4000, 0, sp)
.set noat
mfc0 k1, CP0_CAUSE
-
- /* XXX Have to check for VCE's _before_ we do a load or store. */
-
- la k0, exception_handlers
andi k1, k1, 0x7c
+ li k0, 31<<2
+ beq k1, k0, handle_vced
+ li k0, 14<<2
+ beq k1, k0, handle_vcei
+ la k0, exception_handlers
addu k0, k0, k1
lw k0, (k0)
nop
jr k0
nop
+
+/*
+ * Big shit, we now may have two dirty primary cache lines for the same
+ * physical address. We can savely invalidate the line pointed to by
+ * c0_badvaddr because after return from this exception handler the load /
+ * store will be re-executed.
+ */
+handle_vced:
+ mfc0 k0, CP0_BADVADDR
+ li k1, -4
+ and k0, k1
+ mtc0 zero, CP0_TAGLO
+ // nop;nop
+ cache Index_Store_Tag_D,(k0)
+ // nop;nop
+ cache Hit_Writeback_Inv_SD,(k0)
+ lui k0, %hi(vced_count)
+ lw k1, %lo(vced_count)(k0)
+ addiu k1, 1
+ sw k1, %lo(vced_count)(k0)
+ eret
+
+handle_vcei:
+ mfc0 k0, CP0_BADVADDR
+ cache Hit_Writeback_Inv_SD,(k0) # also cleans pi
+ lui k0, %hi(vcei_count)
+ lw k1, %lo(vcei_count)(k0)
+ addiu k1, 1
+ sw k1, %lo(vcei_count)(k0)
+ eret
+
END(except_vec3_r4000)
.set at
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 2c454c019..b4da7af26 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -12,6 +12,7 @@
#include <asm/watch.h>
unsigned long unaligned_instructions;
+unsigned int vced_count, vcei_count;
/*
* BUFFER is PAGE_SIZE bytes long.
@@ -21,6 +22,7 @@ unsigned long unaligned_instructions;
*/
int get_cpuinfo(char *buffer)
{
+ char fmt [64];
const char *cpu_name[] = CPU_NAMES;
const char *mach_group_names[] = GROUP_NAMES;
const char *mach_unknown_names[] = GROUP_UNKNOWN_NAMES;
@@ -70,5 +72,10 @@ int get_cpuinfo(char *buffer)
len += sprintf(buffer + len, "hardware watchpoint\t: %s\n",
watch_available ? "yes" : "no");
+ sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
+ vce_available ? "%d" : "not available");
+ len += sprintf(buffer + len, fmt, 'D', vced_count);
+ len += sprintf(buffer + len, fmt, 'I', vcei_count);
+
return len;
}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index ff8f4d901..40c8ba492 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.14 1998/07/16 19:10:02 ralf Exp $
+/* $Id: traps.c,v 1.15 1998/08/25 09:14:43 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -55,9 +55,7 @@ extern asmlinkage void handle_ri(void);
extern asmlinkage void handle_cpu(void);
extern asmlinkage void handle_ov(void);
extern asmlinkage void handle_tr(void);
-extern asmlinkage void handle_vcei(void);
extern asmlinkage void handle_fpe(void);
-extern asmlinkage void handle_vced(void);
extern asmlinkage void handle_watch(void);
extern asmlinkage void handle_reserved(void);
@@ -65,6 +63,7 @@ static char *cpu_names[] = CPU_NAMES;
char watch_available = 0;
char dedicated_iv_available = 0;
+char vce_available = 0;
void (*ibe_board_handler)(struct pt_regs *regs);
void (*dbe_board_handler)(struct pt_regs *regs);
@@ -359,24 +358,6 @@ bad_cid:
force_sig(SIGILL, current);
}
-void do_vcei(struct pt_regs *regs)
-{
- /*
- * Only possible on R4[04]00[SM]C. No handler because I don't have
- * such a cpu. Theory says this exception doesn't happen.
- */
- panic("Caught VCEI exception - should not happen");
-}
-
-void do_vced(struct pt_regs *regs)
-{
- /*
- * Only possible on R4[04]00[SM]C. No handler because I don't have
- * such a cpu. Theory says this exception doesn't happen.
- */
- panic("Caught VCE exception - should not happen");
-}
-
void do_watch(struct pt_regs *regs)
{
/*
@@ -513,11 +494,8 @@ __initfunc(void trap_init(void))
case CPU_R4400MC:
case CPU_R4000SC:
case CPU_R4400SC:
- /* XXX The following won't work because we _cannot_
- * XXX perform any load/store before the VCE handler.
- */
- set_except_vector(14, handle_vcei);
- set_except_vector(31, handle_vced);
+ vce_available = 1;
+ /* Fall through ... */
case CPU_R4000PC:
case CPU_R4400PC:
case CPU_R4200:
@@ -533,13 +511,16 @@ __initfunc(void trap_init(void))
else
memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
- /*
- * The idea is that this special r4000 general exception
- * vector will check for VCE exceptions before calling
- * out of the exception array. XXX TODO
- */
+ /* Cache error vector */
memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
- memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80);
+
+ if (vce_available) {
+ memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000,
+ 0x180);
+ } else {
+ memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
+ 0x100);
+ }
save_fp_context = r4k_save_fp_context;
restore_fp_context = r4k_restore_fp_context;
diff --git a/arch/mips/mm/r4xx0.c b/arch/mips/mm/r4xx0.c
index 43c13e263..31b636296 100644
--- a/arch/mips/mm/r4xx0.c
+++ b/arch/mips/mm/r4xx0.c
@@ -1,4 +1,4 @@
-/* $Id: r4xx0.c,v 1.28 1998/08/18 20:45:08 ralf Exp $
+/* $Id: r4xx0.c,v 1.19 1998/08/25 09:14:46 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -41,7 +41,7 @@ static int icache_size, dcache_size; /* Size in bytes */
static int ic_lsize, dc_lsize; /* LineSize in bytes */
/* Secondary cache (if present) parameters. */
-static unsigned long scache_size, sc_lsize; /* Again, in bytes */
+static unsigned int scache_size, sc_lsize; /* Again, in bytes */
#include <asm/cacheops.h>
#include <asm/r4kcache.h>
@@ -78,10 +78,7 @@ struct bcache_ops *bcops = &no_sc_ops;
* - a version which handles the buggy R4600 v1.x
* - a version which handles the buggy R4600 v2.0
* - Finally a last version without fancy cache games for the SC and MC
- * versions of R4000 and R4400. Cache instructions are quite expensive
- * and I guess using them for both the primary and the second level cache
- * wouldn't be worth the effort.
- * This needs to be verified by benchmarking.
+ * versions of R4000 and R4400.
*/
static void r4k_clear_page_d16(unsigned long page)
@@ -245,14 +242,84 @@ static void r4k_clear_page_r4600_v2(unsigned long page)
restore_flags(flags);
}
-static void r4k_clear_page(unsigned long page)
+/*
+ * The next 4 versions are optimized for all possible scache configurations
+ * of the SC / MC versions of R4000 and R4400 ...
+ *
+ * Todo: For even better performance we should have a routine optimized for
+ * every legal combination of dcache / scache linesize. When I (Ralf) tried
+ * this the kernel crashed shortly after mounting the root filesystem. CPU
+ * bug? Weirdo cache instruction semantics?
+ */
+static void r4k_clear_page_s16(unsigned long page)
+{
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ ".set\tnoat\n\t"
+ ".set\tmips3\n\t"
+ "daddiu\t$1,%0,%2\n"
+ "1:\tcache\t%3,(%0)\n\t"
+ "sd\t$0,(%0)\n\t"
+ "sd\t$0,8(%0)\n\t"
+ "cache\t%3,16(%0)\n\t"
+ "sd\t$0,16(%0)\n\t"
+ "sd\t$0,24(%0)\n\t"
+ "daddiu\t%0,64\n\t"
+ "cache\t%3,-32(%0)\n\t"
+ "sd\t$0,-32(%0)\n\t"
+ "sd\t$0,-24(%0)\n\t"
+ "cache\t%3,-16(%0)\n\t"
+ "sd\t$0,-16(%0)\n\t"
+ "bne\t$1,%0,1b\n\t"
+ "sd\t$0,-8(%0)\n\t"
+ ".set\tmips0\n\t"
+ ".set\tat\n\t"
+ ".set\treorder"
+ :"=r" (page)
+ :"0" (page),
+ "I" (PAGE_SIZE),
+ "i" (Create_Dirty_Excl_SD)
+ :"$1","memory");
+}
+
+static void r4k_clear_page_s32(unsigned long page)
+{
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ ".set\tnoat\n\t"
+ ".set\tmips3\n\t"
+ "daddiu\t$1,%0,%2\n"
+ "1:\tcache\t%3,(%0)\n\t"
+ "sd\t$0,(%0)\n\t"
+ "sd\t$0,8(%0)\n\t"
+ "sd\t$0,16(%0)\n\t"
+ "sd\t$0,24(%0)\n\t"
+ "daddiu\t%0,64\n\t"
+ "cache\t%3,-32(%0)\n\t"
+ "sd\t$0,-32(%0)\n\t"
+ "sd\t$0,-24(%0)\n\t"
+ "sd\t$0,-16(%0)\n\t"
+ "bne\t$1,%0,1b\n\t"
+ "sd\t$0,-8(%0)\n\t"
+ ".set\tmips0\n\t"
+ ".set\tat\n\t"
+ ".set\treorder"
+ :"=r" (page)
+ :"0" (page),
+ "I" (PAGE_SIZE),
+ "i" (Create_Dirty_Excl_SD)
+ :"$1","memory");
+}
+
+static void r4k_clear_page_s64(unsigned long page)
{
__asm__ __volatile__(
".set\tnoreorder\n\t"
".set\tnoat\n\t"
".set\tmips3\n\t"
"daddiu\t$1,%0,%2\n"
- "1:\tsd\t$0,(%0)\n\t"
+ "1:\tcache\t%3,(%0)\n\t"
+ "sd\t$0,(%0)\n\t"
"sd\t$0,8(%0)\n\t"
"sd\t$0,16(%0)\n\t"
"sd\t$0,24(%0)\n\t"
@@ -267,7 +334,44 @@ static void r4k_clear_page(unsigned long page)
".set\treorder"
:"=r" (page)
:"0" (page),
- "I" (PAGE_SIZE)
+ "I" (PAGE_SIZE),
+ "i" (Create_Dirty_Excl_SD)
+ :"$1","memory");
+}
+
+static void r4k_clear_page_s128(unsigned long page)
+{
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ ".set\tnoat\n\t"
+ ".set\tmips3\n\t"
+ "daddiu\t$1,%0,%2\n"
+ "1:\tcache\t%3,(%0)\n\t"
+ "sd\t$0,(%0)\n\t"
+ "sd\t$0,8(%0)\n\t"
+ "sd\t$0,16(%0)\n\t"
+ "sd\t$0,24(%0)\n\t"
+ "sd\t$0,32(%0)\n\t"
+ "sd\t$0,40(%0)\n\t"
+ "sd\t$0,48(%0)\n\t"
+ "sd\t$0,56(%0)\n\t"
+ "daddiu\t%0,128\n\t"
+ "sd\t$0,-64(%0)\n\t"
+ "sd\t$0,-56(%0)\n\t"
+ "sd\t$0,-48(%0)\n\t"
+ "sd\t$0,-40(%0)\n\t"
+ "sd\t$0,-32(%0)\n\t"
+ "sd\t$0,-24(%0)\n\t"
+ "sd\t$0,-16(%0)\n\t"
+ "bne\t$1,%0,1b\n\t"
+ "sd\t$0,-8(%0)\n\t"
+ ".set\tmips0\n\t"
+ ".set\tat\n\t"
+ ".set\treorder"
+ :"=r" (page)
+ :"0" (page),
+ "I" (PAGE_SIZE),
+ "i" (Create_Dirty_Excl_SD)
:"$1","memory");
}
@@ -529,7 +633,10 @@ static void r4k_copy_page_r4600_v2(unsigned long to, unsigned long from)
restore_flags(flags);
}
-static void r4k_copy_page(unsigned long to, unsigned long from)
+/*
+ * These are for R4000SC / R4400MC
+ */
+static void r4k_copy_page_s16(unsigned long to, unsigned long from)
{
unsigned long dummy1, dummy2;
unsigned long reg1, reg2, reg3, reg4;
@@ -539,7 +646,8 @@ static void r4k_copy_page(unsigned long to, unsigned long from)
".set\tnoat\n\t"
".set\tmips3\n\t"
"daddiu\t$1,%0,%8\n"
- "1:\tlw\t%2,(%1)\n\t"
+ "1:\tcache\t%9,(%0)\n\t"
+ "lw\t%2,(%1)\n\t"
"lw\t%3,4(%1)\n\t"
"lw\t%4,8(%1)\n\t"
"lw\t%5,12(%1)\n\t"
@@ -547,6 +655,7 @@ static void r4k_copy_page(unsigned long to, unsigned long from)
"sw\t%3,4(%0)\n\t"
"sw\t%4,8(%0)\n\t"
"sw\t%5,12(%0)\n\t"
+ "cache\t%9,16(%0)\n\t"
"lw\t%2,16(%1)\n\t"
"lw\t%3,20(%1)\n\t"
"lw\t%4,24(%1)\n\t"
@@ -555,6 +664,7 @@ static void r4k_copy_page(unsigned long to, unsigned long from)
"sw\t%3,20(%0)\n\t"
"sw\t%4,24(%0)\n\t"
"sw\t%5,28(%0)\n\t"
+ "cache\t%9,32(%0)\n\t"
"daddiu\t%0,64\n\t"
"daddiu\t%1,64\n\t"
"lw\t%2,-32(%1)\n\t"
@@ -565,6 +675,208 @@ static void r4k_copy_page(unsigned long to, unsigned long from)
"sw\t%3,-28(%0)\n\t"
"sw\t%4,-24(%0)\n\t"
"sw\t%5,-20(%0)\n\t"
+ "cache\t%9,-16(%0)\n\t"
+ "lw\t%2,-16(%1)\n\t"
+ "lw\t%3,-12(%1)\n\t"
+ "lw\t%4,-8(%1)\n\t"
+ "lw\t%5,-4(%1)\n\t"
+ "sw\t%2,-16(%0)\n\t"
+ "sw\t%3,-12(%0)\n\t"
+ "sw\t%4,-8(%0)\n\t"
+ "bne\t$1,%0,1b\n\t"
+ "sw\t%5,-4(%0)\n\t"
+ ".set\tmips0\n\t"
+ ".set\tat\n\t"
+ ".set\treorder"
+ :"=r" (dummy1), "=r" (dummy2),
+ "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
+ :"0" (to), "1" (from),
+ "I" (PAGE_SIZE),
+ "i" (Create_Dirty_Excl_SD));
+}
+
+static void r4k_copy_page_s32(unsigned long to, unsigned long from)
+{
+ unsigned long dummy1, dummy2;
+ unsigned long reg1, reg2, reg3, reg4;
+
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ ".set\tnoat\n\t"
+ ".set\tmips3\n\t"
+ "daddiu\t$1,%0,%8\n"
+ "1:\tcache\t%9,(%0)\n\t"
+ "lw\t%2,(%1)\n\t"
+ "lw\t%3,4(%1)\n\t"
+ "lw\t%4,8(%1)\n\t"
+ "lw\t%5,12(%1)\n\t"
+ "sw\t%2,(%0)\n\t"
+ "sw\t%3,4(%0)\n\t"
+ "sw\t%4,8(%0)\n\t"
+ "sw\t%5,12(%0)\n\t"
+ "lw\t%2,16(%1)\n\t"
+ "lw\t%3,20(%1)\n\t"
+ "lw\t%4,24(%1)\n\t"
+ "lw\t%5,28(%1)\n\t"
+ "sw\t%2,16(%0)\n\t"
+ "sw\t%3,20(%0)\n\t"
+ "sw\t%4,24(%0)\n\t"
+ "sw\t%5,28(%0)\n\t"
+ "cache\t%9,32(%0)\n\t"
+ "daddiu\t%0,64\n\t"
+ "daddiu\t%1,64\n\t"
+ "lw\t%2,-32(%1)\n\t"
+ "lw\t%3,-28(%1)\n\t"
+ "lw\t%4,-24(%1)\n\t"
+ "lw\t%5,-20(%1)\n\t"
+ "sw\t%2,-32(%0)\n\t"
+ "sw\t%3,-28(%0)\n\t"
+ "sw\t%4,-24(%0)\n\t"
+ "sw\t%5,-20(%0)\n\t"
+ "lw\t%2,-16(%1)\n\t"
+ "lw\t%3,-12(%1)\n\t"
+ "lw\t%4,-8(%1)\n\t"
+ "lw\t%5,-4(%1)\n\t"
+ "sw\t%2,-16(%0)\n\t"
+ "sw\t%3,-12(%0)\n\t"
+ "sw\t%4,-8(%0)\n\t"
+ "bne\t$1,%0,1b\n\t"
+ "sw\t%5,-4(%0)\n\t"
+ ".set\tmips0\n\t"
+ ".set\tat\n\t"
+ ".set\treorder"
+ :"=r" (dummy1), "=r" (dummy2),
+ "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
+ :"0" (to), "1" (from),
+ "I" (PAGE_SIZE),
+ "i" (Create_Dirty_Excl_SD));
+}
+
+static void r4k_copy_page_s64(unsigned long to, unsigned long from)
+{
+ unsigned long dummy1, dummy2;
+ unsigned long reg1, reg2, reg3, reg4;
+
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ ".set\tnoat\n\t"
+ ".set\tmips3\n\t"
+ "daddiu\t$1,%0,%8\n"
+ "1:\tcache\t%9,(%0)\n\t"
+ "lw\t%2,(%1)\n\t"
+ "lw\t%3,4(%1)\n\t"
+ "lw\t%4,8(%1)\n\t"
+ "lw\t%5,12(%1)\n\t"
+ "sw\t%2,(%0)\n\t"
+ "sw\t%3,4(%0)\n\t"
+ "sw\t%4,8(%0)\n\t"
+ "sw\t%5,12(%0)\n\t"
+ "lw\t%2,16(%1)\n\t"
+ "lw\t%3,20(%1)\n\t"
+ "lw\t%4,24(%1)\n\t"
+ "lw\t%5,28(%1)\n\t"
+ "sw\t%2,16(%0)\n\t"
+ "sw\t%3,20(%0)\n\t"
+ "sw\t%4,24(%0)\n\t"
+ "sw\t%5,28(%0)\n\t"
+ "daddiu\t%0,64\n\t"
+ "daddiu\t%1,64\n\t"
+ "lw\t%2,-32(%1)\n\t"
+ "lw\t%3,-28(%1)\n\t"
+ "lw\t%4,-24(%1)\n\t"
+ "lw\t%5,-20(%1)\n\t"
+ "sw\t%2,-32(%0)\n\t"
+ "sw\t%3,-28(%0)\n\t"
+ "sw\t%4,-24(%0)\n\t"
+ "sw\t%5,-20(%0)\n\t"
+ "lw\t%2,-16(%1)\n\t"
+ "lw\t%3,-12(%1)\n\t"
+ "lw\t%4,-8(%1)\n\t"
+ "lw\t%5,-4(%1)\n\t"
+ "sw\t%2,-16(%0)\n\t"
+ "sw\t%3,-12(%0)\n\t"
+ "sw\t%4,-8(%0)\n\t"
+ "bne\t$1,%0,1b\n\t"
+ "sw\t%5,-4(%0)\n\t"
+ ".set\tmips0\n\t"
+ ".set\tat\n\t"
+ ".set\treorder"
+ :"=r" (dummy1), "=r" (dummy2),
+ "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
+ :"0" (to), "1" (from),
+ "I" (PAGE_SIZE),
+ "i" (Create_Dirty_Excl_SD));
+}
+
+static void r4k_copy_page_s128(unsigned long to, unsigned long from)
+{
+ unsigned long dummy1, dummy2;
+ unsigned long reg1, reg2, reg3, reg4;
+
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ ".set\tnoat\n\t"
+ ".set\tmips3\n\t"
+ "daddiu\t$1,%0,%8\n"
+ "1:\tcache\t%9,(%0)\n\t"
+ "lw\t%2,(%1)\n\t"
+ "lw\t%3,4(%1)\n\t"
+ "lw\t%4,8(%1)\n\t"
+ "lw\t%5,12(%1)\n\t"
+ "sw\t%2,(%0)\n\t"
+ "sw\t%3,4(%0)\n\t"
+ "sw\t%4,8(%0)\n\t"
+ "sw\t%5,12(%0)\n\t"
+ "lw\t%2,16(%1)\n\t"
+ "lw\t%3,20(%1)\n\t"
+ "lw\t%4,24(%1)\n\t"
+ "lw\t%5,28(%1)\n\t"
+ "sw\t%2,16(%0)\n\t"
+ "sw\t%3,20(%0)\n\t"
+ "sw\t%4,24(%0)\n\t"
+ "sw\t%5,28(%0)\n\t"
+ "lw\t%2,32(%1)\n\t"
+ "lw\t%3,36(%1)\n\t"
+ "lw\t%4,40(%1)\n\t"
+ "lw\t%5,44(%1)\n\t"
+ "sw\t%2,32(%0)\n\t"
+ "sw\t%3,36(%0)\n\t"
+ "sw\t%4,40(%0)\n\t"
+ "sw\t%5,44(%0)\n\t"
+ "lw\t%2,48(%1)\n\t"
+ "lw\t%3,52(%1)\n\t"
+ "lw\t%4,56(%1)\n\t"
+ "lw\t%5,60(%1)\n\t"
+ "sw\t%2,48(%0)\n\t"
+ "sw\t%3,52(%0)\n\t"
+ "sw\t%4,56(%0)\n\t"
+ "sw\t%5,60(%0)\n\t"
+ "daddiu\t%0,128\n\t"
+ "daddiu\t%1,128\n\t"
+ "lw\t%2,-64(%1)\n\t"
+ "lw\t%3,-60(%1)\n\t"
+ "lw\t%4,-56(%1)\n\t"
+ "lw\t%5,-52(%1)\n\t"
+ "sw\t%2,-64(%0)\n\t"
+ "sw\t%3,-60(%0)\n\t"
+ "sw\t%4,-56(%0)\n\t"
+ "sw\t%5,-52(%0)\n\t"
+ "lw\t%2,-48(%1)\n\t"
+ "lw\t%3,-44(%1)\n\t"
+ "lw\t%4,-40(%1)\n\t"
+ "lw\t%5,-36(%1)\n\t"
+ "sw\t%2,-48(%0)\n\t"
+ "sw\t%3,-44(%0)\n\t"
+ "sw\t%4,-40(%0)\n\t"
+ "sw\t%5,-36(%0)\n\t"
+ "lw\t%2,-32(%1)\n\t"
+ "lw\t%3,-28(%1)\n\t"
+ "lw\t%4,-24(%1)\n\t"
+ "lw\t%5,-20(%1)\n\t"
+ "sw\t%2,-32(%0)\n\t"
+ "sw\t%3,-28(%0)\n\t"
+ "sw\t%4,-24(%0)\n\t"
+ "sw\t%5,-20(%0)\n\t"
"lw\t%2,-16(%1)\n\t"
"lw\t%3,-12(%1)\n\t"
"lw\t%4,-8(%1)\n\t"
@@ -580,9 +892,11 @@ static void r4k_copy_page(unsigned long to, unsigned long from)
:"=r" (dummy1), "=r" (dummy2),
"=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
:"0" (to), "1" (from),
- "I" (PAGE_SIZE));
+ "I" (PAGE_SIZE),
+ "i" (Create_Dirty_Excl_SD));
}
+
/*
* If you think for one second that this stuff coming up is a lot
* of bulky code eating too many kernel cache lines. Think _again_.
@@ -632,15 +946,6 @@ static inline void r4k_flush_cache_all_s128d16i16(void)
restore_flags(flags);
}
-static inline void r4k_flush_cache_all_s16d32i32(void)
-{
- unsigned long flags;
-
- save_and_cli(flags);
- blast_dcache32(); blast_icache32(); blast_scache16();
- restore_flags(flags);
-}
-
static inline void r4k_flush_cache_all_s32d32i32(void)
{
unsigned long flags;
@@ -718,12 +1023,8 @@ r4k_flush_cache_range_s16d16i16(struct mm_struct *mm,
pmd = pmd_offset(pgd, start);
pte = pte_offset(pmd, start);
- if(pte_val(*pte) & _PAGE_VALID) {
- blast_dcache16_page(start);
- if(text)
- blast_icache16_page(start);
+ if(pte_val(*pte) & _PAGE_VALID)
blast_scache16_page(start);
- }
start += PAGE_SIZE;
}
restore_flags(flags);
@@ -763,12 +1064,8 @@ r4k_flush_cache_range_s32d16i16(struct mm_struct *mm,
pmd = pmd_offset(pgd, start);
pte = pte_offset(pmd, start);
- if(pte_val(*pte) & _PAGE_VALID) {
- blast_dcache16_page(start);
- if(text)
- blast_icache16_page(start);
+ if(pte_val(*pte) & _PAGE_VALID)
blast_scache32_page(start);
- }
start += PAGE_SIZE;
}
restore_flags(flags);
@@ -807,12 +1104,8 @@ static void r4k_flush_cache_range_s64d16i16(struct mm_struct *mm,
pmd = pmd_offset(pgd, start);
pte = pte_offset(pmd, start);
- if(pte_val(*pte) & _PAGE_VALID) {
- blast_dcache16_page(start);
- if(text)
- blast_icache16_page(start);
+ if(pte_val(*pte) & _PAGE_VALID)
blast_scache64_page(start);
- }
start += PAGE_SIZE;
}
restore_flags(flags);
@@ -851,56 +1144,8 @@ static void r4k_flush_cache_range_s128d16i16(struct mm_struct *mm,
pmd = pmd_offset(pgd, start);
pte = pte_offset(pmd, start);
- if(pte_val(*pte) & _PAGE_VALID) {
- blast_dcache16_page(start);
- if(text)
- blast_icache16_page(start);
+ if(pte_val(*pte) & _PAGE_VALID)
blast_scache128_page(start);
- }
- start += PAGE_SIZE;
- }
- restore_flags(flags);
- }
- }
-}
-
-static void r4k_flush_cache_range_s16d32i32(struct mm_struct *mm,
- unsigned long start,
- unsigned long end)
-{
- struct vm_area_struct *vma;
- unsigned long flags;
-
- if(mm->context == 0)
- return;
-
- start &= PAGE_MASK;
-#ifdef DEBUG_CACHE
- printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
-#endif
- vma = find_vma(mm, start);
- if(vma) {
- if(mm->context != current->mm->context) {
- r4k_flush_cache_all_s16d32i32();
- } else {
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte;
- int text;
-
- save_and_cli(flags);
- text = vma->vm_flags & VM_EXEC;
- while(start < end) {
- pgd = pgd_offset(mm, start);
- pmd = pmd_offset(pgd, start);
- pte = pte_offset(pmd, start);
-
- if(pte_val(*pte) & _PAGE_VALID) {
- blast_dcache32_page(start);
- if(text)
- blast_icache32_page(start);
- blast_scache16_page(start);
- }
start += PAGE_SIZE;
}
restore_flags(flags);
@@ -939,12 +1184,8 @@ static void r4k_flush_cache_range_s32d32i32(struct mm_struct *mm,
pmd = pmd_offset(pgd, start);
pte = pte_offset(pmd, start);
- if(pte_val(*pte) & _PAGE_VALID) {
- blast_dcache32_page(start);
- if(text)
- blast_icache32_page(start);
+ if(pte_val(*pte) & _PAGE_VALID)
blast_scache32_page(start);
- }
start += PAGE_SIZE;
}
restore_flags(flags);
@@ -983,12 +1224,8 @@ static void r4k_flush_cache_range_s64d32i32(struct mm_struct *mm,
pmd = pmd_offset(pgd, start);
pte = pte_offset(pmd, start);
- if(pte_val(*pte) & _PAGE_VALID) {
- blast_dcache32_page(start);
- if(text)
- blast_icache32_page(start);
+ if(pte_val(*pte) & _PAGE_VALID)
blast_scache64_page(start);
- }
start += PAGE_SIZE;
}
restore_flags(flags);
@@ -1027,12 +1264,8 @@ static void r4k_flush_cache_range_s128d32i32(struct mm_struct *mm,
pmd = pmd_offset(pgd, start);
pte = pte_offset(pmd, start);
- if(pte_val(*pte) & _PAGE_VALID) {
- blast_dcache32_page(start);
- if(text)
- blast_icache32_page(start);
+ if(pte_val(*pte) & _PAGE_VALID)
blast_scache128_page(start);
- }
start += PAGE_SIZE;
}
restore_flags(flags);
@@ -1117,16 +1350,6 @@ static void r4k_flush_cache_mm_s128d16i16(struct mm_struct *mm)
}
}
-static void r4k_flush_cache_mm_s16d32i32(struct mm_struct *mm)
-{
- if(mm->context != 0) {
-#ifdef DEBUG_CACHE
- printk("cmm[%d]", (int)mm->context);
-#endif
- r4k_flush_cache_all_s16d32i32();
- }
-}
-
static void r4k_flush_cache_mm_s32d32i32(struct mm_struct *mm)
{
if(mm->context != 0) {
@@ -1225,12 +1448,8 @@ static void r4k_flush_cache_page_s16d16i16(struct vm_area_struct *vma,
if(text)
blast_icache16_page_indexed(page);
blast_scache16_page_indexed(page);
- } else {
- blast_dcache16_page(page);
- if(text)
- blast_icache16_page(page);
+ } else
blast_scache16_page(page);
- }
out:
restore_flags(flags);
}
@@ -1282,12 +1501,8 @@ static void r4k_flush_cache_page_s32d16i16(struct vm_area_struct *vma,
if(text)
blast_icache16_page_indexed(page);
blast_scache32_page_indexed(page);
- } else {
- blast_dcache16_page(page);
- if(text)
- blast_icache16_page(page);
+ } else
blast_scache32_page(page);
- }
out:
restore_flags(flags);
}
@@ -1340,12 +1555,8 @@ static void r4k_flush_cache_page_s64d16i16(struct vm_area_struct *vma,
if(text)
blast_icache16_page_indexed(page);
blast_scache64_page_indexed(page);
- } else {
- blast_dcache16_page(page);
- if(text)
- blast_icache16_page(page);
+ } else
blast_scache64_page(page);
- }
out:
restore_flags(flags);
}
@@ -1399,70 +1610,8 @@ static void r4k_flush_cache_page_s128d16i16(struct vm_area_struct *vma,
if(text)
blast_icache16_page_indexed(page);
blast_scache128_page_indexed(page);
- } else {
- blast_dcache16_page(page);
- if(text)
- blast_icache16_page(page);
+ } else
blast_scache128_page(page);
- }
-out:
- restore_flags(flags);
-}
-
-static void r4k_flush_cache_page_s16d32i32(struct vm_area_struct *vma,
- unsigned long page)
-{
- struct mm_struct *mm = vma->vm_mm;
- unsigned long flags;
- pgd_t *pgdp;
- pmd_t *pmdp;
- pte_t *ptep;
- int text;
-
- /*
- * If ownes no valid ASID yet, cannot possibly have gotten
- * this page into the cache.
- */
- if(mm->context == 0)
- return;
-
-#ifdef DEBUG_CACHE
- printk("cpage[%d,%08lx]", (int)mm->context, page);
-#endif
- save_and_cli(flags);
- page &= PAGE_MASK;
- pgdp = pgd_offset(mm, page);
- pmdp = pmd_offset(pgdp, page);
- ptep = pte_offset(pmdp, page);
-
- /* If the page isn't marked valid, the page cannot possibly be
- * in the cache.
- */
- if(!(pte_val(*ptep) & _PAGE_VALID))
- goto out;
-
- text = (vma->vm_flags & VM_EXEC);
- /*
- * Doing flushes for another ASID than the current one is
- * too difficult since stupid R4k caches do a TLB translation
- * for every cache flush operation. So we do indexed flushes
- * in that case, which doesn't overly flush the cache too much.
- */
- if(mm->context != current->mm->context) {
- /* Do indexed flush, too much work to get the (possible)
- * tlb refills to work correctly.
- */
- page = (KSEG0 + (page & (scache_size - 1)));
- blast_dcache32_page_indexed(page);
- if(text)
- blast_icache32_page_indexed(page);
- blast_scache16_page_indexed(page);
- } else {
- blast_dcache32_page(page);
- if(text)
- blast_icache32_page(page);
- blast_scache16_page(page);
- }
out:
restore_flags(flags);
}
@@ -1517,12 +1666,8 @@ static void r4k_flush_cache_page_s32d32i32(struct vm_area_struct *vma,
if(text)
blast_icache32_page_indexed(page);
blast_scache32_page_indexed(page);
- } else {
- blast_dcache32_page(page);
- if(text)
- blast_icache32_page(page);
+ } else
blast_scache32_page(page);
- }
out:
restore_flags(flags);
}
@@ -1577,12 +1722,8 @@ static void r4k_flush_cache_page_s64d32i32(struct vm_area_struct *vma,
if(text)
blast_icache32_page_indexed(page);
blast_scache64_page_indexed(page);
- } else {
- blast_dcache32_page(page);
- if(text)
- blast_icache32_page(page);
+ } else
blast_scache64_page(page);
- }
out:
restore_flags(flags);
}
@@ -1635,12 +1776,8 @@ static void r4k_flush_cache_page_s128d32i32(struct vm_area_struct *vma,
if(text)
blast_icache32_page_indexed(page);
blast_scache128_page_indexed(page);
- } else {
- blast_dcache32_page(page);
- if(text)
- blast_icache32_page(page);
+ } else
blast_scache128_page(page);
- }
out:
restore_flags(flags);
}
@@ -1832,15 +1969,10 @@ static void r4k_flush_page_to_ram_s16d16i16(unsigned long page)
{
page &= PAGE_MASK;
if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
- unsigned long flags;
-
#ifdef DEBUG_CACHE
printk("cram[%08lx]", page);
#endif
- save_and_cli(flags);
- blast_dcache16_page(page);
blast_scache16_page(page);
- restore_flags(flags);
}
}
@@ -1848,15 +1980,10 @@ static void r4k_flush_page_to_ram_s32d16i16(unsigned long page)
{
page &= PAGE_MASK;
if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
- unsigned long flags;
-
#ifdef DEBUG_CACHE
printk("cram[%08lx]", page);
#endif
- save_and_cli(flags);
- blast_dcache16_page(page);
blast_scache32_page(page);
- restore_flags(flags);
}
}
@@ -1864,15 +1991,10 @@ static void r4k_flush_page_to_ram_s64d16i16(unsigned long page)
{
page &= PAGE_MASK;
if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
- unsigned long flags;
-
#ifdef DEBUG_CACHE
printk("cram[%08lx]", page);
#endif
- save_and_cli(flags);
- blast_dcache16_page(page);
blast_scache64_page(page);
- restore_flags(flags);
}
}
@@ -1880,31 +2002,10 @@ static void r4k_flush_page_to_ram_s128d16i16(unsigned long page)
{
page &= PAGE_MASK;
if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
- unsigned long flags;
-
#ifdef DEBUG_CACHE
printk("cram[%08lx]", page);
#endif
- save_and_cli(flags);
- blast_dcache16_page(page);
blast_scache128_page(page);
- restore_flags(flags);
- }
-}
-
-static void r4k_flush_page_to_ram_s16d32i32(unsigned long page)
-{
- page &= PAGE_MASK;
- if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
- unsigned long flags;
-
-#ifdef DEBUG_CACHE
- printk("cram[%08lx]", page);
-#endif
- save_and_cli(flags);
- blast_dcache32_page(page);
- blast_scache16_page(page);
- restore_flags(flags);
}
}
@@ -1912,15 +2013,10 @@ static void r4k_flush_page_to_ram_s32d32i32(unsigned long page)
{
page &= PAGE_MASK;
if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
- unsigned long flags;
-
#ifdef DEBUG_CACHE
printk("cram[%08lx]", page);
#endif
- save_and_cli(flags);
- blast_dcache32_page(page);
blast_scache32_page(page);
- restore_flags(flags);
}
}
@@ -1928,15 +2024,10 @@ static void r4k_flush_page_to_ram_s64d32i32(unsigned long page)
{
page &= PAGE_MASK;
if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
- unsigned long flags;
-
#ifdef DEBUG_CACHE
printk("cram[%08lx]", page);
#endif
- save_and_cli(flags);
- blast_dcache32_page(page);
blast_scache64_page(page);
- restore_flags(flags);
}
}
@@ -1944,15 +2035,10 @@ static void r4k_flush_page_to_ram_s128d32i32(unsigned long page)
{
page &= PAGE_MASK;
if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
- unsigned long flags;
-
#ifdef DEBUG_CACHE
printk("cram[%08lx]", page);
#endif
- save_and_cli(flags);
- blast_dcache32_page(page);
blast_scache128_page(page);
- restore_flags(flags);
}
}
@@ -2026,20 +2112,10 @@ static void
r4k_dma_cache_wback_inv_sc(unsigned long addr, unsigned long size)
{
unsigned long end, a;
- unsigned int flags;
if (size >= scache_size) {
flush_cache_all();
- } else {
- save_and_cli(flags);
- a = addr & ~(dc_lsize - 1);
- end = (addr + size) & ~(dc_lsize - 1);
- while (1) {
- flush_dcache_line(a); /* Hit_Writeback_Inv_D */
- if (a == end) break;
- a += dc_lsize;
- }
- restore_flags(flags);
+ return;
}
a = addr & ~(sc_lsize - 1);
@@ -2081,20 +2157,10 @@ static void
r4k_dma_cache_inv_sc(unsigned long addr, unsigned long size)
{
unsigned long end, a;
- unsigned int flags;
if (size >= scache_size) {
flush_cache_all();
- } else {
- save_and_cli(flags);
- a = addr & ~(dc_lsize - 1);
- end = (addr + size) & ~(dc_lsize - 1);
- while (1) {
- flush_dcache_line(a); /* Hit_Writeback_Inv_D */
- if (a == end) break;
- a += dc_lsize;
- }
- restore_flags(flags);
+ return;
}
a = addr & ~(sc_lsize - 1);
@@ -2546,8 +2612,8 @@ __initfunc(static int probe_scache(unsigned long config))
}
restore_flags(flags);
addr -= begin;
- printk("Secondary cache sized at %dK linesize %d\n", (int) (addr >> 10),
- sc_lsize);
+ printk("Secondary cache sized at %dK linesize %d\n",
+ (int) (addr >> 10), sc_lsize);
scache_size = addr;
return 1;
}
@@ -2602,13 +2668,10 @@ __initfunc(static void setup_scache_funcs(void))
flush_page_to_ram = r4k_flush_page_to_ram_s16d16i16;
break;
case 32:
- flush_cache_all = r4k_flush_cache_all_s16d32i32;
- flush_cache_mm = r4k_flush_cache_mm_s16d32i32;
- flush_cache_range = r4k_flush_cache_range_s16d32i32;
- flush_cache_page = r4k_flush_cache_page_s16d32i32;
- flush_page_to_ram = r4k_flush_page_to_ram_s16d32i32;
- break;
+ panic("Invalid cache configuration detected");
};
+ clear_page = r4k_clear_page_s16;
+ copy_page = r4k_copy_page_s16;
break;
case 32:
switch(dc_lsize) {
@@ -2627,6 +2690,9 @@ __initfunc(static void setup_scache_funcs(void))
flush_page_to_ram = r4k_flush_page_to_ram_s32d32i32;
break;
};
+ clear_page = r4k_clear_page_s32;
+ copy_page = r4k_copy_page_s32;
+ break;
case 64:
switch(dc_lsize) {
case 16:
@@ -2644,6 +2710,9 @@ __initfunc(static void setup_scache_funcs(void))
flush_page_to_ram = r4k_flush_page_to_ram_s64d32i32;
break;
};
+ clear_page = r4k_clear_page_s64;
+ copy_page = r4k_copy_page_s64;
+ break;
case 128:
switch(dc_lsize) {
case 16:
@@ -2661,10 +2730,10 @@ __initfunc(static void setup_scache_funcs(void))
flush_page_to_ram = r4k_flush_page_to_ram_s128d32i32;
break;
};
+ clear_page = r4k_clear_page_s128;
+ copy_page = r4k_copy_page_s128;
break;
}
- clear_page = r4k_clear_page;
- copy_page = r4k_copy_page;
dma_cache_wback_inv = r4k_dma_cache_wback_inv_sc;
dma_cache_inv = r4k_dma_cache_inv_sc;
}