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: run non-performance critical code in DRAM #9522

Merged
merged 9 commits into from
Nov 27, 2024

Conversation

lyakh
Copy link
Collaborator

@lyakh lyakh commented Sep 27, 2024

very raw, still work in progress, not fully functional
update: working so far, might still need to improve the API

void *drc_who_called(void)
{
return my_addr();
//return __builtin_return_address(0);
Copy link
Member

Choose a reason for hiding this comment

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

out of interest, why wont the builtin work ? Its not relying on linker script to set address is it ?

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 good question, I don't have an answer to it yet, it's still under investigation.

Copy link
Member

Choose a reason for hiding this comment

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

builtin is probably set at build time now. I would bet that this is a relocatable ELF object, maybe with a different type/id that we have to fixup at runtime link time.

@@ -138,6 +139,7 @@ static int drc_setup(struct drc_comp_data *cd, uint16_t channels, uint32_t rate)
* End of DRC setup code. Next the standard component methods.
*/

__sof_llext_dram_text(CONFIG_COMP_DRC_MODULE)
Copy link
Member

Choose a reason for hiding this comment

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

Btw, - this should be something small and simple that should complie in/out based on Kconfig in the definition. e.g.
__cold static int drc_init(struct processing_module *mod)

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 the name can be changed of course, and sure, it resolves to nothing with suitable Kconfig, but it has to depend on the respective Kconfig option. Effectively what it does is

#if CONFIG_COMP_X_MODULE
__section(".text.dram")
#endif

so in each module it needs to know which Kconfig option to depend upon. I also made it explicit, that it's a SOF macro, it only works with LLEXT, and this one is for functions, not for data. The easiest would be to have two different macros for functions and for data. And "cold" sounds like it can be applied to either. I'm not sure we can resolve automatically at build time data from code.

Copy link
Member

Choose a reason for hiding this comment

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

It needs to be short and sweet, keep the CONFIG part in the header. It should be one word. e.g. Linux uses __init for initialization sections.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It needs to be short and sweet, keep the CONFIG part in the header. It should be one word. e.g. Linux uses __init for initialization sections.

@lgirdwood but you'd need such a macro for each component. And some components might not even have their own headers. So are you proposing to put something like

#if CONFIG_COMP_X_MODULE
#define __cold __section("...")
#else
#define __cold
#endif

in each component and eventually in each LLEXT-enabled source file?

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-line version is very nice!

Copy link
Member

@lgirdwood lgirdwood Nov 25, 2024

Choose a reason for hiding this comment

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

We shouldn't need per module definitions, we should be able to #include <llext_module.h (or whatever) and in that header define e.g.

#if defined (CC_SAYS_I_AM_BUILDING_A_MODULE)
#define __cold __section("...")
#else
#define __cold
#endif

This means CC needs to define this on its command line via Cmake.

@lyakh lyakh changed the title [SKIP SOF_TEST][WiP][DNM] IMR: illustrate running in IMR [WiP][DNM] IMR: illustrate running in IMR Nov 11, 2024
@lyakh
Copy link
Collaborator Author

lyakh commented Nov 11, 2024

SOFCI TEST

@lyakh lyakh marked this pull request as ready for review November 22, 2024 15:00
@lyakh lyakh changed the title [WiP][DNM] IMR: illustrate running in IMR LLEXT: run non-performance critical code in DRAM Nov 22, 2024
@cujomalainey
Copy link
Contributor

@andyross please review

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.

Looks great! Some notes inline, but nothing blocking.

* detached sections, they will be linked with addresses in this range.
*/
#define LLEXT_DRAM_LINK_START 0
#define LLEXT_DRAM_LINK_END 0x01000000
Copy link
Collaborator

Choose a reason for hiding this comment

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

This definition is now in multiple places. Kconfig or common header? Probably can be handled in a follow-up, but at least a note would be good this is a shared defintion.

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 yeah, we can try to find a place for it in an rimage header, maybe not worth adding a Kconfig for it for now at least

@@ -138,6 +139,7 @@ static int drc_setup(struct drc_comp_data *cd, uint16_t channels, uint32_t rate)
* End of DRC setup code. Next the standard component methods.
*/

__sof_llext_dram_text(CONFIG_COMP_DRC_MODULE)
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-line version is very nice!

@lyakh
Copy link
Collaborator Author

lyakh commented Nov 25, 2024

CI: LNL pause-resume and suspend bugs are known and unrelated

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.

Lets have the Cmakefile define a I_AM_BUILDING_A_MODULE macro so we can use this globally. Everything else LGTM.

Copy link
Contributor

@andyross andyross left a comment

Choose a reason for hiding this comment

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

This all looks clean to me, though I've been hiding from a lot of the llext work for complexity reasons (like, surely there's a symmetric patch to the linker script in zephyr somewhere? Or is it all handled on the linker command line?).

As far as API: I think "dram" is about as clear as it gets, but I actually personally preferred "__cold", or more generally dichotomy settings like cold/hot, fast/slow, etc... I'm as we speak about finishing up a Zephyrized MTK platform, and those devices have a lot less SRAM than Intel parts (but also rather larger instruction caches). There, it might make more sense (well, it's how I'm doing it right now) to link .text to DRAM by default, only moving known latency-sensitive[1] areas like vector handlers and ISRs as needed.

A correct decision would require a performance rig that we don't have, but "hot/cold" supports both more cleanly than "dram/sram". Not a -1, just some thoughts.

[1] Not quite the same as performance sensitive! One could imagine a highly CPU-bound compute module that sits in a tight loop and runs entirely out of icache and thus would work great in DRAM.

@lyakh
Copy link
Collaborator Author

lyakh commented Nov 26, 2024

Lets have the Cmakefile define a I_AM_BUILDING_A_MODULE macro so we can use this globally. Everything else LGTM.

@lgirdwood right, yes, this would work and indeed make it simpler. I did indeed consider it earlier, but dismissed it because using each module's CONFIG_X_MODULE option seemed rather clean to me. In fact we do already have such a macro: LL_EXTENSION_BUILD. Let me update

@lyakh
Copy link
Collaborator Author

lyakh commented Nov 26, 2024

This all looks clean to me, though I've been hiding from a lot of the llext work for complexity reasons (like, surely there's a symmetric patch to the linker script in zephyr somewhere? Or is it all handled on the linker command line?).

@andyross we don't use linker scripts for LLEXT, only command-line parameters

norm_int32() is called by LLEXT modules when built with gcc, export
it.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
Remove multiple end-of-line spaces in comments.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
With this commit functions can be marked to be placed in custom
sections, e.g. by adding __attribute__((section(".text.dram"))) to
them. Those sections will then become "detached," i.e. they won't be
linked into the main address space of the module. Instead they will
be linked at a low address, after which Zephyr LLEXT linked will
prepare them to be used at their original location, e.g. in DRAM.
This commit modifies the SOF LLEXT link helper to use low addresses
for linking of such sections.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
Re-use values from the caller instead of re-calculating them in the
function.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
The LLEXT manifest array can be accessed in DRAM, no need to
recalculate its address in SRAM.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
Rimage shouldn't include detached sections in image size calculations
to avoid creating meaninglessly large values.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
We link detached sections, to be used in DRAM, at low addresses,
beginning at 0. Add a callback for Zephyr llext to recognise our
detached sections.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
With this macro modules can use "__cold" in front of their function
definitions to place them in the .text.dram section, which will force
their execution in DRAM without being copied to SRAM.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
DRC's .init() and .free() functions aren't performance-critical,
move them to DRAM for modular builds.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
@lgirdwood
Copy link
Member

@lyakh can you check test results. Thanks !

@lyakh
Copy link
Collaborator Author

lyakh commented Nov 26, 2024

@lyakh can you check test results. Thanks !

@lgirdwood sure, being dealt with

@lyakh
Copy link
Collaborator Author

lyakh commented Nov 27, 2024

@lgirdwood QB clean now

@lgirdwood lgirdwood merged commit 40ed1e2 into thesofproject:main Nov 27, 2024
46 of 49 checks passed
@lyakh lyakh deleted the imr branch November 27, 2024 15:50
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.

5 participants