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 pgdir_is_page_size(void)20a6bbf5d4SArd Biesheuvelstatic bool pgdir_is_page_size(void) 21a6bbf5d4SArd Biesheuvel { 22a6bbf5d4SArd Biesheuvel if (PGD_SIZE == PAGE_SIZE) 23a6bbf5d4SArd Biesheuvel return true; 24*0dd4f60aSArd Biesheuvel if (CONFIG_PGTABLE_LEVELS == 4) 25*0dd4f60aSArd Biesheuvel return !pgtable_l4_enabled(); 26a6bbf5d4SArd Biesheuvel if (CONFIG_PGTABLE_LEVELS == 5) 27a6bbf5d4SArd Biesheuvel return !pgtable_l5_enabled(); 28a6bbf5d4SArd Biesheuvel return false; 29a6bbf5d4SArd Biesheuvel } 30a6bbf5d4SArd Biesheuvel pgd_alloc(struct mm_struct * mm)311d18c47cSCatalin Marinaspgd_t *pgd_alloc(struct mm_struct *mm) 321d18c47cSCatalin Marinas { 3350f11a8aSMike Rapoport gfp_t gfp = GFP_PGTABLE_USER; 3450f11a8aSMike Rapoport 35a6bbf5d4SArd Biesheuvel if (pgdir_is_page_size()) 3650f11a8aSMike Rapoport return (pgd_t *)__get_free_page(gfp); 371d18c47cSCatalin Marinas else 3850f11a8aSMike Rapoport return kmem_cache_alloc(pgd_cache, gfp); 391d18c47cSCatalin Marinas } 401d18c47cSCatalin Marinas pgd_free(struct mm_struct * mm,pgd_t * pgd)411d18c47cSCatalin Marinasvoid pgd_free(struct mm_struct *mm, pgd_t *pgd) 421d18c47cSCatalin Marinas { 43a6bbf5d4SArd Biesheuvel if (pgdir_is_page_size()) 441d18c47cSCatalin Marinas free_page((unsigned long)pgd); 451d18c47cSCatalin Marinas else 462a0b5c0dSCatalin Marinas kmem_cache_free(pgd_cache, pgd); 471d18c47cSCatalin Marinas } 482a0b5c0dSCatalin Marinas pgtable_cache_init(void)49782de70cSMike Rapoportvoid __init pgtable_cache_init(void) 502a0b5c0dSCatalin Marinas { 51a6bbf5d4SArd Biesheuvel if (pgdir_is_page_size()) 5239b5be9bSWill Deacon return; 5339b5be9bSWill Deacon 54529c4b05SKristina Martsenko #ifdef CONFIG_ARM64_PA_BITS_52 55529c4b05SKristina Martsenko /* 56529c4b05SKristina Martsenko * With 52-bit physical addresses, the architecture requires the 57529c4b05SKristina Martsenko * top-level table to be aligned to at least 64 bytes. 58529c4b05SKristina Martsenko */ 59529c4b05SKristina Martsenko BUILD_BUG_ON(PGD_SIZE < 64); 60529c4b05SKristina Martsenko #endif 61529c4b05SKristina Martsenko 622a0b5c0dSCatalin Marinas /* 632a0b5c0dSCatalin Marinas * Naturally aligned pgds required by the architecture. 642a0b5c0dSCatalin Marinas */ 652a0b5c0dSCatalin Marinas pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE, 662a0b5c0dSCatalin Marinas SLAB_PANIC, NULL); 672a0b5c0dSCatalin Marinas } 68