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 committed Apr 11, 2024
1 parent 97e7339 commit b49ef79
Show file tree
Hide file tree
Showing 2 changed files with 79 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
78 changes: 78 additions & 0 deletions developer_guides/firmware/llext_modules.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
.. _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 and a manifest. When loaded and instantiated,
Zephyr LLEXT functionality is used to dynamically resolve module internal as
well as SOF 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.

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. If
any such symbols are needed to LLEXT modules, additionally exporting them can be
considered.

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. See
src/samples/audio/smart_amp_test_ipc4.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. A small additional file to bring components
together is needed too, 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. Currently it contains a
lot of open-coded instructions, later it will be ported to use Zephyr's
``add_llext_target()`` function.

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, however, for modules, exclusively built as LLEXT objects,
this might not be necessary. Thus it is possible to implement third party Module
Adapter drivers, that would be built exclusively as loadable modules.

Note, that a single LLEXT object file can also contain multiple Module Adapter
modules. 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.

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

As described in :ref:`intel_debug_introduction` the |SOF| Linux kernel driver
loads SOF modules, using their UUIDs. For SOF internal modules the process
of creation and installation of modules in a deployment tree is automated by the
xtensa-build-zephyr.py script.

0 comments on commit b49ef79

Please sign in to comment.