1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef M68K_MCF_PGALLOC_H
3 #define M68K_MCF_PGALLOC_H
4
5 #include <asm/tlb.h>
6 #include <asm/tlbflush.h>
7
pte_free_kernel(struct mm_struct * mm,pte_t * pte)8 static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
9 {
10 pagetable_dtor_free(virt_to_ptdesc(pte));
11 }
12
13 extern const char bad_pmd_string[];
14
pte_alloc_one_kernel(struct mm_struct * mm)15 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
16 {
17 struct ptdesc *ptdesc = pagetable_alloc((GFP_DMA | __GFP_ZERO) &
18 ~__GFP_HIGHMEM, 0);
19
20 if (!ptdesc)
21 return NULL;
22 if (!pagetable_pte_ctor(mm, ptdesc)) {
23 pagetable_free(ptdesc);
24 return NULL;
25 }
26
27 return ptdesc_address(ptdesc);
28 }
29
pmd_alloc_kernel(pgd_t * pgd,unsigned long address)30 extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
31 {
32 return (pmd_t *) pgd;
33 }
34
35 #define pmd_populate(mm, pmd, pte) (pmd_val(*pmd) = (unsigned long)(pte))
36
37 #define pmd_populate_kernel pmd_populate
38
__pte_free_tlb(struct mmu_gather * tlb,pgtable_t pgtable,unsigned long address)39 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pgtable,
40 unsigned long address)
41 {
42 struct ptdesc *ptdesc = virt_to_ptdesc(pgtable);
43
44 pagetable_dtor(ptdesc);
45 pagetable_free(ptdesc);
46 }
47
pte_alloc_one(struct mm_struct * mm)48 static inline pgtable_t pte_alloc_one(struct mm_struct *mm)
49 {
50 struct ptdesc *ptdesc = pagetable_alloc(GFP_DMA | __GFP_ZERO, 0);
51 pte_t *pte;
52
53 if (!ptdesc)
54 return NULL;
55 if (!pagetable_pte_ctor(mm, ptdesc)) {
56 pagetable_free(ptdesc);
57 return NULL;
58 }
59
60 pte = ptdesc_address(ptdesc);
61 return pte;
62 }
63
pte_free(struct mm_struct * mm,pgtable_t pgtable)64 static inline void pte_free(struct mm_struct *mm, pgtable_t pgtable)
65 {
66 struct ptdesc *ptdesc = virt_to_ptdesc(pgtable);
67
68 pagetable_dtor(ptdesc);
69 pagetable_free(ptdesc);
70 }
71
72 /*
73 * In our implementation, each pgd entry contains 1 pmd that is never allocated
74 * or freed. pgd_present is always 1, so this should never be called. -NL
75 */
76 #define pmd_free(mm, pmd) BUG()
77
pgd_free(struct mm_struct * mm,pgd_t * pgd)78 static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
79 {
80 pagetable_dtor_free(virt_to_ptdesc(pgd));
81 }
82
pgd_alloc(struct mm_struct * mm)83 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
84 {
85 pgd_t *new_pgd;
86 struct ptdesc *ptdesc = pagetable_alloc((GFP_DMA | __GFP_NOWARN) &
87 ~__GFP_HIGHMEM, 0);
88
89 if (!ptdesc)
90 return NULL;
91 pagetable_pgd_ctor(ptdesc);
92 new_pgd = ptdesc_address(ptdesc);
93
94 memcpy(new_pgd, swapper_pg_dir, PTRS_PER_PGD * sizeof(pgd_t));
95 memset(new_pgd, 0, PAGE_OFFSET >> PGDIR_SHIFT);
96 return new_pgd;
97 }
98
99 #endif /* M68K_MCF_PGALLOC_H */
100