
From: David Mosberger <davidm@napali.hpl.hp.com>

Changeset

  roland@redhat.com[torvalds]|ChangeSet|20040624165002|30880

inadvertently broke ia64 because the patch assumed that pgd_offset_k() is
just an optimization of pgd_offset(), which it is not.  This patch fixes
the problem by introducing pgd_offset_gate().  On architectures on which
the gate area lives in the user's address-space, this should be aliased to
pgd_offset() and on architectures on which the gate area lives in the
kernel-mapped segment, this should be aliased to pgd_offset_k().

This bug was found and tracked down by Peter Chubb.

Signed-off-by: <davidm@hpl.hp.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/include/asm-generic/pgtable.h |    4 ++++
 25-akpm/include/asm-ia64/pgtable.h    |    6 ++++++
 25-akpm/mm/memory.c                   |    2 +-
 3 files changed, 11 insertions(+), 1 deletion(-)

diff -puN include/asm-generic/pgtable.h~ia64-ptrace-fix-fix include/asm-generic/pgtable.h
--- 25/include/asm-generic/pgtable.h~ia64-ptrace-fix-fix	2004-07-07 22:20:26.222314224 -0700
+++ 25-akpm/include/asm-generic/pgtable.h	2004-07-07 22:20:26.229313160 -0700
@@ -122,4 +122,8 @@ static inline void ptep_mkdirty(pte_t *p
 #define page_test_and_clear_young(page) (0)
 #endif
 
+#ifndef __HAVE_ARCH_PGD_OFFSET_GATE
+#define pgd_offset_gate(mm, addr)	pgd_offset(mm, addr)
+#endif
+
 #endif /* _ASM_GENERIC_PGTABLE_H */
diff -puN include/asm-ia64/pgtable.h~ia64-ptrace-fix-fix include/asm-ia64/pgtable.h
--- 25/include/asm-ia64/pgtable.h~ia64-ptrace-fix-fix	2004-07-07 22:20:26.223314072 -0700
+++ 25-akpm/include/asm-ia64/pgtable.h	2004-07-07 22:20:26.230313008 -0700
@@ -321,6 +321,11 @@ pgd_offset (struct mm_struct *mm, unsign
 #define pgd_offset_k(addr) \
 	(init_mm.pgd + (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)))
 
+/* Look up a pgd entry in the gate area.  On IA-64, the gate-area
+   resides in the kernel-mapped segment, hence we use pgd_offset_k()
+   here.  */
+#define pgd_offset_gate(mm, addr)	pgd_offset_k(addr)
+
 /* Find an entry in the second-level page table.. */
 #define pmd_offset(dir,addr) \
 	((pmd_t *) pgd_page(*(dir)) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)))
@@ -552,6 +557,7 @@ do {											\
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTEP_MKDIRTY
 #define __HAVE_ARCH_PTE_SAME
+#define __HAVE_ARCH_PGD_OFFSET_GATE
 #include <asm-generic/pgtable.h>
 
 #endif /* _ASM_IA64_PGTABLE_H */
diff -puN mm/memory.c~ia64-ptrace-fix-fix mm/memory.c
--- 25/mm/memory.c~ia64-ptrace-fix-fix	2004-07-07 22:20:26.225313768 -0700
+++ 25-akpm/mm/memory.c	2004-07-07 22:20:26.231312856 -0700
@@ -728,7 +728,7 @@ int get_user_pages(struct task_struct *t
 			pte_t *pte;
 			if (write) /* user gate pages are read-only */
 				return i ? : -EFAULT;
-			pgd = pgd_offset(mm, pg);
+			pgd = pgd_offset_gate(mm, pg);
 			if (!pgd)
 				return i ? : -EFAULT;
 			pmd = pmd_offset(pgd, pg);
_
