llext: Keep constant data in flash.

This patch adds a new Kconfig option that allows read-only data sections
without relocations to be mapped directly (remain in flash) instead of
being copied to RAM during extension loading. This helps extensions that
have large constant data, such as certificates, lookup tables etc.. to
save saving significant RAM, especially with MPU is enabled.

This feature requires the extension to place rodata sections without
relocations in LLEXT_RODATA_NO_RELOC section.

Note that we chose to disable this optimization when MMU or USERSPACE is
enabled because the NO_RELOC section may not be aligned to the MPU/MMU
requirements on some architectures. If we leave it in place, llext will
attempt to create an MPU region for it using a misaligned address, and
if we allow it to be copied to RAM, it defeats the purpose of this feature.

Signed-off-by: Ibrahim Abdalkader <i.abdalkader@gmail.com>
This commit is contained in:
Ibrahim Abdalkader
2025-12-09 13:07:01 +01:00
committed by Fabio Baltieri
parent 234aa30a8f
commit dca4136f5e
3 changed files with 44 additions and 0 deletions

View File

@@ -53,6 +53,9 @@ enum llext_mem {
LLEXT_MEM_PREINIT, /**< Array of early setup functions */
LLEXT_MEM_INIT, /**< Array of setup functions */
LLEXT_MEM_FINI, /**< Array of cleanup functions */
#ifdef CONFIG_LLEXT_RODATA_NO_RELOC
LLEXT_MEM_RODATA_NO_RELOC, /**< Read-only data without relocations (kept in flash) */
#endif
LLEXT_MEM_COUNT, /**< Number of regions managed by LLEXT */
};
@@ -62,6 +65,22 @@ enum llext_mem {
/* Number of memory partitions used by LLEXT */
#define LLEXT_MEM_PARTITIONS (LLEXT_MEM_BSS+1)
#ifdef CONFIG_LLEXT_RODATA_NO_RELOC
/* Section name for read-only data kept in flash */
#define LLEXT_SECT_RODATA_NO_RELOC llext.rodata.noreloc
/* Full section name as string for comparisons */
#define LLEXT_SECTION_RODATA_NO_RELOC ("." STRINGIFY(LLEXT_SECT_RODATA_NO_RELOC))
/**
* Use this attribute on read-only data that should remain in flash
* instead of being copied to RAM.
*/
#define LLEXT_RODATA_NO_RELOC Z_GENERIC_DOT_SECTION(LLEXT_SECT_RODATA_NO_RELOC)
#else
#define LLEXT_RODATA_NO_RELOC
#endif
struct llext_loader;
/** @endcond */

View File

@@ -108,6 +108,20 @@ config LLEXT_STORAGE_WRITABLE
Select if LLEXT storage is writable, i.e. if extensions are stored in
RAM and can be modified in place
config LLEXT_RODATA_NO_RELOC
bool "Keep read-only data without relocations in flash"
depends on !MMU && !USERSPACE
help
When enabled, read-only data sections (.rodata) that do not have
any relocations are kept in their original location (typically flash)
instead of being copied to RAM.
This is useful for large constant data like certificates, lookup
tables, or string literals that don't contain any pointers.
This feature requires the extension to manually tag that data with
the LLEXT_RODATA_NO_RELOC macro.
config LLEXT_EXPORT_DEVICES
bool "Export all DT devices to llexts"
select LLEXT_EXPORT_SYMBOL_GROUP_DEVICE

View File

@@ -262,6 +262,10 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext,
mem_idx = LLEXT_MEM_TEXT;
} else if (shdr->sh_flags & SHF_WRITE) {
mem_idx = LLEXT_MEM_DATA;
#ifdef CONFIG_LLEXT_RODATA_NO_RELOC
} else if (strcmp(name, LLEXT_SECTION_RODATA_NO_RELOC) == 0) {
mem_idx = LLEXT_MEM_RODATA_NO_RELOC;
#endif
} else {
mem_idx = LLEXT_MEM_RODATA;
}
@@ -534,6 +538,13 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext,
}
}
#ifdef CONFIG_LLEXT_RODATA_NO_RELOC
if (ldr->sects[LLEXT_MEM_RODATA_NO_RELOC].sh_flags & SHF_LLEXT_HAS_RELOCS) {
LOG_ERR("%s has relocations", LLEXT_SECTION_RODATA_NO_RELOC);
return -ENOEXEC;
}
#endif
return 0;
}