xref: /linux/arch/arm64/mm/pgd.c (revision 2a0b5c0d19298cad54573682321b5fe015fa5a0d)
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