Loadable Library Manager

The Loadable Library Manager is a MPP Layer component responsible for loading and running loadable components provided in external libraries. It supports SOF native components as well as IADK cAVS/ACE developed modules through IADK Modules Adapter.

Loading an external library is a feature available only for IPC4 protocol with command: SOF_IPC4_GLB_LOAD_LIBRARY.

@startuml

box "Host" #LightGreen
	participant "Driver" as host_driver
end box

box "SOF" #LightBlue
	participant "IPC4 Handler" as ipc4_handler
	participant "Library Manager" as library_manager
	participant "MPP Memory Manager" as mpp_memory_manager
end box

box "ACE Platform" #LightYellow
	participant "ROM EXT" as rom_ext
end box


host_driver -> ipc4_handler: SOF_IPC4_GLB_LOAD_LIBRARY
	activate ipc4_handler
	ipc4_handler -> library_manager: lib_manager_load_library()
	activate library_manager
	library_manager -> library_manager: Parse Manifest \nPrepare Storage Memory
	library_manager -> mpp_memory_manager: Allocate L3 memory for library
	activate mpp_memory_manager
	mpp_memory_manager -> library_manager
	deactivate mpp_memory_manager
	library_manager -> library_manager: Prepare HDA DMA transfer
	host_driver -> library_manager: Transfer library manifest over DMA\nto L3 memory
	note right: if SoC does not support L3 memory\nthen L2 memory has to be used
	opt if AUTH_API_ENABLED
		library_manager -> rom_ext: Verify Manifest
		activate rom_ext
		rom_ext -> library_manager: result
		deactivate rom_ext
	end opt
	host_driver -> library_manager: Transfer library code over DMA\nto L3 memory
	opt if AUTH_API_ENABLED
		library_manager -> rom_ext: Verify whole Library
		activate rom_ext
		rom_ext -> library_manager: result
		deactivate rom_ext
	end opt
	library_manager -> library_manager: Update Library \ndescriptors table
	library_manager -> ipc4_handler: return status
	deactivate library_manager
ipc4_handler -> host_driver: Complete IPC request
deactivate ipc4_handler

@enduml

Figure 54 Library Manager: Load library flow

In the SOF_IPC4_GLB_LOAD_LIBRARY IPC flow the lib_manager_load_library() api function loads binary from host driver to DSP memory and updates its internal structure with library descriptor data. If AUTH_API Kconfig option is selected, library manager communicates with platform ROM Extension library to perform library image verification. In that case only trusted libraries will be successfully loaded.

NOTE: AUTH_API Kconfig option is available only for Intel platforms.

During the SOF_IPC4_MOD_INIT_INSTANCE IPC4 protocol call, handler searches for specific module among build-in components and if not found, verifies manifests of all already loaded external libraries. When module is found in external library, it is registered in SOF Firmware struct comp_driver_list with lib_manager_register_module() api function and loaded from L3 memory to L2 memory. Afterwards module is created with standard component device operation.

NOTE: If L3 memory is not available, the L2 memory has to be used and there is no memory load operation required.

@startuml

box "Host" #LightGreen
	participant "Driver" as host_driver
end box

box "SOF" #LightSkyBlue
	participant "IPC4 Handler" as ipc4_handler
	participant "Component Manager" as component_manager
	participant "Library Manager" as library_manager
end box

box "Zephyr RTOS" #LightBlue
	participant "Memory Management Driver" as memory_management_driver
end box

host_driver -> ipc4_handler: SOF_IPC4_MOD_INIT_INSTANCE
	activate ipc4_handler
	ipc4_handler -> library_manager: lib_manager_register_module()
	activate library_manager
	library_manager -> ipc4_handler: return status
	deactivate library_manager
	ipc4_handler -> component_manager: Create comp_driver
		activate component_manager
		component_manager -> library_manager: Allocate L2 memory for module
		activate library_manager
		library_manager -> memory_management_driver: Map L2 memory
		deactivate library_manager
		activate memory_management_driver
		memory_management_driver -> library_manager
		deactivate memory_management_driver
		activate library_manager
		library_manager -> memory_management_driver: Load module code and rodata \nfrom L3 to L2 memory
		activate memory_management_driver
		memory_management_driver -> library_manager
		deactivate memory_management_driver
		library_manager -> memory_management_driver: Initialize L2 memory for bss
		activate memory_management_driver
		memory_management_driver -> library_manager
		deactivate memory_management_driver
	loop Search library for shared module
		library_manager -> library_manager: Check if shared module exists and is not loaded
		library_manager -> memory_management_driver: Allocate/Map L2 memory for shared module
		activate memory_management_driver
		memory_management_driver -> library_manager
		deactivate memory_management_driver
		library_manager -> memory_management_driver: Load shared module code and rodata \nfrom L3 to L2 memory
		activate memory_management_driver
		memory_management_driver -> library_manager
		deactivate memory_management_driver
	end loop
	alt IADK module
		component_manager -> library_manager: Create/Initialize comp_driver \nwith IADK Module Adapter 
		library_manager -> component_manager: return status
	else SOF module
		component_manager -> library_manager: Create/Initialize comp_driver 
		library_manager -> component_manager: return status
		deactivate library_manager
	end alt
	component_manager -> ipc4_handler: return status
	deactivate component_manager
ipc4_handler -> host_driver: Complete IPC request
deactivate ipc4_handler

@enduml

Figure 55 Init instance flow for loadable module

External libraries could contain not only processing modules but also shared library code that could be reused across several external modules. The library manager searches external library manifest for such entities and loads them together with first processing module loaded.

When an external processing module is no longer needed, it could be unloaded with the IPC4 call SOF_IPC4_MOD_DELETE_INSTANCE. The command performs reverse flow to the previous one. It frees L2 SRAM memory allocated for the processing module and if it is last one unloaded from given library, it frees also resources used for all shared libraries loaded previously.

@startuml

box "Host" #LightGreen
	participant "Driver" as host_driver
end box

box "SOF" #LightSkyBlue
	participant "IPC4 Handler" as ipc4_handler
	participant "Component Manager" as component_manager
	participant "Library Manager" as library_manager
end box

box "Zephyr RTOS" #LightBlue
	participant "Memory Management Driver" as memory_management_driver
end box

host_driver -> ipc4_handler: SOF_IPC4_MOD_DELETE_INSTANCE
	activate ipc4_handler
	ipc4_handler -> component_manager: Free comp_driver
	activate component_manager
	alt IADK module
		component_manager -> library_manager: Deinitialize comp_driver \nwith Processing Module Adapter 
		activate library_manager
		library_manager -> component_manager: return status
		deactivate library_manager
	else SOF module
		component_manager -> library_manager: Deinitialize comp_driver 
		activate library_manager
		library_manager -> component_manager: return status
		deactivate library_manager
	end alt
	component_manager -> library_manager: Free comp_driver resources
	activate library_manager
	library_manager -> memory_management_driver: Free/Unmap L2 memory for code and rodata
	activate memory_management_driver
	memory_management_driver -> library_manager
	deactivate memory_management_driver
	library_manager -> memory_management_driver: Free/Unmap L2 memory for bss
	activate memory_management_driver
	memory_management_driver -> library_manager
	deactivate memory_management_driver
	loop Search library for shared module
		library_manager -> library_manager: Check if shared module exists and is loaded
		library_manager -> memory_management_driver: Free/Unmap L2 memory for shared module
		activate memory_management_driver
		memory_management_driver -> library_manager
		deactivate memory_management_driver
	end loop
	library_manager -> component_manager: return status
	deactivate library_manager
	component_manager -> ipc4_handler: return status
	deactivate component_manager
ipc4_handler -> host_driver: Complete IPC request
deactivate ipc4_handler

@enduml

Figure 56 Delete instance flow for loadable module

In SOF_IPC4_MOD_INIT_INSTANCE and SOF_IPC4_MOD_DELETE_INSTANCE flows, particular module could be loaded in more than one instance. Its .text and .rodata memory sections are allocated only for the first instance and shared for all other instances. Also the .text and .rodata resources are released only for the last instance of given processing module.