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 311d18c47cSCatalin Marinas #define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t)) 321d18c47cSCatalin Marinas 33*2a0b5c0dSCatalin Marinas static struct kmem_cache *pgd_cache; 34*2a0b5c0dSCatalin Marinas 351d18c47cSCatalin Marinas pgd_t *pgd_alloc(struct mm_struct *mm) 361d18c47cSCatalin Marinas { 371d18c47cSCatalin Marinas if (PGD_SIZE == PAGE_SIZE) 38883d50a0SMark Rutland return (pgd_t *)get_zeroed_page(GFP_KERNEL); 391d18c47cSCatalin Marinas else 40*2a0b5c0dSCatalin Marinas return kmem_cache_zalloc(pgd_cache, GFP_KERNEL); 411d18c47cSCatalin Marinas } 421d18c47cSCatalin Marinas 431d18c47cSCatalin Marinas void pgd_free(struct mm_struct *mm, pgd_t *pgd) 441d18c47cSCatalin Marinas { 451d18c47cSCatalin Marinas if (PGD_SIZE == PAGE_SIZE) 461d18c47cSCatalin Marinas free_page((unsigned long)pgd); 471d18c47cSCatalin Marinas else 48*2a0b5c0dSCatalin Marinas kmem_cache_free(pgd_cache, pgd); 491d18c47cSCatalin Marinas } 50*2a0b5c0dSCatalin Marinas 51*2a0b5c0dSCatalin Marinas static int __init pgd_cache_init(void) 52*2a0b5c0dSCatalin Marinas { 53*2a0b5c0dSCatalin Marinas /* 54*2a0b5c0dSCatalin Marinas * Naturally aligned pgds required by the architecture. 55*2a0b5c0dSCatalin Marinas */ 56*2a0b5c0dSCatalin Marinas if (PGD_SIZE != PAGE_SIZE) 57*2a0b5c0dSCatalin Marinas pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE, 58*2a0b5c0dSCatalin Marinas SLAB_PANIC, NULL); 59*2a0b5c0dSCatalin Marinas return 0; 60*2a0b5c0dSCatalin Marinas } 61*2a0b5c0dSCatalin Marinas core_initcall(pgd_cache_init); 62