1#ifndef _ASM_POWERPC_PGALLOC_64_H 2#define _ASM_POWERPC_PGALLOC_64_H 3/* 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 */ 9 10#include <linux/mm.h> 11#include <linux/slab.h> 12#include <linux/cpumask.h> 13#include <linux/percpu.h> 14 15#ifndef CONFIG_PPC_SUBPAGE_PROT 16static inline void subpage_prot_free(pgd_t *pgd) {} 17#endif 18 19extern struct kmem_cache *pgtable_cache[]; 20 21#define PGD_CACHE_NUM 0 22#define PUD_CACHE_NUM 1 23#define PMD_CACHE_NUM 1 24#define HUGEPTE_CACHE_NUM 2 25#define PTE_NONCACHE_NUM 3 /* from GFP rather than kmem_cache */ 26 27static inline pgd_t *pgd_alloc(struct mm_struct *mm) 28{ 29 return kmem_cache_alloc(pgtable_cache[PGD_CACHE_NUM], GFP_KERNEL); 30} 31 32static inline void pgd_free(pgd_t *pgd) 33{ 34 subpage_prot_free(pgd); 35 kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd); 36} 37 38#ifndef CONFIG_PPC_64K_PAGES 39 40#define pgd_populate(MM, PGD, PUD) pgd_set(PGD, PUD) 41 42static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) 43{ 44 return kmem_cache_alloc(pgtable_cache[PUD_CACHE_NUM], 45 GFP_KERNEL|__GFP_REPEAT); 46} 47 48static inline void pud_free(pud_t *pud) 49{ 50 kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud); 51} 52 53static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) 54{ 55 pud_set(pud, (unsigned long)pmd); 56} 57 58#define pmd_populate(mm, pmd, 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)) 61 62 63#else /* CONFIG_PPC_64K_PAGES */ 64 65#define pud_populate(mm, pud, pmd) pud_set(pud, (unsigned long)pmd) 66 67static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, 68 pte_t *pte) 69{ 70 pmd_set(pmd, (unsigned long)pte); 71} 72 73#define pmd_populate(mm, pmd, pte_page) \ 74 pmd_populate_kernel(mm, pmd, page_address(pte_page)) 75 76#endif /* CONFIG_PPC_64K_PAGES */ 77 78static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) 79{ 80 return kmem_cache_alloc(pgtable_cache[PMD_CACHE_NUM], 81 GFP_KERNEL|__GFP_REPEAT); 82} 83 84static inline void pmd_free(pmd_t *pmd) 85{ 86 kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd); 87} 88 89static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, 90 unsigned long address) 91{ 92 return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO); 93} 94 95static inline struct page *pte_alloc_one(struct mm_struct *mm, 96 unsigned long address) 97{ 98 pte_t *pte = pte_alloc_one_kernel(mm, address); 99 return pte ? virt_to_page(pte) : NULL; 100} 101 102static inline void pte_free_kernel(pte_t *pte) 103{ 104 free_page((unsigned long)pte); 105} 106 107static inline void pte_free(struct page *ptepage) 108{ 109 __free_page(ptepage); 110} 111 112#define PGF_CACHENUM_MASK 0x3 113 114typedef struct pgtable_free { 115 unsigned long val; 116} pgtable_free_t; 117 118static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, 119 unsigned long mask) 120{ 121 BUG_ON(cachenum > PGF_CACHENUM_MASK); 122 123 return (pgtable_free_t){.val = ((unsigned long) p & ~mask) | cachenum}; 124} 125 126static inline void pgtable_free(pgtable_free_t pgf) 127{ 128 void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK); 129 int cachenum = pgf.val & PGF_CACHENUM_MASK; 130 131 if (cachenum == PTE_NONCACHE_NUM) 132 free_page((unsigned long)p); 133 else 134 kmem_cache_free(pgtable_cache[cachenum], p); 135} 136 137extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); 138 139#define __pte_free_tlb(tlb, ptepage) \ 140 pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \ 141 PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1)) 142#define __pmd_free_tlb(tlb, pmd) \ 143 pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \ 144 PMD_CACHE_NUM, PMD_TABLE_SIZE-1)) 145#ifndef CONFIG_PPC_64K_PAGES 146#define __pud_free_tlb(tlb, pud) \ 147 pgtable_free_tlb(tlb, pgtable_free_cache(pud, \ 148 PUD_CACHE_NUM, PUD_TABLE_SIZE-1)) 149#endif /* CONFIG_PPC_64K_PAGES */ 150 151#define check_pgt_cache() do { } while (0) 152 153#endif /* _ASM_POWERPC_PGALLOC_64_H */