1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * PGD allocation/freeing 4 * 5 * Copyright (C) 2012 ARM Ltd. 6 * Author: Catalin Marinas <catalin.marinas@arm.com> 7 */ 8 9 #include <linux/mm.h> 10 #include <linux/gfp.h> 11 #include <linux/highmem.h> 12 #include <linux/slab.h> 13 14 #include <asm/pgalloc.h> 15 #include <asm/page.h> 16 #include <asm/tlbflush.h> 17 18 static struct kmem_cache *pgd_cache __ro_after_init; 19 20 pgd_t *pgd_alloc(struct mm_struct *mm) 21 { 22 gfp_t gfp = GFP_PGTABLE_USER; 23 24 if (PGD_SIZE == PAGE_SIZE) 25 return (pgd_t *)__get_free_page(gfp); 26 else 27 return kmem_cache_alloc(pgd_cache, gfp); 28 } 29 30 void pgd_free(struct mm_struct *mm, pgd_t *pgd) 31 { 32 if (PGD_SIZE == PAGE_SIZE) 33 free_page((unsigned long)pgd); 34 else 35 kmem_cache_free(pgd_cache, pgd); 36 } 37 38 void __init pgd_cache_init(void) 39 { 40 if (PGD_SIZE == PAGE_SIZE) 41 return; 42 43 #ifdef CONFIG_ARM64_PA_BITS_52 44 /* 45 * With 52-bit physical addresses, the architecture requires the 46 * top-level table to be aligned to at least 64 bytes. 47 */ 48 BUILD_BUG_ON(PGD_SIZE < 64); 49 #endif 50 51 /* 52 * Naturally aligned pgds required by the architecture. 53 */ 54 pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE, 55 SLAB_PANIC, NULL); 56 } 57