-
Notifications
You must be signed in to change notification settings - Fork 325
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
1st part of llext #8180 #8759
Merged
+362
−68
Merged
1st part of llext #8180 #8759
Changes from 1 commit
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
25f62e4
llext: add a new module type
lyakh ca0add2
lib-manager: fork a copy for LLEXT support
lyakh 5d62dec
llext-manager: handle unaligned .text and .data sections
lyakh d19ae99
llext-manager: remove instance-count handling
lyakh 7c8c77a
llext-manager: store segment sizes locally
lyakh a41e607
module: fix cache synchronisation
lyakh 4285f2e
rimage: mtl: extract platform part from mtl.toml.h
lyakh 9978873
rimage: add a generic platform.toml
lyakh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
// | ||
// Copyright(c) 2022 Intel Corporation. All rights reserved. | ||
// | ||
// Author: Jaroslaw Stelter <[email protected]> | ||
// Pawel Dobrowolski<[email protected]> | ||
|
||
/* | ||
* 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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this could be more explict and mention "Dynamic module loading functions using Zephyr Linkable Loadable Extensions (LLEXT) interface".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kv2019i I propose to address any cosmetic improvements in a follow-up PR, will do one first thing after this is merged