mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-01-21 03:40:51 -05:00
We enable CONFIG_RELOCATABLE even when CONFIG_RANDOMIZE_BASE is disabled, and this permits the loader (i.e., EFI) to place the kernel anywhere in physical memory as long as the base address is 64k aligned. This means that the 'KASLR' case described in the header that defines the size of the statically allocated page tables could take effect even when CONFIG_RANDMIZE_BASE=n. So check for CONFIG_RELOCATABLE instead. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com> Link: https://lore.kernel.org/r/20231129111555.3594833-45-ardb@google.com Signed-off-by: Will Deacon <will@kernel.org>
107 lines
3.7 KiB
C
107 lines
3.7 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Kernel page table mapping
|
|
*
|
|
* Copyright (C) 2015 ARM Ltd.
|
|
*/
|
|
|
|
#ifndef __ASM_KERNEL_PGTABLE_H
|
|
#define __ASM_KERNEL_PGTABLE_H
|
|
|
|
#include <asm/boot.h>
|
|
#include <asm/pgtable-hwdef.h>
|
|
#include <asm/sparsemem.h>
|
|
|
|
/*
|
|
* The linear mapping and the start of memory are both 2M aligned (per
|
|
* the arm64 booting.txt requirements). Hence we can use section mapping
|
|
* with 4K (section size = 2M) but not with 16K (section size = 32M) or
|
|
* 64K (section size = 512M).
|
|
*/
|
|
|
|
/*
|
|
* The idmap and swapper page tables need some space reserved in the kernel
|
|
* image. Both require pgd, pud (4 levels only) and pmd tables to (section)
|
|
* map the kernel. With the 64K page configuration, swapper and idmap need to
|
|
* map to pte level. The swapper also maps the FDT (see __create_page_tables
|
|
* for more information). Note that the number of ID map translation levels
|
|
* could be increased on the fly if system RAM is out of reach for the default
|
|
* VA range, so pages required to map highest possible PA are reserved in all
|
|
* cases.
|
|
*/
|
|
#ifdef CONFIG_ARM64_4K_PAGES
|
|
#define SWAPPER_PGTABLE_LEVELS (CONFIG_PGTABLE_LEVELS - 1)
|
|
#else
|
|
#define SWAPPER_PGTABLE_LEVELS (CONFIG_PGTABLE_LEVELS)
|
|
#endif
|
|
|
|
|
|
/*
|
|
* A relocatable kernel may execute from an address that differs from the one at
|
|
* which it was linked. In the worst case, its runtime placement may intersect
|
|
* with two adjacent PGDIR entries, which means that an additional page table
|
|
* may be needed at each subordinate level.
|
|
*/
|
|
#define EXTRA_PAGE __is_defined(CONFIG_RELOCATABLE)
|
|
|
|
#define SPAN_NR_ENTRIES(vstart, vend, shift) \
|
|
((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1)
|
|
|
|
#define EARLY_ENTRIES(vstart, vend, shift, add) \
|
|
(SPAN_NR_ENTRIES(vstart, vend, shift) + (add))
|
|
|
|
#define EARLY_PGDS(vstart, vend, add) (EARLY_ENTRIES(vstart, vend, PGDIR_SHIFT, add))
|
|
|
|
#if SWAPPER_PGTABLE_LEVELS > 3
|
|
#define EARLY_PUDS(vstart, vend, add) (EARLY_ENTRIES(vstart, vend, PUD_SHIFT, add))
|
|
#else
|
|
#define EARLY_PUDS(vstart, vend, add) (0)
|
|
#endif
|
|
|
|
#if SWAPPER_PGTABLE_LEVELS > 2
|
|
#define EARLY_PMDS(vstart, vend, add) (EARLY_ENTRIES(vstart, vend, SWAPPER_TABLE_SHIFT, add))
|
|
#else
|
|
#define EARLY_PMDS(vstart, vend, add) (0)
|
|
#endif
|
|
|
|
#define EARLY_PAGES(vstart, vend, add) ( 1 /* PGDIR page */ \
|
|
+ EARLY_PGDS((vstart), (vend), add) /* each PGDIR needs a next level page table */ \
|
|
+ EARLY_PUDS((vstart), (vend), add) /* each PUD needs a next level page table */ \
|
|
+ EARLY_PMDS((vstart), (vend), add)) /* each PMD needs a next level page table */
|
|
#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end, EXTRA_PAGE))
|
|
|
|
/* the initial ID map may need two extra pages if it needs to be extended */
|
|
#if VA_BITS < 48
|
|
#define INIT_IDMAP_DIR_SIZE ((INIT_IDMAP_DIR_PAGES + 2) * PAGE_SIZE)
|
|
#else
|
|
#define INIT_IDMAP_DIR_SIZE (INIT_IDMAP_DIR_PAGES * PAGE_SIZE)
|
|
#endif
|
|
#define INIT_IDMAP_DIR_PAGES EARLY_PAGES(KIMAGE_VADDR, _end + MAX_FDT_SIZE + SWAPPER_BLOCK_SIZE, 1)
|
|
|
|
/* Initial memory map size */
|
|
#ifdef CONFIG_ARM64_4K_PAGES
|
|
#define SWAPPER_BLOCK_SHIFT PMD_SHIFT
|
|
#define SWAPPER_BLOCK_SIZE PMD_SIZE
|
|
#define SWAPPER_TABLE_SHIFT PUD_SHIFT
|
|
#else
|
|
#define SWAPPER_BLOCK_SHIFT PAGE_SHIFT
|
|
#define SWAPPER_BLOCK_SIZE PAGE_SIZE
|
|
#define SWAPPER_TABLE_SHIFT PMD_SHIFT
|
|
#endif
|
|
|
|
/*
|
|
* Initial memory map attributes.
|
|
*/
|
|
#define SWAPPER_PTE_FLAGS (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED | PTE_UXN)
|
|
#define SWAPPER_PMD_FLAGS (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S | PTE_UXN)
|
|
|
|
#ifdef CONFIG_ARM64_4K_PAGES
|
|
#define SWAPPER_RW_MMUFLAGS (PMD_ATTRINDX(MT_NORMAL) | SWAPPER_PMD_FLAGS | PTE_WRITE)
|
|
#define SWAPPER_RX_MMUFLAGS (SWAPPER_RW_MMUFLAGS | PMD_SECT_RDONLY)
|
|
#else
|
|
#define SWAPPER_RW_MMUFLAGS (PTE_ATTRINDX(MT_NORMAL) | SWAPPER_PTE_FLAGS | PTE_WRITE)
|
|
#define SWAPPER_RX_MMUFLAGS (SWAPPER_RW_MMUFLAGS | PTE_RDONLY)
|
|
#endif
|
|
|
|
#endif /* __ASM_KERNEL_PGTABLE_H */
|