diff options
Diffstat (limited to 'include/asm-generic/pgalloc.h')
| -rw-r--r-- | include/asm-generic/pgalloc.h | 88 | 
1 files changed, 52 insertions, 36 deletions
diff --git a/include/asm-generic/pgalloc.h b/include/asm-generic/pgalloc.h index a7cf825befae..c75d4a753849 100644 --- a/include/asm-generic/pgalloc.h +++ b/include/asm-generic/pgalloc.h @@ -8,7 +8,7 @@  #define GFP_PGTABLE_USER	(GFP_PGTABLE_KERNEL | __GFP_ACCOUNT)  /** - * __pte_alloc_one_kernel - allocate a page for PTE-level kernel page table + * __pte_alloc_one_kernel - allocate memory for a PTE-level kernel page table   * @mm: the mm_struct of the current context   *   * This function is intended for architectures that need @@ -18,12 +18,17 @@   */  static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm)  { -	return (pte_t *)__get_free_page(GFP_PGTABLE_KERNEL); +	struct ptdesc *ptdesc = pagetable_alloc(GFP_PGTABLE_KERNEL & +			~__GFP_HIGHMEM, 0); + +	if (!ptdesc) +		return NULL; +	return ptdesc_address(ptdesc);  }  #ifndef __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL  /** - * pte_alloc_one_kernel - allocate a page for PTE-level kernel page table + * pte_alloc_one_kernel - allocate memory for a PTE-level kernel page table   * @mm: the mm_struct of the current context   *   * Return: pointer to the allocated memory or %NULL on error @@ -35,40 +40,40 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)  #endif  /** - * pte_free_kernel - free PTE-level kernel page table page + * pte_free_kernel - free PTE-level kernel page table memory   * @mm: the mm_struct of the current context   * @pte: pointer to the memory containing the page table   */  static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)  { -	free_page((unsigned long)pte); +	pagetable_free(virt_to_ptdesc(pte));  }  /** - * __pte_alloc_one - allocate a page for PTE-level user page table + * __pte_alloc_one - allocate memory for a PTE-level user page table   * @mm: the mm_struct of the current context   * @gfp: GFP flags to use for the allocation   * - * Allocates a page and runs the pgtable_pte_page_ctor(). + * Allocate memory for a page table and ptdesc and runs pagetable_pte_ctor().   *   * This function is intended for architectures that need   * anything beyond simple page allocation or must have custom GFP flags.   * - * Return: `struct page` initialized as page table or %NULL on error + * Return: `struct page` referencing the ptdesc or %NULL on error   */  static inline pgtable_t __pte_alloc_one(struct mm_struct *mm, gfp_t gfp)  { -	struct page *pte; +	struct ptdesc *ptdesc; -	pte = alloc_page(gfp); -	if (!pte) +	ptdesc = pagetable_alloc(gfp, 0); +	if (!ptdesc)  		return NULL; -	if (!pgtable_pte_page_ctor(pte)) { -		__free_page(pte); +	if (!pagetable_pte_ctor(ptdesc)) { +		pagetable_free(ptdesc);  		return NULL;  	} -	return pte; +	return ptdesc_page(ptdesc);  }  #ifndef __HAVE_ARCH_PTE_ALLOC_ONE @@ -76,9 +81,9 @@ static inline pgtable_t __pte_alloc_one(struct mm_struct *mm, gfp_t gfp)   * pte_alloc_one - allocate a page for PTE-level user page table   * @mm: the mm_struct of the current context   * - * Allocates a page and runs the pgtable_pte_page_ctor(). + * Allocate memory for a page table and ptdesc and runs pagetable_pte_ctor().   * - * Return: `struct page` initialized as page table or %NULL on error + * Return: `struct page` referencing the ptdesc or %NULL on error   */  static inline pgtable_t pte_alloc_one(struct mm_struct *mm)  { @@ -92,14 +97,16 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm)   */  /** - * pte_free - free PTE-level user page table page + * pte_free - free PTE-level user page table memory   * @mm: the mm_struct of the current context - * @pte_page: the `struct page` representing the page table + * @pte_page: the `struct page` referencing the ptdesc   */  static inline void pte_free(struct mm_struct *mm, struct page *pte_page)  { -	pgtable_pte_page_dtor(pte_page); -	__free_page(pte_page); +	struct ptdesc *ptdesc = page_ptdesc(pte_page); + +	pagetable_pte_dtor(ptdesc); +	pagetable_free(ptdesc);  } @@ -107,10 +114,11 @@ static inline void pte_free(struct mm_struct *mm, struct page *pte_page)  #ifndef __HAVE_ARCH_PMD_ALLOC_ONE  /** - * pmd_alloc_one - allocate a page for PMD-level page table + * pmd_alloc_one - allocate memory for a PMD-level page table   * @mm: the mm_struct of the current context   * - * Allocates a page and runs the pgtable_pmd_page_ctor(). + * Allocate memory for a page table and ptdesc and runs pagetable_pmd_ctor(). + *   * Allocations use %GFP_PGTABLE_USER in user context and   * %GFP_PGTABLE_KERNEL in kernel context.   * @@ -118,28 +126,30 @@ static inline void pte_free(struct mm_struct *mm, struct page *pte_page)   */  static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)  { -	struct page *page; +	struct ptdesc *ptdesc;  	gfp_t gfp = GFP_PGTABLE_USER;  	if (mm == &init_mm)  		gfp = GFP_PGTABLE_KERNEL; -	page = alloc_page(gfp); -	if (!page) +	ptdesc = pagetable_alloc(gfp, 0); +	if (!ptdesc)  		return NULL; -	if (!pgtable_pmd_page_ctor(page)) { -		__free_page(page); +	if (!pagetable_pmd_ctor(ptdesc)) { +		pagetable_free(ptdesc);  		return NULL;  	} -	return (pmd_t *)page_address(page); +	return ptdesc_address(ptdesc);  }  #endif  #ifndef __HAVE_ARCH_PMD_FREE  static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)  { +	struct ptdesc *ptdesc = virt_to_ptdesc(pmd); +  	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); -	pgtable_pmd_page_dtor(virt_to_page(pmd)); -	free_page((unsigned long)pmd); +	pagetable_pmd_dtor(ptdesc); +	pagetable_free(ptdesc);  }  #endif @@ -150,19 +160,25 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)  static inline pud_t *__pud_alloc_one(struct mm_struct *mm, unsigned long addr)  {  	gfp_t gfp = GFP_PGTABLE_USER; +	struct ptdesc *ptdesc;  	if (mm == &init_mm)  		gfp = GFP_PGTABLE_KERNEL; -	return (pud_t *)get_zeroed_page(gfp); +	gfp &= ~__GFP_HIGHMEM; + +	ptdesc = pagetable_alloc(gfp, 0); +	if (!ptdesc) +		return NULL; +	return ptdesc_address(ptdesc);  }  #ifndef __HAVE_ARCH_PUD_ALLOC_ONE  /** - * pud_alloc_one - allocate a page for PUD-level page table + * pud_alloc_one - allocate memory for a PUD-level page table   * @mm: the mm_struct of the current context   * - * Allocates a page using %GFP_PGTABLE_USER for user context and - * %GFP_PGTABLE_KERNEL for kernel context. + * Allocate memory for a page table using %GFP_PGTABLE_USER for user context + * and %GFP_PGTABLE_KERNEL for kernel context.   *   * Return: pointer to the allocated memory or %NULL on error   */ @@ -175,7 +191,7 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)  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); +	pagetable_free(virt_to_ptdesc(pud));  }  #ifndef __HAVE_ARCH_PUD_FREE @@ -190,7 +206,7 @@ static inline void pud_free(struct mm_struct *mm, pud_t *pud)  #ifndef __HAVE_ARCH_PGD_FREE  static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)  { -	free_page((unsigned long)pgd); +	pagetable_free(virt_to_ptdesc(pgd));  }  #endif  | 
