aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/flush.c
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2010-09-13 10:58:06 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-09-19 07:17:44 -0400
commit6012191aa9c6ffff3a23b81162298318b56d7cb3 (patch)
tree8f08d869b452d66f126743bcfd73aa6f5a701605 /arch/arm/mm/flush.c
parentc01778001a4f5ad9c62d882776235f3f31922fdd (diff)
ARM: 6380/1: Introduce __sync_icache_dcache() for VIPT caches
On SMP systems, there is a small chance of a PTE becoming visible to a different CPU before the current cache maintenance operations in update_mmu_cache(). To avoid this, cache maintenance must be handled in set_pte_at() (similar to IA-64 and PowerPC). This patch provides a unified VIPT cache handling mechanism and implements the __sync_icache_dcache() function for ARMv6 onwards architectures. It is called from set_pte_at() and replaces the update_mmu_cache(). The latter is still used on VIVT hardware where a vm_area_struct is required. 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.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index b4efce9b7985..dd5b0120b92e 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -215,6 +215,36 @@ static void __flush_dcache_aliases(struct address_space *mapping, struct page *p
215 flush_dcache_mmap_unlock(mapping); 215 flush_dcache_mmap_unlock(mapping);
216} 216}
217 217
218#if __LINUX_ARM_ARCH__ >= 6
219void __sync_icache_dcache(pte_t pteval)
220{
221 unsigned long pfn;
222 struct page *page;
223 struct address_space *mapping;
224
225 if (!pte_present_user(pteval))
226 return;
227 if (cache_is_vipt_nonaliasing() && !pte_exec(pteval))
228 /* only flush non-aliasing VIPT caches for exec mappings */
229 return;
230 pfn = pte_pfn(pteval);
231 if (!pfn_valid(pfn))
232 return;
233
234 page = pfn_to_page(pfn);
235 if (cache_is_vipt_aliasing())
236 mapping = page_mapping(page);
237 else
238 mapping = NULL;
239
240 if (!test_and_set_bit(PG_dcache_clean, &page->flags))
241 __flush_dcache_page(mapping, page);
242 /* pte_exec() already checked above for non-aliasing VIPT cache */
243 if (cache_is_vipt_nonaliasing() || pte_exec(pteval))
244 __flush_icache_all();
245}
246#endif
247
218/* 248/*
219 * Ensure cache coherency between kernel mapping and userspace mapping 249 * Ensure cache coherency between kernel mapping and userspace mapping
220 * of this page. 250 * of this page.