at v2.6.30 132 lines 3.5 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/slab.h> 11#include <linux/cpumask.h> 12#include <linux/percpu.h> 13 14#ifndef CONFIG_PPC_SUBPAGE_PROT 15static inline void subpage_prot_free(pgd_t *pgd) {} 16#endif 17 18extern struct kmem_cache *pgtable_cache[]; 19 20#define PGD_CACHE_NUM 0 21#define PUD_CACHE_NUM 1 22#define PMD_CACHE_NUM 1 23#define HUGEPTE_CACHE_NUM 2 24#define PTE_NONCACHE_NUM 7 /* from GFP rather than kmem_cache */ 25 26static inline pgd_t *pgd_alloc(struct mm_struct *mm) 27{ 28 return kmem_cache_alloc(pgtable_cache[PGD_CACHE_NUM], GFP_KERNEL); 29} 30 31static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) 32{ 33 subpage_prot_free(pgd); 34 kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd); 35} 36 37#ifndef CONFIG_PPC_64K_PAGES 38 39#define pgd_populate(MM, PGD, PUD) pgd_set(PGD, PUD) 40 41static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) 42{ 43 return kmem_cache_alloc(pgtable_cache[PUD_CACHE_NUM], 44 GFP_KERNEL|__GFP_REPEAT); 45} 46 47static inline void pud_free(struct mm_struct *mm, pud_t *pud) 48{ 49 kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud); 50} 51 52static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) 53{ 54 pud_set(pud, (unsigned long)pmd); 55} 56 57#define pmd_populate(mm, pmd, pte_page) \ 58 pmd_populate_kernel(mm, pmd, page_address(pte_page)) 59#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, (unsigned long)(pte)) 60#define pmd_pgtable(pmd) pmd_page(pmd) 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#define pmd_pgtable(pmd) pmd_page(pmd) 76 77#endif /* CONFIG_PPC_64K_PAGES */ 78 79static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) 80{ 81 return kmem_cache_alloc(pgtable_cache[PMD_CACHE_NUM], 82 GFP_KERNEL|__GFP_REPEAT); 83} 84 85static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) 86{ 87 kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd); 88} 89 90static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, 91 unsigned long address) 92{ 93 return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO); 94} 95 96static inline pgtable_t pte_alloc_one(struct mm_struct *mm, 97 unsigned long address) 98{ 99 struct page *page; 100 pte_t *pte; 101 102 pte = pte_alloc_one_kernel(mm, address); 103 if (!pte) 104 return NULL; 105 page = virt_to_page(pte); 106 pgtable_page_ctor(page); 107 return page; 108} 109 110static inline void pgtable_free(pgtable_free_t pgf) 111{ 112 void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK); 113 int cachenum = pgf.val & PGF_CACHENUM_MASK; 114 115 if (cachenum == PTE_NONCACHE_NUM) 116 free_page((unsigned long)p); 117 else 118 kmem_cache_free(pgtable_cache[cachenum], p); 119} 120 121#define __pmd_free_tlb(tlb, pmd) \ 122 pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \ 123 PMD_CACHE_NUM, PMD_TABLE_SIZE-1)) 124#ifndef CONFIG_PPC_64K_PAGES 125#define __pud_free_tlb(tlb, pud) \ 126 pgtable_free_tlb(tlb, pgtable_free_cache(pud, \ 127 PUD_CACHE_NUM, PUD_TABLE_SIZE-1)) 128#endif /* CONFIG_PPC_64K_PAGES */ 129 130#define check_pgt_cache() do { } while (0) 131 132#endif /* _ASM_POWERPC_PGALLOC_64_H */