diff options
53 files changed, 326 insertions, 132 deletions
diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c index 1a2e5c8d03a9..66f616fb4860 100644 --- a/arch/frv/mm/pgalloc.c +++ b/arch/frv/mm/pgalloc.c | |||
@@ -28,7 +28,7 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) | |||
28 | return pte; | 28 | return pte; |
29 | } | 29 | } |
30 | 30 | ||
31 | struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | 31 | pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) |
32 | { | 32 | { |
33 | struct page *page; | 33 | struct page *page; |
34 | 34 | ||
@@ -37,9 +37,11 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | |||
37 | #else | 37 | #else |
38 | page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0); | 38 | page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0); |
39 | #endif | 39 | #endif |
40 | if (page) | 40 | if (page) { |
41 | clear_highpage(page); | 41 | clear_highpage(page); |
42 | flush_dcache_page(page); | 42 | pgtable_page_ctor(page); |
43 | flush_dcache_page(page); | ||
44 | } | ||
43 | return page; | 45 | return page; |
44 | } | 46 | } |
45 | 47 | ||
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index f80f90c4d58b..ac3390f81900 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -107,19 +107,20 @@ __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long add | |||
107 | return pte; | 107 | return pte; |
108 | } | 108 | } |
109 | 109 | ||
110 | struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | 110 | pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) |
111 | { | 111 | { |
112 | struct page *ptepage; | 112 | struct page *ptepage; |
113 | 113 | ||
114 | #ifdef CONFIG_HIGHPTE | 114 | #ifdef CONFIG_HIGHPTE |
115 | gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT; | 115 | gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT | __GFP_ZERO; |
116 | #else | 116 | #else |
117 | gfp_t flags = GFP_KERNEL | __GFP_REPEAT; | 117 | gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO; |
118 | #endif | 118 | #endif |
119 | 119 | ||
120 | ptepage = alloc_pages(flags, 0); | 120 | ptepage = alloc_pages(flags, 0); |
121 | if (ptepage) | 121 | if (!ptepage) |
122 | clear_highpage(ptepage); | 122 | return NULL; |
123 | pgtable_page_ctor(ptepage); | ||
123 | return ptepage; | 124 | return ptepage; |
124 | } | 125 | } |
125 | 126 | ||
@@ -131,11 +132,12 @@ void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | |||
131 | free_page((unsigned long)pte); | 132 | free_page((unsigned long)pte); |
132 | } | 133 | } |
133 | 134 | ||
134 | void pte_free(struct mm_struct *mm, struct page *ptepage) | 135 | void pte_free(struct mm_struct *mm, pgtable_t ptepage) |
135 | { | 136 | { |
136 | #ifdef CONFIG_SMP | 137 | #ifdef CONFIG_SMP |
137 | hash_page_sync(); | 138 | hash_page_sync(); |
138 | #endif | 139 | #endif |
140 | pgtable_page_dtor(ptepage); | ||
139 | __free_page(ptepage); | 141 | __free_page(ptepage); |
140 | } | 142 | } |
141 | 143 | ||
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c index 409fcaa4994a..03a79bff1271 100644 --- a/arch/ppc/mm/pgtable.c +++ b/arch/ppc/mm/pgtable.c | |||
@@ -95,7 +95,7 @@ __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long add | |||
95 | return pte; | 95 | return pte; |
96 | } | 96 | } |
97 | 97 | ||
98 | struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | 98 | pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) |
99 | { | 99 | { |
100 | struct page *ptepage; | 100 | struct page *ptepage; |
101 | 101 | ||
@@ -106,8 +106,10 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | |||
106 | #endif | 106 | #endif |
107 | 107 | ||
108 | ptepage = alloc_pages(flags, 0); | 108 | ptepage = alloc_pages(flags, 0); |
109 | if (ptepage) | 109 | if (ptepage) { |
110 | clear_highpage(ptepage); | 110 | clear_highpage(ptepage); |
111 | pgtable_page_ctor(ptepage); | ||
112 | } | ||
111 | return ptepage; | 113 | return ptepage; |
112 | } | 114 | } |
113 | 115 | ||
@@ -119,11 +121,12 @@ void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | |||
119 | free_page((unsigned long)pte); | 121 | free_page((unsigned long)pte); |
120 | } | 122 | } |
121 | 123 | ||
122 | void pte_free(struct mm_struct *mm, struct page *ptepage) | 124 | void pte_free(struct mm_struct *mm, pgtable_t ptepage) |
123 | { | 125 | { |
124 | #ifdef CONFIG_SMP | 126 | #ifdef CONFIG_SMP |
125 | hash_page_sync(); | 127 | hash_page_sync(); |
126 | #endif | 128 | #endif |
129 | pgtable_page_dtor(ptepage); | ||
127 | __free_page(ptepage); | 130 | __free_page(ptepage); |
128 | } | 131 | } |
129 | 132 | ||
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index e60e0ae13402..019f518cd5a0 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c | |||
@@ -78,6 +78,7 @@ unsigned long *page_table_alloc(int noexec) | |||
78 | clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE); | 78 | clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE); |
79 | page->index = (addr_t) table; | 79 | page->index = (addr_t) table; |
80 | } | 80 | } |
81 | pgtable_page_ctor(page); | ||
81 | table = (unsigned long *) page_to_phys(page); | 82 | table = (unsigned long *) page_to_phys(page); |
82 | clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE); | 83 | clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE); |
83 | return table; | 84 | return table; |
@@ -87,6 +88,7 @@ void page_table_free(unsigned long *table) | |||
87 | { | 88 | { |
88 | unsigned long *shadow = get_shadow_pte(table); | 89 | unsigned long *shadow = get_shadow_pte(table); |
89 | 90 | ||
91 | pgtable_page_dtor(virt_to_page(table)); | ||
90 | if (shadow) | 92 | if (shadow) |
91 | free_page((unsigned long) shadow); | 93 | free_page((unsigned long) shadow); |
92 | free_page((unsigned long) table); | 94 | free_page((unsigned long) table); |
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index dc98e3844a0a..23d3291a3e81 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c | |||
@@ -489,14 +489,17 @@ srmmu_pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) | |||
489 | return (pte_t *)srmmu_get_nocache(PTE_SIZE, PTE_SIZE); | 489 | return (pte_t *)srmmu_get_nocache(PTE_SIZE, PTE_SIZE); |
490 | } | 490 | } |
491 | 491 | ||
492 | static struct page * | 492 | static pgtable_t |
493 | srmmu_pte_alloc_one(struct mm_struct *mm, unsigned long address) | 493 | srmmu_pte_alloc_one(struct mm_struct *mm, unsigned long address) |
494 | { | 494 | { |
495 | unsigned long pte; | 495 | unsigned long pte; |
496 | struct page *page; | ||
496 | 497 | ||
497 | if ((pte = (unsigned long)srmmu_pte_alloc_one_kernel(mm, address)) == 0) | 498 | if ((pte = (unsigned long)srmmu_pte_alloc_one_kernel(mm, address)) == 0) |
498 | return NULL; | 499 | return NULL; |
499 | return pfn_to_page( __nocache_pa(pte) >> PAGE_SHIFT ); | 500 | page = pfn_to_page( __nocache_pa(pte) >> PAGE_SHIFT ); |
501 | pgtable_page_ctor(page); | ||
502 | return page; | ||
500 | } | 503 | } |
501 | 504 | ||
502 | static void srmmu_free_pte_fast(pte_t *pte) | 505 | static void srmmu_free_pte_fast(pte_t *pte) |
@@ -504,10 +507,11 @@ static void srmmu_free_pte_fast(pte_t *pte) | |||
504 | srmmu_free_nocache((unsigned long)pte, PTE_SIZE); | 507 | srmmu_free_nocache((unsigned long)pte, PTE_SIZE); |
505 | } | 508 | } |
506 | 509 | ||
507 | static void srmmu_pte_free(struct page *pte) | 510 | static void srmmu_pte_free(pgtable_t pte) |
508 | { | 511 | { |
509 | unsigned long p; | 512 | unsigned long p; |
510 | 513 | ||
514 | pgtable_page_dtor(pte); | ||
511 | p = (unsigned long)page_address(pte); /* Cached address (for test) */ | 515 | p = (unsigned long)page_address(pte); /* Cached address (for test) */ |
512 | if (p == 0) | 516 | if (p == 0) |
513 | BUG(); | 517 | BUG(); |
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 0729305f2f59..c0442e8c4b15 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c | |||
@@ -1947,12 +1947,17 @@ static pte_t *sun4c_pte_alloc_one_kernel(struct mm_struct *mm, unsigned long add | |||
1947 | return pte; | 1947 | return pte; |
1948 | } | 1948 | } |
1949 | 1949 | ||
1950 | static struct page *sun4c_pte_alloc_one(struct mm_struct *mm, unsigned long address) | 1950 | static pgtable_t sun4c_pte_alloc_one(struct mm_struct *mm, unsigned long address) |
1951 | { | 1951 | { |
1952 | pte_t *pte = sun4c_pte_alloc_one_kernel(mm, address); | 1952 | pte_t *pte; |
1953 | struct page *page; | ||
1954 | |||
1955 | pte = sun4c_pte_alloc_one_kernel(mm, address); | ||
1953 | if (pte == NULL) | 1956 | if (pte == NULL) |
1954 | return NULL; | 1957 | return NULL; |
1955 | return virt_to_page(pte); | 1958 | page = virt_to_page(pte); |
1959 | pgtable_page_ctor(page); | ||
1960 | return page; | ||
1956 | } | 1961 | } |
1957 | 1962 | ||
1958 | static inline void sun4c_free_pte_fast(pte_t *pte) | 1963 | static inline void sun4c_free_pte_fast(pte_t *pte) |
@@ -1962,8 +1967,9 @@ static inline void sun4c_free_pte_fast(pte_t *pte) | |||
1962 | pgtable_cache_size++; | 1967 | pgtable_cache_size++; |
1963 | } | 1968 | } |
1964 | 1969 | ||
1965 | static void sun4c_pte_free(struct page *pte) | 1970 | static void sun4c_pte_free(pgtable_t pte) |
1966 | { | 1971 | { |
1972 | pgtable_page_dtor(pte); | ||
1967 | sun4c_free_pte_fast(page_address(pte)); | 1973 | sun4c_free_pte_fast(page_address(pte)); |
1968 | } | 1974 | } |
1969 | 1975 | ||
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index d872fdce1d7e..2627ce82e918 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c | |||
@@ -354,11 +354,13 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) | |||
354 | return pte; | 354 | return pte; |
355 | } | 355 | } |
356 | 356 | ||
357 | struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | 357 | pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) |
358 | { | 358 | { |
359 | struct page *pte; | 359 | struct page *pte; |
360 | 360 | ||
361 | pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); | 361 | pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); |
362 | if (pte) | ||
363 | pgtable_page_ctor(pte); | ||
362 | return pte; | 364 | return pte; |
363 | } | 365 | } |
364 | 366 | ||
diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c index 6c1914622a88..73aba7125203 100644 --- a/arch/x86/mm/pgtable_32.c +++ b/arch/x86/mm/pgtable_32.c | |||
@@ -183,7 +183,7 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) | |||
183 | return (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); | 183 | return (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); |
184 | } | 184 | } |
185 | 185 | ||
186 | struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | 186 | pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) |
187 | { | 187 | { |
188 | struct page *pte; | 188 | struct page *pte; |
189 | 189 | ||
@@ -192,6 +192,8 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | |||
192 | #else | 192 | #else |
193 | pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); | 193 | pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); |
194 | #endif | 194 | #endif |
195 | if (pte) | ||
196 | pgtable_page_ctor(pte); | ||
195 | return pte; | 197 | return pte; |
196 | } | 198 | } |
197 | 199 | ||
@@ -365,6 +367,7 @@ void check_pgt_cache(void) | |||
365 | 367 | ||
366 | void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte) | 368 | void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte) |
367 | { | 369 | { |
370 | pgtable_page_dtor(pte); | ||
368 | paravirt_release_pt(page_to_pfn(pte)); | 371 | paravirt_release_pt(page_to_pfn(pte)); |
369 | tlb_remove_page(tlb, pte); | 372 | tlb_remove_page(tlb, pte); |
370 | } | 373 | } |
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 | ||
65 | typedef 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 | ||
13 | static inline void | 13 | static inline void |
14 | pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte) | 14 | pmd_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 | ||
19 | static inline void | 20 | static inline void |
20 | pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte) | 21 | pmd_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 | ||
60 | static inline struct page * | 61 | static inline pgtable_t |
61 | pte_alloc_one(struct mm_struct *mm, unsigned long addr) | 62 | pte_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 | ||
69 | static inline void | 74 | static inline void |
70 | pte_free(struct mm_struct *mm, struct page *page) | 75 | pte_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 | ||
174 | typedef 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 | ||
69 | static inline struct page * | 69 | static inline pgtable_t |
70 | pte_alloc_one(struct mm_struct *mm, unsigned long addr) | 70 | pte_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 | ||
94 | static inline void pte_free(struct mm_struct *mm, struct page *pte) | 95 | static 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 | ||
125 | static inline void | 127 | static inline void |
126 | pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep) | 128 | pmd_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); | |||
34 | typedef struct { unsigned long pte; } pte_t; | 34 | typedef struct { unsigned long pte; } pte_t; |
35 | typedef struct { unsigned long pgd; } pgd_t; | 35 | typedef struct { unsigned long pgd; } pgd_t; |
36 | typedef struct { unsigned long pgprot; } pgprot_t; | 36 | typedef struct { unsigned long pgprot; } pgprot_t; |
37 | typedef 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 | ||
19 | static __inline__ void pmd_populate(struct mm_struct *mm, pmd_t *pmd, | 19 | static __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 | ||
63 | static inline void pte_free(struct mm_struct *mm, struct page *pte) | 66 | static 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) \ |
73 | do { \ | ||
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 @@ | |||
26 | typedef struct { unsigned long pte; } pte_t; | 26 | typedef struct { unsigned long pte; } pte_t; |
27 | typedef struct { unsigned long pgd; } pgd_t; | 27 | typedef struct { unsigned long pgd; } pgd_t; |
28 | typedef struct { unsigned long pgprot; } pgprot_t; | 28 | typedef struct { unsigned long pgprot; } pgprot_t; |
29 | typedef 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 | ||
30 | static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | 31 | static 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 | ||
42 | static inline void pte_free(struct mm_struct *mm, struct page *pte) | 44 | static 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)) | 51 | do { \ |
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; | |||
25 | typedef struct { pmd_t pue[1]; } pud_t; | 25 | typedef struct { pmd_t pue[1]; } pud_t; |
26 | typedef struct { pud_t pge[1]; } pgd_t; | 26 | typedef struct { pud_t pge[1]; } pgd_t; |
27 | typedef struct { unsigned long pgprot; } pgprot_t; | 27 | typedef struct { unsigned long pgprot; } pgprot_t; |
28 | typedef 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 @@ | |||
25 | do { \ | 25 | do { \ |
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 | ||
36 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long); | 37 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long); |
37 | 38 | ||
38 | extern struct page *pte_alloc_one(struct mm_struct *, unsigned long); | 39 | extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long); |
39 | 40 | ||
40 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | 41 | static 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 | ||
45 | static inline void pte_free(struct mm_struct *mm, struct page *pte) | 46 | static 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) \ |
53 | do { \ | ||
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 | ||
72 | static inline void | 72 | static inline void |
73 | pmd_populate(struct mm_struct *mm, pmd_t * pmd_entry, struct page *pte) | 73 | pmd_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 | ||
78 | static inline void | 79 | static inline void |
79 | pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmd_entry, pte_t * pte) | 80 | pmd_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 | ||
84 | static inline struct page *pte_alloc_one(struct mm_struct *mm, | 85 | static 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 | ||
91 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | 98 | static 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 | ||
97 | static inline void pte_free(struct mm_struct *mm, struct page *pte) | 104 | static 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 | ||
30 | typedef struct { unsigned long pgprot; } pgprot_t; | 30 | typedef struct { unsigned long pgprot; } pgprot_t; |
31 | typedef 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 | ||
11 | static __inline__ void pmd_populate(struct mm_struct *mm, pmd_t *pmd, | 11 | static __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 | ||
40 | static __inline__ struct page *pte_alloc_one(struct mm_struct *mm, | 41 | static __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 | ||
54 | static inline void pte_free(struct mm_struct *mm, struct page *pte) | 55 | static 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 @@ | |||
7 | extern pmd_t *get_pointer_table(void); | 7 | extern pmd_t *get_pointer_table(void); |
8 | extern int free_pointer_table(pmd_t *); | 8 | extern int free_pointer_table(pmd_t *); |
9 | 9 | ||
10 | |||
11 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) | 10 | static 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 | ||
31 | static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | 30 | static 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 | ||
50 | static inline void pte_free(struct mm_struct *mm, struct page *page) | 49 | static 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 | ||
57 | static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *page) | 57 | static 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 | ||
97 | static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page) | 98 | static 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 | ||
102 | static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) | 104 | static 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; | |||
91 | typedef struct { unsigned long pmd[16]; } pmd_t; | 91 | typedef struct { unsigned long pmd[16]; } pmd_t; |
92 | typedef struct { unsigned long pgd; } pgd_t; | 92 | typedef struct { unsigned long pgd; } pgd_t; |
93 | typedef struct { unsigned long pgprot; } pgprot_t; | 93 | typedef struct { unsigned long pgprot; } pgprot_t; |
94 | typedef 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 | ||
29 | static inline void pte_free(struct mm_struct *mm, struct page *page) | 29 | static 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) \ |
36 | do { \ | ||
37 | pgtable_page_dtor(pte); \ | ||
38 | tlb_remove_page((tlb), pte); \ | ||
39 | } while (0) | ||
35 | 40 | ||
36 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | 41 | static 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 | ||
48 | static inline struct page *pte_alloc_one(struct mm_struct *mm, | 53 | static 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 | ||
66 | static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page) | 72 | static 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 |
93 | typedef 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 | ||
22 | static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, | 22 | static 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 | ||
93 | static inline void pte_free(struct mm_struct *mm, struct page *pte) | 95 | static 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) \ |
102 | do { \ | ||
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 | ||
94 | typedef struct page *pgtable_t; | ||
94 | 95 | ||
95 | typedef struct __physmem_range { | 96 | typedef 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 | ||
119 | static inline struct page * | 120 | static inline pgtable_t |
120 | pte_alloc_one(struct mm_struct *mm, unsigned long address) | 121 | pte_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)) | 141 | static 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 | ||
191 | struct vm_area_struct; | 191 | struct vm_area_struct; |
192 | 192 | ||
193 | typedef 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 | ||
32 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); | 34 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); |
33 | extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr); | 35 | extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr); |
34 | extern void pte_free_kernel(struct mm_struct *mm, pte_t *pte); | 36 | extern void pte_free_kernel(struct mm_struct *mm, pte_t *pte); |
35 | extern void pte_free(struct mm_struct *mm, struct page *pte); | 37 | extern 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 | ||
95 | static inline struct page *pte_alloc_one(struct mm_struct *mm, | 97 | static 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 | ||
102 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | 111 | static 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 | ||
107 | static inline void pte_free(struct mm_struct *mm, struct page *ptepage) | 116 | static 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 | ||
137 | extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); | 147 | extern 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) \ |
150 | do { \ | ||
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 | ||
33 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); | 35 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); |
34 | extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr); | 36 | extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr); |
35 | extern void pte_free_kernel(struct mm_struct *mm, pte_t *pte); | 37 | extern void pte_free_kernel(struct mm_struct *mm, pte_t *pte); |
36 | extern void pte_free(struct mm_struct *mm, struct page *pte); | 38 | extern 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 | ||
112 | typedef 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 | ||
134 | static inline void | 134 | static inline void |
135 | pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page) | 135 | pmd_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 | */ |
98 | static inline void pte_free_tlb(struct mmu_gather *tlb, struct page *page) | 98 | static 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 | ||
103 | typedef 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 | ||
16 | static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, | 16 | static 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 | ||
22 | static inline void pgd_ctor(void *x) | 23 | static 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 | ||
50 | static inline struct page *pte_alloc_one(struct mm_struct *mm, | 51 | static 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 | ||
57 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | 65 | static 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 | ||
62 | static inline void pte_free(struct mm_struct *mm, struct page *pte) | 70 | static 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) \ |
77 | do { \ | ||
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 | ||
126 | typedef struct page *pgtable_t; | ||
127 | |||
126 | extern unsigned long sparc_unmapped_base; | 128 | extern unsigned long sparc_unmapped_base; |
127 | 129 | ||
128 | BTFIXUPDEF_SETHI(sparc_unmapped_base) | 130 | BTFIXUPDEF_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 | ||
51 | BTFIXUPDEF_CALL(void, pmd_populate, pmd_t *, struct page *) | 51 | BTFIXUPDEF_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) | ||
53 | BTFIXUPDEF_CALL(void, pmd_set, pmd_t *, pte_t *) | 54 | BTFIXUPDEF_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 | ||
56 | BTFIXUPDEF_CALL(struct page *, pte_alloc_one, struct mm_struct *, unsigned long) | 57 | BTFIXUPDEF_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) |
58 | BTFIXUPDEF_CALL(pte_t *, pte_alloc_one_kernel, struct mm_struct *, unsigned long) | 59 | BTFIXUPDEF_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 | |||
61 | BTFIXUPDEF_CALL(void, free_pte_fast, pte_t *) | 62 | BTFIXUPDEF_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 | ||
64 | BTFIXUPDEF_CALL(void, pte_free, struct page *) | 65 | BTFIXUPDEF_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 | ||
107 | typedef 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 | ||
46 | static inline struct page *pte_alloc_one(struct mm_struct *mm, | 46 | static 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 | ||
53 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | 60 | static 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 | ||
58 | static inline void pte_free(struct mm_struct *mm, struct page *ptepage) | 65 | static 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 | ||
68 | static inline void check_pgt_cache(void) | 77 | static 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 | ||
80 | typedef struct { unsigned long pgprot; } pgprot_t; | 80 | typedef struct { unsigned long pgprot; } pgprot_t; |
81 | 81 | ||
82 | typedef 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 *); | |||
26 | extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); | 27 | extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); |
27 | 28 | ||
28 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long); | 29 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long); |
29 | extern struct page *pte_alloc_one(struct mm_struct *, unsigned long); | 30 | extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long); |
30 | 31 | ||
31 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | 32 | static 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 | ||
36 | static inline void pte_free(struct mm_struct *mm, struct page *pte) | 37 | static 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) \ |
44 | do { \ | ||
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; | |||
50 | typedef union { pteval_t pte, pte_low; } pte_t; | 50 | typedef union { pteval_t pte, pte_low; } pte_t; |
51 | typedef pte_t boot_pte_t; | 51 | typedef pte_t boot_pte_t; |
52 | 52 | ||
53 | typedef 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; | |||
71 | typedef unsigned long pgprotval_t; | 71 | typedef unsigned long pgprotval_t; |
72 | typedef unsigned long phys_addr_t; | 72 | typedef unsigned long phys_addr_t; |
73 | 73 | ||
74 | typedef struct page *pgtable_t; | ||
75 | |||
74 | typedef struct { pteval_t pte; } pte_t; | 76 | typedef 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 *); | |||
39 | extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); | 40 | extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); |
40 | 41 | ||
41 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long); | 42 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long); |
42 | extern struct page *pte_alloc_one(struct mm_struct *, unsigned long); | 43 | extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long); |
43 | 44 | ||
44 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | 45 | static 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 | ||
49 | static inline void pte_free(struct mm_struct *mm, struct page *pte) | 50 | static 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 | |||
15 | static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte) | 17 | static 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 | ||
94 | static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | 96 | static 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 | ||
111 | static inline void pte_free(struct mm_struct *mm, struct page *pte) | 118 | static 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) \ |
125 | do { \ | ||
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 @@ | |||
98 | typedef struct { unsigned long pte; } pte_t; /* page table entry */ | 98 | typedef struct { unsigned long pte; } pte_t; /* page table entry */ |
99 | typedef struct { unsigned long pgd; } pgd_t; /* PGD table entry */ | 99 | typedef struct { unsigned long pgd; } pgd_t; /* PGD table entry */ |
100 | typedef struct { unsigned long pgprot; } pgprot_t; | 100 | typedef struct { unsigned long pgprot; } pgprot_t; |
101 | typedef 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 | ||
28 | static inline pgd_t* | 29 | static inline pgd_t* |
29 | pgd_alloc(struct mm_struct *mm) | 30 | pgd_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 | ||
49 | static inline struct page *pte_alloc_one(struct mm_struct *mm, | 50 | static 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 | ||
55 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | 60 | static 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 | ||
60 | static inline void pte_free(struct mm_struct *mm, struct page *page) | 65 | static 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 | ||
897 | static inline void pgtable_page_ctor(struct page *page) | ||
898 | { | ||
899 | pte_lock_init(page); | ||
900 | inc_zone_page_state(page, NR_PAGETABLE); | ||
901 | } | ||
902 | |||
903 | static 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 | ||
1139 | typedef int (*pte_fn_t)(pte_t *pte, struct page *pmd_page, unsigned long addr, | 1151 | typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, |
1140 | void *data); | 1152 | void *data); |
1141 | extern int apply_to_page_range(struct mm_struct *mm, unsigned long address, | 1153 | extern 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); |
diff --git a/mm/memory.c b/mm/memory.c index 153a54b2013c..e5628a5fd678 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -134,11 +134,9 @@ void pmd_clear_bad(pmd_t *pmd) | |||
134 | */ | 134 | */ |
135 | static void free_pte_range(struct mmu_gather *tlb, pmd_t *pmd) | 135 | static void free_pte_range(struct mmu_gather *tlb, pmd_t *pmd) |
136 | { | 136 | { |
137 | struct page *page = pmd_page(*pmd); | 137 | pgtable_t token = pmd_pgtable(*pmd); |
138 | pmd_clear(pmd); | 138 | pmd_clear(pmd); |
139 | pte_lock_deinit(page); | 139 | pte_free_tlb(tlb, token); |
140 | pte_free_tlb(tlb, page); | ||
141 | dec_zone_page_state(page, NR_PAGETABLE); | ||
142 | tlb->mm->nr_ptes--; | 140 | tlb->mm->nr_ptes--; |
143 | } | 141 | } |
144 | 142 | ||
@@ -309,21 +307,19 @@ void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *vma, | |||
309 | 307 | ||
310 | int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address) | 308 | int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address) |
311 | { | 309 | { |
312 | struct page *new = pte_alloc_one(mm, address); | 310 | pgtable_t new = pte_alloc_one(mm, address); |
313 | if (!new) | 311 | if (!new) |
314 | return -ENOMEM; | 312 | return -ENOMEM; |
315 | 313 | ||
316 | pte_lock_init(new); | ||
317 | spin_lock(&mm->page_table_lock); | 314 | spin_lock(&mm->page_table_lock); |
318 | if (pmd_present(*pmd)) { /* Another has populated it */ | 315 | if (!pmd_present(*pmd)) { /* Has another populated it ? */ |
319 | pte_lock_deinit(new); | ||
320 | pte_free(mm, new); | ||
321 | } else { | ||
322 | mm->nr_ptes++; | 316 | mm->nr_ptes++; |
323 | inc_zone_page_state(new, NR_PAGETABLE); | ||
324 | pmd_populate(mm, pmd, new); | 317 | pmd_populate(mm, pmd, new); |
318 | new = NULL; | ||
325 | } | 319 | } |
326 | spin_unlock(&mm->page_table_lock); | 320 | spin_unlock(&mm->page_table_lock); |
321 | if (new) | ||
322 | pte_free(mm, new); | ||
327 | return 0; | 323 | return 0; |
328 | } | 324 | } |
329 | 325 | ||
@@ -334,11 +330,13 @@ int __pte_alloc_kernel(pmd_t *pmd, unsigned long address) | |||
334 | return -ENOMEM; | 330 | return -ENOMEM; |
335 | 331 | ||
336 | spin_lock(&init_mm.page_table_lock); | 332 | spin_lock(&init_mm.page_table_lock); |
337 | if (pmd_present(*pmd)) /* Another has populated it */ | 333 | if (!pmd_present(*pmd)) { /* Has another populated it ? */ |
338 | pte_free_kernel(&init_mm, new); | ||
339 | else | ||
340 | pmd_populate_kernel(&init_mm, pmd, new); | 334 | pmd_populate_kernel(&init_mm, pmd, new); |
335 | new = NULL; | ||
336 | } | ||
341 | spin_unlock(&init_mm.page_table_lock); | 337 | spin_unlock(&init_mm.page_table_lock); |
338 | if (new) | ||
339 | pte_free_kernel(&init_mm, new); | ||
342 | return 0; | 340 | return 0; |
343 | } | 341 | } |
344 | 342 | ||
@@ -1390,7 +1388,7 @@ static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd, | |||
1390 | { | 1388 | { |
1391 | pte_t *pte; | 1389 | pte_t *pte; |
1392 | int err; | 1390 | int err; |
1393 | struct page *pmd_page; | 1391 | pgtable_t token; |
1394 | spinlock_t *uninitialized_var(ptl); | 1392 | spinlock_t *uninitialized_var(ptl); |
1395 | 1393 | ||
1396 | pte = (mm == &init_mm) ? | 1394 | pte = (mm == &init_mm) ? |
@@ -1401,10 +1399,10 @@ static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd, | |||
1401 | 1399 | ||
1402 | BUG_ON(pmd_huge(*pmd)); | 1400 | BUG_ON(pmd_huge(*pmd)); |
1403 | 1401 | ||
1404 | pmd_page = pmd_page(*pmd); | 1402 | token = pmd_pgtable(*pmd); |
1405 | 1403 | ||
1406 | do { | 1404 | do { |
1407 | err = fn(pte, pmd_page, addr, data); | 1405 | err = fn(pte, token, addr, data); |
1408 | if (err) | 1406 | if (err) |
1409 | break; | 1407 | break; |
1410 | } while (pte++, addr += PAGE_SIZE, addr != end); | 1408 | } while (pte++, addr += PAGE_SIZE, addr != end); |
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 0536dde139d1..950c0be9ca81 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -820,7 +820,7 @@ void __attribute__((weak)) vmalloc_sync_all(void) | |||
820 | } | 820 | } |
821 | 821 | ||
822 | 822 | ||
823 | static int f(pte_t *pte, struct page *pmd_page, unsigned long addr, void *data) | 823 | static int f(pte_t *pte, pgtable_t table, unsigned long addr, void *data) |
824 | { | 824 | { |
825 | /* apply_to_page_range() does all the hard work. */ | 825 | /* apply_to_page_range() does all the hard work. */ |
826 | return 0; | 826 | return 0; |