2005-04-16 15:20:36 -07:00
# ifndef _I386_PGALLOC_H
# define _I386_PGALLOC_H
# include <linux/threads.h>
# include <linux/mm.h> /* for struct page */
2008-01-31 22:05:48 +01:00
# include <linux/pagemap.h>
2008-01-30 13:33:39 +01:00
# include <asm/tlb.h>
# include <asm-generic/tlb.h>
2005-04-16 15:20:36 -07:00
2007-02-13 13:26:21 +01:00
# ifdef CONFIG_PARAVIRT
# include <asm/paravirt.h>
# else
2007-07-17 18:37:03 -07:00
# define paravirt_alloc_pt(mm, pfn) do { } while (0)
2008-01-30 13:33:39 +01:00
# define paravirt_alloc_pd(mm, pfn) do { } while (0)
2007-02-13 13:26:21 +01:00
# define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) do { } while (0)
# define paravirt_release_pt(pfn) do { } while (0)
# define paravirt_release_pd(pfn) do { } while (0)
# endif
2008-01-30 13:33:39 +01:00
static inline void pmd_populate_kernel ( struct mm_struct * mm ,
pmd_t * pmd , pte_t * pte )
{
paravirt_alloc_pt ( mm , __pa ( pte ) > > PAGE_SHIFT ) ;
set_pmd ( pmd , __pmd ( __pa ( pte ) | _PAGE_TABLE ) ) ;
}
2005-04-16 15:20:36 -07:00
2008-01-30 13:33:39 +01:00
static inline void pmd_populate ( struct mm_struct * mm , pmd_t * pmd , struct page * pte )
{
unsigned long pfn = page_to_pfn ( pte ) ;
paravirt_alloc_pt ( mm , pfn ) ;
set_pmd ( pmd , __pmd ( ( ( pteval_t ) pfn < < PAGE_SHIFT ) | _PAGE_TABLE ) ) ;
}
2007-02-13 13:26:21 +01:00
2005-04-16 15:20:36 -07:00
/*
* Allocate and free page tables .
*/
extern pgd_t * pgd_alloc ( struct mm_struct * ) ;
2008-02-04 22:29:14 -08:00
extern void pgd_free ( struct mm_struct * mm , pgd_t * pgd ) ;
2005-04-16 15:20:36 -07:00
extern pte_t * pte_alloc_one_kernel ( struct mm_struct * , unsigned long ) ;
extern struct page * pte_alloc_one ( struct mm_struct * , unsigned long ) ;
2008-02-04 22:29:14 -08:00
static inline void pte_free_kernel ( struct mm_struct * mm , pte_t * pte )
2005-04-16 15:20:36 -07:00
{
free_page ( ( unsigned long ) pte ) ;
}
2008-02-04 22:29:14 -08:00
static inline void pte_free ( struct mm_struct * mm , struct page * pte )
2005-04-16 15:20:36 -07:00
{
__free_page ( pte ) ;
}
2008-01-31 22:05:48 +01:00
extern void __pte_free_tlb ( struct mmu_gather * tlb , struct page * pte ) ;
2005-04-16 15:20:36 -07:00
# ifdef CONFIG_X86_PAE
/*
* In the PAE case we free the pmds as part of the pgd .
*/
2008-01-30 13:33:39 +01:00
static inline pmd_t * pmd_alloc_one ( struct mm_struct * mm , unsigned long addr )
{
2008-01-30 13:34:11 +01:00
return ( pmd_t * ) get_zeroed_page ( GFP_KERNEL | __GFP_REPEAT ) ;
2008-01-30 13:33:39 +01:00
}
2008-02-04 22:29:14 -08:00
static inline void pmd_free ( struct mm_struct * mm , pmd_t * pmd )
2008-01-30 13:33:39 +01:00
{
2008-01-30 13:34:11 +01:00
BUG_ON ( ( unsigned long ) pmd & ( PAGE_SIZE - 1 ) ) ;
free_page ( ( unsigned long ) pmd ) ;
2008-01-30 13:33:39 +01:00
}
2008-01-31 22:05:48 +01:00
extern void __pmd_free_tlb ( struct mmu_gather * tlb , pmd_t * pmd ) ;
2008-01-30 13:33:39 +01:00
2008-01-30 13:34:11 +01:00
static inline void pud_populate ( struct mm_struct * mm , pud_t * pudp , pmd_t * pmd )
2008-01-30 13:33:39 +01:00
{
2008-01-30 13:34:11 +01:00
paravirt_alloc_pd ( mm , __pa ( pmd ) > > PAGE_SHIFT ) ;
/* Note: almost everything apart from _PAGE_PRESENT is
reserved at the pmd ( PDPT ) level . */
set_pud ( pudp , __pud ( __pa ( pmd ) | _PAGE_PRESENT ) ) ;
/*
2008-02-04 16:48:02 +01:00
* According to Intel App note " TLBs, Paging-Structure Caches,
* and Their Invalidation " , April 2007, document 317080-001,
* section 8.1 : in PAE mode we explicitly have to flush the
* TLB via cr3 if the top - level pgd is changed . . .
2008-01-30 13:34:11 +01:00
*/
if ( mm = = current - > active_mm )
write_cr3 ( read_cr3 ( ) ) ;
2008-01-30 13:33:39 +01:00
}
# endif /* CONFIG_X86_PAE */
2005-04-16 15:20:36 -07:00
# endif /* _I386_PGALLOC_H */