From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933663AbbDJNVp (ORCPT ); Fri, 10 Apr 2015 09:21:45 -0400 Received: from bastet.se.axis.com ([195.60.68.11]:45552 "EHLO bastet.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S964824AbbDJNVi (ORCPT ); Fri, 10 Apr 2015 09:21:38 -0400 From: Lars Persson To: ralf@linux-mips.org, paul.burton@imgtec.com Cc: linux-mips@linux-mips.org, linux-kernel@vger.kernel.org, Lars Persson Subject: [PATCH] MIPS: Fix HIGHMEM crash in __update_cache(). Date: Fri, 10 Apr 2015 15:21:24 +0200 Message-Id: <1428672084-20676-1-git-send-email-larper@axis.com> X-Mailer: git-send-email 1.7.10.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- 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