aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2009-04-10 16:52:08 -0400
committerMike Frysinger <vapier@gentoo.org>2009-06-12 06:03:45 -0400
commit5d89137a17ca804ee60077f5d4ad8d7ca60f0614 (patch)
treee6445551fdb86ffdbb3da14b8ab91d0e05c94612 /arch
parentf82e0a0c67621df83458753aef580a3508d5428e (diff)
Blackfin: fix data cache flushing when doing icache flushing
Make sure we flush all data caches and their write buffers before flushing icache, otherwise random edge cases could crop up where stale data is read into icache from external memory. As fallout, punt the combined icache + dcache flush function since we cannot safely do them back to back -- the SSYNC is needed between the dcache flush and the icache flush. Signed-off-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/blackfin/include/asm/cacheflush.h35
-rw-r--r--arch/blackfin/kernel/bfin_ksyms.c1
-rw-r--r--arch/blackfin/mach-common/cache.S16
3 files changed, 16 insertions, 36 deletions
diff --git a/arch/blackfin/include/asm/cacheflush.h b/arch/blackfin/include/asm/cacheflush.h
index 1b040f5b4feb..d7726ab486ff 100644
--- a/arch/blackfin/include/asm/cacheflush.h
+++ b/arch/blackfin/include/asm/cacheflush.h
@@ -30,7 +30,8 @@
30#ifndef _BLACKFIN_CACHEFLUSH_H 30#ifndef _BLACKFIN_CACHEFLUSH_H
31#define _BLACKFIN_CACHEFLUSH_H 31#define _BLACKFIN_CACHEFLUSH_H
32 32
33extern void blackfin_icache_dcache_flush_range(unsigned long start_address, unsigned long end_address); 33#include <asm/blackfin.h> /* for SSYNC() */
34
34extern void blackfin_icache_flush_range(unsigned long start_address, unsigned long end_address); 35extern void blackfin_icache_flush_range(unsigned long start_address, unsigned long end_address);
35extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned long end_address); 36extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned long end_address);
36extern void blackfin_dcache_invalidate_range(unsigned long start_address, unsigned long end_address); 37extern void blackfin_dcache_invalidate_range(unsigned long start_address, unsigned long end_address);
@@ -54,32 +55,28 @@ extern void blackfin_invalidate_entire_dcache(void);
54 55
55static inline void flush_icache_range(unsigned start, unsigned end) 56static inline void flush_icache_range(unsigned start, unsigned end)
56{ 57{
57#if defined(CONFIG_BFIN_DCACHE) && defined(CONFIG_BFIN_ICACHE) 58#if defined(CONFIG_BFIN_WB)
58 59 blackfin_dcache_flush_range(start, end);
59# if defined(CONFIG_BFIN_WT) 60#endif
60 blackfin_icache_flush_range((start), (end));
61 flush_icache_range_others(start, end);
62# else
63 blackfin_icache_dcache_flush_range((start), (end));
64# endif
65
66#else
67 61
68# if defined(CONFIG_BFIN_ICACHE) 62 /* Make sure all write buffers in the data side of the core
69 blackfin_icache_flush_range((start), (end)); 63 * are flushed before trying to invalidate the icache. This
64 * needs to be after the data flush and before the icache
65 * flush so that the SSYNC does the right thing in preventing
66 * the instruction prefetcher from hitting things in cached
67 * memory at the wrong time -- it runs much further ahead than
68 * the pipeline.
69 */
70 SSYNC();
71#if defined(CONFIG_BFIN_ICACHE)
72 blackfin_icache_flush_range(start, end);
70 flush_icache_range_others(start, end); 73 flush_icache_range_others(start, end);
71# endif
72# if defined(CONFIG_BFIN_DCACHE)
73 blackfin_dcache_flush_range((start), (end));
74# endif
75
76#endif 74#endif
77} 75}
78 76
79#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ 77#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
80do { memcpy(dst, src, len); \ 78do { memcpy(dst, src, len); \
81 flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ 79 flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \
82 flush_icache_range_others((unsigned long) (dst), (unsigned long) (dst) + (len));\
83} while (0) 80} while (0)
84 81
85#define copy_from_user_page(vma, page, vaddr, dst, src, len) memcpy(dst, src, len) 82#define copy_from_user_page(vma, page, vaddr, dst, src, len) memcpy(dst, src, len)
diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c
index 01f917d58b59..53e893ff708a 100644
--- a/arch/blackfin/kernel/bfin_ksyms.c
+++ b/arch/blackfin/kernel/bfin_ksyms.c
@@ -16,7 +16,6 @@ EXPORT_SYMBOL(bfin_return_from_exception);
16 16
17/* All the Blackfin cache functions: mach-common/cache.S */ 17/* All the Blackfin cache functions: mach-common/cache.S */
18EXPORT_SYMBOL(blackfin_dcache_invalidate_range); 18EXPORT_SYMBOL(blackfin_dcache_invalidate_range);
19EXPORT_SYMBOL(blackfin_icache_dcache_flush_range);
20EXPORT_SYMBOL(blackfin_icache_flush_range); 19EXPORT_SYMBOL(blackfin_icache_flush_range);
21EXPORT_SYMBOL(blackfin_dcache_flush_range); 20EXPORT_SYMBOL(blackfin_dcache_flush_range);
22EXPORT_SYMBOL(blackfin_dflush_page); 21EXPORT_SYMBOL(blackfin_dflush_page);
diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S
index aa0648c6a9fe..c295e8f837c0 100644
--- a/arch/blackfin/mach-common/cache.S
+++ b/arch/blackfin/mach-common/cache.S
@@ -80,22 +80,6 @@ ENTRY(_blackfin_icache_flush_range)
80 do_flush IFLUSH, , nop 80 do_flush IFLUSH, , nop
81ENDPROC(_blackfin_icache_flush_range) 81ENDPROC(_blackfin_icache_flush_range)
82 82
83/* Flush all cache lines assocoiated with this area of memory. */
84ENTRY(_blackfin_icache_dcache_flush_range)
85/*
86 * Walkaround to avoid loading wrong instruction after invalidating icache
87 * and following sequence is met.
88 *
89 * 1) One instruction address is cached in the instruction cache.
90 * 2) This instruction in SDRAM is changed.
91 * 3) IFLASH[P0] is executed only once in blackfin_icache_flush_range().
92 * 4) This instruction is executed again, but the old one is loaded.
93 */
94 P0 = R0;
95 IFLUSH[P0];
96 do_flush FLUSH, IFLUSH
97ENDPROC(_blackfin_icache_dcache_flush_range)
98
99/* Throw away all D-cached data in specified region without any obligation to 83/* Throw away all D-cached data in specified region without any obligation to
100 * write them back. Since the Blackfin ISA does not have an "invalidate" 84 * write them back. Since the Blackfin ISA does not have an "invalidate"
101 * instruction, we use flush/invalidate. Perhaps as a speed optimization we 85 * instruction, we use flush/invalidate. Perhaps as a speed optimization we