Commit | Line | Data |
---|---|---|
caab277b | 1 | // SPDX-License-Identifier: GPL-2.0-only |
1d18c47c CM |
2 | /* |
3 | * PGD allocation/freeing | |
4 | * | |
5 | * Copyright (C) 2012 ARM Ltd. | |
6 | * Author: Catalin Marinas <catalin.marinas@arm.com> | |
1d18c47c CM |
7 | */ |
8 | ||
9 | #include <linux/mm.h> | |
10 | #include <linux/gfp.h> | |
11 | #include <linux/highmem.h> | |
12 | #include <linux/slab.h> | |
13 | ||
14 | #include <asm/pgalloc.h> | |
15 | #include <asm/page.h> | |
16 | #include <asm/tlbflush.h> | |
17 | ||
a349b302 | 18 | static struct kmem_cache *pgd_cache __ro_after_init; |
2a0b5c0d | 19 | |
1d18c47c CM |
20 | pgd_t *pgd_alloc(struct mm_struct *mm) |
21 | { | |
50f11a8a MR |
22 | gfp_t gfp = GFP_PGTABLE_USER; |
23 | ||
1d18c47c | 24 | if (PGD_SIZE == PAGE_SIZE) |
50f11a8a | 25 | return (pgd_t *)__get_free_page(gfp); |
1d18c47c | 26 | else |
50f11a8a | 27 | return kmem_cache_alloc(pgd_cache, gfp); |
1d18c47c CM |
28 | } |
29 | ||
30 | void pgd_free(struct mm_struct *mm, pgd_t *pgd) | |
31 | { | |
32 | if (PGD_SIZE == PAGE_SIZE) | |
33 | free_page((unsigned long)pgd); | |
34 | else | |
2a0b5c0d CM |
35 | kmem_cache_free(pgd_cache, pgd); |
36 | } | |
37 | ||
782de70c | 38 | void __init pgtable_cache_init(void) |
2a0b5c0d | 39 | { |
39b5be9b WD |
40 | if (PGD_SIZE == PAGE_SIZE) |
41 | return; | |
42 | ||
529c4b05 KM |
43 | #ifdef CONFIG_ARM64_PA_BITS_52 |
44 | /* | |
45 | * With 52-bit physical addresses, the architecture requires the | |
46 | * top-level table to be aligned to at least 64 bytes. | |
47 | */ | |
48 | BUILD_BUG_ON(PGD_SIZE < 64); | |
49 | #endif | |
50 | ||
2a0b5c0d CM |
51 | /* |
52 | * Naturally aligned pgds required by the architecture. | |
53 | */ | |
39b5be9b WD |
54 | pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE, |
55 | SLAB_PANIC, NULL); | |
1d18c47c | 56 | } |