diff options
Diffstat (limited to 'arch/powerpc/include/asm/pgalloc.h')
| -rw-r--r-- | arch/powerpc/include/asm/pgalloc.h | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/arch/powerpc/include/asm/pgalloc.h b/arch/powerpc/include/asm/pgalloc.h index 1730e5e298d6..f2e812de7c3c 100644 --- a/arch/powerpc/include/asm/pgalloc.h +++ b/arch/powerpc/include/asm/pgalloc.h | |||
| @@ -4,6 +4,15 @@ | |||
| 4 | 4 | ||
| 5 | #include <linux/mm.h> | 5 | #include <linux/mm.h> |
| 6 | 6 | ||
| 7 | #ifdef CONFIG_PPC_BOOK3E | ||
| 8 | extern void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address); | ||
| 9 | #else /* CONFIG_PPC_BOOK3E */ | ||
| 10 | static inline void tlb_flush_pgtable(struct mmu_gather *tlb, | ||
| 11 | unsigned long address) | ||
| 12 | { | ||
| 13 | } | ||
| 14 | #endif /* !CONFIG_PPC_BOOK3E */ | ||
| 15 | |||
| 7 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | 16 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) |
| 8 | { | 17 | { |
| 9 | free_page((unsigned long)pte); | 18 | free_page((unsigned long)pte); |
| @@ -19,7 +28,12 @@ typedef struct pgtable_free { | |||
| 19 | unsigned long val; | 28 | unsigned long val; |
| 20 | } pgtable_free_t; | 29 | } pgtable_free_t; |
| 21 | 30 | ||
| 22 | #define PGF_CACHENUM_MASK 0x7 | 31 | /* This needs to be big enough to allow for MMU_PAGE_COUNT + 2 to be stored |
| 32 | * and small enough to fit in the low bits of any naturally aligned page | ||
| 33 | * table cache entry. Arbitrarily set to 0x1f, that should give us some | ||
| 34 | * room to grow | ||
| 35 | */ | ||
| 36 | #define PGF_CACHENUM_MASK 0x1f | ||
| 23 | 37 | ||
| 24 | static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, | 38 | static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, |
| 25 | unsigned long mask) | 39 | unsigned long mask) |
| @@ -35,19 +49,27 @@ static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, | |||
| 35 | #include <asm/pgalloc-32.h> | 49 | #include <asm/pgalloc-32.h> |
| 36 | #endif | 50 | #endif |
| 37 | 51 | ||
| 38 | extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); | ||
| 39 | |||
| 40 | #ifdef CONFIG_SMP | 52 | #ifdef CONFIG_SMP |
| 41 | #define __pte_free_tlb(tlb,ptepage,address) \ | 53 | extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); |
| 42 | do { \ | 54 | extern void pte_free_finish(void); |
| 43 | pgtable_page_dtor(ptepage); \ | 55 | #else /* CONFIG_SMP */ |
| 44 | pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \ | 56 | static inline void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) |
| 45 | PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1)); \ | 57 | { |
| 46 | } while (0) | 58 | pgtable_free(pgf); |
| 47 | #else | 59 | } |
| 48 | #define __pte_free_tlb(tlb, pte, address) pte_free((tlb)->mm, (pte)) | 60 | static inline void pte_free_finish(void) { } |
| 49 | #endif | 61 | #endif /* !CONFIG_SMP */ |
| 50 | 62 | ||
| 63 | static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage, | ||
| 64 | unsigned long address) | ||
| 65 | { | ||
| 66 | pgtable_free_t pgf = pgtable_free_cache(page_address(ptepage), | ||
| 67 | PTE_NONCACHE_NUM, | ||
| 68 | PTE_TABLE_SIZE-1); | ||
| 69 | tlb_flush_pgtable(tlb, address); | ||
| 70 | pgtable_page_dtor(ptepage); | ||
| 71 | pgtable_free_tlb(tlb, pgf); | ||
| 72 | } | ||
| 51 | 73 | ||
| 52 | #endif /* __KERNEL__ */ | 74 | #endif /* __KERNEL__ */ |
| 53 | #endif /* _ASM_POWERPC_PGALLOC_H */ | 75 | #endif /* _ASM_POWERPC_PGALLOC_H */ |
