doc/services/llext/config.rst
Configuration #############
The following Kconfig options are available for the LLEXT subsystem:
.. _llext_kconfig_heap:
The LLEXT subsystem needs a heap to be allocated for extension related data. The following option controls this allocation, when allocating a static heap.
:kconfig:option:CONFIG_LLEXT_HEAP_SIZE
Size of the LLEXT heap in kilobytes.
For boards using the Harvard architecture, the LLEXT heap is split into two: one heap in instruction memory and another in data memory. The following options control these allocations.
:kconfig:option:CONFIG_LLEXT_INSTR_HEAP_SIZE
Size of the LLEXT heap in instruction memory in kilobytes.
:kconfig:option:CONFIG_LLEXT_DATA_HEAP_SIZE
Size of the LLEXT heap in data memory in kilobytes.
Alternatively the application can configure a dynamic heap using the following option.
:kconfig:option:CONFIG_LLEXT_HEAP_DYNAMIC
Some applications require loading extensions into the memory which does
not exist during the boot time and cannot be allocated statically. Make
the application responsible for LLEXT heap allocation. Do not allocate
LLEXT heap statically.
Application must call :c:func:`llext_heap_init` in order to assign a
buffer to be used as the LLEXT heap, otherwise LLEXT modules will not
load. When the application does not need LLEXT functionality any more,
it should call :c:func:`llext_heap_uninit` which releases control of
the buffer back to the application.
.. note::
When :ref:user mode <usermode_api> is enabled, the heap size must be
large enough to allow the extension sections to be allocated with the
alignment required by the architecture.
.. note::
On Harvard architectures, applications must call
:c:func:llext_heap_init_harvard.
The backing data structure for the LLEXT heap is by default a
:c:struct:k_heap, but it can be changed to :c:type:sys_mem_blocks_t for
non-metadata (i.e., extension regions) by selecting
:kconfig:option:CONFIG_LLEXT_HEAP_MEMBLK for
:kconfig:option:CONFIG_LLEXT_HEAP_MANAGEMENT.
:kconfig:option:CONFIG_LLEXT_HEAP_MANAGEMENT
Select the memory management API used to store extension regions in
LLEXT heap memory. This choice does not affect LLEXT metadata, which
is always managed with :c:struct:`k_heap`.
:kconfig:option:CONFIG_LLEXT_HEAP_MEMBLK
Use :c:type:`sys_mem_blocks_t` API to manage LLEXT heap memory for
extension regions. A minimum of one block will be allocated per region.
Block size must be selected with care to ensure proper alignment for
extension regions.
.. note::
:kconfig:option:CONFIG_LLEXT_HEAP_MEMBLK does not support
:kconfig:option:CONFIG_LLEXT_HEAP_DYNAMIC.
The heap will be split into two, with the size of each sub-heap controlled by the following options.
:kconfig:option:CONFIG_LLEXT_EXT_HEAP_SIZE
Heap size in kilobytes available for LLEXT extension sections. Must be
a multiple of :kconfig:option:`CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE`.
Replaced by :kconfig:option:`CONFIG_LLEXT_INSTR_HEAP_SIZE` and
:kconfig:option:`CONFIG_LLEXT_DATA_HEAP_SIZE` if
:kconfig:option:`CONFIG_HARVARD` is selected.
:kconfig:option:CONFIG_LLEXT_METADATA_HEAP_SIZE
Heap size in kilobytes available for LLEXT metadata.
Another option controls block size.
:kconfig:option:CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE
Block size in bytes for LLEXT :c:type:`sys_mem_blocks_t` heap(s).
Must be equal to or a multiple of ``LLEXT_PAGE_SIZE``. The block size
must also be equal to or a multiple of the largest alignment needed
for any extension region. If
:kconfig:option:`CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT` is
selected and regions are large, an unreasonably large block size may be
needed to satisfy alignment requirements.
The LLEXT heap(s) have custom sections. Non-Harvard heap sections
(.llext_heap, or .llext_metadata_heap and .llext_ext_heap if
:kconfig:option:CONFIG_LLEXT_HEAP_MEMBLK is selected) are placed alongside
.noinit sections in the file
:file:include/zephyr/linker/common-noinit.ld. If none of your linker scripts
include this file, you will need to place the non-Harvard LLEXT heap sections
manually. One way to do this is by including :file:snippets-noinit.ld in
your linker script after your .noinit sections.
.. code-block:: none
/* Located in generated directory. This file is populated by the * zephyr_linker_sources() CMake function. */ #include <snippets-noinit.ld>
Add the file as a linker source in your board, SoC, or architecture
:file:CMakeFiles.txt.
.. code-block:: cmake
zephyr_linker_sources(NOINIT snippets-noinit.ld)
Then create a file in the same directory as your :file:CMakeFiles.txt named
:file:noinit.ld.
.. code-block:: none
#ifdef CONFIG_LLEXT *(.llext_heap) *(.llext_ext_heap) (.llext_metadata_heap) #endif / CONFIG_LLEXT */
For ARC, the Harvard instruction and data heap sections (.llext_instr_heap
and .llext_data_heap) are placed in instruction and data memory at the
architecture level. If you are using a non-ARC board with a Harvard
architecture, you will need to manually place .llext_instr_heap and
.llext_data_heap.
.. warning::
LLEXT will be unable to load extensions if the instruction memory
.llext_instr_heap is placed in is not writable at the time the
extensions are loaded and linked.
Placements can also be specified, or default placements overridden, by providing a custom linker script.
:kconfig:option:CONFIG_CUSTOM_LINKER_SCRIPT
Path to the linker script to be used instead of the one defined by the
board.
The linker script must be based on a version provided by Zephyr since
the kernel can expect a certain layout/certain regions.
This is useful when an application needs to add sections into the
linker script and avoid having to change the script provided by
Zephyr.
.. _llext_kconfig_type:
The LLEXT subsystem supports loading different types of extensions; the type can be set by choosing among the following Kconfig options:
:kconfig:option:CONFIG_LLEXT_TYPE_ELF_OBJECT
Build and expect relocatable files as binary object type for the LLEXT
subsystem. A single compiler invocation is used to generate the object
file.
:kconfig:option:CONFIG_LLEXT_TYPE_ELF_RELOCATABLE
Build and expect relocatable (partially linked) files as the binary
object type for the LLEXT subsystem. These object files are generated
by the linker by combining multiple object files into a single one.
:kconfig:option:CONFIG_LLEXT_TYPE_ELF_SHAREDLIB
Build and expect shared libraries as binary object type for the LLEXT
subsystem. The standard linking process is used to generate the shared
library from multiple object files.
.. note::
This is not currently supported on ARM architectures.
.. _llext_kconfig_storage:
The LLEXT subsystem loading mechanism, by default, uses a seek/read abstraction and copies all data into allocated memory; this is done to allow the extension to be loaded from any storage medium. Sometimes, however, data is already in a buffer in RAM and copying it is not necessary. The following option allows the LLEXT subsystem to optimize memory footprint in this case.
:kconfig:option:CONFIG_LLEXT_STORAGE_WRITABLE
Allow the extension to be loaded by directly referencing section data
into the ELF buffer. To be effective, this requires the use of an ELF
loader that supports the ``peek`` functionality, such as the
:c:struct:`llext_buf_loader`.
.. warning::
The application must ensure that the buffer used to load the
extension remains allocated until the extension is unloaded.
.. note::
This will directly modify the contents of the buffer during the link
phase. Once the extension is unloaded, the buffer must be reloaded
before it can be used again in a call to :c:func:`llext_load`.
.. note::
This is currently required by the Xtensa architecture. Further
information on this topic is available on GitHub issue `#75341
<https://github.com/zephyrproject-rtos/zephyr/issues/75341>`_.
.. _llext_symbol_groups:
All LLEXT symbols belong to a group, with the inclusion of each group in the
exported symbol table controlled by a corresponding Kconfig symbol. Exporting
a symbol as part of a group is done with the :c:macro:EXPORT_GROUP_SYMBOL
and :c:macro:EXPORT_GROUP_SYMBOL_NAMED macros. For example the following
exports the symbol memcpy as part of the LIBC group:
.. code:: c
EXPORT_GROUP_SYMBOL(LIBC, memcpy);
Group names are arbitrary, but they must be all uppercase. For each group used in C code, there MUST be a corresponding Kconfig symbol of the form:
.. code::
config LLEXT_EXPORT_SYMBOL_GROUP_{GROUP_NAME} bool "Export all symbols from the {GROUP_NAME} group"
The default group for symbols (those declared with :c:macro:EXPORT_SYMBOL
or :c:macro:EXPORT_SYMBOL_NAMED) is the UNASSIGNED group. As per the
above rules, the inclusion of this group is controlled by
:kconfig:option:CONFIG_LLEXT_EXPORT_SYMBOL_GROUP_UNASSIGNED.
The groups currently defined by Zephyr are:
.. csv-table:: Zephyr LLEXT symbol groups :header: Group Name, Kconfig Symbol, Description
UNASSIGNED, :kconfig:option:CONFIG_LLEXT_EXPORT_SYMBOL_GROUP_UNASSIGNED, Symbols without an explicit group
SYSCALL, :kconfig:option:CONFIG_LLEXT_EXPORT_SYMBOL_GROUP_SYSCALL, Zephyr kernel system calls
LIBC, :kconfig:option:CONFIG_LLEXT_EXPORT_SYMBOL_GROUP_LIBC, C standard library functions (:c:func:memcpy etc)
DEVICE, :kconfig:option:CONFIG_LLEXT_EXPORT_SYMBOL_GROUP_DEVICE, Devicetree devices
.. _llext_kconfig_slid:
When an extension is loaded, the LLEXT subsystem must find the address of all the symbols residing in the main application that the extension references. To this end, the main binary contains a LLEXT-dedicated symbol table, filled with one symbol-name-to-address mapping entry for each symbol exported by the main application to extensions. This table can then be searched into by the LLEXT linker at extension load time. This process is pretty slow due to the nature of string comparisons, and the size consumed by the table can become significant as the number of exported symbols increases.
:kconfig:option:CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID
Perform an extra processing step on the Zephyr binary and on all
extensions being built, converting every string in the symbol tables to
a pointer-sized hash called Symbol Link Identifier (SLID), which is
stored in the binary.
This speeds up the symbol lookup process by allowing usage of
integer-based comparisons rather than string-based ones. Another
benefit of SLID-based linking is that storing symbol names in the
binary is no longer necessary, which provides a significant decrease in
symbol table size.
.. note::
This option is not currently compatible with the :ref:`LLEXT EDK
<llext_build_edk>`.
.. note::
Using a different value for this option in the main binary and in
extensions is not supported. For example, if the main application
is built with ``CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y``, it is
forbidden to load an extension that was compiled with
``CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=n``.
Options influencing the generation and behavior of the LLEXT EDK are described
in :ref:llext_kconfig_edk.