3030#include <zephyr/llext/llext.h>
3131#include <zephyr/logging/log_ctrl.h>
3232#include <zephyr/llext/inspect.h>
33+ #include <kernel_arch_interface.h>
3334
3435#include <rimage/sof/user/manifest.h>
3536#include <module/module/api_ver.h>
@@ -71,6 +72,32 @@ static int llext_manager_align_unmap(void __sparse_cache *vma, size_t size)
7172 return sys_mm_drv_unmap_region (aligned_vma , ALIGN_UP (pre_pad_size + size , PAGE_SZ ));
7273}
7374
75+ static void llext_manager_detached_map (void __sparse_cache * vma , size_t size , uint32_t flags )
76+ {
77+ #ifdef CONFIG_MMU
78+ size_t pre_pad_size = (uintptr_t )vma & (PAGE_SZ - 1 );
79+ void * aligned_vma = (__sparse_force uint8_t * )vma - pre_pad_size ;
80+
81+ /* Use cached virtual address */
82+ uintptr_t va = POINTER_TO_UINT (sys_cache_cached_ptr_get (aligned_vma ));
83+
84+ arch_mem_map (aligned_vma , va , ALIGN_UP (pre_pad_size + size , PAGE_SZ ), flags );
85+ #endif
86+ }
87+
88+ static void llext_manager_detached_unmap (void __sparse_cache * vma , size_t size )
89+ {
90+ #ifdef CONFIG_MMU
91+ size_t pre_pad_size = (uintptr_t )vma & (PAGE_SZ - 1 );
92+ void * aligned_vma = (__sparse_force uint8_t * )vma - pre_pad_size ;
93+
94+ /* Use cached virtual address */
95+ void * va = sys_cache_cached_ptr_get (aligned_vma );
96+
97+ arch_mem_unmap (va , ALIGN_UP (pre_pad_size + size , PAGE_SZ ));
98+ #endif
99+ }
100+
74101/*
75102 * Map the memory range covered by 'vma' and 'size' as writable, copy all
76103 * sections that belong to the specified 'region' and are contained in the
@@ -107,8 +134,16 @@ static int llext_manager_load_data_from_storage(const struct llext_loader *ldr,
107134
108135 /* skip detached sections (will be outside requested VMA area) */
109136 if ((uintptr_t )shdr -> sh_addr < (uintptr_t )vma ||
110- (uintptr_t )shdr -> sh_addr >= (uintptr_t )vma + size )
137+ (uintptr_t )shdr -> sh_addr >= (uintptr_t )vma + size ) {
138+ llext_manager_detached_map ((__sparse_force void * )
139+ ((uint8_t * )region_addr + s_offset ),
140+ shdr -> sh_size , flags );
141+ if (flags & SYS_MM_MEM_PERM_EXEC )
142+ icache_invalidate_region ((__sparse_force void * )
143+ ((uint8_t * )region_addr + s_offset ),
144+ shdr -> sh_size );
111145 continue ;
146+ }
112147
113148 ret = memcpy_s ((__sparse_force void * )shdr -> sh_addr , size - s_offset ,
114149 (const uint8_t * )region_addr + s_offset , shdr -> sh_size );
@@ -129,6 +164,39 @@ static int llext_manager_load_data_from_storage(const struct llext_loader *ldr,
129164 return ret ;
130165}
131166
167+ static void llext_manager_unmap_detached_sections (const struct llext_loader * ldr ,
168+ const struct llext * ext ,
169+ enum llext_mem region ,
170+ void __sparse_cache * vma ,
171+ size_t size )
172+ {
173+ #ifdef CONFIG_MMU
174+ unsigned int i ;
175+ const void * region_addr ;
176+
177+ llext_get_region_info (ldr , ext , region , NULL , & region_addr , NULL );
178+
179+ for (i = 0 ; i < llext_section_count (ext ); i ++ ) {
180+ const elf_shdr_t * shdr ;
181+ enum llext_mem s_region = LLEXT_MEM_COUNT ;
182+ size_t s_offset = 0 ;
183+
184+ llext_get_section_info (ldr , ext , i , & shdr , & s_region , & s_offset );
185+
186+ /* skip sections not in the requested region */
187+ if (s_region != region )
188+ continue ;
189+
190+ /* unmap detached sections (will be outside requested VMA area) */
191+ if ((uintptr_t )shdr -> sh_addr < (uintptr_t )vma ||
192+ (uintptr_t )shdr -> sh_addr >= (uintptr_t )vma + size )
193+ llext_manager_detached_unmap ((__sparse_force void * )
194+ ((uint8_t * )region_addr + s_offset ),
195+ shdr -> sh_size );
196+ }
197+ #endif
198+ }
199+
132200static int llext_manager_load_module (struct lib_manager_module * mctx )
133201{
134202 /* Executable code (.text) */
@@ -216,6 +284,9 @@ static int llext_manager_load_module(struct lib_manager_module *mctx)
216284
217285static int llext_manager_unload_module (struct lib_manager_module * mctx )
218286{
287+ const struct llext_loader * ldr = & mctx -> ebl -> loader ;
288+ const struct llext * ext = mctx -> llext ;
289+
219290 /* Executable code (.text) */
220291 void __sparse_cache * va_base_text = (void __sparse_cache * )
221292 mctx -> segment [LIB_MANAGER_TEXT ].addr ;
@@ -232,14 +303,20 @@ static int llext_manager_unload_module(struct lib_manager_module *mctx)
232303 size_t data_size = mctx -> segment [LIB_MANAGER_DATA ].size ;
233304 int err = 0 , ret ;
234305
306+ llext_manager_unmap_detached_sections (ldr , ext , LLEXT_MEM_TEXT ,
307+ va_base_text , text_size );
235308 ret = llext_manager_align_unmap (va_base_text , text_size );
236309 if (ret < 0 )
237310 err = ret ;
238311
312+ llext_manager_unmap_detached_sections (ldr , ext , LLEXT_MEM_DATA ,
313+ va_base_data , data_size );
239314 ret = llext_manager_align_unmap (va_base_data , data_size );
240315 if (ret < 0 && !err )
241316 err = ret ;
242317
318+ llext_manager_unmap_detached_sections (ldr , ext , LLEXT_MEM_RODATA ,
319+ va_base_rodata , rodata_size );
243320 ret = llext_manager_align_unmap (va_base_rodata , rodata_size );
244321 if (ret < 0 && !err )
245322 err = ret ;
0 commit comments