// SPDX-License-Identifier: GPL-2.0-only /* * PGD allocation/freeing * * Copyright (C) 2012 ARM Ltd. * Author: Catalin Marinas <catalin.marinas@arm.com> */ #include <linux/mm.h> #include <linux/gfp.h> #include <linux/highmem.h> #include <linux/slab.h> #include <asm/pgalloc.h> #include <asm/page.h> #include <asm/tlbflush.h> static struct kmem_cache *pgd_cache __ro_after_init; pgd_t *pgd_alloc(struct mm_struct *mm) { gfp_t gfp = GFP_PGTABLE_USER; if (PGD_SIZE == PAGE_SIZE) return (pgd_t *)__get_free_page(gfp); else return kmem_cache_alloc(pgd_cache, gfp); } void pgd_free(struct mm_struct *mm, pgd_t *pgd) { if (PGD_SIZE == PAGE_SIZE) free_page((unsigned long)pgd); else kmem_cache_free(pgd_cache, pgd); } void __init pgtable_cache_init(void) { if (PGD_SIZE == PAGE_SIZE) return; #ifdef CONFIG_ARM64_PA_BITS_52 /* * With 52-bit physical addresses, the architecture requires the * top-level table to be aligned to at least 64 bytes. */ BUILD_BUG_ON(PGD_SIZE < 64); #endif /* * Naturally aligned pgds required by the architecture. */ pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE, SLAB_PANIC, NULL); }