diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2010-09-13 10:58:37 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-09-19 07:17:45 -0400 |
commit | 85848dd7ab75fce1134856228582a8df522c91d9 (patch) | |
tree | 3b5f34bf871e983d30fad787c098e6d778d962bd /arch/arm/mm/flush.c | |
parent | 6012191aa9c6ffff3a23b81162298318b56d7cb3 (diff) |
ARM: 6381/1: Use lazy cache flushing on ARMv7 SMP systems
ARMv7 processors like Cortex-A9 broadcast the cache maintenance
operations in hardware. This patch allows the
flush_dcache_page/update_mmu_cache pair to work in lazy flushing mode
similar to the UP case.
Note that cache flushing on SMP systems now takes place via the
set_pte_at() call (__sync_icache_dcache) and there is no race with other
CPUs executing code from the new PTE before the cache flushing took
place.
Tested-by: Rabin Vincent <rabin.vincent@stericsson.com>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm/flush.c')
-rw-r--r-- | arch/arm/mm/flush.c | 13 |
1 files changed, 4 insertions, 9 deletions
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index dd5b0120b92e..2332b774c6b9 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm/smp_plat.h> | 17 | #include <asm/smp_plat.h> |
18 | #include <asm/system.h> | 18 | #include <asm/system.h> |
19 | #include <asm/tlbflush.h> | 19 | #include <asm/tlbflush.h> |
20 | #include <asm/smp_plat.h> | ||
20 | 21 | ||
21 | #include "mm.h" | 22 | #include "mm.h" |
22 | 23 | ||
@@ -93,12 +94,10 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig | |||
93 | #define flush_pfn_alias(pfn,vaddr) do { } while (0) | 94 | #define flush_pfn_alias(pfn,vaddr) do { } while (0) |
94 | #endif | 95 | #endif |
95 | 96 | ||
96 | #ifdef CONFIG_SMP | ||
97 | static void flush_ptrace_access_other(void *args) | 97 | static void flush_ptrace_access_other(void *args) |
98 | { | 98 | { |
99 | __flush_icache_all(); | 99 | __flush_icache_all(); |
100 | } | 100 | } |
101 | #endif | ||
102 | 101 | ||
103 | static | 102 | static |
104 | void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, | 103 | void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, |
@@ -122,11 +121,9 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, | |||
122 | if (vma->vm_flags & VM_EXEC) { | 121 | if (vma->vm_flags & VM_EXEC) { |
123 | unsigned long addr = (unsigned long)kaddr; | 122 | unsigned long addr = (unsigned long)kaddr; |
124 | __cpuc_coherent_kern_range(addr, addr + len); | 123 | __cpuc_coherent_kern_range(addr, addr + len); |
125 | #ifdef CONFIG_SMP | ||
126 | if (cache_ops_need_broadcast()) | 124 | if (cache_ops_need_broadcast()) |
127 | smp_call_function(flush_ptrace_access_other, | 125 | smp_call_function(flush_ptrace_access_other, |
128 | NULL, 1); | 126 | NULL, 1); |
129 | #endif | ||
130 | } | 127 | } |
131 | } | 128 | } |
132 | 129 | ||
@@ -276,12 +273,10 @@ void flush_dcache_page(struct page *page) | |||
276 | 273 | ||
277 | mapping = page_mapping(page); | 274 | mapping = page_mapping(page); |
278 | 275 | ||
279 | #ifndef CONFIG_SMP | 276 | if (!cache_ops_need_broadcast() && |
280 | if (mapping && !mapping_mapped(mapping)) | 277 | mapping && !mapping_mapped(mapping)) |
281 | clear_bit(PG_dcache_clean, &page->flags); | 278 | clear_bit(PG_dcache_clean, &page->flags); |
282 | else | 279 | else { |
283 | #endif | ||
284 | { | ||
285 | __flush_dcache_page(mapping, page); | 280 | __flush_dcache_page(mapping, page); |
286 | if (mapping && cache_is_vivt()) | 281 | if (mapping && cache_is_vivt()) |
287 | __flush_dcache_aliases(mapping, page); | 282 | __flush_dcache_aliases(mapping, page); |