at v2.6.22-rc2 147 lines 3.8 kB view raw
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 15extern struct kmem_cache *pgtable_cache[]; 16 17#define PGD_CACHE_NUM 0 18#define PUD_CACHE_NUM 1 19#define PMD_CACHE_NUM 1 20#define HUGEPTE_CACHE_NUM 2 21#define PTE_NONCACHE_NUM 3 /* from GFP rather than kmem_cache */ 22 23static inline pgd_t *pgd_alloc(struct mm_struct *mm) 24{ 25 return kmem_cache_alloc(pgtable_cache[PGD_CACHE_NUM], GFP_KERNEL); 26} 27 28static inline void pgd_free(pgd_t *pgd) 29{ 30 kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd); 31} 32 33#ifndef CONFIG_PPC_64K_PAGES 34 35#define pgd_populate(MM, PGD, PUD) pgd_set(PGD, PUD) 36 37static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) 38{ 39 return kmem_cache_alloc(pgtable_cache[PUD_CACHE_NUM], 40 GFP_KERNEL|__GFP_REPEAT); 41} 42 43static inline void pud_free(pud_t *pud) 44{ 45 kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud); 46} 47 48static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) 49{ 50 pud_set(pud, (unsigned long)pmd); 51} 52 53#define pmd_populate(mm, pmd, pte_page) \ 54 pmd_populate_kernel(mm, pmd, page_address(pte_page)) 55#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, (unsigned long)(pte)) 56 57 58#else /* CONFIG_PPC_64K_PAGES */ 59 60#define pud_populate(mm, pud, pmd) pud_set(pud, (unsigned long)pmd) 61 62static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, 63 pte_t *pte) 64{ 65 pmd_set(pmd, (unsigned long)pte); 66} 67 68#define pmd_populate(mm, pmd, pte_page) \ 69 pmd_populate_kernel(mm, pmd, page_address(pte_page)) 70 71#endif /* CONFIG_PPC_64K_PAGES */ 72 73static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) 74{ 75 return kmem_cache_alloc(pgtable_cache[PMD_CACHE_NUM], 76 GFP_KERNEL|__GFP_REPEAT); 77} 78 79static inline void pmd_free(pmd_t *pmd) 80{ 81 kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd); 82} 83 84static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, 85 unsigned long address) 86{ 87 return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO); 88} 89 90static inline struct page *pte_alloc_one(struct mm_struct *mm, 91 unsigned long address) 92{ 93 return virt_to_page(pte_alloc_one_kernel(mm, address)); 94} 95 96static inline void pte_free_kernel(pte_t *pte) 97{ 98 free_page((unsigned long)pte); 99} 100 101static inline void pte_free(struct page *ptepage) 102{ 103 __free_page(ptepage); 104} 105 106#define PGF_CACHENUM_MASK 0x3 107 108typedef struct pgtable_free { 109 unsigned long val; 110} pgtable_free_t; 111 112static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, 113 unsigned long mask) 114{ 115 BUG_ON(cachenum > PGF_CACHENUM_MASK); 116 117 return (pgtable_free_t){.val = ((unsigned long) p & ~mask) | cachenum}; 118} 119 120static inline void pgtable_free(pgtable_free_t pgf) 121{ 122 void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK); 123 int cachenum = pgf.val & PGF_CACHENUM_MASK; 124 125 if (cachenum == PTE_NONCACHE_NUM) 126 free_page((unsigned long)p); 127 else 128 kmem_cache_free(pgtable_cache[cachenum], p); 129} 130 131extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); 132 133#define __pte_free_tlb(tlb, ptepage) \ 134 pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \ 135 PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1)) 136#define __pmd_free_tlb(tlb, pmd) \ 137 pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \ 138 PMD_CACHE_NUM, PMD_TABLE_SIZE-1)) 139#ifndef CONFIG_PPC_64K_PAGES 140#define __pud_free_tlb(tlb, pud) \ 141 pgtable_free_tlb(tlb, pgtable_free_cache(pud, \ 142 PUD_CACHE_NUM, PUD_TABLE_SIZE-1)) 143#endif /* CONFIG_PPC_64K_PAGES */ 144 145#define check_pgt_cache() do { } while (0) 146 147#endif /* _ASM_POWERPC_PGALLOC_64_H */