aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/asm-alpha/page.h2
-rw-r--r--include/asm-alpha/pgalloc.h22
-rw-r--r--include/asm-arm/page.h2
-rw-r--r--include/asm-arm/pgalloc.h9
-rw-r--r--include/asm-avr32/page.h1
-rw-r--r--include/asm-avr32/pgalloc.h16
-rw-r--r--include/asm-cris/page.h1
-rw-r--r--include/asm-cris/pgalloc.h14
-rw-r--r--include/asm-frv/page.h1
-rw-r--r--include/asm-frv/pgalloc.h12
-rw-r--r--include/asm-ia64/page.h2
-rw-r--r--include/asm-ia64/pgalloc.h20
-rw-r--r--include/asm-m32r/page.h1
-rw-r--r--include/asm-m32r/pgalloc.h10
-rw-r--r--include/asm-m68k/motorola_pgalloc.h14
-rw-r--r--include/asm-m68k/page.h1
-rw-r--r--include/asm-m68k/sun3_pgalloc.h17
-rw-r--r--include/asm-mips/page.h1
-rw-r--r--include/asm-mips/pgalloc.h17
-rw-r--r--include/asm-parisc/page.h1
-rw-r--r--include/asm-parisc/pgalloc.h11
-rw-r--r--include/asm-powerpc/page.h2
-rw-r--r--include/asm-powerpc/pgalloc-32.h6
-rw-r--r--include/asm-powerpc/pgalloc-64.h27
-rw-r--r--include/asm-ppc/pgalloc.h6
-rw-r--r--include/asm-s390/page.h2
-rw-r--r--include/asm-s390/pgalloc.h3
-rw-r--r--include/asm-s390/tlb.h2
-rw-r--r--include/asm-sh/page.h2
-rw-r--r--include/asm-sh/pgalloc.h27
-rw-r--r--include/asm-sparc/page.h2
-rw-r--r--include/asm-sparc/pgalloc.h5
-rw-r--r--include/asm-sparc64/page.h2
-rw-r--r--include/asm-sparc64/pgalloc.h19
-rw-r--r--include/asm-um/page.h2
-rw-r--r--include/asm-um/pgalloc.h12
-rw-r--r--include/asm-x86/page_32.h2
-rw-r--r--include/asm-x86/page_64.h2
-rw-r--r--include/asm-x86/pgalloc_32.h6
-rw-r--r--include/asm-x86/pgalloc_64.h22
-rw-r--r--include/asm-xtensa/page.h1
-rw-r--r--include/asm-xtensa/pgalloc.h17
-rw-r--r--include/linux/mm.h14
43 files changed, 265 insertions, 93 deletions
diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h
index 05f09f997d82..22ff9762d17b 100644
--- a/include/asm-alpha/page.h
+++ b/include/asm-alpha/page.h
@@ -62,6 +62,8 @@ typedef unsigned long pgprot_t;
62 62
63#endif /* STRICT_MM_TYPECHECKS */ 63#endif /* STRICT_MM_TYPECHECKS */
64 64
65typedef struct page *pgtable_t;
66
65#ifdef USE_48_BIT_KSEG 67#ifdef USE_48_BIT_KSEG
66#define PAGE_OFFSET 0xffff800000000000UL 68#define PAGE_OFFSET 0xffff800000000000UL
67#else 69#else
diff --git a/include/asm-alpha/pgalloc.h b/include/asm-alpha/pgalloc.h
index fdbedacc7375..fd090155dccd 100644
--- a/include/asm-alpha/pgalloc.h
+++ b/include/asm-alpha/pgalloc.h
@@ -11,10 +11,11 @@
11 */ 11 */
12 12
13static inline void 13static inline void
14pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte) 14pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t pte)
15{ 15{
16 pmd_set(pmd, (pte_t *)(page_to_pa(pte) + PAGE_OFFSET)); 16 pmd_set(pmd, (pte_t *)(page_to_pa(pte) + PAGE_OFFSET));
17} 17}
18#define pmd_pgtable(pmd) pmd_page(pmd)
18 19
19static inline void 20static inline void
20pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte) 21pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
@@ -57,18 +58,23 @@ pte_free_kernel(struct mm_struct *mm, pte_t *pte)
57 free_page((unsigned long)pte); 58 free_page((unsigned long)pte);
58} 59}
59 60
60static inline struct page * 61static inline pgtable_t
61pte_alloc_one(struct mm_struct *mm, unsigned long addr) 62pte_alloc_one(struct mm_struct *mm, unsigned long address)
62{ 63{
63 pte_t *pte = pte_alloc_one_kernel(mm, addr); 64 pte_t *pte = pte_alloc_one_kernel(mm, address);
64 if (pte) 65 struct page *page;
65 return virt_to_page(pte); 66
66 return NULL; 67 if (!pte)
68 return NULL;
69 page = virt_to_page(pte);
70 pgtable_page_ctor(page);
71 return page;
67} 72}
68 73
69static inline void 74static inline void
70pte_free(struct mm_struct *mm, struct page *page) 75pte_free(struct mm_struct *mm, pgtable_t page)
71{ 76{
77 pgtable_page_dtor(page);
72 __free_page(page); 78 __free_page(page);
73} 79}
74 80
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h
index 31ff12f4ffb7..c86f68ee6511 100644
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -171,6 +171,8 @@ typedef unsigned long pgprot_t;
171 171
172#endif /* STRICT_MM_TYPECHECKS */ 172#endif /* STRICT_MM_TYPECHECKS */
173 173
174typedef struct page *pgtable_t;
175
174#endif /* CONFIG_MMU */ 176#endif /* CONFIG_MMU */
175 177
176#include <asm/memory.h> 178#include <asm/memory.h>
diff --git a/include/asm-arm/pgalloc.h b/include/asm-arm/pgalloc.h
index fb6c6e3222bd..163b0305dd76 100644
--- a/include/asm-arm/pgalloc.h
+++ b/include/asm-arm/pgalloc.h
@@ -66,7 +66,7 @@ pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
66 return pte; 66 return pte;
67} 67}
68 68
69static inline struct page * 69static inline pgtable_t
70pte_alloc_one(struct mm_struct *mm, unsigned long addr) 70pte_alloc_one(struct mm_struct *mm, unsigned long addr)
71{ 71{
72 struct page *pte; 72 struct page *pte;
@@ -75,6 +75,7 @@ pte_alloc_one(struct mm_struct *mm, unsigned long addr)
75 if (pte) { 75 if (pte) {
76 void *page = page_address(pte); 76 void *page = page_address(pte);
77 clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE); 77 clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE);
78 pgtable_page_ctor(pte);
78 } 79 }
79 80
80 return pte; 81 return pte;
@@ -91,8 +92,9 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
91 } 92 }
92} 93}
93 94
94static inline void pte_free(struct mm_struct *mm, struct page *pte) 95static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
95{ 96{
97 pgtable_page_dtor(pte);
96 __free_page(pte); 98 __free_page(pte);
97} 99}
98 100
@@ -123,10 +125,11 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
123} 125}
124 126
125static inline void 127static inline void
126pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep) 128pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
127{ 129{
128 __pmd_populate(pmdp, page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE); 130 __pmd_populate(pmdp, page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE);
129} 131}
132#define pmd_pgtable(pmd) pmd_page(pmd)
130 133
131#endif /* CONFIG_MMU */ 134#endif /* CONFIG_MMU */
132 135
diff --git a/include/asm-avr32/page.h b/include/asm-avr32/page.h
index ee23499cec34..5582968feee8 100644
--- a/include/asm-avr32/page.h
+++ b/include/asm-avr32/page.h
@@ -34,6 +34,7 @@ extern void copy_page(void *to, void *from);
34typedef struct { unsigned long pte; } pte_t; 34typedef struct { unsigned long pte; } pte_t;
35typedef struct { unsigned long pgd; } pgd_t; 35typedef struct { unsigned long pgd; } pgd_t;
36typedef struct { unsigned long pgprot; } pgprot_t; 36typedef struct { unsigned long pgprot; } pgprot_t;
37typedef struct page *pgtable_t;
37 38
38#define pte_val(x) ((x).pte) 39#define pte_val(x) ((x).pte)
39#define pgd_val(x) ((x).pgd) 40#define pgd_val(x) ((x).pgd)
diff --git a/include/asm-avr32/pgalloc.h b/include/asm-avr32/pgalloc.h
index b77e364b4c44..51fc1f6e4b17 100644
--- a/include/asm-avr32/pgalloc.h
+++ b/include/asm-avr32/pgalloc.h
@@ -17,10 +17,11 @@
17 set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))) 17 set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
18 18
19static __inline__ void pmd_populate(struct mm_struct *mm, pmd_t *pmd, 19static __inline__ void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
20 struct page *pte) 20 pgtable_t pte)
21{ 21{
22 set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte))); 22 set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte)));
23} 23}
24#define pmd_pgtable(pmd) pmd_page(pmd)
24 25
25/* 26/*
26 * Allocate and free page tables 27 * Allocate and free page tables
@@ -51,7 +52,9 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
51 struct page *pte; 52 struct page *pte;
52 53
53 pte = alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO); 54 pte = alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
54 55 if (!pte)
56 return NULL;
57 pgtable_page_ctor(pte);
55 return pte; 58 return pte;
56} 59}
57 60
@@ -60,12 +63,17 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
60 free_page((unsigned long)pte); 63 free_page((unsigned long)pte);
61} 64}
62 65
63static inline void pte_free(struct mm_struct *mm, struct page *pte) 66static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
64{ 67{
68 pgtable_page_dtor(pte);
65 __free_page(pte); 69 __free_page(pte);
66} 70}
67 71
68#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) 72#define __pte_free_tlb(tlb,pte) \
73do { \
74 pgtable_page_dtor(pte); \
75 tlb_remove_page((tlb), pte); \
76} while (0)
69 77
70#define check_pgt_cache() do { } while(0) 78#define check_pgt_cache() do { } while(0)
71 79
diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h
index 3b0156c46311..c45bb1ef397c 100644
--- a/include/asm-cris/page.h
+++ b/include/asm-cris/page.h
@@ -26,6 +26,7 @@
26typedef struct { unsigned long pte; } pte_t; 26typedef struct { unsigned long pte; } pte_t;
27typedef struct { unsigned long pgd; } pgd_t; 27typedef struct { unsigned long pgd; } pgd_t;
28typedef struct { unsigned long pgprot; } pgprot_t; 28typedef struct { unsigned long pgprot; } pgprot_t;
29typedef struct page *pgtable_t;
29#endif 30#endif
30 31
31#define pte_val(x) ((x).pte) 32#define pte_val(x) ((x).pte)
diff --git a/include/asm-cris/pgalloc.h b/include/asm-cris/pgalloc.h
index 8ddd66f81773..a1ba761d0573 100644
--- a/include/asm-cris/pgalloc.h
+++ b/include/asm-cris/pgalloc.h
@@ -6,6 +6,7 @@
6 6
7#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, pte) 7#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, pte)
8#define pmd_populate(mm, pmd, pte) pmd_set(pmd, page_address(pte)) 8#define pmd_populate(mm, pmd, pte) pmd_set(pmd, page_address(pte))
9#define pmd_pgtable(pmd) pmd_page(pmd)
9 10
10/* 11/*
11 * Allocate and free page tables. 12 * Allocate and free page tables.
@@ -27,10 +28,11 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long ad
27 return pte; 28 return pte;
28} 29}
29 30
30static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) 31static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
31{ 32{
32 struct page *pte; 33 struct page *pte;
33 pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); 34 pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
35 pgtable_page_ctor(pte);
34 return pte; 36 return pte;
35} 37}
36 38
@@ -39,13 +41,17 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
39 free_page((unsigned long)pte); 41 free_page((unsigned long)pte);
40} 42}
41 43
42static inline void pte_free(struct mm_struct *mm, struct page *pte) 44static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
43{ 45{
46 pgtable_page_dtor(pte);
44 __free_page(pte); 47 __free_page(pte);
45} 48}
46 49
47 50#define __pte_free_tlb(tlb,pte) \
48#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) 51do { \
52 pgtable_page_dtor(pte); \
53 tlb_remove_page((tlb), pte); \
54} while (0)
49 55
50#define check_pgt_cache() do { } while (0) 56#define check_pgt_cache() do { } while (0)
51 57
diff --git a/include/asm-frv/page.h b/include/asm-frv/page.h
index cacc045700de..c2c1e89e747d 100644
--- a/include/asm-frv/page.h
+++ b/include/asm-frv/page.h
@@ -25,6 +25,7 @@ typedef struct { unsigned long ste[64];} pmd_t;
25typedef struct { pmd_t pue[1]; } pud_t; 25typedef struct { pmd_t pue[1]; } pud_t;
26typedef struct { pud_t pge[1]; } pgd_t; 26typedef struct { pud_t pge[1]; } pgd_t;
27typedef struct { unsigned long pgprot; } pgprot_t; 27typedef struct { unsigned long pgprot; } pgprot_t;
28typedef struct page *pgtable_t;
28 29
29#define pte_val(x) ((x).pte) 30#define pte_val(x) ((x).pte)
30#define pmd_val(x) ((x).ste[0]) 31#define pmd_val(x) ((x).ste[0])
diff --git a/include/asm-frv/pgalloc.h b/include/asm-frv/pgalloc.h
index e89620ef08ca..971e6addb009 100644
--- a/include/asm-frv/pgalloc.h
+++ b/include/asm-frv/pgalloc.h
@@ -25,6 +25,7 @@
25do { \ 25do { \
26 __set_pmd((PMD), page_to_pfn(PAGE) << PAGE_SHIFT | _PAGE_TABLE); \ 26 __set_pmd((PMD), page_to_pfn(PAGE) << PAGE_SHIFT | _PAGE_TABLE); \
27} while(0) 27} while(0)
28#define pmd_pgtable(pmd) pmd_page(pmd)
28 29
29/* 30/*
30 * Allocate and free page tables. 31 * Allocate and free page tables.
@@ -35,19 +36,24 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *);
35 36
36extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long); 37extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
37 38
38extern struct page *pte_alloc_one(struct mm_struct *, unsigned long); 39extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
39 40
40static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 41static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
41{ 42{
42 free_page((unsigned long)pte); 43 free_page((unsigned long)pte);
43} 44}
44 45
45static inline void pte_free(struct mm_struct *mm, struct page *pte) 46static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
46{ 47{
48 pgtable_page_dtor(pte);
47 __free_page(pte); 49 __free_page(pte);
48} 50}
49 51
50#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) 52#define __pte_free_tlb(tlb,pte) \
53do { \
54 pgtable_page_dtor(pte); \
55 tlb_remove_page((tlb),(pte)); \
56} while (0)
51 57
52/* 58/*
53 * allocating and freeing a pmd is trivial: the 1-entry pmd is 59 * allocating and freeing a pmd is trivial: the 1-entry pmd is
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 8a8aa3fd7cd4..4999a6c63775 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -185,6 +185,7 @@ get_order (unsigned long size)
185#endif 185#endif
186 typedef struct { unsigned long pgd; } pgd_t; 186 typedef struct { unsigned long pgd; } pgd_t;
187 typedef struct { unsigned long pgprot; } pgprot_t; 187 typedef struct { unsigned long pgprot; } pgprot_t;
188 typedef struct page *pgtable_t;
188 189
189# define pte_val(x) ((x).pte) 190# define pte_val(x) ((x).pte)
190# define pmd_val(x) ((x).pmd) 191# define pmd_val(x) ((x).pmd)
@@ -206,6 +207,7 @@ get_order (unsigned long size)
206 typedef unsigned long pmd_t; 207 typedef unsigned long pmd_t;
207 typedef unsigned long pgd_t; 208 typedef unsigned long pgd_t;
208 typedef unsigned long pgprot_t; 209 typedef unsigned long pgprot_t;
210 typedef struct page *pgtable_t;
209# endif 211# endif
210 212
211# define pte_val(x) (x) 213# define pte_val(x) (x)
diff --git a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h
index 556d988123ac..b9ac1a6fc216 100644
--- a/include/asm-ia64/pgalloc.h
+++ b/include/asm-ia64/pgalloc.h
@@ -70,10 +70,11 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
70#define __pmd_free_tlb(tlb, pmd) pmd_free((tlb)->mm, pmd) 70#define __pmd_free_tlb(tlb, pmd) pmd_free((tlb)->mm, pmd)
71 71
72static inline void 72static inline void
73pmd_populate(struct mm_struct *mm, pmd_t * pmd_entry, struct page *pte) 73pmd_populate(struct mm_struct *mm, pmd_t * pmd_entry, pgtable_t pte)
74{ 74{
75 pmd_val(*pmd_entry) = page_to_phys(pte); 75 pmd_val(*pmd_entry) = page_to_phys(pte);
76} 76}
77#define pmd_pgtable(pmd) pmd_page(pmd)
77 78
78static inline void 79static inline void
79pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmd_entry, pte_t * pte) 80pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmd_entry, pte_t * pte)
@@ -81,11 +82,17 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmd_entry, pte_t * pte)
81 pmd_val(*pmd_entry) = __pa(pte); 82 pmd_val(*pmd_entry) = __pa(pte);
82} 83}
83 84
84static inline struct page *pte_alloc_one(struct mm_struct *mm, 85static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr)
85 unsigned long addr)
86{ 86{
87 void *pg = quicklist_alloc(0, GFP_KERNEL, NULL); 87 struct page *page;
88 return pg ? virt_to_page(pg) : NULL; 88 void *pg;
89
90 pg = quicklist_alloc(0, GFP_KERNEL, NULL);
91 if (!pg)
92 return NULL;
93 page = virt_to_page(pg);
94 pgtable_page_ctor(page);
95 return page;
89} 96}
90 97
91static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, 98static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
@@ -94,8 +101,9 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
94 return quicklist_alloc(0, GFP_KERNEL, NULL); 101 return quicklist_alloc(0, GFP_KERNEL, NULL);
95} 102}
96 103
97static inline void pte_free(struct mm_struct *mm, struct page *pte) 104static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
98{ 105{
106 pgtable_page_dtor(pte);
99 quicklist_free_page(0, NULL, pte); 107 quicklist_free_page(0, NULL, pte);
100} 108}
101 109
diff --git a/include/asm-m32r/page.h b/include/asm-m32r/page.h
index 05d43bbbf940..8a677f3fca68 100644
--- a/include/asm-m32r/page.h
+++ b/include/asm-m32r/page.h
@@ -28,6 +28,7 @@ typedef struct { unsigned long pgd; } pgd_t;
28#define PTE_MASK PAGE_MASK 28#define PTE_MASK PAGE_MASK
29 29
30typedef struct { unsigned long pgprot; } pgprot_t; 30typedef struct { unsigned long pgprot; } pgprot_t;
31typedef struct page *pgtable_t;
31 32
32#define pmd_val(x) ((x).pmd) 33#define pmd_val(x) ((x).pmd)
33#define pgd_val(x) ((x).pgd) 34#define pgd_val(x) ((x).pgd)
diff --git a/include/asm-m32r/pgalloc.h b/include/asm-m32r/pgalloc.h
index e5921adfad1b..f11a2b909cdb 100644
--- a/include/asm-m32r/pgalloc.h
+++ b/include/asm-m32r/pgalloc.h
@@ -9,10 +9,11 @@
9 set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))) 9 set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
10 10
11static __inline__ void pmd_populate(struct mm_struct *mm, pmd_t *pmd, 11static __inline__ void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
12 struct page *pte) 12 pgtable_t pte)
13{ 13{
14 set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte))); 14 set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte)));
15} 15}
16#define pmd_pgtable(pmd) pmd_page(pmd)
16 17
17/* 18/*
18 * Allocate and free page tables. 19 * Allocate and free page tables.
@@ -37,12 +38,12 @@ static __inline__ pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
37 return pte; 38 return pte;
38} 39}
39 40
40static __inline__ struct page *pte_alloc_one(struct mm_struct *mm, 41static __inline__ pgtable_t pte_alloc_one(struct mm_struct *mm,
41 unsigned long address) 42 unsigned long address)
42{ 43{
43 struct page *pte = alloc_page(GFP_KERNEL|__GFP_ZERO); 44 struct page *pte = alloc_page(GFP_KERNEL|__GFP_ZERO);
44 45
45 46 pgtable_page_ctor(pte);
46 return pte; 47 return pte;
47} 48}
48 49
@@ -51,8 +52,9 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
51 free_page((unsigned long)pte); 52 free_page((unsigned long)pte);
52} 53}
53 54
54static inline void pte_free(struct mm_struct *mm, struct page *pte) 55static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
55{ 56{
57 pgtable_page_dtor(pte);
56 __free_page(pte); 58 __free_page(pte);
57} 59}
58 60
diff --git a/include/asm-m68k/motorola_pgalloc.h b/include/asm-m68k/motorola_pgalloc.h
index 500ec9b8b189..d08bf6261df8 100644
--- a/include/asm-m68k/motorola_pgalloc.h
+++ b/include/asm-m68k/motorola_pgalloc.h
@@ -7,7 +7,6 @@
7extern pmd_t *get_pointer_table(void); 7extern pmd_t *get_pointer_table(void);
8extern int free_pointer_table(pmd_t *); 8extern int free_pointer_table(pmd_t *);
9 9
10
11static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) 10static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
12{ 11{
13 pte_t *pte; 12 pte_t *pte;
@@ -28,7 +27,7 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
28 free_page((unsigned long) pte); 27 free_page((unsigned long) pte);
29} 28}
30 29
31static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) 30static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
32{ 31{
33 struct page *page = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); 32 struct page *page = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
34 pte_t *pte; 33 pte_t *pte;
@@ -43,19 +42,21 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long add
43 nocache_page(pte); 42 nocache_page(pte);
44 } 43 }
45 kunmap(pte); 44 kunmap(pte);
46 45 pgtable_page_ctor(page);
47 return page; 46 return page;
48} 47}
49 48
50static inline void pte_free(struct mm_struct *mm, struct page *page) 49static inline void pte_free(struct mm_struct *mm, pgtable_t page)
51{ 50{
51 pgtable_page_dtor(page);
52 cache_page(kmap(page)); 52 cache_page(kmap(page));
53 kunmap(page); 53 kunmap(page);
54 __free_page(page); 54 __free_page(page);
55} 55}
56 56
57static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *page) 57static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page)
58{ 58{
59 pgtable_page_dtor(page);
59 cache_page(kmap(page)); 60 cache_page(kmap(page));
60 kunmap(page); 61 kunmap(page);
61 __free_page(page); 62 __free_page(page);
@@ -94,10 +95,11 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *
94 pmd_set(pmd, pte); 95 pmd_set(pmd, pte);
95} 96}
96 97
97static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page) 98static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t page)
98{ 99{
99 pmd_set(pmd, page_address(page)); 100 pmd_set(pmd, page_address(page));
100} 101}
102#define pmd_pgtable(pmd) pmd_page(pmd)
101 103
102static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) 104static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
103{ 105{
diff --git a/include/asm-m68k/page.h b/include/asm-m68k/page.h
index 3f29e2a03a43..880c2cbff8a6 100644
--- a/include/asm-m68k/page.h
+++ b/include/asm-m68k/page.h
@@ -91,6 +91,7 @@ typedef struct { unsigned long pte; } pte_t;
91typedef struct { unsigned long pmd[16]; } pmd_t; 91typedef struct { unsigned long pmd[16]; } pmd_t;
92typedef struct { unsigned long pgd; } pgd_t; 92typedef struct { unsigned long pgd; } pgd_t;
93typedef struct { unsigned long pgprot; } pgprot_t; 93typedef struct { unsigned long pgprot; } pgprot_t;
94typedef struct page *pgtable_t;
94 95
95#define pte_val(x) ((x).pte) 96#define pte_val(x) ((x).pte)
96#define pmd_val(x) ((&x)->pmd[0]) 97#define pmd_val(x) ((&x)->pmd[0])
diff --git a/include/asm-m68k/sun3_pgalloc.h b/include/asm-m68k/sun3_pgalloc.h
index a5a91e72714b..d4c83f143816 100644
--- a/include/asm-m68k/sun3_pgalloc.h
+++ b/include/asm-m68k/sun3_pgalloc.h
@@ -26,12 +26,17 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
26 free_page((unsigned long) pte); 26 free_page((unsigned long) pte);
27} 27}
28 28
29static inline void pte_free(struct mm_struct *mm, struct page *page) 29static inline void pte_free(struct mm_struct *mm, pgtable_t page)
30{ 30{
31 pgtable_page_dtor(page);
31 __free_page(page); 32 __free_page(page);
32} 33}
33 34
34#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) 35#define __pte_free_tlb(tlb,pte) \
36do { \
37 pgtable_page_dtor(pte); \
38 tlb_remove_page((tlb), pte); \
39} while (0)
35 40
36static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, 41static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
37 unsigned long address) 42 unsigned long address)
@@ -45,8 +50,8 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
45 return (pte_t *) (page); 50 return (pte_t *) (page);
46} 51}
47 52
48static inline struct page *pte_alloc_one(struct mm_struct *mm, 53static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
49 unsigned long address) 54 unsigned long address)
50{ 55{
51 struct page *page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0); 56 struct page *page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
52 57
@@ -54,6 +59,7 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
54 return NULL; 59 return NULL;
55 60
56 clear_highpage(page); 61 clear_highpage(page);
62 pgtable_page_ctor(page);
57 return page; 63 return page;
58 64
59} 65}
@@ -63,10 +69,11 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *
63 pmd_val(*pmd) = __pa((unsigned long)pte); 69 pmd_val(*pmd) = __pa((unsigned long)pte);
64} 70}
65 71
66static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page) 72static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t page)
67{ 73{
68 pmd_val(*pmd) = __pa((unsigned long)page_address(page)); 74 pmd_val(*pmd) = __pa((unsigned long)page_address(page));
69} 75}
76#define pmd_pgtable(pmd) pmd_page(pmd)
70 77
71/* 78/*
72 * allocating and freeing a pmd is trivial: the 1-entry pmd is 79 * allocating and freeing a pmd is trivial: the 1-entry pmd is
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 635aa44d2290..8735aa0b8963 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -90,6 +90,7 @@ typedef struct { unsigned long pte; } pte_t;
90#define pte_val(x) ((x).pte) 90#define pte_val(x) ((x).pte)
91#define __pte(x) ((pte_t) { (x) } ) 91#define __pte(x) ((pte_t) { (x) } )
92#endif 92#endif
93typedef struct page *pgtable_t;
93 94
94/* 95/*
95 * For 3-level pagetables we defines these ourselves, for 2-level the 96 * For 3-level pagetables we defines these ourselves, for 2-level the
diff --git a/include/asm-mips/pgalloc.h b/include/asm-mips/pgalloc.h
index c4efeced8396..1275831dda29 100644
--- a/include/asm-mips/pgalloc.h
+++ b/include/asm-mips/pgalloc.h
@@ -20,10 +20,11 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
20} 20}
21 21
22static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, 22static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
23 struct page *pte) 23 pgtable_t pte)
24{ 24{
25 set_pmd(pmd, __pmd((unsigned long)page_address(pte))); 25 set_pmd(pmd, __pmd((unsigned long)page_address(pte)));
26} 26}
27#define pmd_pgtable(pmd) pmd_page(pmd)
27 28
28/* 29/*
29 * Initialize a new pmd table with invalid pointers. 30 * Initialize a new pmd table with invalid pointers.
@@ -79,9 +80,10 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
79 struct page *pte; 80 struct page *pte;
80 81
81 pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER); 82 pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER);
82 if (pte) 83 if (pte) {
83 clear_highpage(pte); 84 clear_highpage(pte);
84 85 pgtable_page_ctor(pte);
86 }
85 return pte; 87 return pte;
86} 88}
87 89
@@ -90,12 +92,17 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
90 free_pages((unsigned long)pte, PTE_ORDER); 92 free_pages((unsigned long)pte, PTE_ORDER);
91} 93}
92 94
93static inline void pte_free(struct mm_struct *mm, struct page *pte) 95static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
94{ 96{
97 pgtable_page_dtor(pte);
95 __free_pages(pte, PTE_ORDER); 98 __free_pages(pte, PTE_ORDER);
96} 99}
97 100
98#define __pte_free_tlb(tlb, pte) tlb_remove_page((tlb), (pte)) 101#define __pte_free_tlb(tlb,pte) \
102do { \
103 pgtable_page_dtor(pte); \
104 tlb_remove_page((tlb), pte); \
105} while (0)
99 106
100#ifdef CONFIG_32BIT 107#ifdef CONFIG_32BIT
101 108
diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h
index b08d9151c71e..27d50b859541 100644
--- a/include/asm-parisc/page.h
+++ b/include/asm-parisc/page.h
@@ -91,6 +91,7 @@ typedef unsigned long pgprot_t;
91 91
92#endif /* STRICT_MM_TYPECHECKS */ 92#endif /* STRICT_MM_TYPECHECKS */
93 93
94typedef struct page *pgtable_t;
94 95
95typedef struct __physmem_range { 96typedef struct __physmem_range {
96 unsigned long start_pfn; 97 unsigned long start_pfn;
diff --git a/include/asm-parisc/pgalloc.h b/include/asm-parisc/pgalloc.h
index aab66f1bea14..3996dfc30a3f 100644
--- a/include/asm-parisc/pgalloc.h
+++ b/include/asm-parisc/pgalloc.h
@@ -115,11 +115,14 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
115 115
116#define pmd_populate(mm, pmd, pte_page) \ 116#define pmd_populate(mm, pmd, pte_page) \
117 pmd_populate_kernel(mm, pmd, page_address(pte_page)) 117 pmd_populate_kernel(mm, pmd, page_address(pte_page))
118#define pmd_pgtable(pmd) pmd_page(pmd)
118 119
119static inline struct page * 120static inline pgtable_t
120pte_alloc_one(struct mm_struct *mm, unsigned long address) 121pte_alloc_one(struct mm_struct *mm, unsigned long address)
121{ 122{
122 struct page *page = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); 123 struct page *page = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
124 if (page)
125 pgtable_page_ctor(page);
123 return page; 126 return page;
124} 127}
125 128
@@ -135,7 +138,11 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
135 free_page((unsigned long)pte); 138 free_page((unsigned long)pte);
136} 139}
137 140
138#define pte_free(mm, page) pte_free_kernel(page_address(page)) 141static inline void pte_free_kernel(struct mm_struct *mm, struct page *pte)
142{
143 pgtable_page_dtor(pte);
144 pte_free_kernel(page_address((pte));
145}
139 146
140#define check_pgt_cache() do { } while (0) 147#define check_pgt_cache() do { } while (0)
141 148
diff --git a/include/asm-powerpc/page.h b/include/asm-powerpc/page.h
index 61e3725bbd37..df47bbb6ea13 100644
--- a/include/asm-powerpc/page.h
+++ b/include/asm-powerpc/page.h
@@ -190,6 +190,8 @@ extern int page_is_ram(unsigned long pfn);
190 190
191struct vm_area_struct; 191struct vm_area_struct;
192 192
193typedef struct page *pgtable_t;
194
193#include <asm-generic/memory_model.h> 195#include <asm-generic/memory_model.h>
194#endif /* __ASSEMBLY__ */ 196#endif /* __ASSEMBLY__ */
195 197
diff --git a/include/asm-powerpc/pgalloc-32.h b/include/asm-powerpc/pgalloc-32.h
index c162a4c37b39..58c07147b3ea 100644
--- a/include/asm-powerpc/pgalloc-32.h
+++ b/include/asm-powerpc/pgalloc-32.h
@@ -22,17 +22,19 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
22 (pmd_val(*(pmd)) = __pa(pte) | _PMD_PRESENT) 22 (pmd_val(*(pmd)) = __pa(pte) | _PMD_PRESENT)
23#define pmd_populate(mm, pmd, pte) \ 23#define pmd_populate(mm, pmd, pte) \
24 (pmd_val(*(pmd)) = (page_to_pfn(pte) << PAGE_SHIFT) | _PMD_PRESENT) 24 (pmd_val(*(pmd)) = (page_to_pfn(pte) << PAGE_SHIFT) | _PMD_PRESENT)
25#define pmd_pgtable(pmd) pmd_page(pmd)
25#else 26#else
26#define pmd_populate_kernel(mm, pmd, pte) \ 27#define pmd_populate_kernel(mm, pmd, pte) \
27 (pmd_val(*(pmd)) = (unsigned long)pte | _PMD_PRESENT) 28 (pmd_val(*(pmd)) = (unsigned long)pte | _PMD_PRESENT)
28#define pmd_populate(mm, pmd, pte) \ 29#define pmd_populate(mm, pmd, pte) \
29 (pmd_val(*(pmd)) = (unsigned long)lowmem_page_address(pte) | _PMD_PRESENT) 30 (pmd_val(*(pmd)) = (unsigned long)lowmem_page_address(pte) | _PMD_PRESENT)
31#define pmd_pgtable(pmd) pmd_page(pmd)
30#endif 32#endif
31 33
32extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); 34extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
33extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr); 35extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr);
34extern void pte_free_kernel(struct mm_struct *mm, pte_t *pte); 36extern void pte_free_kernel(struct mm_struct *mm, pte_t *pte);
35extern void pte_free(struct mm_struct *mm, struct page *pte); 37extern void pte_free(struct mm_struct *mm, pgtable_t pte);
36 38
37#define __pte_free_tlb(tlb, pte) pte_free((tlb)->mm, (pte)) 39#define __pte_free_tlb(tlb, pte) pte_free((tlb)->mm, (pte))
38 40
diff --git a/include/asm-powerpc/pgalloc-64.h b/include/asm-powerpc/pgalloc-64.h
index 5afae8593931..68980990f62a 100644
--- a/include/asm-powerpc/pgalloc-64.h
+++ b/include/asm-powerpc/pgalloc-64.h
@@ -58,6 +58,7 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
58#define pmd_populate(mm, pmd, pte_page) \ 58#define pmd_populate(mm, pmd, pte_page) \
59 pmd_populate_kernel(mm, pmd, page_address(pte_page)) 59 pmd_populate_kernel(mm, pmd, page_address(pte_page))
60#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, (unsigned long)(pte)) 60#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, (unsigned long)(pte))
61#define pmd_pgtable(pmd) pmd_page(pmd)
61 62
62 63
63#else /* CONFIG_PPC_64K_PAGES */ 64#else /* CONFIG_PPC_64K_PAGES */
@@ -72,6 +73,7 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
72 73
73#define pmd_populate(mm, pmd, pte_page) \ 74#define pmd_populate(mm, pmd, pte_page) \
74 pmd_populate_kernel(mm, pmd, page_address(pte_page)) 75 pmd_populate_kernel(mm, pmd, page_address(pte_page))
76#define pmd_pgtable(pmd) pmd_page(pmd)
75 77
76#endif /* CONFIG_PPC_64K_PAGES */ 78#endif /* CONFIG_PPC_64K_PAGES */
77 79
@@ -92,11 +94,18 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
92 return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO); 94 return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
93} 95}
94 96
95static inline struct page *pte_alloc_one(struct mm_struct *mm, 97static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
96 unsigned long address) 98 unsigned long address)
97{ 99{
98 pte_t *pte = pte_alloc_one_kernel(mm, address); 100 struct page *page;
99 return pte ? virt_to_page(pte) : NULL; 101 pte_t *pte;
102
103 pte = pte_alloc_one_kernel(mm, address);
104 if (!pte)
105 return NULL;
106 page = virt_to_page(pte);
107 pgtable_page_ctor(page);
108 return page;
100} 109}
101 110
102static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 111static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
@@ -104,8 +113,9 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
104 free_page((unsigned long)pte); 113 free_page((unsigned long)pte);
105} 114}
106 115
107static inline void pte_free(struct mm_struct *mm, struct page *ptepage) 116static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
108{ 117{
118 pgtable_page_dtor(ptepage);
109 __free_page(ptepage); 119 __free_page(ptepage);
110} 120}
111 121
@@ -136,9 +146,12 @@ static inline void pgtable_free(pgtable_free_t pgf)
136 146
137extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); 147extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf);
138 148
139#define __pte_free_tlb(tlb, ptepage) \ 149#define __pte_free_tlb(tlb,ptepage) \
150do { \
151 pgtable_page_dtor(ptepage); \
140 pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \ 152 pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \
141 PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1)) 153 PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1)); \
154} while (0)
142#define __pmd_free_tlb(tlb, pmd) \ 155#define __pmd_free_tlb(tlb, pmd) \
143 pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \ 156 pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \
144 PMD_CACHE_NUM, PMD_TABLE_SIZE-1)) 157 PMD_CACHE_NUM, PMD_TABLE_SIZE-1))
diff --git a/include/asm-ppc/pgalloc.h b/include/asm-ppc/pgalloc.h
index 7c39a95829c7..fd4d1d74cfb1 100644
--- a/include/asm-ppc/pgalloc.h
+++ b/include/asm-ppc/pgalloc.h
@@ -23,17 +23,19 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
23 (pmd_val(*(pmd)) = __pa(pte) | _PMD_PRESENT) 23 (pmd_val(*(pmd)) = __pa(pte) | _PMD_PRESENT)
24#define pmd_populate(mm, pmd, pte) \ 24#define pmd_populate(mm, pmd, pte) \
25 (pmd_val(*(pmd)) = (page_to_pfn(pte) << PAGE_SHIFT) | _PMD_PRESENT) 25 (pmd_val(*(pmd)) = (page_to_pfn(pte) << PAGE_SHIFT) | _PMD_PRESENT)
26#define pmd_pgtable(pmd) pmd_page(pmd)
26#else 27#else
27#define pmd_populate_kernel(mm, pmd, pte) \ 28#define pmd_populate_kernel(mm, pmd, pte) \
28 (pmd_val(*(pmd)) = (unsigned long)pte | _PMD_PRESENT) 29 (pmd_val(*(pmd)) = (unsigned long)pte | _PMD_PRESENT)
29#define pmd_populate(mm, pmd, pte) \ 30#define pmd_populate(mm, pmd, pte) \
30 (pmd_val(*(pmd)) = (unsigned long)lowmem_page_address(pte) | _PMD_PRESENT) 31 (pmd_val(*(pmd)) = (unsigned long)lowmem_page_address(pte) | _PMD_PRESENT)
32#define pmd_pgtable(pmd) pmd_page(pmd)
31#endif 33#endif
32 34
33extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); 35extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
34extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr); 36extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr);
35extern void pte_free_kernel(struct mm_struct *mm, pte_t *pte); 37extern void pte_free_kernel(struct mm_struct *mm, pte_t *pte);
36extern void pte_free(struct mm_struct *mm, struct page *pte); 38extern void pte_free(struct mm_struct *mm, pgtable_t pte);
37 39
38#define __pte_free_tlb(tlb, pte) pte_free((tlb)->mm, (pte)) 40#define __pte_free_tlb(tlb, pte) pte_free((tlb)->mm, (pte))
39 41
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index a55f9d979dfb..7f29a981f48c 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -109,6 +109,8 @@ typedef struct { unsigned long pgd; } pgd_t;
109 109
110#endif /* __s390x__ */ 110#endif /* __s390x__ */
111 111
112typedef struct page *pgtable_t;
113
112#define __pte(x) ((pte_t) { (x) } ) 114#define __pte(x) ((pte_t) { (x) } )
113#define __pmd(x) ((pmd_t) { (x) } ) 115#define __pmd(x) ((pmd_t) { (x) } )
114#define __pgd(x) ((pgd_t) { (x) } ) 116#define __pgd(x) ((pgd_t) { (x) } )
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
index 6f6619ba8980..900d44807e10 100644
--- a/include/asm-s390/pgalloc.h
+++ b/include/asm-s390/pgalloc.h
@@ -132,7 +132,7 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
132} 132}
133 133
134static inline void 134static inline void
135pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page) 135pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t page)
136{ 136{
137 pte_t *pte = (pte_t *)page_to_phys(page); 137 pte_t *pte = (pte_t *)page_to_phys(page);
138 pmd_t *shadow_pmd = get_shadow_table(pmd); 138 pmd_t *shadow_pmd = get_shadow_table(pmd);
@@ -142,6 +142,7 @@ pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page)
142 if (shadow_pmd && shadow_pte) 142 if (shadow_pmd && shadow_pte)
143 pmd_populate_kernel(mm, shadow_pmd, shadow_pte); 143 pmd_populate_kernel(mm, shadow_pmd, shadow_pte);
144} 144}
145#define pmd_pgtable(pmd) pmd_page(pmd)
145 146
146/* 147/*
147 * page table entry allocation/free routines. 148 * page table entry allocation/free routines.
diff --git a/include/asm-s390/tlb.h b/include/asm-s390/tlb.h
index 985de2b88279..3c8177fa9e06 100644
--- a/include/asm-s390/tlb.h
+++ b/include/asm-s390/tlb.h
@@ -95,7 +95,7 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
95 * pte_free_tlb frees a pte table and clears the CRSTE for the 95 * pte_free_tlb frees a pte table and clears the CRSTE for the
96 * page table from the tlb. 96 * page table from the tlb.
97 */ 97 */
98static inline void pte_free_tlb(struct mmu_gather *tlb, struct page *page) 98static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t page)
99{ 99{
100 if (!tlb->fullmm) { 100 if (!tlb->fullmm) {
101 tlb->array[tlb->nr_ptes++] = page; 101 tlb->array[tlb->nr_ptes++] = page;
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index e0fe02950f52..134562dc8c45 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -100,6 +100,8 @@ typedef struct { unsigned long pgd; } pgd_t;
100#define __pgd(x) ((pgd_t) { (x) } ) 100#define __pgd(x) ((pgd_t) { (x) } )
101#define __pgprot(x) ((pgprot_t) { (x) } ) 101#define __pgprot(x) ((pgprot_t) { (x) } )
102 102
103typedef struct page *pgtable_t;
104
103#endif /* !__ASSEMBLY__ */ 105#endif /* !__ASSEMBLY__ */
104 106
105/* 107/*
diff --git a/include/asm-sh/pgalloc.h b/include/asm-sh/pgalloc.h
index 59ca16d77a1d..84dd2db7104c 100644
--- a/include/asm-sh/pgalloc.h
+++ b/include/asm-sh/pgalloc.h
@@ -14,10 +14,11 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
14} 14}
15 15
16static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, 16static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
17 struct page *pte) 17 pgtable_t pte)
18{ 18{
19 set_pmd(pmd, __pmd((unsigned long)page_address(pte))); 19 set_pmd(pmd, __pmd((unsigned long)page_address(pte)));
20} 20}
21#define pmd_pgtable(pmd) pmd_page(pmd)
21 22
22static inline void pgd_ctor(void *x) 23static inline void pgd_ctor(void *x)
23{ 24{
@@ -47,11 +48,18 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
47 return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL); 48 return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
48} 49}
49 50
50static inline struct page *pte_alloc_one(struct mm_struct *mm, 51static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
51 unsigned long address) 52 unsigned long address)
52{ 53{
53 void *pg = quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL); 54 struct page *page;
54 return pg ? virt_to_page(pg) : NULL; 55 void *pg;
56
57 pg = quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
58 if (!pg)
59 return NULL;
60 page = virt_to_page(pg);
61 pgtable_page_ctor(page);
62 return page;
55} 63}
56 64
57static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 65static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
@@ -59,12 +67,17 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
59 quicklist_free(QUICK_PT, NULL, pte); 67 quicklist_free(QUICK_PT, NULL, pte);
60} 68}
61 69
62static inline void pte_free(struct mm_struct *mm, struct page *pte) 70static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
63{ 71{
72 pgtable_page_dtor(pte);
64 quicklist_free_page(QUICK_PT, NULL, pte); 73 quicklist_free_page(QUICK_PT, NULL, pte);
65} 74}
66 75
67#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) 76#define __pte_free_tlb(tlb,pte) \
77do { \
78 pgtable_page_dtor(pte); \
79 tlb_remove_page((tlb), (pte)); \
80} while (0)
68 81
69/* 82/*
70 * allocating and freeing a pmd is trivial: the 1-entry pmd is 83 * allocating and freeing a pmd is trivial: the 1-entry pmd is
diff --git a/include/asm-sparc/page.h b/include/asm-sparc/page.h
index cbc48c0c4e15..39ccf2da297c 100644
--- a/include/asm-sparc/page.h
+++ b/include/asm-sparc/page.h
@@ -123,6 +123,8 @@ typedef unsigned long iopgprot_t;
123 123
124#endif 124#endif
125 125
126typedef struct page *pgtable_t;
127
126extern unsigned long sparc_unmapped_base; 128extern unsigned long sparc_unmapped_base;
127 129
128BTFIXUPDEF_SETHI(sparc_unmapped_base) 130BTFIXUPDEF_SETHI(sparc_unmapped_base)
diff --git a/include/asm-sparc/pgalloc.h b/include/asm-sparc/pgalloc.h
index b5fbdd36447f..6292cd00e5af 100644
--- a/include/asm-sparc/pgalloc.h
+++ b/include/asm-sparc/pgalloc.h
@@ -50,10 +50,11 @@ BTFIXUPDEF_CALL(void, free_pmd_fast, pmd_t *)
50 50
51BTFIXUPDEF_CALL(void, pmd_populate, pmd_t *, struct page *) 51BTFIXUPDEF_CALL(void, pmd_populate, pmd_t *, struct page *)
52#define pmd_populate(MM, PMD, PTE) BTFIXUP_CALL(pmd_populate)(PMD, PTE) 52#define pmd_populate(MM, PMD, PTE) BTFIXUP_CALL(pmd_populate)(PMD, PTE)
53#define pmd_pgtable(pmd) pmd_page(pmd)
53BTFIXUPDEF_CALL(void, pmd_set, pmd_t *, pte_t *) 54BTFIXUPDEF_CALL(void, pmd_set, pmd_t *, pte_t *)
54#define pmd_populate_kernel(MM, PMD, PTE) BTFIXUP_CALL(pmd_set)(PMD, PTE) 55#define pmd_populate_kernel(MM, PMD, PTE) BTFIXUP_CALL(pmd_set)(PMD, PTE)
55 56
56BTFIXUPDEF_CALL(struct page *, pte_alloc_one, struct mm_struct *, unsigned long) 57BTFIXUPDEF_CALL(pgtable_t , pte_alloc_one, struct mm_struct *, unsigned long)
57#define pte_alloc_one(mm, address) BTFIXUP_CALL(pte_alloc_one)(mm, address) 58#define pte_alloc_one(mm, address) BTFIXUP_CALL(pte_alloc_one)(mm, address)
58BTFIXUPDEF_CALL(pte_t *, pte_alloc_one_kernel, struct mm_struct *, unsigned long) 59BTFIXUPDEF_CALL(pte_t *, pte_alloc_one_kernel, struct mm_struct *, unsigned long)
59#define pte_alloc_one_kernel(mm, addr) BTFIXUP_CALL(pte_alloc_one_kernel)(mm, addr) 60#define pte_alloc_one_kernel(mm, addr) BTFIXUP_CALL(pte_alloc_one_kernel)(mm, addr)
@@ -61,7 +62,7 @@ BTFIXUPDEF_CALL(pte_t *, pte_alloc_one_kernel, struct mm_struct *, unsigned long
61BTFIXUPDEF_CALL(void, free_pte_fast, pte_t *) 62BTFIXUPDEF_CALL(void, free_pte_fast, pte_t *)
62#define pte_free_kernel(mm, pte) BTFIXUP_CALL(free_pte_fast)(pte) 63#define pte_free_kernel(mm, pte) BTFIXUP_CALL(free_pte_fast)(pte)
63 64
64BTFIXUPDEF_CALL(void, pte_free, struct page *) 65BTFIXUPDEF_CALL(void, pte_free, pgtable_t )
65#define pte_free(mm, pte) BTFIXUP_CALL(pte_free)(pte) 66#define pte_free(mm, pte) BTFIXUP_CALL(pte_free)(pte)
66#define __pte_free_tlb(tlb, pte) pte_free((tlb)->mm, pte) 67#define __pte_free_tlb(tlb, pte) pte_free((tlb)->mm, pte)
67 68
diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h
index cdf950e017ee..e93a482aa24a 100644
--- a/include/asm-sparc64/page.h
+++ b/include/asm-sparc64/page.h
@@ -104,6 +104,8 @@ typedef unsigned long pgprot_t;
104 104
105#endif /* (STRICT_MM_TYPECHECKS) */ 105#endif /* (STRICT_MM_TYPECHECKS) */
106 106
107typedef struct page *pgtable_t;
108
107#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_32BIT) ? \ 109#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_32BIT) ? \
108 (_AC(0x0000000070000000,UL)) : \ 110 (_AC(0x0000000070000000,UL)) : \
109 (_AC(0xfffff80000000000,UL) + (1UL << 32UL))) 111 (_AC(0xfffff80000000000,UL) + (1UL << 32UL)))
diff --git a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h
index b48f73c2274e..3ee2d406373b 100644
--- a/include/asm-sparc64/pgalloc.h
+++ b/include/asm-sparc64/pgalloc.h
@@ -43,11 +43,18 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
43 return quicklist_alloc(0, GFP_KERNEL, NULL); 43 return quicklist_alloc(0, GFP_KERNEL, NULL);
44} 44}
45 45
46static inline struct page *pte_alloc_one(struct mm_struct *mm, 46static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
47 unsigned long address) 47 unsigned long address)
48{ 48{
49 void *pg = quicklist_alloc(0, GFP_KERNEL, NULL); 49 struct page *page;
50 return pg ? virt_to_page(pg) : NULL; 50 void *pg;
51
52 pg = quicklist_alloc(0, GFP_KERNEL, NULL);
53 if (!pg)
54 return NULL;
55 page = virt_to_page(pg);
56 pgtable_page_ctor(page);
57 return page;
51} 58}
52 59
53static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 60static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
@@ -55,8 +62,9 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
55 quicklist_free(0, NULL, pte); 62 quicklist_free(0, NULL, pte);
56} 63}
57 64
58static inline void pte_free(struct mm_struct *mm, struct page *ptepage) 65static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
59{ 66{
67 pgtable_page_dtor(ptepage);
60 quicklist_free_page(0, NULL, ptepage); 68 quicklist_free_page(0, NULL, ptepage);
61} 69}
62 70
@@ -64,6 +72,7 @@ static inline void pte_free(struct mm_struct *mm, struct page *ptepage)
64#define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE) 72#define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE)
65#define pmd_populate(MM,PMD,PTE_PAGE) \ 73#define pmd_populate(MM,PMD,PTE_PAGE) \
66 pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE)) 74 pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE))
75#define pmd_pgtable(pmd) pmd_page(pmd)
67 76
68static inline void check_pgt_cache(void) 77static inline void check_pgt_cache(void)
69{ 78{
diff --git a/include/asm-um/page.h b/include/asm-um/page.h
index fe2374d705d1..381f96b1c825 100644
--- a/include/asm-um/page.h
+++ b/include/asm-um/page.h
@@ -79,6 +79,8 @@ typedef unsigned long phys_t;
79 79
80typedef struct { unsigned long pgprot; } pgprot_t; 80typedef struct { unsigned long pgprot; } pgprot_t;
81 81
82typedef struct page *pgtable_t;
83
82#define pgd_val(x) ((x).pgd) 84#define pgd_val(x) ((x).pgd)
83#define pgprot_val(x) ((x).pgprot) 85#define pgprot_val(x) ((x).pgprot)
84 86
diff --git a/include/asm-um/pgalloc.h b/include/asm-um/pgalloc.h
index 4f3e62b02861..9062a6e72241 100644
--- a/include/asm-um/pgalloc.h
+++ b/include/asm-um/pgalloc.h
@@ -18,6 +18,7 @@
18 set_pmd(pmd, __pmd(_PAGE_TABLE + \ 18 set_pmd(pmd, __pmd(_PAGE_TABLE + \
19 ((unsigned long long)page_to_pfn(pte) << \ 19 ((unsigned long long)page_to_pfn(pte) << \
20 (unsigned long long) PAGE_SHIFT))) 20 (unsigned long long) PAGE_SHIFT)))
21#define pmd_pgtable(pmd) pmd_page(pmd)
21 22
22/* 23/*
23 * Allocate and free page tables. 24 * Allocate and free page tables.
@@ -26,19 +27,24 @@ extern pgd_t *pgd_alloc(struct mm_struct *);
26extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); 27extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
27 28
28extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long); 29extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
29extern struct page *pte_alloc_one(struct mm_struct *, unsigned long); 30extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
30 31
31static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 32static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
32{ 33{
33 free_page((unsigned long) pte); 34 free_page((unsigned long) pte);
34} 35}
35 36
36static inline void pte_free(struct mm_struct *mm, struct page *pte) 37static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
37{ 38{
39 pgtable_page_dtor(pte);
38 __free_page(pte); 40 __free_page(pte);
39} 41}
40 42
41#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) 43#define __pte_free_tlb(tlb,pte) \
44do { \
45 pgtable_page_dtor(pte); \
46 tlb_remove_page((tlb),(pte)); \
47} while (0)
42 48
43#ifdef CONFIG_3_LEVEL_PGTABLES 49#ifdef CONFIG_3_LEVEL_PGTABLES
44 50
diff --git a/include/asm-x86/page_32.h b/include/asm-x86/page_32.h
index a6fd10f230d2..ba715d9798b0 100644
--- a/include/asm-x86/page_32.h
+++ b/include/asm-x86/page_32.h
@@ -50,6 +50,8 @@ typedef unsigned long phys_addr_t;
50typedef union { pteval_t pte, pte_low; } pte_t; 50typedef union { pteval_t pte, pte_low; } pte_t;
51typedef pte_t boot_pte_t; 51typedef pte_t boot_pte_t;
52 52
53typedef struct page *pgtable_t;
54
53#endif /* __ASSEMBLY__ */ 55#endif /* __ASSEMBLY__ */
54#endif /* CONFIG_X86_PAE */ 56#endif /* CONFIG_X86_PAE */
55 57
diff --git a/include/asm-x86/page_64.h b/include/asm-x86/page_64.h
index dcf0c0746075..f7393bc516ef 100644
--- a/include/asm-x86/page_64.h
+++ b/include/asm-x86/page_64.h
@@ -71,6 +71,8 @@ typedef unsigned long pgdval_t;
71typedef unsigned long pgprotval_t; 71typedef unsigned long pgprotval_t;
72typedef unsigned long phys_addr_t; 72typedef unsigned long phys_addr_t;
73 73
74typedef struct page *pgtable_t;
75
74typedef struct { pteval_t pte; } pte_t; 76typedef struct { pteval_t pte; } pte_t;
75 77
76#define vmemmap ((struct page *)VMEMMAP_START) 78#define vmemmap ((struct page *)VMEMMAP_START)
diff --git a/include/asm-x86/pgalloc_32.h b/include/asm-x86/pgalloc_32.h
index bab12718a913..6bea6e5b5ee5 100644
--- a/include/asm-x86/pgalloc_32.h
+++ b/include/asm-x86/pgalloc_32.h
@@ -31,6 +31,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *p
31 paravirt_alloc_pt(mm, pfn); 31 paravirt_alloc_pt(mm, pfn);
32 set_pmd(pmd, __pmd(((pteval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE)); 32 set_pmd(pmd, __pmd(((pteval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE));
33} 33}
34#define pmd_pgtable(pmd) pmd_page(pmd)
34 35
35/* 36/*
36 * Allocate and free page tables. 37 * Allocate and free page tables.
@@ -39,15 +40,16 @@ extern pgd_t *pgd_alloc(struct mm_struct *);
39extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); 40extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
40 41
41extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long); 42extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
42extern struct page *pte_alloc_one(struct mm_struct *, unsigned long); 43extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
43 44
44static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 45static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
45{ 46{
46 free_page((unsigned long)pte); 47 free_page((unsigned long)pte);
47} 48}
48 49
49static inline void pte_free(struct mm_struct *mm, struct page *pte) 50static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
50{ 51{
52 pgtable_page_dtor(pte);
51 __free_page(pte); 53 __free_page(pte);
52} 54}
53 55
diff --git a/include/asm-x86/pgalloc_64.h b/include/asm-x86/pgalloc_64.h
index 4f6220db22b1..8d6722320dcc 100644
--- a/include/asm-x86/pgalloc_64.h
+++ b/include/asm-x86/pgalloc_64.h
@@ -12,6 +12,8 @@
12#define pgd_populate(mm, pgd, pud) \ 12#define pgd_populate(mm, pgd, pud) \
13 set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud))) 13 set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)))
14 14
15#define pmd_pgtable(pmd) pmd_page(pmd)
16
15static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte) 17static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
16{ 18{
17 set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT))); 19 set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
@@ -91,12 +93,17 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long ad
91 return (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); 93 return (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
92} 94}
93 95
94static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) 96static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
95{ 97{
96 void *p = (void *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); 98 struct page *page;
99 void *p;
100
101 p = (void *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
97 if (!p) 102 if (!p)
98 return NULL; 103 return NULL;
99 return virt_to_page(p); 104 page = virt_to_page(p);
105 pgtable_page_ctor(page);
106 return page;
100} 107}
101 108
102/* Should really implement gc for free page table pages. This could be 109/* Should really implement gc for free page table pages. This could be
@@ -108,12 +115,17 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
108 free_page((unsigned long)pte); 115 free_page((unsigned long)pte);
109} 116}
110 117
111static inline void pte_free(struct mm_struct *mm, struct page *pte) 118static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
112{ 119{
120 pgtable_page_dtor(pte);
113 __free_page(pte); 121 __free_page(pte);
114} 122}
115 123
116#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) 124#define __pte_free_tlb(tlb,pte) \
125do { \
126 pgtable_page_dtor((pte)); \
127 tlb_remove_page((tlb), (pte)); \
128} while (0)
117 129
118#define __pmd_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x)) 130#define __pmd_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x))
119#define __pud_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x)) 131#define __pud_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x))
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
index 1adedbf41d01..80a6ae0dd259 100644
--- a/include/asm-xtensa/page.h
+++ b/include/asm-xtensa/page.h
@@ -98,6 +98,7 @@
98typedef struct { unsigned long pte; } pte_t; /* page table entry */ 98typedef struct { unsigned long pte; } pte_t; /* page table entry */
99typedef struct { unsigned long pgd; } pgd_t; /* PGD table entry */ 99typedef struct { unsigned long pgd; } pgd_t; /* PGD table entry */
100typedef struct { unsigned long pgprot; } pgprot_t; 100typedef struct { unsigned long pgprot; } pgprot_t;
101typedef struct page *pgtable_t;
101 102
102#define pte_val(x) ((x).pte) 103#define pte_val(x) ((x).pte)
103#define pgd_val(x) ((x).pgd) 104#define pgd_val(x) ((x).pgd)
diff --git a/include/asm-xtensa/pgalloc.h b/include/asm-xtensa/pgalloc.h
index 1d51ba5463f9..8d1544eb461e 100644
--- a/include/asm-xtensa/pgalloc.h
+++ b/include/asm-xtensa/pgalloc.h
@@ -24,6 +24,7 @@
24 (pmd_val(*(pmdp)) = ((unsigned long)ptep)) 24 (pmd_val(*(pmdp)) = ((unsigned long)ptep))
25#define pmd_populate(mm, pmdp, page) \ 25#define pmd_populate(mm, pmdp, page) \
26 (pmd_val(*(pmdp)) = ((unsigned long)page_to_virt(page))) 26 (pmd_val(*(pmdp)) = ((unsigned long)page_to_virt(page)))
27#define pmd_pgtable(pmd) pmd_page(pmd)
27 28
28static inline pgd_t* 29static inline pgd_t*
29pgd_alloc(struct mm_struct *mm) 30pgd_alloc(struct mm_struct *mm)
@@ -46,10 +47,14 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
46 return kmem_cache_alloc(pgtable_cache, GFP_KERNEL|__GFP_REPEAT); 47 return kmem_cache_alloc(pgtable_cache, GFP_KERNEL|__GFP_REPEAT);
47} 48}
48 49
49static inline struct page *pte_alloc_one(struct mm_struct *mm, 50static inline pte_token_t pte_alloc_one(struct mm_struct *mm,
50 unsigned long addr) 51 unsigned long addr)
51{ 52{
52 return virt_to_page(pte_alloc_one_kernel(mm, addr)); 53 struct page *page;
54
55 page = virt_to_page(pte_alloc_one_kernel(mm, addr));
56 pgtable_page_ctor(page);
57 return page;
53} 58}
54 59
55static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 60static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
@@ -57,10 +62,12 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
57 kmem_cache_free(pgtable_cache, pte); 62 kmem_cache_free(pgtable_cache, pte);
58} 63}
59 64
60static inline void pte_free(struct mm_struct *mm, struct page *page) 65static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
61{ 66{
62 kmem_cache_free(pgtable_cache, page_address(page)); 67 pgtable_page_dtor(pte);
68 kmem_cache_free(pgtable_cache, page_address(pte));
63} 69}
70#define pmd_pgtable(pmd) pmd_page(pmd)
64 71
65#endif /* __KERNEL__ */ 72#endif /* __KERNEL__ */
66#endif /* _XTENSA_PGALLOC_H */ 73#endif /* _XTENSA_PGALLOC_H */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 89d7c691b93a..e8abb3814209 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -894,6 +894,18 @@ static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long a
894#define pte_lockptr(mm, pmd) ({(void)(pmd); &(mm)->page_table_lock;}) 894#define pte_lockptr(mm, pmd) ({(void)(pmd); &(mm)->page_table_lock;})
895#endif /* NR_CPUS < CONFIG_SPLIT_PTLOCK_CPUS */ 895#endif /* NR_CPUS < CONFIG_SPLIT_PTLOCK_CPUS */
896 896
897static inline void pgtable_page_ctor(struct page *page)
898{
899 pte_lock_init(page);
900 inc_zone_page_state(page, NR_PAGETABLE);
901}
902
903static inline void pgtable_page_dtor(struct page *page)
904{
905 pte_lock_deinit(page);
906 dec_zone_page_state(page, NR_PAGETABLE);
907}
908
897#define pte_offset_map_lock(mm, pmd, address, ptlp) \ 909#define pte_offset_map_lock(mm, pmd, address, ptlp) \
898({ \ 910({ \
899 spinlock_t *__ptl = pte_lockptr(mm, pmd); \ 911 spinlock_t *__ptl = pte_lockptr(mm, pmd); \
@@ -1136,7 +1148,7 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address,
1136#define FOLL_GET 0x04 /* do get_page on page */ 1148#define FOLL_GET 0x04 /* do get_page on page */
1137#define FOLL_ANON 0x08 /* give ZERO_PAGE if no pgtable */ 1149#define FOLL_ANON 0x08 /* give ZERO_PAGE if no pgtable */
1138 1150
1139typedef int (*pte_fn_t)(pte_t *pte, struct page *pmd_page, unsigned long addr, 1151typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
1140 void *data); 1152 void *data);
1141extern int apply_to_page_range(struct mm_struct *mm, unsigned long address, 1153extern int apply_to_page_range(struct mm_struct *mm, unsigned long address,
1142 unsigned long size, pte_fn_t fn, void *data); 1154 unsigned long size, pte_fn_t fn, void *data);