--- linux-2.6-npiggin/include/asm-generic/4level-fixup.h | 32 +++++++++++++++++++ linux-2.6-npiggin/include/linux/mm.h | 6 +++ linux-2.6-npiggin/mm/memory.c | 25 ++++++++++++++ 3 files changed, 63 insertions(+) diff -puN /dev/null include/asm-generic/4level-fixup.h --- /dev/null 2004-09-06 19:38:39.000000000 +1000 +++ linux-2.6-npiggin/include/asm-generic/4level-fixup.h 2004-12-21 20:27:48.000000000 +1100 @@ -0,0 +1,32 @@ +#ifndef _4LEVEL_FIXUP_H +#define _4LEVEL_FIXUP_H + +#define __ARCH_HAS_4LEVEL_HACK + +#define PUD_SIZE PGDIR_SIZE +#define PUD_MASK PGDIR_MASK +#define PTRS_PER_PUD 1 + +#define pud_t pgd_t + +#define pmd_alloc(mm, pud, address) \ +({ pmd_t *ret; \ + if (pgd_none(*pud)) \ + ret = __pmd_alloc(mm, pud, address); \ + else \ + ret = pmd_offset(pud, address); \ + ret; \ +}) + +#define pud_alloc(mm, pgd, address) (pgd) +#define pud_offset(pgd, start) (pgd) +#define pud_none(pud) 0 +#define pud_bad(pud) 0 +#define pud_present(pud) 1 +#define pud_ERROR(pud) do { printk("pud_ERROR\n"); BUG(); } while (0) +#define pud_clear(pud) do { } while (0) + +#define pud_free(x) do { } while (0) +#define __pud_free_tlb(tlb, x) do { } while (0) + +#endif diff -puN include/linux/mm.h~4level-fallback include/linux/mm.h --- linux-2.6/include/linux/mm.h~4level-fallback 2004-12-21 20:27:48.000000000 +1100 +++ linux-2.6-npiggin/include/linux/mm.h 2004-12-21 20:27:48.000000000 +1100 @@ -631,6 +631,11 @@ extern void remove_shrinker(struct shrin * the inlining and the symmetry break with pte_alloc_map() that does all * of this out-of-line. */ +/* + * The following ifdef needed to get the 4level-fixup.h header to work. + * Remove it when 4level-fixup.h has been removed. + */ +#ifndef __ARCH_HAS_4LEVEL_HACK static inline pud_t *pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address) { if (pgd_none(*pgd)) @@ -644,6 +649,7 @@ static inline pmd_t *pmd_alloc(struct mm return __pmd_alloc(mm, pud, address); return pmd_offset(pud, address); } +#endif extern void free_area_init(unsigned long * zones_size); extern void free_area_init_node(int nid, pg_data_t *pgdat, diff -puN mm/memory.c~4level-fallback mm/memory.c --- linux-2.6/mm/memory.c~4level-fallback 2004-12-21 20:27:48.000000000 +1100 +++ linux-2.6-npiggin/mm/memory.c 2004-12-21 20:27:48.000000000 +1100 @@ -1940,6 +1940,7 @@ int handle_mm_fault(struct mm_struct *mm return VM_FAULT_OOM; } +#ifndef __ARCH_HAS_4LEVEL_HACK #if (PTRS_PER_PGD > 1) /* * Allocate page upper directory. @@ -2007,6 +2008,30 @@ out: return pmd_offset(pud, address); } #endif +#else +pmd_t fastcall *__pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) +{ + pmd_t *new; + + spin_unlock(&mm->page_table_lock); + new = pmd_alloc_one(mm, address); + spin_lock(&mm->page_table_lock); + if (!new) + return NULL; + + /* + * Because we dropped the lock, we should re-check the + * entry, as somebody else could have populated it.. + */ + if (pgd_present(*pud)) { + pmd_free(new); + goto out; + } + pgd_populate(mm, pud, new); +out: + return pmd_offset(pud, address); +} +#endif int make_pages_present(unsigned long addr, unsigned long end) { _