Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LLEXT multiple modules #9090

Merged
merged 9 commits into from
May 14, 2024
Merged

LLEXT multiple modules #9090

merged 9 commits into from
May 14, 2024

Conversation

lyakh
Copy link
Collaborator

@lyakh lyakh commented Apr 30, 2024

This converts two more modules: mixin-mixout and eq_iir to llext modules. This has an added complexity of mixin-mixout containing two module-adapter drivers. This PR currently contains #9013 with an expectation of that being merged soon, after which the first 7 commits will be dropped from this one.

@lyakh lyakh force-pushed the llext-multi branch 2 times, most recently from 752cbf2 to 7f78163 Compare May 2, 2024 12:50
Copy link
Member

@lgirdwood lgirdwood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just minor optimization questions.

Comment on lines 263 to 279
#if CONFIG_COMP_IIR_MODULE
/* modular: llext dynamic link */

static const struct module_interface *loadable_eq_iir_main(void *mod_cfg,
void *parent_ppl,
void **mod_ptr)
{
return &eq_iir_interface;
}

static const struct sof_man_module_manifest eq_iir_manifest __section(".module") __used = {
.module = {
.name = "EQIIR",
.uuid = {0xE6, 0xC0, 0x50, 0x51, 0xF9, 0x27, 0xC8, 0x4E,
0x83, 0x51, 0xC7, 0x05, 0xB6, 0x42, 0xD1, 0x2F},
.entry_point = (uint32_t)loadable_eq_iir_main,
.type = {
.load_type = SOF_MAN_MOD_TYPE_LLEXT,
.domain_ll = 1,
},
.affinity_mask = 1,
}
};

static const struct sof_module_api_build_info buildinfo __section(".mod_buildinfo") __used = {
.format = SOF_MODULE_API_BUILD_INFO_FORMAT,
.api_version_number.full = SOF_MODULE_API_CURRENT_VERSION,
};

#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all of this can be expressed as a single macro i.e.

SOF_DECLARE_MODULE(name, interface, uuid);

@@ -0,0 +1,99 @@
# Copyright (c) 2024 Intel Corporation.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming this file will be shrunk/replaced when Zephyr llext cmake helpers are used ?

add_llext_command(TARGET ${MODULE}
POST_BUILD
COMMAND ${SOF_BASE}scripts/llext_link_helper.py
--text-addr="0xa06ea000" -f ${proc_in_file} ${CMAKE_C_COMPILER} --
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does this address come from ? Does it need to come from platform / DT or Kconfig ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lgirdwood right, now this is a good question, let's talk about this. These address values come originally from the original loadable module concept, whereby we build modules for a fixed address in memory - I think that holds for system services too, probably for IADK as well. Having those addresses helps - it makes linking at run time easier, internal address references are already correct, but it does mean that we need to maintain those addresses somehow somewhere. The original one, that is now used for the smart-amp was exactly the address used in some old examples. Now for mixin-mixout and eq-iir I picked up some addresses "similar" to smart-amp but far enough from it... But you're right, we need to come up with a system of how to assign these addresses or maybe to aim to get rid of them completely and to perform full run-time linking / relocation instead

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the very least don't copy/paste/diverge it in every module. Define it in one place and ta-da: you can paste your explanation above in that place.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, we can have a comment today and have a per platform memory address for this in the Zephyr llext core as next steps, probably best to align with @teburd

Copy link
Contributor

@teburd teburd May 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had some ideas around this by reusing the devicetree flash partitions or something like it, which is also used by mcuboot to designate memory regions for images.

E.g. imagine a set of partitions described for fixed location modules/applications akin to this dts:
https://github.com/zephyrproject-rtos/zephyr/blob/main/boards/nxp/frdm_k64f/frdm_k64f.dts#L229

I think @dapperlo would also be interested (also using parts of llext) zephyrproject-rtos/zephyr#72258

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interested indeed. I need to ramp on the context for this use-case, but there is a desire for fixed address extensions and the load-time benefits that comes from it.

Nodes in the dts sounds reasonable, routing loaded .llext blobs could then use a label/attribute in blob header to associate.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, we can have a comment today and have a per platform memory address for this in the Zephyr llext core as next steps, probably best to align with @teburd

It isn't just per platform, it's also per module. This is the starting address of this module on this platform. So, we could have a per-platform address range for loadable modules and then per-module offsets defined in modules themselves? But that would mean some co-ordination in terms of sufficiently large offsets. I'm not sure how large is the usable address range e.g. on MTL? If it's large enough we could just dedicate an MB per module?

Alternatively: we already have TOMLs per platform that include all modules, so I'm wondering if we could add in all those locations like

#ifdef CONFIG_COMP_COPIER
#define ${MODULE}_base 0x... statements (e.g. #define smart_amp_test_base 0xa06ca000) but I'm not sure we'd be able to pull those out into cmake.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

E.g. imagine a set of partitions described for fixed location modules/applications akin to this dts:
https://github.com/zephyrproject-rtos/zephyr/blob/main/boards/nxp/frdm_k64f/frdm_k64f.dts#L229

@teburd yes, looks good, with a slight inconvenience that we now have on MTL something like 28 modules. Maybe a separate .dts, included into the main one

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no issue with toml either but I’ll need help in understanding how we piece this together. Do we need to link the extensions to be placed appropriately with a custom linker script per extension slot? Sure seems like it to me at first glance but please do correct me if wrong.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@teburd no, I tried very hard and so far have succeeded in avoiding custom linker scripts. I "only" provide section addresses to the linker on the command line. For that I only take a single base address as input and calculate all further addresses automatically.

@lyakh lyakh changed the title [PREVIEW] LLEXT multiple modules LLEXT multiple modules May 7, 2024
@lyakh lyakh marked this pull request as ready for review May 7, 2024 10:55
Copy link
Collaborator

@kv2019i kv2019i left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers really, a few comments inline.

#ifndef typeof
#define typeof __typeof__
#endif

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we have a Zephyr solution for this? We should be shrinking, not growing the sof/common.h.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could just replace all typeof() with __typeof__(), I haven't found anything global in Zephyr, they have two "local" definitions in arch/arm/include/cortex_m/cmse.h and in drivers/usb/device/usb_dc_rpi_pico.c

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kv2019i I think I'll do that - replace that patch with a switch to __typeof__() globally in SOF

-o ${MODULE}_pre.so $<TARGET_OBJECTS:${MODULE}>
COMMAND ${COPY_CMD}
COMMAND_EXPAND_LISTS
--text-addr="0xa06ca000" -f ${proc_in_file} ${CMAKE_C_COMPILER} --
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This magic address does pop out given this is no way platform specific file.

Copy link
Collaborator

@marc-hb marc-hb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CMake files are 95% copy/paste/diverge! CMake sucks but it has functions and macros. Define a new sof_add_llext() function and problem solved.

project(smart_amp_test)

SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
cmake_path(SET SOF_BASE NORMALIZE ${CMAKE_CURRENT_SOURCE_DIR}/../../../..)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The quadruple .. is quite ugly, how about ${APPLICATION_SOURCE_DIR}/.. instead?

# extract UUID value - drop the 'uuid = ' part of the assignment line
string(REGEX REPLACE "^[ \t]*uuid *= \"([0-9A-F\-]*)\"" "\\1" uuid ${line})
file(APPEND ${ZEPHYR_BINARY_DIR}/${MODULE}_llext/llext.uuid "${uuid}\n")
endforeach()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fairly complex regex, please don't copy/paste/diverge it in every module. Make this a macro or function in zephyr/CMakeLists.txt

Warning: CMake function can't "return" anything: they can only set "pseudo-return" variables. Find a very simple macro example in ef563eb

COMMAND ${CMAKE_C_COMPILER} -E ${CMAKE_CURRENT_LIST_DIR}/llext.toml.h -P -DREM=
-I${SOF_BASE} -I${SOF_BASE}src
-imacros ../include/generated/autoconf.h
-o rimage_config.toml
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one does not return anything so it is trivial to make it a shared function in zephyr/CMakeLists.txt

add_llext_command(TARGET ${MODULE}
POST_BUILD
COMMAND ${SOF_BASE}scripts/llext_link_helper.py
--text-addr="0xa06ea000" -f ${proc_in_file} ${CMAKE_C_COMPILER} --
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the very least don't copy/paste/diverge it in every module. Define it in one place and ta-da: you can paste your explanation above in that place.

Copy link
Collaborator

@marc-hb marc-hb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • suffix confusion
  • mass CMake duplication

llext_input = entry_path / (llext_base + '.so')
llext_output = entry_path / llext_file
llext_input = entry_path / (llext_base + '.llext')
llext_output = entry_path / (llext_file + '.ri')
Copy link
Collaborator

@marc-hb marc-hb May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Err... no, please don't go from .llext to .ri and then BACK to .llext where each step is a different file type; this is incredibly confusing!

One suggestion:

  1. .llext because that's what comes from Zephyr so you don't have a choice?
  2. .ri0 because that's the first rimage stage. Similar to zephyr_pre0
  3. Either .ri or .llext.ri.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marc-hb yeah, .llext -> something else -> .llext is ugly, I agree. There was a wish to have .llext as the final suffix, but now with the use of Zephyr cmake .llext comes out of those functions. Maybe yes - .llext.ri would be a good option for the final output

@marc-hb
Copy link
Collaborator

marc-hb commented May 9, 2024

I think this PR should be split in (at least) two PRs:

  1. switch to add_llext_target() and other refactoring of the single smart_amp module
  2. Additions of new modules based on 1.

lyakh added 9 commits May 10, 2024 10:32
When compiled with '-std=c99' or newer 'typeof' is unavailable and
'__typeof__' should be used instead [1].

[1] https://gcc.gnu.org/onlinedocs/gcc/Alternate-Keywords.html

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Add 3 macros to simplify LLEXT module implementation and use them in
mixin-mixout and eq_iir. Only two of them can be used in
smart_amp_test_ipc4.c so far, because it's also used for LMDK-style
module building.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Zephyr now provides a convenient cmake API for LLEXT modules, update
SOF to use it by defining common cmake functions.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
west.configuration.get() already returns a string, no need to call
'str()' on it again.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Convert mixin-mixout to a loadable llext module.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Build eq-iir as a loadable llext module.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Export additional symbols, needed for modules like eq_iir and
mixin-mixout.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
If module_adapter_new() fails in lib_manager_module_create(),
lib_manager_free_module() must be called to free allocated resources.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Some components like mixin-mixout implement multiple modules
internally.  They should be handled by LLEXT as a single ELF object,
including for use-counting. But at the SOF level they implement
multiple module adapter drivers.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
@lyakh
Copy link
Collaborator Author

lyakh commented May 10, 2024

I think this PR should be split in (at least) two PRs:

1. switch to add_llext_target() and other refactoring of the single smart_amp module

2. Additions of new modules based on 1.

@marc-hb individual commits like mixin-mixout and eq-iir have become much smaller now (and don't say you didn't ask for that), so, maybe 1 PR would be acceptable

@lyakh
Copy link
Collaborator Author

lyakh commented May 10, 2024

CI: a single alsabat failure on LNL shouldn't be related https://sof-ci.01.org/sofpr/PR9090/build4606/devicetest/index.html?model=LNLM_SDW_AIOC&testcase=check-alsabat-headset-playback-997
Checkpatch complains about existing code patterns in SOF container_of() implementation, a multi-component UUID definition and an opening curly brace on a new line. There's also one trivial typo, nothing exciting https://github.com/thesofproject/sof/actions/runs/9030070153/job/24813619935?pr=9090

@lyakh lyakh requested a review from marc-hb May 13, 2024 08:12
Copy link
Member

@lgirdwood lgirdwood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good to go, the remaining opens are all second order and can be resolved incrementally. The important thing here is to get this code to the CI devs for integration into test/build/sign services.

Copy link
Collaborator

@kv2019i kv2019i left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My comments addressed, refresh +1

@lgirdwood lgirdwood merged commit 01228bb into thesofproject:main May 14, 2024
43 of 47 checks passed
@lyakh lyakh deleted the llext-multi branch May 14, 2024 14:58
@marc-hb
Copy link
Collaborator

marc-hb commented May 15, 2024

Looks like this was merged broken:

https://github.com/thesofproject/sof/actions/runs/9030070149/job/24813622867
https://github.com/thesofproject/sof/actions/runs/9088127947

/opt/toolchains/zephyr-sdk-0.16.4/aarch64-zephyr-elf/bin/../lib/gcc/aarch64-zephyr-elf/12.2.0/../../../../aarch64-zephyr-elf/bin/ld.bfd:
modules/sof/libmodules_sof.a(numbers.c.obj):(._llext_const_symbol.static.__udivdi3_sym_+0x8): undefined reference to `__udivdi3'
collect2: error: ld returned 1 exit status

cc: @LaurentiuM1234

@lyakh
Copy link
Collaborator Author

lyakh commented May 16, 2024

Looks like this was merged broken:

https://github.com/thesofproject/sof/actions/runs/9030070149/job/24813622867 https://github.com/thesofproject/sof/actions/runs/9088127947

/opt/toolchains/zephyr-sdk-0.16.4/aarch64-zephyr-elf/bin/../lib/gcc/aarch64-zephyr-elf/12.2.0/../../../../aarch64-zephyr-elf/bin/ld.bfd:
modules/sof/libmodules_sof.a(numbers.c.obj):(._llext_const_symbol.static.__udivdi3_sym_+0x8): undefined reference to `__udivdi3'
collect2: error: ld returned 1 exit status

cc: @LaurentiuM1234

@marc-hb @LaurentiuM1234 #9130

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants