@@ -104,7 +104,7 @@ static int llext_manager_load_data_from_storage(void __sparse_cache *vma, void *
104104 return ret ;
105105}
106106
107- static int llext_manager_load_module (uint32_t module_id , const struct sof_man_module * mod )
107+ static int llext_manager_load_module (uint32_t module_id )
108108{
109109 struct lib_manager_mod_ctx * ctx = lib_manager_get_mod_ctx (module_id );
110110 uint8_t * load_base = (uint8_t * )ctx -> base_addr ;
@@ -185,9 +185,8 @@ static int llext_manager_load_module(uint32_t module_id, const struct sof_man_mo
185185 return ret ;
186186}
187187
188- static int llext_manager_unload_module (uint32_t module_id , const struct sof_man_module * mod )
188+ static int llext_manager_unload_module (struct lib_manager_mod_ctx * ctx )
189189{
190- struct lib_manager_mod_ctx * ctx = lib_manager_get_mod_ctx (module_id );
191190 /* Executable code (.text) */
192191 void __sparse_cache * va_base_text = (void __sparse_cache * )
193192 ctx -> segment [LIB_MANAGER_TEXT ].addr ;
@@ -219,8 +218,9 @@ static int llext_manager_unload_module(uint32_t module_id, const struct sof_man_
219218 return err ;
220219}
221220
222- static int llext_manager_link (struct sof_man_fw_desc * desc , struct sof_man_module * mod ,
223- uint32_t module_id , struct llext * * llext , const void * * buildinfo ,
221+ static int llext_manager_link (const struct sof_man_fw_desc * desc , const struct sof_man_module * mod ,
222+ uint32_t module_id , struct llext * * llext ,
223+ const struct sof_module_api_build_info * * buildinfo ,
224224 const struct sof_man_module_manifest * * mod_manifest )
225225{
226226 size_t mod_size = desc -> header .preload_page_count * PAGE_SZ - FILE_TEXT_OFFSET_V1_8 ;
@@ -291,10 +291,34 @@ static int llext_manager_link(struct sof_man_fw_desc *desc, struct sof_man_modul
291291 return binfo_o >= 0 && mod_o >= 0 ? 0 : - EPROTO ;
292292}
293293
294+ static int llext_lib_find (const struct llext * llext , struct lib_manager_mod_ctx * * dep_ctx )
295+ {
296+ struct ext_library * _ext_lib = ext_lib_get ();
297+ unsigned int i ;
298+
299+ if (!llext )
300+ return - EINVAL ;
301+
302+ for (i = 0 ; i < ARRAY_SIZE (_ext_lib -> desc ); i ++ )
303+ if (_ext_lib -> desc [i ] && _ext_lib -> desc [i ]-> llext == llext ) {
304+ * dep_ctx = _ext_lib -> desc [i ];
305+ return i ;
306+ }
307+
308+ return - ENOENT ;
309+ }
310+
311+ static void llext_depend_unlink (struct lib_manager_mod_ctx * dep_ctx [], int n )
312+ {
313+ for (; n >= 0 ; n -- )
314+ if (dep_ctx [n ]-> llext -> use_count == 1 )
315+ llext_manager_unload_module (dep_ctx [n ]);
316+ }
317+
294318uintptr_t llext_manager_allocate_module (const struct comp_ipc_config * ipc_config ,
295319 const void * ipc_specific_config )
296320{
297- struct sof_man_fw_desc * desc ;
321+ const struct sof_man_fw_desc * desc ;
298322 struct sof_man_module * mod_array ;
299323 int ret ;
300324 uint32_t module_id = IPC4_MOD_ID (ipc_config -> id );
@@ -311,11 +335,16 @@ uintptr_t llext_manager_allocate_module(const struct comp_ipc_config *ipc_config
311335 return 0 ;
312336 }
313337
314- mod_array = (struct sof_man_module * )((char * )desc + SOF_MAN_MODULE_OFFSET (0 ));
338+ mod_array = (struct sof_man_module * )((const char * )desc + SOF_MAN_MODULE_OFFSET (0 ));
315339
316- /* LLEXT linking is only needed once for all the modules in the library */
340+ /*
341+ * LLEXT linking is only needed once for all the modules in the library.
342+ * This calls llext_load(), which also takes references to any
343+ * dependencies, sets up sections and retrieves buildinfo and
344+ * mod_manifest
345+ */
317346 ret = llext_manager_link (desc , mod_array , module_id , & ctx -> llext ,
318- ( const void * * ) & buildinfo , & mod_manifest );
347+ & buildinfo , & mod_manifest );
319348 if (ret < 0 )
320349 return 0 ;
321350
@@ -327,8 +356,49 @@ uintptr_t llext_manager_allocate_module(const struct comp_ipc_config *ipc_config
327356 return - ENOEXEC ;
328357 }
329358
359+ int i ;
360+
361+ /* Check if any dependencies need to be mapped */
362+ for (i = 0 ; i < ARRAY_SIZE (ctx -> llext -> dependency ); i ++ ) {
363+ /* Dependencies are filled from the beginning of the array upwards */
364+ if (!ctx -> llext -> dependency [i ])
365+ break ;
366+
367+ /*
368+ * Protected by the IPC serialization, but maybe we should protect the
369+ * use-count explicitly too. Currently the use-count is first incremented
370+ * when an auxiliary library is loaded, it was then additionally incremented
371+ * when the current dependent module was mapped. If it's higher than two,
372+ * then some other modules also depend on it and have already mapped it.
373+ */
374+ if (ctx -> llext -> dependency [i ]-> use_count > 2 )
375+ continue ;
376+
377+ /* First user of this dependency, load it into SRAM */
378+ struct lib_manager_mod_ctx * dep_ctx [LLEXT_MAX_DEPENDENCIES ];
379+ int dep_id = llext_lib_find (ctx -> llext -> dependency [i ], & dep_ctx [i ]);
380+
381+ if (dep_id < 0 ) {
382+ tr_err (& lib_manager_tr ,
383+ "Unmet dependency: cannot find dependency %u" , i );
384+ continue ;
385+ }
386+
387+ tr_info (& lib_manager_tr , "%s depending on %s base %p, %u users" ,
388+ ctx -> llext -> name ,
389+ ctx -> llext -> dependency [i ]-> name ,
390+ dep_ctx [i ]-> base_addr ,
391+ ctx -> llext -> dependency [i ]-> use_count );
392+
393+ ret = llext_manager_load_module (dep_id << LIB_MANAGER_LIB_ID_SHIFT );
394+ if (ret < 0 ) {
395+ llext_depend_unlink (dep_ctx , i - 1 );
396+ return 0 ;
397+ }
398+ }
399+
330400 /* Map executable code and data */
331- ret = llext_manager_load_module (module_id , mod_array );
401+ ret = llext_manager_load_module (module_id );
332402 if (ret < 0 )
333403 return 0 ;
334404
@@ -348,7 +418,6 @@ uintptr_t llext_manager_allocate_module(const struct comp_ipc_config *ipc_config
348418
349419int llext_manager_free_module (const uint32_t component_id )
350420{
351- const struct sof_man_module * mod ;
352421 const uint32_t module_id = IPC4_MOD_ID (component_id );
353422 const unsigned int base_module_id = LIB_MANAGER_GET_LIB_ID (module_id ) <<
354423 LIB_MANAGER_LIB_ID_SHIFT ;
@@ -361,13 +430,36 @@ int llext_manager_free_module(const uint32_t component_id)
361430 return - ENOENT ;
362431 }
363432
433+ struct lib_manager_mod_ctx * dep_ctx [LLEXT_MAX_DEPENDENCIES ] = {};
434+ int i ;
435+
436+ for (i = 0 ; i < ARRAY_SIZE (ctx -> llext -> dependency ); i ++ )
437+ if (llext_lib_find (ctx -> llext -> dependency [i ], & dep_ctx [i ]) < 0 )
438+ break ;
439+
364440 if (llext_unload (& ctx -> llext ))
365441 /* More users are active */
366442 return 0 ;
367443
368- mod = lib_manager_get_module_manifest (base_module_id );
444+ /* Last user cleaning up, put dependencies */
445+ if (i > 0 )
446+ llext_depend_unlink (dep_ctx , i - 1 );
447+
448+ return llext_manager_unload_module (ctx );
449+ }
450+
451+ /* An auxiliary library has been loaded, need to read in its exported symbols */
452+ int llext_manager_add_library (const struct sof_man_module * mod , uint32_t module_id )
453+ {
454+ if (mod -> type .load_type != SOF_MAN_MOD_TYPE_LLEXT_AUX )
455+ return 0 ;
456+
457+ struct lib_manager_mod_ctx * const ctx = lib_manager_get_mod_ctx (module_id );
458+ const struct sof_man_fw_desc * desc = lib_manager_get_library_manifest (module_id );
459+ const struct sof_module_api_build_info * buildinfo ;
460+ const struct sof_man_module_manifest * mod_manifest ;
369461
370- return llext_manager_unload_module ( base_module_id , mod );
462+ return llext_manager_link ( desc , mod , module_id , & ctx -> llext , & buildinfo , & mod_manifest );
371463}
372464
373465bool comp_is_llext (struct comp_dev * comp )
0 commit comments