[Userspace LL] scattered commits from #10945 without dependencies - #11065
[Userspace LL] scattered commits from #10945 without dependencies#11065lyakh wants to merge 12 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR cherry-picks a set of userspace-LL–related changes (from #10945) to support userspace low-latency scheduling, including userspace-safe module allocation/freeing paths and memory-domain handling for dynamically loaded modules and DP vregion-backed allocations.
Changes:
- Extend module/vregion allocation plumbing to track vregion address/size and (when CONFIG_SOF_USERSPACE_LL) map/unmap vregion memory into the LL memory domain via syscalls.
- Update library manager + LLEXT manager to better integrate with Zephyr userspace (syscall for module free, LL domain integration, DP-domain exceptions).
- Refactor IPC user thread creation to allocate kernel objects dynamically and improve multi-pipeline state handling safety.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| zephyr/include/rtos/alloc.h | Extends mod_alloc_ctx with vregion base/size for domain mapping/unmapping. |
| zephyr/CMakeLists.txt | Adds lib_manager.h to Zephyr syscall header generation. |
| src/schedule/zephyr_dp_schedule.c | Moves scheduler state allocation to heap allocator and ensures ops struct is in sysuser data. |
| src/library_manager/llext_manager.c | Adds LL-domain mapping logic and refactors module-domain add/remove internals. |
| src/library_manager/lib_manager.c | Introduces syscall-backed module free and refactors module create/free helper paths. |
| src/ipc/ipc4/helper.c | Tightens pointer types used for IPC payload parsing (unsigned char *). |
| src/ipc/ipc4/handler-user.c | Extracts pipeline ID parsing and adds mailbox bounds checks for multi-pipeline IPC. |
| src/ipc/ipc-helper.c | Adjusts locking path for userspace LL builds (avoid unused IRQ flags). |
| src/ipc/ipc-common.c | Refactors IPC userspace thread creation to use dynamically allocated kernel objects. |
| src/include/sof/lib_manager.h | Adds syscall declaration and exposes lib_manager_mod_create_priv() helper. |
| src/include/sof/audio/module_adapter/module/generic.h | Adds syscalls for vregion creation/unmapping and exports vregion-free helper. |
| src/include/sof/audio/component.h | Adds uid_cp storage to keep stable UUID backing for LLEXT module drivers. |
| src/audio/module_adapter/module_adapter.c | Implements vregion syscalls, LL-domain partition mapping/unmapping, and unified vregion free helper. |
| src/audio/buffers/comp_buffer.c | Switches vregion-backed buffer teardown to the new module_adapter_vreg_free() helper. |
Suppressed comments (3)
src/ipc/ipc4/handler-user.c:460
dcache_invalidate_region()is invalidatingcntentries of auint32_tarray, but usessizeof(int) * cnt. This is the wrong element size and can under/over-invalidate depending on platform type sizes.
dcache_invalidate_region((__sparse_force void __sparse_cache *)ppl_data->ppl_id,
sizeof(int) * cnt);
src/ipc/ipc4/handler-user.c:498
- When there is a single pipeline,
ppl_id = &id;points aconst uint32_t *at anint. This is a type/size mismatch and can lead to incorrectppl_id[i]values when iterating.
if (ppl_count == 1)
ppl_id = &id;
src/audio/module_adapter/module_adapter.c:154
vreg_startandvreg_sizeare uninitialized when the vregion path is not taken, but are still copied intoalloc. Even if currently unused whenalloc->vreg == NULL, this is undefined/indeterminate data and can trigger compiler or static-analysis warnings.
size_t vreg_size;
uintptr_t vreg_start;
Extract a privileged LLEXT-related part from lib_manager_module_create() into a separate function to be called from kernel context. At the same time lib_manager_mod_free_priv() already executes privileged operations, to make it callable in userspace convert lib_manager_free_module() to a system call. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
When CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP isn't selected, dynamically allocated driver objects should still be accessible to the userspace. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
When loading and linking LLEXT modules map them automatically for the LL memory domain, unless they belong to the DP domain. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Prepare for multi-core support: allocate the IPC thread dynamically and extract thread initialisation into a separate function. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Userspace IPC context is global, allocate it uncached. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
The SOF_IPC4_GLB_SET_PIPELINE_STATE IPC can apply to one or to multiple pipelines. Extract pipeline ID detection into a function to be re-used with userspace IPC processing. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Add two syscall functions to allocate and map, and to unmap vregion for userspace modules. For now only used for DP modules. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
DP scheduler operations, instance data and DP module memory have to be accessible to the userspace LL scheduler. Allocate dynamic data on the userspace heap and place static data in the userspace accessible ELF section. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Fix an "unused variable" compiler warning for when buildins with CONFIG_SOF_USERSPACE_LL=y. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Change several pointers from "char *" to "unsigned char *" to reduce the number of type-casts. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
The .uid field in struct comp_driver is used for driver identification using its unique UUID. However with LLEXT that UUID is located in DRAM, which makes access to it difficult from userspace threads. Make a local copy of it instead for reliable driver searching from different contexts. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Add a check to llext_manager_mod_find() in case scanning the array reached the last element, that the index indeed is within that element's range. Return an error otherwise. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
|
|
||
| static int z_vrfy_lib_manager_free_module(const uint32_t component_id) | ||
| { | ||
| return z_impl_lib_manager_free_module(component_id); |
There was a problem hiding this comment.
Isn't this too unsafe? Any user-space code (including non-privileged DP module can free a module)?
| { | ||
| K_OOPS(K_SYSCALL_MEMORY_WRITE(vreg_start, sizeof(*vreg_start))); | ||
| K_OOPS(K_SYSCALL_MEMORY_WRITE(vreg_size, sizeof(*vreg_size))); | ||
| K_OOPS(K_SYSCALL_MEMORY_READ(config, sizeof(*config))); |
There was a problem hiding this comment.
Minor: syscall should do a copy of config to protect against user-space modifying the config when kernel code is using the struct. Not really an issue yet as "config" is unused for now, but could be an issue later if config desribes the size of allocation needed and kernel needs to verify valid config parameters. To prepare for this case, a copy should be made of config (or at least a visible TODO/FIXME).
various commits from #10945 without unmerged dependencies