diff --git a/src/include/sof/lib_manager.h b/src/include/sof/lib_manager.h index fb277ac75f64..019695be69ef 100644 --- a/src/include/sof/lib_manager.h +++ b/src/include/sof/lib_manager.h @@ -123,6 +123,7 @@ struct lib_manager_module { struct lib_manager_mod_ctx { void *base_addr; /* library cold storage address (e.g. DRAM) */ unsigned int n_mod; + unsigned int load_type; struct lib_manager_module *mod; }; diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index 1b1dd5f2cc9e..a672f51133d2 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -423,15 +423,18 @@ static int lib_manager_free_module(const uint32_t component_id) tr_dbg(&lib_manager_tr, "mod_id: %#x", component_id); + const struct lib_manager_mod_ctx *const ctx = lib_manager_get_mod_ctx(module_id); + + if (ctx->load_type == SOF_MAN_MOD_TYPE_LLEXT || + ctx->load_type == SOF_MAN_MOD_TYPE_LLEXT_AUX) + return llext_manager_free_module(component_id); + mod = lib_manager_get_module_manifest(module_id); if (!mod) { tr_err(&lib_manager_tr, "failed to get module descriptor"); return -EINVAL; } - if (module_is_llext(mod)) - return llext_manager_free_module(component_id); - ret = lib_manager_unload_module(mod); if (ret < 0) return ret; @@ -500,6 +503,7 @@ static void lib_manager_update_sof_ctx(void *base_addr, uint32_t lib_id) } ctx->base_addr = base_addr; + ctx->load_type = SOF_MAN_MOD_TYPE_MODULE; _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 4ad3c55d55bc..bcbfd290ceb0 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -168,6 +168,38 @@ static int llext_manager_load_data_from_storage(const struct sys_mm_drv_region * return ret; } +#ifdef CONFIG_USERSPACE +static int llext_manager_add_partition(struct k_mem_domain *domain, + uintptr_t addr, size_t size, + k_mem_partition_attr_t attr) +{ + size_t pre_pad_size = addr & (PAGE_SZ - 1); + struct k_mem_partition part = { + .start = addr - pre_pad_size, + .size = ALIGN_UP(pre_pad_size + size, PAGE_SZ), + .attr = attr, + }; + + tr_dbg(&lib_manager_tr, "add %#zx @ %lx partition", part.size, part.start); + return k_mem_domain_add_partition(domain, &part); +} + +static int llext_manager_rm_partition(struct k_mem_domain *domain, + uintptr_t addr, size_t size, + k_mem_partition_attr_t attr) +{ + size_t pre_pad_size = addr & (PAGE_SZ - 1); + struct k_mem_partition part = { + .start = addr - pre_pad_size, + .size = ALIGN_UP(pre_pad_size + size, PAGE_SZ), + .attr = attr, + }; + + tr_dbg(&lib_manager_tr, "remove %#zx @ %lx partition", part.size, part.start); + return k_mem_domain_remove_partition(domain, &part); +} +#endif + static void llext_manager_unmap_detached_sections(const struct llext_loader *ldr, const struct llext *ext, enum llext_mem region, @@ -350,6 +382,19 @@ static int llext_manager_unload_module(struct lib_manager_module *mctx) mctx->segment[LIB_MANAGER_BSS].size; int err = 0, ret; +#ifdef CONFIG_SOF_USERSPACE_LL + unsigned int sect_cnt = llext_section_count(ext); + size_t total = sect_cnt * sizeof(elf_shdr_t); + const elf_shdr_t *shdr; + + ret = llext_get_section_info(ldr, ext, 0, &shdr, NULL, NULL); + if (ret < 0) + return ret; + + /* Temporarily map ELF section headers */ + llext_manager_add_partition(zephyr_ll_mem_domain(), (uintptr_t)shdr, total, + K_MEM_PARTITION_P_RW_U_NA | XTENSA_MMU_CACHED_WB); +#endif llext_manager_unmap_detached_sections(ldr, ext, LLEXT_MEM_TEXT, va_base_text, text_size); ret = llext_manager_align_unmap(va_base_text, text_size); @@ -374,6 +419,10 @@ static int llext_manager_unload_module(struct lib_manager_module *mctx) if (ret < 0 && !err) err = ret; +#ifdef CONFIG_SOF_USERSPACE_LL + llext_manager_rm_partition(zephyr_ll_mem_domain(), (uintptr_t)shdr, total, + K_MEM_PARTITION_P_RW_U_NA | XTENSA_MMU_CACHED_WB); +#endif mctx->mapped = false; #ifdef CONFIG_SOF_USERSPACE_LL @@ -794,35 +843,6 @@ uintptr_t llext_manager_allocate_module(const struct comp_ipc_config *ipc_config } #ifdef CONFIG_USERSPACE -static int llext_manager_add_partition(struct k_mem_domain *domain, - uintptr_t addr, size_t size, - k_mem_partition_attr_t attr) -{ - size_t pre_pad_size = addr & (PAGE_SZ - 1); - struct k_mem_partition part = { - .start = addr - pre_pad_size, - .size = ALIGN_UP(pre_pad_size + size, PAGE_SZ), - .attr = attr, - }; - - tr_dbg(&lib_manager_tr, "add %#zx @ %lx partition", part.size, part.start); - return k_mem_domain_add_partition(domain, &part); -} - -static int llext_manager_rm_partition(struct k_mem_domain *domain, - uintptr_t addr, size_t size, - k_mem_partition_attr_t attr) -{ - size_t pre_pad_size = addr & (PAGE_SZ - 1); - struct k_mem_partition part = { - .start = addr - pre_pad_size, - .size = ALIGN_UP(pre_pad_size + size, PAGE_SZ), - .attr = attr, - }; - - tr_dbg(&lib_manager_tr, "remove %#zx @ %lx partition", part.size, part.start); - return k_mem_domain_remove_partition(domain, &part); -} static int llext_manager_add_mod_domain(struct lib_manager_module *mctx, struct k_mem_domain *domain) { @@ -1066,16 +1086,9 @@ int llext_manager_rm_domain(const uint32_t component_id, struct k_mem_domain *do int llext_manager_free_module(const uint32_t component_id) { const uint32_t module_id = IPC4_MOD_ID(component_id); - struct sof_man_fw_desc *desc = (struct sof_man_fw_desc *)lib_manager_get_library_manifest(module_id); struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(module_id); - if (entry_index >= desc->header.num_module_entries) { - tr_err(&lib_manager_tr, "Invalid driver index %u exceeds %d", - entry_index, desc->header.num_module_entries - 1); - return -ENOENT; - } - if (!ctx->mod) { tr_err(&lib_manager_tr, "NULL module array: ID %#x ctx %p", component_id, ctx); return -ENOENT; @@ -1167,6 +1180,7 @@ int llext_manager_add_library(uint32_t module_id) return ret; } } + ctx->load_type = SOF_MAN_MOD_TYPE_LLEXT; return 0; }