2008-07-17 21:55:51 -07:00
# ifndef _SPARC64_PGALLOC_H
# define _SPARC64_PGALLOC_H
# include <linux/kernel.h>
# include <linux/sched.h>
# include <linux/mm.h>
# include <linux/slab.h>
# include <asm/spitfire.h>
# include <asm/cpudata.h>
# include <asm/cacheflush.h>
# include <asm/page.h>
/* Page table allocation/freeing. */
2011-07-25 17:12:20 -07:00
extern struct kmem_cache * pgtable_cache ;
2008-07-17 21:55:51 -07:00
static inline pgd_t * pgd_alloc ( struct mm_struct * mm )
{
2011-07-25 17:12:20 -07:00
return kmem_cache_alloc ( pgtable_cache , GFP_KERNEL ) ;
2008-07-17 21:55:51 -07:00
}
static inline void pgd_free ( struct mm_struct * mm , pgd_t * pgd )
{
2011-07-25 17:12:20 -07:00
kmem_cache_free ( pgtable_cache , pgd ) ;
2008-07-17 21:55:51 -07:00
}
# define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD)
static inline pmd_t * pmd_alloc_one ( struct mm_struct * mm , unsigned long addr )
{
2011-07-25 17:12:20 -07:00
return kmem_cache_alloc ( pgtable_cache ,
GFP_KERNEL | __GFP_REPEAT ) ;
2008-07-17 21:55:51 -07:00
}
static inline void pmd_free ( struct mm_struct * mm , pmd_t * pmd )
{
2011-07-25 17:12:20 -07:00
kmem_cache_free ( pgtable_cache , pmd ) ;
2008-07-17 21:55:51 -07:00
}
static inline pte_t * pte_alloc_one_kernel ( struct mm_struct * mm ,
unsigned long address )
{
2011-07-25 17:12:20 -07:00
return ( pte_t * ) __get_free_page ( GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO ) ;
2008-07-17 21:55:51 -07:00
}
static inline pgtable_t pte_alloc_one ( struct mm_struct * mm ,
unsigned long address )
{
struct page * page ;
2011-07-25 17:12:20 -07:00
pte_t * pte ;
2008-07-17 21:55:51 -07:00
2011-07-25 17:12:20 -07:00
pte = pte_alloc_one_kernel ( mm , address ) ;
if ( ! pte )
2008-07-17 21:55:51 -07:00
return NULL ;
2011-07-25 17:12:20 -07:00
page = virt_to_page ( pte ) ;
2008-07-17 21:55:51 -07:00
pgtable_page_ctor ( page ) ;
return page ;
}
static inline void pte_free_kernel ( struct mm_struct * mm , pte_t * pte )
{
2011-07-25 17:12:20 -07:00
free_page ( ( unsigned long ) pte ) ;
2008-07-17 21:55:51 -07:00
}
static inline void pte_free ( struct mm_struct * mm , pgtable_t ptepage )
{
pgtable_page_dtor ( ptepage ) ;
2011-07-25 17:12:20 -07:00
__free_page ( ptepage ) ;
2008-07-17 21:55:51 -07:00
}
# define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE)
# define pmd_populate(MM,PMD,PTE_PAGE) \
pmd_populate_kernel ( MM , PMD , page_address ( PTE_PAGE ) )
# define pmd_pgtable(pmd) pmd_page(pmd)
2011-07-25 17:12:20 -07:00
# define check_pgt_cache() do { } while (0)
2008-07-17 21:55:51 -07:00
2011-07-25 17:12:21 -07:00
static inline void pgtable_free ( void * table , bool is_page )
{
if ( is_page )
free_page ( ( unsigned long ) table ) ;
else
kmem_cache_free ( pgtable_cache , table ) ;
}
# ifdef CONFIG_SMP
struct mmu_gather ;
extern void tlb_remove_table ( struct mmu_gather * , void * ) ;
static inline void pgtable_free_tlb ( struct mmu_gather * tlb , void * table , bool is_page )
{
unsigned long pgf = ( unsigned long ) table ;
if ( is_page )
pgf | = 0x1UL ;
tlb_remove_table ( tlb , ( void * ) pgf ) ;
}
static inline void __tlb_remove_table ( void * _table )
{
void * table = ( void * ) ( ( unsigned long ) _table & ~ 0x1UL ) ;
bool is_page = false ;
if ( ( unsigned long ) _table & 0x1UL )
is_page = true ;
pgtable_free ( table , is_page ) ;
}
# else /* CONFIG_SMP */
static inline void pgtable_free_tlb ( struct mmu_gather * tlb , void * table , bool is_page )
{
pgtable_free ( table , is_page ) ;
}
# endif /* !CONFIG_SMP */
static inline void __pte_free_tlb ( struct mmu_gather * tlb , struct page * ptepage ,
unsigned long address )
{
pgtable_page_dtor ( ptepage ) ;
pgtable_free_tlb ( tlb , page_address ( ptepage ) , true ) ;
}
# define __pmd_free_tlb(tlb, pmd, addr) \
pgtable_free_tlb ( tlb , pmd , false )
2011-05-24 17:11:50 -07:00
2008-07-17 21:55:51 -07:00
# endif /* _SPARC64_PGALLOC_H */