diff options
Diffstat (limited to 'include')
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 | ||
| 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); |
