From a5b402ecf960e262d87e1c272f93ccea15b2b678 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Wed, 11 Sep 2024 10:07:31 +0200 Subject: [PATCH 1/4] west.yml: [TMP] use Zephyr PR with new LLEXT API This is a temporary change to use the Zephyr PR adding the new LLEXT inspection API. This is needed to test the SOF integration with the new API. Signed-off-by: Luca Burelli --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 6fd718c542ea..2110f3d05500 100644 --- a/west.yml +++ b/west.yml @@ -43,7 +43,7 @@ manifest: - name: zephyr repo-path: zephyr - revision: 42701fdb27298d20b4040cea5cde375b72c27cfc + revision: pull/85498/head remote: zephyrproject # Import some projects listed in zephyr/west.yml@revision From 755f2907e59cb76fea8e56f665204f31d6893c47 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Mon, 10 Feb 2025 11:00:40 +0100 Subject: [PATCH 2/4] llext_manager: minor preparatory refactors This commit does some minor preparatory refactors in the llext_manager module in preparation for the upcoming change to use the new LLEXT inspection API. Signed-off-by: Luca Burelli --- src/library_manager/llext_manager.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index c2cd5254ed76..625681e90059 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -75,9 +75,10 @@ static int llext_manager_load_data_from_storage(const struct llext *ext, size_t size, uint32_t flags) { unsigned int i; - int ret = llext_manager_align_map(vma, size, SYS_MM_MEM_PERM_RW); + int ret; const elf_shdr_t *shdr; + ret = llext_manager_align_map(vma, size, SYS_MM_MEM_PERM_RW); if (ret < 0) { tr_err(&lib_manager_tr, "cannot map %u of %p", size, (__sparse_force void *)vma); return ret; @@ -240,8 +241,9 @@ static int llext_manager_link(struct llext_buf_loader *ebl, const char *name, .pre_located = true, .section_detached = llext_manager_section_detached, }; - int ret = llext_load(&ebl->loader, name, llext, &ldr_parm); + int ret; + ret = llext_load(&ebl->loader, name, llext, &ldr_parm); if (ret) return ret; @@ -270,17 +272,19 @@ static int llext_manager_link(struct llext_buf_loader *ebl, const char *name, mctx->segment[LIB_MANAGER_DATA].addr, mctx->segment[LIB_MANAGER_DATA].size); + *buildinfo = NULL; ssize_t binfo_o = llext_find_section(&ebl->loader, ".mod_buildinfo"); if (binfo_o >= 0) *buildinfo = llext_peek(&ebl->loader, binfo_o); + *mod_manifest = NULL; ssize_t mod_o = llext_find_section(&ebl->loader, ".module"); if (mod_o >= 0) *mod_manifest = llext_peek(&ebl->loader, mod_o); - return binfo_o >= 0 && mod_o >= 0 ? 0 : -EPROTO; + return *buildinfo && *mod_manifest ? 0 : -EPROTO; } static int llext_manager_mod_init(struct lib_manager_mod_ctx *ctx, From ce254e3c7acde1e4a920c364a8ca59e02574d2c7 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 7 Feb 2025 14:34:04 +0100 Subject: [PATCH 3/4] llext_manager: convert to use new LLEXT inspection API This patch converts the llext_manager to use the new LLEXT inspection API. The new API allows to get information about sections and regions without the need to access the internal structures of the LLEXT loader, decoupling SOF and LLEXT code and making it easier to maintain. Signed-off-by: Luca Burelli --- src/library_manager/llext_manager.c | 92 +++++++++++++++++------------ 1 file changed, 53 insertions(+), 39 deletions(-) diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index 625681e90059..23a81e5b1fcd 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -69,14 +70,15 @@ static int llext_manager_align_unmap(void __sparse_cache *vma, size_t 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(const struct llext *ext, +static int llext_manager_load_data_from_storage(const struct llext_loader *ldr, + const struct llext *ext, + enum llext_mem region, void __sparse_cache *vma, - const uint8_t *load_base, size_t size, uint32_t flags) { unsigned int i; + const void *region_addr; int ret; - const elf_shdr_t *shdr; ret = llext_manager_align_map(vma, size, SYS_MM_MEM_PERM_RW); if (ret < 0) { @@ -84,22 +86,21 @@ static int llext_manager_load_data_from_storage(const struct llext *ext, return ret; } - size_t init_offset = 0; + llext_get_region_info(ldr, ext, region, NULL, ®ion_addr, NULL); /* Need to copy sections within regions individually, offsets may differ */ - for (i = 0, shdr = llext_section_headers(ext); i < llext_section_count(ext); i++, shdr++) { - if ((uintptr_t)shdr->sh_addr < (uintptr_t)vma || - (uintptr_t)shdr->sh_addr >= (uintptr_t)vma + size) - continue; + for (i = 0; i < llext_section_count(ext); i++) { + const elf_shdr_t *shdr; + enum llext_mem s_region = LLEXT_MEM_COUNT; + size_t s_offset = 0; - if (!init_offset) - init_offset = shdr->sh_offset; + llext_get_section_info(ldr, ext, i, &shdr, &s_region, &s_offset); - /* found a section within the region */ - size_t offset = shdr->sh_offset - init_offset; + if (s_region != region) + continue; - ret = memcpy_s((__sparse_force void *)shdr->sh_addr, size - offset, - load_base + offset, shdr->sh_size); + ret = memcpy_s((__sparse_force void *)shdr->sh_addr, size - s_offset, + (const uint8_t *)region_addr + s_offset, shdr->sh_size); if (ret < 0) return ret; } @@ -120,6 +121,10 @@ 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, const struct lib_manager_module *mctx) { + const elf_shdr_t *bss_hdr; + + llext_get_region_info(&ebl->loader, ext, LLEXT_MEM_BSS, &bss_hdr, NULL, NULL); + /* Executable code (.text) */ void __sparse_cache *va_base_text = (void __sparse_cache *) mctx->segment[LIB_MANAGER_TEXT].addr; @@ -137,8 +142,8 @@ static int llext_manager_load_module(const struct llext *ext, const struct llext /* .bss, should be within writable data above */ void __sparse_cache *bss_addr = (void __sparse_cache *) - ebl->loader.sects[LLEXT_MEM_BSS].sh_addr; - size_t bss_size = ebl->loader.sects[LLEXT_MEM_BSS].sh_size; + bss_hdr->sh_addr; + size_t bss_size = bss_hdr->sh_size; int ret; /* Check, that .bss is within .data */ @@ -151,7 +156,7 @@ static int llext_manager_load_module(const struct llext *ext, const struct llext va_base_data = bss_addr; data_size += bss_size; } else if ((uintptr_t)bss_addr == (uintptr_t)va_base_data + - ALIGN_UP(data_size, ebl->loader.sects[LLEXT_MEM_BSS].sh_addralign)) { + ALIGN_UP(data_size, bss_hdr->sh_addralign)) { /* .bss directly behind writable data, append */ data_size += bss_size; } else { @@ -163,20 +168,20 @@ static int llext_manager_load_module(const struct llext *ext, const struct llext } /* Copy Code */ - ret = llext_manager_load_data_from_storage(ext, va_base_text, ext->mem[LLEXT_MEM_TEXT], - text_size, SYS_MM_MEM_PERM_EXEC); + ret = llext_manager_load_data_from_storage(&ebl->loader, ext, LLEXT_MEM_TEXT, + va_base_text, text_size, SYS_MM_MEM_PERM_EXEC); if (ret < 0) return ret; /* Copy read-only data */ - ret = llext_manager_load_data_from_storage(ext, va_base_rodata, ext->mem[LLEXT_MEM_RODATA], - rodata_size, 0); + ret = llext_manager_load_data_from_storage(&ebl->loader, ext, LLEXT_MEM_RODATA, + va_base_rodata, rodata_size, 0); if (ret < 0) goto e_text; /* Copy writable data */ - ret = llext_manager_load_data_from_storage(ext, va_base_data, ext->mem[LLEXT_MEM_DATA], - data_size, SYS_MM_MEM_PERM_RW); + ret = llext_manager_load_data_from_storage(&ebl->loader, ext, LLEXT_MEM_DATA, + va_base_data, data_size, SYS_MM_MEM_PERM_RW); if (ret < 0) goto e_rodata; @@ -240,49 +245,58 @@ static int llext_manager_link(struct llext_buf_loader *ebl, const char *name, .relocate_local = !mctx->segment[LIB_MANAGER_TEXT].size, .pre_located = true, .section_detached = llext_manager_section_detached, + .keep_section_info = true, }; + const elf_shdr_t *hdr; int ret; ret = llext_load(&ebl->loader, name, llext, &ldr_parm); if (ret) return ret; - 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; + /* All code sections */ + llext_get_region_info(&ebl->loader, *llext, LLEXT_MEM_TEXT, + &hdr, NULL, NULL); + mctx->segment[LIB_MANAGER_TEXT].addr = hdr->sh_addr; + mctx->segment[LIB_MANAGER_TEXT].size = hdr->sh_size; tr_dbg(&lib_manager_tr, ".text: start: %#lx size %#x", mctx->segment[LIB_MANAGER_TEXT].addr, mctx->segment[LIB_MANAGER_TEXT].size); /* All read-only data sections */ - mctx->segment[LIB_MANAGER_RODATA].addr = - ebl->loader.sects[LLEXT_MEM_RODATA].sh_addr; - mctx->segment[LIB_MANAGER_RODATA].size = ebl->loader.sects[LLEXT_MEM_RODATA].sh_size; + llext_get_region_info(&ebl->loader, *llext, LLEXT_MEM_RODATA, + &hdr, NULL, NULL); + mctx->segment[LIB_MANAGER_RODATA].addr = hdr->sh_addr; + mctx->segment[LIB_MANAGER_RODATA].size = hdr->sh_size; tr_dbg(&lib_manager_tr, ".rodata: start: %#lx size %#x", mctx->segment[LIB_MANAGER_RODATA].addr, mctx->segment[LIB_MANAGER_RODATA].size); /* All writable data sections */ - mctx->segment[LIB_MANAGER_DATA].addr = - ebl->loader.sects[LLEXT_MEM_DATA].sh_addr; - mctx->segment[LIB_MANAGER_DATA].size = ebl->loader.sects[LLEXT_MEM_DATA].sh_size; + llext_get_region_info(&ebl->loader, *llext, LLEXT_MEM_DATA, + &hdr, NULL, NULL); + mctx->segment[LIB_MANAGER_DATA].addr = hdr->sh_addr; + mctx->segment[LIB_MANAGER_DATA].size = hdr->sh_size; tr_dbg(&lib_manager_tr, ".data: start: %#lx size %#x", mctx->segment[LIB_MANAGER_DATA].addr, mctx->segment[LIB_MANAGER_DATA].size); *buildinfo = NULL; - ssize_t binfo_o = llext_find_section(&ebl->loader, ".mod_buildinfo"); - - if (binfo_o >= 0) - *buildinfo = llext_peek(&ebl->loader, binfo_o); + ret = llext_section_shndx(&ebl->loader, *llext, ".mod_buildinfo"); + if (ret >= 0) { + llext_get_section_info(&ebl->loader, *llext, ret, &hdr, NULL, NULL); + *buildinfo = llext_peek(&ebl->loader, hdr->sh_offset); + } *mod_manifest = NULL; - ssize_t mod_o = llext_find_section(&ebl->loader, ".module"); - - if (mod_o >= 0) - *mod_manifest = llext_peek(&ebl->loader, mod_o); + ret = llext_section_shndx(&ebl->loader, *llext, ".module"); + if (ret >= 0) { + llext_get_section_info(&ebl->loader, *llext, ret, &hdr, NULL, NULL); + *mod_manifest = llext_peek(&ebl->loader, hdr->sh_offset); + } return *buildinfo && *mod_manifest ? 0 : -EPROTO; } From 4987f6253469ef00822354f6873c2ae2b07f69de Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Tue, 11 Feb 2025 17:39:42 +0100 Subject: [PATCH 4/4] llext_manager: [TMP] add debugging code Add debugging code for comparing memory copy operations between previous and current situations. Signed-off-by: Luca Burelli --- src/library_manager/llext_manager.c | 44 ++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index 23a81e5b1fcd..70326f43c514 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -86,11 +86,31 @@ static int llext_manager_load_data_from_storage(const struct llext_loader *ldr, return ret; } + /* DEBUG */ + size_t init_offset = 0; + const elf_shdr_t *shdr; + + /* Need to copy sections within regions individually, offsets may differ */ + for (i = 0, shdr = llext_section_headers(ext); i < llext_section_count(ext); i++, shdr++) { + if ((uintptr_t)shdr->sh_addr < (uintptr_t)vma || + (uintptr_t)shdr->sh_addr >= (uintptr_t)vma + size) + continue; + + if (!init_offset) + init_offset = shdr->sh_offset; + + /* found a section within the region */ + size_t offset = shdr->sh_offset - init_offset; + + tr_info(&lib_manager_tr, "old %u: %p -> %p, %u", i, + (void *)shdr->sh_addr, + (const uint8_t *)ext->mem[region] + offset, shdr->sh_size); + } + llext_get_region_info(ldr, ext, region, NULL, ®ion_addr, NULL); /* Need to copy sections within regions individually, offsets may differ */ for (i = 0; i < llext_section_count(ext); i++) { - const elf_shdr_t *shdr; enum llext_mem s_region = LLEXT_MEM_COUNT; size_t s_offset = 0; @@ -99,6 +119,10 @@ static int llext_manager_load_data_from_storage(const struct llext_loader *ldr, if (s_region != region) continue; + tr_info(&lib_manager_tr, "%u: %p -> %p, %u", i, + (void *)shdr->sh_addr, + (const uint8_t *)region_addr + s_offset, shdr->sh_size); + ret = memcpy_s((__sparse_force void *)shdr->sh_addr, size - s_offset, (const uint8_t *)region_addr + s_offset, shdr->sh_size); if (ret < 0) @@ -260,9 +284,9 @@ static int llext_manager_link(struct llext_buf_loader *ebl, const char *name, mctx->segment[LIB_MANAGER_TEXT].addr = hdr->sh_addr; mctx->segment[LIB_MANAGER_TEXT].size = hdr->sh_size; - tr_dbg(&lib_manager_tr, ".text: start: %#lx size %#x", - mctx->segment[LIB_MANAGER_TEXT].addr, - mctx->segment[LIB_MANAGER_TEXT].size); + tr_info(&lib_manager_tr, ".text: start: %#lx size %#x", + mctx->segment[LIB_MANAGER_TEXT].addr, + mctx->segment[LIB_MANAGER_TEXT].size); /* All read-only data sections */ llext_get_region_info(&ebl->loader, *llext, LLEXT_MEM_RODATA, @@ -270,9 +294,9 @@ static int llext_manager_link(struct llext_buf_loader *ebl, const char *name, mctx->segment[LIB_MANAGER_RODATA].addr = hdr->sh_addr; mctx->segment[LIB_MANAGER_RODATA].size = hdr->sh_size; - tr_dbg(&lib_manager_tr, ".rodata: start: %#lx size %#x", - mctx->segment[LIB_MANAGER_RODATA].addr, - mctx->segment[LIB_MANAGER_RODATA].size); + tr_info(&lib_manager_tr, ".rodata: start: %#lx size %#x", + mctx->segment[LIB_MANAGER_RODATA].addr, + mctx->segment[LIB_MANAGER_RODATA].size); /* All writable data sections */ llext_get_region_info(&ebl->loader, *llext, LLEXT_MEM_DATA, @@ -280,9 +304,9 @@ static int llext_manager_link(struct llext_buf_loader *ebl, const char *name, mctx->segment[LIB_MANAGER_DATA].addr = hdr->sh_addr; mctx->segment[LIB_MANAGER_DATA].size = hdr->sh_size; - tr_dbg(&lib_manager_tr, ".data: start: %#lx size %#x", - mctx->segment[LIB_MANAGER_DATA].addr, - mctx->segment[LIB_MANAGER_DATA].size); + tr_info(&lib_manager_tr, ".data: start: %#lx size %#x", + mctx->segment[LIB_MANAGER_DATA].addr, + mctx->segment[LIB_MANAGER_DATA].size); *buildinfo = NULL; ret = llext_section_shndx(&ebl->loader, *llext, ".mod_buildinfo");