0001
0002 #ifndef _SPARC64_PGALLOC_H
0003 #define _SPARC64_PGALLOC_H
0004
0005 #include <linux/kernel.h>
0006 #include <linux/sched.h>
0007 #include <linux/mm.h>
0008 #include <linux/slab.h>
0009
0010 #include <asm/spitfire.h>
0011 #include <asm/cpudata.h>
0012 #include <asm/cacheflush.h>
0013 #include <asm/page.h>
0014
0015
0016
0017 extern struct kmem_cache *pgtable_cache;
0018
0019 static inline void __p4d_populate(p4d_t *p4d, pud_t *pud)
0020 {
0021 p4d_set(p4d, pud);
0022 }
0023
0024 #define p4d_populate(MM, P4D, PUD) __p4d_populate(P4D, PUD)
0025
0026 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
0027 {
0028 return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
0029 }
0030
0031 static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
0032 {
0033 kmem_cache_free(pgtable_cache, pgd);
0034 }
0035
0036 static inline void __pud_populate(pud_t *pud, pmd_t *pmd)
0037 {
0038 pud_set(pud, pmd);
0039 }
0040
0041 #define pud_populate(MM, PUD, PMD) __pud_populate(PUD, PMD)
0042
0043 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
0044 {
0045 return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
0046 }
0047
0048 static inline void pud_free(struct mm_struct *mm, pud_t *pud)
0049 {
0050 kmem_cache_free(pgtable_cache, pud);
0051 }
0052
0053 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
0054 {
0055 return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
0056 }
0057
0058 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
0059 {
0060 kmem_cache_free(pgtable_cache, pmd);
0061 }
0062
0063 pte_t *pte_alloc_one_kernel(struct mm_struct *mm);
0064 pgtable_t pte_alloc_one(struct mm_struct *mm);
0065 void pte_free_kernel(struct mm_struct *mm, pte_t *pte);
0066 void pte_free(struct mm_struct *mm, pgtable_t ptepage);
0067
0068 #define pmd_populate_kernel(MM, PMD, PTE) pmd_set(MM, PMD, PTE)
0069 #define pmd_populate(MM, PMD, PTE) pmd_set(MM, PMD, PTE)
0070
0071 void pgtable_free(void *table, bool is_page);
0072
0073 #ifdef CONFIG_SMP
0074
0075 struct mmu_gather;
0076 void tlb_remove_table(struct mmu_gather *, void *);
0077
0078 static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
0079 {
0080 unsigned long pgf = (unsigned long)table;
0081 if (is_page)
0082 pgf |= 0x1UL;
0083 tlb_remove_table(tlb, (void *)pgf);
0084 }
0085
0086 static inline void __tlb_remove_table(void *_table)
0087 {
0088 void *table = (void *)((unsigned long)_table & ~0x1UL);
0089 bool is_page = false;
0090
0091 if ((unsigned long)_table & 0x1UL)
0092 is_page = true;
0093 pgtable_free(table, is_page);
0094 }
0095 #else
0096 static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
0097 {
0098 pgtable_free(table, is_page);
0099 }
0100 #endif
0101
0102 static inline void __pte_free_tlb(struct mmu_gather *tlb, pte_t *pte,
0103 unsigned long address)
0104 {
0105 pgtable_free_tlb(tlb, pte, true);
0106 }
0107
0108 #define __pmd_free_tlb(tlb, pmd, addr) \
0109 pgtable_free_tlb(tlb, pmd, false)
0110
0111 #define __pud_free_tlb(tlb, pud, addr) \
0112 pgtable_free_tlb(tlb, pud, false)
0113
0114 #endif