CVSROOT: /home/cvs
Module name: linux
Changes by: ths@ftp.linux-mips.org 05/04/25 17:36:23
Modified files:
arch/mips/lib : Makefile
arch/mips/mm : c-r4k.c sc-rm7k.c
include/asm-mips: cacheflush.h mipsregs.h
Added files:
arch/mips/lib : uncached.c
Log message:
Better interface to run uncached cache setup code.
diff -urN linux/arch/mips/lib/uncached.c linux/arch/mips/lib/uncached.c
--- linux/arch/mips/lib/uncached.c 1970/01/01 00:00:00
+++ linux/arch/mips/lib/uncached.c 2005-04-25 17:36:23.326575000 +0100
1.1
@@ -0,0 +1,36 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright (C) 2005 Thiemo Seufer
+ */
+#include <linux/init.h>
+
+#include <asm/addrspace.h>
+
+/*
+ * FUNC is executed in the uncached segment CKSEG1. This works only if
+ * both code and stack live in CKSEG0. The stack handling works because
+ * we don't handle stack arguments or more complex return values, so we
+ * can avoid to share the same stack area between cached and uncached
+ * mode.
+ */
+unsigned long __init run_uncached(void *func)
+{
+ register unsigned long sp __asm__("$sp");
+ register unsigned long ret __asm__("$2");
+ unsigned long usp = sp - CAC_BASE + UNCAC_BASE;
+ unsigned long ufunc = func - CAC_BASE + UNCAC_BASE;
+
+ __asm__ __volatile__ (
+ " move $16, $sp\n"
+ " move $sp, %1\n"
+ " jalr $ra, %2\n"
+ " move $sp, $16"
+ : "=&r" (ret)
+ : "r" (usp), "r" (ufunc)
+ : "$16", "$31");
+
+ return ret;
+}
diff -urN linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile
--- linux/arch/mips/lib/Makefile 2004/01/03 20:22:41 1.39
+++ linux/arch/mips/lib/Makefile 2005/04/25 16:36:23 1.40
@@ -3,6 +3,6 @@
#
lib-y += csum_partial_copy.o dec_and_lock.o memcpy.o promlib.o strlen_user.o \
- strncpy_user.o strnlen_user.o
+ strncpy_user.o strnlen_user.o uncached.o
EXTRA_AFLAGS := $(CFLAGS)
diff -urN linux/arch/mips/mm/c-r4k.c linux/arch/mips/mm/c-r4k.c
--- linux/arch/mips/mm/c-r4k.c 2005/03/18 17:36:53 1.107
+++ linux/arch/mips/mm/c-r4k.c 2005/04/25 16:36:23 1.108
@@ -26,6 +26,7 @@
#include <asm/system.h>
#include <asm/mmu_context.h>
#include <asm/war.h>
+#include <asm/cacheflush.h> /* for run_uncached() */
static unsigned long icache_size, dcache_size, scache_size;
@@ -1119,7 +1120,6 @@
return 1;
}
-typedef int (*probe_func_t)(unsigned long);
extern int r5k_sc_init(void);
extern int rm7k_sc_init(void);
@@ -1127,7 +1127,6 @@
{
struct cpuinfo_mips *c = ¤t_cpu_data;
unsigned int config = read_c0_config();
- probe_func_t probe_scache_kseg1;
int sc_present = 0;
/*
@@ -1140,8 +1139,7 @@
case CPU_R4000MC:
case CPU_R4400SC:
case CPU_R4400MC:
- probe_scache_kseg1 = (probe_func_t) (CKSEG1ADDR(&probe_scache));
- sc_present = probe_scache_kseg1(config);
+ sc_present = run_uncached(probe_scache);
if (sc_present)
c->options |= MIPS_CPU_CACHE_CDEX_S;
break;
diff -urN linux/arch/mips/mm/sc-rm7k.c linux/arch/mips/mm/sc-rm7k.c
--- linux/arch/mips/mm/sc-rm7k.c 2004/12/15 20:39:23 1.7
+++ linux/arch/mips/mm/sc-rm7k.c 2005/04/25 16:36:23 1.8
@@ -15,6 +15,7 @@
#include <asm/cacheops.h>
#include <asm/mipsregs.h>
#include <asm/processor.h>
+#include <asm/cacheflush.h> /* for run_uncached() */
/* Primary cache parameters. */
#define sc_lsize 32
@@ -96,25 +97,13 @@
}
/*
- * This function is executed in the uncached segment CKSEG1.
- * It must not touch the stack, because the stack pointer still points
- * into CKSEG0.
- *
- * Three options:
- * - Write it in assembly and guarantee that we don't use the stack.
- * - Disable caching for CKSEG0 before calling it.
- * - Pray that GCC doesn't randomly start using the stack.
- *
- * This being Linux, we obviously take the least sane of those options -
- * following DaveM's lead in c-r4k.c
- *
- * It seems we get our kicks from relying on unguaranteed behaviour in GCC
+ * This function is executed in uncached address space.
*/
static __init void __rm7k_sc_enable(void)
{
int i;
- set_c0_config(1 << 3); /* CONF_SE */
+ set_c0_config(R7K_CONF_SE);
write_c0_taglo(0);
write_c0_taghi(0);
@@ -127,24 +116,22 @@
".set mips0\n\t"
".set reorder"
:
- : "r" (KSEG0ADDR(i)), "i" (Index_Store_Tag_SD));
+ : "r" (CKSEG0ADDR(i)), "i" (Index_Store_Tag_SD));
}
}
static __init void rm7k_sc_enable(void)
{
- void (*func)(void) = (void *) KSEG1ADDR(&__rm7k_sc_enable);
-
- if (read_c0_config() & 0x08) /* CONF_SE */
+ if (read_c0_config() & R7K_CONF_SE)
return;
printk(KERN_INFO "Enabling secondary cache...");
- func();
+ run_uncached(__rm7k_sc_enable);
}
static void rm7k_sc_disable(void)
{
- clear_c0_config(1<<3); /* CONF_SE */
+ clear_c0_config(R7K_CONF_SE);
}
struct bcache_ops rm7k_sc_ops = {
@@ -164,7 +151,7 @@
printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n",
(scache_size >> 10), sc_lsize);
- if (!((config >> 3) & 1)) /* CONF_SE */
+ if (!(config & R7K_CONF_SE))
rm7k_sc_enable();
/*
diff -urN linux/include/asm-mips/cacheflush.h
linux/include/asm-mips/cacheflush.h
--- linux/include/asm-mips/cacheflush.h 2005/03/18 17:38:08 1.17
+++ linux/include/asm-mips/cacheflush.h 2005/04/25 16:36:23 1.18
@@ -90,4 +90,7 @@
#define ClearPageDcacheDirty(page) \
clear_bit(PG_dcache_dirty, &(page)->flags)
+/* Run kernel code uncached, useful for cache probing functions. */
+unsigned long __init run_uncached(void *func);
+
#endif /* _ASM_CACHEFLUSH_H */
diff -urN linux/include/asm-mips/mipsregs.h linux/include/asm-mips/mipsregs.h
--- linux/include/asm-mips/mipsregs.h 2005/02/06 21:24:55 1.70
+++ linux/include/asm-mips/mipsregs.h 2005/04/25 16:36:23 1.71
@@ -433,6 +433,9 @@
#define R5K_CONF_SE (_ULCAST_(1) << 12)
#define R5K_CONF_SS (_ULCAST_(3) << 20)
+/* Bits specific to the RM7000. */
+#define R7K_CONF_SE (_ULCAST_(1) << 3)
+
/* Bits specific to the R10000. */
#define R10K_CONF_DN (_ULCAST_(3) << 3)
#define R10K_CONF_CT (_ULCAST_(1) << 5)
|