Skip to content

Commit

Permalink
llext: add per-module contexts
Browse files Browse the repository at this point in the history
Run-time loadable SOF libraries can contain multiple modules. To
prepare to support them add a module context type.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
  • Loading branch information
lyakh authored and lgirdwood committed Dec 6, 2024
1 parent 13f6226 commit 362aa36
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 40 deletions.
10 changes: 8 additions & 2 deletions src/include/sof/lib_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,18 @@ struct lib_manager_segment_desc {
size_t size;
};

struct lib_manager_mod_ctx {
void *base_addr;
struct lib_manager_module {
unsigned int start_idx;
const struct sof_man_module_manifest *mod_manifest;
struct lib_manager_segment_desc segment[LIB_MANAGER_N_SEGMENTS];
};

struct lib_manager_mod_ctx {
void *base_addr;
unsigned int n_mod;
struct lib_manager_module *mod;
};

struct ext_library {
struct k_spinlock lock; /* last locking CPU record */
struct lib_manager_mod_ctx *desc[LIB_MANAGER_MAX_LIBS];
Expand Down
98 changes: 60 additions & 38 deletions src/library_manager/llext_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,24 +125,22 @@ static int llext_manager_load_data_from_storage(const struct llext *ext,
}

static int llext_manager_load_module(const struct llext *ext, const struct llext_buf_loader *ebl,
uint32_t module_id)
const struct lib_manager_module *mctx)
{
struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id);

/* Executable code (.text) */
void __sparse_cache *va_base_text = (void __sparse_cache *)
ctx->segment[LIB_MANAGER_TEXT].addr;
size_t text_size = ctx->segment[LIB_MANAGER_TEXT].size;
mctx->segment[LIB_MANAGER_TEXT].addr;
size_t text_size = mctx->segment[LIB_MANAGER_TEXT].size;

/* Read-only data (.rodata and others) */
void __sparse_cache *va_base_rodata = (void __sparse_cache *)
ctx->segment[LIB_MANAGER_RODATA].addr;
size_t rodata_size = ctx->segment[LIB_MANAGER_RODATA].size;
mctx->segment[LIB_MANAGER_RODATA].addr;
size_t rodata_size = mctx->segment[LIB_MANAGER_RODATA].size;

/* Writable data (.data, .bss and others) */
void __sparse_cache *va_base_data = (void __sparse_cache *)
ctx->segment[LIB_MANAGER_DATA].addr;
size_t data_size = ctx->segment[LIB_MANAGER_DATA].size;
mctx->segment[LIB_MANAGER_DATA].addr;
size_t data_size = mctx->segment[LIB_MANAGER_DATA].size;

/* .bss, should be within writable data above */
void __sparse_cache *bss_addr = (void __sparse_cache *)
Expand Down Expand Up @@ -201,23 +199,22 @@ static int llext_manager_load_module(const struct llext *ext, const struct llext
return ret;
}

static int llext_manager_unload_module(uint32_t module_id)
static int llext_manager_unload_module(const struct lib_manager_module *mctx)
{
struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id);
/* Executable code (.text) */
void __sparse_cache *va_base_text = (void __sparse_cache *)
ctx->segment[LIB_MANAGER_TEXT].addr;
size_t text_size = ctx->segment[LIB_MANAGER_TEXT].size;
mctx->segment[LIB_MANAGER_TEXT].addr;
size_t text_size = mctx->segment[LIB_MANAGER_TEXT].size;

/* Read-only data (.rodata, etc.) */
void __sparse_cache *va_base_rodata = (void __sparse_cache *)
ctx->segment[LIB_MANAGER_RODATA].addr;
size_t rodata_size = ctx->segment[LIB_MANAGER_RODATA].size;
mctx->segment[LIB_MANAGER_RODATA].addr;
size_t rodata_size = mctx->segment[LIB_MANAGER_RODATA].size;

/* Writable data (.data, .bss, etc.) */
void __sparse_cache *va_base_data = (void __sparse_cache *)
ctx->segment[LIB_MANAGER_DATA].addr;
size_t data_size = ctx->segment[LIB_MANAGER_DATA].size;
mctx->segment[LIB_MANAGER_DATA].addr;
size_t data_size = mctx->segment[LIB_MANAGER_DATA].size;
int err = 0, ret;

ret = llext_manager_align_unmap(va_base_text, text_size);
Expand All @@ -240,15 +237,14 @@ static bool llext_manager_section_detached(const elf_shdr_t *shdr)
return shdr->sh_addr < SOF_MODULE_DRAM_LINK_END;
}

static int llext_manager_link(struct llext_buf_loader *ebl,
const char *name, uint32_t module_id, struct module_data *md,
static int llext_manager_link(struct llext_buf_loader *ebl, const char *name,
struct lib_manager_module *mctx, struct module_data *md,
const void **buildinfo,
const struct sof_man_module_manifest **mod_manifest)
{
struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id);
/* Identify if this is the first time loading this module */
struct llext_load_param ldr_parm = {
.relocate_local = !ctx->segment[LIB_MANAGER_TEXT].size,
.relocate_local = !mctx->segment[LIB_MANAGER_TEXT].size,
.pre_located = true,
.section_detached = llext_manager_section_detached,
};
Expand All @@ -257,30 +253,30 @@ static int llext_manager_link(struct llext_buf_loader *ebl,
if (ret)
return ret;

ctx->segment[LIB_MANAGER_TEXT].addr = ebl->loader.sects[LLEXT_MEM_TEXT].sh_addr;
ctx->segment[LIB_MANAGER_TEXT].size = ebl->loader.sects[LLEXT_MEM_TEXT].sh_size;
mctx->segment[LIB_MANAGER_TEXT].addr = ebl->loader.sects[LLEXT_MEM_TEXT].sh_addr;
mctx->segment[LIB_MANAGER_TEXT].size = ebl->loader.sects[LLEXT_MEM_TEXT].sh_size;

tr_dbg(&lib_manager_tr, ".text: start: %#lx size %#x",
ctx->segment[LIB_MANAGER_TEXT].addr,
ctx->segment[LIB_MANAGER_TEXT].size);
mctx->segment[LIB_MANAGER_TEXT].addr,
mctx->segment[LIB_MANAGER_TEXT].size);

/* All read-only data sections */
ctx->segment[LIB_MANAGER_RODATA].addr =
mctx->segment[LIB_MANAGER_RODATA].addr =
ebl->loader.sects[LLEXT_MEM_RODATA].sh_addr;
ctx->segment[LIB_MANAGER_RODATA].size = ebl->loader.sects[LLEXT_MEM_RODATA].sh_size;
mctx->segment[LIB_MANAGER_RODATA].size = ebl->loader.sects[LLEXT_MEM_RODATA].sh_size;

tr_dbg(&lib_manager_tr, ".rodata: start: %#lx size %#x",
ctx->segment[LIB_MANAGER_RODATA].addr,
ctx->segment[LIB_MANAGER_RODATA].size);
mctx->segment[LIB_MANAGER_RODATA].addr,
mctx->segment[LIB_MANAGER_RODATA].size);

/* All writable data sections */
ctx->segment[LIB_MANAGER_DATA].addr =
mctx->segment[LIB_MANAGER_DATA].addr =
ebl->loader.sects[LLEXT_MEM_DATA].sh_addr;
ctx->segment[LIB_MANAGER_DATA].size = ebl->loader.sects[LLEXT_MEM_DATA].sh_size;
mctx->segment[LIB_MANAGER_DATA].size = ebl->loader.sects[LLEXT_MEM_DATA].sh_size;

tr_dbg(&lib_manager_tr, ".data: start: %#lx size %#x",
ctx->segment[LIB_MANAGER_DATA].addr,
ctx->segment[LIB_MANAGER_DATA].size);
mctx->segment[LIB_MANAGER_DATA].addr,
mctx->segment[LIB_MANAGER_DATA].size);

ssize_t binfo_o = llext_find_section(&ebl->loader, ".mod_buildinfo");

Expand All @@ -295,6 +291,25 @@ static int llext_manager_link(struct llext_buf_loader *ebl,
return binfo_o >= 0 && mod_o >= 0 ? 0 : -EPROTO;
}

static int llext_manager_mod_init(struct lib_manager_mod_ctx *ctx,
const struct sof_man_fw_desc *desc,
const struct sof_man_module *mod_array)
{
/*
* Loadable modules are loaded to DRAM once and never unloaded from it.
* Context, related to them, is never freed
*/
ctx->mod = rmalloc(SOF_MEM_ZONE_RUNTIME_SHARED, SOF_MEM_FLAG_COHERENT,
SOF_MEM_CAPS_RAM, sizeof(ctx->mod[0]));
if (!ctx->mod)
return -ENOMEM;

ctx->n_mod = 1;
ctx->mod[0].start_idx = 0;

return 0;
}

uintptr_t llext_manager_allocate_module(struct processing_module *proc,
const struct comp_ipc_config *ipc_config,
const void *ipc_specific_config)
Expand Down Expand Up @@ -322,6 +337,11 @@ uintptr_t llext_manager_allocate_module(struct processing_module *proc,

mod_array = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(0));

if (!ctx->mod)
llext_manager_mod_init(ctx, desc, mod_array);

struct lib_manager_module *mctx = ctx->mod;

/* LLEXT linking is only needed once for all the modules in the library */
ret = llext_manager_link(&ebl, mod_array[0].name, module_id, md,
(const void **)&buildinfo, &mod_manifest);
Expand All @@ -339,26 +359,28 @@ uintptr_t llext_manager_allocate_module(struct processing_module *proc,
}

/* Map executable code and data */
ret = llext_manager_load_module(md->llext, &ebl, module_id);
ret = llext_manager_load_module(md->llext, &ebl, mctx);
if (ret < 0)
return 0;

/* ctx->mod_manifest points to a const array of module manifests */
ctx->mod_manifest = mod_manifest;
/* mctx->mod_manifest points to a const array of module manifests */
mctx->mod_manifest = mod_manifest;
}

return ctx->mod_manifest[entry_index].module.entry_point;
return mctx->mod_manifest[entry_index].module.entry_point;
}

int llext_manager_free_module(const uint32_t component_id)
{
const uint32_t module_id = IPC4_MOD_ID(component_id);
struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id);
const unsigned int base_module_id = LIB_MANAGER_GET_LIB_ID(module_id) <<
LIB_MANAGER_LIB_ID_SHIFT;
struct lib_manager_module *mctx = ctx->mod;

tr_dbg(&lib_manager_tr, "mod_id: %#x", component_id);

return llext_manager_unload_module(base_module_id);
return llext_manager_unload_module(mctx);
}

bool comp_is_llext(struct comp_dev *comp)
Expand Down

0 comments on commit 362aa36

Please sign in to comment.