18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Kernel page table mapping 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2015 ARM Ltd. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef __ASM_KERNEL_PGTABLE_H 98c2ecf20Sopenharmony_ci#define __ASM_KERNEL_PGTABLE_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <asm/pgtable-hwdef.h> 128c2ecf20Sopenharmony_ci#include <asm/sparsemem.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* 158c2ecf20Sopenharmony_ci * The linear mapping and the start of memory are both 2M aligned (per 168c2ecf20Sopenharmony_ci * the arm64 booting.txt requirements). Hence we can use section mapping 178c2ecf20Sopenharmony_ci * with 4K (section size = 2M) but not with 16K (section size = 32M) or 188c2ecf20Sopenharmony_ci * 64K (section size = 512M). 198c2ecf20Sopenharmony_ci */ 208c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM64_4K_PAGES 218c2ecf20Sopenharmony_ci#define ARM64_SWAPPER_USES_SECTION_MAPS 1 228c2ecf20Sopenharmony_ci#else 238c2ecf20Sopenharmony_ci#define ARM64_SWAPPER_USES_SECTION_MAPS 0 248c2ecf20Sopenharmony_ci#endif 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* 278c2ecf20Sopenharmony_ci * The idmap and swapper page tables need some space reserved in the kernel 288c2ecf20Sopenharmony_ci * image. Both require pgd, pud (4 levels only) and pmd tables to (section) 298c2ecf20Sopenharmony_ci * map the kernel. With the 64K page configuration, swapper and idmap need to 308c2ecf20Sopenharmony_ci * map to pte level. The swapper also maps the FDT (see __create_page_tables 318c2ecf20Sopenharmony_ci * for more information). Note that the number of ID map translation levels 328c2ecf20Sopenharmony_ci * could be increased on the fly if system RAM is out of reach for the default 338c2ecf20Sopenharmony_ci * VA range, so pages required to map highest possible PA are reserved in all 348c2ecf20Sopenharmony_ci * cases. 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_ci#if ARM64_SWAPPER_USES_SECTION_MAPS 378c2ecf20Sopenharmony_ci#define SWAPPER_PGTABLE_LEVELS (CONFIG_PGTABLE_LEVELS - 1) 388c2ecf20Sopenharmony_ci#define IDMAP_PGTABLE_LEVELS (ARM64_HW_PGTABLE_LEVELS(PHYS_MASK_SHIFT) - 1) 398c2ecf20Sopenharmony_ci#else 408c2ecf20Sopenharmony_ci#define SWAPPER_PGTABLE_LEVELS (CONFIG_PGTABLE_LEVELS) 418c2ecf20Sopenharmony_ci#define IDMAP_PGTABLE_LEVELS (ARM64_HW_PGTABLE_LEVELS(PHYS_MASK_SHIFT)) 428c2ecf20Sopenharmony_ci#endif 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* 468c2ecf20Sopenharmony_ci * If KASLR is enabled, then an offset K is added to the kernel address 478c2ecf20Sopenharmony_ci * space. The bottom 21 bits of this offset are zero to guarantee 2MB 488c2ecf20Sopenharmony_ci * alignment for PA and VA. 498c2ecf20Sopenharmony_ci * 508c2ecf20Sopenharmony_ci * For each pagetable level of the swapper, we know that the shift will 518c2ecf20Sopenharmony_ci * be larger than 21 (for the 4KB granule case we use section maps thus 528c2ecf20Sopenharmony_ci * the smallest shift is actually 30) thus there is the possibility that 538c2ecf20Sopenharmony_ci * KASLR can increase the number of pagetable entries by 1, so we make 548c2ecf20Sopenharmony_ci * room for this extra entry. 558c2ecf20Sopenharmony_ci * 568c2ecf20Sopenharmony_ci * Note KASLR cannot increase the number of required entries for a level 578c2ecf20Sopenharmony_ci * by more than one because it increments both the virtual start and end 588c2ecf20Sopenharmony_ci * addresses equally (the extra entry comes from the case where the end 598c2ecf20Sopenharmony_ci * address is just pushed over a boundary and the start address isn't). 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#ifdef CONFIG_RANDOMIZE_BASE 638c2ecf20Sopenharmony_ci#define EARLY_KASLR (1) 648c2ecf20Sopenharmony_ci#else 658c2ecf20Sopenharmony_ci#define EARLY_KASLR (0) 668c2ecf20Sopenharmony_ci#endif 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#define EARLY_ENTRIES(vstart, vend, shift) \ 698c2ecf20Sopenharmony_ci ((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1 + EARLY_KASLR) 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci#define EARLY_PGDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, PGDIR_SHIFT)) 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#if SWAPPER_PGTABLE_LEVELS > 3 748c2ecf20Sopenharmony_ci#define EARLY_PUDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, PUD_SHIFT)) 758c2ecf20Sopenharmony_ci#else 768c2ecf20Sopenharmony_ci#define EARLY_PUDS(vstart, vend) (0) 778c2ecf20Sopenharmony_ci#endif 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci#if SWAPPER_PGTABLE_LEVELS > 2 808c2ecf20Sopenharmony_ci#define EARLY_PMDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, SWAPPER_TABLE_SHIFT)) 818c2ecf20Sopenharmony_ci#else 828c2ecf20Sopenharmony_ci#define EARLY_PMDS(vstart, vend) (0) 838c2ecf20Sopenharmony_ci#endif 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#define EARLY_PAGES(vstart, vend) ( 1 /* PGDIR page */ \ 868c2ecf20Sopenharmony_ci + EARLY_PGDS((vstart), (vend)) /* each PGDIR needs a next level page table */ \ 878c2ecf20Sopenharmony_ci + EARLY_PUDS((vstart), (vend)) /* each PUD needs a next level page table */ \ 888c2ecf20Sopenharmony_ci + EARLY_PMDS((vstart), (vend))) /* each PMD needs a next level page table */ 898c2ecf20Sopenharmony_ci#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end)) 908c2ecf20Sopenharmony_ci#define IDMAP_DIR_SIZE (IDMAP_PGTABLE_LEVELS * PAGE_SIZE) 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci/* Initial memory map size */ 938c2ecf20Sopenharmony_ci#if ARM64_SWAPPER_USES_SECTION_MAPS 948c2ecf20Sopenharmony_ci#define SWAPPER_BLOCK_SHIFT SECTION_SHIFT 958c2ecf20Sopenharmony_ci#define SWAPPER_BLOCK_SIZE SECTION_SIZE 968c2ecf20Sopenharmony_ci#define SWAPPER_TABLE_SHIFT PUD_SHIFT 978c2ecf20Sopenharmony_ci#else 988c2ecf20Sopenharmony_ci#define SWAPPER_BLOCK_SHIFT PAGE_SHIFT 998c2ecf20Sopenharmony_ci#define SWAPPER_BLOCK_SIZE PAGE_SIZE 1008c2ecf20Sopenharmony_ci#define SWAPPER_TABLE_SHIFT PMD_SHIFT 1018c2ecf20Sopenharmony_ci#endif 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci/* The size of the initial kernel direct mapping */ 1048c2ecf20Sopenharmony_ci#define SWAPPER_INIT_MAP_SIZE (_AC(1, UL) << SWAPPER_TABLE_SHIFT) 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* 1078c2ecf20Sopenharmony_ci * Initial memory map attributes. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_ci#define SWAPPER_PTE_FLAGS (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) 1108c2ecf20Sopenharmony_ci#define SWAPPER_PMD_FLAGS (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci#if ARM64_SWAPPER_USES_SECTION_MAPS 1138c2ecf20Sopenharmony_ci#define SWAPPER_MM_MMUFLAGS (PMD_ATTRINDX(MT_NORMAL) | SWAPPER_PMD_FLAGS) 1148c2ecf20Sopenharmony_ci#else 1158c2ecf20Sopenharmony_ci#define SWAPPER_MM_MMUFLAGS (PTE_ATTRINDX(MT_NORMAL) | SWAPPER_PTE_FLAGS) 1168c2ecf20Sopenharmony_ci#endif 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/* 1198c2ecf20Sopenharmony_ci * To make optimal use of block mappings when laying out the linear 1208c2ecf20Sopenharmony_ci * mapping, round down the base of physical memory to a size that can 1218c2ecf20Sopenharmony_ci * be mapped efficiently, i.e., either PUD_SIZE (4k granule) or PMD_SIZE 1228c2ecf20Sopenharmony_ci * (64k granule), or a multiple that can be mapped using contiguous bits 1238c2ecf20Sopenharmony_ci * in the page tables: 32 * PMD_SIZE (16k granule) 1248c2ecf20Sopenharmony_ci */ 1258c2ecf20Sopenharmony_ci#if defined(CONFIG_ARM64_4K_PAGES) 1268c2ecf20Sopenharmony_ci#define ARM64_MEMSTART_SHIFT PUD_SHIFT 1278c2ecf20Sopenharmony_ci#elif defined(CONFIG_ARM64_16K_PAGES) 1288c2ecf20Sopenharmony_ci#define ARM64_MEMSTART_SHIFT (PMD_SHIFT + 5) 1298c2ecf20Sopenharmony_ci#else 1308c2ecf20Sopenharmony_ci#define ARM64_MEMSTART_SHIFT PMD_SHIFT 1318c2ecf20Sopenharmony_ci#endif 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci/* 1348c2ecf20Sopenharmony_ci * sparsemem vmemmap imposes an additional requirement on the alignment of 1358c2ecf20Sopenharmony_ci * memstart_addr, due to the fact that the base of the vmemmap region 1368c2ecf20Sopenharmony_ci * has a direct correspondence, and needs to appear sufficiently aligned 1378c2ecf20Sopenharmony_ci * in the virtual address space. 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci#if defined(CONFIG_SPARSEMEM_VMEMMAP) && ARM64_MEMSTART_SHIFT < SECTION_SIZE_BITS 1408c2ecf20Sopenharmony_ci#define ARM64_MEMSTART_ALIGN (1UL << SECTION_SIZE_BITS) 1418c2ecf20Sopenharmony_ci#else 1428c2ecf20Sopenharmony_ci#define ARM64_MEMSTART_ALIGN (1UL << ARM64_MEMSTART_SHIFT) 1438c2ecf20Sopenharmony_ci#endif 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci#endif /* __ASM_KERNEL_PGTABLE_H */ 146