1*310f541aSLiu Shixin // SPDX-License-Identifier: GPL-2.0 2*310f541aSLiu Shixin 3*310f541aSLiu Shixin #include <asm/pgalloc.h> 4*310f541aSLiu Shixin #include <linux/gfp.h> 5*310f541aSLiu Shixin #include <linux/kernel.h> 6*310f541aSLiu Shixin #include <linux/pgtable.h> 7*310f541aSLiu Shixin 8*310f541aSLiu Shixin #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP 9*310f541aSLiu Shixin int p4d_set_huge(p4d_t *p4d, phys_addr_t addr, pgprot_t prot) 10*310f541aSLiu Shixin { 11*310f541aSLiu Shixin return 0; 12*310f541aSLiu Shixin } 13*310f541aSLiu Shixin 14*310f541aSLiu Shixin void p4d_clear_huge(p4d_t *p4d) 15*310f541aSLiu Shixin { 16*310f541aSLiu Shixin } 17*310f541aSLiu Shixin 18*310f541aSLiu Shixin int pud_set_huge(pud_t *pud, phys_addr_t phys, pgprot_t prot) 19*310f541aSLiu Shixin { 20*310f541aSLiu Shixin pud_t new_pud = pfn_pud(__phys_to_pfn(phys), prot); 21*310f541aSLiu Shixin 22*310f541aSLiu Shixin set_pud(pud, new_pud); 23*310f541aSLiu Shixin return 1; 24*310f541aSLiu Shixin } 25*310f541aSLiu Shixin 26*310f541aSLiu Shixin int pud_clear_huge(pud_t *pud) 27*310f541aSLiu Shixin { 28*310f541aSLiu Shixin if (!pud_leaf(READ_ONCE(*pud))) 29*310f541aSLiu Shixin return 0; 30*310f541aSLiu Shixin pud_clear(pud); 31*310f541aSLiu Shixin return 1; 32*310f541aSLiu Shixin } 33*310f541aSLiu Shixin 34*310f541aSLiu Shixin int pud_free_pmd_page(pud_t *pud, unsigned long addr) 35*310f541aSLiu Shixin { 36*310f541aSLiu Shixin pmd_t *pmd = pud_pgtable(*pud); 37*310f541aSLiu Shixin int i; 38*310f541aSLiu Shixin 39*310f541aSLiu Shixin pud_clear(pud); 40*310f541aSLiu Shixin 41*310f541aSLiu Shixin flush_tlb_kernel_range(addr, addr + PUD_SIZE); 42*310f541aSLiu Shixin 43*310f541aSLiu Shixin for (i = 0; i < PTRS_PER_PMD; i++) { 44*310f541aSLiu Shixin if (!pmd_none(pmd[i])) { 45*310f541aSLiu Shixin pte_t *pte = (pte_t *)pmd_page_vaddr(pmd[i]); 46*310f541aSLiu Shixin 47*310f541aSLiu Shixin pte_free_kernel(NULL, pte); 48*310f541aSLiu Shixin } 49*310f541aSLiu Shixin } 50*310f541aSLiu Shixin 51*310f541aSLiu Shixin pmd_free(NULL, pmd); 52*310f541aSLiu Shixin 53*310f541aSLiu Shixin return 1; 54*310f541aSLiu Shixin } 55*310f541aSLiu Shixin 56*310f541aSLiu Shixin int pmd_set_huge(pmd_t *pmd, phys_addr_t phys, pgprot_t prot) 57*310f541aSLiu Shixin { 58*310f541aSLiu Shixin pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), prot); 59*310f541aSLiu Shixin 60*310f541aSLiu Shixin set_pmd(pmd, new_pmd); 61*310f541aSLiu Shixin return 1; 62*310f541aSLiu Shixin } 63*310f541aSLiu Shixin 64*310f541aSLiu Shixin int pmd_clear_huge(pmd_t *pmd) 65*310f541aSLiu Shixin { 66*310f541aSLiu Shixin if (!pmd_leaf(READ_ONCE(*pmd))) 67*310f541aSLiu Shixin return 0; 68*310f541aSLiu Shixin pmd_clear(pmd); 69*310f541aSLiu Shixin return 1; 70*310f541aSLiu Shixin } 71*310f541aSLiu Shixin 72*310f541aSLiu Shixin int pmd_free_pte_page(pmd_t *pmd, unsigned long addr) 73*310f541aSLiu Shixin { 74*310f541aSLiu Shixin pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd); 75*310f541aSLiu Shixin 76*310f541aSLiu Shixin pmd_clear(pmd); 77*310f541aSLiu Shixin 78*310f541aSLiu Shixin flush_tlb_kernel_range(addr, addr + PMD_SIZE); 79*310f541aSLiu Shixin pte_free_kernel(NULL, pte); 80*310f541aSLiu Shixin return 1; 81*310f541aSLiu Shixin } 82*310f541aSLiu Shixin 83*310f541aSLiu Shixin #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */ 84