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 <npitre@baylibre.com>
This commit is contained in:
Nicolas Pitre 2024-07-22 16:19:51 -04:00 committed by Anas Nashif
commit cbbd8579b8
5 changed files with 84 additions and 0 deletions

View file

@ -260,6 +260,19 @@ config LINKER_USE_PINNED_SECTION
Requires that pinned sections exist in the architecture, SoC, Requires that pinned sections exist in the architecture, SoC,
board or custom linker script. 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 config LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT
bool "Generic sections are present at boot" if DEMAND_PAGING && LINKER_USE_PINNED_SECTION bool "Generic sections are present at boot" if DEMAND_PAGING && LINKER_USE_PINNED_SECTION
default y default y

View file

@ -70,6 +70,9 @@ MEMORY
LINKER_DT_REGIONS() LINKER_DT_REGIONS()
/* Used by and documented in include/linker/intlist.ld */ /* Used by and documented in include/linker/intlist.ld */
IDT_LIST (wx) : ORIGIN = 0xFFFF8000, LENGTH = 32K 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) ENTRY(CONFIG_KERNEL_ENTRY)
@ -294,6 +297,35 @@ SECTIONS
GROUP_END(RAMABLE_REGION) 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 <zephyr/linker/debug-sections.ld> #include <zephyr/linker/debug-sections.ld>
SECTION_PROLOGUE(.ARM.attributes, 0,) SECTION_PROLOGUE(.ARM.attributes, 0,)

View file

@ -337,6 +337,24 @@ static inline bool lnkr_is_region_pinned(uint8_t *addr, size_t sz)
#endif /* CONFIG_LINKER_USE_PINNED_SECTION */ #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 /* ! _ASMLANGUAGE */
#endif /* ZEPHYR_INCLUDE_LINKER_LINKER_DEFS_H_ */ #endif /* ZEPHYR_INCLUDE_LINKER_LINKER_DEFS_H_ */

View file

@ -100,6 +100,14 @@
#define __pinned_noinit __noinit #define __pinned_noinit __noinit
#endif /* CONFIG_LINKER_USE_PINNED_SECTION */ #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) #if defined(CONFIG_LINKER_USE_PINNED_SECTION)
#define __isr __pinned_func #define __isr __pinned_func
#else #else

View file

@ -101,6 +101,11 @@
#define PINNED_NOINIT_SECTION_NAME pinned_noinit #define PINNED_NOINIT_SECTION_NAME pinned_noinit
#endif #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 */ /* Short section references for use in ASM files */
#if defined(_ASMLANGUAGE) #if defined(_ASMLANGUAGE)
/* Various text section names */ /* Various text section names */
@ -140,6 +145,14 @@
#define PINNED_NOINIT NOINIT #define PINNED_NOINIT NOINIT
#endif /* CONFIG_LINKER_USE_PINNED_SECTION */ #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 */ #endif /* _ASMLANGUAGE */
#include <zephyr/linker/section_tags.h> #include <zephyr/linker/section_tags.h>