Skip to content

LL userspace ipc_msg_send() and send_resource_notif() syscalls and related changes#10725

Draft
jsarha wants to merge 113 commits intothesofproject:mainfrom
jsarha:ll_userspace_ipc_msg_send
Draft

LL userspace ipc_msg_send() and send_resource_notif() syscalls and related changes#10725
jsarha wants to merge 113 commits intothesofproject:mainfrom
jsarha:ll_userspace_ipc_msg_send

Conversation

@jsarha
Copy link
Copy Markdown
Contributor

@jsarha jsarha commented Apr 25, 2026

FYI @kv2019i , @lyakh , @lrgirdwo

I still intent to make sure the position updates work.

kv2019i added 30 commits April 22, 2026 17:00
If CONFIG_SOF_BOOT_TEST_STANDALONE is set, ipc_init() is terminated
early. This ensures SOF will not start to generate or respond
to IPC messages that could potentially interfere with standalone
test cases (some of which send and receive IPCs).

The current implementation leaves the component list uninitialized
and this can cause trouble to standalone tests that want to utilzie
common IPC code to build messages.

Fix this problem by executing more of ipc_init() also in the standalone
mode.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add a method to add access to a component object to a particular
thread. This is required as component object state includes kernel
objects and to use these from user-space, access needs to be granted.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
In userspace LL builds, use a mutex to protect component
connections. This code shoudl work for kernel builds, but at least
now add new code under a ifdef to avoid the cost of additional
mutex object.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
- replace dynamically-allocated k_mutex *list_mutex with embedded sys_mutex
- remove k_object_alloc in comp_init, k_object_release in comp_free
- remove comp_grant_access_to_thread() function and caller
- update PPL_LOCK/PPL_UNLOCK and ipc-helper lock sites

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add sof_sys_user_heap_get() to get heap object to use for SOF audio
application heap allocations. When SOF is built with
CONFIG_SOF_USERSPACE_LL, this will return a heap that can be
used for user-space code.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add APP_SYSUSER_BSS() and APP_SYSUSER_DATA() macros to put global
objects to a memory partition that is available to the user context
used to run main SOF application. If SOF is run in kernel space,
these are no-ops, but if CONFIG_SOF_USERSPACE_LL is set, a dedicated
memory partition is used.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add a built option to make sof_heap_allo/free available as
system calls to user-space.

Add a test case for the functions that runs in a user-space thread.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Separate the state for LL scheduler memory into kernel and user
accessible resources. The pointer to the LL heap must be accessible
from user-space, so that user space can allocate memory and pass
the heap pointer as argument.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Turn the pdata->sem into a dynamic object in userspace LL builds.
Keep statically allocated semaphore for kernel LL builds.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Replace the dynamically-allocated k_sem (via k_object_alloc) in
zephyr_ll_pdata with an embedded sys_sem. The dynamic kernel semaphore
could not be freed from user-space threads, causing kernel object leaks
that exhausted the kernel object pool during long test runs.

sys_sem uses k_futex in user mode and lives in user memory, so no
kernel object allocation or cleanup is needed. Add POSIX no-op stubs
for sys_sem to maintain testbench build compatibility.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Move the user-accessible heap pointer to common partition defined
in userspace_helper.h.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add a heap parameter to DMA scatter-gather allocation interface. This
makes it possible to control how allocations are done for the DMA
buffers.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Continue the work in commit 9567234 ("buffer: allocate on specific
heap") and add ability to specify the heap to all buffer interface
functions.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add an overlay for Intel 'ptl' target that allows to build
SOF with all audio pipeline code running in Zephyr user-sapce.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Allow a non-null pointer at the end of the DMA transfer block list,
if and only if it points to the first entry in the block list.

The SOF DAI module sets the DMA transfers blocks like this and
this change is required to use DAI module from user-space.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
The platform data descriptions need to be accessible to all threads.
These are e.g. used when setting up host/DAI copiers and they need
platform DMA properties.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Use separate heaps depending whether host copier is run in user
or kernel space.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
For historical reasons, host-zephyr has somewhat complicated code to
manage the DMA channel instance information. When a DMA channel is allocated,
a pointer to the system DMA channel table is acquired and some additional
information is stored per channel. This is however redundant as the only
piece of information actually needed is the channel index.

Simplify the code by not storing the channel pointer anymore, but
rather just store the channel index and use that in all calls to the
DMA driver.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Make sure we use the same heap to allocate DMA SG buffers as
we use for other component resources.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
These interfaces are no longer used anywhere, so they can be
safely removed.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Force to use user-space LL heap in host_common_new() if
CONFIG_SOF_USERSPACE_LL is set.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Ensure component heap is correctly passed whenever memory
is allocated in the component. This allows to run the component
both in kernel and user space.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
The pcm_converter depends on a set of global function tables to set up
correct conversion functions. These objects need to be made available to
user-space threads, so that pcm_converter can be also run in user-space.
No impact to kernel-space use of pcm_converter.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
kv2019i and others added 30 commits April 22, 2026 17:00
Use sof_dma_get_status() call to allow the audio pipeline to
be run in user-space.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Fix a few remaining uses of direct DMA driver calls. Use
the sof_dma.h wrapper instead, allowing the code to be used
also from user-space.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Replace rfree() calls with sof_heap_free() using the system user heap
for IPC component and pipeline objects. In ipc4_create_pipeline(),
replace the conditional zephyr_ll_user_heap() with the generic
sof_sys_user_heap_get() to unify the allocation path across
configurations.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Mark the fw_reg mutex with APP_SYSUSER_BSS, allowing the lock to be used
when DAI module is run in user-space.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Do not use IRQ disable/enable when built for user-space. The driver list
is immutable by IPC processing time so no lock is needed.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
- add arch_schedulers_get_for_core() for task-carried core routing
- route 8 task-aware scheduler callers via task->core under CONFIG_SOF_USERSPACE_LL
- fix zephyr_domain_thread_tid() to accept core parameter instead of hardcoding core 0
- create domain threads for secondary cores in secondary_core_init()
- remove FIXME workaround from arch_schedulers_get()

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
No need to copy the trace context object to buffer object, when
audio pipelines are running in user-space.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
To make ipc4_create_buffer() usable from user-space, do not call
cpu_get_id() but instead rely on "src->ipc_config.core". If code
is run in kernel space, check the core matching current active
core, but skip the check if run in user-space (as check is
privileged).

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Make ipc_comp_connect() safe to run in user-space with limited
functionality. The core id queries are privileged, so limit connections
to cases where pipeline is running on 0.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Move handling of SOF_IPC4_MOD_CONFIG_GET/GET to user-space IPC
thread when SOF is built with CONFIG_SOF_USERSPACE_LL.

Handling these IPC messages require calls to module interface
get/set_attribute() methods, which must be run in user-space.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Move handling of SOF_IPC4_MOD_BIND/UNBIND to user-space IPC
thread when SOF is built with CONFIG_SOF_USERSPACE_LL.

Handling these IPC messages require calls to module interface
bind/unbind() methods, which must be run in user-space.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Move handling of SOF_IPC4_IPC4_MOD_INIT_INSTANCE partially to user-space IPC
thread when SOF is built with CONFIG_SOF_USERSPACE_LL.

Module init involves multiple privileged actions, so part of module
init handling is still done in kernel space, but the module specific
initialization is run in user-space.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Move handling of SOF_IPC4_GLB_SET_PIPELINE_STATE to user-space IPC
thread when SOF is built with CONFIG_SOF_USERSPACE_LL.

The IPC compound message helpers in IPC common.h are turned into
system calls, allowing the user-space IPC thread to synchronize
with kernel IPC thread that still does the low-level IPC messaging.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Move handling of SOF_IPC4_MOD_LARGE_CONFIG_GET/SET to user-space IPC
thread when SOF is built with CONFIG_SOF_USERSPACE_LL.

Handling of these IPCs requires calling to module specific code
via the module get/set_large_config() method, so this code needs
to run in user-space context if audio pipelines are running in
user-space.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add a new test to userspace_ll set that takes a step towards
running full audio pipelines in user-space. The test creates a pipeline
with two components (IPC4 host and DAI copiers), does pipeline
prepare, one copy cycle in prepared state and tears down the pipeline.

One user-space thread is created to manage the pipelines. This would
be equivalent to user IPC handler thread. Another user-space thread
is created for the LL scheduler.

This test has some limitation, but is a useful test point to
test resource allocations in pipeline, component and module adapter
code. The code adds a reference test case where the same flow is fully
run in kernel space.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add a test that sends SOF_IPC4_GLB_CREATE_PIPELINE message
via ipc_cmd() interface. This test can be used to test SOF when built
with CONFIG_SOF_USERSPACE_LL. Handling of audio pipeline IPC
messages (like CREATE_PIPELINE) will be routed to a user-space
IPC thread.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
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>
If SOF is built with CONFIG_SOF_USERSPACE_LL, the IPC user
handled will require access to coldrodata sections to initialize
audio modules.

This logic is not required for LLEXT modules, which have existing
code to add access to coldrodata (and other sections). This commit
is needed for builds where LLEXT is not used.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
This is a set of temporary changes to audio code to remove calls
to privileged interfaces that are not mandatory to run simple
audio tests.

These need proper solutions to be able to run all use-cases in user
LL version.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Pull in Zephyr PR.

Link: zephyrproject-rtos/zephyr#107341
Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Make ipc_msg_send() a Zephyr system call so audio processing
modules running in user-space LL threads can queue IPC messages
(e.g. position updates, notifications) back to the host.

Follows the same pattern used for ipc_msg_reply(): a dedicated
header with __syscall declaration, z_impl/z_vrfy split, and
syscall header registration in CMakeLists.txt.

The verifier validates that the msg struct is writable (the
implementation touches the list linkage) and that the data
buffer, when provided, is readable up to msg->tx_size bytes.

Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com>
Add an optional heap parameter to ipc_msg_w_ext_init() and
ipc_msg_init() so callers can direct allocations to a specific
heap. When the heap argument is NULL the existing rzalloc()
path is used; when non-NULL, sof_heap_alloc()/sof_heap_free()
are used instead. This allows IPC messages to be allocated from
userspace-accessible heaps.

For audio module contexts, introduce mod_ipc_msg_w_ext_init()
and mod_ipc_msg_init() in generic.h. These use mod_zalloc()/
mod_free() for allocations that are automatically tracked and
freed with the module lifecycle.

ipc_msg_w_ext_init() is moved from a static inline in msg.h to
a non-inline function in ipc-common.c due to the additional
sof_heap_alloc dependency.

Update all existing callers:
- Module context callers (cadence, tdfb, sound_dose) use the
  new mod_ipc_msg_*() variants.
- host-zephyr.c uses hd->heap, pipeline-graph.c uses the heap
  parameter from pipeline_new().
- Remaining kernel-context callers pass NULL for the default
  heap.

Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com>
Move user-facing notification functions (send_copier_gateway_xrun_notif_msg,
send_gateway_xrun_notif_msg, send_mixer_underrun_notif_msg,
send_process_data_error_notif_msg) to a new notification-user.c file so they
can run in userspace.

The send_resource_notif() function, which depends on the kernel-side
notification pool and IPC message infrastructure, is converted to a Zephyr
syscall. The implementation is renamed to z_impl_send_resource_notif() and
remains in notification.c alongside is_notif_filtered_out() and
ipc4_update_notification_mask().

A z_vrfy_send_resource_notif() handler is added in zephyr/syscall/notification.c
to validate the user-provided data buffer before forwarding to the kernel
implementation.

Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants