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 if (PGD_SIZE == PAGE_SIZE) 23 return (pgd_t *)__get_free_page(PGALLOC_GFP); 24 else 25 return kmem_cache_alloc(pgd_cache, PGALLOC_GFP); 26 } 27 28 void pgd_free(struct mm_struct *mm, pgd_t *pgd) 29 { 30 if (PGD_SIZE == PAGE_SIZE) 31 free_page((unsigned long)pgd); 32 else 33 kmem_cache_free(pgd_cache, pgd); 34 } 35 36 void __init pgd_cache_init(void) 37 { 38 if (PGD_SIZE == PAGE_SIZE) 39 return; 40 41 #ifdef CONFIG_ARM64_PA_BITS_52 42 /* 43 * With 52-bit physical addresses, the architecture requires the 44 * top-level table to be aligned to at least 64 bytes. 45 */ 46 BUILD_BUG_ON(PGD_SIZE < 64); 47 #endif 48 49 /* 50 * Naturally aligned pgds required by the architecture. 51 */ 52 pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE, 53 SLAB_PANIC, NULL); 54 } 55