[DRAFT/TESTING] userspace LL/audio test PR (latest ver: V43) - #10558
[DRAFT/TESTING] userspace LL/audio test PR (latest ver: V43)#10558kv2019i wants to merge 10 commits into
Conversation
|
Running the pipeline_two_components_user test added in this PR, on a Intel PTL, looks like this: |
9cdb1be to
37b0412
Compare
|
V2 snapshot pushed:
|
37b0412 to
7317b18
Compare
|
V3 snapshot pushed:
|
|
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
c029d49
Compare
|
V4 snapshot pushed:
|
|
Example output with V4 patchset: |
c029d49 to
9c778e4
Compare
|
V5 pushed:
|
9c778e4 to
c4b127f
Compare
|
V6 pushed:
|
c4b127f to
ad359d6
Compare
|
V7 submitted:
|
ad359d6 to
c7e9a37
Compare
|
V8 submitted:
|
c7e9a37 to
8af1be4
Compare
|
V9 submitted:
|
|
V10:
|
aa5efe0 to
35a61b6
Compare
|
V11 pushed:
|
35a61b6 to
214c051
Compare
|
V12 pushed:
|
|
V36:
|
There was a problem hiding this comment.
Pull request overview
This PR is an early-stage step toward running low-latency (LL) audio pipeline work in Zephyr user-space by making pipeline position tracking safe/accessible from user threads, and by enabling the required Zephyr userspace configuration on ACE30 boards.
Changes:
- Move
pipeline_posn_init()earlier in the Zephyr init sequence and add user-thread access grants for the pipeline position mutex. - Update pipeline position locking to use a mutex (userspace-safe) when
CONFIG_SOF_USERSPACE_LLis enabled, and avoid copying non-userspace-accessible trace context. - Enable/adjust userspace LL-related Kconfig settings in ACE30 PTL/WCL board configs and disable features noted as not yet userspace-compatible.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| zephyr/wrapper.c | Removes late pipeline position init from task_main_start() (init is moved earlier). |
| src/schedule/zephyr_ll.c | Adds warning/handling when task-free semaphore wait times out. |
| src/ipc/ipc-common.c | Grants IPC userspace thread access to the pipeline position mutex. |
| src/init/init.c | Calls pipeline_posn_init() earlier (before platform_init() / userspace IPC init). |
| src/include/sof/audio/pipeline.h | Declares pipeline_posn_grant_access() for userspace LL builds. |
| src/include/sof/audio/pipeline-trace.h | Adds a build-time guard for userspace LL + non-Zephyr-log trace usage. |
| src/audio/pipeline/pipeline-graph.c | Uses mutex-based locking for pipeline position offsets under userspace LL and adds access-grant helper. |
| app/boards/intel_adsp_ace30_wcl.conf | Enables userspace + userspace LL and disables currently incompatible features. |
| app/boards/intel_adsp_ace30_ptl.conf | Enables userspace LL and disables currently incompatible features. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if (wait_ret && task->state != SOF_TASK_STATE_FREE) { | ||
| tr_warn(&ll_tr, "task %p still active on free (state %d, semret %d)", | ||
| task, task->state, wait_ret); | ||
| zephyr_ll_task_done(sch, task); | ||
| } |
|
V37 version:
|
|
V38 update:
|
|
V38b:
|
PR 10558: test resultsRun date: 2026-09-04 14:28 UTC Tested commit: 2d40017d4bb569dc0cc66861dc4c74069a5a3e71 |
|
V39 update:
|
|
V40 update:
|
|
V41 update:
|
|
V42 update:
|
Add a check to ensure task state is what is expected after k_sem_take() returns in zephyr_ll_task_free(). This is needed to avoid a rare error hit when running stress tests with chain DMA in user-space LL builds. Issue is hard to reproduce, but similar error signature can be created by passing K_NO_WAIT to k_sem_take() and running a test with chain-dma pipeline. Add defensive code that handles this scenario and prints out a warning when unexpected return occurs. Tested with a custom build with K_NO_WAIT passed to k_sem_take(). Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
z_vrfy_ipc_msg_list_remove() rejected any message that was not currently on ipc->msg_list by failing K_SYSCALL_VERIFY(found), which turns into a kernel oops. But ipc_msg_list_remove() is called from ipc_msg_free() / mod_ipc_msg_free() to drop a message that may or may not still be queued. The common case at stream stop / pipeline delete is freeing a message that has already been sent and dequeued: its list node is self-linked (empty), so it is not "found" and the verifier oopses the LL user thread with: <err> os.z_vrfy_ipc_msg_list_remove: syscall z_vrfy_ipc_msg_list_remove ... failed check: found <err> os.z_fatal_error: >>> ZEPHYR FATAL ERROR 3: Kernel oops on CPU 0 Relax the checks to avoid this scenario. If the msg->list is empty, it is safe to call z_impl_ipc_msg_list_remove(). The msg->list pointer itself is already verified with K_SYSCALL_MEMORY_WRITE(). Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
…aths vregion_verify() asserts that the vregion metadata object is NOT accessible to the userspace context. It did this with K_OOPS(!K_SYSCALL_MEMORY_READ(vr, sizeof(*vr))); but K_SYSCALL_MEMORY_READ() emits an "os.vregion_verify: ... Memory region <addr> (size 88) read access denied" error via LOG_ERR precisely when the region is inaccessible - i.e. in the expected, correct case for a kernel-only vregion. Probe the mapping directly with arch_buffer_validate(), which performs the same check without logging, and oops only if the userspace context can actually read the metadata. No functional change to the security check; only the false-positive error logging is removed. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Replace the bare k_heap pointer in struct pipeline with a mod_alloc_ctx object. The context is created in pipeline_new() and freed symmetrically in pipeline_free(). No vregion is associated with this context yet, so allocation behavior is unchanged: sof_ctx_alloc()/sof_ctx_zalloc()/sof_ctx_free() fall back to the plain heap when the context has no vregion. Update all remaining pipeline->heap consumers, including the pipeline and trigger task allocations in pipeline-schedule.c, to go through the alloc context instead of the heap pointer directly. Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com> (cherry picked from commit deac1c8)
Create a per-pipeline vregion in pipeline_new() when the IPC4 pipeline extension payload specifies the required heap size, and attach it to the pipeline's alloc context. LL modules on a pipeline with a vregion use it as their allocation backend via vregion_get(), instead of the driver's default heap, and share the pipeline's mod_alloc_ctx. A use_ppl_alloc flag gates the sharing to LL modules only, so DP modules continue to create their own vregion and alloc context as before. Also the behaviour in the case the where ppl_alloc is not available remains unchanged. module_adapter_mem_free() detects whether a module's alloc belongs to its pipeline and either just releases the vregion reference (ppl_alloc case) or tears down the module's own alloc. Setting of dev->pipeline is moved earlier in module_adapter_new_ext() so that we can still use module_adapter_mem_free() in its error handling. Call vregion_set_interim() for the pipeline vregion in pipeline_complete() to switch the allocator to interim mode after all lifetime allocations are done, and release it in pipeline_free(), warning if the refcount does not reach zero. Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com> (cherry picked from commit 6407e81)
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>
The upstream SOF nocodec topologies require more than 32 memory partitions. Bump the max to 64. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Increase the max limit for memory partitions to allow running SOF with sof-ptl-nocodec.tplg when running all pipelines in user-space. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
|
V43 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.