From 25f62e40050f4e854c90083424e2b3b79da4269e Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 19 Jan 2024 12:58:50 +0100 Subject: [PATCH 1/8] llext: add a new module type We need to be able to distinguish LLEXT loadable dynamically linkable modules at run-time. Add a new type for them. Compatibility is preserved. Signed-off-by: Guennadi Liakhovetski --- tools/rimage/src/include/rimage/sof/user/manifest.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/rimage/src/include/rimage/sof/user/manifest.h b/tools/rimage/src/include/rimage/sof/user/manifest.h index f470f34d713d..a311670a7483 100644 --- a/tools/rimage/src/include/rimage/sof/user/manifest.h +++ b/tools/rimage/src/include/rimage/sof/user/manifest.h @@ -25,6 +25,7 @@ /* module type load type */ #define SOF_MAN_MOD_TYPE_BUILTIN 0 #define SOF_MAN_MOD_TYPE_MODULE 1 +#define SOF_MAN_MOD_TYPE_LLEXT 2 /* module init config */ #define SOF_MAN_MOD_INIT_CONFIG_BASE_CFG 0 /* Base config only */ From ca0add215b93cc553774a07b07e23876d8609904 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 25 Jan 2024 10:03:02 +0100 Subject: [PATCH 2/8] lib-manager: fork a copy for LLEXT support This forks a slightly earlier version of library loading code for upcoming LLEXT support. Signed-off-by: Guennadi Liakhovetski --- src/include/sof/llext_manager.h | 20 +++ src/library_manager/lib_manager.c | 12 ++ src/library_manager/llext_manager.c | 241 ++++++++++++++++++++++++++++ zephyr/CMakeLists.txt | 6 + 4 files changed, 279 insertions(+) create mode 100644 src/include/sof/llext_manager.h create mode 100644 src/library_manager/llext_manager.c diff --git a/src/include/sof/llext_manager.h b/src/include/sof/llext_manager.h new file mode 100644 index 000000000000..6d1e90d70796 --- /dev/null +++ b/src/include/sof/llext_manager.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + */ + +#ifndef __SOF_LLEXT_MANAGER_H__ +#define __SOF_LLEXT_MANAGER_H__ + +#include + +struct comp_driver; +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); +int llext_manager_free_module(const struct comp_driver *drv, + struct comp_ipc_config *ipc_config); + +#endif diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index 80ffb0da0178..7ce6503c7853 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -265,6 +266,11 @@ static int lib_manager_free_module_instance(uint32_t module_id, uint32_t instanc return sys_mm_drv_unmap_region((__sparse_force void *)va_base, bss_size); } +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, struct comp_ipc_config *ipc_config, const void *ipc_specific_config) @@ -288,6 +294,9 @@ 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); + ret = lib_manager_load_module(module_id, mod); if (ret < 0) return 0; @@ -329,6 +338,9 @@ int lib_manager_free_module(const struct comp_driver *drv, desc = lib_manager_get_library_module_desc(module_id); 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); + ret = lib_manager_unload_module(mod); if (ret < 0) return ret; diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c new file mode 100644 index 000000000000..c68e3bcf5d03 --- /dev/null +++ b/src/library_manager/llext_manager.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Jaroslaw Stelter +// Pawel Dobrowolski + +/* + * Dynamic module loading functions. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +LOG_MODULE_DECLARE(lib_manager, CONFIG_SOF_LOG_LEVEL); + +extern struct tr_ctx lib_manager_tr; + +#define PAGE_SZ CONFIG_MM_DRV_PAGE_SIZE + +static int llext_manager_load_data_from_storage(void __sparse_cache *vma, void *s_addr, + uint32_t size, uint32_t flags) +{ + int ret = sys_mm_drv_map_region((__sparse_force void *)vma, POINTER_TO_UINT(NULL), + size, flags); + if (ret < 0) + return ret; + + ret = memcpy_s((__sparse_force void *)vma, size, s_addr, size); + if (ret < 0) + return ret; + + dcache_writeback_region(vma, size); + + /* TODO: Change attributes for memory to FLAGS */ + return 0; +} + +static int llext_manager_load_module(uint32_t module_id, struct sof_man_module *mod, + struct sof_man_fw_desc *desc) +{ + struct ext_library *ext_lib = ext_lib_get(); + uint32_t lib_id = LIB_MANAGER_GET_LIB_ID(module_id); + size_t load_offset = (size_t)((void *)ext_lib->desc[lib_id]); + void __sparse_cache *va_base_text = (void __sparse_cache *) + mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr; + void *src_txt = (void *)(mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset + load_offset); + size_t st_text_size = mod->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length; + void __sparse_cache *va_base_rodata = (void __sparse_cache *) + mod->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr; + void *src_rodata = + (void *)(mod->segment[SOF_MAN_SEGMENT_RODATA].file_offset + load_offset); + size_t st_rodata_size = mod->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length; + int ret; + + st_text_size = st_text_size * PAGE_SZ; + st_rodata_size = st_rodata_size * PAGE_SZ; + + /* Copy Code */ + ret = llext_manager_load_data_from_storage(va_base_text, src_txt, st_text_size, + SYS_MM_MEM_PERM_RW | SYS_MM_MEM_PERM_EXEC); + if (ret < 0) + return ret; + + /* Copy RODATA */ + ret = llext_manager_load_data_from_storage(va_base_rodata, src_rodata, + st_rodata_size, SYS_MM_MEM_PERM_RW); + if (ret < 0) + goto e_text; + + return 0; + +e_text: + sys_mm_drv_unmap_region((__sparse_force void *)va_base_text, st_text_size); + + return ret; +} + +static int llext_manager_unload_module(uint32_t module_id, struct sof_man_module *mod, + struct sof_man_fw_desc *desc) +{ + void __sparse_cache *va_base_text = (void __sparse_cache *) + mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr; + size_t st_text_size = mod->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length; + void __sparse_cache *va_base_rodata = (void __sparse_cache *) + mod->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr; + size_t st_rodata_size = mod->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length; + int ret; + + st_text_size = st_text_size * PAGE_SZ; + st_rodata_size = st_rodata_size * PAGE_SZ; + + ret = sys_mm_drv_unmap_region((__sparse_force void *)va_base_text, st_text_size); + if (ret < 0) + return ret; + + return sys_mm_drv_unmap_region((__sparse_force void *)va_base_rodata, st_rodata_size); +} + +static void __sparse_cache *llext_manager_get_instance_bss_address(uint32_t module_id, + uint32_t instance_id, + struct sof_man_module *mod) +{ + uint32_t instance_bss_size = + mod->segment[SOF_MAN_SEGMENT_BSS].flags.r.length / mod->instance_max_count; + uint32_t inst_offset = instance_bss_size * PAGE_SZ * instance_id; + void __sparse_cache *va_base = + (void __sparse_cache *)(mod->segment[SOF_MAN_SEGMENT_BSS].v_base_addr + + inst_offset); + + tr_dbg(&lib_manager_tr, + "llext_manager_get_instance_bss_address(): instance_bss_size: %#x, pointer: %p", + instance_bss_size, (__sparse_force void *)va_base); + + return va_base; +} + +static int llext_manager_allocate_module_instance(uint32_t module_id, uint32_t instance_id, + uint32_t is_pages, struct sof_man_module *mod) +{ + uint32_t bss_size = + (mod->segment[SOF_MAN_SEGMENT_BSS].flags.r.length / mod->instance_max_count) + * PAGE_SZ; + void __sparse_cache *va_base = llext_manager_get_instance_bss_address(module_id, + instance_id, mod); + + if ((is_pages * PAGE_SZ) > bss_size) { + tr_err(&lib_manager_tr, + "llext_manager_allocate_module_instance(): invalid is_pages: %u, required: %u", + is_pages, bss_size / PAGE_SZ); + return -ENOMEM; + } + + /* + * Map bss memory and clear it. + */ + if (sys_mm_drv_map_region((__sparse_force void *)va_base, POINTER_TO_UINT(NULL), + bss_size, SYS_MM_MEM_PERM_RW) < 0) + return -ENOMEM; + + memset((__sparse_force void *)va_base, 0, bss_size); + + return 0; +} + +static int llext_manager_free_module_instance(uint32_t module_id, uint32_t instance_id, + struct sof_man_module *mod) +{ + uint32_t bss_size = + (mod->segment[SOF_MAN_SEGMENT_BSS].flags.r.length / mod->instance_max_count) + * PAGE_SZ; + void __sparse_cache *va_base = llext_manager_get_instance_bss_address(module_id, + instance_id, mod); + /* + * Unmap bss memory. + */ + return sys_mm_drv_unmap_region((__sparse_force void *)va_base, bss_size); +} + +uint32_t llext_manager_allocate_module(const struct comp_driver *drv, + struct comp_ipc_config *ipc_config, + const void *ipc_specific_config) +{ + 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); + + tr_dbg(&lib_manager_tr, "llext_manager_allocate_module(): mod_id: %#x", + ipc_config->id); + + desc = lib_manager_get_library_module_desc(module_id); + if (!desc) { + tr_err(&lib_manager_tr, + "llext_manager_allocate_module(): failed to get module descriptor"); + return 0; + } + + mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); + + ret = llext_manager_load_module(module_id, mod, desc); + if (ret < 0) + return 0; + + ret = llext_manager_allocate_module_instance(module_id, IPC4_INST_ID(ipc_config->id), + base_cfg->is_pages, mod); + if (ret < 0) { + tr_err(&lib_manager_tr, + "llext_manager_allocate_module(): module allocation failed: %d", ret); + return 0; + } + return mod->entry_point; +} + +int llext_manager_free_module(const struct comp_driver *drv, + struct comp_ipc_config *ipc_config) +{ + struct sof_man_fw_desc *desc; + struct sof_man_module *mod; + uint32_t module_id = IPC4_MOD_ID(ipc_config->id); + uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(module_id); + int ret; + + tr_dbg(&lib_manager_tr, "llext_manager_free_module(): mod_id: %#x", ipc_config->id); + + desc = lib_manager_get_library_module_desc(module_id); + mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); + + ret = llext_manager_unload_module(module_id, mod, desc); + if (ret < 0) + return ret; + + ret = llext_manager_free_module_instance(module_id, IPC4_INST_ID(ipc_config->id), mod); + if (ret < 0) { + tr_err(&lib_manager_tr, + "llext_manager_free_module(): free module instance failed: %d", ret); + return ret; + } + return 0; +} diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index ab0062c65e28..4d1fe49f6662 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -630,6 +630,12 @@ zephyr_library_sources_ifdef(CONFIG_LIBRARY_MANAGER ${SOF_SRC_PATH}/library_manager/lib_notification.c ) +if (CONFIG_MM_DRV) +zephyr_library_sources_ifdef(CONFIG_LIBRARY_MANAGER + ${SOF_SRC_PATH}/library_manager/llext_manager.c +) +endif() + zephyr_include_directories_ifdef(CONFIG_INTEL_MODULES ${SOF_SRC_PATH}/include/sof/audio/module_adapter/iadk/ ${SOF_SRC_PATH}/include/sof/audio/module_adapter/library/ From 5d62decfbf2ded070c9f0d96691ab1f92a718145 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 7 Dec 2023 12:16:50 +0100 Subject: [PATCH 3/8] llext-manager: handle unaligned .text and .data sections Currently only page size-aligned .text and .rodata sections are supported. Remove this limitation by prepadding the address to restore the alignment. Signed-off-by: Guennadi Liakhovetski --- src/library_manager/llext_manager.c | 51 +++++++++++++++++++---------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index c68e3bcf5d03..387af2c67e1f 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -37,18 +37,39 @@ extern struct tr_ctx lib_manager_tr; #define PAGE_SZ CONFIG_MM_DRV_PAGE_SIZE +static int llext_manager_align_map(void __sparse_cache *vma, size_t size, uint32_t flags) +{ + size_t pre_pad_size = (uintptr_t)vma & (PAGE_SZ - 1); + void *aligned_vma = (__sparse_force uint8_t *)vma - pre_pad_size; + + return sys_mm_drv_map_region(aligned_vma, POINTER_TO_UINT(NULL), + ALIGN_UP(pre_pad_size + size, PAGE_SZ), flags); +} + +static int llext_manager_align_unmap(void __sparse_cache *vma, size_t size) +{ + size_t pre_pad_size = (uintptr_t)vma & (PAGE_SZ - 1); + void *aligned_vma = (__sparse_force uint8_t *)vma - pre_pad_size; + + return sys_mm_drv_unmap_region(aligned_vma, ALIGN_UP(pre_pad_size + size, PAGE_SZ)); +} + static int llext_manager_load_data_from_storage(void __sparse_cache *vma, void *s_addr, - uint32_t size, uint32_t flags) + size_t size, uint32_t flags) { - int ret = sys_mm_drv_map_region((__sparse_force void *)vma, POINTER_TO_UINT(NULL), - size, flags); - if (ret < 0) + int ret = llext_manager_align_map(vma, size, flags); + + if (ret < 0) { + tr_err(&lib_manager_tr, "cannot map %u of %p", size, (__sparse_force void *)vma); return ret; + } ret = memcpy_s((__sparse_force void *)vma, size, s_addr, size); if (ret < 0) return ret; + /* Some data can be accessed as uncached, in fact that's the default */ + /* Both D- and I-caches have been invalidated */ dcache_writeback_region(vma, size); /* TODO: Change attributes for memory to FLAGS */ @@ -90,7 +111,7 @@ static int llext_manager_load_module(uint32_t module_id, struct sof_man_module * return 0; e_text: - sys_mm_drv_unmap_region((__sparse_force void *)va_base_text, st_text_size); + llext_manager_align_unmap(va_base_text, st_text_size); return ret; } @@ -109,11 +130,11 @@ static int llext_manager_unload_module(uint32_t module_id, struct sof_man_module st_text_size = st_text_size * PAGE_SZ; st_rodata_size = st_rodata_size * PAGE_SZ; - ret = sys_mm_drv_unmap_region((__sparse_force void *)va_base_text, st_text_size); + ret = llext_manager_align_unmap(va_base_text, st_text_size); if (ret < 0) return ret; - return sys_mm_drv_unmap_region((__sparse_force void *)va_base_rodata, st_rodata_size); + return llext_manager_align_unmap(va_base_rodata, st_rodata_size); } static void __sparse_cache *llext_manager_get_instance_bss_address(uint32_t module_id, @@ -150,11 +171,8 @@ static int llext_manager_allocate_module_instance(uint32_t module_id, uint32_t i return -ENOMEM; } - /* - * Map bss memory and clear it. - */ - if (sys_mm_drv_map_region((__sparse_force void *)va_base, POINTER_TO_UINT(NULL), - bss_size, SYS_MM_MEM_PERM_RW) < 0) + /* Map bss memory and clear it. */ + if (llext_manager_align_map(va_base, bss_size, SYS_MM_MEM_PERM_RW) < 0) return -ENOMEM; memset((__sparse_force void *)va_base, 0, bss_size); @@ -165,15 +183,14 @@ static int llext_manager_allocate_module_instance(uint32_t module_id, uint32_t i static int llext_manager_free_module_instance(uint32_t module_id, uint32_t instance_id, struct sof_man_module *mod) { - uint32_t bss_size = + size_t bss_size = (mod->segment[SOF_MAN_SEGMENT_BSS].flags.r.length / mod->instance_max_count) * PAGE_SZ; void __sparse_cache *va_base = llext_manager_get_instance_bss_address(module_id, instance_id, mod); - /* - * Unmap bss memory. - */ - return sys_mm_drv_unmap_region((__sparse_force void *)va_base, bss_size); + + /* Unmap bss memory. */ + return llext_manager_align_unmap(va_base, bss_size); } uint32_t llext_manager_allocate_module(const struct comp_driver *drv, From d19ae99a2905b141252ee98c569ec0b47fdfcd09 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 12 Jan 2024 17:01:50 +0100 Subject: [PATCH 4/8] llext-manager: remove instance-count handling .bss splitting is specific to system-service module loading, LLEXT uses a traditional shared .bss ELF section. Signed-off-by: Guennadi Liakhovetski --- src/library_manager/llext_manager.c | 51 +++++++++-------------------- 1 file changed, 16 insertions(+), 35 deletions(-) diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index 387af2c67e1f..ad13a0732401 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -137,36 +137,21 @@ static int llext_manager_unload_module(uint32_t module_id, struct sof_man_module return llext_manager_align_unmap(va_base_rodata, st_rodata_size); } -static void __sparse_cache *llext_manager_get_instance_bss_address(uint32_t module_id, - uint32_t instance_id, - struct sof_man_module *mod) +static void __sparse_cache *llext_manager_get_bss_address(uint32_t module_id, + struct sof_man_module *mod) { - uint32_t instance_bss_size = - mod->segment[SOF_MAN_SEGMENT_BSS].flags.r.length / mod->instance_max_count; - uint32_t inst_offset = instance_bss_size * PAGE_SZ * instance_id; - void __sparse_cache *va_base = - (void __sparse_cache *)(mod->segment[SOF_MAN_SEGMENT_BSS].v_base_addr + - inst_offset); - - tr_dbg(&lib_manager_tr, - "llext_manager_get_instance_bss_address(): instance_bss_size: %#x, pointer: %p", - instance_bss_size, (__sparse_force void *)va_base); - - return va_base; + return (void __sparse_cache *)mod->segment[SOF_MAN_SEGMENT_BSS].v_base_addr; } -static int llext_manager_allocate_module_instance(uint32_t module_id, uint32_t instance_id, - uint32_t is_pages, struct sof_man_module *mod) +static int llext_manager_allocate_module_bss(uint32_t module_id, + uint32_t is_pages, struct sof_man_module *mod) { - uint32_t bss_size = - (mod->segment[SOF_MAN_SEGMENT_BSS].flags.r.length / mod->instance_max_count) - * PAGE_SZ; - void __sparse_cache *va_base = llext_manager_get_instance_bss_address(module_id, - instance_id, mod); + size_t bss_size = mod->segment[SOF_MAN_SEGMENT_BSS].flags.r.length * PAGE_SZ; + void __sparse_cache *va_base = llext_manager_get_bss_address(module_id, mod); - if ((is_pages * PAGE_SZ) > bss_size) { + if (is_pages * PAGE_SZ > bss_size) { tr_err(&lib_manager_tr, - "llext_manager_allocate_module_instance(): invalid is_pages: %u, required: %u", + "llext_manager_allocate_module_bss(): invalid is_pages: %u, required: %u", is_pages, bss_size / PAGE_SZ); return -ENOMEM; } @@ -180,14 +165,11 @@ static int llext_manager_allocate_module_instance(uint32_t module_id, uint32_t i return 0; } -static int llext_manager_free_module_instance(uint32_t module_id, uint32_t instance_id, - struct sof_man_module *mod) +static int llext_manager_free_module_bss(uint32_t module_id, + struct sof_man_module *mod) { - size_t bss_size = - (mod->segment[SOF_MAN_SEGMENT_BSS].flags.r.length / mod->instance_max_count) - * PAGE_SZ; - void __sparse_cache *va_base = llext_manager_get_instance_bss_address(module_id, - instance_id, mod); + size_t bss_size = mod->segment[SOF_MAN_SEGMENT_BSS].flags.r.length * PAGE_SZ; + void __sparse_cache *va_base = llext_manager_get_bss_address(module_id, mod); /* Unmap bss memory. */ return llext_manager_align_unmap(va_base, bss_size); @@ -220,8 +202,7 @@ uint32_t llext_manager_allocate_module(const struct comp_driver *drv, if (ret < 0) return 0; - ret = llext_manager_allocate_module_instance(module_id, IPC4_INST_ID(ipc_config->id), - base_cfg->is_pages, mod); + ret = llext_manager_allocate_module_bss(module_id, base_cfg->is_pages, mod); if (ret < 0) { tr_err(&lib_manager_tr, "llext_manager_allocate_module(): module allocation failed: %d", ret); @@ -248,10 +229,10 @@ int llext_manager_free_module(const struct comp_driver *drv, if (ret < 0) return ret; - ret = llext_manager_free_module_instance(module_id, IPC4_INST_ID(ipc_config->id), mod); + ret = llext_manager_free_module_bss(module_id, mod); if (ret < 0) { tr_err(&lib_manager_tr, - "llext_manager_free_module(): free module instance failed: %d", ret); + "llext_manager_free_module(): free module bss failed: %d", ret); return ret; } return 0; From 7c8c77a36229bf0f75a80b5ea3c33fc71f3dd454 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 12 Dec 2023 16:11:43 +0100 Subject: [PATCH 5/8] llext-manager: store segment sizes locally Currently segment sizes are calculated from page counts, stored in module manifests. This restricts us to only using page size-aligned segment sizes. In case of not page size-aligned ELF sections this can lead to wasted memory. To avoid this store segment sizes in full-size per-module variables to access them at any time. Signed-off-by: Guennadi Liakhovetski --- src/include/sof/lib_manager.h | 15 +++++++++++- src/library_manager/lib_manager.c | 19 +++++++++------ src/library_manager/llext_manager.c | 38 ++++++++++++++--------------- 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/include/sof/lib_manager.h b/src/include/sof/lib_manager.h index 0ca21bacbb57..8c0262bd096f 100644 --- a/src/include/sof/lib_manager.h +++ b/src/include/sof/lib_manager.h @@ -78,9 +78,14 @@ struct ipc_lib_msg { struct list_item list; }; +struct lib_manager_mod_ctx { + struct sof_man_fw_desc *desc; + size_t segment_size[3]; +}; + struct ext_library { struct k_spinlock lock; /* last locking CPU record */ - struct sof_man_fw_desc *desc[LIB_MANAGER_MAX_LIBS]; + struct lib_manager_mod_ctx *desc[LIB_MANAGER_MAX_LIBS]; #ifdef CONFIG_LIBCODE_MODULE_SUPPORT uint32_t mods_exec_load_cnt; #endif @@ -97,6 +102,14 @@ static inline struct ext_library *ext_lib_get(void) { return sof_get()->ext_library; } + +static inline struct lib_manager_mod_ctx *lib_manager_get_mod_ctx(int module_id) +{ + uint32_t lib_id = LIB_MANAGER_GET_LIB_ID(module_id); + struct ext_library *_ext_lib = ext_lib_get(); + + return _ext_lib->desc[lib_id]; +} #endif /* diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index 7ce6503c7853..b85bec3ff9b8 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -77,9 +77,8 @@ static int lib_manager_load_data_from_storage(void __sparse_cache *vma, void *s_ static int lib_manager_load_module(const uint32_t module_id, const struct sof_man_module *const mod) { - const struct ext_library *const ext_lib = ext_lib_get(); - const uint32_t lib_id = LIB_MANAGER_GET_LIB_ID(module_id); - const uintptr_t load_offset = POINTER_TO_UINT(ext_lib->desc[lib_id]); + struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); + const uintptr_t load_offset = POINTER_TO_UINT(ctx->desc); void *src; void __sparse_cache *va_base; size_t size; @@ -393,9 +392,8 @@ void lib_manager_init(void) struct sof_man_fw_desc *lib_manager_get_library_module_desc(int module_id) { - uint32_t lib_id = LIB_MANAGER_GET_LIB_ID(module_id); - struct ext_library *_ext_lib = ext_lib_get(); - uint8_t *buffptr = (uint8_t *)_ext_lib->desc[lib_id]; + struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); + uint8_t *buffptr = (uint8_t *)(ctx ? ctx->desc : NULL); if (!buffptr) return NULL; @@ -405,9 +403,14 @@ struct sof_man_fw_desc *lib_manager_get_library_module_desc(int module_id) static void lib_manager_update_sof_ctx(struct sof_man_fw_desc *desc, 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; - _ext_lib->desc[lib_id] = desc; - /* TODO: maybe need to call here dcache_writeback here? */ + _ext_lib->desc[lib_id] = ctx; + /* TODO: maybe need to call dcache_writeback here? */ } #if CONFIG_INTEL_MODULES diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index ad13a0732401..5883719b9b67 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -79,23 +79,19 @@ static int llext_manager_load_data_from_storage(void __sparse_cache *vma, void * static int llext_manager_load_module(uint32_t module_id, struct sof_man_module *mod, struct sof_man_fw_desc *desc) { - struct ext_library *ext_lib = ext_lib_get(); - uint32_t lib_id = LIB_MANAGER_GET_LIB_ID(module_id); - size_t load_offset = (size_t)((void *)ext_lib->desc[lib_id]); + struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); + uint8_t *load_base = (uint8_t *)ctx->desc; void __sparse_cache *va_base_text = (void __sparse_cache *) mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr; - void *src_txt = (void *)(mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset + load_offset); - size_t st_text_size = mod->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length; + void *src_txt = (void *)(load_base + mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset); + size_t st_text_size = ctx->segment_size[SOF_MAN_SEGMENT_TEXT]; void __sparse_cache *va_base_rodata = (void __sparse_cache *) mod->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr; - void *src_rodata = - (void *)(mod->segment[SOF_MAN_SEGMENT_RODATA].file_offset + load_offset); - size_t st_rodata_size = mod->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length; + void *src_rodata = (void *)(load_base + + mod->segment[SOF_MAN_SEGMENT_RODATA].file_offset); + size_t st_rodata_size = ctx->segment_size[SOF_MAN_SEGMENT_RODATA]; int ret; - st_text_size = st_text_size * PAGE_SZ; - st_rodata_size = st_rodata_size * PAGE_SZ; - /* Copy Code */ ret = llext_manager_load_data_from_storage(va_base_text, src_txt, st_text_size, SYS_MM_MEM_PERM_RW | SYS_MM_MEM_PERM_EXEC); @@ -119,17 +115,15 @@ static int llext_manager_load_module(uint32_t module_id, struct sof_man_module * static int llext_manager_unload_module(uint32_t module_id, struct sof_man_module *mod, struct sof_man_fw_desc *desc) { + struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); void __sparse_cache *va_base_text = (void __sparse_cache *) mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr; - size_t st_text_size = mod->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length; + size_t st_text_size = ctx->segment_size[SOF_MAN_SEGMENT_TEXT]; void __sparse_cache *va_base_rodata = (void __sparse_cache *) mod->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr; - size_t st_rodata_size = mod->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length; + size_t st_rodata_size = ctx->segment_size[SOF_MAN_SEGMENT_RODATA]; int ret; - st_text_size = st_text_size * PAGE_SZ; - st_rodata_size = st_rodata_size * PAGE_SZ; - ret = llext_manager_align_unmap(va_base_text, st_text_size); if (ret < 0) return ret; @@ -146,7 +140,8 @@ 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) { - size_t bss_size = mod->segment[SOF_MAN_SEGMENT_BSS].flags.r.length * PAGE_SZ; + 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) { @@ -168,7 +163,8 @@ static int llext_manager_allocate_module_bss(uint32_t module_id, static int llext_manager_free_module_bss(uint32_t module_id, struct sof_man_module *mod) { - size_t bss_size = mod->segment[SOF_MAN_SEGMENT_BSS].flags.r.length * PAGE_SZ; + 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); /* Unmap bss memory. */ @@ -185,12 +181,13 @@ uint32_t llext_manager_allocate_module(const struct comp_driver *drv, 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); tr_dbg(&lib_manager_tr, "llext_manager_allocate_module(): mod_id: %#x", ipc_config->id); desc = lib_manager_get_library_module_desc(module_id); - if (!desc) { + if (!ctx || !desc) { tr_err(&lib_manager_tr, "llext_manager_allocate_module(): failed to get module descriptor"); return 0; @@ -198,6 +195,9 @@ 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_load_module(module_id, mod, desc); if (ret < 0) return 0; From a41e6073de21966ba80e111394d5f6e989163fc7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 24 Oct 2023 17:56:31 +0200 Subject: [PATCH 6/8] module: fix cache synchronisation Buffers, where modules are stored originally, don't need their caches to be synchronised - they're only used as a data storage and only accessed via cached aliases. But when final buffers are allocated, from which modules are actually run, those buffers do indeed need cache synchronisation. Signed-off-by: Guennadi Liakhovetski --- src/library_manager/lib_manager.c | 3 --- src/library_manager/llext_manager.c | 17 ++++++++--------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index b85bec3ff9b8..716e4d31fd12 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -614,9 +614,6 @@ static void __sparse_cache *lib_manager_allocate_store_mem(uint32_t size, return NULL; } - dcache_invalidate_region(local_add, size); - icache_invalidate_region(local_add, size); - return local_add; } diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index 5883719b9b67..4b885b25f29e 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -64,16 +64,8 @@ static int llext_manager_load_data_from_storage(void __sparse_cache *vma, void * return ret; } - ret = memcpy_s((__sparse_force void *)vma, size, s_addr, size); - if (ret < 0) - return ret; - - /* Some data can be accessed as uncached, in fact that's the default */ - /* Both D- and I-caches have been invalidated */ - dcache_writeback_region(vma, size); - /* TODO: Change attributes for memory to FLAGS */ - return 0; + return memcpy_s((__sparse_force void *)vma, size, s_addr, size); } static int llext_manager_load_module(uint32_t module_id, struct sof_man_module *mod, @@ -98,12 +90,19 @@ static int llext_manager_load_module(uint32_t module_id, struct sof_man_module * if (ret < 0) return ret; + /* .text contains instructions and it also often contains local data */ + dcache_writeback_region(va_base_text, st_text_size); + icache_invalidate_region(va_base_text, st_text_size); + /* Copy RODATA */ ret = llext_manager_load_data_from_storage(va_base_rodata, src_rodata, st_rodata_size, SYS_MM_MEM_PERM_RW); if (ret < 0) goto e_text; + /* Some data can be accessed as uncached, in fact that's the default */ + dcache_writeback_region(va_base_rodata, st_rodata_size); + return 0; e_text: From 4285f2e815b012df16abf28ad5f4cc292068729f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 9 Jan 2024 12:33:27 +0100 Subject: [PATCH 7/8] rimage: mtl: extract platform part from mtl.toml.h A part of mtl.toml.h is also needed for loadable modules, built for MTL. Extract it into a separate file. Signed-off-by: Guennadi Liakhovetski --- tools/rimage/config/mtl.toml.h | 57 +-------------------------- tools/rimage/config/platform-mtl.toml | 56 ++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 56 deletions(-) create mode 100644 tools/rimage/config/platform-mtl.toml diff --git a/tools/rimage/config/mtl.toml.h b/tools/rimage/config/mtl.toml.h index d8b872ce4f8d..a1c23dbcba2c 100644 --- a/tools/rimage/config/mtl.toml.h +++ b/tools/rimage/config/mtl.toml.h @@ -1,59 +1,4 @@ -version = [3, 0] - -[adsp] -name = "mtl" -image_size = "0x2C0000" # (22) bank * 128KB -alias_mask = "0xE0000000" - -[[adsp.mem_zone]] -type = "ROM" -base = "0x1FF80000" -size = "0x400" -[[adsp.mem_zone]] -type = "IMR" -base = "0xA104A000" -size = "0x2000" -[[adsp.mem_zone]] -type = "SRAM" -base = "0xa00f0000" -size = "0x100000" - -[[adsp.mem_alias]] -type = "uncached" -base = "0x40000000" -[[adsp.mem_alias]] -type = "cached" -base = "0xA0000000" - -[cse] -partition_name = "ADSP" -[[cse.entry]] -name = "ADSP.man" -offset = "0x5c" -length = "0x4b8" -[[cse.entry]] -name = "ADSP.met" -offset = "0x4c0" -length = "0x70" -[[cse.entry]] -name = "ADSP" -offset = "0x540" -length = "0x0" # calculated by rimage - -[css] - -[signed_pkg] -name = "ADSP" -[[signed_pkg.module]] -name = "ADSP.met" - -[adsp_file] -[[adsp_file.comp]] -base_offset = "0x2000" - -[fw_desc.header] -name = "ADSPFW" -load_offset = "0x40000" +#include "platform-mtl.toml" [[module.entry]] name = "BRNGUP" diff --git a/tools/rimage/config/platform-mtl.toml b/tools/rimage/config/platform-mtl.toml new file mode 100644 index 000000000000..fdce10fd4c94 --- /dev/null +++ b/tools/rimage/config/platform-mtl.toml @@ -0,0 +1,56 @@ +version = [3, 0] + +[adsp] +name = "mtl" +image_size = "0x2C0000" # (22) bank * 128KB +alias_mask = "0xE0000000" + +[[adsp.mem_zone]] +type = "ROM" +base = "0x1FF80000" +size = "0x400" +[[adsp.mem_zone]] +type = "IMR" +base = "0xA104A000" +size = "0x2000" +[[adsp.mem_zone]] +type = "SRAM" +base = "0xa00f0000" +size = "0x100000" + +[[adsp.mem_alias]] +type = "uncached" +base = "0x40000000" +[[adsp.mem_alias]] +type = "cached" +base = "0xA0000000" + +[cse] +partition_name = "ADSP" +[[cse.entry]] +name = "ADSP.man" +offset = "0x5c" +length = "0x4b8" +[[cse.entry]] +name = "ADSP.met" +offset = "0x4c0" +length = "0x70" +[[cse.entry]] +name = "ADSP" +offset = "0x540" +length = "0x0" # calculated by rimage + +[css] + +[signed_pkg] +name = "ADSP" +[[signed_pkg.module]] +name = "ADSP.met" + +[adsp_file] +[[adsp_file.comp]] +base_offset = "0x2000" + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0x40000" From 99788730a8ddccbe76ca7c10f27e36dd42ac66df Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 9 Jan 2024 13:01:48 +0100 Subject: [PATCH 8/8] rimage: add a generic platform.toml Instead of including TOML files for each platform explicitly, add a generic platform.toml, that will contain all respective platform TOML files, and select the correct one, based on build configucation. Signed-off-by: Guennadi Liakhovetski --- tools/rimage/config/platform.toml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tools/rimage/config/platform.toml diff --git a/tools/rimage/config/platform.toml b/tools/rimage/config/platform.toml new file mode 100644 index 000000000000..131d656f1656 --- /dev/null +++ b/tools/rimage/config/platform.toml @@ -0,0 +1,3 @@ +#if CONFIG_METEORLAKE +#include "platform-mtl.toml" +#endif