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 | |
| 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>
| -rw-r--r-- | arch/arm/include/asm/smp_plat.h | 4 | ||||
| -rw-r--r-- | arch/arm/mm/flush.c | 13 |
2 files changed, 8 insertions, 9 deletions
diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h index e6215305544a..963a338d567b 100644 --- a/arch/arm/include/asm/smp_plat.h +++ b/arch/arm/include/asm/smp_plat.h | |||
| @@ -13,9 +13,13 @@ static inline int tlb_ops_need_broadcast(void) | |||
| 13 | return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2; | 13 | return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | #if !defined(CONFIG_SMP) || __LINUX_ARM_ARCH__ >= 7 | ||
| 17 | #define cache_ops_need_broadcast() 0 | ||
| 18 | #else | ||
| 16 | static inline int cache_ops_need_broadcast(void) | 19 | static inline int cache_ops_need_broadcast(void) |
| 17 | { | 20 | { |
| 18 | return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1; | 21 | return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1; |
| 19 | } | 22 | } |
| 23 | #endif | ||
| 20 | 24 | ||
| 21 | #endif | 25 | #endif |
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); |
