mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-28 05:12:49 +00:00
414c109bdf
Today the fixmap code largely maps elements at PAGE_SIZE granularity, but we special-case the FDT mapping such that it can be mapped with 2M block mappings when 4K pages are in use. The original rationale for this was simplicity, but it has some unfortunate side-effects, and complicates portions of the fixmap code (i.e. is not so simple after all). The FDT can be up to 2M in size but is only required to have 8-byte alignment, and so it may straddle a 2M boundary. Thus when using 2M block mappings we may map up to 4M of memory surrounding the FDT. This is unfortunate as most of that memory will be unrelated to the FDT, and any pages which happen to share a 2M block with the FDT will by mapped with Normal Write-Back Cacheable attributes, which might not be what we want elsewhere (e.g. for carve-outs using Non-Cacheable attributes). The logic to handle mapping the FDT with 2M blocks requires some special cases in the fixmap code, and ties it to the early page table configuration by virtue of the SWAPPER_TABLE_SHIFT and SWAPPER_BLOCK_SIZE constants used to determine the granularity used to map the FDT. This patch simplifies the FDT logic and removes the unnecessary mappings of surrounding pages by always mapping the FDT at page granularity as with all other fixmap mappings. To do so we statically reserve multiple PTE tables to cover the fixmap VA range. Since the FDT can be at most 2M, for 4K pages we only need to allocate a single additional PTE table, and for 16K and 64K pages the existing single PTE table is sufficient. The PTE table allocation scales with the number of slots reserved in the fixmap, and so this also makes it easier to add more fixmap entries if we require those in future. Our VA layout means that the fixmap will always fall within a single PMD table (and consequently, within a single PUD/P4D/PGD entry), which we can verify at compile time with a static_assert(). With that assert a number of runtime warnings become impossible, and are removed. I've boot-tested this patch with both 4K and 64K pages. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Cc: Anshuman Khandual <anshuman.khandual@arm.com> Cc: Ard Biesheuvel <ardb@kernel.org> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Ryan Roberts <ryan.roberts@arm.com> Cc: Will Deacon <will@kernel.org> Reviewed-by: Ryan Roberts <ryan.roberts@arm.com> Link: https://lore.kernel.org/r/20230406152759.4164229-4-mark.rutland@arm.com Signed-off-by: Will Deacon <will@kernel.org>
115 lines
3.1 KiB
C
115 lines
3.1 KiB
C
/*
|
|
* fixmap.h: compile-time virtual memory allocation
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file "COPYING" in the main directory of this archive
|
|
* for more details.
|
|
*
|
|
* Copyright (C) 1998 Ingo Molnar
|
|
* Copyright (C) 2013 Mark Salter <msalter@redhat.com>
|
|
*
|
|
* Adapted from arch/x86 version.
|
|
*
|
|
*/
|
|
|
|
#ifndef _ASM_ARM64_FIXMAP_H
|
|
#define _ASM_ARM64_FIXMAP_H
|
|
|
|
#ifndef __ASSEMBLY__
|
|
#include <linux/kernel.h>
|
|
#include <linux/math.h>
|
|
#include <linux/sizes.h>
|
|
#include <asm/boot.h>
|
|
#include <asm/page.h>
|
|
#include <asm/pgtable-prot.h>
|
|
|
|
/*
|
|
* Here we define all the compile-time 'special' virtual
|
|
* addresses. The point is to have a constant address at
|
|
* compile time, but to set the physical address only
|
|
* in the boot process.
|
|
*
|
|
* Each enum increment in these 'compile-time allocated'
|
|
* memory buffers is page-sized. Use set_fixmap(idx,phys)
|
|
* to associate physical memory with a fixmap index.
|
|
*/
|
|
enum fixed_addresses {
|
|
FIX_HOLE,
|
|
|
|
/*
|
|
* Reserve a virtual window for the FDT that is a page bigger than the
|
|
* maximum supported size. The additional space ensures that any FDT
|
|
* that does not exceed MAX_FDT_SIZE can be mapped regardless of
|
|
* whether it crosses any page boundary.
|
|
*/
|
|
FIX_FDT_END,
|
|
FIX_FDT = FIX_FDT_END + DIV_ROUND_UP(MAX_FDT_SIZE, PAGE_SIZE) + 1,
|
|
|
|
FIX_EARLYCON_MEM_BASE,
|
|
FIX_TEXT_POKE0,
|
|
|
|
#ifdef CONFIG_ACPI_APEI_GHES
|
|
/* Used for GHES mapping from assorted contexts */
|
|
FIX_APEI_GHES_IRQ,
|
|
FIX_APEI_GHES_SEA,
|
|
#ifdef CONFIG_ARM_SDE_INTERFACE
|
|
FIX_APEI_GHES_SDEI_NORMAL,
|
|
FIX_APEI_GHES_SDEI_CRITICAL,
|
|
#endif
|
|
#endif /* CONFIG_ACPI_APEI_GHES */
|
|
|
|
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
|
|
#ifdef CONFIG_RELOCATABLE
|
|
FIX_ENTRY_TRAMP_TEXT4, /* one extra slot for the data page */
|
|
#endif
|
|
FIX_ENTRY_TRAMP_TEXT3,
|
|
FIX_ENTRY_TRAMP_TEXT2,
|
|
FIX_ENTRY_TRAMP_TEXT1,
|
|
#define TRAMP_VALIAS (__fix_to_virt(FIX_ENTRY_TRAMP_TEXT1))
|
|
#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
|
|
__end_of_permanent_fixed_addresses,
|
|
|
|
/*
|
|
* Temporary boot-time mappings, used by early_ioremap(),
|
|
* before ioremap() is functional.
|
|
*/
|
|
#define NR_FIX_BTMAPS (SZ_256K / PAGE_SIZE)
|
|
#define FIX_BTMAPS_SLOTS 7
|
|
#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
|
|
|
|
FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
|
|
FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
|
|
|
|
/*
|
|
* Used for kernel page table creation, so unmapped memory may be used
|
|
* for tables.
|
|
*/
|
|
FIX_PTE,
|
|
FIX_PMD,
|
|
FIX_PUD,
|
|
FIX_PGD,
|
|
|
|
__end_of_fixed_addresses
|
|
};
|
|
|
|
#define FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT)
|
|
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
|
|
#define FIXADDR_TOT_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
|
|
#define FIXADDR_TOT_START (FIXADDR_TOP - FIXADDR_TOT_SIZE)
|
|
|
|
#define FIXMAP_PAGE_IO __pgprot(PROT_DEVICE_nGnRE)
|
|
|
|
void __init early_fixmap_init(void);
|
|
void __init fixmap_copy(pgd_t *pgdir);
|
|
|
|
#define __early_set_fixmap __set_fixmap
|
|
|
|
#define __late_set_fixmap __set_fixmap
|
|
#define __late_clear_fixmap(idx) __set_fixmap((idx), 0, FIXMAP_PAGE_CLEAR)
|
|
|
|
extern void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot);
|
|
|
|
#include <asm-generic/fixmap.h>
|
|
|
|
#endif /* !__ASSEMBLY__ */
|
|
#endif /* _ASM_ARM64_FIXMAP_H */
|