Loading arch/mips/lib/Makefile +2 −2 Original line number Diff line number Diff line Loading @@ -2,8 +2,8 @@ # Makefile for MIPS-specific library files.. # lib-y += csum_partial_copy.o memcpy.o promlib.o \ strlen_user.o strncpy_user.o strnlen_user.o lib-y += csum_partial_copy.o memcpy.o promlib.o strlen_user.o strncpy_user.o \ strnlen_user.o uncached.o obj-y += iomap.o Loading arch/mips/lib/uncached.c 0 → 100644 +76 −0 Original line number Diff line number Diff line /* * 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 * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. * Author: Maciej W. Rozycki <macro@mips.com> */ #include <linux/init.h> #include <asm/addrspace.h> #include <asm/bug.h> #ifndef CKSEG2 #define CKSEG2 CKSSEG #endif #ifndef TO_PHYS_MASK #define TO_PHYS_MASK -1 #endif /* * FUNC is executed in one of the uncached segments, depending on its * original address as follows: * * 1. If the original address is in CKSEG0 or CKSEG1, then the uncached * segment used is CKSEG1. * 2. If the original address is in XKPHYS, then the uncached segment * used is XKPHYS(2). * 3. Otherwise it's a bug. * * The same remapping is done with the stack pointer. Stack handling * works because we don't handle stack arguments or more complex return * values, so we can avoid sharing the same stack area between a cached * and the uncached mode. */ unsigned long __init run_uncached(void *func) { register long sp __asm__("$sp"); register long ret __asm__("$2"); long lfunc = (long)func, ufunc; long usp; if (sp >= (long)CKSEG0 && sp < (long)CKSEG2) usp = CKSEG1ADDR(sp); else if ((long long)sp >= (long long)PHYS_TO_XKPHYS(0LL, 0) && (long long)sp < (long long)PHYS_TO_XKPHYS(8LL, 0)) usp = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED, XKPHYS_TO_PHYS((long long)sp)); else { BUG(); usp = sp; } if (lfunc >= (long)CKSEG0 && lfunc < (long)CKSEG2) ufunc = CKSEG1ADDR(lfunc); else if ((long long)lfunc >= (long long)PHYS_TO_XKPHYS(0LL, 0) && (long long)lfunc < (long long)PHYS_TO_XKPHYS(8LL, 0)) ufunc = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED, XKPHYS_TO_PHYS((long long)lfunc)); else { BUG(); ufunc = lfunc; } __asm__ __volatile__ ( " move $16, $sp\n" " move $sp, %1\n" " jalr %2\n" " move $sp, $16" : "=r" (ret) : "r" (usp), "r" (ufunc) : "$16", "$31"); return ret; } arch/mips/mm/c-r4k.c +2 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -1119,7 +1120,6 @@ static int __init probe_scache(void) return 1; } typedef int (*probe_func_t)(unsigned long); extern int r5k_sc_init(void); extern int rm7k_sc_init(void); Loading @@ -1127,7 +1127,6 @@ static void __init setup_scache(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config = read_c0_config(); probe_func_t probe_scache_kseg1; int sc_present = 0; /* Loading @@ -1140,8 +1139,7 @@ static void __init setup_scache(void) 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; Loading arch/mips/mm/sc-rm7k.c +8 −21 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -96,25 +97,13 @@ static void rm7k_sc_inv(unsigned long addr, unsigned long size) } /* * 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); Loading @@ -127,24 +116,22 @@ static __init void __rm7k_sc_enable(void) ".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 = { Loading @@ -164,7 +151,7 @@ void __init rm7k_sc_init(void) 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(); /* Loading include/asm-mips/cacheflush.h +3 −0 Original line number Diff line number Diff line Loading @@ -90,4 +90,7 @@ extern void (*flush_data_cache_page)(unsigned long addr); #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 */ Loading
arch/mips/lib/Makefile +2 −2 Original line number Diff line number Diff line Loading @@ -2,8 +2,8 @@ # Makefile for MIPS-specific library files.. # lib-y += csum_partial_copy.o memcpy.o promlib.o \ strlen_user.o strncpy_user.o strnlen_user.o lib-y += csum_partial_copy.o memcpy.o promlib.o strlen_user.o strncpy_user.o \ strnlen_user.o uncached.o obj-y += iomap.o Loading
arch/mips/lib/uncached.c 0 → 100644 +76 −0 Original line number Diff line number Diff line /* * 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 * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. * Author: Maciej W. Rozycki <macro@mips.com> */ #include <linux/init.h> #include <asm/addrspace.h> #include <asm/bug.h> #ifndef CKSEG2 #define CKSEG2 CKSSEG #endif #ifndef TO_PHYS_MASK #define TO_PHYS_MASK -1 #endif /* * FUNC is executed in one of the uncached segments, depending on its * original address as follows: * * 1. If the original address is in CKSEG0 or CKSEG1, then the uncached * segment used is CKSEG1. * 2. If the original address is in XKPHYS, then the uncached segment * used is XKPHYS(2). * 3. Otherwise it's a bug. * * The same remapping is done with the stack pointer. Stack handling * works because we don't handle stack arguments or more complex return * values, so we can avoid sharing the same stack area between a cached * and the uncached mode. */ unsigned long __init run_uncached(void *func) { register long sp __asm__("$sp"); register long ret __asm__("$2"); long lfunc = (long)func, ufunc; long usp; if (sp >= (long)CKSEG0 && sp < (long)CKSEG2) usp = CKSEG1ADDR(sp); else if ((long long)sp >= (long long)PHYS_TO_XKPHYS(0LL, 0) && (long long)sp < (long long)PHYS_TO_XKPHYS(8LL, 0)) usp = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED, XKPHYS_TO_PHYS((long long)sp)); else { BUG(); usp = sp; } if (lfunc >= (long)CKSEG0 && lfunc < (long)CKSEG2) ufunc = CKSEG1ADDR(lfunc); else if ((long long)lfunc >= (long long)PHYS_TO_XKPHYS(0LL, 0) && (long long)lfunc < (long long)PHYS_TO_XKPHYS(8LL, 0)) ufunc = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED, XKPHYS_TO_PHYS((long long)lfunc)); else { BUG(); ufunc = lfunc; } __asm__ __volatile__ ( " move $16, $sp\n" " move $sp, %1\n" " jalr %2\n" " move $sp, $16" : "=r" (ret) : "r" (usp), "r" (ufunc) : "$16", "$31"); return ret; }
arch/mips/mm/c-r4k.c +2 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -1119,7 +1120,6 @@ static int __init probe_scache(void) return 1; } typedef int (*probe_func_t)(unsigned long); extern int r5k_sc_init(void); extern int rm7k_sc_init(void); Loading @@ -1127,7 +1127,6 @@ static void __init setup_scache(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config = read_c0_config(); probe_func_t probe_scache_kseg1; int sc_present = 0; /* Loading @@ -1140,8 +1139,7 @@ static void __init setup_scache(void) 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; Loading
arch/mips/mm/sc-rm7k.c +8 −21 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -96,25 +97,13 @@ static void rm7k_sc_inv(unsigned long addr, unsigned long size) } /* * 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); Loading @@ -127,24 +116,22 @@ static __init void __rm7k_sc_enable(void) ".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 = { Loading @@ -164,7 +151,7 @@ void __init rm7k_sc_init(void) 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(); /* Loading
include/asm-mips/cacheflush.h +3 −0 Original line number Diff line number Diff line Loading @@ -90,4 +90,7 @@ extern void (*flush_data_cache_page)(unsigned long addr); #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 */