From 9d02a83e6004c830f3d6a46118f23e4115765272 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 20 Aug 2026 14:34:01 +0200 Subject: [PATCH 1/4] schedule: dp: use scheduler_get_user_data() The DP scheduler runs tasks in userspace mode, it's registered with the user scheduler list, therefore it should use scheduler_get_user_data(), not scheduler_get_data(). Signed-off-by: Guennadi Liakhovetski --- src/schedule/zephyr_dp_schedule.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/schedule/zephyr_dp_schedule.c b/src/schedule/zephyr_dp_schedule.c index fa8bbd285791..6576fc428daa 100644 --- a/src/schedule/zephyr_dp_schedule.c +++ b/src/schedule/zephyr_dp_schedule.c @@ -227,7 +227,11 @@ static enum task_state scheduler_dp_ll_tick_dummy(void *data) void scheduler_dp_ll_tick(void) { unsigned int lock_key; +#if CONFIG_SOF_USERSPACE_LL + struct scheduler_dp_data *dp_sch = scheduler_get_user_data(SOF_SCHEDULE_DP); +#else struct scheduler_dp_data *dp_sch = scheduler_get_data(SOF_SCHEDULE_DP); +#endif if (!dp_sch) return; @@ -376,8 +380,11 @@ void scheduler_get_task_info_dp(struct scheduler_props *scheduler_props, uint32_ unsigned int lock_key; scheduler_props->processing_domain = COMP_PROCESSING_DOMAIN_DP; - struct scheduler_dp_data *dp_sch = - (struct scheduler_dp_data *)scheduler_get_data(SOF_SCHEDULE_DP); +#if CONFIG_SOF_USERSPACE_LL + struct scheduler_dp_data *dp_sch = scheduler_get_user_data(SOF_SCHEDULE_DP); +#else + struct scheduler_dp_data *dp_sch = scheduler_get_data(SOF_SCHEDULE_DP); +#endif lock_key = scheduler_dp_lock(cpu_get_id()); scheduler_get_task_info(scheduler_props, data_off_size, &dp_sch->tasks); From c3994f2b31fe173f3ae2e453e4e1f163ec8cc032 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 7 Jul 2026 12:45:00 +0200 Subject: [PATCH 2/4] schedule: userspace: DP: make scheduler_dp_ll_tick() a syscall scheduler_dp_ll_tick(() has to recalculate DP deadlines and reschedule DP threads. Make it a syscall to be able to call it from the userspace LL scheduler. Signed-off-by: Guennadi Liakhovetski --- src/include/sof/schedule/dp_schedule.h | 6 +++++- src/schedule/zephyr_dp_schedule.c | 11 ++++++++++- zephyr/CMakeLists.txt | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/include/sof/schedule/dp_schedule.h b/src/include/sof/schedule/dp_schedule.h index 1b55405d0fb1..9bfd9b06978a 100644 --- a/src/include/sof/schedule/dp_schedule.h +++ b/src/include/sof/schedule/dp_schedule.h @@ -78,7 +78,11 @@ int scheduler_dp_task_init(struct task **task, uint16_t core, size_t stack_size, uint32_t options); -void scheduler_dp_ll_tick(void); + +#if defined(__ZEPHYR__) && CONFIG_SOF_FULL_ZEPHYR_APPLICATION +__syscall void scheduler_dp_ll_tick(void); +#include +#endif /** * \brief Extract information about scheduler's tasks diff --git a/src/schedule/zephyr_dp_schedule.c b/src/schedule/zephyr_dp_schedule.c index 6576fc428daa..6b907a43d8a9 100644 --- a/src/schedule/zephyr_dp_schedule.c +++ b/src/schedule/zephyr_dp_schedule.c @@ -224,7 +224,7 @@ static enum task_state scheduler_dp_ll_tick_dummy(void *data) * needed 1.2ms for processing - but the example would be too complicated) */ -void scheduler_dp_ll_tick(void) +void z_impl_scheduler_dp_ll_tick(void) { unsigned int lock_key; #if CONFIG_SOF_USERSPACE_LL @@ -244,6 +244,15 @@ void scheduler_dp_ll_tick(void) scheduler_dp_unlock(lock_key); } +#ifdef CONFIG_USERSPACE +#include +void z_vrfy_scheduler_dp_ll_tick(void) +{ + z_impl_scheduler_dp_ll_tick(); +} +#include +#endif + #if CONFIG_SOF_USERSPACE_APPLICATION static int scheduler_dp_task_cancel(void *data, struct task *task) { diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index c8f49c1f07cb..d036eaeede90 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -625,6 +625,7 @@ zephyr_library_sources_ifdef(CONFIG_USERSPACE syscall/cpu.c) zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/audio/module_adapter/module/generic.h) zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/lib/fast-get.h) zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/ipc/ipc_reply.h) +zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/schedule/dp_schedule.h) zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/schedule/ll_schedule_domain.h) zephyr_syscall_header(${SOF_SRC_PATH}/include/ipc4/handler.h) zephyr_syscall_header(include/rtos/alloc.h) From 7a05a4a99c9be88e8d61e3f2c0a58b3a7b18ed60 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 28 Aug 2026 13:55:49 +0200 Subject: [PATCH 3/4] schedule: dp: userspace: make scheduler_dp_internal_free() a syscall Make scheduler_dp_internal_free() a syscall in the "application" DP implementation. Signed-off-by: Guennadi Liakhovetski --- src/include/sof/schedule/dp_schedule.h | 1 + src/schedule/zephyr_dp_schedule.h | 4 -- src/schedule/zephyr_dp_schedule_application.c | 47 ++++++++++++++++++- src/schedule/zephyr_dp_schedule_thread.c | 16 ++++++- 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/include/sof/schedule/dp_schedule.h b/src/include/sof/schedule/dp_schedule.h index 9bfd9b06978a..449bf2151872 100644 --- a/src/include/sof/schedule/dp_schedule.h +++ b/src/include/sof/schedule/dp_schedule.h @@ -80,6 +80,7 @@ int scheduler_dp_task_init(struct task **task, uint32_t options); #if defined(__ZEPHYR__) && CONFIG_SOF_FULL_ZEPHYR_APPLICATION +__syscall void scheduler_dp_internal_free(struct task *task); __syscall void scheduler_dp_ll_tick(void); #include #endif diff --git a/src/schedule/zephyr_dp_schedule.h b/src/schedule/zephyr_dp_schedule.h index 694bb541f87e..2119e44c9dfc 100644 --- a/src/schedule/zephyr_dp_schedule.h +++ b/src/schedule/zephyr_dp_schedule.h @@ -57,7 +57,3 @@ void dp_thread_fn(void *p1, void *p2, void *p3); unsigned int scheduler_dp_lock(uint16_t core); void scheduler_dp_unlock(unsigned int key); void scheduler_dp_grant(k_tid_t thread_id, uint16_t core); -int scheduler_dp_task_init(struct task **task, const struct sof_uuid_entry *uid, - const struct task_ops *ops, struct processing_module *mod, - uint16_t core, size_t stack_size, uint32_t options); -void scheduler_dp_internal_free(struct task *task); diff --git a/src/schedule/zephyr_dp_schedule_application.c b/src/schedule/zephyr_dp_schedule_application.c index 547823ca6e6f..3183ca95aef3 100644 --- a/src/schedule/zephyr_dp_schedule_application.c +++ b/src/schedule/zephyr_dp_schedule_application.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -400,7 +401,7 @@ struct scheduler_dp_task_memory { struct ipc4_flat flat; }; -void scheduler_dp_internal_free(struct task *task) +void z_impl_scheduler_dp_internal_free(struct task *task) { struct task_dp_pdata *pdata = task->priv_data; @@ -616,3 +617,47 @@ int scheduler_dp_task_init(struct task **task, const struct sof_uuid_entry *uid, mod_free(mod, task_memory); return ret; } + +#ifdef CONFIG_USERSPACE +#include + +static void scheduler_dp_mod_vrfy(struct processing_module *mod) +{ + K_OOPS(K_SYSCALL_MEMORY_WRITE(mod, sizeof(*mod))); + K_OOPS(K_SYSCALL_MEMORY_WRITE(mod->dev, sizeof(*mod->dev))); + K_OOPS(K_SYSCALL_MEMORY_READ(mod->dev->drv, sizeof(*mod->dev->drv))); + + struct mod_alloc_ctx *alloc = mod->priv.resources.alloc; + + K_OOPS(K_SYSCALL_MEMORY_WRITE(alloc, sizeof(*alloc))); + if (alloc->heap) { + size_t h_size = 0; + uintptr_t h_start; + + mod_heap_info(mod, &h_size, &h_start); + if (h_size) + K_OOPS(K_SYSCALL_MEMORY_WRITE(h_start, h_size)); + } + if (alloc->vreg) { + size_t vr_size = 0; + uintptr_t vr_start; + + vregion_mem_info(alloc->vreg, &vr_size, &vr_start); + K_OOPS(K_SYSCALL_MEMORY_WRITE(vr_start, vr_size)); + } +} + +void z_vrfy_scheduler_dp_internal_free(struct task *task) +{ + K_OOPS(K_SYSCALL_MEMORY_WRITE(task, sizeof(*task))); + + struct task_dp_pdata *pdata = task->priv_data; + + K_OOPS(K_SYSCALL_MEMORY_WRITE(pdata, sizeof(*pdata))); + K_OOPS(K_SYSCALL_OBJ(pdata->event, K_OBJ_EVENT)); + K_OOPS(K_SYSCALL_OBJ_INIT(pdata->thread, K_OBJ_THREAD)); + scheduler_dp_mod_vrfy(pdata->mod); + return z_impl_scheduler_dp_internal_free(task); +} +#include +#endif diff --git a/src/schedule/zephyr_dp_schedule_thread.c b/src/schedule/zephyr_dp_schedule_thread.c index f2c2434bc2b5..43c4b43e35e2 100644 --- a/src/schedule/zephyr_dp_schedule_thread.c +++ b/src/schedule/zephyr_dp_schedule_thread.c @@ -340,7 +340,7 @@ int scheduler_dp_task_init(struct task **task, return ret; } -void scheduler_dp_internal_free(struct task *task) +void z_impl_scheduler_dp_internal_free(struct task *task) { struct task_dp_pdata *pdata = task->priv_data; @@ -354,3 +354,17 @@ void scheduler_dp_internal_free(struct task *task) /* task is the first member in task_memory above */ sof_heap_free(pdata->mod->dev->drv->user_heap, task); } + +#ifdef CONFIG_USERSPACE +#include + +void z_vrfy_scheduler_dp_internal_free(struct task *task) +{ + /* + * With the thread DP scheduler variant scheduler_dp_internal_free() is + * never called from the userspace context + */ + K_OOPS(true); +} +#include +#endif From e58f00a4e2dfe96d660b60f4ceda41f77286aef3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 8 Jul 2026 16:17:54 +0200 Subject: [PATCH 4/4] schedule: ll: userspace: grant the LL thread rights on DP The LL userspace thread has to interact with the DP one. Grant required rights. Signed-off-by: Guennadi Liakhovetski --- src/include/sof/schedule/ll_schedule_domain.h | 1 + src/schedule/zephyr_domain.c | 12 ++++++++++++ src/schedule/zephyr_dp_schedule.c | 3 ++- src/schedule/zephyr_dp_schedule_application.c | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/include/sof/schedule/ll_schedule_domain.h b/src/include/sof/schedule/ll_schedule_domain.h index 03991debb0cb..cfd0043995db 100644 --- a/src/include/sof/schedule/ll_schedule_domain.h +++ b/src/include/sof/schedule/ll_schedule_domain.h @@ -330,6 +330,7 @@ struct ll_schedule_domain *zephyr_domain_init(int clk); struct k_thread *zephyr_domain_thread_tid(struct ll_schedule_domain *domain); struct k_thread *zephyr_domain_thread_tid_for_core(int core); struct k_mem_domain *zephyr_ll_mem_domain(void); +struct k_thread *zephyr_ll_domain_thread(void); #endif /* CONFIG_SOF_USERSPACE_LL */ #ifdef CONFIG_SOF_FULL_ZEPHYR_APPLICATION __syscall int zephyr_ll_task_sem_alloc(struct task *task); diff --git a/src/schedule/zephyr_domain.c b/src/schedule/zephyr_domain.c index b37f91285854..cc1b76600dee 100644 --- a/src/schedule/zephyr_domain.c +++ b/src/schedule/zephyr_domain.c @@ -525,6 +525,18 @@ struct k_thread *zephyr_domain_thread_tid_for_core(int core) return ll_thread_tid[core]; } +struct k_thread *zephyr_ll_domain_thread(void) +{ + struct ll_schedule_domain *ll_domain = zephyr_ll_domain(); + + if (!ll_domain) + return NULL; + + struct zephyr_domain *zephyr_domain = ll_sch_domain_get_pdata(ll_domain); + + return zephyr_domain->domain_thread[cpu_get_id()].ll_thread; +} + #endif /* CONFIG_SOF_USERSPACE_LL */ #if CONFIG_CROSS_CORE_STREAM diff --git a/src/schedule/zephyr_dp_schedule.c b/src/schedule/zephyr_dp_schedule.c index 6b907a43d8a9..2f6e5e6c5201 100644 --- a/src/schedule/zephyr_dp_schedule.c +++ b/src/schedule/zephyr_dp_schedule.c @@ -62,7 +62,8 @@ void scheduler_dp_unlock(unsigned int key) void scheduler_dp_grant(k_tid_t thread_id, uint16_t core) { - k_thread_access_grant(thread_id, &dp_lock[core]); + if (thread_id) + k_thread_access_grant(thread_id, &dp_lock[core]); } /* dummy LL task - to start LL on secondary cores */ diff --git a/src/schedule/zephyr_dp_schedule_application.c b/src/schedule/zephyr_dp_schedule_application.c index 3183ca95aef3..c01d73964175 100644 --- a/src/schedule/zephyr_dp_schedule_application.c +++ b/src/schedule/zephyr_dp_schedule_application.c @@ -528,6 +528,9 @@ int scheduler_dp_task_init(struct task **task, const struct sof_uuid_entry *uid, k_thread_access_grant(pdata->thread_id, pdata->event, &dp_sync[core]); scheduler_dp_grant(pdata->thread_id, core); +#if CONFIG_SOF_USERSPACE_LL + scheduler_dp_grant(zephyr_ll_domain_thread(), core); +#endif struct k_mem_domain *mdom = objpool_alloc(&dp_mdom_head, sizeof(*mdom), SOF_MEM_FLAG_COHERENT);