From: David Mosberger 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: Signed-off-by: Andrew Morton --- 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 #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); _