xref: /openbmc/linux/arch/riscv/include/asm/pgalloc.h (revision 07037db5d479f90377c998259a4f9a469c404edf)
1*07037db5SPalmer Dabbelt /*
2*07037db5SPalmer Dabbelt  * Copyright (C) 2009 Chen Liqin <liqin.chen@sunplusct.com>
3*07037db5SPalmer Dabbelt  * Copyright (C) 2012 Regents of the University of California
4*07037db5SPalmer Dabbelt  *
5*07037db5SPalmer Dabbelt  *   This program is free software; you can redistribute it and/or
6*07037db5SPalmer Dabbelt  *   modify it under the terms of the GNU General Public License
7*07037db5SPalmer Dabbelt  *   as published by the Free Software Foundation, version 2.
8*07037db5SPalmer Dabbelt  *
9*07037db5SPalmer Dabbelt  *   This program is distributed in the hope that it will be useful,
10*07037db5SPalmer Dabbelt  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11*07037db5SPalmer Dabbelt  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*07037db5SPalmer Dabbelt  *   GNU General Public License for more details.
13*07037db5SPalmer Dabbelt  */
14*07037db5SPalmer Dabbelt 
15*07037db5SPalmer Dabbelt #ifndef _ASM_RISCV_PGALLOC_H
16*07037db5SPalmer Dabbelt #define _ASM_RISCV_PGALLOC_H
17*07037db5SPalmer Dabbelt 
18*07037db5SPalmer Dabbelt #include <linux/mm.h>
19*07037db5SPalmer Dabbelt #include <asm/tlb.h>
20*07037db5SPalmer Dabbelt 
21*07037db5SPalmer Dabbelt static inline void pmd_populate_kernel(struct mm_struct *mm,
22*07037db5SPalmer Dabbelt 	pmd_t *pmd, pte_t *pte)
23*07037db5SPalmer Dabbelt {
24*07037db5SPalmer Dabbelt 	unsigned long pfn = virt_to_pfn(pte);
25*07037db5SPalmer Dabbelt 
26*07037db5SPalmer Dabbelt 	set_pmd(pmd, __pmd((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE));
27*07037db5SPalmer Dabbelt }
28*07037db5SPalmer Dabbelt 
29*07037db5SPalmer Dabbelt static inline void pmd_populate(struct mm_struct *mm,
30*07037db5SPalmer Dabbelt 	pmd_t *pmd, pgtable_t pte)
31*07037db5SPalmer Dabbelt {
32*07037db5SPalmer Dabbelt 	unsigned long pfn = virt_to_pfn(page_address(pte));
33*07037db5SPalmer Dabbelt 
34*07037db5SPalmer Dabbelt 	set_pmd(pmd, __pmd((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE));
35*07037db5SPalmer Dabbelt }
36*07037db5SPalmer Dabbelt 
37*07037db5SPalmer Dabbelt #ifndef __PAGETABLE_PMD_FOLDED
38*07037db5SPalmer Dabbelt static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
39*07037db5SPalmer Dabbelt {
40*07037db5SPalmer Dabbelt 	unsigned long pfn = virt_to_pfn(pmd);
41*07037db5SPalmer Dabbelt 
42*07037db5SPalmer Dabbelt 	set_pud(pud, __pud((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE));
43*07037db5SPalmer Dabbelt }
44*07037db5SPalmer Dabbelt #endif /* __PAGETABLE_PMD_FOLDED */
45*07037db5SPalmer Dabbelt 
46*07037db5SPalmer Dabbelt #define pmd_pgtable(pmd)	pmd_page(pmd)
47*07037db5SPalmer Dabbelt 
48*07037db5SPalmer Dabbelt static inline pgd_t *pgd_alloc(struct mm_struct *mm)
49*07037db5SPalmer Dabbelt {
50*07037db5SPalmer Dabbelt 	pgd_t *pgd;
51*07037db5SPalmer Dabbelt 
52*07037db5SPalmer Dabbelt 	pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
53*07037db5SPalmer Dabbelt 	if (likely(pgd != NULL)) {
54*07037db5SPalmer Dabbelt 		memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
55*07037db5SPalmer Dabbelt 		/* Copy kernel mappings */
56*07037db5SPalmer Dabbelt 		memcpy(pgd + USER_PTRS_PER_PGD,
57*07037db5SPalmer Dabbelt 			init_mm.pgd + USER_PTRS_PER_PGD,
58*07037db5SPalmer Dabbelt 			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
59*07037db5SPalmer Dabbelt 	}
60*07037db5SPalmer Dabbelt 	return pgd;
61*07037db5SPalmer Dabbelt }
62*07037db5SPalmer Dabbelt 
63*07037db5SPalmer Dabbelt static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
64*07037db5SPalmer Dabbelt {
65*07037db5SPalmer Dabbelt 	free_page((unsigned long)pgd);
66*07037db5SPalmer Dabbelt }
67*07037db5SPalmer Dabbelt 
68*07037db5SPalmer Dabbelt #ifndef __PAGETABLE_PMD_FOLDED
69*07037db5SPalmer Dabbelt 
70*07037db5SPalmer Dabbelt static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
71*07037db5SPalmer Dabbelt {
72*07037db5SPalmer Dabbelt 	return (pmd_t *)__get_free_page(
73*07037db5SPalmer Dabbelt 		GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_ZERO);
74*07037db5SPalmer Dabbelt }
75*07037db5SPalmer Dabbelt 
76*07037db5SPalmer Dabbelt static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
77*07037db5SPalmer Dabbelt {
78*07037db5SPalmer Dabbelt 	free_page((unsigned long)pmd);
79*07037db5SPalmer Dabbelt }
80*07037db5SPalmer Dabbelt 
81*07037db5SPalmer Dabbelt #define __pmd_free_tlb(tlb, pmd, addr)  pmd_free((tlb)->mm, pmd)
82*07037db5SPalmer Dabbelt 
83*07037db5SPalmer Dabbelt #endif /* __PAGETABLE_PMD_FOLDED */
84*07037db5SPalmer Dabbelt 
85*07037db5SPalmer Dabbelt static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
86*07037db5SPalmer Dabbelt 	unsigned long address)
87*07037db5SPalmer Dabbelt {
88*07037db5SPalmer Dabbelt 	return (pte_t *)__get_free_page(
89*07037db5SPalmer Dabbelt 		GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_ZERO);
90*07037db5SPalmer Dabbelt }
91*07037db5SPalmer Dabbelt 
92*07037db5SPalmer Dabbelt static inline struct page *pte_alloc_one(struct mm_struct *mm,
93*07037db5SPalmer Dabbelt 	unsigned long address)
94*07037db5SPalmer Dabbelt {
95*07037db5SPalmer Dabbelt 	struct page *pte;
96*07037db5SPalmer Dabbelt 
97*07037db5SPalmer Dabbelt 	pte = alloc_page(GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_ZERO);
98*07037db5SPalmer Dabbelt 	if (likely(pte != NULL))
99*07037db5SPalmer Dabbelt 		pgtable_page_ctor(pte);
100*07037db5SPalmer Dabbelt 	return pte;
101*07037db5SPalmer Dabbelt }
102*07037db5SPalmer Dabbelt 
103*07037db5SPalmer Dabbelt static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
104*07037db5SPalmer Dabbelt {
105*07037db5SPalmer Dabbelt 	free_page((unsigned long)pte);
106*07037db5SPalmer Dabbelt }
107*07037db5SPalmer Dabbelt 
108*07037db5SPalmer Dabbelt static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
109*07037db5SPalmer Dabbelt {
110*07037db5SPalmer Dabbelt 	pgtable_page_dtor(pte);
111*07037db5SPalmer Dabbelt 	__free_page(pte);
112*07037db5SPalmer Dabbelt }
113*07037db5SPalmer Dabbelt 
114*07037db5SPalmer Dabbelt #define __pte_free_tlb(tlb, pte, buf)   \
115*07037db5SPalmer Dabbelt do {                                    \
116*07037db5SPalmer Dabbelt 	pgtable_page_dtor(pte);         \
117*07037db5SPalmer Dabbelt 	tlb_remove_page((tlb), pte);    \
118*07037db5SPalmer Dabbelt } while (0)
119*07037db5SPalmer Dabbelt 
120*07037db5SPalmer Dabbelt static inline void check_pgt_cache(void)
121*07037db5SPalmer Dabbelt {
122*07037db5SPalmer Dabbelt }
123*07037db5SPalmer Dabbelt 
124*07037db5SPalmer Dabbelt #endif /* _ASM_RISCV_PGALLOC_H */
125