diff options
-rw-r--r-- | arch/arm/mm/fault-armv.c | 4 | ||||
-rw-r--r-- | arch/arm/mm/flush.c | 2 | ||||
-rw-r--r-- | include/asm-arm/cacheflush.h | 7 | ||||
-rw-r--r-- | include/asm-arm/mmu_context.h | 5 |
4 files changed, 18 insertions, 0 deletions
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 44558d5..fbfa260 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -144,13 +144,17 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) page = pfn_to_page(pfn); mapping = page_mapping(page); if (mapping) { +#ifndef CONFIG_SMP int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); if (dirty) __flush_dcache_page(mapping, page); +#endif if (cache_is_vivt()) make_coherent(mapping, vma, addr, pfn); + else if (vma->vm_flags & VM_EXEC) + __flush_icache_all(); } } diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 9df507d..029ee65 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -199,6 +199,8 @@ void flush_dcache_page(struct page *page) __flush_dcache_page(mapping, page); if (mapping && cache_is_vivt()) __flush_dcache_aliases(mapping, page); + else if (mapping) + __flush_icache_all(); } } EXPORT_SYMBOL(flush_dcache_page); diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index 759a97b..559fb4a 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h @@ -410,6 +410,13 @@ extern void flush_dcache_page(struct page *); extern void __flush_dcache_page(struct address_space *mapping, struct page *page); +static inline void __flush_icache_all(void) +{ + asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n" + : + : "r" (0)); +} + #define ARCH_HAS_FLUSH_ANON_PAGE static inline void flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr) diff --git a/include/asm-arm/mmu_context.h b/include/asm-arm/mmu_context.h index 6913d02..91b9dfd 100644 --- a/include/asm-arm/mmu_context.h +++ b/include/asm-arm/mmu_context.h @@ -97,6 +97,11 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, #ifdef CONFIG_MMU unsigned int cpu = smp_processor_id(); +#ifdef CONFIG_SMP + /* check for possible thread migration */ + if (!cpus_empty(next->cpu_vm_mask) && !cpu_isset(cpu, next->cpu_vm_mask)) + __flush_icache_all(); +#endif if (!cpu_test_and_set(cpu, next->cpu_vm_mask) || prev != next) { check_context(next); cpu_switch_mm(next->pgd, next); |