Stuff was ripped out of the patch by hand to separate kgdb and other debugging crud. diff -urpN linux-2.5.50/arch/i386/Kconfig highpmd-2.5.50-3/arch/i386/Kconfig --- linux-2.5.50/arch/i386/Kconfig 2002-11-27 14:35:50.000000000 -0800 +++ highpmd-2.5.50-3/arch/i386/Kconfig 2002-12-03 19:46:35.000000000 -0800 @@ -720,6 +720,10 @@ config HIGHPTE low memory. Setting this option will put user-space page table entries in high memory. +config HIGHPMD + bool "Allocate 2nd-level pagetables from highmem" + depends on HIGHMEM4G || HIGHMEM64G + config MATH_EMULATION bool "Math emulation" ---help--- diff -urpN linux-2.5.50/arch/i386/kernel/acpi.c highpmd-2.5.50-3/arch/i386/kernel/acpi.c --- linux-2.5.50/arch/i386/kernel/acpi.c 2002-11-27 14:36:18.000000000 -0800 +++ highpmd-2.5.50-3/arch/i386/kernel/acpi.c 2002-12-02 16:18:01.000000000 -0800 @@ -489,13 +489,14 @@ static void acpi_create_identity_pmd (vo set_pte(ptep + i, pfn_pte(i, PAGE_SHARED)); pgd = pgd_offset(current->active_mm, 0); - pmd = pmd_alloc(current->mm,pgd, 0); + pmd = pmd_alloc_map(current->mm,pgd, 0); /* save the old pmd */ saved_pmd = *pmd; /* set the new one */ set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(ptep))); + pmd_unmap(pmd); /* flush the TLB */ local_flush_tlb(); diff -urpN linux-2.5.50/arch/i386/kernel/vm86.c highpmd-2.5.50-3/arch/i386/kernel/vm86.c --- linux-2.5.50/arch/i386/kernel/vm86.c 2002-11-27 14:35:50.000000000 -0800 +++ highpmd-2.5.50-3/arch/i386/kernel/vm86.c 2002-12-02 16:18:01.000000000 -0800 @@ -136,12 +136,14 @@ static void mark_screen_rdonly(struct ta pgd_clear(pgd); goto out; } - pmd = pmd_offset(pgd, 0xA0000); - if (pmd_none(*pmd)) + pmd = pmd_offset_map(pgd, 0xA0000); + if (pmd_none(*pmd)) { + pmd_unmap(pmd); goto out; - if (pmd_bad(*pmd)) { + } else if (pmd_bad(*pmd)) { pmd_ERROR(*pmd); pmd_clear(pmd); + pmd_unmap(pmd); goto out; } pte = mapped = pte_offset_map(pmd, 0xA0000); @@ -151,6 +153,7 @@ static void mark_screen_rdonly(struct ta pte++; } pte_unmap(mapped); + pmd_unmap(pmd); out: spin_unlock(&tsk->mm->page_table_lock); preempt_enable(); diff -urpN linux-2.5.50/arch/i386/lib/usercopy.c highpmd-2.5.50-3/arch/i386/lib/usercopy.c --- linux-2.5.50/arch/i386/lib/usercopy.c 2002-11-27 14:35:46.000000000 -0800 +++ highpmd-2.5.50-3/arch/i386/lib/usercopy.c 2002-12-10 19:22:19.000000000 -0800 @@ -6,6 +6,7 @@ * Copyright 1997 Linus Torvalds */ #include +#include #include #include @@ -96,8 +97,43 @@ do { \ unsigned long clear_user(void *to, unsigned long n) { - if (access_ok(VERIFY_WRITE, to, n)) - __do_clear_user(to, n); + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + unsigned long addr = (unsigned long)to; + + if (!access_ok(VERIFY_WRITE, to, n)) { + printk("access to %p not okay in clear_user()!\n", to); + return 0; + } + + printk("about to clear user around %p\n", to); + + pgd = pgd_offset(current->mm, addr); + printk("pgd = %Lx\n", *pgd); + + pmd = pmd_offset_map(pgd, addr); + printk("pmd = %Lx\n", *pmd); + + if (pmd_none(*pmd)) + printk("pmd_none(*pmd)!!!\n"); + else if (pmd_bad(*pmd)) + printk("bad pmd!!\n"); + else if (!pmd_present(*pmd)) + printk("pmd not present!\n"); + else { + pte = pte_offset_map(pmd, addr); + printk("pte = %Lx\n", *pte); + if (pte_none(*pte)) + printk("pte none!\n"); + else if (!pte_present(*pte)) + printk("pte not present\n"); + else + printk("pte pfn == %lx\n", pte_pfn(*pte)); + pte_unmap(pte); + } + pmd_unmap(pmd); + __do_clear_user(to, n); return n; } diff -urpN linux-2.5.50/arch/i386/mm/fault.c highpmd-2.5.50-3/arch/i386/mm/fault.c --- linux-2.5.50/arch/i386/mm/fault.c 2002-11-27 14:35:46.000000000 -0800 +++ highpmd-2.5.50-3/arch/i386/mm/fault.c 2002-12-10 19:56:27.000000000 -0800 @@ -411,11 +456,14 @@ vmalloc_fault: goto no_context; set_pgd(pgd, *pgd_k); - pmd = pmd_offset(pgd, address); - pmd_k = pmd_offset(pgd_k, address); - if (!pmd_present(*pmd_k)) + pmd = pmd_offset_map(pgd, address); + pmd_k = pmd_offset_kernel(pgd_k, address); + if (!pmd_present(*pmd_k)) { + pmd_unmap(pmd); goto no_context; + } set_pmd(pmd, *pmd_k); + pmd_unmap(pmd); pte_k = pte_offset_kernel(pmd_k, address); if (!pte_present(*pte_k)) diff -urpN linux-2.5.50/arch/i386/mm/hugetlbpage.c highpmd-2.5.50-3/arch/i386/mm/hugetlbpage.c --- linux-2.5.50/arch/i386/mm/hugetlbpage.c 2002-11-27 14:36:19.000000000 -0800 +++ highpmd-2.5.50-3/arch/i386/mm/hugetlbpage.c 2002-12-02 16:18:01.000000000 -0800 @@ -169,7 +169,7 @@ static pte_t *huge_pte_alloc(struct mm_s pmd_t *pmd = NULL; pgd = pgd_offset(mm, addr); - pmd = pmd_alloc(mm, pgd, addr); + pmd = pmd_alloc_map(mm, pgd, addr); return (pte_t *) pmd; } @@ -179,7 +179,7 @@ static pte_t *huge_pte_offset(struct mm_ pmd_t *pmd = NULL; pgd = pgd_offset(mm, addr); - pmd = pmd_offset(pgd, addr); + pmd = pmd_offset_map(pgd, addr); return (pte_t *) pmd; } @@ -228,8 +228,10 @@ static int make_hugetlb_pages_present(un if ((pte) && (pte_none(*pte))) { if (anon_get_hugetlb_page(mm, vma, write ? VM_WRITE : VM_READ, - pte) == -1) + pte) == -1) { goto out_error; + pmd_unmap(pte); + } } else goto out_error; addr += HPAGE_SIZE; @@ -271,6 +273,8 @@ copy_hugetlb_page_range(struct mm_struct set_pte(dst_pte, entry); dst->rss += (HPAGE_SIZE / PAGE_SIZE); addr += HPAGE_SIZE; + pmd_unmap_nested(src_pte); + pmd_unmap(dst_pte); } return 0; @@ -291,10 +295,10 @@ follow_hugetlb_page(struct mm_struct *mm do { pstart = start; - ptep = huge_pte_offset(mm, start); - pte = *ptep; back1: + ptep = huge_pte_offset(mm, start); + pte = *ptep; page = pte_page(pte); if (pages) { page += ((start & ~HPAGE_MASK) >> PAGE_SHIFT); @@ -306,8 +310,10 @@ back1: len--; start += PAGE_SIZE; if (((start & HPAGE_MASK) == pstart) && len && - (start < vma->vm_end)) + (start < vma->vm_end)) { + pmd_unmap(ptep); goto back1; + } } while (len && start < vma->vm_end); *length = len; *st = start; diff -urpN linux-2.5.50/arch/i386/mm/init.c highpmd-2.5.50-3/arch/i386/mm/init.c --- linux-2.5.50/arch/i386/mm/init.c 2002-11-27 14:36:16.000000000 -0800 +++ highpmd-2.5.50-3/arch/i386/mm/init.c 2002-12-02 21:33:27.000000000 -0800 @@ -56,10 +56,10 @@ static pmd_t * __init one_md_table_init( #if CONFIG_X86_PAE pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); - if (pmd_table != pmd_offset(pgd, 0)) + if (pmd_table != pmd_offset_kernel(pgd, 0)) BUG(); #else - pmd_table = pmd_offset(pgd, 0); + pmd_table = pmd_offset_kernel(pgd, 0); #endif return pmd_table; @@ -106,7 +106,7 @@ static void __init page_table_range_init if (pgd_none(*pgd)) one_md_table_init(pgd); - pmd = pmd_offset(pgd, vaddr); + pmd = pmd_offset_kernel(pgd, vaddr); for (; (pmd_ofs < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_ofs++) { if (pmd_none(*pmd)) one_page_table_init(pmd); @@ -185,7 +185,7 @@ pte_t *kmap_pte; pgprot_t kmap_prot; #define kmap_get_fixmap_pte(vaddr) \ - pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) + pte_offset_kernel(pmd_offset_kernel(pgd_offset_k(vaddr), (vaddr)), (vaddr)) void __init kmap_init(void) { @@ -209,7 +209,7 @@ void __init permanent_kmaps_init(pgd_t * page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base); pgd = swapper_pg_dir + __pgd_offset(vaddr); - pmd = pmd_offset(pgd, vaddr); + pmd = pmd_offset_kernel(pgd, vaddr); pte = pte_offset_kernel(pmd, vaddr); pkmap_page_table = pte; } diff -urpN linux-2.5.50/arch/i386/mm/ioremap.c highpmd-2.5.50-3/arch/i386/mm/ioremap.c --- linux-2.5.50/arch/i386/mm/ioremap.c 2002-11-27 14:35:53.000000000 -0800 +++ highpmd-2.5.50-3/arch/i386/mm/ioremap.c 2002-12-02 17:10:25.000000000 -0800 @@ -82,13 +82,16 @@ static int remap_area_pages(unsigned lon spin_lock(&init_mm.page_table_lock); do { pmd_t *pmd; - pmd = pmd_alloc(&init_mm, dir, address); + pmd = pmd_alloc_map(&init_mm, dir, address); error = -ENOMEM; if (!pmd) break; if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) + phys_addr + address, flags)) { + pmd_unmap(pmd); break; + } + pmd_unmap(pmd); error = 0; address = (address + PGDIR_SIZE) & PGDIR_MASK; dir++; diff -urpN linux-2.5.50/arch/i386/mm/pageattr.c highpmd-2.5.50-3/arch/i386/mm/pageattr.c --- linux-2.5.50/arch/i386/mm/pageattr.c 2002-11-27 14:35:59.000000000 -0800 +++ highpmd-2.5.50-3/arch/i386/mm/pageattr.c 2002-12-02 16:18:01.000000000 -0800 @@ -16,7 +16,7 @@ static inline pte_t *lookup_address(unsigned long address) { pgd_t *pgd = pgd_offset_k(address); - pmd_t *pmd = pmd_offset(pgd, address); + pmd_t *pmd = pmd_offset_kernel(pgd, address); if (pmd_large(*pmd)) return (pte_t *)pmd; return pte_offset_kernel(pmd, address); @@ -60,7 +60,7 @@ static void set_pmd_pte(pte_t *kpte, uns spin_lock(&mmlist_lock); list_for_each(l, &init_mm.mmlist) { struct mm_struct *mm = list_entry(l, struct mm_struct, mmlist); - pmd_t *pmd = pmd_offset(pgd_offset(mm, address), address); + pmd_t *pmd = pmd_offset_kernel(pgd_offset(mm, address), address); set_pte_atomic((pte_t *)pmd, pte); } spin_unlock(&mmlist_lock); @@ -75,7 +75,7 @@ static void set_pmd_pte(pte_t *kpte, uns static inline void revert_page(struct page *kpte_page, unsigned long address) { pte_t *linear = (pte_t *) - pmd_offset(pgd_offset(&init_mm, address), address); + pmd_offset_kernel(pgd_offset(&init_mm, address), address); set_pmd_pte(linear, address, pfn_pte((__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); diff -urpN linux-2.5.50/arch/i386/mm/pgtable.c highpmd-2.5.50-3/arch/i386/mm/pgtable.c --- linux-2.5.50/arch/i386/mm/pgtable.c 2002-11-27 14:36:24.000000000 -0800 +++ highpmd-2.5.50-3/arch/i386/mm/pgtable.c 2002-12-08 01:39:29.000000000 -0800 @@ -68,8 +68,9 @@ static void set_pte_pfn(unsigned long va BUG(); return; } - pmd = pmd_offset(pgd, vaddr); + pmd = pmd_offset_map(pgd, vaddr); if (pmd_none(*pmd)) { + pmd_unmap(pmd); BUG(); return; } @@ -108,7 +109,7 @@ void set_pmd_pfn(unsigned long vaddr, un printk ("set_pmd_pfn: pgd_none\n"); return; /* BUG(); */ } - pmd = pmd_offset(pgd, vaddr); + pmd = pmd_offset_kernel(pgd, vaddr); set_pmd(pmd, pfn_pmd(pfn, flags)); /* * It's enough to flush this one mapping. @@ -168,18 +169,29 @@ struct page *pte_alloc_one(struct mm_str #if CONFIG_X86_PAE +#ifdef CONFIG_HIGHPMD +#define GFP_PMD (GFP_KERNEL | __GFP_HIGHMEM) +#else +#define GFP_PMD GFP_KERNEL +#endif + pgd_t *pgd_alloc(struct mm_struct *mm) { int i; pgd_t *pgd = kmem_cache_alloc(pae_pgd_cachep, GFP_KERNEL); if (pgd) { + printk("allocating pmd's:\n"); for (i = 0; i < USER_PTRS_PER_PGD; i++) { - unsigned long pmd = __get_free_page(GFP_KERNEL); - if (!pmd) + struct page *page = alloc_page(GFP_PMD); + unsigned long long pmd_paddr; + if (!page) goto out_oom; - clear_page(pmd); - set_pgd(pgd + i, __pgd(1 + __pa(pmd))); + printk("pmd_pfn = %lx\n", page_to_pfn(page)); + pmd_paddr = ((unsigned long long)page_to_pfn(page)) << PAGE_SHIFT; + clear_highpage(page); + set_pgd(pgd + i, __pgd(1 + pmd_paddr)); + printk("pmd_paddr = %Lx, pgd = %Lx\n", pmd_paddr, pgd_val(pgd[i])); } memcpy(pgd + USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD, @@ -188,7 +200,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm) return pgd; out_oom: for (i--; i >= 0; i--) - free_page((unsigned long)__va(pgd_val(pgd[i])-1)); + __free_page(pgd_page(pgd[i])); kmem_cache_free(pae_pgd_cachep, pgd); return NULL; } @@ -198,7 +210,7 @@ void pgd_free(pgd_t *pgd) int i; for (i = 0; i < USER_PTRS_PER_PGD; i++) - free_page((unsigned long)__va(pgd_val(pgd[i])-1)); + __free_page(pgd_page(pgd[i])); kmem_cache_free(pae_pgd_cachep, pgd); } diff -urpN linux-2.5.50/fs/exec.c highpmd-2.5.50-3/fs/exec.c --- linux-2.5.50/fs/exec.c 2002-11-27 14:35:57.000000000 -0800 +++ highpmd-2.5.50-3/fs/exec.c 2002-12-09 23:55:47.000000000 -0800 @@ -300,14 +300,16 @@ void put_dirty_page(struct task_struct * pgd = pgd_offset(tsk->mm, address); spin_lock(&tsk->mm->page_table_lock); - pmd = pmd_alloc(tsk->mm, pgd, address); + pmd = pmd_alloc_map(tsk->mm, pgd, address); if (!pmd) goto out; pte = pte_alloc_map(tsk->mm, pmd, address); - if (!pte) + if (!pte) { + pmd_unmap(pmd); goto out; - if (!pte_none(*pte)) { + } if (!pte_none(*pte)) { pte_unmap(pte); + pmd_unmap(pmd); goto out; } lru_cache_add_active(page); @@ -317,6 +319,7 @@ void put_dirty_page(struct task_struct * page_add_rmap(page, pte); pte_unmap(pte); tsk->mm->rss++; + pmd_unmap(pmd); spin_unlock(&tsk->mm->page_table_lock); /* no need for flush_tlb */ diff -urpN linux-2.5.50/include/asm-i386/highmem.h highpmd-2.5.50-3/include/asm-i386/highmem.h --- linux-2.5.50/include/asm-i386/highmem.h 2002-11-27 14:35:49.000000000 -0800 +++ highpmd-2.5.50-3/include/asm-i386/highmem.h 2002-12-02 16:18:01.000000000 -0800 @@ -24,6 +24,7 @@ #include #include #include +#include /* declarations for highmem.c */ extern unsigned long highstart_pfn, highend_pfn; @@ -51,6 +52,8 @@ extern void kmap_init(void); extern void * FASTCALL(kmap_high(struct page *page)); extern void FASTCALL(kunmap_high(struct page *page)); +extern void *page_address(struct page *page); +extern struct page *highmem_start_page; void *kmap(struct page *page); void kunmap(struct page *page); diff -urpN linux-2.5.50/include/asm-i386/kmap_types.h highpmd-2.5.50-3/include/asm-i386/kmap_types.h --- linux-2.5.50/include/asm-i386/kmap_types.h 2002-11-27 14:36:16.000000000 -0800 +++ highpmd-2.5.50-3/include/asm-i386/kmap_types.h 2002-12-02 16:18:01.000000000 -0800 @@ -20,11 +20,13 @@ D(6) KM_BIO_DST_IRQ, D(7) KM_PTE0, D(8) KM_PTE1, D(9) KM_PTE2, -D(10) KM_IRQ0, -D(11) KM_IRQ1, -D(12) KM_CRYPTO_USER, -D(13) KM_CRYPTO_SOFTIRQ, -D(14) KM_TYPE_NR +D(10) KM_PMD0, +D(11) KM_PMD1, +D(12) KM_IRQ0, +D(13) KM_IRQ1, +D(14) KM_CRYPTO_USER, +D(15) KM_CRYPTO_SOFTIRQ, +D(16) KM_TYPE_NR }; #undef D diff -urpN linux-2.5.50/include/asm-i386/pgalloc.h highpmd-2.5.50-3/include/asm-i386/pgalloc.h --- linux-2.5.50/include/asm-i386/pgalloc.h 2002-11-27 14:35:49.000000000 -0800 +++ highpmd-2.5.50-3/include/asm-i386/pgalloc.h 2002-12-02 16:18:01.000000000 -0800 @@ -45,10 +45,13 @@ static inline void pte_free(struct page * (In the PAE case we free the pmds as part of the pgd.) */ -#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); }) -#define pmd_free(x) do { } while (0) -#define __pmd_free_tlb(tlb,x) do { } while (0) -#define pgd_populate(mm, pmd, pte) BUG() +#define pmd_alloc_one(mm, addr) ({ BUG(); ((struct page *)2); }) +#define pmd_alloc_one_kernel(mm, addr) ({ BUG(); ((struct page *)2); }) +#define pmd_free(x) do { } while (0) +#define pmd_free_kernel(x) do { } while (0) +#define __pmd_free_tlb(tlb,x) do { } while (0) +#define pgd_populate(mm, pmd, pte) BUG() +#define pgd_populate_kernel(mm, pmd, pte) BUG() #define check_pgt_cache() do { } while (0) diff -urpN linux-2.5.50/include/asm-i386/pgtable-2level.h highpmd-2.5.50-3/include/asm-i386/pgtable-2level.h --- linux-2.5.50/include/asm-i386/pgtable-2level.h 2002-11-27 14:36:01.000000000 -0800 +++ highpmd-2.5.50-3/include/asm-i386/pgtable-2level.h 2002-12-02 16:41:56.000000000 -0800 @@ -48,13 +48,15 @@ static inline int pgd_present(pgd_t pgd) #define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) #define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval) -#define pgd_page(pgd) \ -((unsigned long) __va(pgd_val(pgd) & PAGE_MASK)) - -static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) +static inline pmd_t *pmd_offset_map(pgd_t * dir, unsigned long address) { return (pmd_t *) dir; } + +#define pmd_offset_map_nested(dir, address) pmd_offset_map(dir, address) +#define pmd_unmap(pmd) do { ; } while (0) +#define pmd_unmap_nested(pmd) do { ; } while (0) + #define ptep_get_and_clear(xp) __pte(xchg(&(xp)->pte_low, 0)) #define pte_same(a, b) ((a).pte_low == (b).pte_low) #define pte_page(x) pfn_to_page(pte_pfn(x)) diff -urpN linux-2.5.50/include/asm-i386/pgtable-3level.h highpmd-2.5.50-3/include/asm-i386/pgtable-3level.h --- linux-2.5.50/include/asm-i386/pgtable-3level.h 2002-11-27 14:36:17.000000000 -0800 +++ highpmd-2.5.50-3/include/asm-i386/pgtable-3level.h 2002-12-02 21:55:12.000000000 -0800 @@ -64,12 +64,37 @@ static inline void set_pte(pte_t *ptep, */ static inline void pgd_clear (pgd_t * pgd) { } -#define pgd_page(pgd) \ -((unsigned long) __va(pgd_val(pgd) & PAGE_MASK)) +#define pgd_pfn(pgd) (pgd_val(pgd) >> PAGE_SHIFT) +#define pgd_page(pgd) (pfn_to_page(pgd_pfn(pgd))) +#define pgd_addr(pgd) (pgd_val(pgd) & PAGE_MASK) /* Find an entry in the second-level page table.. */ -#define pmd_offset(dir, address) ((pmd_t *) pgd_page(*(dir)) + \ - __pmd_offset(address)) +#define pmd_offset_kernel(pgd, addr) \ + ((pmd_t *)__va(pgd_addr(*(pgd))) + __pmd_offset(addr)) + +#ifdef CONFIG_HIGHPMD +struct page; +#include +void *kmap_atomic(struct page *, enum km_type); +void kunmap_atomic(void *, enum km_type); + +#define pmd_offset_map(dir, addr) \ + ((pmd_t *)kmap_atomic(pgd_page(*(dir)),KM_PMD0)+__pmd_offset(addr)) + +#define pmd_offset_map_nested(dir, addr) \ + ((pmd_t *)kmap_atomic(pgd_page(*(dir)),KM_PMD1)+__pmd_offset(addr)) + +#define pmd_unmap(pmd) kunmap_atomic(pmd, KM_PMD0) +#define pmd_unmap_nested(pmd) kunmap_atomic(pmd, KM_PMD1) + +#else /* !CONFIG_HIGHPMD */ + +#define pmd_offset_map(pgd, addr) pmd_offset_kernel(pgd, addr) +#define pmd_offset_map_nested(pgd, addr) pmd_offset_map(pgd, addr) +#define pmd_unmap(pmd) do { ; } while (0) +#define pmd_unmap_nested(pmd) do { ; } while (0) + +#endif /* !CONFIG_HIGHPMD */ static inline pte_t ptep_get_and_clear(pte_t *ptep) { diff -urpN linux-2.5.50/include/linux/highmem.h highpmd-2.5.50-3/include/linux/highmem.h --- linux-2.5.50/include/linux/highmem.h 2002-11-27 14:36:16.000000000 -0800 +++ highpmd-2.5.50-3/include/linux/highmem.h 2002-12-02 16:18:01.000000000 -0800 @@ -9,6 +9,7 @@ extern struct page *highmem_start_page; +#include #include /* declarations for linux/mm/highmem.c */ diff -urpN linux-2.5.50/include/linux/mm.h highpmd-2.5.50-3/include/linux/mm.h --- linux-2.5.50/include/linux/mm.h 2002-11-27 14:35:48.000000000 -0800 +++ highpmd-2.5.50-3/include/linux/mm.h 2002-12-02 16:18:01.000000000 -0800 @@ -367,7 +367,7 @@ extern int remap_page_range(struct vm_ar extern int zeromap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long size, pgprot_t prot); extern int vmtruncate(struct inode * inode, loff_t offset); -extern pmd_t *FASTCALL(__pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)); +extern pmd_t *FASTCALL(__pmd_alloc_map(struct mm_struct *mm, pgd_t *pgd, unsigned long address)); extern pte_t *FASTCALL(pte_alloc_kernel(struct mm_struct *mm, pmd_t *pmd, unsigned long address)); extern pte_t *FASTCALL(pte_alloc_map(struct mm_struct *mm, pmd_t *pmd, unsigned long address)); extern int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, unsigned long prot); @@ -429,11 +429,15 @@ static inline int set_page_dirty(struct * inlining and the symmetry break with pte_alloc_map() that does all * of this out-of-line. */ -static inline pmd_t *pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address) + +#ifdef CONFIG_HIGHMEM +#include +#endif +static inline pmd_t *pmd_alloc_map(struct mm_struct *mm, pgd_t *pgd, unsigned long address) { if (pgd_none(*pgd)) - return __pmd_alloc(mm, pgd, address); - return pmd_offset(pgd, address); + return __pmd_alloc_map(mm, pgd, address); + return pmd_offset_map(pgd, address); } extern void free_area_init(unsigned long * zones_size); diff -urpN linux-2.5.50/mm/fremap.c highpmd-2.5.50-3/mm/fremap.c --- linux-2.5.50/mm/fremap.c 2002-11-27 14:35:48.000000000 -0800 +++ highpmd-2.5.50-3/mm/fremap.c 2002-12-02 16:59:20.000000000 -0800 @@ -56,7 +56,7 @@ int install_page(struct mm_struct *mm, s pgd = pgd_offset(mm, addr); spin_lock(&mm->page_table_lock); - pmd = pmd_alloc(mm, pgd, addr); + pmd = pmd_alloc_map(mm, pgd, addr); if (!pmd) goto err_unlock; @@ -76,12 +76,13 @@ int install_page(struct mm_struct *mm, s page_add_rmap(page, pte); pte_unmap(pte); flush_tlb_page(vma, addr); - + pmd_unmap(pmd); spin_unlock(&mm->page_table_lock); return 0; err_unlock: + pmd_unmap(pmd); spin_unlock(&mm->page_table_lock); return err; } diff -urpN linux-2.5.50/mm/memory.c highpmd-2.5.50-3/mm/memory.c --- linux-2.5.50/mm/memory.c 2002-11-27 14:35:59.000000000 -0800 +++ highpmd-2.5.50-3/mm/memory.c 2002-12-11 17:07:26.000000000 -0800 @@ -89,6 +89,7 @@ static inline void free_one_pmd(mmu_gath return; if (pmd_bad(*dir)) { pmd_ERROR(*dir); + BUG(); pmd_clear(dir); return; } @@ -110,13 +111,14 @@ static inline void free_one_pgd(mmu_gath pgd_clear(dir); return; } - pmd = pmd_offset(dir, 0); + pmd = pmd_offset_map(dir, 0); pgd_clear(dir); for (j = 0; j < PTRS_PER_PMD ; j++) { prefetchw(pmd+j+(PREFETCH_STRIDE/16)); free_one_pmd(tlb, pmd+j); } pmd_free_tlb(tlb, pmd); + pmd_unmap(pmd); } /* @@ -138,15 +140,21 @@ void clear_page_tables(mmu_gather_t *tlb pte_t * pte_alloc_map(struct mm_struct *mm, pmd_t *pmd, unsigned long address) { + pte_t *pte; + if (!pmd_present(*pmd)) { struct page *new; + pgd_t *pgd; + pmd_unmap(pmd); spin_unlock(&mm->page_table_lock); new = pte_alloc_one(mm, address); spin_lock(&mm->page_table_lock); if (!new) return NULL; + pgd = pgd_offset(mm, address); + pmd = pmd_offset_map(mm, address); /* * Because we dropped the lock, we should re-check the * entry, as somebody else could have populated it.. @@ -159,9 +167,9 @@ pte_t * pte_alloc_map(struct mm_struct * pmd_populate(mm, pmd, new); } out: - if (pmd_present(*pmd)) - return pte_offset_map(pmd, address); - return NULL; + pte = pmd_present(*pmd) ? pte_offset_map(pmd, address) : NULL; + pmd_unmap(pmd); + return pte; } pte_t * pte_alloc_kernel(struct mm_struct *mm, pmd_t *pmd, unsigned long address) @@ -211,8 +219,12 @@ int copy_page_range(struct mm_struct *ds unsigned long end = vma->vm_end; unsigned long cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE; - if (is_vm_hugetlb_page(vma)) + printk("enter copy_page_range()\n"); + + if (is_vm_hugetlb_page(vma)) { + printk("return copy_hugetlb_page_range()\n"); return copy_hugetlb_page_range(dst, src, vma); + } src_pgd = pgd_offset(src, address)-1; dst_pgd = pgd_offset(dst, address)-1; @@ -235,8 +247,8 @@ skip_copy_pmd_range: address = (address continue; } - src_pmd = pmd_offset(src_pgd, address); - dst_pmd = pmd_alloc(dst, dst_pgd, address); + dst_pmd = pmd_alloc_map(dst, dst_pgd, address); + src_pmd = pmd_offset_map_nested(src_pgd, address); if (!dst_pmd) goto nomem; @@ -249,6 +261,7 @@ skip_copy_pmd_range: address = (address goto skip_copy_pte_range; if (pmd_bad(*src_pmd)) { pmd_ERROR(*src_pmd); + BUG(); pmd_clear(src_pmd); skip_copy_pte_range: address = (address + PMD_SIZE) & PMD_MASK; if (address >= end) @@ -256,10 +269,16 @@ skip_copy_pte_range: address = (address goto cont_copy_pmd_range; } + /* You've got to be kidding me, this can't + * sleep because the pmd is kmapped... + */ + pmd_unmap_nested(src_pmd); dst_pte = pte_alloc_map(dst, dst_pmd, address); if (!dst_pte) goto nomem; spin_lock(&src->page_table_lock); + dst_pmd = pmd_offset_map(dst_pgd, address); + src_pmd = pmd_offset_map_nested(src_pgd, address); src_pte = pte_offset_map_nested(src_pmd, address); do { pte_t pte = *src_pte; @@ -315,12 +334,16 @@ cont_copy_pte_range_noset: address += PA cont_copy_pmd_range: src_pmd++; dst_pmd++; } while ((unsigned long)src_pmd & PMD_TABLE_MASK); + pmd_unmap_nested(src_pmd-1); + pmd_unmap(dst_pmd-1); } out_unlock: spin_unlock(&src->page_table_lock); out: + printk("return 0 from copy_page_range()\n"); return 0; nomem: + printk("return -ENOMEM from copy_page_range()\n"); return -ENOMEM; } @@ -333,6 +356,7 @@ static void zap_pte_range(mmu_gather_t * return; if (pmd_bad(*pmd)) { pmd_ERROR(*pmd); + BUG(); pmd_clear(pmd); return; } @@ -383,7 +407,7 @@ static void zap_pmd_range(mmu_gather_t * pgd_clear(dir); return; } - pmd = pmd_offset(dir, address); + pmd = pmd_offset_map(dir, address); end = address + size; if (end > ((address + PGDIR_SIZE) & PGDIR_MASK)) end = ((address + PGDIR_SIZE) & PGDIR_MASK); @@ -392,13 +416,17 @@ static void zap_pmd_range(mmu_gather_t * address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address < end); + pmd_unmap(pmd-1); } void unmap_page_range(mmu_gather_t *tlb, struct vm_area_struct *vma, unsigned long address, unsigned long end) { pgd_t * dir; + printk("enter unmap_page_range()\n"); + if (is_vm_hugetlb_page(vma)) { + printk("return unmap_hugepage_range()\n"); unmap_hugepage_range(vma, address, end); return; } @@ -413,6 +441,7 @@ void unmap_page_range(mmu_gather_t *tlb, dir++; } while (address && (address < end)); tlb_end_vma(tlb, vma); + printk("return from unmap_page_range()\n"); } /* Dispose of an entire mmu_gather_t per rescheduling point */ @@ -442,7 +471,10 @@ void zap_page_range(struct vm_area_struc mmu_gather_t *tlb; unsigned long end, block; + printk("enter zap_page_range()\n"); + if (is_vm_hugetlb_page(vma)) { + printk("return zap_hugepage_range()\n"); zap_hugepage_range(vma, address, size); return; } @@ -471,6 +503,7 @@ void zap_page_range(struct vm_area_struc } spin_unlock(&mm->page_table_lock); + printk("return from zap_page_range()\n"); } /* @@ -489,9 +522,12 @@ follow_page(struct mm_struct *mm, unsign if (pgd_none(*pgd) || pgd_bad(*pgd)) goto out; - pmd = pmd_offset(pgd, address); - if (pmd_none(*pmd) || pmd_bad(*pmd)) + pmd = pmd_offset_map(pgd, address); + if (pmd_none(*pmd) || pmd_bad(*pmd)) { + BUG_ON(pmd_bad(*pmd)); + pmd_unmap(pmd); goto out; + } ptep = pte_offset_map(pmd, address); if (!ptep) @@ -499,6 +535,7 @@ follow_page(struct mm_struct *mm, unsign pte = *ptep; pte_unmap(ptep); + pmd_unmap(pmd); if (pte_present(pte)) { if (!write || (pte_write(pte) && pte_dirty(pte))) { pfn = pte_pfn(pte); @@ -647,6 +684,8 @@ int zeromap_page_range(struct vm_area_st unsigned long end = address + size; struct mm_struct *mm = vma->vm_mm; + printk("enter zeromap_page_range()\n"); + dir = pgd_offset(mm, address); flush_cache_range(vma, beg, end); if (address >= end) @@ -654,11 +693,12 @@ int zeromap_page_range(struct vm_area_st spin_lock(&mm->page_table_lock); do { - pmd_t *pmd = pmd_alloc(mm, dir, address); + pmd_t *pmd = pmd_alloc_map(mm, dir, address); error = -ENOMEM; if (!pmd) break; error = zeromap_pmd_range(mm, pmd, address, end - address, prot); + pmd_unmap(pmd); if (error) break; address = (address + PGDIR_SIZE) & PGDIR_MASK; @@ -666,6 +706,7 @@ int zeromap_page_range(struct vm_area_st } while (address && (address < end)); flush_tlb_range(vma, beg, end); spin_unlock(&mm->page_table_lock); + printk("return %d from zeromap_page_range()\n", error); return error; } @@ -727,6 +768,8 @@ int remap_page_range(struct vm_area_stru unsigned long end = from + size; struct mm_struct *mm = vma->vm_mm; + printk("enter remap_page_range()\n"); + phys_addr -= from; dir = pgd_offset(mm, from); flush_cache_range(vma, beg, end); @@ -735,11 +778,12 @@ int remap_page_range(struct vm_area_stru spin_lock(&mm->page_table_lock); do { - pmd_t *pmd = pmd_alloc(mm, dir, from); + pmd_t *pmd = pmd_alloc_map(mm, dir, from); error = -ENOMEM; if (!pmd) break; error = remap_pmd_range(mm, pmd, from, end - from, phys_addr + from, prot); + pmd_unmap(pmd); if (error) break; from = (from + PGDIR_SIZE) & PGDIR_MASK; @@ -747,6 +791,7 @@ int remap_page_range(struct vm_area_stru } while (from && (from < end)); flush_tlb_range(vma, beg, end); spin_unlock(&mm->page_table_lock); + printk("return %d from remap_page_range()\n", error); return error; } @@ -803,6 +848,8 @@ static int do_wp_page(struct mm_struct * struct page *old_page, *new_page; unsigned long pfn = pte_pfn(pte); + printk("in do_wp_page()\n"); + if (!pfn_valid(pfn)) goto bad_wp_page; old_page = pfn_to_page(pfn); @@ -814,11 +861,13 @@ static int do_wp_page(struct mm_struct * flush_cache_page(vma, address); establish_pte(vma, address, page_table, pte_mkyoung(pte_mkdirty(pte_mkwrite(pte)))); pte_unmap(page_table); + pmd_unmap(pmd); spin_unlock(&mm->page_table_lock); return VM_FAULT_MINOR; } } pte_unmap(page_table); + pmd_unmap(pmd); /* * Ok, we need to copy. Oh, well.. @@ -835,6 +884,7 @@ static int do_wp_page(struct mm_struct * * Re-check the pte - we dropped the lock */ spin_lock(&mm->page_table_lock); + pmd = pmd_offset_map(mm->pgd, address); page_table = pte_offset_map(pmd, address); if (pte_same(*page_table, pte)) { if (PageReserved(old_page)) @@ -848,6 +898,7 @@ static int do_wp_page(struct mm_struct * new_page = old_page; } pte_unmap(page_table); + pmd_unmap(pmd); spin_unlock(&mm->page_table_lock); page_cache_release(new_page); page_cache_release(old_page); @@ -989,7 +1040,10 @@ static int do_swap_page(struct mm_struct pte_t pte; int ret = VM_FAULT_MINOR; + printk("in do_swap_page()\n"); + pte_unmap(page_table); + pmd_unmap(pmd); spin_unlock(&mm->page_table_lock); page = lookup_swap_cache(entry); if (!page) { @@ -1001,12 +1055,14 @@ static int do_swap_page(struct mm_struct * we released the page table lock. */ spin_lock(&mm->page_table_lock); + pmd = pmd_offset_map(mm->pgd, address); page_table = pte_offset_map(pmd, address); if (pte_same(*page_table, orig_pte)) ret = VM_FAULT_OOM; else ret = VM_FAULT_MINOR; pte_unmap(page_table); + pmd_unmap(pmd); spin_unlock(&mm->page_table_lock); goto out; } @@ -1024,9 +1080,11 @@ static int do_swap_page(struct mm_struct * released the page table lock. */ spin_lock(&mm->page_table_lock); + pmd = pmd_offset_map(mm->pgd, address); page_table = pte_offset_map(pmd, address); if (!pte_same(*page_table, orig_pte)) { pte_unmap(page_table); + pmd_unmap(pmd); spin_unlock(&mm->page_table_lock); unlock_page(page); page_cache_release(page); @@ -1054,6 +1112,7 @@ static int do_swap_page(struct mm_struct /* No need to invalidate - it was non-present before */ update_mmu_cache(vma, address, pte); pte_unmap(page_table); + pmd_unmap(pmd); spin_unlock(&mm->page_table_lock); out: return ret; @@ -1069,6 +1128,8 @@ static int do_anonymous_page(struct mm_s pte_t entry; struct page * page = ZERO_PAGE(addr); + printk("in do_anonymous_page()\n"); + /* Read-only mapping of ZERO_PAGE. */ entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot)); @@ -1076,6 +1137,7 @@ static int do_anonymous_page(struct mm_s if (write_access) { /* Allocate our own private page. */ pte_unmap(page_table); + pmd_unmap(pmd); spin_unlock(&mm->page_table_lock); page = alloc_page(GFP_HIGHUSER); @@ -1084,10 +1146,12 @@ static int do_anonymous_page(struct mm_s clear_user_highpage(page, addr); spin_lock(&mm->page_table_lock); + pmd = pmd_offset_map(mm->pgd, addr); page_table = pte_offset_map(pmd, addr); if (!pte_none(*page_table)) { pte_unmap(page_table); + pmd_unmap(pmd); page_cache_release(page); spin_unlock(&mm->page_table_lock); return VM_FAULT_MINOR; @@ -1102,6 +1166,7 @@ static int do_anonymous_page(struct mm_s set_pte(page_table, entry); page_add_rmap(page, page_table); /* ignores ZERO_PAGE */ pte_unmap(page_table); + pmd_unmap(pmd); /* No need to invalidate - it was non-present before */ update_mmu_cache(vma, addr, entry); @@ -1130,12 +1195,19 @@ static int do_no_page(struct mm_struct * struct page * new_page; pte_t entry; - if (!vma->vm_ops || !vma->vm_ops->nopage) + printk("in do_no_page()\n"); + + if (!vma->vm_ops || !vma->vm_ops->nopage) { + printk("do_no_page(): falling back to do_anonymous_page()\n"); return do_anonymous_page(mm, vma, page_table, pmd, write_access, address); + } pte_unmap(page_table); + pmd_unmap(pmd); spin_unlock(&mm->page_table_lock); + printk("about to call ->nopage()\n"); new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, 0); + printk("survived calling ->nopage()\n"); /* no page was available -- either SIGBUS or OOM */ if (new_page == NOPAGE_SIGBUS) @@ -1148,8 +1220,10 @@ static int do_no_page(struct mm_struct * */ if (write_access && !(vma->vm_flags & VM_SHARED)) { struct page * page = alloc_page(GFP_HIGHUSER); + printk("in write_access branch\n"); if (!page) { page_cache_release(new_page); + printk("we're OOM\n"); return VM_FAULT_OOM; } copy_user_highpage(page, new_page, address); @@ -1159,7 +1233,10 @@ static int do_no_page(struct mm_struct * } spin_lock(&mm->page_table_lock); + pmd = pmd_offset_map(mm->pgd, address); page_table = pte_offset_map(pmd, address); + printk("did foo_offset_map() stuff\n"); + printk("pmd = %Lx, pte = %Lx\n", *pmd, *page_table); /* * This silly early PAGE_DIRTY setting removes a race @@ -1173,6 +1250,7 @@ static int do_no_page(struct mm_struct * */ /* Only go through if we didn't race with anybody else... */ if (pte_none(*page_table)) { + printk("we didn't race\n"); ++mm->rss; flush_page_to_ram(new_page); flush_icache_page(vma, new_page); @@ -1182,9 +1260,12 @@ static int do_no_page(struct mm_struct * set_pte(page_table, entry); page_add_rmap(new_page, page_table); pte_unmap(page_table); + pmd_unmap(pmd); } else { + printk("we raced\n"); /* One of our sibling threads was faster, back out. */ pte_unmap(page_table); + pmd_unmap(pmd); page_cache_release(new_page); spin_unlock(&mm->page_table_lock); return VM_FAULT_MINOR; @@ -1193,6 +1274,7 @@ static int do_no_page(struct mm_struct * /* no need to invalidate: a not-present page shouldn't be cached */ update_mmu_cache(vma, address, entry); spin_unlock(&mm->page_table_lock); + printk("major fault\n"); return VM_FAULT_MAJOR; } @@ -1244,6 +1326,7 @@ static inline int handle_pte_fault(struc entry = pte_mkyoung(entry); establish_pte(vma, address, pte, entry); pte_unmap(pte); + pmd_unmap(pmd); spin_unlock(&mm->page_table_lock); return VM_FAULT_MINOR; } @@ -1256,6 +1339,10 @@ int handle_mm_fault(struct mm_struct *mm { pgd_t *pgd; pmd_t *pmd; + pte_t *pte; + int error = VM_FAULT_OOM; + + /* printk("enter handle_mm_fault()\n"); */ current->state = TASK_RUNNING; pgd = pgd_offset(mm, address); @@ -1266,15 +1353,21 @@ int handle_mm_fault(struct mm_struct *mm * and the SMP-safe atomic PTE updates. */ spin_lock(&mm->page_table_lock); - pmd = pmd_alloc(mm, pgd, address); - - if (pmd) { - pte_t * pte = pte_alloc_map(mm, pmd, address); - if (pte) - return handle_pte_fault(mm, vma, address, write_access, pte, pmd); + pmd = pmd_alloc_map(mm, pgd, address); + if (!pmd) { + spin_unlock(&mm->page_table_lock); + goto out; } - spin_unlock(&mm->page_table_lock); - return VM_FAULT_OOM; + + pte = pte_alloc_map(mm, pmd, address); + if (pte) + error = handle_pte_fault(mm, vma, address, write_access, pte, pmd); + else + spin_unlock(&mm->page_table_lock); +out: + if (error != VM_FAULT_MINOR && error != VM_FAULT_MAJOR) + printk("return %d from handle_mm_fault()\n", error); + return error; } /* @@ -1288,7 +1381,7 @@ int handle_mm_fault(struct mm_struct *mm */ pmd_t *__pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address) { - pmd_t *new; + struct page *new; spin_unlock(&mm->page_table_lock); new = pmd_alloc_one(mm, address); @@ -1306,7 +1399,7 @@ pmd_t *__pmd_alloc(struct mm_struct *mm, } pgd_populate(mm, pgd, new); out: - return pmd_offset(pgd, address); + return pmd_offset_map(pgd, address); } int make_pages_present(unsigned long addr, unsigned long end) @@ -1338,7 +1431,7 @@ struct page * vmalloc_to_page(void * vma pte_t *ptep, pte; if (!pgd_none(*pgd)) { - pmd = pmd_offset(pgd, addr); + pmd = pmd_offset_map(pgd, addr); if (!pmd_none(*pmd)) { preempt_disable(); ptep = pte_offset_map(pmd, addr); @@ -1348,6 +1441,7 @@ struct page * vmalloc_to_page(void * vma pte_unmap(ptep); preempt_enable(); } + pmd_unmap(pmd); } return page; } diff -urpN linux-2.5.50/mm/mprotect.c highpmd-2.5.50-3/mm/mprotect.c --- linux-2.5.50/mm/mprotect.c 2002-11-27 14:35:58.000000000 -0800 +++ highpmd-2.5.50-3/mm/mprotect.c 2002-12-10 17:08:56.000000000 -0800 @@ -34,6 +34,7 @@ change_pte_range(pmd_t *pmd, unsigned lo return; if (pmd_bad(*pmd)) { pmd_ERROR(*pmd); + BUG(); pmd_clear(pmd); return; } @@ -73,7 +74,7 @@ change_pmd_range(pgd_t *pgd, unsigned lo pgd_clear(pgd); return; } - pmd = pmd_offset(pgd, address); + pmd = pmd_offset_map(pgd, address); address &= ~PGDIR_MASK; end = address + size; if (end > PGDIR_SIZE) @@ -83,6 +84,7 @@ change_pmd_range(pgd_t *pgd, unsigned lo address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address && (address < end)); + pmd_unmap(pmd-1); } static void diff -urpN linux-2.5.50/mm/mremap.c highpmd-2.5.50-3/mm/mremap.c --- linux-2.5.50/mm/mremap.c 2002-11-27 14:36:02.000000000 -0800 +++ highpmd-2.5.50-3/mm/mremap.c 2002-12-10 17:09:09.000000000 -0800 @@ -36,12 +36,15 @@ static pte_t *get_one_pte_map_nested(str goto end; } - pmd = pmd_offset(pgd, addr); - if (pmd_none(*pmd)) + pmd = pmd_offset_map_nested(pgd, addr); + if (pmd_none(*pmd)) { + pmd_unmap_nested(pmd); goto end; - if (pmd_bad(*pmd)) { + } else if (pmd_bad(*pmd)) { pmd_ERROR(*pmd); + BUG(); pmd_clear(pmd); + pmd_unmap_nested(pmd); goto end; } @@ -50,6 +53,7 @@ static pte_t *get_one_pte_map_nested(str pte_unmap_nested(pte); pte = NULL; } + pmd_unmap_nested(pmd); end: return pte; } @@ -59,12 +63,15 @@ static inline int page_table_present(str { pgd_t *pgd; pmd_t *pmd; + int ret; pgd = pgd_offset(mm, addr); if (pgd_none(*pgd)) return 0; - pmd = pmd_offset(pgd, addr); - return pmd_present(*pmd); + pmd = pmd_offset_map(pgd, addr); + ret = pmd_present(*pmd); + pmd_unmap(pmd); + return ret; } #else #define page_table_present(mm, addr) (1) @@ -75,9 +82,11 @@ static inline pte_t *alloc_one_pte_map(s pmd_t * pmd; pte_t * pte = NULL; - pmd = pmd_alloc(mm, pgd_offset(mm, addr), addr); - if (pmd) + pmd = pmd_alloc_map(mm, pgd_offset(mm, addr), addr); + if (pmd) { pte = pte_alloc_map(mm, pmd, addr); + pmd_unmap(pmd); + } return pte; } diff -urpN linux-2.5.50/mm/msync.c highpmd-2.5.50-3/mm/msync.c --- linux-2.5.50/mm/msync.c 2002-11-27 14:35:57.000000000 -0800 +++ highpmd-2.5.50-3/mm/msync.c 2002-12-10 17:09:22.000000000 -0800 @@ -50,6 +50,7 @@ static int filemap_sync_pte_range(pmd_t return 0; if (pmd_bad(*pmd)) { pmd_ERROR(*pmd); + BUG(); pmd_clear(pmd); return 0; } @@ -82,7 +83,7 @@ static inline int filemap_sync_pmd_range pgd_clear(pgd); return 0; } - pmd = pmd_offset(pgd, address); + pmd = pmd_offset_map(pgd, address); if ((address & PGDIR_MASK) != (end & PGDIR_MASK)) end = (address & PGDIR_MASK) + PGDIR_SIZE; error = 0; @@ -91,6 +92,7 @@ static inline int filemap_sync_pmd_range address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address && (address < end)); + pmd_unmap(pmd-1); return error; } diff -urpN linux-2.5.50/mm/swapfile.c highpmd-2.5.50-3/mm/swapfile.c --- linux-2.5.50/mm/swapfile.c 2002-11-27 14:35:51.000000000 -0800 +++ highpmd-2.5.50-3/mm/swapfile.c 2002-12-10 17:09:36.000000000 -0800 @@ -404,6 +404,7 @@ static void unuse_pmd(struct vm_area_str return; if (pmd_bad(*dir)) { pmd_ERROR(*dir); + BUG(); pmd_clear(dir); return; } @@ -436,7 +437,7 @@ static void unuse_pgd(struct vm_area_str pgd_clear(dir); return; } - pmd = pmd_offset(dir, address); + pmd = pmd_offset_map(dir, address); offset = address & PGDIR_MASK; address &= ~PGDIR_MASK; end = address + size; @@ -450,6 +451,7 @@ static void unuse_pgd(struct vm_area_str address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address && (address < end)); + pmd_unmap(pmd-1); } /* mmlist_lock and vma->vm_mm->page_table_lock are held */ diff -urpN linux-2.5.50/mm/vmalloc.c highpmd-2.5.50-3/mm/vmalloc.c --- linux-2.5.50/mm/vmalloc.c 2002-11-27 14:36:04.000000000 -0800 +++ highpmd-2.5.50-3/mm/vmalloc.c 2002-12-10 17:09:47.000000000 -0800 @@ -33,6 +33,7 @@ static void unmap_area_pte(pmd_t *pmd, u return; if (pmd_bad(*pmd)) { pmd_ERROR(*pmd); + BUG(); pmd_clear(pmd); return; } @@ -70,7 +71,7 @@ static void unmap_area_pmd(pgd_t *dir, u return; } - pmd = pmd_offset(dir, address); + pmd = pmd_offset_map(dir, address); address &= ~PGDIR_MASK; end = address + size; if (end > PGDIR_SIZE) @@ -81,6 +82,7 @@ static void unmap_area_pmd(pgd_t *dir, u address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address < end); + pmd_unmap(pmd-1); } static int map_area_pte(pte_t *pte, unsigned long address, @@ -160,16 +162,17 @@ int map_vm_area(struct vm_struct *area, dir = pgd_offset_k(address); spin_lock(&init_mm.page_table_lock); do { - pmd_t *pmd = pmd_alloc(&init_mm, dir, address); + pmd_t *pmd = pmd_alloc_map(&init_mm, dir, address); if (!pmd) { err = -ENOMEM; break; } if (map_area_pmd(pmd, address, end - address, prot, pages)) { err = -ENOMEM; + pmd_unmap(pmd); break; } - + pmd_unmap(pmd); address = (address + PGDIR_SIZE) & PGDIR_MASK; dir++; } while (address && (address < end));