From cbbd8579b8e3d58d356ef8e5053f878cb51f7f14 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 22 Jul 2024 16:19:51 -0400 Subject: [PATCH] linker: introduce on-demand linker section tags This provides __ondemand_func and __ondemand_rodata tags for annotating functions and read-only data that should be loaded on demand so not to exhaust all available RAM. The demand paging mechanism will be leveraged to load so designated code/data as needed and to evict it from memory when unused. Signed-off-by: Nicolas Pitre --- Kconfig.zephyr | 13 +++++++++ include/zephyr/arch/arm64/scripts/linker.ld | 32 +++++++++++++++++++++ include/zephyr/linker/linker-defs.h | 18 ++++++++++++ include/zephyr/linker/section_tags.h | 8 ++++++ include/zephyr/linker/sections.h | 13 +++++++++ 5 files changed, 84 insertions(+) diff --git a/Kconfig.zephyr b/Kconfig.zephyr index 89cdefdc87f..36b753dd4a8 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -260,6 +260,19 @@ config LINKER_USE_PINNED_SECTION Requires that pinned sections exist in the architecture, SoC, board or custom linker script. +config LINKER_USE_ONDEMAND_SECTION + bool "Use Evictable Linker Section" + depends on !LINKER_USE_PINNED_SECTION + depends on !ARCH_MAPS_ALL_RAM + help + If enabled, the symbols which may be evicted from memory + will be put into a linker section reserved for on-demand symbols. + During boot, the corresponding memory will be mapped as paged out. + This is conceptually the opposite of CONFIG_LINKER_USE_PINNED_SECTION. + + Requires that on-demand sections exist in the architecture, SoC, + board or custom linker script. + config LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT bool "Generic sections are present at boot" if DEMAND_PAGING && LINKER_USE_PINNED_SECTION default y diff --git a/include/zephyr/arch/arm64/scripts/linker.ld b/include/zephyr/arch/arm64/scripts/linker.ld index 67ac090705e..648ebba5690 100644 --- a/include/zephyr/arch/arm64/scripts/linker.ld +++ b/include/zephyr/arch/arm64/scripts/linker.ld @@ -70,6 +70,9 @@ MEMORY LINKER_DT_REGIONS() /* Used by and documented in include/linker/intlist.ld */ IDT_LIST (wx) : ORIGIN = 0xFFFF8000, LENGTH = 32K +#ifdef CONFIG_LINKER_USE_ONDEMAND_SECTION + ONDEMAND (rx) : ORIGIN = (CONFIG_KERNEL_VM_BASE), LENGTH = (CONFIG_KERNEL_VM_SIZE) +#endif } ENTRY(CONFIG_KERNEL_ENTRY) @@ -294,6 +297,35 @@ SECTIONS GROUP_END(RAMABLE_REGION) +#ifdef CONFIG_LINKER_USE_ONDEMAND_SECTION + . = z_mapped_end; + MMU_ALIGN; + lnkr_ondemand_start = .; + + ONDEMAND_TEXT_SECTION_NAME (.) : AT(ADDR(_BSS_SECTION_NAME)) + { + lnkr_ondemand_text_start = .; + *(.ondemand_text) + *(.ondemand_text.*) + MMU_ALIGN; + lnkr_ondemand_text_end = .; + } > ONDEMAND + lnkr_ondemand_text_size = SIZEOF(ONDEMAND_TEXT_SECTION_NAME); + + ONDEMAND_RODATA_SECTION_NAME : + { + lnkr_ondemand_rodata_start = .; + *(.ondemand_rodata) + *(.ondemand_rodata.*) + MMU_ALIGN; + lnkr_ondemand_rodata_end = .; + } > ONDEMAND + lnkr_ondemand_rodata_size = SIZEOF(ONDEMAND_RODATA_SECTION_NAME); + + lnkr_ondemand_end = .; + lnkr_ondemand_load_start = LOADADDR(ONDEMAND_TEXT_SECTION_NAME); +#endif + #include SECTION_PROLOGUE(.ARM.attributes, 0,) diff --git a/include/zephyr/linker/linker-defs.h b/include/zephyr/linker/linker-defs.h index d860222ffac..5c1089c0fcf 100644 --- a/include/zephyr/linker/linker-defs.h +++ b/include/zephyr/linker/linker-defs.h @@ -337,6 +337,24 @@ static inline bool lnkr_is_region_pinned(uint8_t *addr, size_t sz) #endif /* CONFIG_LINKER_USE_PINNED_SECTION */ +#ifdef CONFIG_LINKER_USE_ONDEMAND_SECTION +/* lnkr_ondemand_start[] and lnkr_ondemand_end[] must encapsulate + * all the on-demand sections as these are used by + * the MMU code to mark the virtual pages with the appropriate backing store + * location token to have them be paged in on demand. + */ +extern char lnkr_ondemand_start[]; +extern char lnkr_ondemand_end[]; +extern char lnkr_ondemand_load_start[]; + +extern char lnkr_ondemand_text_start[]; +extern char lnkr_ondemand_text_end[]; +extern char lnkr_ondemand_text_size[]; +extern char lnkr_ondemand_rodata_start[]; +extern char lnkr_ondemand_rodata_end[]; +extern char lnkr_ondemand_rodata_size[]; + +#endif /* CONFIG_LINKER_USE_ONDEMAND_SECTION */ #endif /* ! _ASMLANGUAGE */ #endif /* ZEPHYR_INCLUDE_LINKER_LINKER_DEFS_H_ */ diff --git a/include/zephyr/linker/section_tags.h b/include/zephyr/linker/section_tags.h index 546ba4e09ad..560d7611b7a 100644 --- a/include/zephyr/linker/section_tags.h +++ b/include/zephyr/linker/section_tags.h @@ -100,6 +100,14 @@ #define __pinned_noinit __noinit #endif /* CONFIG_LINKER_USE_PINNED_SECTION */ +#if defined(CONFIG_LINKER_USE_ONDEMAND_SECTION) +#define __ondemand_func Z_GENERIC_DOT_SECTION(ONDEMAND_TEXT_SECTION_NAME) +#define __ondemand_rodata Z_GENERIC_DOT_SECTION(ONDEMAND_RODATA_SECTION_NAME) +#else +#define __ondemand_func +#define __ondemand_rodata +#endif /* CONFIG_LINKER_USE_ONDEMAND_SECTION */ + #if defined(CONFIG_LINKER_USE_PINNED_SECTION) #define __isr __pinned_func #else diff --git a/include/zephyr/linker/sections.h b/include/zephyr/linker/sections.h index 1557d72d867..36159427fa6 100644 --- a/include/zephyr/linker/sections.h +++ b/include/zephyr/linker/sections.h @@ -101,6 +101,11 @@ #define PINNED_NOINIT_SECTION_NAME pinned_noinit #endif +#if defined(CONFIG_LINKER_USE_ONDEMAND_SECTION) +#define ONDEMAND_TEXT_SECTION_NAME ondemand_text +#define ONDEMAND_RODATA_SECTION_NAME ondemand_rodata +#endif + /* Short section references for use in ASM files */ #if defined(_ASMLANGUAGE) /* Various text section names */ @@ -140,6 +145,14 @@ #define PINNED_NOINIT NOINIT #endif /* CONFIG_LINKER_USE_PINNED_SECTION */ +#if defined(CONFIG_LINKER_USE_ONDEMAND_SECTION) +#define ONDEMAND_TEXT ONDEMAND_TEXT_SECTION_NAME +#define ONDEMAND_RODATA ONDEMAND_RODATA_SECTION_NAME +#else +#define ONDEMAND_TEXT TEXT +#define ONDEMAND_RODATA RODATA +#endif /* CONFIG_LINKER_USE_ONDEMAND_SECTION */ + #endif /* _ASMLANGUAGE */ #include