diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2005-09-08 10:32:23 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2005-09-08 10:32:23 -0400 |
commit | d7b6b3589471c3856f1e6dc9c77abc4af962ffdb (patch) | |
tree | 82751eba321a062ce91af7f0f0bff8c4c5531a1c | |
parent | b38d950d3aedf90c8b15b3c7c799b5eb53c47c45 (diff) |
[ARM] Fix ARMv6 VIPT cache >= 32K
This adds the necessary changes to ensure that we flush the
caches correctly with aliasing VIPT caches.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/mm/flush.c | 52 | ||||
-rw-r--r-- | include/asm-arm/cacheflush.h | 7 |
2 files changed, 58 insertions, 1 deletions
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 191788fb18d1..b0208c992576 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c | |||
@@ -16,6 +16,58 @@ | |||
16 | #include <asm/tlbflush.h> | 16 | #include <asm/tlbflush.h> |
17 | 17 | ||
18 | #ifdef CONFIG_CPU_CACHE_VIPT | 18 | #ifdef CONFIG_CPU_CACHE_VIPT |
19 | |||
20 | void flush_cache_mm(struct mm_struct *mm) | ||
21 | { | ||
22 | if (cache_is_vivt()) { | ||
23 | if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) | ||
24 | __cpuc_flush_user_all(); | ||
25 | return; | ||
26 | } | ||
27 | |||
28 | if (cache_is_vipt_aliasing()) { | ||
29 | asm( "mcr p15, 0, %0, c7, c14, 0\n" | ||
30 | " mcr p15, 0, %0, c7, c5, 0\n" | ||
31 | " mcr p15, 0, %0, c7, c10, 4" | ||
32 | : | ||
33 | : "r" (0) | ||
34 | : "cc"); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) | ||
39 | { | ||
40 | if (cache_is_vivt()) { | ||
41 | if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) | ||
42 | __cpuc_flush_user_range(start & PAGE_MASK, PAGE_ALIGN(end), | ||
43 | vma->vm_flags); | ||
44 | return; | ||
45 | } | ||
46 | |||
47 | if (cache_is_vipt_aliasing()) { | ||
48 | asm( "mcr p15, 0, %0, c7, c14, 0\n" | ||
49 | " mcr p15, 0, %0, c7, c5, 0\n" | ||
50 | " mcr p15, 0, %0, c7, c10, 4" | ||
51 | : | ||
52 | : "r" (0) | ||
53 | : "cc"); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn) | ||
58 | { | ||
59 | if (cache_is_vivt()) { | ||
60 | if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) { | ||
61 | unsigned long addr = user_addr & PAGE_MASK; | ||
62 | __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); | ||
63 | } | ||
64 | return; | ||
65 | } | ||
66 | |||
67 | if (cache_is_vipt_aliasing()) | ||
68 | flush_pfn_alias(pfn, user_addr); | ||
69 | } | ||
70 | |||
19 | #define ALIAS_FLUSH_START 0xffff4000 | 71 | #define ALIAS_FLUSH_START 0xffff4000 |
20 | 72 | ||
21 | #define TOP_PTE(x) pte_offset_kernel(top_pmd, x) | 73 | #define TOP_PTE(x) pte_offset_kernel(top_pmd, x) |
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index 035cdcff43d2..e81baff4f54b 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h | |||
@@ -256,7 +256,7 @@ extern void dmac_flush_range(unsigned long, unsigned long); | |||
256 | * Convert calls to our calling convention. | 256 | * Convert calls to our calling convention. |
257 | */ | 257 | */ |
258 | #define flush_cache_all() __cpuc_flush_kern_all() | 258 | #define flush_cache_all() __cpuc_flush_kern_all() |
259 | 259 | #ifndef CONFIG_CPU_CACHE_VIPT | |
260 | static inline void flush_cache_mm(struct mm_struct *mm) | 260 | static inline void flush_cache_mm(struct mm_struct *mm) |
261 | { | 261 | { |
262 | if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) | 262 | if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) |
@@ -279,6 +279,11 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned l | |||
279 | __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); | 279 | __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); |
280 | } | 280 | } |
281 | } | 281 | } |
282 | #else | ||
283 | extern void flush_cache_mm(struct mm_struct *mm); | ||
284 | extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); | ||
285 | extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn); | ||
286 | #endif | ||
282 | 287 | ||
283 | /* | 288 | /* |
284 | * flush_cache_user_range is used when we want to ensure that the | 289 | * flush_cache_user_range is used when we want to ensure that the |