mirror of https://github.com/thesofproject/sof.git
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 <guennadi.liakhovetski@linux.intel.com>
This commit is contained in:
parent
ab29f8db82
commit
bd5c24b282
|
@ -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 <stdint.h>
|
||||
|
||||
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
|
|
@ -19,6 +19,7 @@
|
|||
#include <rtos/spinlock.h>
|
||||
#include <sof/lib/cpu-clk-manager.h>
|
||||
#include <sof/lib_manager.h>
|
||||
#include <sof/llext_manager.h>
|
||||
#include <sof/audio/module_adapter/module/generic.h>
|
||||
#include <sof/audio/module_adapter/module/modules.h>
|
||||
|
||||
|
@ -337,6 +338,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)
|
||||
|
@ -360,6 +366,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;
|
||||
|
@ -401,6 +410,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;
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
//
|
||||
// Copyright(c) 2022 Intel Corporation. All rights reserved.
|
||||
//
|
||||
// Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com>
|
||||
// Pawel Dobrowolski<pawelx.dobrowolski@intel.com>
|
||||
|
||||
/*
|
||||
* Dynamic module loading functions.
|
||||
*/
|
||||
|
||||
#include <sof/audio/buffer.h>
|
||||
#include <sof/audio/component_ext.h>
|
||||
#include <sof/common.h>
|
||||
#include <sof/compiler_attributes.h>
|
||||
#include <sof/ipc/topology.h>
|
||||
|
||||
#include <rtos/sof.h>
|
||||
#include <rtos/spinlock.h>
|
||||
#include <sof/lib/cpu-clk-manager.h>
|
||||
#include <sof/lib_manager.h>
|
||||
#include <sof/llext_manager.h>
|
||||
#include <sof/audio/module_adapter/module/generic.h>
|
||||
#include <sof/audio/module_adapter/module/modules.h>
|
||||
|
||||
#include <zephyr/cache.h>
|
||||
#include <zephyr/drivers/mm/system_mm.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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;
|
||||
}
|
|
@ -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/
|
||||
|
|
Loading…
Reference in New Issue