From 902b1e581738a16b5bb8d5a106cc18e031369f8d Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Mon, 11 Mar 2024 19:12:23 +0100 Subject: [PATCH] lib_manager: modules: move native lib support to lib_manager Moved module type identification to lib_manager. Since llext modules place the buildinfo structure in a separate section, API version verification has been moved to llext_manager. Thanks to these changes, the Processing Module Adapter is used only by IADK modules as intended. This commit also fixes an issue with the modules_free function not being called for native modules. Signed-off-by: Adrian Warecki Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module/modules.c | 129 ++++--------------- src/audio/module_adapter/module_adapter.c | 1 + src/include/module/module/base.h | 3 - src/include/sof/lib_manager.h | 5 +- src/include/sof/llext_manager.h | 2 +- src/library_manager/lib_manager.c | 148 +++++++++++++++++++--- src/library_manager/llext_manager.c | 41 ++++-- 7 files changed, 191 insertions(+), 138 deletions(-) diff --git a/src/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c index c995fc5c0..c25f8f7d9 100644 --- a/src/audio/module_adapter/module/modules.c +++ b/src/audio/module_adapter/module/modules.c @@ -10,12 +10,8 @@ #include #include #include -#include -#include #include #include -#include -#include /* Intel module adapter is an extension to SOF module adapter component that allows to integrate * modules developed under IADK (Intel Audio Development Kit) Framework. IADK modules uses uniform @@ -51,63 +47,6 @@ DECLARE_SOF_RT_UUID("modules", intel_uuid, 0xee2585f2, 0xe7d8, 0x43dc, 0x90, 0xab, 0x42, 0x24, 0xe0, 0x0c, 0x3e, 0x84); DECLARE_TR_CTX(intel_codec_tr, SOF_UUID(intel_uuid), LOG_LEVEL_INFO); -static int modules_new(struct processing_module *mod, const void *buildinfo, - uintptr_t module_entry_point) -{ - struct module_data *md = &mod->priv; - struct comp_dev *dev = mod->dev; - struct comp_driver *drv = (struct comp_driver *)dev->drv; - uint32_t module_id = IPC4_MOD_ID(dev->ipc_config.id); - uint32_t instance_id = IPC4_INST_ID(dev->ipc_config.id); - uint32_t log_handle = (uint32_t) dev->drv->tctx; - /* Connect loadable module interfaces with module adapter entity. */ - /* Check if native Zephyr lib is loaded */ - void *system_agent; - - const struct sof_module_api_build_info *mod_buildinfo; - - if (buildinfo) { - mod_buildinfo = buildinfo; - } else { - const struct sof_man_module *const module_entry = - lib_manager_get_module_manifest(module_id); - - if (!module_entry) { - comp_err(dev, "modules_new(): Failed to load manifest"); - return -ENODATA; - } - - mod_buildinfo = - (struct sof_module_api_build_info *) - (module_entry->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr); - } - - byte_array_t mod_cfg = { - .data = (uint8_t *)md->cfg.init_data, - /* Intel modules expects DW size here */ - .size = md->cfg.size >> 2, - }; - - /* Check if module is FDK */ - if (mod_buildinfo->format == IADK_MODULE_API_BUILD_INFO_FORMAT && - mod_buildinfo->api_version_number.full == IADK_MODULE_API_CURRENT_VERSION) { - system_agent = system_agent_start(module_entry_point, module_id, instance_id, 0, - log_handle, &mod_cfg); - - module_set_private_data(mod, system_agent); - } else if (mod_buildinfo->format == SOF_MODULE_API_BUILD_INFO_FORMAT && - mod_buildinfo->api_version_number.full == SOF_MODULE_API_CURRENT_VERSION) { - /* The module is native: start agent for sof loadable */ - mod->is_native_sof = true; - drv->adapter_ops = native_system_agent_start(module_entry_point, module_id, - instance_id, 0, log_handle, &mod_cfg); - } else { - return -ENOEXEC; - } - - return 0; -} - /** * \brief modules_init. * \param[in] mod - processing module pointer. @@ -121,51 +60,39 @@ static int modules_init(struct processing_module *mod) struct comp_dev *dev = mod->dev; const struct comp_driver *const drv = dev->drv; const struct ipc4_base_module_cfg *src_cfg = &md->cfg.base_cfg; - struct comp_ipc_config *config = &(dev->ipc_config); - /* At this point module resources are allocated and it is moved to L2 memory. */ - const void *buildinfo = NULL; - int ret; - uintptr_t module_entry_point = lib_manager_allocate_module(mod, config, src_cfg, - &buildinfo); + const struct comp_ipc_config *config = &dev->ipc_config; + void *system_agent; + + uintptr_t module_entry_point = lib_manager_allocate_module(mod, config, src_cfg); if (module_entry_point == 0) { comp_err(dev, "modules_init(), lib_manager_allocate_module() failed!"); return -EINVAL; } + + /* At this point module resources are allocated and it is moved to L2 memory. */ comp_info(dev, "modules_init() start"); - if (!module_get_private_data(mod) && - drv->adapter_ops == &processing_module_adapter_interface) { - /* First load */ - ret = modules_new(mod, buildinfo, module_entry_point); - if (ret < 0) - return ret; - } + const uint32_t module_id = IPC4_MOD_ID(config->id); + const uint32_t instance_id = IPC4_INST_ID(config->id); + const uint32_t log_handle = (uint32_t)drv->tctx; + + byte_array_t mod_cfg = { + .data = (uint8_t *)md->cfg.init_data, + /* Intel modules expects DW size here */ + .size = md->cfg.size >> 2, + }; + + system_agent = system_agent_start(module_entry_point, module_id, instance_id, 0, log_handle, + &mod_cfg); + + module_set_private_data(mod, system_agent); md->mpd.in_buff_size = src_cfg->ibs; md->mpd.out_buff_size = src_cfg->obs; - /* Call module specific init function if exists. */ - if (mod->is_native_sof) { - const struct module_interface *mod_in = drv->adapter_ops; - - /* The order of preference */ - if (mod_in->process) - mod->proc_type = MODULE_PROCESS_TYPE_SOURCE_SINK; - else if (mod_in->process_audio_stream) - mod->proc_type = MODULE_PROCESS_TYPE_STREAM; - else if (mod_in->process_raw_data) - mod->proc_type = MODULE_PROCESS_TYPE_RAW; - else - return -EINVAL; - - ret = mod_in->init(mod); - } else { - mod->proc_type = MODULE_PROCESS_TYPE_SOURCE_SINK; - ret = iadk_wrapper_init(module_get_private_data(mod)); - } - - return ret; + mod->proc_type = MODULE_PROCESS_TYPE_SOURCE_SINK; + return iadk_wrapper_init(system_agent); } /** @@ -208,7 +135,6 @@ static int modules_process(struct processing_module *mod, static int modules_free(struct processing_module *mod) { struct comp_dev *dev = mod->dev; - struct module_data *md = &mod->priv; int ret; comp_info(dev, "modules_free()"); @@ -216,13 +142,10 @@ static int modules_free(struct processing_module *mod) if (ret) comp_err(dev, "modules_free(): iadk_wrapper_free failed with error: %d", ret); - - if (!md->llext || !llext_unload(&md->llext)) { - /* Free module resources allocated in L2 memory. */ - ret = lib_manager_free_module(dev->ipc_config.id); - if (ret < 0) - comp_err(dev, "modules_free(), lib_manager_free_module() failed!"); - } + /* Free module resources allocated in L2 memory. */ + ret = lib_manager_free_module(dev->ipc_config.id); + if (ret < 0) + comp_err(dev, "modules_free(), lib_manager_free_module() failed!"); return ret; } diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 621045f43..90cfc755d 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -33,6 +33,7 @@ LOG_MODULE_REGISTER(module_adapter, CONFIG_SOF_LOG_LEVEL); * \brief 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. */ diff --git a/src/include/module/module/base.h b/src/include/module/module/base.h index a57c433dc..8eb98dd13 100644 --- a/src/include/module/module/base.h +++ b/src/include/module/module/base.h @@ -179,9 +179,6 @@ struct processing_module { */ bool stream_copy_single_to_single; - /* flag to insure that module is loadable */ - bool is_native_sof; - /* total processed data after stream started */ uint64_t total_data_consumed; uint64_t total_data_produced; diff --git a/src/include/sof/lib_manager.h b/src/include/sof/lib_manager.h index 80c016001..cae001d67 100644 --- a/src/include/sof/lib_manager.h +++ b/src/include/sof/lib_manager.h @@ -81,8 +81,11 @@ struct ipc_lib_msg { struct list_item list; }; +struct sof_man_module_manifest; + struct lib_manager_mod_ctx { void *base_addr; + const struct sof_man_module_manifest *mod_manifest; size_t segment_size[3]; }; @@ -166,7 +169,7 @@ struct processing_module; */ uintptr_t lib_manager_allocate_module(struct processing_module *proc, const struct comp_ipc_config *ipc_config, - const void *ipc_specific_config, const void **buildinfo); + const void *ipc_specific_config); /* * \brief Free module diff --git a/src/include/sof/llext_manager.h b/src/include/sof/llext_manager.h index 9730fea4c..d75dae4b4 100644 --- a/src/include/sof/llext_manager.h +++ b/src/include/sof/llext_manager.h @@ -13,7 +13,7 @@ struct comp_ipc_config; uintptr_t llext_manager_allocate_module(struct processing_module *proc, const struct comp_ipc_config *ipc_config, - const void *ipc_specific_config, const void **buildinfo); + const void *ipc_specific_config); int llext_manager_free_module(const uint32_t component_id); diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index 67b87217f..ad6a9da02 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -22,9 +22,14 @@ #include #include #include +#include +#include +#include +#include #include #include +#include #if CONFIG_LIBRARY_AUTH_SUPPORT #include @@ -340,7 +345,7 @@ static inline bool module_is_llext(const struct sof_man_module *mod) uintptr_t lib_manager_allocate_module(struct processing_module *proc, const struct comp_ipc_config *ipc_config, - const void *ipc_specific_config, const void **buildinfo) + const void *ipc_specific_config) { const struct sof_man_module *mod; const struct ipc4_base_module_cfg *base_cfg = ipc_specific_config; @@ -358,8 +363,7 @@ uintptr_t lib_manager_allocate_module(struct processing_module *proc, } if (module_is_llext(mod)) - return llext_manager_allocate_module(proc, ipc_config, ipc_specific_config, - buildinfo); + return llext_manager_allocate_module(proc, ipc_config, ipc_specific_config); ret = lib_manager_load_module(module_id, mod); if (ret < 0) @@ -495,12 +499,93 @@ const struct sof_man_module *lib_manager_get_module_manifest(const uint32_t modu } #if CONFIG_INTEL_MODULES +/* + * \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) +{ + const struct ipc_config_process *args = (struct ipc_config_process *)spec; + const uint32_t module_id = IPC4_MOD_ID(config->id); + const uint32_t instance_id = IPC4_INST_ID(config->id); + const uint32_t log_handle = (uint32_t)drv->tctx; + byte_array_t mod_cfg; + + /* + * Variable used by llext_manager to temporary store llext handle before creation + * a instance of processing_module. + */ + struct processing_module tmp_proc; + struct comp_dev *dev; + + /* At this point module resources are allocated and it is moved to L2 memory. */ + tmp_proc.priv.llext = NULL; + const uint32_t module_entry_point = lib_manager_allocate_module(&tmp_proc, config, + args->data); + + if (!module_entry_point) { + tr_err(&lib_manager_tr, + "lib_manager_module_create(), lib_manager_allocate_module() failed!"); + return NULL; + } + tr_info(&lib_manager_tr, "lib_manager_module_create() start"); + + mod_cfg.data = (uint8_t *)args->data; + /* Intel modules expects DW size here */ + mod_cfg.size = args->size >> 2; + + ((struct comp_driver *)drv)->adapter_ops = native_system_agent_start(module_entry_point, + module_id, instance_id, + 0, log_handle, + &mod_cfg); + + if (!drv->adapter_ops) { + lib_manager_free_module(module_id); + tr_err(&lib_manager_tr, + "lib_manager_module_create(), native_system_agent_start failed!"); + return NULL; + } + + dev = module_adapter_new(drv, config, spec); + if (dev) { + struct processing_module *mod = comp_get_drvdata(dev); + + mod->priv.llext = tmp_proc.priv.llext; + } + return dev; +} + +static void lib_manager_module_free(struct comp_dev *dev) +{ + struct processing_module *mod = comp_get_drvdata(dev); + struct llext *llext = mod->priv.llext; + const struct comp_ipc_config *const config = &mod->dev->ipc_config; + const uint32_t module_id = config->id; + int ret; + + /* This call invalidates dev, mod and config pointers! */ + module_adapter_free(dev); + + if (!llext || !llext_unload(&llext)) { + /* Free module resources allocated in L2 memory. */ + ret = lib_manager_free_module(module_id); + if (ret < 0) + comp_err(dev, "modules_free(), lib_manager_free_module() failed!"); + } +} + static void lib_manager_prepare_module_adapter(struct comp_driver *drv, const struct sof_uuid *uuid) { drv->type = SOF_COMP_MODULE_ADAPTER; drv->uid = uuid; drv->tctx = &lib_manager_tr; - drv->ops.create = module_adapter_new; + drv->ops.create = lib_manager_module_create; drv->ops.prepare = module_adapter_prepare; drv->ops.params = module_adapter_params; drv->ops.copy = module_adapter_copy; @@ -509,7 +594,7 @@ static void lib_manager_prepare_module_adapter(struct comp_driver *drv, const st #endif drv->ops.trigger = module_adapter_trigger; drv->ops.reset = module_adapter_reset; - drv->ops.free = module_adapter_free; + drv->ops.free = lib_manager_module_free; drv->ops.set_large_config = module_set_large_config; drv->ops.get_large_config = module_get_large_config; drv->ops.get_attribute = module_adapter_get_attribute; @@ -527,22 +612,22 @@ static void lib_manager_prepare_module_adapter(struct comp_driver *drv, const st int lib_manager_register_module(const uint32_t component_id) { - const struct lib_manager_mod_ctx *const ctx = lib_manager_get_mod_ctx(component_id); + const struct sof_man_fw_desc *const desc = lib_manager_get_library_manifest(component_id); const uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(component_id); - const struct sof_man_fw_desc *desc; + const struct sof_module_api_build_info *build_info; struct comp_driver_info *new_drv_info; struct comp_driver *drv = NULL; - struct sof_man_module *mod; + const struct sof_man_module *mod; int ret; - /* Get library manifest based on component_id */ - if (!ctx || !ctx->base_addr) + if (!desc) { + tr_err(&lib_manager_tr, "Error: Couldn't find loadable module with id %u.", + component_id); return -ENOENT; + } - desc = (const struct sof_man_fw_desc *)((const char *)ctx->base_addr + - SOF_MAN_ELF_TEXT_OFFSET); if (entry_index >= desc->header.num_module_entries) { - tr_err(&lib_manager_tr, "Entry index %d out of bounds.", entry_index); + tr_err(&lib_manager_tr, "Entry index %u out of bounds.", entry_index); return -ENOENT; } @@ -568,13 +653,44 @@ int lib_manager_register_module(const uint32_t component_id) goto cleanup; } - /* Fill the new_drv_info structure with already known parameters */ - /* Check already registered components */ - mod = (struct sof_man_module *)((uint8_t *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); + mod = (struct sof_man_module *)((const uint8_t *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); const struct sof_uuid *uid = (struct sof_uuid *)&mod->uuid[0]; lib_manager_prepare_module_adapter(drv, uid); + /* + * llext modules store build info structure in separate section which is not accessible now. + */ + if (!module_is_llext(mod)) { + build_info = (const struct sof_module_api_build_info *)((const char *)desc - + SOF_MAN_ELF_TEXT_OFFSET + + mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset); + + tr_info(&lib_manager_tr, + "lib_manager_register_module(): Module API version: %u.%u.%u, format: 0x%x", + build_info->api_version_number.fields.major, + build_info->api_version_number.fields.middle, + build_info->api_version_number.fields.minor, + build_info->format); + + /* Check if module is IADK */ + if (build_info->format == IADK_MODULE_API_BUILD_INFO_FORMAT && + build_info->api_version_number.full == IADK_MODULE_API_CURRENT_VERSION) { + /* Use module_adapter functions */ + drv->ops.create = module_adapter_new; + drv->ops.prepare = module_adapter_prepare; + } else { + /* Check if module is NOT native */ + if (build_info->format != SOF_MODULE_API_BUILD_INFO_FORMAT || + build_info->api_version_number.full != SOF_MODULE_API_CURRENT_VERSION) { + tr_err(&lib_manager_tr, + "lib_manager_register_module(): Unsupported module API version"); + return -ENOEXEC; + } + } + } + + /* Fill the new_drv_info structure with already known parameters */ new_drv_info->drv = drv; /* Register new driver in the list */ diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index 8422ad26b..6f4122234 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -181,7 +182,7 @@ static int llext_manager_link(struct sof_man_fw_desc *desc, struct sof_man_modul struct llext_load_param ldr_parm = {!ctx->segment_size[SOF_MAN_SEGMENT_TEXT]}; int ret = llext_load(&ebl.loader, mod->name, &md->llext, &ldr_parm); - if (ret < 0) + if (ret) return ret; mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr = ebl.loader.sects[LLEXT_MEM_TEXT].sh_addr; @@ -230,7 +231,7 @@ static int llext_manager_link(struct sof_man_fw_desc *desc, struct sof_man_modul uintptr_t llext_manager_allocate_module(struct processing_module *proc, const struct comp_ipc_config *ipc_config, - const void *ipc_specific_config, const void **buildinfo) + const void *ipc_specific_config) { struct sof_man_fw_desc *desc; struct sof_man_module *mod; @@ -238,7 +239,7 @@ uintptr_t llext_manager_allocate_module(struct processing_module *proc, uint32_t module_id = IPC4_MOD_ID(ipc_config->id); uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(module_id); struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); - const struct sof_man_module_manifest *mod_manifest; + const struct sof_module_api_build_info *buildinfo; tr_dbg(&lib_manager_tr, "llext_manager_allocate_module(): mod_id: %#x", ipc_config->id); @@ -252,23 +253,35 @@ uintptr_t llext_manager_allocate_module(struct processing_module *proc, mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); - ret = llext_manager_link(desc, mod, module_id, &proc->priv, buildinfo, &mod_manifest); + ret = llext_manager_link(desc, mod, module_id, &proc->priv, (const void **)&buildinfo, + &ctx->mod_manifest); if (ret < 0) return 0; - /* Map .text and the rest as .data */ - ret = llext_manager_load_module(module_id, mod); - if (ret < 0) - return 0; + if (!ret) { + /* First instance: check that the module is native */ + if (buildinfo->format != SOF_MODULE_API_BUILD_INFO_FORMAT || + buildinfo->api_version_number.full != SOF_MODULE_API_CURRENT_VERSION) { + tr_err(&lib_manager_tr, + "llext_manager_allocate_module(): Unsupported module API version"); + return -ENOEXEC; + } - ret = llext_manager_allocate_module_bss(module_id, mod); - if (ret < 0) { - tr_err(&lib_manager_tr, - "llext_manager_allocate_module(): module allocation failed: %d", ret); - return 0; + /* Map .text and the rest as .data */ + ret = llext_manager_load_module(module_id, mod); + if (ret < 0) + return 0; + + ret = llext_manager_allocate_module_bss(module_id, mod); + if (ret < 0) { + tr_err(&lib_manager_tr, + "llext_manager_allocate_module(): module allocation failed: %d", + ret); + return 0; + } } - return mod_manifest->module.entry_point; + return ctx->mod_manifest->module.entry_point; } int llext_manager_free_module(const uint32_t component_id)