summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/sh/include/asm/cacheflush.h37
-rw-r--r--arch/sh/include/cpu-common/cpu/cacheflush.h37
-rw-r--r--arch/sh/include/cpu-sh4/cpu/cacheflush.h31
-rw-r--r--arch/sh/include/cpu-sh5/cpu/cacheflush.h10
-rw-r--r--arch/sh/mm/cache-sh4.c87
-rw-r--r--arch/sh/mm/cache-sh5.c4
-rw-r--r--arch/sh/mm/cache.c70
-rw-r--r--arch/sh/mm/flush-sh4.c13
-rw-r--r--arch/sh/mm/init.c5
9 files changed, 159 insertions, 135 deletions
diff --git a/arch/sh/include/asm/cacheflush.h b/arch/sh/include/asm/cacheflush.h
index b1cf30f423af..25b7f46494de 100644
--- a/arch/sh/include/asm/cacheflush.h
+++ b/arch/sh/include/asm/cacheflush.h
@@ -1,46 +1,11 @@
#ifndef __ASM_SH_CACHEFLUSH_H
#define __ASM_SH_CACHEFLUSH_H
-#include <linux/mm.h>
-
#ifdef __KERNEL__
-#ifdef CONFIG_CACHE_OFF
-/*
- * Nothing to do when the cache is disabled, initial flush and explicit
- * disabling is handled at CPU init time.
- *
- * See arch/sh/kernel/cpu/init.c:cache_init().
- */
-#define flush_cache_all() do { } while (0)
-#define flush_cache_mm(mm) do { } while (0)
-#define flush_cache_dup_mm(mm) do { } while (0)
-#define flush_cache_range(vma, start, end) do { } while (0)
-#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
-#define flush_dcache_page(page) do { } while (0)
-#define flush_icache_range(start, end) do { } while (0)
-#define flush_icache_page(vma,pg) do { } while (0)
-#define flush_cache_sigtramp(vaddr) do { } while (0)
-#define __flush_wback_region(start, size) do { (void)(start); } while (0)
-#define __flush_purge_region(start, size) do { (void)(start); } while (0)
-#define __flush_invalidate_region(start, size) do { (void)(start); } while (0)
-#else
+#include <linux/mm.h>
#include <cpu/cacheflush.h>
-/*
- * Consistent DMA requires that the __flush_xxx() primitives must be set
- * for any of the enabled non-coherent caches (most of the UP CPUs),
- * regardless of PIPT or VIPT cache configurations.
- */
-
-/* Flush (write-back only) a region (smaller than a page) */
-extern void __flush_wback_region(void *start, int size);
-/* Flush (write-back & invalidate) a region (smaller than a page) */
-extern void __flush_purge_region(void *start, int size);
-/* Flush (invalidate only) a region (smaller than a page) */
-extern void __flush_invalidate_region(void *start, int size);
-#endif
-
#define ARCH_HAS_FLUSH_ANON_PAGE
extern void __flush_anon_page(struct page *page, unsigned long);
diff --git a/arch/sh/include/cpu-common/cpu/cacheflush.h b/arch/sh/include/cpu-common/cpu/cacheflush.h
index 5dc3736218e7..8189dbd68f8f 100644
--- a/arch/sh/include/cpu-common/cpu/cacheflush.h
+++ b/arch/sh/include/cpu-common/cpu/cacheflush.h
@@ -1,14 +1,12 @@
/*
- * include/asm-sh/cpu-sh2/cacheflush.h
- *
* Copyright (C) 2003 Paul Mundt
*
* 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.
*/
-#ifndef __ASM_CPU_SH2_CACHEFLUSH_H
-#define __ASM_CPU_SH2_CACHEFLUSH_H
+#ifndef __ASM_CPU_SH_CACHEFLUSH_H
+#define __ASM_CPU_SH_CACHEFLUSH_H
/*
* Cache flushing:
@@ -22,18 +20,23 @@
* - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
* - flush_icache_range(start, end) flushes(invalidates) a range for icache
* - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
- *
- * Caches are indexed (effectively) by physical address on SH-2, so
- * we don't need them.
+ * - flush_cache_sigtramp(vaddr) flushes the signal trampoline
*/
-#define flush_cache_all() do { } while (0)
-#define flush_cache_mm(mm) do { } while (0)
-#define flush_cache_dup_mm(mm) do { } while (0)
-#define flush_cache_range(vma, start, end) do { } while (0)
-#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
-#define flush_dcache_page(page) do { } while (0)
-#define flush_icache_range(start, end) do { } while (0)
-#define flush_icache_page(vma,pg) do { } while (0)
-#define flush_cache_sigtramp(vaddr) do { } while (0)
+extern void (*flush_cache_all)(void);
+extern void (*flush_cache_mm)(struct mm_struct *mm);
+extern void (*flush_cache_dup_mm)(struct mm_struct *mm);
+extern void (*flush_cache_page)(struct vm_area_struct *vma,
+ unsigned long addr, unsigned long pfn);
+extern void (*flush_cache_range)(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end);
+extern void (*flush_dcache_page)(struct page *page);
+extern void (*flush_icache_range)(unsigned long start, unsigned long end);
+extern void (*flush_icache_page)(struct vm_area_struct *vma,
+ struct page *page);
+extern void (*flush_cache_sigtramp)(unsigned long address);
+
+extern void (*__flush_wback_region)(void *start, int size);
+extern void (*__flush_purge_region)(void *start, int size);
+extern void (*__flush_invalidate_region)(void *start, int size);
-#endif /* __ASM_CPU_SH2_CACHEFLUSH_H */
+#endif /* __ASM_CPU_SH_CACHEFLUSH_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/cacheflush.h b/arch/sh/include/cpu-sh4/cpu/cacheflush.h
deleted file mode 100644
index d6bd396d7dfb..000000000000
--- a/arch/sh/include/cpu-sh4/cpu/cacheflush.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * include/asm-sh/cpu-sh4/cacheflush.h
- *
- * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2003 Paul Mundt
- *
- * 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.
- */
-#ifndef __ASM_CPU_SH4_CACHEFLUSH_H
-#define __ASM_CPU_SH4_CACHEFLUSH_H
-
-/*
- * Caches are broken on SH-4 (unless we use write-through
- * caching; in which case they're only semi-broken),
- * so we need them.
- */
-void flush_cache_all(void);
-void flush_cache_mm(struct mm_struct *mm);
-#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
-void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end);
-void flush_cache_page(struct vm_area_struct *vma, unsigned long addr,
- unsigned long pfn);
-void flush_dcache_page(struct page *pg);
-void flush_icache_range(unsigned long start, unsigned long end);
-
-#define flush_icache_page(vma,pg) do { } while (0)
-
-#endif /* __ASM_CPU_SH4_CACHEFLUSH_H */
diff --git a/arch/sh/include/cpu-sh5/cpu/cacheflush.h b/arch/sh/include/cpu-sh5/cpu/cacheflush.h
index 740d10a316ef..202f637a0e17 100644
--- a/arch/sh/include/cpu-sh5/cpu/cacheflush.h
+++ b/arch/sh/include/cpu-sh5/cpu/cacheflush.h
@@ -3,10 +3,6 @@
#ifndef __ASSEMBLY__
-struct vm_area_struct;
-struct page;
-struct mm_struct;
-
extern void flush_cache_all(void);
extern void flush_cache_mm(struct mm_struct *mm);
extern void flush_cache_sigtramp(unsigned long vaddr);
@@ -16,10 +12,14 @@ extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, uns
extern void flush_dcache_page(struct page *pg);
extern void flush_icache_range(unsigned long start, unsigned long end);
+/* XXX .. */
+extern void (*__flush_wback_region)(void *start, int size);
+extern void (*__flush_purge_region)(void *start, int size);
+extern void (*__flush_invalidate_region)(void *start, int size);
+
#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
#define flush_icache_page(vma, page) do { } while (0)
#endif /* __ASSEMBLY__ */
#endif /* __ASM_SH_CPU_SH5_CACHEFLUSH_H */
-
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index b5860535e61f..05cb04bc3940 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -26,13 +26,6 @@
#define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */
#define MAX_ICACHE_PAGES 32
-static void __flush_dcache_segment_1way(unsigned long start,
- unsigned long extent);
-static void __flush_dcache_segment_2way(unsigned long start,
- unsigned long extent);
-static void __flush_dcache_segment_4way(unsigned long start,
- unsigned long extent);
-
static void __flush_cache_4096(unsigned long addr, unsigned long phys,
unsigned long exec_offset);
@@ -45,38 +38,12 @@ static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) =
(void (*)(unsigned long, unsigned long))0xdeadbeef;
/*
- * SH-4 has virtually indexed and physically tagged cache.
- */
-void __init sh4_cache_init(void)
-{
- printk("PVR=%08x CVR=%08x PRR=%08x\n",
- ctrl_inl(CCN_PVR),
- ctrl_inl(CCN_CVR),
- ctrl_inl(CCN_PRR));
-
- switch (boot_cpu_data.dcache.ways) {
- case 1:
- __flush_dcache_segment_fn = __flush_dcache_segment_1way;
- break;
- case 2:
- __flush_dcache_segment_fn = __flush_dcache_segment_2way;
- break;
- case 4:
- __flush_dcache_segment_fn = __flush_dcache_segment_4way;
- break;
- default:
- panic("unknown number of cache ways\n");
- break;
- }
-}
-
-/*
* Write back the range of D-cache, and purge the I-cache.
*
* Called from kernel/module.c:sys_init_module and routine for a.out format,
* signal handler code and kprobes code
*/
-void flush_icache_range(unsigned long start, unsigned long end)
+static void sh4_flush_icache_range(unsigned long start, unsigned long end)
{
int icacheaddr;
unsigned long flags, v;
@@ -137,7 +104,7 @@ static inline void flush_cache_4096(unsigned long start,
* Write back & invalidate the D-cache of the page.
* (To avoid "alias" issues)
*/
-void flush_dcache_page(struct page *page)
+static void sh4_flush_dcache_page(struct page *page)
{
struct address_space *mapping = page_mapping(page);
@@ -188,7 +155,7 @@ static inline void flush_dcache_all(void)
wmb();
}
-void flush_cache_all(void)
+static void sh4_flush_cache_all(void)
{
flush_dcache_all();
flush_icache_all();
@@ -280,7 +247,7 @@ loop_exit:
*
* Caller takes mm->mmap_sem.
*/
-void flush_cache_mm(struct mm_struct *mm)
+static void sh4_flush_cache_mm(struct mm_struct *mm)
{
if (cpu_context(smp_processor_id(), mm) == NO_CONTEXT)
return;
@@ -320,8 +287,8 @@ void flush_cache_mm(struct mm_struct *mm)
* ADDR: Virtual Address (U0 address)
* PFN: Physical page number
*/
-void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
- unsigned long pfn)
+static void sh4_flush_cache_page(struct vm_area_struct *vma,
+ unsigned long address, unsigned long pfn)
{
unsigned long phys = pfn << PAGE_SHIFT;
unsigned int alias_mask;
@@ -368,8 +335,8 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
* Flushing the cache lines for U0 only isn't enough.
* We need to flush for P1 too, which may contain aliases.
*/
-void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
+static void sh4_flush_cache_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
{
if (cpu_context(smp_processor_id(), vma->vm_mm) == NO_CONTEXT)
return;
@@ -668,3 +635,41 @@ static void __flush_dcache_segment_4way(unsigned long start,
a3 += linesz;
} while (a0 < a0e);
}
+
+extern void __weak sh4__flush_region_init(void);
+
+/*
+ * SH-4 has virtually indexed and physically tagged cache.
+ */
+void __init sh4_cache_init(void)
+{
+ printk("PVR=%08x CVR=%08x PRR=%08x\n",
+ ctrl_inl(CCN_PVR),
+ ctrl_inl(CCN_CVR),
+ ctrl_inl(CCN_PRR));
+
+ switch (boot_cpu_data.dcache.ways) {
+ case 1:
+ __flush_dcache_segment_fn = __flush_dcache_segment_1way;
+ break;
+ case 2:
+ __flush_dcache_segment_fn = __flush_dcache_segment_2way;
+ break;
+ case 4:
+ __flush_dcache_segment_fn = __flush_dcache_segment_4way;
+ break;
+ default:
+ panic("unknown number of cache ways\n");
+ break;
+ }
+
+ flush_icache_range = sh4_flush_icache_range;
+ flush_dcache_page = sh4_flush_dcache_page;
+ flush_cache_all = sh4_flush_cache_all;
+ flush_cache_mm = sh4_flush_cache_mm;
+ flush_cache_dup_mm = sh4_flush_cache_mm;
+ flush_cache_page = sh4_flush_cache_page;
+ flush_cache_range = sh4_flush_cache_range;
+
+ sh4__flush_region_init();
+}
diff --git a/arch/sh/mm/cache-sh5.c b/arch/sh/mm/cache-sh5.c
index a50d23caf015..a8f5142dc2cf 100644
--- a/arch/sh/mm/cache-sh5.c
+++ b/arch/sh/mm/cache-sh5.c
@@ -20,6 +20,8 @@
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
+extern void __weak sh4__flush_region_init(void);
+
/* Wired TLB entry for the D-cache */
static unsigned long long dtlb_cache_slot;
@@ -27,6 +29,8 @@ void __init cpu_cache_init(void)
{
/* Reserve a slot for dcache colouring in the DTLB */
dtlb_cache_slot = sh64_get_wired_dtlb_entry();
+
+ sh4__flush_region_init();
}
void __init kmap_coherent_init(void)
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
index a31e5c46e7a6..da5bc6ac1b28 100644
--- a/arch/sh/mm/cache.c
+++ b/arch/sh/mm/cache.c
@@ -15,6 +15,62 @@
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
+void (*flush_cache_all)(void);
+void (*flush_cache_mm)(struct mm_struct *mm);
+void (*flush_cache_dup_mm)(struct mm_struct *mm);
+void (*flush_cache_page)(struct vm_area_struct *vma,
+ unsigned long addr, unsigned long pfn);
+void (*flush_cache_range)(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end);
+void (*flush_dcache_page)(struct page *page);
+void (*flush_icache_range)(unsigned long start, unsigned long end);
+void (*flush_icache_page)(struct vm_area_struct *vma,
+ struct page *page);
+void (*flush_cache_sigtramp)(unsigned long address);
+void (*__flush_wback_region)(void *start, int size);
+void (*__flush_purge_region)(void *start, int size);
+void (*__flush_invalidate_region)(void *start, int size);
+
+static inline void noop_flush_cache_all(void)
+{
+}
+
+static inline void noop_flush_cache_mm(struct mm_struct *mm)
+{
+}
+
+static inline void noop_flush_cache_page(struct vm_area_struct *vma,
+ unsigned long addr, unsigned long pfn)
+{
+}
+
+static inline void noop_flush_cache_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+}
+
+static inline void noop_flush_dcache_page(struct page *page)
+{
+}
+
+static inline void noop_flush_icache_range(unsigned long start,
+ unsigned long end)
+{
+}
+
+static inline void noop_flush_icache_page(struct vm_area_struct *vma,
+ struct page *page)
+{
+}
+
+static inline void noop_flush_cache_sigtramp(unsigned long address)
+{
+}
+
+static inline void noop__flush_region(void *start, int size)
+{
+}
+
void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long vaddr, void *dst, const void *src,
unsigned long len)
@@ -174,6 +230,20 @@ void __init cpu_cache_init(void)
compute_alias(&boot_cpu_data.dcache);
compute_alias(&boot_cpu_data.scache);
+ flush_cache_all = noop_flush_cache_all;
+ flush_cache_mm = noop_flush_cache_mm;
+ flush_cache_dup_mm = noop_flush_cache_mm;
+ flush_cache_page = noop_flush_cache_page;
+ flush_cache_range = noop_flush_cache_range;
+ flush_dcache_page = noop_flush_dcache_page;
+ flush_icache_range = noop_flush_icache_range;
+ flush_icache_page = noop_flush_icache_page;
+ flush_cache_sigtramp = noop_flush_cache_sigtramp;
+
+ __flush_wback_region = noop__flush_region;
+ __flush_purge_region = noop__flush_region;
+ __flush_invalidate_region = noop__flush_region;
+
if ((boot_cpu_data.family == CPU_FAMILY_SH4) ||
(boot_cpu_data.family == CPU_FAMILY_SH4A) ||
(boot_cpu_data.family == CPU_FAMILY_SH4AL_DSP)) {
diff --git a/arch/sh/mm/flush-sh4.c b/arch/sh/mm/flush-sh4.c
index 1b6b6a12a99b..99c50dc7551e 100644
--- a/arch/sh/mm/flush-sh4.c
+++ b/arch/sh/mm/flush-sh4.c
@@ -8,7 +8,7 @@
* START: Virtual Address (U0, P1, or P3)
* SIZE: Size of the region.
*/
-void __weak __flush_wback_region(void *start, int size)
+static void sh4__flush_wback_region(void *start, int size)
{
reg_size_t aligned_start, v, cnt, end;
@@ -51,7 +51,7 @@ void __weak __flush_wback_region(void *start, int size)
* START: Virtual Address (U0, P1, or P3)
* SIZE: Size of the region.
*/
-void __weak __flush_purge_region(void *start, int size)
+static void sh4__flush_purge_region(void *start, int size)
{
reg_size_t aligned_start, v, cnt, end;
@@ -90,7 +90,7 @@ void __weak __flush_purge_region(void *start, int size)
/*
* No write back please
*/
-void __weak __flush_invalidate_region(void *start, int size)
+static void sh4__flush_invalidate_region(void *start, int size)
{
reg_size_t aligned_start, v, cnt, end;
@@ -126,3 +126,10 @@ void __weak __flush_invalidate_region(void *start, int size)
cnt--;
}
}
+
+void __init sh4__flush_region_init(void)
+{
+ __flush_wback_region = sh4__flush_wback_region;
+ __flush_invalidate_region = sh4__flush_invalidate_region;
+ __flush_purge_region = sh4__flush_purge_region;
+}
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index cf0e9c5146b1..0a9b4d855bc9 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -210,6 +210,9 @@ void __init mem_init(void)
high_memory = node_high_memory;
}
+ /* Set this up early, so we can take care of the zero page */
+ cpu_cache_init();
+
/* clear the zero-page */
memset(empty_zero_page, 0, PAGE_SIZE);
__flush_wback_region(empty_zero_page, PAGE_SIZE);
@@ -230,8 +233,6 @@ void __init mem_init(void)
datasize >> 10,
initsize >> 10);
- cpu_cache_init();
-
/* Initialize the vDSO */
vsyscall_init();
}