1caab277bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
21d18c47cSCatalin Marinas /*
31d18c47cSCatalin Marinas * Based on arch/arm/include/asm/pgalloc.h
41d18c47cSCatalin Marinas *
51d18c47cSCatalin Marinas * Copyright (C) 2000-2001 Russell King
61d18c47cSCatalin Marinas * Copyright (C) 2012 ARM Ltd.
71d18c47cSCatalin Marinas */
81d18c47cSCatalin Marinas #ifndef __ASM_PGALLOC_H
91d18c47cSCatalin Marinas #define __ASM_PGALLOC_H
101d18c47cSCatalin Marinas
111d18c47cSCatalin Marinas #include <asm/pgtable-hwdef.h>
121d18c47cSCatalin Marinas #include <asm/processor.h>
131d18c47cSCatalin Marinas #include <asm/cacheflush.h>
141d18c47cSCatalin Marinas #include <asm/tlbflush.h>
151d18c47cSCatalin Marinas
16f9cb654cSMike Rapoport #define __HAVE_ARCH_PGD_FREE
170dd4f60aSArd Biesheuvel #define __HAVE_ARCH_PUD_FREE
181355c31eSMike Rapoport #include <asm-generic/pgalloc.h>
1950f11a8aSMike Rapoport
20fd2203ddSAndrey Ryabinin #define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t))
2115670ef1SMark Rutland
229f25e6adSKirill A. Shutemov #if CONFIG_PGTABLE_LEVELS > 2
231d18c47cSCatalin Marinas
__pud_populate(pud_t * pudp,phys_addr_t pmdp,pudval_t prot)2420a004e7SWill Deacon static inline void __pud_populate(pud_t *pudp, phys_addr_t pmdp, pudval_t prot)
251d18c47cSCatalin Marinas {
2620a004e7SWill Deacon set_pud(pudp, __pud(__phys_to_pud_val(pmdp) | prot));
271d18c47cSCatalin Marinas }
281d18c47cSCatalin Marinas
pud_populate(struct mm_struct * mm,pud_t * pudp,pmd_t * pmdp)2920a004e7SWill Deacon static inline void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmdp)
301e531cceSMark Rutland {
31*efe72541SYicong Yang pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_AF;
3259511cfdSArd Biesheuvel
3359511cfdSArd Biesheuvel pudval |= (mm == &init_mm) ? PUD_TABLE_UXN : PUD_TABLE_PXN;
3459511cfdSArd Biesheuvel __pud_populate(pudp, __pa(pmdp), pudval);
351e531cceSMark Rutland }
361e531cceSMark Rutland #else
__pud_populate(pud_t * pudp,phys_addr_t pmdp,pudval_t prot)3720a004e7SWill Deacon static inline void __pud_populate(pud_t *pudp, phys_addr_t pmdp, pudval_t prot)
381e531cceSMark Rutland {
391e531cceSMark Rutland BUILD_BUG();
401e531cceSMark Rutland }
419f25e6adSKirill A. Shutemov #endif /* CONFIG_PGTABLE_LEVELS > 2 */
421d18c47cSCatalin Marinas
439f25e6adSKirill A. Shutemov #if CONFIG_PGTABLE_LEVELS > 3
44c79b954bSJungseok Lee
__p4d_populate(p4d_t * p4dp,phys_addr_t pudp,p4dval_t prot)45e9f63768SMike Rapoport static inline void __p4d_populate(p4d_t *p4dp, phys_addr_t pudp, p4dval_t prot)
46c79b954bSJungseok Lee {
470dd4f60aSArd Biesheuvel if (pgtable_l4_enabled())
48e9f63768SMike Rapoport set_p4d(p4dp, __p4d(__phys_to_p4d_val(pudp) | prot));
49c79b954bSJungseok Lee }
50c79b954bSJungseok Lee
p4d_populate(struct mm_struct * mm,p4d_t * p4dp,pud_t * pudp)51e9f63768SMike Rapoport static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4dp, pud_t *pudp)
521e531cceSMark Rutland {
53*efe72541SYicong Yang p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_AF;
5459511cfdSArd Biesheuvel
5559511cfdSArd Biesheuvel p4dval |= (mm == &init_mm) ? P4D_TABLE_UXN : P4D_TABLE_PXN;
5659511cfdSArd Biesheuvel __p4d_populate(p4dp, __pa(pudp), p4dval);
571e531cceSMark Rutland }
580dd4f60aSArd Biesheuvel
pud_free(struct mm_struct * mm,pud_t * pud)590dd4f60aSArd Biesheuvel static inline void pud_free(struct mm_struct *mm, pud_t *pud)
600dd4f60aSArd Biesheuvel {
610dd4f60aSArd Biesheuvel if (!pgtable_l4_enabled())
620dd4f60aSArd Biesheuvel return;
633137db4cSArd Biesheuvel __pud_free(mm, pud);
640dd4f60aSArd Biesheuvel }
651e531cceSMark Rutland #else
__p4d_populate(p4d_t * p4dp,phys_addr_t pudp,p4dval_t prot)66e9f63768SMike Rapoport static inline void __p4d_populate(p4d_t *p4dp, phys_addr_t pudp, p4dval_t prot)
671e531cceSMark Rutland {
681e531cceSMark Rutland BUILD_BUG();
691e531cceSMark Rutland }
709f25e6adSKirill A. Shutemov #endif /* CONFIG_PGTABLE_LEVELS > 3 */
71c79b954bSJungseok Lee
72a6bbf5d4SArd Biesheuvel #if CONFIG_PGTABLE_LEVELS > 4
73a6bbf5d4SArd Biesheuvel
__pgd_populate(pgd_t * pgdp,phys_addr_t p4dp,pgdval_t prot)74a6bbf5d4SArd Biesheuvel static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t p4dp, pgdval_t prot)
75a6bbf5d4SArd Biesheuvel {
76a6bbf5d4SArd Biesheuvel if (pgtable_l5_enabled())
77a6bbf5d4SArd Biesheuvel set_pgd(pgdp, __pgd(__phys_to_pgd_val(p4dp) | prot));
78a6bbf5d4SArd Biesheuvel }
79a6bbf5d4SArd Biesheuvel
pgd_populate(struct mm_struct * mm,pgd_t * pgdp,p4d_t * p4dp)80a6bbf5d4SArd Biesheuvel static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgdp, p4d_t *p4dp)
81a6bbf5d4SArd Biesheuvel {
82*efe72541SYicong Yang pgdval_t pgdval = PGD_TYPE_TABLE | PGD_TABLE_AF;
83a6bbf5d4SArd Biesheuvel
84a6bbf5d4SArd Biesheuvel pgdval |= (mm == &init_mm) ? PGD_TABLE_UXN : PGD_TABLE_PXN;
85a6bbf5d4SArd Biesheuvel __pgd_populate(pgdp, __pa(p4dp), pgdval);
86a6bbf5d4SArd Biesheuvel }
87a6bbf5d4SArd Biesheuvel
88a6bbf5d4SArd Biesheuvel #else
__pgd_populate(pgd_t * pgdp,phys_addr_t p4dp,pgdval_t prot)89a6bbf5d4SArd Biesheuvel static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t p4dp, pgdval_t prot)
90a6bbf5d4SArd Biesheuvel {
91a6bbf5d4SArd Biesheuvel BUILD_BUG();
92a6bbf5d4SArd Biesheuvel }
93a6bbf5d4SArd Biesheuvel #endif /* CONFIG_PGTABLE_LEVELS > 4 */
94a6bbf5d4SArd Biesheuvel
951d18c47cSCatalin Marinas extern pgd_t *pgd_alloc(struct mm_struct *mm);
9620a004e7SWill Deacon extern void pgd_free(struct mm_struct *mm, pgd_t *pgdp);
971d18c47cSCatalin Marinas
__pmd_populate(pmd_t * pmdp,phys_addr_t ptep,pmdval_t prot)9820a004e7SWill Deacon static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t ptep,
991d18c47cSCatalin Marinas pmdval_t prot)
1001d18c47cSCatalin Marinas {
10120a004e7SWill Deacon set_pmd(pmdp, __pmd(__phys_to_pmd_val(ptep) | prot));
1021d18c47cSCatalin Marinas }
1031d18c47cSCatalin Marinas
1041d18c47cSCatalin Marinas /*
1051d18c47cSCatalin Marinas * Populate the pmdp entry with a pointer to the pte. This pmd is part
1061d18c47cSCatalin Marinas * of the mm address space.
1071d18c47cSCatalin Marinas */
1081d18c47cSCatalin Marinas static inline void
pmd_populate_kernel(struct mm_struct * mm,pmd_t * pmdp,pte_t * ptep)1091d18c47cSCatalin Marinas pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
1101d18c47cSCatalin Marinas {
111d3eb70eaSPingfan Liu VM_BUG_ON(mm && mm != &init_mm);
112*efe72541SYicong Yang __pmd_populate(pmdp, __pa(ptep),
113*efe72541SYicong Yang PMD_TYPE_TABLE | PMD_TABLE_AF | PMD_TABLE_UXN);
1141d18c47cSCatalin Marinas }
1151d18c47cSCatalin Marinas
1161d18c47cSCatalin Marinas static inline void
pmd_populate(struct mm_struct * mm,pmd_t * pmdp,pgtable_t ptep)1171d18c47cSCatalin Marinas pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
1181d18c47cSCatalin Marinas {
11959511cfdSArd Biesheuvel VM_BUG_ON(mm == &init_mm);
120*efe72541SYicong Yang __pmd_populate(pmdp, page_to_phys(ptep),
121*efe72541SYicong Yang PMD_TYPE_TABLE | PMD_TABLE_AF | PMD_TABLE_PXN);
1221d18c47cSCatalin Marinas }
1231d18c47cSCatalin Marinas
1241d18c47cSCatalin Marinas #endif
125