diff options
Diffstat (limited to 'arch/sh/mm/pg-sh7705.c')
-rw-r--r-- | arch/sh/mm/pg-sh7705.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c index 887ab9d18ccd..a4b015f95a3a 100644 --- a/arch/sh/mm/pg-sh7705.c +++ b/arch/sh/mm/pg-sh7705.c | |||
@@ -7,7 +7,9 @@ | |||
7 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * This file is subject to the terms and conditions of the GNU General Public |
8 | * License. See the file "COPYING" in the main directory of this archive | 8 | * License. See the file "COPYING" in the main directory of this archive |
9 | * for more details. | 9 | * for more details. |
10 | * | ||
10 | */ | 11 | */ |
12 | |||
11 | #include <linux/init.h> | 13 | #include <linux/init.h> |
12 | #include <linux/mman.h> | 14 | #include <linux/mman.h> |
13 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
@@ -74,6 +76,7 @@ void clear_user_page(void *to, unsigned long address, struct page *pg) | |||
74 | { | 76 | { |
75 | struct page *page = virt_to_page(to); | 77 | struct page *page = virt_to_page(to); |
76 | 78 | ||
79 | __set_bit(PG_mapped, &page->flags); | ||
77 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { | 80 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { |
78 | clear_page(to); | 81 | clear_page(to); |
79 | __flush_wback_region(to, PAGE_SIZE); | 82 | __flush_wback_region(to, PAGE_SIZE); |
@@ -92,11 +95,12 @@ void clear_user_page(void *to, unsigned long address, struct page *pg) | |||
92 | * @from: P1 address | 95 | * @from: P1 address |
93 | * @address: U0 address to be mapped | 96 | * @address: U0 address to be mapped |
94 | */ | 97 | */ |
95 | void copy_user_page(void *to, void *from, unsigned long address, | 98 | void copy_user_page(void *to, void *from, unsigned long address, struct page *pg) |
96 | struct page *pg) | ||
97 | { | 99 | { |
98 | struct page *page = virt_to_page(to); | 100 | struct page *page = virt_to_page(to); |
99 | 101 | ||
102 | |||
103 | __set_bit(PG_mapped, &page->flags); | ||
100 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { | 104 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { |
101 | copy_page(to, from); | 105 | copy_page(to, from); |
102 | __flush_wback_region(to, PAGE_SIZE); | 106 | __flush_wback_region(to, PAGE_SIZE); |
@@ -108,3 +112,26 @@ void copy_user_page(void *to, void *from, unsigned long address, | |||
108 | __flush_wback_region(to, PAGE_SIZE); | 112 | __flush_wback_region(to, PAGE_SIZE); |
109 | } | 113 | } |
110 | } | 114 | } |
115 | |||
116 | /* | ||
117 | * For SH7705, we have our own implementation for ptep_get_and_clear | ||
118 | * Copied from pg-sh4.c | ||
119 | */ | ||
120 | inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | ||
121 | { | ||
122 | pte_t pte = *ptep; | ||
123 | |||
124 | pte_clear(mm, addr, ptep); | ||
125 | if (!pte_not_present(pte)) { | ||
126 | unsigned long pfn = pte_pfn(pte); | ||
127 | if (pfn_valid(pfn)) { | ||
128 | struct page *page = pfn_to_page(pfn); | ||
129 | struct address_space *mapping = page_mapping(page); | ||
130 | if (!mapping || !mapping_writably_mapped(mapping)) | ||
131 | __clear_bit(PG_mapped, &page->flags); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | return pte; | ||
136 | } | ||
137 | |||