linux/arch/arm64/include/asm/pgalloc.h
<<
>>
Prefs
   1/*
   2 * Based on arch/arm/include/asm/pgalloc.h
   3 *
   4 * Copyright (C) 2000-2001 Russell King
   5 * Copyright (C) 2012 ARM Ltd.
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19#ifndef __ASM_PGALLOC_H
  20#define __ASM_PGALLOC_H
  21
  22#include <asm/pgtable-hwdef.h>
  23#include <asm/processor.h>
  24#include <asm/cacheflush.h>
  25#include <asm/tlbflush.h>
  26
  27#define check_pgt_cache()               do { } while (0)
  28
  29#define PGALLOC_GFP     (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO)
  30#define PGD_SIZE        (PTRS_PER_PGD * sizeof(pgd_t))
  31
  32#if CONFIG_PGTABLE_LEVELS > 2
  33
  34static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
  35{
  36        return (pmd_t *)__get_free_page(PGALLOC_GFP);
  37}
  38
  39static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
  40{
  41        BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
  42        free_page((unsigned long)pmd);
  43}
  44
  45static inline void __pud_populate(pud_t *pud, phys_addr_t pmd, pudval_t prot)
  46{
  47        set_pud(pud, __pud(pmd | prot));
  48}
  49
  50static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
  51{
  52        __pud_populate(pud, __pa(pmd), PMD_TYPE_TABLE);
  53}
  54#else
  55static inline void __pud_populate(pud_t *pud, phys_addr_t pmd, pudval_t prot)
  56{
  57        BUILD_BUG();
  58}
  59#endif  /* CONFIG_PGTABLE_LEVELS > 2 */
  60
  61#if CONFIG_PGTABLE_LEVELS > 3
  62
  63static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
  64{
  65        return (pud_t *)__get_free_page(PGALLOC_GFP);
  66}
  67
  68static inline void pud_free(struct mm_struct *mm, pud_t *pud)
  69{
  70        BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
  71        free_page((unsigned long)pud);
  72}
  73
  74static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t pud, pgdval_t prot)
  75{
  76        set_pgd(pgdp, __pgd(pud | prot));
  77}
  78
  79static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
  80{
  81        __pgd_populate(pgd, __pa(pud), PUD_TYPE_TABLE);
  82}
  83#else
  84static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t pud, pgdval_t prot)
  85{
  86        BUILD_BUG();
  87}
  88#endif  /* CONFIG_PGTABLE_LEVELS > 3 */
  89
  90extern pgd_t *pgd_alloc(struct mm_struct *mm);
  91extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
  92
  93static inline pte_t *
  94pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
  95{
  96        return (pte_t *)__get_free_page(PGALLOC_GFP);
  97}
  98
  99static inline pgtable_t
 100pte_alloc_one(struct mm_struct *mm, unsigned long addr)
 101{
 102        struct page *pte;
 103
 104        pte = alloc_pages(PGALLOC_GFP, 0);
 105        if (!pte)
 106                return NULL;
 107        if (!pgtable_page_ctor(pte)) {
 108                __free_page(pte);
 109                return NULL;
 110        }
 111        return pte;
 112}
 113
 114/*
 115 * Free a PTE table.
 116 */
 117static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
 118{
 119        if (pte)
 120                free_page((unsigned long)pte);
 121}
 122
 123static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
 124{
 125        pgtable_page_dtor(pte);
 126        __free_page(pte);
 127}
 128
 129static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte,
 130                                  pmdval_t prot)
 131{
 132        set_pmd(pmdp, __pmd(pte | prot));
 133}
 134
 135/*
 136 * Populate the pmdp entry with a pointer to the pte.  This pmd is part
 137 * of the mm address space.
 138 */
 139static inline void
 140pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
 141{
 142        /*
 143         * The pmd must be loaded with the physical address of the PTE table
 144         */
 145        __pmd_populate(pmdp, __pa(ptep), PMD_TYPE_TABLE);
 146}
 147
 148static inline void
 149pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
 150{
 151        __pmd_populate(pmdp, page_to_phys(ptep), PMD_TYPE_TABLE);
 152}
 153#define pmd_pgtable(pmd) pmd_page(pmd)
 154
 155#endif
 156