1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun #include <linux/mm.h>
3*4882a593Smuzhiyun #include <linux/slab.h>
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun static struct kmem_cache *pgd_cachep;
6*4882a593Smuzhiyun #if PAGETABLE_LEVELS > 2
7*4882a593Smuzhiyun static struct kmem_cache *pmd_cachep;
8*4882a593Smuzhiyun #endif
9*4882a593Smuzhiyun
pgd_ctor(void * x)10*4882a593Smuzhiyun void pgd_ctor(void *x)
11*4882a593Smuzhiyun {
12*4882a593Smuzhiyun pgd_t *pgd = x;
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
15*4882a593Smuzhiyun memcpy(pgd + USER_PTRS_PER_PGD,
16*4882a593Smuzhiyun swapper_pg_dir + USER_PTRS_PER_PGD,
17*4882a593Smuzhiyun (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
18*4882a593Smuzhiyun }
19*4882a593Smuzhiyun
pgtable_cache_init(void)20*4882a593Smuzhiyun void pgtable_cache_init(void)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun pgd_cachep = kmem_cache_create("pgd_cache",
23*4882a593Smuzhiyun PTRS_PER_PGD * (1<<PTE_MAGNITUDE),
24*4882a593Smuzhiyun PAGE_SIZE, SLAB_PANIC, pgd_ctor);
25*4882a593Smuzhiyun #if PAGETABLE_LEVELS > 2
26*4882a593Smuzhiyun pmd_cachep = kmem_cache_create("pmd_cache",
27*4882a593Smuzhiyun PTRS_PER_PMD * (1<<PTE_MAGNITUDE),
28*4882a593Smuzhiyun PAGE_SIZE, SLAB_PANIC, NULL);
29*4882a593Smuzhiyun #endif
30*4882a593Smuzhiyun }
31*4882a593Smuzhiyun
pgd_alloc(struct mm_struct * mm)32*4882a593Smuzhiyun pgd_t *pgd_alloc(struct mm_struct *mm)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun return kmem_cache_alloc(pgd_cachep, GFP_KERNEL);
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun
pgd_free(struct mm_struct * mm,pgd_t * pgd)37*4882a593Smuzhiyun void pgd_free(struct mm_struct *mm, pgd_t *pgd)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun kmem_cache_free(pgd_cachep, pgd);
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #if PAGETABLE_LEVELS > 2
pud_populate(struct mm_struct * mm,pud_t * pud,pmd_t * pmd)43*4882a593Smuzhiyun void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun set_pud(pud, __pud((unsigned long)pmd));
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun
pmd_alloc_one(struct mm_struct * mm,unsigned long address)48*4882a593Smuzhiyun pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun return kmem_cache_alloc(pmd_cachep, GFP_KERNEL | __GFP_ZERO);
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun
pmd_free(struct mm_struct * mm,pmd_t * pmd)53*4882a593Smuzhiyun void pmd_free(struct mm_struct *mm, pmd_t *pmd)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun kmem_cache_free(pmd_cachep, pmd);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun #endif /* PAGETABLE_LEVELS > 2 */
58