Commit 8b5fe5e54b47 ("MIPS: Fix race condition in lazy cache flushing.") triggered NULL pointer dereferences on systems with HIGHMEM. The problem was caused by not clearing the PG_dcache_dirty flag in flush_icache_page() and thus we enter __update_cache() that lacks support for HIGHMEM. Signed-off-by: Lars Persson <larper@xxxxxxxx> --- arch/mips/include/asm/cacheflush.h | 7 +++++-- arch/mips/mm/cache.c | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h index 37d5cf9..723229f 100644 --- a/arch/mips/include/asm/cacheflush.h +++ b/arch/mips/include/asm/cacheflush.h @@ -51,6 +51,7 @@ extern void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, unsigned long end); extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); extern void __flush_dcache_page(struct page *page); +extern void __flush_icache_page(struct vm_area_struct *vma, struct page *page); #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 static inline void flush_dcache_page(struct page *page) @@ -77,8 +78,10 @@ static inline void flush_icache_page(struct vm_area_struct *vma, struct page *page) { if (!cpu_has_ic_fills_f_dc && (vma->vm_flags & VM_EXEC) && - Page_dcache_dirty(page)) - __flush_dcache_page(page); + Page_dcache_dirty(page)) { + __flush_icache_page(vma, page); + ClearPageDcacheDirty(page); + } } extern void (*flush_icache_range)(unsigned long start, unsigned long end); diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index f7b91d3..77d96db 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -119,6 +119,18 @@ void __flush_anon_page(struct page *page, unsigned long vmaddr) EXPORT_SYMBOL(__flush_anon_page); +void __flush_icache_page(struct vm_area_struct *vma, struct page *page) +{ + unsigned long addr; + + if (PageHighMem(page)) + return; + + addr = (unsigned long) page_address(page); + flush_data_cache_page(addr); +} +EXPORT_SYMBOL_GPL(__flush_icache_page); + void __update_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) { -- 1.7.10.4