Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/include/sof/lib_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,25 @@ void lib_manager_get_instance_bss_address(uint32_t instance_id,
*/
int lib_manager_load_library(uint32_t dma_id, uint32_t lib_id, uint32_t type);

struct userspace_context;
/*
* \brief Allocate the module and start the agent if needed
*/
int lib_manager_mod_create_priv(const struct comp_driver *drv,
const struct comp_ipc_config *config,
const void *spec, void **adapter_priv,
struct userspace_context **userspace,
const struct module_interface **ops);

#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)
__syscall int lib_manager_free_module(const uint32_t component_id);

#include <zephyr/syscalls/lib_manager.h>
#else
int z_impl_lib_manager_free_module(const uint32_t component_id);
#define lib_manager_free_module z_impl_lib_manager_free_module
#endif

/*
* \brief Initialize message
*
Expand Down
111 changes: 78 additions & 33 deletions src/library_manager/lib_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ static uintptr_t lib_manager_allocate_module(const struct sof_man_fw_desc *const
*
* Function is responsible to free module resources in HP memory.
*/
static int lib_manager_free_module(const uint32_t component_id)
int z_impl_lib_manager_free_module(const uint32_t component_id)
{
const struct sof_man_module *mod;
const uint32_t module_id = IPC4_MOD_ID(component_id);
Expand Down Expand Up @@ -465,7 +465,7 @@ static uintptr_t lib_manager_allocate_module(const struct sof_man_fw_desc *const
return 0;
}

static int lib_manager_free_module(const uint32_t component_id)
static int z_impl_lib_manager_free_module(const uint32_t component_id)
{
/* Since we cannot allocate the freeing is not considered to be an error */
tr_warn(&lib_manager_tr, "Dynamic module freeing is not supported");
Expand Down Expand Up @@ -646,47 +646,49 @@ static enum buildinfo_mod_type lib_manager_get_module_type(const struct sof_man_
}
}

/*
* \brief Load module code, allocate its instance and create a module adapter component.
* \param[in] drv - component driver pointer.
* \param[in] config - component ipc descriptor pointer.
* \param[in] spec - passdowned data from driver.
*
* \return: a pointer to newly created module adapter component on success. NULL on error.
*/
static struct comp_dev *lib_manager_module_create(const struct comp_driver *drv,
const struct comp_ipc_config *config,
const void *spec)
/* Error path resource freeing */
static void lib_manager_mod_free_priv(const struct comp_driver *drv,
const struct comp_ipc_config *config,
struct userspace_context *userspace)
{
#if CONFIG_SOF_USERSPACE_PROXY
if (userspace)
userspace_proxy_destroy(drv, userspace);
#endif /* CONFIG_SOF_USERSPACE_PROXY */
lib_manager_free_module(config->id);
}

int lib_manager_mod_create_priv(const struct comp_driver *drv,
const struct comp_ipc_config *config,
const void *spec, void **adapter_priv,
struct userspace_context **userspace,
const struct module_interface **ops)
{
const struct sof_man_fw_desc *const desc = lib_manager_get_library_manifest(config->id);
const struct ipc_config_process *args = (const struct ipc_config_process *)spec;
const uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(config->id);
struct userspace_context *userspace = NULL;
const struct module_interface *ops;
const struct sof_man_module *mod;
system_agent_start_fn agent;
void *adapter_priv = NULL;
const void **agent_iface;
struct comp_dev *dev;
int ret;

#ifdef CONFIG_SOF_USERSPACE_PROXY
if (drv->user_heap && config->proc_domain != COMP_PROCESSING_DOMAIN_DP) {
tr_err(&lib_manager_tr, "Userspace supports only DP modules.");
return NULL;
return -EOPNOTSUPP;
}
#endif

tr_dbg(&lib_manager_tr, "start");
if (!desc) {
tr_err(&lib_manager_tr, "Error: Couldn't find loadable module with id %u.",
config->id);
return NULL;
return -ENOENT;
}

if (entry_index >= desc->header.num_module_entries) {
tr_err(&lib_manager_tr, "Entry index %u out of bounds.", entry_index);
return NULL;
return -EINVAL;
}

mod = (const struct sof_man_module *)
Expand All @@ -697,53 +699,96 @@ static struct comp_dev *lib_manager_module_create(const struct comp_driver *drv,

if (!module_entry_point) {
tr_err(&lib_manager_tr, "lib_manager_allocate_module() failed!");
return NULL;
return -ENOENT;
}

switch (lib_manager_get_module_type(desc, mod)) {
case MOD_TYPE_LLEXT:
agent = NULL;
ops = (const struct module_interface *)module_entry_point;
*ops = (const struct module_interface *)module_entry_point;
agent_iface = NULL;
break;
case MOD_TYPE_LMDK:
agent = &native_system_agent_start;
agent_iface = (const void **)&ops;
agent_iface = (const void **)ops;
break;
#if CONFIG_INTEL_MODULES
case MOD_TYPE_IADK:
agent = &system_agent_start;
ops = &processing_module_adapter_interface;
agent_iface = (const void **)&adapter_priv;
*ops = &processing_module_adapter_interface;
agent_iface = (const void **)adapter_priv;
break;
#endif
case MOD_TYPE_INVALID:
default:
ret = -EINVAL;
goto err;
}

if (agent || IS_ENABLED(CONFIG_SOF_USERSPACE_PROXY)) {
/* At this point module resources are allocated and it is moved to L2 memory. */
ret = lib_manager_start_agent(drv, config, mod, args, module_entry_point, agent,
agent_iface, &userspace, &ops);
agent_iface, userspace, ops);
if (ret)
goto err;
}

if (comp_set_adapter_ops(drv, ops) < 0)
ret = comp_set_adapter_ops(drv, *ops);
if (ret < 0)
goto err;

dev = module_adapter_new_ext(drv, config, spec, adapter_priv, userspace, NULL);
return 0;

err:
lib_manager_mod_free_priv(drv, config, *userspace);
return ret;
}

#ifdef CONFIG_USERSPACE
#include <zephyr/internal/syscall_handler.h>

static int z_vrfy_lib_manager_free_module(const uint32_t component_id)
{
return z_impl_lib_manager_free_module(component_id);
}
#include <zephyr/syscalls/lib_manager_free_module_mrsh.c>

#endif /* CONFIG_USERSPACE */

/*
* \brief Load module code, allocate its instance and create a module adapter component.
* \param[in] drv - component driver pointer.
* \param[in] config - component ipc descriptor pointer.
* \param[in] spec - passdowned data from driver.
*
* \return: a pointer to newly created module adapter component on success. NULL on error.
*/
static struct comp_dev *lib_manager_module_create(const struct comp_driver *drv,
const struct comp_ipc_config *config,
const void *spec)
{
struct userspace_context *userspace = NULL;
const struct module_interface *ops = NULL;
void *adapter_priv = NULL;
struct comp_dev *dev;

if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP ||
!IS_ENABLED(CONFIG_SOF_USERSPACE_LL)) {
int ret = lib_manager_mod_create_priv(drv, config, spec, &adapter_priv,
&userspace, &ops);

if (ret < 0)
return NULL;
}
Comment on lines +775 to +782

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, yes, in a sense it's a "regression," but a conscious one - it's then fixed in 0e183e9 . So, we can either hold this PR back or st least this commit and merge it in the last step, or merge it anyway, because it "only" breaks userspace LL which isn't functional nor enabled yet anyway.


dev = module_adapter_new_ext(drv, config, spec, adapter_priv, userspace, ops);
if (!dev)
goto err;

return dev;

err:
#if CONFIG_SOF_USERSPACE_PROXY
if (userspace)
userspace_proxy_destroy(drv, userspace);
#endif /* CONFIG_SOF_USERSPACE_PROXY */
lib_manager_free_module(config->id);
lib_manager_mod_free_priv(drv, config, userspace);
return NULL;
}

Expand Down
13 changes: 5 additions & 8 deletions src/library_manager/llext_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,12 +334,10 @@ static int llext_manager_load_module(struct lib_manager_module *mctx)
mctx->mapped = true;

#ifdef CONFIG_SOF_USERSPACE_LL
if (!mctx->domain_dp) {
ret = llext_manager_add_mod_domain(mctx, zephyr_ll_mem_domain());
if (ret < 0) {
tr_err(&lib_manager_tr, "failed to add domain: %d", ret);
goto e_data;
}
ret = llext_manager_add_mod_domain(mctx, zephyr_ll_mem_domain());
if (ret < 0) {
tr_err(&lib_manager_tr, "failed to add domain: %d", ret);
goto e_data;
Comment thread
lyakh marked this conversation as resolved.
}
#endif

Expand Down Expand Up @@ -426,8 +424,7 @@ static int llext_manager_unload_module(struct lib_manager_module *mctx)
mctx->mapped = false;

#ifdef CONFIG_SOF_USERSPACE_LL
if (!mctx->domain_dp)
llext_manager_rm_mod_domain(mctx, zephyr_ll_mem_domain());
llext_manager_rm_mod_domain(mctx, zephyr_ll_mem_domain());
#endif
Comment on lines 426 to 428

@lyakh lyakh Aug 28, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's the purpose of this PR to change that behaviour, but it's the same issue as #11139 (comment) - so let's delay this PR


return err;
Expand Down
1 change: 1 addition & 0 deletions zephyr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,7 @@ zephyr_library_sources_ifdef(CONFIG_SOF_USERSPACE_INTERFACE_ALLOC syscall/alloc.
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/lib/vregion.h)
zephyr_library_sources_ifdef(CONFIG_SOF_USERSPACE_INTERFACE_VREGION syscall/vregion.c)
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/lib/dai-zephyr.h)
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/lib_manager.h)
zephyr_library_sources_ifdef(CONFIG_USERSPACE syscall/dai.c)

zephyr_syscall_header(${SOF_SRC_PATH}/include/user/debug_stream_slot.h)
Expand Down
Loading