2008-10-22 22:26:29 -07:00
# ifndef _ASM_X86_PGALLOC_H
# define _ASM_X86_PGALLOC_H
2008-03-17 16:36:55 -07:00
# include <linux/threads.h>
# include <linux/mm.h> /* for struct page */
# include <linux/pagemap.h>
2008-06-25 00:19:12 -04:00
static inline int __paravirt_pgd_alloc ( struct mm_struct * mm ) { return 0 ; }
2008-03-17 16:36:56 -07:00
# ifdef CONFIG_PARAVIRT
# include <asm/paravirt.h>
# else
2008-06-25 00:19:12 -04:00
# define paravirt_pgd_alloc(mm) __paravirt_pgd_alloc(mm)
static inline void paravirt_pgd_free ( struct mm_struct * mm , pgd_t * pgd ) { }
2008-03-17 16:37:06 -07:00
static inline void paravirt_alloc_pte ( struct mm_struct * mm , unsigned long pfn ) { }
static inline void paravirt_alloc_pmd ( struct mm_struct * mm , unsigned long pfn ) { }
static inline void paravirt_alloc_pmd_clone ( unsigned long pfn , unsigned long clonepfn ,
unsigned long start , unsigned long count ) { }
static inline void paravirt_alloc_pud ( struct mm_struct * mm , unsigned long pfn ) { }
static inline void paravirt_release_pte ( unsigned long pfn ) { }
static inline void paravirt_release_pmd ( unsigned long pfn ) { }
static inline void paravirt_release_pud ( unsigned long pfn ) { }
2008-03-17 16:36:56 -07:00
# endif
2008-03-17 16:36:55 -07:00
/*
* Allocate and free page tables .
*/
extern pgd_t * pgd_alloc ( struct mm_struct * ) ;
extern void pgd_free ( struct mm_struct * mm , pgd_t * pgd ) ;
extern pte_t * pte_alloc_one_kernel ( struct mm_struct * , unsigned long ) ;
extern pgtable_t pte_alloc_one ( struct mm_struct * , unsigned long ) ;
2008-03-17 16:36:57 -07:00
/* Should really implement gc for free page table pages. This could be
done with a reference count in struct page . */
static inline void pte_free_kernel ( struct mm_struct * mm , pte_t * pte )
{
BUG_ON ( ( unsigned long ) pte & ( PAGE_SIZE - 1 ) ) ;
free_page ( ( unsigned long ) pte ) ;
}
static inline void pte_free ( struct mm_struct * mm , struct page * pte )
{
__free_page ( pte ) ;
}
extern void __pte_free_tlb ( struct mmu_gather * tlb , struct page * pte ) ;
2008-03-17 16:36:58 -07:00
static inline void pmd_populate_kernel ( struct mm_struct * mm ,
pmd_t * pmd , pte_t * pte )
{
2008-03-17 16:37:01 -07:00
paravirt_alloc_pte ( mm , __pa ( pte ) > > PAGE_SHIFT ) ;
2008-03-17 16:36:58 -07:00
set_pmd ( pmd , __pmd ( __pa ( pte ) | _PAGE_TABLE ) ) ;
}
static inline void pmd_populate ( struct mm_struct * mm , pmd_t * pmd ,
struct page * pte )
{
unsigned long pfn = page_to_pfn ( pte ) ;
2008-03-17 16:37:01 -07:00
paravirt_alloc_pte ( mm , pfn ) ;
2008-03-17 16:36:58 -07:00
set_pmd ( pmd , __pmd ( ( ( pteval_t ) pfn < < PAGE_SHIFT ) | _PAGE_TABLE ) ) ;
}
# define pmd_pgtable(pmd) pmd_page(pmd)
# if PAGETABLE_LEVELS > 2
static inline pmd_t * pmd_alloc_one ( struct mm_struct * mm , unsigned long addr )
{
return ( pmd_t * ) get_zeroed_page ( GFP_KERNEL | __GFP_REPEAT ) ;
}
static inline void pmd_free ( struct mm_struct * mm , pmd_t * pmd )
{
BUG_ON ( ( unsigned long ) pmd & ( PAGE_SIZE - 1 ) ) ;
free_page ( ( unsigned long ) pmd ) ;
}
extern void __pmd_free_tlb ( struct mmu_gather * tlb , pmd_t * pmd ) ;
2008-03-17 16:36:59 -07:00
# ifdef CONFIG_X86_PAE
extern void pud_populate ( struct mm_struct * mm , pud_t * pudp , pmd_t * pmd ) ;
# else /* !CONFIG_X86_PAE */
static inline void pud_populate ( struct mm_struct * mm , pud_t * pud , pmd_t * pmd )
{
2008-03-17 16:37:01 -07:00
paravirt_alloc_pmd ( mm , __pa ( pmd ) > > PAGE_SHIFT ) ;
2008-03-17 16:36:59 -07:00
set_pud ( pud , __pud ( _PAGE_TABLE | __pa ( pmd ) ) ) ;
}
# endif /* CONFIG_X86_PAE */
# if PAGETABLE_LEVELS > 3
static inline void pgd_populate ( struct mm_struct * mm , pgd_t * pgd , pud_t * pud )
{
2008-03-17 16:37:02 -07:00
paravirt_alloc_pud ( mm , __pa ( pud ) > > PAGE_SHIFT ) ;
2008-03-17 16:36:59 -07:00
set_pgd ( pgd , __pgd ( _PAGE_TABLE | __pa ( pud ) ) ) ;
}
static inline pud_t * pud_alloc_one ( struct mm_struct * mm , unsigned long addr )
{
return ( pud_t * ) get_zeroed_page ( GFP_KERNEL | __GFP_REPEAT ) ;
}
static inline void pud_free ( struct mm_struct * mm , pud_t * pud )
{
BUG_ON ( ( unsigned long ) pud & ( PAGE_SIZE - 1 ) ) ;
free_page ( ( unsigned long ) pud ) ;
}
extern void __pud_free_tlb ( struct mmu_gather * tlb , pud_t * pud ) ;
# endif /* PAGETABLE_LEVELS > 3 */
# endif /* PAGETABLE_LEVELS > 2 */
2008-03-17 16:36:55 -07:00
2008-10-22 22:26:29 -07:00
# endif /* _ASM_X86_PGALLOC_H */