1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 21d18c47cSCatalin Marinas /* 31d18c47cSCatalin Marinas * PGD allocation/freeing 41d18c47cSCatalin Marinas * 51d18c47cSCatalin Marinas * Copyright (C) 2012 ARM Ltd. 61d18c47cSCatalin Marinas * Author: Catalin Marinas <catalin.marinas@arm.com> 71d18c47cSCatalin Marinas */ 81d18c47cSCatalin Marinas 91d18c47cSCatalin Marinas #include <linux/mm.h> 101d18c47cSCatalin Marinas #include <linux/gfp.h> 111d18c47cSCatalin Marinas #include <linux/highmem.h> 121d18c47cSCatalin Marinas #include <linux/slab.h> 131d18c47cSCatalin Marinas 141d18c47cSCatalin Marinas #include <asm/pgalloc.h> 151d18c47cSCatalin Marinas #include <asm/page.h> 161d18c47cSCatalin Marinas #include <asm/tlbflush.h> 171d18c47cSCatalin Marinas 18a349b302SJinbum Park static struct kmem_cache *pgd_cache __ro_after_init; 192a0b5c0dSCatalin Marinas 20*a6bbf5d4SArd Biesheuvel static bool pgdir_is_page_size(void) 21*a6bbf5d4SArd Biesheuvel { 22*a6bbf5d4SArd Biesheuvel if (PGD_SIZE == PAGE_SIZE) 23*a6bbf5d4SArd Biesheuvel return true; 24*a6bbf5d4SArd Biesheuvel if (CONFIG_PGTABLE_LEVELS == 5) 25*a6bbf5d4SArd Biesheuvel return !pgtable_l5_enabled(); 26*a6bbf5d4SArd Biesheuvel return false; 27*a6bbf5d4SArd Biesheuvel } 28*a6bbf5d4SArd Biesheuvel 291d18c47cSCatalin Marinas pgd_t *pgd_alloc(struct mm_struct *mm) 301d18c47cSCatalin Marinas { 3150f11a8aSMike Rapoport gfp_t gfp = GFP_PGTABLE_USER; 3250f11a8aSMike Rapoport 33*a6bbf5d4SArd Biesheuvel if (pgdir_is_page_size()) 3450f11a8aSMike Rapoport return (pgd_t *)__get_free_page(gfp); 351d18c47cSCatalin Marinas else 3650f11a8aSMike Rapoport return kmem_cache_alloc(pgd_cache, gfp); 371d18c47cSCatalin Marinas } 381d18c47cSCatalin Marinas 391d18c47cSCatalin Marinas void pgd_free(struct mm_struct *mm, pgd_t *pgd) 401d18c47cSCatalin Marinas { 41*a6bbf5d4SArd Biesheuvel if (pgdir_is_page_size()) 421d18c47cSCatalin Marinas free_page((unsigned long)pgd); 431d18c47cSCatalin Marinas else 442a0b5c0dSCatalin Marinas kmem_cache_free(pgd_cache, pgd); 451d18c47cSCatalin Marinas } 462a0b5c0dSCatalin Marinas 47782de70cSMike Rapoport void __init pgtable_cache_init(void) 482a0b5c0dSCatalin Marinas { 49*a6bbf5d4SArd Biesheuvel if (pgdir_is_page_size()) 5039b5be9bSWill Deacon return; 5139b5be9bSWill Deacon 52529c4b05SKristina Martsenko #ifdef CONFIG_ARM64_PA_BITS_52 53529c4b05SKristina Martsenko /* 54529c4b05SKristina Martsenko * With 52-bit physical addresses, the architecture requires the 55529c4b05SKristina Martsenko * top-level table to be aligned to at least 64 bytes. 56529c4b05SKristina Martsenko */ 57529c4b05SKristina Martsenko BUILD_BUG_ON(PGD_SIZE < 64); 58529c4b05SKristina Martsenko #endif 59529c4b05SKristina Martsenko 602a0b5c0dSCatalin Marinas /* 612a0b5c0dSCatalin Marinas * Naturally aligned pgds required by the architecture. 622a0b5c0dSCatalin Marinas */ 632a0b5c0dSCatalin Marinas pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE, 642a0b5c0dSCatalin Marinas SLAB_PANIC, NULL); 652a0b5c0dSCatalin Marinas } 66