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>
这个提交包含在:
@@ -215,6 +215,36 @@ static void __flush_dcache_aliases(struct address_space *mapping, struct page *p
|
||||
flush_dcache_mmap_unlock(mapping);
|
||||
}
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 6
|
||||
void __sync_icache_dcache(pte_t pteval)
|
||||
{
|
||||
unsigned long pfn;
|
||||
struct page *page;
|
||||
struct address_space *mapping;
|
||||
|
||||
if (!pte_present_user(pteval))
|
||||
return;
|
||||
if (cache_is_vipt_nonaliasing() && !pte_exec(pteval))
|
||||
/* only flush non-aliasing VIPT caches for exec mappings */
|
||||
return;
|
||||
pfn = pte_pfn(pteval);
|
||||
if (!pfn_valid(pfn))
|
||||
return;
|
||||
|
||||
page = pfn_to_page(pfn);
|
||||
if (cache_is_vipt_aliasing())
|
||||
mapping = page_mapping(page);
|
||||
else
|
||||
mapping = NULL;
|
||||
|
||||
if (!test_and_set_bit(PG_dcache_clean, &page->flags))
|
||||
__flush_dcache_page(mapping, page);
|
||||
/* pte_exec() already checked above for non-aliasing VIPT cache */
|
||||
if (cache_is_vipt_nonaliasing() || pte_exec(pteval))
|
||||
__flush_icache_all();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ensure cache coherency between kernel mapping and userspace mapping
|
||||
* of this page.
|
||||
|
在新工单中引用
屏蔽一个用户