xref: /openbmc/linux/arch/riscv/mm/pgtable.c (revision 310f541a027b1d5dc68f44f176cde618e6ee9691)
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