xref: /linux/arch/arm64/include/asm/kernel-pgtable.h (revision e7d759f31ca295d589f7420719c311870bb3166f)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Kernel page table mapping
4  *
5  * Copyright (C) 2015 ARM Ltd.
6  */
7 
8 #ifndef __ASM_KERNEL_PGTABLE_H
9 #define __ASM_KERNEL_PGTABLE_H
10 
11 #include <asm/boot.h>
12 #include <asm/pgtable-hwdef.h>
13 #include <asm/sparsemem.h>
14 
15 /*
16  * The linear mapping and the start of memory are both 2M aligned (per
17  * the arm64 booting.txt requirements). Hence we can use section mapping
18  * with 4K (section size = 2M) but not with 16K (section size = 32M) or
19  * 64K (section size = 512M).
20  */
21 
22 /*
23  * The idmap and swapper page tables need some space reserved in the kernel
24  * image. Both require pgd, pud (4 levels only) and pmd tables to (section)
25  * map the kernel. With the 64K page configuration, swapper and idmap need to
26  * map to pte level. The swapper also maps the FDT (see __create_page_tables
27  * for more information). Note that the number of ID map translation levels
28  * could be increased on the fly if system RAM is out of reach for the default
29  * VA range, so pages required to map highest possible PA are reserved in all
30  * cases.
31  */
32 #ifdef CONFIG_ARM64_4K_PAGES
33 #define SWAPPER_PGTABLE_LEVELS	(CONFIG_PGTABLE_LEVELS - 1)
34 #else
35 #define SWAPPER_PGTABLE_LEVELS	(CONFIG_PGTABLE_LEVELS)
36 #endif
37 
38 
39 /*
40  * A relocatable kernel may execute from an address that differs from the one at
41  * which it was linked. In the worst case, its runtime placement may intersect
42  * with two adjacent PGDIR entries, which means that an additional page table
43  * may be needed at each subordinate level.
44  */
45 #define EXTRA_PAGE	__is_defined(CONFIG_RELOCATABLE)
46 
47 #define SPAN_NR_ENTRIES(vstart, vend, shift) \
48 	((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1)
49 
50 #define EARLY_ENTRIES(vstart, vend, shift, add) \
51 	(SPAN_NR_ENTRIES(vstart, vend, shift) + (add))
52 
53 #define EARLY_PGDS(vstart, vend, add) (EARLY_ENTRIES(vstart, vend, PGDIR_SHIFT, add))
54 
55 #if SWAPPER_PGTABLE_LEVELS > 3
56 #define EARLY_PUDS(vstart, vend, add) (EARLY_ENTRIES(vstart, vend, PUD_SHIFT, add))
57 #else
58 #define EARLY_PUDS(vstart, vend, add) (0)
59 #endif
60 
61 #if SWAPPER_PGTABLE_LEVELS > 2
62 #define EARLY_PMDS(vstart, vend, add) (EARLY_ENTRIES(vstart, vend, SWAPPER_TABLE_SHIFT, add))
63 #else
64 #define EARLY_PMDS(vstart, vend, add) (0)
65 #endif
66 
67 #define EARLY_PAGES(vstart, vend, add) ( 1 			/* PGDIR page */				\
68 			+ EARLY_PGDS((vstart), (vend), add) 	/* each PGDIR needs a next level page table */	\
69 			+ EARLY_PUDS((vstart), (vend), add)	/* each PUD needs a next level page table */	\
70 			+ EARLY_PMDS((vstart), (vend), add))	/* each PMD needs a next level page table */
71 #define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end, EXTRA_PAGE))
72 
73 /* the initial ID map may need two extra pages if it needs to be extended */
74 #if VA_BITS < 48
75 #define INIT_IDMAP_DIR_SIZE	((INIT_IDMAP_DIR_PAGES + 2) * PAGE_SIZE)
76 #else
77 #define INIT_IDMAP_DIR_SIZE	(INIT_IDMAP_DIR_PAGES * PAGE_SIZE)
78 #endif
79 #define INIT_IDMAP_DIR_PAGES	EARLY_PAGES(KIMAGE_VADDR, _end + MAX_FDT_SIZE + SWAPPER_BLOCK_SIZE, 1)
80 
81 /* Initial memory map size */
82 #ifdef CONFIG_ARM64_4K_PAGES
83 #define SWAPPER_BLOCK_SHIFT	PMD_SHIFT
84 #define SWAPPER_BLOCK_SIZE	PMD_SIZE
85 #define SWAPPER_TABLE_SHIFT	PUD_SHIFT
86 #else
87 #define SWAPPER_BLOCK_SHIFT	PAGE_SHIFT
88 #define SWAPPER_BLOCK_SIZE	PAGE_SIZE
89 #define SWAPPER_TABLE_SHIFT	PMD_SHIFT
90 #endif
91 
92 /*
93  * Initial memory map attributes.
94  */
95 #define SWAPPER_PTE_FLAGS	(PTE_TYPE_PAGE | PTE_AF | PTE_SHARED | PTE_UXN)
96 #define SWAPPER_PMD_FLAGS	(PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S | PTE_UXN)
97 
98 #ifdef CONFIG_ARM64_4K_PAGES
99 #define SWAPPER_RW_MMUFLAGS	(PMD_ATTRINDX(MT_NORMAL) | SWAPPER_PMD_FLAGS | PTE_WRITE)
100 #define SWAPPER_RX_MMUFLAGS	(SWAPPER_RW_MMUFLAGS | PMD_SECT_RDONLY)
101 #else
102 #define SWAPPER_RW_MMUFLAGS	(PTE_ATTRINDX(MT_NORMAL) | SWAPPER_PTE_FLAGS | PTE_WRITE)
103 #define SWAPPER_RX_MMUFLAGS	(SWAPPER_RW_MMUFLAGS | PTE_RDONLY)
104 #endif
105 
106 #endif	/* __ASM_KERNEL_PGTABLE_H */
107