From: Nick Piggin <nickpiggin@yahoo.com.au>

Move the ZERO_PAGE remapping complexity to the move_pte macro in
asm-generic, have it conditionally depend on
__HAVE_ARCH_MULTIPLE_ZERO_PAGE, which gets defined for MIPS.

For architectures without __HAVE_ARCH_MULTIPLE_ZERO_PAGE, move_pte becomes
a noop.

Signed-off-by: Nick Piggin <npiggin@suse.de>
Cc: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 include/asm-generic/pgtable.h |   12 ++++++++++++
 include/asm-mips/pgtable.h    |    2 ++
 mm/mremap.c                   |    6 +++---
 3 files changed, 17 insertions(+), 3 deletions(-)

diff -puN include/asm-generic/pgtable.h~mm-move_pte-to-remap-zero_page include/asm-generic/pgtable.h
--- 25/include/asm-generic/pgtable.h~mm-move_pte-to-remap-zero_page	Fri Sep  9 17:19:52 2005
+++ 25-akpm/include/asm-generic/pgtable.h	Fri Sep  9 17:19:52 2005
@@ -158,6 +158,18 @@ static inline void ptep_set_wrprotect(st
 #define lazy_mmu_prot_update(pte)	do { } while (0)
 #endif
 
+#ifndef __HAVE_ARCH_MULTIPLE_ZERO_PAGE
+#define move_pte(pte, prot, old_addr, new_addr)	(pte)
+#else
+#define move_pte(pte, prot, old_addr, new_addr)				\
+({									\
+ 	pte_t newpte = (pte);						\
+	if (pfn_valid(pte_pfn(pte)) && pte_page(pte) == ZERO_PAGE(old_addr)) \
+		newpte = mk_pte(ZERO_PAGE(new_addr), (prot)));		\
+	newpte;								\
+})
+#endif
+
 /*
  * When walking page tables, get the address of the next boundary,
  * or the end address of the range if that comes earlier.  Although no
diff -puN include/asm-mips/pgtable.h~mm-move_pte-to-remap-zero_page include/asm-mips/pgtable.h
--- 25/include/asm-mips/pgtable.h~mm-move_pte-to-remap-zero_page	Fri Sep  9 17:19:52 2005
+++ 25-akpm/include/asm-mips/pgtable.h	Fri Sep  9 17:19:52 2005
@@ -68,6 +68,8 @@ extern unsigned long zero_page_mask;
 #define ZERO_PAGE(vaddr) \
 	(virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))
 
+#define __HAVE_ARCH_MULTIPLE_ZERO_PAGE
+
 extern void paging_init(void);
 
 /*
diff -puN mm/mremap.c~mm-move_pte-to-remap-zero_page mm/mremap.c
--- 25/mm/mremap.c~mm-move_pte-to-remap-zero_page	Fri Sep  9 17:19:52 2005
+++ 25-akpm/mm/mremap.c	Fri Sep  9 17:19:52 2005
@@ -141,10 +141,10 @@ move_one_page(struct vm_area_struct *vma
 			if (dst) {
 				pte_t pte;
 				pte = ptep_clear_flush(vma, old_addr, src);
+
 				/* ZERO_PAGE can be dependant on virtual addr */
-				if (pfn_valid(pte_pfn(pte)) &&
-					pte_page(pte) == ZERO_PAGE(old_addr))
-					pte = pte_wrprotect(mk_pte(ZERO_PAGE(new_addr), new_vma->vm_page_prot));
+				pte = move_pte(pte, new_vma->vm_page_prot,
+							old_addr, new_addr);
 				set_pte_at(mm, new_addr, dst, pte);
 			} else
 				error = -ENOMEM;
_