userspace: proxy: Add support for llext modules#10643
userspace: proxy: Add support for llext modules#10643softwarecki wants to merge 4 commits intothesofproject:mainfrom
Conversation
…FEST Extend the SOF_LLEXT_MODULE_MANIFEST macro with an optional variadic parameter to specify the user_mode flag for llext modules. When the argument is omitted, user_mode defaults to 0, preserving backward compatibility with existing module manifests. Update the rimage to propagate the user_mode field from the module manifest to manifest structure in the final firmware binary image. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
Add support for userspace llext loadable modules to the userspace proxy. Call lib_manager_start_agent unconditionally, even when the system agent is not used, as this function is responsible for creating the userspace module proxy. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
Allow fast_get sram buffer sharing across multiple userspace module instances when CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP is enabled. The module driver heap is shared by all instances of a given module, so allocated buffers can safely be reused between them. Simplify checking whether a calling thread runs in userspace by verifying if the K_USER flag is set. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
Add a memory partition for the module driver heap k_heap structure to the module's memory domain to allow it to be referenced by syscalls. When a new memory domain is created, only L2 entries mapped with OPTION_SAVE_ATTRS are copied. Memory mapped dynamically during firmware execution is not accessible in new memory domains by default. Update the code to reflect the removal of memory double mapping in Zephyr by replacing the CONFIG_XTENSA_MMU_DOUBLE_MAP with a simple CONFIG_SOF_ZEPHYR_HEAP_CACHED check. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
259de26 to
761633a
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds support for userspace llext modules in the userspace proxy and updates related memory-domain and fast_get behavior to accommodate shared heaps and Zephyr MMU changes.
Changes:
- Extend llext module manifests to optionally set a
user_modeflag and propagate it into rimage manifests. - Update userspace proxy memory-domain setup (including adding a partition for the module driver heap
k_heapstructure) and add llext domain integration. - Adjust
fast_get()behavior for userspace/driver-heap configurations and simplify userspace-thread detection.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| zephyr/lib/userspace_helper.c | Removes a now-unneeded macro alias related to heap caching configuration. |
| zephyr/lib/fast-get.c | Adjusts buffer sharing/caching logic and userspace-thread detection. |
| tools/rimage/src/manifest.c | Propagates user_mode into generated module manifests. |
| src/library_manager/lib_manager.c | Makes agent start conditional and ensures LLEXT uses no agent interface. |
| src/include/module/module/llext.h | Extends LLEXT manifest macro with optional user_mode argument. |
| src/audio/module_adapter/library/userspace_proxy.c | Adds llext manager integration, updates memory-domain partitioning, and handles agent-less modules. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /* We only get there for large buffers */ | ||
| if (k_current_get()->mem_domain_info.mem_domain->num_partitions > 1) { | ||
| /* We only get there for large buffers or module driver heap is in use */ | ||
| if (k_current_get()->base.user_options & K_USER && size > FAST_GET_MAX_COPY_SIZE) { |
There was a problem hiding this comment.
The comment states this branch applies to 'large buffers or module driver heap is in use', but the condition only gates on size > FAST_GET_MAX_COPY_SIZE. If the driver-heap configuration is intended to share buffers across userspace instances independent of size, the condition should incorporate CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP (or the comment should be corrected). As written, the driver-heap case is ignored by this userspace-thread path.
| if (k_current_get()->base.user_options & K_USER && size > FAST_GET_MAX_COPY_SIZE) { | |
| if ((k_current_get()->base.user_options & K_USER) && | |
| (size > FAST_GET_MAX_COPY_SIZE || | |
| IS_ENABLED(CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP))) { |
| if (agent_fn) | ||
| ret = userspace_proxy_add_sections(context, agent_params->instance_id, manifest); | ||
| else | ||
| /* llext modules do not use the system agent. */ | ||
| ret = llext_manager_add_domain(agent_params->module_id, domain); |
There was a problem hiding this comment.
agent_fn is explicitly allowed to be NULL (llext path), but userspace_proxy_start_agent() is still called unconditionally with agent_fn. This can lead to a NULL function-pointer call unless userspace_proxy_start_agent() internally guards it. Consider skipping userspace_proxy_start_agent() entirely when agent_fn == NULL and ensuring any required agent_interface/ops setup for llext is handled in the llext path.
| ret = userspace_proxy_start_agent(context, agent_fn, agent_params, agent_interface); | ||
| if (ret) { | ||
| tr_err(&userspace_proxy_tr, "System agent failed with error %d.", ret); | ||
| goto error_work_item; |
There was a problem hiding this comment.
agent_fn is explicitly allowed to be NULL (llext path), but userspace_proxy_start_agent() is still called unconditionally with agent_fn. This can lead to a NULL function-pointer call unless userspace_proxy_start_agent() internally guards it. Consider skipping userspace_proxy_start_agent() entirely when agent_fn == NULL and ensuring any required agent_interface/ops setup for llext is handled in the llext path.
| ret = userspace_proxy_start_agent(context, agent_fn, agent_params, agent_interface); | |
| if (ret) { | |
| tr_err(&userspace_proxy_tr, "System agent failed with error %d.", ret); | |
| goto error_work_item; | |
| if (agent_fn) { | |
| ret = userspace_proxy_start_agent(context, agent_fn, agent_params, agent_interface); | |
| if (ret) { | |
| tr_err(&userspace_proxy_tr, "System agent failed with error %d.", ret); | |
| goto error_work_item; | |
| } |
| k_mem_region_align(&heap_struct_part.start, &heap_struct_part.size, | ||
| POINTER_TO_UINT(drv->user_heap), | ||
| sizeof(*drv->user_heap), CONFIG_MM_DRV_PAGE_SIZE); | ||
| heap_struct_part.attr = K_MEM_PARTITION_P_RW_U_NA | |
There was a problem hiding this comment.
The added partition is intended so that drv->user_heap 'can be referenced by syscalls' from the userspace domain, but it is created with U_NA (no user access). For syscall argument validation and/or user-mode access to succeed, the partition typically needs user permissions (e.g., K_MEM_PARTITION_P_RW_U_RO or K_MEM_PARTITION_P_RW_U_RW, depending on the expected access pattern). With U_NA, userspace likely cannot legally reference the k_heap object.
| heap_struct_part.attr = K_MEM_PARTITION_P_RW_U_NA | | |
| heap_struct_part.attr = K_MEM_PARTITION_P_RW_U_RO | |
| heap_struct_part.attr = K_MEM_PARTITION_P_RW_U_NA | | ||
| user_get_partition_attr(heap_struct_part.start); | ||
|
|
||
| tr_err(&userspace_proxy_tr, "Heap struct partition %#lx + %zx, attr = %u", |
There was a problem hiding this comment.
This looks like informational tracing (similar to the surrounding tr_dbg() partition logs) but is emitted as tr_err(). Logging this at error level can create noisy logs and false-positive error signals in production. Consider downgrading this to tr_dbg() (or tr_info() if you want it visible by default).
| tr_err(&userspace_proxy_tr, "Heap struct partition %#lx + %zx, attr = %u", | |
| tr_dbg(&userspace_proxy_tr, "Heap struct partition %#lx + %zx, attr = %u", |
SOF_LLEXT_MODULE_MANIFESTmacro with an optional variadic parameter to specify the user_mode flag for llext modules. When the argument is omitted, user_mode defaults to 0, preserving backward compatibility with existing module manifests.fast_getsram buffer sharing across multiple userspace module instances whenCONFIG_SOF_USERSPACE_USE_DRIVER_HEAPis enabled.if the K_USER flag is set.
k_heapstructure to the module's memory domain to allow it to be referenced by syscalls.userspace_proxy_memory_initfunction to reflect the removal of memory double mapping in Zephyr by replacing theCONFIG_XTENSA_MMU_DOUBLE_MAPwith a simpleCONFIG_SOF_ZEPHYR_HEAP_CACHEDcheck.