11d18c47cSCatalin Marinas /* 21d18c47cSCatalin Marinas * PGD allocation/freeing 31d18c47cSCatalin Marinas * 41d18c47cSCatalin Marinas * Copyright (C) 2012 ARM Ltd. 51d18c47cSCatalin Marinas * Author: Catalin Marinas <catalin.marinas@arm.com> 61d18c47cSCatalin Marinas * 71d18c47cSCatalin Marinas * This program is free software; you can redistribute it and/or modify 81d18c47cSCatalin Marinas * it under the terms of the GNU General Public License version 2 as 91d18c47cSCatalin Marinas * published by the Free Software Foundation. 101d18c47cSCatalin Marinas * 111d18c47cSCatalin Marinas * This program is distributed in the hope that it will be useful, 121d18c47cSCatalin Marinas * but WITHOUT ANY WARRANTY; without even the implied warranty of 131d18c47cSCatalin Marinas * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141d18c47cSCatalin Marinas * GNU General Public License for more details. 151d18c47cSCatalin Marinas * 161d18c47cSCatalin Marinas * You should have received a copy of the GNU General Public License 171d18c47cSCatalin Marinas * along with this program. If not, see <http://www.gnu.org/licenses/>. 181d18c47cSCatalin Marinas */ 191d18c47cSCatalin Marinas 201d18c47cSCatalin Marinas #include <linux/mm.h> 211d18c47cSCatalin Marinas #include <linux/gfp.h> 221d18c47cSCatalin Marinas #include <linux/highmem.h> 231d18c47cSCatalin Marinas #include <linux/slab.h> 241d18c47cSCatalin Marinas 251d18c47cSCatalin Marinas #include <asm/pgalloc.h> 261d18c47cSCatalin Marinas #include <asm/page.h> 271d18c47cSCatalin Marinas #include <asm/tlbflush.h> 281d18c47cSCatalin Marinas 291d18c47cSCatalin Marinas #include "mm.h" 301d18c47cSCatalin Marinas 312a0b5c0dSCatalin Marinas static struct kmem_cache *pgd_cache; 322a0b5c0dSCatalin Marinas 331d18c47cSCatalin Marinas pgd_t *pgd_alloc(struct mm_struct *mm) 341d18c47cSCatalin Marinas { 351d18c47cSCatalin Marinas if (PGD_SIZE == PAGE_SIZE) 3615670ef1SMark Rutland return (pgd_t *)__get_free_page(PGALLOC_GFP); 371d18c47cSCatalin Marinas else 3815670ef1SMark Rutland return kmem_cache_alloc(pgd_cache, PGALLOC_GFP); 391d18c47cSCatalin Marinas } 401d18c47cSCatalin Marinas 411d18c47cSCatalin Marinas void pgd_free(struct mm_struct *mm, pgd_t *pgd) 421d18c47cSCatalin Marinas { 431d18c47cSCatalin Marinas if (PGD_SIZE == PAGE_SIZE) 441d18c47cSCatalin Marinas free_page((unsigned long)pgd); 451d18c47cSCatalin Marinas else 462a0b5c0dSCatalin Marinas kmem_cache_free(pgd_cache, pgd); 471d18c47cSCatalin Marinas } 482a0b5c0dSCatalin Marinas 4939b5be9bSWill Deacon void __init pgd_cache_init(void) 502a0b5c0dSCatalin Marinas { 5139b5be9bSWill Deacon if (PGD_SIZE == PAGE_SIZE) 5239b5be9bSWill Deacon return; 5339b5be9bSWill Deacon 542a0b5c0dSCatalin Marinas /* 552a0b5c0dSCatalin Marinas * Naturally aligned pgds required by the architecture. 562a0b5c0dSCatalin Marinas */ 572a0b5c0dSCatalin Marinas pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE, 582a0b5c0dSCatalin Marinas SLAB_PANIC, NULL); 592a0b5c0dSCatalin Marinas } 60