kernel: update kernel 4.4 to version 4.4.3
[openwrt/openwrt.git] / target / linux / generic / patches-4.4 / 101-MIPS-fix-cache-flushing-for-highmem-pages.patch
1 From: Felix Fietkau <nbd@openwrt.org>
2 Date: Sun, 24 Jan 2016 01:03:51 +0100
3 Subject: [PATCH] MIPS: fix cache flushing for highmem pages
4
5 Most cache flush ops were no-op for highmem pages. This led to nasty
6 segfaults and (in the case of page_address(page) == NULL) kernel
7 crashes.
8
9 Fix this by always flushing highmem pages using kmap/kunmap_atomic
10 around the actual cache flush. This might be a bit inefficient, but at
11 least it's stable.
12
13 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
14 ---
15
16 --- a/arch/mips/mm/cache.c
17 +++ b/arch/mips/mm/cache.c
18 @@ -14,6 +14,7 @@
19 #include <linux/sched.h>
20 #include <linux/syscalls.h>
21 #include <linux/mm.h>
22 +#include <linux/highmem.h>
23
24 #include <asm/cacheflush.h>
25 #include <asm/processor.h>
26 @@ -78,18 +79,29 @@ SYSCALL_DEFINE3(cacheflush, unsigned lon
27 return 0;
28 }
29
30 +static void
31 +flush_highmem_page(struct page *page)
32 +{
33 + void *addr = kmap_atomic(page);
34 + flush_data_cache_page((unsigned long)addr);
35 + kunmap_atomic(addr);
36 +}
37 +
38 void __flush_dcache_page(struct page *page)
39 {
40 struct address_space *mapping = page_mapping(page);
41 unsigned long addr;
42
43 - if (PageHighMem(page))
44 - return;
45 if (mapping && !mapping_mapped(mapping)) {
46 SetPageDcacheDirty(page);
47 return;
48 }
49
50 + if (PageHighMem(page)) {
51 + flush_highmem_page(page);
52 + return;
53 + }
54 +
55 /*
56 * We could delay the flush for the !page_mapping case too. But that
57 * case is for exec env/arg pages and those are %99 certainly going to
58 @@ -105,6 +117,11 @@ void __flush_anon_page(struct page *page
59 {
60 unsigned long addr = (unsigned long) page_address(page);
61
62 + if (PageHighMem(page)) {
63 + flush_highmem_page(page);
64 + return;
65 + }
66 +
67 if (pages_do_alias(addr, vmaddr)) {
68 if (page_mapped(page) && !Page_dcache_dirty(page)) {
69 void *kaddr;
70 @@ -123,8 +140,10 @@ void __flush_icache_page(struct vm_area_
71 {
72 unsigned long addr;
73
74 - if (PageHighMem(page))
75 + if (PageHighMem(page)) {
76 + flush_highmem_page(page);
77 return;
78 + }
79
80 addr = (unsigned long) page_address(page);
81 flush_data_cache_page(addr);
82 @@ -142,12 +161,17 @@ void __update_cache(struct vm_area_struc
83 if (unlikely(!pfn_valid(pfn)))
84 return;
85 page = pfn_to_page(pfn);
86 - if (page_mapping(page) && Page_dcache_dirty(page)) {
87 + if (!Page_dcache_dirty(page) || !page_mapping(page))
88 + return;
89 +
90 + if (PageHighMem(page)) {
91 + flush_highmem_page(page);
92 + } else {
93 addr = (unsigned long) page_address(page);
94 if (exec || pages_do_alias(addr, address & PAGE_MASK))
95 flush_data_cache_page(addr);
96 - ClearPageDcacheDirty(page);
97 }
98 + ClearPageDcacheDirty(page);
99 }
100
101 unsigned long _page_cachable_default;