-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
loadable modules: add support for loading modules on Xtensa #62433
Conversation
I've worked on incorporating the EXPORT_SYMBOL work from this PR, which was great. I've reused some existing macros/linker scripts that are useful beyond just ace to do that. Iterable sections and common-ram.ld for now. So same general idea but slight variation on how its implemented. Ideally in the base image the symbol table would be const and placed in rom for most systems, and in loadable modules perhaps a custom linker section could be constructed and then imported to determine which symbols are actually intentionally exported as opposed to the ones marked extern as I've done so far. For loadable modules we likely want the symbol table to be still placed in RAM so that it can be updated on relocation. I don't think generally we can rely on module_peek though. When memory is allocated for a loadable module, on MMU systems especially though also for MPU systems, we likely need to setup some memory permissions (e.g. RO, RW, RX) for the various sections and I don't think its enough to simply point at an arbitrary address in the ELF stream to do that. So module_peek is unlikely to make it in without maybe some pre-defined page aligned sections making the elf stream potentially much bigger than it needs to be. I could be wrong though, and please correct me if so! |
@teburd I thought it would be a bit controversial. But so far I see only one implementation of module operations in your PR - one for buffers. And in it your |
So just to clarify my thinking here... and put into github our conversation a bit Not all streams will come from memory that can be mapped into an addressable space, its very likely some elfs will come from off-chip flash that can be read from and copied out but not mapped. At the same time I completely agree that if you have memory that can be directly mapped, and you happen to have an elf file that is padded and aligned appropriately... as is I believe your case, it should be entirely supported to directly map the elf. In the buffer case, its pretty lame that there's allocations for things like elf headers and section headers when its... right there and can be pointed at. So to support all of these cases I think a little bit of rethinking on the module stream interface is needed to support it. Basic idea would be to modify module_stream_read to take... the stream, memory kind (rx, ro, rw, metadata), and length to read as parameters, while returning a void *. e.g. void* module_read(struct module_stream *ms, enum module_mem_kind *mk, size_t sz); The stream itself can be the allocator then when it needs to be, or it can simply pass back a pointer into the elf. And since the stream API is overrideable it means any of the above scenarios is easily dealt with, leaving the load and link functions to do what the need to without worrying about it or having branching all over the place. This is likely worth doing after the initial PR though as the initial PR is already quite close and mostly needs one other architecture to work imo. |
As also just discussed offline, internal allocation is difficult because it's unknown when to free that memory. I think we need an additional memory pointer for the call. The caller will provide a buffer - be it allocated, on stack or static. And if the caller knows, that they can peek at the image, they'll supply Otherwise this version now works both with twister with the added here Xtensa ELF object, and with SOF. |
Zephyr PR zephyrproject-rtos/zephyr#62433 is the counterpart to this work. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
59d326b
to
43be0a5
Compare
Zephyr PR zephyrproject-rtos/zephyr#62433 is the counterpart to this work. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
e38866f
to
a4472f8
Compare
Zephyr PR zephyrproject-rtos/zephyr#62433 is the counterpart to this work. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Zephyr PR zephyrproject-rtos/zephyr#62433 is the counterpart to this work. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Zephyr PR zephyrproject-rtos/zephyr#62433 is the counterpart to this work. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Zephyr PR zephyrproject-rtos/zephyr#62433 is the counterpart to this work. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This now temporarily includes #64381 until it's merged |
This is an interesting failure "Illegal use of the EPSR" https://github.com/zephyrproject-rtos/zephyr/actions/runs/6665109962/job/18114283475?pr=62433 @teburd any ideas? |
This failure only happens on Cortex M3 and it's introduced by dbd17fa i.e. by the commit, that switches from copying ELF sections to using them in their existing buffers. Other tested ARM architectures work with that configuration, only Cortex M3 has a problem with it. |
Maybe alignment related? It might be worth trying to break this PR up a bit into some small PRs that get merged incrementally. PLT/GOT support with -fPIC, xtensa support, and maybe lastly the peek + copy-free usage perhaps? |
@teburd can we do it in a different order - first add |
7d8ce76
to
36a50b9
Compare
None on my end, but there may be a couple of still relevant compliance issues. Likely the EXPORT_SYMBOL() warnings can be ignored. |
Add support for running a modular "Hello world" example on Xtensa. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Loadable modules can contain global (not "static") functions, even if they aren't exported for use by other modules, e.g. when a module is built from multiple .c files. Such functions are then also included in link tables and have to be re-linked. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Extend the llext_load() / llext_unload() API to let it be called repeatedly for the same extension to increment or decrement its reference counter respectively. We use a mutex to protect the counter and make both llext_load() and llext_unload() return the use-count to let the caller identify when the first loading and the last unloading took place. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
If a function fails it should release all the resources it has managed to acquire. Fix llext_load() to free memory that it has allocated in case of an error. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Extensions should be able to selectively export their global symbols. Add a LL_EXTENSION_SYMBOL() macro for that. Change the present .sym_tab to be a temporary symbol table of all global symbols in an extensions, used only during linking for internal purposes. Add a new .exp_tab symbol table to store symbols, exported by an extension permanently. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Use an element size explicitly when calculating the array size and use the calculated size for memset(). Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
The llext list should be internal to llext.c, remove its scanning from shell.c, export a function for that instead. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
llext_list() is an exported function that returns a pointer to the llext internal extension list. That list should only be accessible directly inside llext, while holding a lock. Remove the function. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
a new llext object is completely initialised with zeros after allocation, no need to additionally set members of an embedded into it array to NULL. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Use an existing mutex to also protect the global llext list. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
When using the LLEXT buffer loader we now avoid copying extensions from storage to allocated memory by pointing directly into the stored image. We then also perform linking and relocation in that memory, which modifies its contents. However, this is impossible if that storage is read-only. Add a Kconfig flag to distinguish between writable and read-only storage types. Also use that flag to decide, whether the extension image in test_llext_simple.c should be defined as const or not. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
@cfriedt I cleaned up a couple of checkpatch / compliance failures, the rest are false positives: |
Zephyr PR zephyrproject-rtos/zephyr#62433 is the counterpart to this work. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Zephyr PR zephyrproject-rtos/zephyr#62433 is the counterpart to this work. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might need a few CI checks fixed, let me look, but approved
overriding checkpatch as false negatives. |
Zephyr PR zephyrproject-rtos/zephyr#62433 is the counterpart to this work. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Zephyr PR zephyrproject-rtos/zephyr#62433 introduced updates, needed for SOF, update to a version, containing it. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Zephyr PR zephyrproject-rtos/zephyr#62433 introduced updates, needed for SOF, update to a version, containing it. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This is based on an earlier version of #57086 . The latter has a few more commits now, but the final state isn't very different from my snapshot - @teburd has fixed a couple of bugs that I also found and fixed in this PR, added support for some ARM specific features, and started work on Xtensa relocation code, which isn't used here yet. So far this code can load shared objects, built as PIC, which don't need relocation. This is still WiP, I expect comments, fixes, and a couple more iterations of this.