Uh oh!
There was an error while loading. Please reload this page.
[DRAFT] userspace LL/audio test PR (latest ver: V35) - #10558
Conversation
kv2019i
commented
Feb 19, 2026
Running the pipeline_two_components_user test added in this PR, on a Intel PTL, looks like this: |
9cdb1be to
37b0412Comparekv2019i
commented
Mar 9, 2026
V2 snapshot pushed:
|
37b0412 to
7317b18Comparekv2019i
commented
Mar 17, 2026
V3 snapshot pushed:
|
kv2019i
commented
Mar 17, 2026
Test output for the new test added in V3: |
| /* works? yes */ | ||
| //return 0; | ||
| printk("ipc %p\n", ipc); |
There was a problem hiding this comment.
Oops, these shouldn't be here. :)
| /* create the pipeline */ | ||
| pipe = pipeline_new(NULL, pipe_desc->primary.r.instance_id, | ||
| pipe = pipeline_new(heap, pipe_desc->primary.r.instance_id, |
There was a problem hiding this comment.
@lyakh@jsarha@lgirdwood This is where you'd plug in the vregions stuff to pass a separate heap to each pipe (based on topology description of its needs). In this series, as a placeholder, I use the zephyr_ll_user_heap() instead.
There was a problem hiding this comment.
right, maybe put a comment there for now to make re-discovery easier
lyakh
left a comment
There was a problem hiding this comment.
last reviewed commit so far "schedule: zephyr_ll: implement thread_init/free domain ops"
| #ifdef CONFIG_SOF_USERSPACE_LL | ||
| void comp_grant_access_to_thread(const struct comp_dev *dev, struct k_thread *th) | ||
| { | ||
| assert(dev->list_mutex); |
There was a problem hiding this comment.
description a bit confusing - this is only granting access to a mutex. Also list_mutex is only added to comp_dev in the next commit.
| } | ||
| stream_addr = rballoc_align(flags, size, align); | ||
| stream_addr = sof_heap_alloc(heap, flags, size, align); |
There was a problem hiding this comment.
the commit, that is mentioned in the commit message, only moved buffer context objects to particular heaps. This commit moves actual data buffers to them too, which is different and (arguably) more risky
| #define HDA_DMA_BUFFER_PERIOD_COUNT 4 | ||
| SHARED_DATA struct sof_dma dma[] = { | ||
| APP_TASK_DATA SHARED_DATA struct sof_dma dma[] = { |
There was a problem hiding this comment.
do I understand correctly, that this kind of userspace access makes that data writable to userspace?
| comp_err(dev, "requested channel %d is busy", hda_chan); | ||
| return -ENODEV; | ||
| } | ||
| hd->chan = &hd->dma->chan[channel]; |
There was a problem hiding this comment.
is this also not needed for the legacy mode? Also below
| uint64_t next_sync; | ||
| uint64_t period_in_cycles; | ||
| #endif | ||
| struct k_heap *heap; |
There was a problem hiding this comment.
wasn't this already referenced in the previous commit?
| k_spinlock_init(&dd->dai->lock); | ||
| #ifdef CONFIG_SOF_USERSPACE_LL | ||
| dd->dai->lock = k_object_alloc(K_OBJ_MUTEX); |
There was a problem hiding this comment.
check for NULL? Possibly in other locations too
| k_mutex_lock(dai->lock, K_FOREVER); | ||
| props = dai_get_properties(dai->dev, direction, stream_id); | ||
| hs_id = props->dma_hs_id; | ||
| ret = dai_get_properties_copy(dai->dev, direction, stream_id, &props); |
There was a problem hiding this comment.
I'm guessing this is made a syscall in one of the commits
| mod_heap = &mod_heap_user->heap; | ||
| } else { | ||
| #ifdef CONFIG_SOF_USERSPACE_LL | ||
| mod_heap = zephyr_ll_user_heap(); |
There was a problem hiding this comment.
looks good, but this else is entered under multiple conditions, might need to double-check
| .schedule_task_before = zephyr_ll_task_schedule_before, | ||
| .schedule_task_after = zephyr_ll_task_schedule_after, | ||
| .schedule_task_free = zephyr_ll_task_free, | ||
| .schedule_task_free = zephyr_ll_task_sched_free, |
There was a problem hiding this comment.
let's "spend" 3 more characters and make it ..._schedule_free()
| return -ENOMEM; | ||
| } | ||
| tr_err(&ll_tr, "Failed to allocate thread object for core %d", core); | ||
| dt->handler = NULL; |
| { | ||
| const struct sof_man_fw_desc *desc = basefw_vendor_get_manifest(); | ||
| const struct sof_man_module *mod; | ||
| uint32_t i; |
| uint32_t i; | ||
| if (!desc) | ||
| return -1; |
| return (int)i; | ||
| } | ||
| return -1; |
| union ipc4_connector_node_id node_id; | ||
| uint32_t dma_buffer_size; | ||
| uint32_t config_length; | ||
| } __packed __aligned(4); |
There was a problem hiding this comment.
does __aligned actually make sense in a type definition?
| pipe_msg.extension.dat = ipc_user->ipc_msg_ext; | ||
| /* Execute pipeline creation in user context */ | ||
| ipc_user->result = ipc_pipeline_new(ipc_user->ipc, (ipc_pipe_new *)&pipe_msg); |
There was a problem hiding this comment.
that's brave! ;-) I'd put a huge "TODO" here to make sure not to ship this by chance :-)
| /* create the pipeline */ | ||
| pipe = pipeline_new(NULL, pipe_desc->primary.r.instance_id, | ||
| pipe = pipeline_new(heap, pipe_desc->primary.r.instance_id, |
There was a problem hiding this comment.
right, maybe put a comment there for now to make re-discovery easier
7317b18 to
c029d49Comparekv2019i
commented
Mar 27, 2026
V4 snapshot pushed:
|
kv2019i
commented
Mar 27, 2026
Example output with V4 patchset: |
c029d49 to
9c778e4Comparekv2019i
commented
Mar 30, 2026
V5 pushed:
|
9c778e4 to
c4b127fComparekv2019i
commented
Apr 1, 2026
V6 pushed:
|
c4b127f to
ad359d6Comparekv2019i
commented
Apr 1, 2026
V7 submitted:
|
ad359d6 to
c7e9a37Comparekv2019i
commented
Apr 10, 2026
V8 submitted:
|
c7e9a37 to
8af1be4Comparekv2019i
commented
Apr 10, 2026
V9 submitted:
|
kv2019i
commented
Apr 14, 2026
V10:
|
aa5efe0 to
35a61b6CompareV11 pushed:
|
35a61b6 to
214c051Comparekv2019i
commented
Apr 15, 2026
V12 pushed:
|
kv2019i
commented
Aug 10, 2026
V32 update:
|
cpu_get_id() ultimately reads a privileged special register via arch_proc_id() (e.g. the Xtensa PRID register). When low-atency pipelines run in user-space threads (CONFIG_SOF_USERSPACE_LL), this read is issued from user mode and faults. While many direct usages of cpu_get_id() have been removed from SOF codebase, multiple usages remain. As the remaining usages are mostly on less frequently used code paths (most via cpu_is_me() call, which is used in IPC handling), opt to keep the remaining cpu_get_id() calls and make the function available as a system call. The system call machinery is gated on CONFIG_SOF_FULL_ZEPHYR_APPLICATION so unit-test builds keep the plain inline definition. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
In CONFIG_SOF_USERSPACE_LL builds the LL scheduler thread runs unprivileged, so every Zephyr kernel object it accesses must be explicitly granted to it. In commit ffa52df ("schedule: ll: dynamically allocate the semaphore"), task semaphores were converted to dynamically allocated objects. Only the bootstrap task's semaphore was granted to the LL thread (in zephyr_ll_init_context()); tasks created later (e.g. chain_dma) were not, so pausing/stopping such a task while it was running crashed the DSP. Fix the issue by grant the LL scheduling thread access to the task's semaphore at allocation time, from the syscall implementation which runs in privileged context. The task's LL scheduler is resolved via task->sch (bound in schedule_task_init() using the core-explicit user scheduler list), because zephyr_ll_domain()/cpu_get_id()-based helpers are unreliable in a syscall context: zephyr_ll_domain() reads the kernel scheduler list and returns NULL for the user-space LL scheduler. Add zephyr_domain_thread_tid_for_core() to look up the LL thread for an explicit core without relying on cpu_get_id(). Fixes: ffa52df ("schedule: ll: dynamically allocate the semaphore") Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
4832df1 to
3b87697Comparekv2019i
commented
Aug 11, 2026
V33 update:
|
3b87697 to
8c45fa2Comparekv2019i
commented
Aug 12, 2026
V34 update:
|
Place the pipeline position lookup table in the sysuser memory partition and replace k_spinlock with a dynamically allocated k_mutex when CONFIG_SOF_USERSPACE_LL is enabled. Spinlocks disable interrupts which is a privileged operation unavailable from user-mode threads. The mutex pointer is stored in a separate APP_SYSUSER_BSS variable outside the SHARED_DATA struct so Zephyr's kernel object tracking can recognize it for syscall verification. Move pipeline_posn_init() from task_main_start() to primary_core_init() before platform_init(), so the mutex is allocated before ipc_user_init() grants thread access to it. In pipeline_posn_get(), bypass the sof_get() kernel singleton and access the shared structure directly when running in user-space. Grant the ipc_user_init thread access to the pipeline position mutex via new pipeline_posn_grant_access() helper. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Use the sof_dma_get_status() wrapper to get DMA status in dai_common_position(). This allows the code to be used from user-space context. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> (cherry picked from commit ab7f6ce)
Support to run DP scheduler when LL is running in user-space is not yet complete, so disable this feature in the overlay for now. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
module_adapter_free() runs in a user-mode thread in userspace-LL mode and calls mod_free_all(). Unlike mod_free(), mod_free_all() was a plain function, so its internal sof_heap_free() calls on the module heap went through the user-mode syscall verifier, which only permits the LL user heap and K_OOPSes on the module heap. Convert mod_free_all() to a syscall so the objpool/heap cleanup runs in supervisor context, matching mod_free(). Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Replace the per-pool k_mutex embedded in struct module_resources with a single static K_MUTEX_DEFINE() shared by all module resource pools. This approach to implement locking works both in kernel and userspace SOF builds. When userspace is enabled, the resource API is only ever entered from supervisor context (the z_impl_* syscall bodies), so is it ok to have the lock only accessible from kernel. Lock contention is negligible: resource bookkeeping happens at module setup and teardown, not on the processing path, and the mutex carries priority inheritance for the rare overlap. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Implement a wrapper for this Zephyr interface so it can be used in generic SOF code. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> (cherry picked from commit ec22a69)
Replace the per-pool k_mutex embedded in struct module_resources with a single static K_MUTEX_DEFINE() shared by all module resource pools. This approach to implement locking works both in kernel and userspace SOF builds. When userspace is enabled, the resource API is only ever entered from supervisor context (the z_impl_* syscall bodies), so is it ok to have the lock only accessible from kernel. Lock contention is negligible: resource bookkeeping happens at module setup and teardown, not on the processing path, and the mutex carries priority inheritance for the rare overlap. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> (cherry picked from commit 6b6af15)
Make the options from app/overlays/ptl/ll_userspace_overlay.conf the default for the Intel Panther Lake (ptl) and Wildcat Lake (wcl) build targets, so user-space Low-Latency audio pipelines are enabled without having to pass the overlay explicitly. As noted in the overlay header, once user-space LL is enabled for a target by default the settings belong in the SOF board file directly. For ptl the board already provides the user-space base (USERSPACE, dynamic threads, MMU L2 tables, domain partitions), so only the LL overlay options are added and the conflicting telemetry / cold-store / llext / modules defaults are flipped to match the overlay. wcl had no user-space base at all; since CONFIG_SOF_USERSPACE_LL depends on CONFIG_USERSPACE it would otherwise be silently dropped. Mirror ptl's user-space base into the wcl board file as well so LL actually takes effect there. The ll_userspace_overlay.conf file is kept unchanged; it now re-applies identical values and remains usable by development build scripts. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
8c45fa2 to
65f092dComparekv2019i
commented
Aug 13, 2026
V35 update:
|
SOF has recently gained ability to run DP (=preemptable audio tasks) in Zephyr user-space.
This PR is an early stage pull-request for changes to extend this capability to all of the audio pipeline code, and specifically the LL (low-latency) tasks.
This early stage as the design is not set in stone and the PR uses a number of short cuts in order to move (and tests) incrementally larger sets of audio functionality.