162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci#ifndef _ASM_POWERPC_BOOK3S_64_PGALLOC_H 362306a36Sopenharmony_ci#define _ASM_POWERPC_BOOK3S_64_PGALLOC_H 462306a36Sopenharmony_ci/* 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/slab.h> 862306a36Sopenharmony_ci#include <linux/cpumask.h> 962306a36Sopenharmony_ci#include <linux/kmemleak.h> 1062306a36Sopenharmony_ci#include <linux/percpu.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cistruct vmemmap_backing { 1362306a36Sopenharmony_ci struct vmemmap_backing *list; 1462306a36Sopenharmony_ci unsigned long phys; 1562306a36Sopenharmony_ci unsigned long virt_addr; 1662306a36Sopenharmony_ci}; 1762306a36Sopenharmony_ciextern struct vmemmap_backing *vmemmap_list; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ciextern pmd_t *pmd_fragment_alloc(struct mm_struct *, unsigned long); 2062306a36Sopenharmony_ciextern void pmd_fragment_free(unsigned long *); 2162306a36Sopenharmony_ciextern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift); 2262306a36Sopenharmony_ciextern void __tlb_remove_table(void *_table); 2362306a36Sopenharmony_civoid pte_frag_destroy(void *pte_frag); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic inline pgd_t *radix__pgd_alloc(struct mm_struct *mm) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci#ifdef CONFIG_PPC_64K_PAGES 2862306a36Sopenharmony_ci return (pgd_t *)__get_free_page(pgtable_gfp_flags(mm, PGALLOC_GFP)); 2962306a36Sopenharmony_ci#else 3062306a36Sopenharmony_ci struct page *page; 3162306a36Sopenharmony_ci page = alloc_pages(pgtable_gfp_flags(mm, PGALLOC_GFP | __GFP_RETRY_MAYFAIL), 3262306a36Sopenharmony_ci 4); 3362306a36Sopenharmony_ci if (!page) 3462306a36Sopenharmony_ci return NULL; 3562306a36Sopenharmony_ci return (pgd_t *) page_address(page); 3662306a36Sopenharmony_ci#endif 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic inline void radix__pgd_free(struct mm_struct *mm, pgd_t *pgd) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci#ifdef CONFIG_PPC_64K_PAGES 4262306a36Sopenharmony_ci free_page((unsigned long)pgd); 4362306a36Sopenharmony_ci#else 4462306a36Sopenharmony_ci free_pages((unsigned long)pgd, 4); 4562306a36Sopenharmony_ci#endif 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic inline pgd_t *pgd_alloc(struct mm_struct *mm) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci pgd_t *pgd; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci if (radix_enabled()) 5362306a36Sopenharmony_ci return radix__pgd_alloc(mm); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci pgd = kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), 5662306a36Sopenharmony_ci pgtable_gfp_flags(mm, GFP_KERNEL)); 5762306a36Sopenharmony_ci if (unlikely(!pgd)) 5862306a36Sopenharmony_ci return pgd; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci /* 6162306a36Sopenharmony_ci * Don't scan the PGD for pointers, it contains references to PUDs but 6262306a36Sopenharmony_ci * those references are not full pointers and so can't be recognised by 6362306a36Sopenharmony_ci * kmemleak. 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ci kmemleak_no_scan(pgd); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* 6862306a36Sopenharmony_ci * With hugetlb, we don't clear the second half of the page table. 6962306a36Sopenharmony_ci * If we share the same slab cache with the pmd or pud level table, 7062306a36Sopenharmony_ci * we need to make sure we zero out the full table on alloc. 7162306a36Sopenharmony_ci * With 4K we don't store slot in the second half. Hence we don't 7262306a36Sopenharmony_ci * need to do this for 4k. 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_ci#if defined(CONFIG_HUGETLB_PAGE) && defined(CONFIG_PPC_64K_PAGES) && \ 7562306a36Sopenharmony_ci (H_PGD_INDEX_SIZE == H_PUD_CACHE_INDEX) 7662306a36Sopenharmony_ci memset(pgd, 0, PGD_TABLE_SIZE); 7762306a36Sopenharmony_ci#endif 7862306a36Sopenharmony_ci return pgd; 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci if (radix_enabled()) 8462306a36Sopenharmony_ci return radix__pgd_free(mm, pgd); 8562306a36Sopenharmony_ci kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd); 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic inline void p4d_populate(struct mm_struct *mm, p4d_t *pgd, pud_t *pud) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci *pgd = __p4d(__pgtable_ptr_val(pud) | PGD_VAL_BITS); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci pud_t *pud; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci pud = kmem_cache_alloc(PGT_CACHE(PUD_CACHE_INDEX), 9862306a36Sopenharmony_ci pgtable_gfp_flags(mm, GFP_KERNEL)); 9962306a36Sopenharmony_ci /* 10062306a36Sopenharmony_ci * Tell kmemleak to ignore the PUD, that means don't scan it for 10162306a36Sopenharmony_ci * pointers and don't consider it a leak. PUDs are typically only 10262306a36Sopenharmony_ci * referred to by their PGD, but kmemleak is not able to recognise those 10362306a36Sopenharmony_ci * as pointers, leading to false leak reports. 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_ci kmemleak_ignore(pud); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci return pud; 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic inline void __pud_free(pud_t *pud) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci struct page *page = virt_to_page(pud); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci /* 11562306a36Sopenharmony_ci * Early pud pages allocated via memblock allocator 11662306a36Sopenharmony_ci * can't be directly freed to slab. KFENCE pages have 11762306a36Sopenharmony_ci * both reserved and slab flags set so need to be freed 11862306a36Sopenharmony_ci * kmem_cache_free. 11962306a36Sopenharmony_ci */ 12062306a36Sopenharmony_ci if (PageReserved(page) && !PageSlab(page)) 12162306a36Sopenharmony_ci free_reserved_page(page); 12262306a36Sopenharmony_ci else 12362306a36Sopenharmony_ci kmem_cache_free(PGT_CACHE(PUD_CACHE_INDEX), pud); 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic inline void pud_free(struct mm_struct *mm, pud_t *pud) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci return __pud_free(pud); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci *pud = __pud(__pgtable_ptr_val(pmd) | PUD_VAL_BITS); 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, 13762306a36Sopenharmony_ci unsigned long address) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci pgtable_free_tlb(tlb, pud, PUD_INDEX); 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci return pmd_fragment_alloc(mm, addr); 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci pmd_fragment_free((unsigned long *)pmd); 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, 15362306a36Sopenharmony_ci unsigned long address) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci return pgtable_free_tlb(tlb, pmd, PMD_INDEX); 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cistatic inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, 15962306a36Sopenharmony_ci pte_t *pte) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci *pmd = __pmd(__pgtable_ptr_val(pte) | PMD_VAL_BITS); 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, 16562306a36Sopenharmony_ci pgtable_t pte_page) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci *pmd = __pmd(__pgtable_ptr_val(pte_page) | PMD_VAL_BITS); 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table, 17162306a36Sopenharmony_ci unsigned long address) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci pgtable_free_tlb(tlb, table, PTE_INDEX); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ciextern atomic_long_t direct_pages_count[MMU_PAGE_COUNT]; 17762306a36Sopenharmony_cistatic inline void update_page_count(int psize, long count) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_PROC_FS)) 18062306a36Sopenharmony_ci atomic_long_add(count, &direct_pages_count[psize]); 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci#endif /* _ASM_POWERPC_BOOK3S_64_PGALLOC_H */ 184