From: Andi Kleen <ak@suse.de>

This adds generic macros to asm-generic to make it easy to convert a existing
2/3level page table function to 4levels.

The pml4_t simply consists of a pointer to the pgd_t.

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/include/asm-generic/nopml4-page.h    |   14 ++++++++
 25-akpm/include/asm-generic/nopml4-pgalloc.h |   21 +++++++++++++
 25-akpm/include/asm-generic/nopml4-pgtable.h |   43 +++++++++++++++++++++++++++
 25-akpm/include/asm-generic/pgtable.h        |    2 -
 25-akpm/include/asm-generic/tlb.h            |    6 +++
 5 files changed, 85 insertions(+), 1 deletion(-)

diff -puN /dev/null include/asm-generic/nopml4-page.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/include/asm-generic/nopml4-page.h	2004-11-03 21:53:18.764215480 -0800
@@ -0,0 +1,14 @@
+#ifndef _NOPML4_PAGE_H
+#define _NOPML4_PAGE_H 1
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Generic page.h declarations for architectures without four level
+ * page tables
+ */
+
+typedef struct { pgd_t pgd; } pml4_t;
+#endif
+
+#endif
diff -puN /dev/null include/asm-generic/nopml4-pgalloc.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/include/asm-generic/nopml4-pgalloc.h	2004-11-03 21:53:18.765215328 -0800
@@ -0,0 +1,21 @@
+#ifndef _NOPML4_PGALLOC_H
+#define _NOPML4_PGALLOC_H 1
+
+/* Fallback used for architectures without 4 level pagetables */
+
+#define pml4_populate(mm, pml4, pgd) ((mm)->pml4 = (pml4_t *)(pgd))
+
+static inline pml4_t *pml4_alloc(struct mm_struct *mm)
+{
+	pml4_t dummy;
+	return (pml4_t *)__pgd_alloc(mm, &dummy, 0);
+}
+
+static inline void pml4_free(pml4_t *pml4)
+{
+	pgd_free((pgd_t *)pml4);
+}
+
+#define __pgd_free_tlb(tlb,x)   do {} while(0)
+
+#endif
diff -puN /dev/null include/asm-generic/nopml4-pgtable.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/include/asm-generic/nopml4-pgtable.h	2004-11-03 21:53:18.765215328 -0800
@@ -0,0 +1,43 @@
+#ifndef _NOPML4_H
+#define _NOPML4_H 1
+
+#ifndef __ASSEMBLY__
+
+/* Included by architectures that don't have a fourth page table level.
+
+   pml4 is simply casted to pgd */
+
+#define pml4_ERROR(x)
+#define pml4_bad(x) 0
+#define pml4_clear(x)
+
+/* Covers all address room. This implies that walks will usually wrap.
+   The code has to handle this.
+
+   Could use TASK_SIZE here, but a lot of architectures make it different
+   for 32bit and 64bit tasks. */
+#define PML4_SIZE (~0UL)
+#define PML4_MASK 0UL
+
+#define pml4_offset(mm, addr) ((mm)->pml4)
+#define pml4_offset_k(addr) (init_mm.pml4)
+#define pml4_pgd_offset(pml4, addr) ((pgd_t *)(pml4) + pgd_index(addr))
+#define pml4_pgd_offset_k(pml4, addr) ((pgd_t *)(pml4) + pgd_index_k(addr))
+
+#define pml4_none(pml4) 0
+#define pml4_present(pml4) 1
+#define pml4_index(pml4) 0
+
+#define swapper_pml4 ((pml4_t *)swapper_pg_dir)
+
+/* Use pml4_pgd_offset and pml4_offset_k instead */
+
+#undef pgd_offset
+#define pgd_offset pgd_offset_is_obsolete
+
+#undef pgd_offset_k
+#define pgd_offset_k pgd_offset_k_is_obsolete
+
+#endif
+
+#endif
diff -puN include/asm-generic/pgtable.h~4level-add-asm-generic-support-for-emulating include/asm-generic/pgtable.h
--- 25/include/asm-generic/pgtable.h~4level-add-asm-generic-support-for-emulating	2004-11-03 21:53:18.760216088 -0800
+++ 25-akpm/include/asm-generic/pgtable.h	2004-11-03 21:53:18.765215328 -0800
@@ -131,7 +131,7 @@ static inline void ptep_mkdirty(pte_t *p
 #endif
 
 #ifndef __HAVE_ARCH_PGD_OFFSET_GATE
-#define pgd_offset_gate(mm, addr)	pgd_offset(mm, addr)
+#define pml4_offset_gate(mm, addr)	pml4_offset(mm, addr)
 #endif
 
 #endif /* _ASM_GENERIC_PGTABLE_H */
diff -puN include/asm-generic/tlb.h~4level-add-asm-generic-support-for-emulating include/asm-generic/tlb.h
--- 25/include/asm-generic/tlb.h~4level-add-asm-generic-support-for-emulating	2004-11-03 21:53:18.761215936 -0800
+++ 25-akpm/include/asm-generic/tlb.h	2004-11-03 21:53:18.766215176 -0800
@@ -147,6 +147,12 @@ static inline void tlb_remove_page(struc
 		__pmd_free_tlb(tlb, pmdp);			\
 	} while (0)
 
+#define pgd_free_tlb(tlb, pgdp)					\
+	do {							\
+		tlb->need_flush = 1;				\
+		__pgd_free_tlb(tlb, pgdp);			\
+	} while (0)
+
 #define tlb_migrate_finish(mm) do {} while (0)
 
 #endif /* _ASM_GENERIC__TLB_H */
_