From 1b2c9e3e76da1e25e3bfcf97f1607a9113ba87fb Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 7 Dec 2023 17:27:22 +0100 Subject: [PATCH 1/9] lib-manager: add support for llext Add support for loadable modules, built for dynamic linking with Zephyr's LLEXT API. Signed-off-by: Guennadi Liakhovetski --- app/prj.conf | 4 + src/audio/module_adapter/module/modules.c | 21 ++++-- src/include/sof/lib_manager.h | 2 +- src/include/sof/llext_manager.h | 2 +- src/library_manager/lib_manager.c | 12 ++- src/library_manager/llext_manager.c | 89 +++++++++++++++++++---- 6 files changed, 104 insertions(+), 26 deletions(-) diff --git a/app/prj.conf b/app/prj.conf index cd182e5be16c..5a681ac5b74b 100644 --- a/app/prj.conf +++ b/app/prj.conf @@ -53,3 +53,7 @@ CONFIG_SCHED_CPU_MASK_PIN_ONLY=y CONFIG_SYS_CLOCK_TICKS_PER_SEC=15000 CONFIG_DAI=y CONFIG_HEAP_MEM_POOL_SIZE=2048 + +CONFIG_LLEXT=y +CONFIG_LLEXT_STORAGE_WRITABLE=y +CONFIG_MODULES=y diff --git a/src/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c index 773811550af0..088a6853ae68 100644 --- a/src/audio/module_adapter/module/modules.c +++ b/src/audio/module_adapter/module/modules.c @@ -72,7 +72,9 @@ static int modules_init(struct processing_module *mod) struct comp_ipc_config *config = &(dev->ipc_config); /* At this point module resources are allocated and it is moved to L2 memory. */ - module_entry_point = lib_manager_allocate_module(dev->drv, config, src_cfg); + const void *buildinfo = NULL; + + module_entry_point = lib_manager_allocate_module(dev->drv, config, src_cfg, &buildinfo); if (module_entry_point == 0) { comp_err(dev, "modules_init(), lib_manager_allocate_module() failed!"); return -EINVAL; @@ -92,12 +94,19 @@ static int modules_init(struct processing_module *mod) comp_err(dev, "modules_init(): Failed to load manifest"); return -ENOMEM; } - struct sof_man_module *module_entry = - (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(0)); - struct sof_module_api_build_info *mod_buildinfo = - (struct sof_module_api_build_info *) - (module_entry->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr); + const struct sof_module_api_build_info *mod_buildinfo; + + if (buildinfo) { + mod_buildinfo = buildinfo; + } else { + struct sof_man_module *module_entry = + (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(0)); + + mod_buildinfo = + (struct sof_module_api_build_info *) + (module_entry->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr); + } /* Check if module is FDK */ if (mod_buildinfo->format == IADK_MODULE_API_BUILD_INFO_FORMAT && diff --git a/src/include/sof/lib_manager.h b/src/include/sof/lib_manager.h index d9c5f9239e30..b54c42c5d9e1 100644 --- a/src/include/sof/lib_manager.h +++ b/src/include/sof/lib_manager.h @@ -156,7 +156,7 @@ struct sof_man_fw_desc *lib_manager_get_library_module_desc(int module_id); */ uint32_t lib_manager_allocate_module(const struct comp_driver *drv, struct comp_ipc_config *ipc_config, - const void *ipc_specific_config); + const void *ipc_specific_config, const void **buildinfo); /* * \brief Free module diff --git a/src/include/sof/llext_manager.h b/src/include/sof/llext_manager.h index 6d1e90d70796..8a53c1f5673f 100644 --- a/src/include/sof/llext_manager.h +++ b/src/include/sof/llext_manager.h @@ -13,7 +13,7 @@ struct comp_ipc_config; uint32_t llext_manager_allocate_module(const struct comp_driver *drv, struct comp_ipc_config *ipc_config, - const void *ipc_specific_config); + const void *ipc_specific_config, const void **buildinfo); int llext_manager_free_module(const struct comp_driver *drv, struct comp_ipc_config *ipc_config); diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index 1b74c3ce748d..8e02b3533842 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -344,7 +344,7 @@ static bool module_is_llext(struct sof_man_module *mod) uint32_t lib_manager_allocate_module(const struct comp_driver *drv, struct comp_ipc_config *ipc_config, - const void *ipc_specific_config) + const void *ipc_specific_config, const void **buildinfo) { struct sof_man_fw_desc *desc; struct sof_man_module *mod; @@ -366,7 +366,8 @@ uint32_t lib_manager_allocate_module(const struct comp_driver *drv, mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); if (module_is_llext(mod)) - return llext_manager_allocate_module(drv, ipc_config, ipc_specific_config); + return llext_manager_allocate_module(drv, ipc_config, ipc_specific_config, + buildinfo); ret = lib_manager_load_module(module_id, mod); if (ret < 0) @@ -437,7 +438,7 @@ int lib_manager_free_module(const struct comp_driver *drv, uint32_t lib_manager_allocate_module(const struct comp_driver *drv, struct comp_ipc_config *ipc_config, - const void *ipc_specific_config) + const void *ipc_specific_config, const void **buildinfo) { tr_err(&lib_manager_tr, "lib_manager_allocate_module(): Dynamic module allocation is not supported"); @@ -697,7 +698,10 @@ static int lib_manager_store_library(struct lib_manager_dma_ext *dma_ext, uint32_t preload_size = man_desc->header.preload_page_count * PAGE_SZ; int ret; - /* Prepare storage memory, note: it is never freed, library unloading is unsupported */ + /* + * Prepare storage memory, note: it is never freed, it is assumed, that this + * memory is abundant, so we store all loaded modules there permanently + */ library_base_address = lib_manager_allocate_store_mem(preload_size, 0); if (!library_base_address) return -ENOMEM; diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index a0503117bd95..6fc0f6836839 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -25,6 +25,11 @@ #include #include +#include +#include +#include + +#include #include #include @@ -137,19 +142,12 @@ static void __sparse_cache *llext_manager_get_bss_address(uint32_t module_id, } static int llext_manager_allocate_module_bss(uint32_t module_id, - uint32_t is_pages, struct sof_man_module *mod) + struct sof_man_module *mod) { struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); size_t bss_size = ctx->segment_size[SOF_MAN_SEGMENT_BSS]; void __sparse_cache *va_base = llext_manager_get_bss_address(module_id, mod); - if (is_pages * PAGE_SZ > bss_size) { - tr_err(&lib_manager_tr, - "llext_manager_allocate_module_bss(): invalid is_pages: %u, required: %u", - is_pages, bss_size / PAGE_SZ); - return -ENOMEM; - } - /* Map bss memory and clear it. */ if (llext_manager_align_map(va_base, bss_size, SYS_MM_MEM_PERM_RW) < 0) return -ENOMEM; @@ -170,17 +168,77 @@ static int llext_manager_free_module_bss(uint32_t module_id, return llext_manager_align_unmap(va_base, bss_size); } +static int llext_manager_link(struct sof_man_fw_desc *desc, struct sof_man_module *mod, + uint32_t module_id, const void **buildinfo, + const struct sof_man_module_manifest **mod_manifest) +{ + size_t mod_size = desc->header.preload_page_count * PAGE_SZ; + /* FIXME: where does the module begin?? */ + struct llext_buf_loader ebl = LLEXT_BUF_LOADER((uint8_t *)desc - + SOF_MAN_ELF_TEXT_OFFSET + 0x8000, + mod_size); + struct llext *ext; + struct llext_load_param ldr_parm = {false}; + struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); + int ret = llext_load(&ebl.loader, mod->name, &ext, &ldr_parm); + + if (ret < 0) + return ret; + + mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr = ebl.loader.sects[LLEXT_MEM_TEXT].sh_addr; + mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset = (uintptr_t)ext->mem[LLEXT_MEM_TEXT] - + (uintptr_t)desc + SOF_MAN_ELF_TEXT_OFFSET; + ctx->segment_size[SOF_MAN_SEGMENT_TEXT] = ebl.loader.sects[LLEXT_MEM_TEXT].sh_size; + + tr_dbg(&lib_manager_tr, ".text: start: %#x size %#x offset %#x", + mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr, + ctx->segment_size[SOF_MAN_SEGMENT_TEXT], + mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset); + + /* This contains all other sections, except .text, it might contain .bss too */ + mod->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr = + ebl.loader.sects[LLEXT_MEM_RODATA].sh_addr; + mod->segment[SOF_MAN_SEGMENT_RODATA].file_offset = (uintptr_t)ext->mem[LLEXT_MEM_RODATA] - + (uintptr_t)desc + SOF_MAN_ELF_TEXT_OFFSET; + ctx->segment_size[SOF_MAN_SEGMENT_RODATA] = mod_size - + ebl.loader.sects[LLEXT_MEM_TEXT].sh_size; + + tr_dbg(&lib_manager_tr, ".data: start: %#x size %#x offset %#x", + mod->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr, + ctx->segment_size[SOF_MAN_SEGMENT_RODATA], + mod->segment[SOF_MAN_SEGMENT_RODATA].file_offset); + + mod->segment[SOF_MAN_SEGMENT_BSS].v_base_addr = ebl.loader.sects[LLEXT_MEM_BSS].sh_addr; + ctx->segment_size[SOF_MAN_SEGMENT_BSS] = ebl.loader.sects[LLEXT_MEM_BSS].sh_size; + + tr_dbg(&lib_manager_tr, ".bss: start: %#x size %#x", + mod->segment[SOF_MAN_SEGMENT_BSS].v_base_addr, + ctx->segment_size[SOF_MAN_SEGMENT_BSS]); + + ssize_t binfo_o = llext_find_section(&ebl.loader, ".mod_buildinfo"); + + if (binfo_o) + *buildinfo = llext_peek(&ebl.loader, binfo_o); + + ssize_t mod_o = llext_find_section(&ebl.loader, ".module"); + + if (mod_o) + *mod_manifest = llext_peek(&ebl.loader, mod_o); + + return 0; +} + uint32_t llext_manager_allocate_module(const struct comp_driver *drv, struct comp_ipc_config *ipc_config, - const void *ipc_specific_config) + const void *ipc_specific_config, const void **buildinfo) { struct sof_man_fw_desc *desc; struct sof_man_module *mod; - const struct ipc4_base_module_cfg *base_cfg = ipc_specific_config; int ret; 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; tr_dbg(&lib_manager_tr, "llext_manager_allocate_module(): mod_id: %#x", ipc_config->id); @@ -194,20 +252,23 @@ uint32_t llext_manager_allocate_module(const struct comp_driver *drv, mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); - for (unsigned int i = 0; i < ARRAY_SIZE(ctx->segment_size); i++) - ctx->segment_size[i] = mod->segment[i].flags.r.length * PAGE_SZ; + ret = llext_manager_link(desc, mod, module_id, buildinfo, &mod_manifest); + if (ret < 0) + return 0; + /* Map .text and the rest as .data */ ret = llext_manager_load_module(module_id, mod, desc); if (ret < 0) return 0; - ret = llext_manager_allocate_module_bss(module_id, base_cfg->is_pages, mod); + 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->entry_point; + + return mod_manifest->module.entry_point; } int llext_manager_free_module(const struct comp_driver *drv, From a861ae42740ffd4ac00f847aab85f5803a5898e3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 27 Oct 2023 16:42:13 +0200 Subject: [PATCH 2/9] lib-manager: migrate to module adapter context lib-manager is module-adapter specific, it doesn't need the component API and shouldn't use struct comp_driver in function arguments. Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module/modules.c | 4 ++-- src/include/sof/lib_manager.h | 5 +++-- src/include/sof/llext_manager.h | 4 ++-- src/library_manager/lib_manager.c | 12 ++++++------ src/library_manager/llext_manager.c | 4 ++-- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c index 088a6853ae68..58966fe6b201 100644 --- a/src/audio/module_adapter/module/modules.c +++ b/src/audio/module_adapter/module/modules.c @@ -74,7 +74,7 @@ static int modules_init(struct processing_module *mod) /* At this point module resources are allocated and it is moved to L2 memory. */ const void *buildinfo = NULL; - module_entry_point = lib_manager_allocate_module(dev->drv, config, src_cfg, &buildinfo); + module_entry_point = lib_manager_allocate_module(mod, config, src_cfg, &buildinfo); if (module_entry_point == 0) { comp_err(dev, "modules_init(), lib_manager_allocate_module() failed!"); return -EINVAL; @@ -294,7 +294,7 @@ static int modules_free(struct processing_module *mod) rfree(md->mpd.out_buff); /* Free module resources allocated in L2 memory. */ - ret = lib_manager_free_module(dev->drv, config); + ret = lib_manager_free_module(mod, config); if (ret < 0) comp_err(dev, "modules_free(), lib_manager_free_module() failed!"); diff --git a/src/include/sof/lib_manager.h b/src/include/sof/lib_manager.h index b54c42c5d9e1..f78740326278 100644 --- a/src/include/sof/lib_manager.h +++ b/src/include/sof/lib_manager.h @@ -144,6 +144,7 @@ int lib_manager_register_module(struct sof_man_fw_desc *desc, int module_id); */ struct sof_man_fw_desc *lib_manager_get_library_module_desc(int module_id); +struct processing_module; /* * \brief Allocate module * @@ -154,7 +155,7 @@ struct sof_man_fw_desc *lib_manager_get_library_module_desc(int module_id); * Function is responsible to allocate module in available free memory and assigning proper address. * (WIP) These feature will contain module validation and proper memory management. */ -uint32_t lib_manager_allocate_module(const struct comp_driver *drv, +uint32_t lib_manager_allocate_module(struct processing_module *proc, struct comp_ipc_config *ipc_config, const void *ipc_specific_config, const void **buildinfo); @@ -167,7 +168,7 @@ uint32_t lib_manager_allocate_module(const struct comp_driver *drv, * * Function is responsible to free module resources in HP memory. */ -int lib_manager_free_module(const struct comp_driver *drv, +int lib_manager_free_module(struct processing_module *proc, struct comp_ipc_config *ipc_config); /* * \brief Load library diff --git a/src/include/sof/llext_manager.h b/src/include/sof/llext_manager.h index 8a53c1f5673f..c77564d99537 100644 --- a/src/include/sof/llext_manager.h +++ b/src/include/sof/llext_manager.h @@ -11,10 +11,10 @@ struct comp_driver; struct comp_ipc_config; -uint32_t llext_manager_allocate_module(const struct comp_driver *drv, +uint32_t llext_manager_allocate_module(struct processing_module *proc, struct comp_ipc_config *ipc_config, const void *ipc_specific_config, const void **buildinfo); -int llext_manager_free_module(const struct comp_driver *drv, +int llext_manager_free_module(struct processing_module *proc, struct comp_ipc_config *ipc_config); #endif diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index 8e02b3533842..71b29e3b06bb 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -342,7 +342,7 @@ static bool module_is_llext(struct sof_man_module *mod) return mod->type.load_type == SOF_MAN_MOD_TYPE_LLEXT; } -uint32_t lib_manager_allocate_module(const struct comp_driver *drv, +uint32_t lib_manager_allocate_module(struct processing_module *proc, struct comp_ipc_config *ipc_config, const void *ipc_specific_config, const void **buildinfo) { @@ -366,7 +366,7 @@ uint32_t lib_manager_allocate_module(const struct comp_driver *drv, mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); if (module_is_llext(mod)) - return llext_manager_allocate_module(drv, ipc_config, ipc_specific_config, + return llext_manager_allocate_module(proc, ipc_config, ipc_specific_config, buildinfo); ret = lib_manager_load_module(module_id, mod); @@ -396,7 +396,7 @@ uint32_t lib_manager_allocate_module(const struct comp_driver *drv, return 0; } -int lib_manager_free_module(const struct comp_driver *drv, +int lib_manager_free_module(struct processing_module *proc, struct comp_ipc_config *ipc_config) { struct sof_man_fw_desc *desc; @@ -411,7 +411,7 @@ int lib_manager_free_module(const struct comp_driver *drv, mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); if (module_is_llext(mod)) - return llext_manager_free_module(drv, ipc_config); + return llext_manager_free_module(proc, ipc_config); ret = lib_manager_unload_module(mod); if (ret < 0) @@ -436,7 +436,7 @@ int lib_manager_free_module(const struct comp_driver *drv, #define PAGE_SZ 4096 /* equals to MAN_PAGE_SIZE used by rimage */ -uint32_t lib_manager_allocate_module(const struct comp_driver *drv, +uint32_t lib_manager_allocate_module(struct processing_module *proc, struct comp_ipc_config *ipc_config, const void *ipc_specific_config, const void **buildinfo) { @@ -445,7 +445,7 @@ uint32_t lib_manager_allocate_module(const struct comp_driver *drv, return 0; } -int lib_manager_free_module(const struct comp_driver *drv, +int lib_manager_free_module(struct processing_module *proc, struct comp_ipc_config *ipc_config) { /* Since we cannot allocate the freeing is not considered to be an error */ diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index 6fc0f6836839..68c9a2ed1b22 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -228,7 +228,7 @@ static int llext_manager_link(struct sof_man_fw_desc *desc, struct sof_man_modul return 0; } -uint32_t llext_manager_allocate_module(const struct comp_driver *drv, +uint32_t llext_manager_allocate_module(struct processing_module *proc, struct comp_ipc_config *ipc_config, const void *ipc_specific_config, const void **buildinfo) { @@ -271,7 +271,7 @@ uint32_t llext_manager_allocate_module(const struct comp_driver *drv, return mod_manifest->module.entry_point; } -int llext_manager_free_module(const struct comp_driver *drv, +int llext_manager_free_module(struct processing_module *proc, struct comp_ipc_config *ipc_config) { struct sof_man_fw_desc *desc; From ec0038ea2189c93390a05bdf68c5c8793b6b4d52 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 27 Oct 2023 17:00:25 +0200 Subject: [PATCH 3/9] module-adapter: add Zephyr extension context Module adapter drivers can be loaded and unloaded, using the Zephyr loadable extension API. Add its context to struct struct module_data. Signed-off-by: Guennadi Liakhovetski --- src/include/module/module/base.h | 3 +++ src/library_manager/llext_manager.c | 13 +++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/include/module/module/base.h b/src/include/module/module/base.h index 323599b055f2..55e61ada27f9 100644 --- a/src/include/module/module/base.h +++ b/src/include/module/module/base.h @@ -37,6 +37,8 @@ struct module_config { #endif }; +struct llext; + /* * A structure containing a module's private data, intended for its exclusive use. * @@ -61,6 +63,7 @@ struct module_data { struct module_processing_data mpd; /**< shared data comp <-> module */ void *module_adapter; /**header.preload_page_count * PAGE_SZ; @@ -177,16 +177,16 @@ static int llext_manager_link(struct sof_man_fw_desc *desc, struct sof_man_modul struct llext_buf_loader ebl = LLEXT_BUF_LOADER((uint8_t *)desc - SOF_MAN_ELF_TEXT_OFFSET + 0x8000, mod_size); - struct llext *ext; struct llext_load_param ldr_parm = {false}; struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); - int ret = llext_load(&ebl.loader, mod->name, &ext, &ldr_parm); + int ret = llext_load(&ebl.loader, mod->name, &md->llext, &ldr_parm); if (ret < 0) return ret; mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr = ebl.loader.sects[LLEXT_MEM_TEXT].sh_addr; - mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset = (uintptr_t)ext->mem[LLEXT_MEM_TEXT] - + mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset = + (uintptr_t)md->llext->mem[LLEXT_MEM_TEXT] - (uintptr_t)desc + SOF_MAN_ELF_TEXT_OFFSET; ctx->segment_size[SOF_MAN_SEGMENT_TEXT] = ebl.loader.sects[LLEXT_MEM_TEXT].sh_size; @@ -198,7 +198,8 @@ static int llext_manager_link(struct sof_man_fw_desc *desc, struct sof_man_modul /* This contains all other sections, except .text, it might contain .bss too */ mod->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr = ebl.loader.sects[LLEXT_MEM_RODATA].sh_addr; - mod->segment[SOF_MAN_SEGMENT_RODATA].file_offset = (uintptr_t)ext->mem[LLEXT_MEM_RODATA] - + mod->segment[SOF_MAN_SEGMENT_RODATA].file_offset = + (uintptr_t)md->llext->mem[LLEXT_MEM_RODATA] - (uintptr_t)desc + SOF_MAN_ELF_TEXT_OFFSET; ctx->segment_size[SOF_MAN_SEGMENT_RODATA] = mod_size - ebl.loader.sects[LLEXT_MEM_TEXT].sh_size; @@ -252,7 +253,7 @@ uint32_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, buildinfo, &mod_manifest); + ret = llext_manager_link(desc, mod, module_id, &proc->priv, buildinfo, &mod_manifest); if (ret < 0) return 0; From 76edab33ada1db862ef27a3e8055dcde925cea99 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 2 Nov 2023 16:43:30 +0100 Subject: [PATCH 4/9] lib-manager: fix a wrongly named .desc pointer Pointers that we store in a global array for each loaded library, aren't really firmware manifest descriptor pointers, they're pointers to storage buffers, where entire libraries are stored. A SOF_MAN_ELF_TEXT_OFFSET offset has to be added to that address to get to the manifest descriptor. Signed-off-by: Guennadi Liakhovetski --- src/include/sof/lib_manager.h | 2 +- src/library_manager/lib_manager.c | 8 ++++---- src/library_manager/llext_manager.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/include/sof/lib_manager.h b/src/include/sof/lib_manager.h index f78740326278..df23d29ead43 100644 --- a/src/include/sof/lib_manager.h +++ b/src/include/sof/lib_manager.h @@ -82,7 +82,7 @@ struct ipc_lib_msg { }; struct lib_manager_mod_ctx { - struct sof_man_fw_desc *desc; + void *base_addr; size_t segment_size[3]; }; diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index 71b29e3b06bb..3d49f27c9847 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -150,7 +150,7 @@ static int lib_manager_load_module(const uint32_t module_id, const struct sof_man_module *const mod) { struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); - const uintptr_t load_offset = POINTER_TO_UINT(ctx->desc); + const uintptr_t load_offset = POINTER_TO_UINT(ctx->base_addr); void *src; void __sparse_cache *va_base; size_t size; @@ -466,21 +466,21 @@ void lib_manager_init(void) struct sof_man_fw_desc *lib_manager_get_library_module_desc(int module_id) { struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); - uint8_t *buffptr = (uint8_t *)(ctx ? ctx->desc : NULL); + uint8_t *buffptr = ctx ? ctx->base_addr : NULL; if (!buffptr) return NULL; return (struct sof_man_fw_desc *)(buffptr + SOF_MAN_ELF_TEXT_OFFSET); } -static void lib_manager_update_sof_ctx(struct sof_man_fw_desc *desc, uint32_t lib_id) +static void lib_manager_update_sof_ctx(void *base_addr, uint32_t lib_id) { struct ext_library *_ext_lib = ext_lib_get(); /* Never freed, will panic if fails */ struct lib_manager_mod_ctx *ctx = rmalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, sizeof(*ctx)); - ctx->desc = desc; + ctx->base_addr = base_addr; _ext_lib->desc[lib_id] = ctx; /* TODO: maybe need to call dcache_writeback here? */ diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index 7e10ceb9994f..2f974f457b38 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -77,7 +77,7 @@ static int llext_manager_load_module(uint32_t module_id, struct sof_man_module * struct sof_man_fw_desc *desc) { struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); - uint8_t *load_base = (uint8_t *)ctx->desc; + uint8_t *load_base = (uint8_t *)ctx->base_addr; void __sparse_cache *va_base_text = (void __sparse_cache *) mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr; void *src_txt = (void *)(load_base + mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset); From 387bd4f8fcac1f2bad20a9082ad30fce1814e6d4 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 2 Nov 2023 17:29:56 +0100 Subject: [PATCH 5/9] module: (cosmetic) regroup some declarations and assignments Regroup code in modules_init() to move declarations and assignments closer to where they're needed. Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module/modules.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c index 58966fe6b201..e4525ea3859d 100644 --- a/src/audio/module_adapter/module/modules.c +++ b/src/audio/module_adapter/module/modules.c @@ -62,15 +62,7 @@ static int modules_init(struct processing_module *mod) struct module_data *md = &mod->priv; struct comp_dev *dev = mod->dev; const struct ipc4_base_module_cfg *src_cfg = &md->cfg.base_cfg; - byte_array_t mod_cfg; - - mod_cfg.data = (uint8_t *)md->cfg.init_data; - /* Intel modules expects DW size here */ - mod_cfg.size = md->cfg.size >> 2; - md->private = mod; - 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; @@ -79,7 +71,6 @@ static int modules_init(struct processing_module *mod) comp_err(dev, "modules_init(), lib_manager_allocate_module() failed!"); return -EINVAL; } - md->module_entry_point = module_entry_point; comp_info(dev, "modules_init() start"); uint32_t module_id = IPC4_MOD_ID(dev->ipc_config.id); @@ -108,10 +99,16 @@ static int modules_init(struct processing_module *mod) (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) { - md->module_adapter = (void *)system_agent_start(md->module_entry_point, module_id, + md->module_adapter = (void *)system_agent_start(module_entry_point, module_id, instance_id, 0, log_handle, &mod_cfg); } else @@ -120,12 +117,15 @@ static int modules_init(struct processing_module *mod) mod_buildinfo->api_version_number.full == SOF_MODULE_API_CURRENT_VERSION) { /* If start agent for sof loadable */ mod->is_native_sof = true; - md->ops = native_system_agent_start(mod->sys_service, md->module_entry_point, + md->ops = native_system_agent_start(mod->sys_service, module_entry_point, module_id, instance_id, 0, log_handle, &mod_cfg); } else return -ENOEXEC; + md->module_entry_point = module_entry_point; + md->private = mod; + /* Allocate module buffers */ md->mpd.in_buff = rballoc(0, SOF_MEM_CAPS_RAM, src_cfg->ibs); if (!md->mpd.in_buff) { From a2fd06b37e18f6cbc08ceab08f3cdd9df99ff89a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 2 Nov 2023 17:52:25 +0100 Subject: [PATCH 6/9] lib-manager: use an appropriate type for a pointer integer lib_manager_allocate_module() returns a pointer as an integer, use uintptr_t for it. Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module/modules.c | 4 ++-- src/include/module/module/base.h | 2 +- src/include/sof/lib_manager.h | 6 +++--- src/include/sof/llext_manager.h | 6 +++--- src/library_manager/lib_manager.c | 12 ++++++------ src/library_manager/llext_manager.c | 6 +++--- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c index e4525ea3859d..4aef4ea9ad85 100644 --- a/src/audio/module_adapter/module/modules.c +++ b/src/audio/module_adapter/module/modules.c @@ -58,15 +58,15 @@ DECLARE_TR_CTX(intel_codec_tr, SOF_UUID(intel_uuid), LOG_LEVEL_INFO); */ static int modules_init(struct processing_module *mod) { - uint32_t module_entry_point; struct module_data *md = &mod->priv; struct comp_dev *dev = mod->dev; 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; + uintptr_t module_entry_point = lib_manager_allocate_module(mod, config, src_cfg, + &buildinfo); - module_entry_point = lib_manager_allocate_module(mod, config, src_cfg, &buildinfo); if (module_entry_point == 0) { comp_err(dev, "modules_init(), lib_manager_allocate_module() failed!"); return -EINVAL; diff --git a/src/include/module/module/base.h b/src/include/module/module/base.h index 55e61ada27f9..69e216435033 100644 --- a/src/include/module/module/base.h +++ b/src/include/module/module/base.h @@ -62,7 +62,7 @@ struct module_data { struct module_memory memory; /**< memory allocated by module */ struct module_processing_data mpd; /**< shared data comp <-> module */ void *module_adapter; /**type.load_type == SOF_MAN_MOD_TYPE_LLEXT; } -uint32_t lib_manager_allocate_module(struct processing_module *proc, - struct comp_ipc_config *ipc_config, - const void *ipc_specific_config, const void **buildinfo) +uintptr_t lib_manager_allocate_module(struct processing_module *proc, + struct comp_ipc_config *ipc_config, + const void *ipc_specific_config, const void **buildinfo) { struct sof_man_fw_desc *desc; struct sof_man_module *mod; @@ -436,9 +436,9 @@ int lib_manager_free_module(struct processing_module *proc, #define PAGE_SZ 4096 /* equals to MAN_PAGE_SIZE used by rimage */ -uint32_t lib_manager_allocate_module(struct processing_module *proc, - struct comp_ipc_config *ipc_config, - const void *ipc_specific_config, const void **buildinfo) +uintptr_t lib_manager_allocate_module(struct processing_module *proc, + struct comp_ipc_config *ipc_config, + const void *ipc_specific_config, const void **buildinfo) { tr_err(&lib_manager_tr, "lib_manager_allocate_module(): Dynamic module allocation is not supported"); diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index 2f974f457b38..23ded81f9a10 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -229,9 +229,9 @@ static int llext_manager_link(struct sof_man_fw_desc *desc, struct sof_man_modul return 0; } -uint32_t llext_manager_allocate_module(struct processing_module *proc, - struct comp_ipc_config *ipc_config, - const void *ipc_specific_config, const void **buildinfo) +uintptr_t llext_manager_allocate_module(struct processing_module *proc, + struct comp_ipc_config *ipc_config, + const void *ipc_specific_config, const void **buildinfo) { struct sof_man_fw_desc *desc; struct sof_man_module *mod; From 19dee614e249121bb77abb0cd564948aecb91a0f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 6 Mar 2024 12:32:39 +0100 Subject: [PATCH 7/9] modules: split modules_init() into two parts The first part modules_new() is only needed when a new module is registered, the rest is needed every time a module is instantiated. Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module/modules.c | 81 +++++++++++++---------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/src/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c index 4aef4ea9ad85..4818925b9688 100644 --- a/src/audio/module_adapter/module/modules.c +++ b/src/audio/module_adapter/module/modules.c @@ -49,38 +49,18 @@ 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); -/** - * \brief modules_init. - * \param[in] mod - processing module pointer. - * - * \return: zero on success - * error code on failure - */ -static int modules_init(struct processing_module *mod) +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; - 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; - uintptr_t module_entry_point = lib_manager_allocate_module(mod, config, src_cfg, - &buildinfo); - - if (module_entry_point == 0) { - comp_err(dev, "modules_init(), lib_manager_allocate_module() failed!"); - return -EINVAL; - } - comp_info(dev, "modules_init() start"); - 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 */ - struct sof_man_fw_desc *desc; + struct sof_man_fw_desc *desc = lib_manager_get_library_module_desc(module_id); - desc = lib_manager_get_library_module_desc(module_id); if (!desc) { comp_err(dev, "modules_init(): Failed to load manifest"); return -ENOMEM; @@ -108,24 +88,55 @@ static int modules_init(struct processing_module *mod) /* 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) { - md->module_adapter = (void *)system_agent_start(module_entry_point, module_id, - instance_id, 0, log_handle, - &mod_cfg); - } else - /* Check if module is native */ - if (mod_buildinfo->format == SOF_MODULE_API_BUILD_INFO_FORMAT && - mod_buildinfo->api_version_number.full == SOF_MODULE_API_CURRENT_VERSION) { - /* If start agent for sof loadable */ + md->module_adapter = (void *)system_agent_start(module_entry_point, + module_id, instance_id, + 0, log_handle, &mod_cfg); + } 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; md->ops = native_system_agent_start(mod->sys_service, module_entry_point, - module_id, instance_id, 0, log_handle, - &mod_cfg); - } else + module_id, instance_id, + 0, log_handle, &mod_cfg); + } else { return -ENOEXEC; + } md->module_entry_point = module_entry_point; md->private = mod; + return 0; +} + +/** + * \brief modules_init. + * \param[in] mod - processing module pointer. + * + * \return: zero on success + * error code on failure + */ +static int modules_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + 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; + uintptr_t module_entry_point = lib_manager_allocate_module(mod, config, src_cfg, + &buildinfo); + + if (module_entry_point == 0) { + comp_err(dev, "modules_init(), lib_manager_allocate_module() failed!"); + return -EINVAL; + } + comp_info(dev, "modules_init() start"); + + int ret = modules_new(mod, buildinfo, module_entry_point); + + if (ret < 0) + return ret; + /* Allocate module buffers */ md->mpd.in_buff = rballoc(0, SOF_MEM_CAPS_RAM, src_cfg->ibs); if (!md->mpd.in_buff) { @@ -142,8 +153,6 @@ static int modules_init(struct processing_module *mod) } md->mpd.out_buff_size = src_cfg->obs; - int ret; - /* Call module specific init function if exists. */ if (mod->is_native_sof) { const struct module_interface *mod_in = md->ops; From 92d84b1b15737131cef526d2fb96f1e59c30ca4a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 6 Mar 2024 13:00:57 +0100 Subject: [PATCH 8/9] modules: don't re-load on each restart While modules are in use, no need to unload and re-load them, re-initialising audio interfaces is enough. With llext modules this uses the LLEXT reference counting to identify when a module should be unloaded. Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module/modules.c | 30 ++++++++++++++++------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c index 4818925b9688..04b8a27e0c50 100644 --- a/src/audio/module_adapter/module/modules.c +++ b/src/audio/module_adapter/module/modules.c @@ -14,6 +14,7 @@ #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 @@ -49,6 +50,8 @@ 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 const struct module_interface interface; + static int modules_new(struct processing_module *mod, const void *buildinfo, uintptr_t module_entry_point) { @@ -123,6 +126,7 @@ static int modules_init(struct processing_module *mod) 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); @@ -132,10 +136,12 @@ static int modules_init(struct processing_module *mod) } comp_info(dev, "modules_init() start"); - int ret = modules_new(mod, buildinfo, module_entry_point); - - if (ret < 0) - return ret; + if (!md->module_adapter && md->ops == &interface) { + /* First load */ + ret = modules_new(mod, buildinfo, module_entry_point); + if (ret < 0) + return ret; + } /* Allocate module buffers */ md->mpd.in_buff = rballoc(0, SOF_MEM_CAPS_RAM, src_cfg->ibs); @@ -289,7 +295,7 @@ static int modules_free(struct processing_module *mod) struct comp_dev *dev = mod->dev; struct module_data *md = &mod->priv; struct comp_ipc_config *config = &(mod->dev->ipc_config); - int ret = 0; + int ret; comp_info(dev, "modules_free()"); if (mod->is_native_sof) { @@ -299,13 +305,19 @@ static int modules_free(struct processing_module *mod) } else { ret = iadk_wrapper_free(mod->priv.module_adapter); } + + if (ret < 0) + comp_err(dev, "Failed to free a module: %d", ret); + rfree(md->mpd.in_buff); rfree(md->mpd.out_buff); - /* Free module resources allocated in L2 memory. */ - ret = lib_manager_free_module(mod, config); - if (ret < 0) - comp_err(dev, "modules_free(), lib_manager_free_module() failed!"); + if (!md->llext || !llext_unload(&md->llext)) { + /* Free module resources allocated in L2 memory. */ + ret = lib_manager_free_module(mod, config); + if (ret < 0) + comp_err(dev, "modules_free(), lib_manager_free_module() failed!"); + } return ret; } From c067427f93ee3522d5d8beb9988d41188adb3d1c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 7 Dec 2023 17:53:43 +0100 Subject: [PATCH 9/9] smart-amp-test: make a loadable module Convert the smart-amp-test in its IPC4 version to a loadable LLEXT module. Use an overlay configuration to select between monolithic and modular builds. Signed-off-by: Guennadi Liakhovetski --- app/overlays/mtl/module_overlay.conf | 1 + scripts/llext_link_helper.py | 56 ++++++++++++++ src/samples/audio/Kconfig | 2 +- .../audio/smart_amp_llext/CMakeLists.txt | 75 +++++++++++++++++++ .../audio/smart_amp_llext/llext.toml.h | 5 ++ src/samples/audio/smart_amp_test_ipc4.c | 60 ++++++++++++--- zephyr/CMakeLists.txt | 12 ++- 7 files changed, 198 insertions(+), 13 deletions(-) create mode 100644 app/overlays/mtl/module_overlay.conf create mode 100755 scripts/llext_link_helper.py create mode 100644 src/samples/audio/smart_amp_llext/CMakeLists.txt create mode 100644 src/samples/audio/smart_amp_llext/llext.toml.h diff --git a/app/overlays/mtl/module_overlay.conf b/app/overlays/mtl/module_overlay.conf new file mode 100644 index 000000000000..172a8ea28e82 --- /dev/null +++ b/app/overlays/mtl/module_overlay.conf @@ -0,0 +1 @@ +CONFIG_SAMPLE_SMART_AMP=m diff --git a/scripts/llext_link_helper.py b/scripts/llext_link_helper.py new file mode 100755 index 000000000000..1b8ad8c86221 --- /dev/null +++ b/scripts/llext_link_helper.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause + +# We need to calculate ELF section addresses of an LLEXT module and use them to +# run the linker. We could just use Python to calculate addresses and pass them +# back to cmake to have it call the linker. However, there doesn't seem to be a +# portable way to do that. Therefore we pass the linker path and all the command +# line parameters to this script and call the linker directly. + +import argparse +import subprocess +from elftools.elf.elffile import ELFFile + +args = None +def parse_args(): + global args + + parser = argparse.ArgumentParser(description='Helper utility to run a linker command ' + 'with calculated ELF section addresses') + + parser.add_argument('command', type=str, help='Linker command to execute') + parser.add_argument('params', nargs='+', help='Additional linker parameters') + parser.add_argument("-f", "--file", required=True, type=str, + help='Object file name') + parser.add_argument("-t", "--text-addr", required=True, type=str, + help='.text section address') + + args = parser.parse_args() + +def main(): + parse_args() + + elf = ELFFile(open(args.file, 'rb')) + + text_addr = int(args.text_addr, 0) + + text_offset = elf.get_section_by_name('.text').header.sh_offset + rodata_offset = elf.get_section_by_name('.rodata').header.sh_offset + data_offset = elf.get_section_by_name('.data').header.sh_offset + + upper = rodata_offset - text_offset + text_addr + 0xfff + rodata_addr = upper - (upper % 0x1000) + + upper = data_offset - rodata_offset + rodata_addr + 0xf + data_addr = upper - (upper % 0x10) + + command = [args.command, + f'-Wl,-Ttext=0x{text_addr:x}', + f'-Wl,--section-start=.rodata=0x{rodata_addr:x}', + f'-Wl,-Tdata=0x{data_addr:x}'] + command.extend(args.params) + + subprocess.run(command) + +if __name__ == "__main__": + main() diff --git a/src/samples/audio/Kconfig b/src/samples/audio/Kconfig index a427f0b3172f..e853b0668f1a 100644 --- a/src/samples/audio/Kconfig +++ b/src/samples/audio/Kconfig @@ -3,7 +3,7 @@ menu "Audio component samples" config SAMPLE_SMART_AMP - bool "Smart amplifier test component" + tristate "Smart amplifier test component" default y help Select for test smart amplifier component diff --git a/src/samples/audio/smart_amp_llext/CMakeLists.txt b/src/samples/audio/smart_amp_llext/CMakeLists.txt new file mode 100644 index 000000000000..006e53b79f66 --- /dev/null +++ b/src/samples/audio/smart_amp_llext/CMakeLists.txt @@ -0,0 +1,75 @@ +# Copyright (c) 2023 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(smart_amp_test) + +SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE) + +set(MODULE "smart_amp_test") +cmake_path(SET SOF_BASE NORMALIZE ${PROJECT_SOURCE_DIR}/../../../..) + +add_library(${MODULE} SHARED) + +target_sources(${MODULE} PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/../smart_amp_test_ipc4.c +) + +sof_append_relative_path_definitions(${MODULE}) + +target_include_directories(${MODULE} PRIVATE + "${ZEPHYR_BASE}/include" + "${ZEPHYR_BASE}/soc/xtensa/intel_adsp/common/include" + "${ZEPHYR_BASE}/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm" + "${ZEPHYR_BASE}/../modules/hal/xtensa/include" + "${ZEPHYR_BASE}/../modules/hal/xtensa/zephyr/soc/intel_ace15_mtpm" + "${SOF_BASE}/src/include" + "${SOF_BASE}/src/arch/xtensa/include" + "${SOF_BASE}/src/platform/meteorlake/include" + "${SOF_BASE}/src/platform/intel/ace/include" + "${SOF_BASE}/src/include/sof/audio/module_adapter/iadk" + "${SOF_BASE}/zephyr/include" + "${SOF_BASE}/xtos/include" + "${SOF_BASE}/tools/rimage/src/include" + "${PROJECT_BINARY_DIR}/../include/generated" +) + +set(MODULE_PROPERTIES HPSRAM_ADDR "0xa06c1000") +set_target_properties(${MODULE} PROPERTIES ${MODULE_PROPERTIES}) + +set(MODULE_COMPILE_DEF + __ZEPHYR__=1 + __XTENSA__ + KERNEL + MAJOR_IADSP_API_VERSION=5 + MIDDLE_IADSP_API_VERSION=0 + MINOR_IADSP_API_VERSION=0 +) +target_compile_definitions(${MODULE} PRIVATE ${MODULE_COMPILE_DEF}) + +target_compile_options(${MODULE} PRIVATE + -imacros${PROJECT_BINARY_DIR}/../include/generated/autoconf.h + -save-temps -O2 +) + +set(MODULE_LINKER_PARAMS -nostdlib -nodefaultlibs) +target_link_options(${MODULE} PRIVATE + ${MODULE_LINKER_PARAMS} +) + +add_custom_command(OUTPUT lib${MODULE}_out.so + DEPENDS ${MODULE} + COMMAND ${SOF_BASE}scripts/llext_link_helper.py + -f lib${MODULE}.so -t "0xa06ca000" ${CMAKE_C_COMPILER} -- + ${MODULE_LINKER_PARAMS} -shared -fPIC + -o lib${MODULE}_llext.so $ + COMMAND ${CMAKE_STRIP} -R .xt.* -o lib${MODULE}_out.so lib${MODULE}_llext.so + COMMAND_EXPAND_LISTS +) + +add_custom_target(${MODULE}_llext ALL + DEPENDS lib${MODULE}_out.so +) + +add_dependencies(${MODULE} zephyr_interface) diff --git a/src/samples/audio/smart_amp_llext/llext.toml.h b/src/samples/audio/smart_amp_llext/llext.toml.h new file mode 100644 index 000000000000..350cdc076e06 --- /dev/null +++ b/src/samples/audio/smart_amp_llext/llext.toml.h @@ -0,0 +1,5 @@ +#include +#include "../smart_amp_test.toml" + +[module] +count = __COUNTER__ diff --git a/src/samples/audio/smart_amp_test_ipc4.c b/src/samples/audio/smart_amp_test_ipc4.c index f6ffd6dae115..13f5f866e9a9 100644 --- a/src/samples/audio/smart_amp_test_ipc4.c +++ b/src/samples/audio/smart_amp_test_ipc4.c @@ -33,16 +33,16 @@ DECLARE_TR_CTX(smart_amp_test_comp_tr, SOF_UUID(smart_amp_test_comp_uuid), #include #include -#include #include #include -#include #include