LCOV - code coverage report
Current view: top level - include/asm-generic - pgalloc.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 9 22 40.9 %
Date: 2023-04-06 08:38:28 Functions: 1 3 33.3 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 */
       2             : #ifndef __ASM_GENERIC_PGALLOC_H
       3             : #define __ASM_GENERIC_PGALLOC_H
       4             : 
       5             : #ifdef CONFIG_MMU
       6             : 
       7             : #define GFP_PGTABLE_KERNEL      (GFP_KERNEL | __GFP_ZERO)
       8             : #define GFP_PGTABLE_USER        (GFP_PGTABLE_KERNEL | __GFP_ACCOUNT)
       9             : 
      10             : /**
      11             :  * __pte_alloc_one_kernel - allocate a page for PTE-level kernel page table
      12             :  * @mm: the mm_struct of the current context
      13             :  *
      14             :  * This function is intended for architectures that need
      15             :  * anything beyond simple page allocation.
      16             :  *
      17             :  * Return: pointer to the allocated memory or %NULL on error
      18             :  */
      19             : static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm)
      20             : {
      21          17 :         return (pte_t *)__get_free_page(GFP_PGTABLE_KERNEL);
      22             : }
      23             : 
      24             : #ifndef __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL
      25             : /**
      26             :  * pte_alloc_one_kernel - allocate a page for PTE-level kernel page table
      27             :  * @mm: the mm_struct of the current context
      28             :  *
      29             :  * Return: pointer to the allocated memory or %NULL on error
      30             :  */
      31             : static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
      32             : {
      33          17 :         return __pte_alloc_one_kernel(mm);
      34             : }
      35             : #endif
      36             : 
      37             : /**
      38             :  * pte_free_kernel - free PTE-level kernel page table page
      39             :  * @mm: the mm_struct of the current context
      40             :  * @pte: pointer to the memory containing the page table
      41             :  */
      42             : static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
      43             : {
      44           0 :         free_page((unsigned long)pte);
      45             : }
      46             : 
      47             : /**
      48             :  * __pte_alloc_one - allocate a page for PTE-level user page table
      49             :  * @mm: the mm_struct of the current context
      50             :  * @gfp: GFP flags to use for the allocation
      51             :  *
      52             :  * Allocates a page and runs the pgtable_pte_page_ctor().
      53             :  *
      54             :  * This function is intended for architectures that need
      55             :  * anything beyond simple page allocation or must have custom GFP flags.
      56             :  *
      57             :  * Return: `struct page` initialized as page table or %NULL on error
      58             :  */
      59           0 : static inline pgtable_t __pte_alloc_one(struct mm_struct *mm, gfp_t gfp)
      60             : {
      61             :         struct page *pte;
      62             : 
      63           0 :         pte = alloc_page(gfp);
      64           0 :         if (!pte)
      65             :                 return NULL;
      66             :         if (!pgtable_pte_page_ctor(pte)) {
      67             :                 __free_page(pte);
      68             :                 return NULL;
      69             :         }
      70             : 
      71             :         return pte;
      72             : }
      73             : 
      74             : #ifndef __HAVE_ARCH_PTE_ALLOC_ONE
      75             : /**
      76             :  * pte_alloc_one - allocate a page for PTE-level user page table
      77             :  * @mm: the mm_struct of the current context
      78             :  *
      79             :  * Allocates a page and runs the pgtable_pte_page_ctor().
      80             :  *
      81             :  * Return: `struct page` initialized as page table or %NULL on error
      82             :  */
      83             : static inline pgtable_t pte_alloc_one(struct mm_struct *mm)
      84             : {
      85           0 :         return __pte_alloc_one(mm, GFP_PGTABLE_USER);
      86             : }
      87             : #endif
      88             : 
      89             : /*
      90             :  * Should really implement gc for free page table pages. This could be
      91             :  * done with a reference count in struct page.
      92             :  */
      93             : 
      94             : /**
      95             :  * pte_free - free PTE-level user page table page
      96             :  * @mm: the mm_struct of the current context
      97             :  * @pte_page: the `struct page` representing the page table
      98             :  */
      99             : static inline void pte_free(struct mm_struct *mm, struct page *pte_page)
     100             : {
     101           0 :         pgtable_pte_page_dtor(pte_page);
     102           0 :         __free_page(pte_page);
     103             : }
     104             : 
     105             : 
     106             : #if CONFIG_PGTABLE_LEVELS > 2
     107             : 
     108             : #ifndef __HAVE_ARCH_PMD_ALLOC_ONE
     109             : /**
     110             :  * pmd_alloc_one - allocate a page for PMD-level page table
     111             :  * @mm: the mm_struct of the current context
     112             :  *
     113             :  * Allocates a page and runs the pgtable_pmd_page_ctor().
     114             :  * Allocations use %GFP_PGTABLE_USER in user context and
     115             :  * %GFP_PGTABLE_KERNEL in kernel context.
     116             :  *
     117             :  * Return: pointer to the allocated memory or %NULL on error
     118             :  */
     119           1 : static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
     120             : {
     121             :         struct page *page;
     122           1 :         gfp_t gfp = GFP_PGTABLE_USER;
     123             : 
     124           1 :         if (mm == &init_mm)
     125           1 :                 gfp = GFP_PGTABLE_KERNEL;
     126           1 :         page = alloc_pages(gfp, 0);
     127           1 :         if (!page)
     128             :                 return NULL;
     129             :         if (!pgtable_pmd_page_ctor(page)) {
     130             :                 __free_pages(page, 0);
     131             :                 return NULL;
     132             :         }
     133           1 :         return (pmd_t *)page_address(page);
     134             : }
     135             : #endif
     136             : 
     137             : #ifndef __HAVE_ARCH_PMD_FREE
     138           0 : static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
     139             : {
     140           0 :         BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
     141           0 :         pgtable_pmd_page_dtor(virt_to_page(pmd));
     142           0 :         free_page((unsigned long)pmd);
     143           0 : }
     144             : #endif
     145             : 
     146             : #endif /* CONFIG_PGTABLE_LEVELS > 2 */
     147             : 
     148             : #if CONFIG_PGTABLE_LEVELS > 3
     149             : 
     150             : static inline pud_t *__pud_alloc_one(struct mm_struct *mm, unsigned long addr)
     151             : {
     152             :         gfp_t gfp = GFP_PGTABLE_USER;
     153             : 
     154             :         if (mm == &init_mm)
     155             :                 gfp = GFP_PGTABLE_KERNEL;
     156             :         return (pud_t *)get_zeroed_page(gfp);
     157             : }
     158             : 
     159             : #ifndef __HAVE_ARCH_PUD_ALLOC_ONE
     160             : /**
     161             :  * pud_alloc_one - allocate a page for PUD-level page table
     162             :  * @mm: the mm_struct of the current context
     163             :  *
     164             :  * Allocates a page using %GFP_PGTABLE_USER for user context and
     165             :  * %GFP_PGTABLE_KERNEL for kernel context.
     166             :  *
     167             :  * Return: pointer to the allocated memory or %NULL on error
     168             :  */
     169             : static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
     170             : {
     171             :         return __pud_alloc_one(mm, addr);
     172             : }
     173             : #endif
     174             : 
     175             : static inline void __pud_free(struct mm_struct *mm, pud_t *pud)
     176             : {
     177             :         BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
     178             :         free_page((unsigned long)pud);
     179             : }
     180             : 
     181             : #ifndef __HAVE_ARCH_PUD_FREE
     182             : static inline void pud_free(struct mm_struct *mm, pud_t *pud)
     183             : {
     184             :         __pud_free(mm, pud);
     185             : }
     186             : #endif
     187             : 
     188             : #endif /* CONFIG_PGTABLE_LEVELS > 3 */
     189             : 
     190             : #ifndef __HAVE_ARCH_PGD_FREE
     191             : static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
     192             : {
     193           0 :         free_page((unsigned long)pgd);
     194             : }
     195             : #endif
     196             : 
     197             : #endif /* CONFIG_MMU */
     198             : 
     199             : #endif /* __ASM_GENERIC_PGALLOC_H */

Generated by: LCOV version 1.14