aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/asm-generic/pgtable.h13
-rw-r--r--include/asm-mips/pgtable.h2
-rw-r--r--mm/mremap.c6
3 files changed, 18 insertions, 3 deletions
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index f86c1e549466..ff28c8b31f58 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -158,6 +158,19 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
158#define lazy_mmu_prot_update(pte) do { } while (0) 158#define lazy_mmu_prot_update(pte) do { } while (0)
159#endif 159#endif
160 160
161#ifndef __HAVE_ARCH_MULTIPLE_ZERO_PAGE
162#define move_pte(pte, prot, old_addr, new_addr) (pte)
163#else
164#define move_pte(pte, prot, old_addr, new_addr) \
165({ \
166 pte_t newpte = (pte); \
167 if (pte_present(pte) && pfn_valid(pte_pfn(pte)) && \
168 pte_page(pte) == ZERO_PAGE(old_addr)) \
169 newpte = mk_pte(ZERO_PAGE(new_addr), (prot)); \
170 newpte; \
171})
172#endif
173
161/* 174/*
162 * When walking page tables, get the address of the next boundary, 175 * When walking page tables, get the address of the next boundary,
163 * or the end address of the range if that comes earlier. Although no 176 * or the end address of the range if that comes earlier. Although no
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index cbd1672c94cb..eaf5d9b3a0e1 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -68,6 +68,8 @@ extern unsigned long zero_page_mask;
68#define ZERO_PAGE(vaddr) \ 68#define ZERO_PAGE(vaddr) \
69 (virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask))) 69 (virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))
70 70
71#define __HAVE_ARCH_MULTIPLE_ZERO_PAGE
72
71extern void paging_init(void); 73extern void paging_init(void);
72 74
73/* 75/*
diff --git a/mm/mremap.c b/mm/mremap.c
index a32fed454bd7..f343fc73a8bd 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -141,10 +141,10 @@ move_one_page(struct vm_area_struct *vma, unsigned long old_addr,
141 if (dst) { 141 if (dst) {
142 pte_t pte; 142 pte_t pte;
143 pte = ptep_clear_flush(vma, old_addr, src); 143 pte = ptep_clear_flush(vma, old_addr, src);
144
144 /* ZERO_PAGE can be dependant on virtual addr */ 145 /* ZERO_PAGE can be dependant on virtual addr */
145 if (pfn_valid(pte_pfn(pte)) && 146 pte = move_pte(pte, new_vma->vm_page_prot,
146 pte_page(pte) == ZERO_PAGE(old_addr)) 147 old_addr, new_addr);
147 pte = pte_wrprotect(mk_pte(ZERO_PAGE(new_addr), new_vma->vm_page_prot));
148 set_pte_at(mm, new_addr, dst, pte); 148 set_pte_at(mm, new_addr, dst, pte);
149 } else 149 } else
150 error = -ENOMEM; 150 error = -ENOMEM;