Skip to content

Commit

Permalink
developer-guide: add LLEXT module documentation
Browse files Browse the repository at this point in the history
Describe LLEXT loadable module support in SOF.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
  • Loading branch information
lyakh authored and lgirdwood committed Sep 13, 2024
1 parent d382e2c commit 8c2a968
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
1 change: 1 addition & 0 deletions developer_guides/firmware/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ Developer guides and information for firmware development.
porting
cmake
async_messaging_best_practices
llext_modules
108 changes: 108 additions & 0 deletions developer_guides/firmware/llext_modules.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
.. _llext_modules:

LLEXT Modules
#############

|SOF| support for loadable modules, using Zephyr LLEXT API.

Zephyr LLEXT API
****************

Please refer to https://docs.zephyrproject.org/latest/services/llext/index.html
for detailed documentation. In short, the Zephyr Linkable Loadable Extensions
(LLEXT) API implements support for run-time loading and unloading of ELF-format
executable code and data.

SOF use of the LLEXT API
************************

SOF has multiple ways to implement loadable modules. LLEXT is one of them.
With it modules are built as shared or relocatable ELF objects with an addition
of a cryptographic signature, using any user-supplied key, and a manifest. When
loaded and instantiated, Zephyr LLEXT functionality is used to dynamically
resolve module internal as well as SOF and Zephyr external code and data
references. In the future support for inter-module linking will be added.

Accessing the base firmware from LLEXT modules
**********************************************

LLEXT modules can access all code and data from the base firmware exported,
using the ``EXPORT_SYMBOL()`` macro. Therefore writing LLEXT modules isn't very
different from built-in ones.

Implementing LLEXT modules
**************************

At the moment only modules, implementing the Module Adapter API
:ref:`apps-comp-world` are supported.

.. _multiple-adapter-modules:

It is possible to implement multiple Module Adapter modules with a common code
base, i.e. sharing a set of source files and functions. Then a single LLEXT
object would be created, implementing multiple Module Adapter interfaces. In
that case an array of ``struct sof_module_api_build_info`` objects is needed and
the TOML file should contain those multiple module entries too.
src/audio/mixin_mixout/mixin_mixout.c is an example of such a case.

As explained above, LLEXT modules in general look very similar to native SOF
code, with the only restriction of having no access to not-exported symbols.

LLEXT modules should also contain a ``.buildinfo`` section, containing a
``struct sof_module_api_build_info`` object and a ``.module`` section,
containing a ``struct sof_man_module_manifest`` object. The latter should also
contain a pointer to a module entry point function, returning a pointer to the
module's ``struct module_interface`` instance. All these additions can be
performed, using ``SOF_LLEXT_MOD_ENTRY()``, ``SOF_LLEXT_MODULE_MANIFEST()`` and
``SOF_LLEXT_BUILDINFO`` helper macros. See src/audio/eq_iir/eq_iir.c for an
example.

A TOML configuration file is needed for building of LLEXT modules too. It is
generated by the C preprocessor at build time from the same components, as would
be used for a monolithic build. For this preprocessor run a small header file is
added. It mostly just includes ``platform.toml`` and ``${module}.toml``, similar
to src/samples/audio/smart_amp_test_llext/llext.toml.h.

Finally an additional CMakeLists.txt is needed similar to
src/samples/audio/smart_amp_test_llext/CMakeLists.txt. It contains a single call
to ``sof_llext_build()``, which is an SOF helper function, using Zephyr LLEXT
cmake support by calling ``add_llext_target()`` and ``add_llext_command()``.

With that in place, it is also possible to switch between monolithic and modular
builds by specifying the module as "tristate" in its Kconfig and selecting "m"
for modular builds. Note, that it is possible to implement third party Module
Adapter drivers, that would be built exclusively as loadable modules. Such
modules don't have to use "tristate" in their Kconfig entries.

Installation
************

As specified in
:ref:`Firmware look-up paths per Intel platform <intel_firmware_paths>`
the |SOF| Linux kernel driver loads SOF modules by their UUIDs,
specified in the topology. For SOF in-tree modules the process of creation and
installation of modules in a deployment tree is automated by the
xtensa-build-zephyr.py script. It copies modules to the deployment tree as
files with a "llext" extension and creates symbolic links to them named as
``${UUID}.bin``. E.g.

.. code-block:: cfg
B36EE4DA-006F-47F9-A06D-FECBE2D8B6CE.bin -> drc.llext
Note, that as described :ref:`above <multiple-adapter-modules>` multiple UUIDs
can be associated with a single module, in such cases multiple symbolic links
will be created, e.g.

.. code-block:: cfg
39656EB2-3B71-4049-8D3F-F92CD5C43C09.bin -> mixin_mixout.llext
3C56505A-24D7-418F-BDDC-C1F5A3AC2AE0.bin -> mixin_mixout.llext
See :ref:`apps-component-overview` for more information on UUID use by SOF
component and module adapter drivers.

It is also possible to avoid using the script by running ``west build`` to build
an SOF image and any modules, then using the cross-compiler to preprocess TOML
files and finally by running rimage to sign them. This would generate the same
result but figuring out all the command-line arguments would be rather difficult.
1 change: 1 addition & 0 deletions getting_started/intel_debug/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ configuration issue.

Linux SOF will look up firmware files at the following paths:

.. _intel_firmware_paths:
.. list-table:: Firmware look-up paths per Intel platform
:widths: 55 5 50 25
:header-rows: 1
Expand Down

0 comments on commit 8c2a968

Please sign in to comment.