Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Russell King and committed by
Russell King
d7b6b358 b38d950d

+58 -1
+52
arch/arm/mm/flush.c
··· 16 16 #include <asm/tlbflush.h> 17 17 18 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 71 #define ALIAS_FLUSH_START 0xffff4000 20 72 21 73 #define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
+6 -1
include/asm-arm/cacheflush.h
··· 256 256 * Convert calls to our calling convention. 257 257 */ 258 258 #define flush_cache_all() __cpuc_flush_kern_all() 259 - 259 + #ifndef CONFIG_CPU_CACHE_VIPT 260 260 static inline void flush_cache_mm(struct mm_struct *mm) 261 261 { 262 262 if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) ··· 279 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 289 * flush_cache_user_range is used when we want to ensure that the