@@ -54,7 +54,7 @@ static int lib_manager_load_data_from_storage(void __sparse_cache *vma, void *s_
5454 uint32_t size , uint32_t flags )
5555{
5656 int ret = sys_mm_drv_map_region ((__sparse_force void * )vma , POINTER_TO_UINT (NULL ),
57- size , flags );
57+ size , SYS_MM_MEM_PERM_RW );
5858 if (ret < 0 )
5959 return ret ;
6060
@@ -68,114 +68,134 @@ static int lib_manager_load_data_from_storage(void __sparse_cache *vma, void *s_
6868 return 0 ;
6969}
7070
71- static int lib_manager_load_module (uint32_t module_id , struct sof_man_module * mod ,
72- struct sof_man_fw_desc * desc )
71+ static int lib_manager_load_module (const uint32_t module_id ,
72+ const struct sof_man_module * const mod )
7373{
74- struct ext_library * ext_lib = ext_lib_get ();
75- uint32_t lib_id = LIB_MANAGER_GET_LIB_ID (module_id );
76- size_t load_offset = (size_t )((void * )ext_lib -> desc [lib_id ]);
77- void __sparse_cache * va_base_text = (void __sparse_cache * )
78- mod -> segment [SOF_MAN_SEGMENT_TEXT ].v_base_addr ;
79- void * src_txt = (void * )(mod -> segment [SOF_MAN_SEGMENT_TEXT ].file_offset + load_offset );
80- size_t st_text_size = mod -> segment [SOF_MAN_SEGMENT_TEXT ].flags .r .length ;
81- void __sparse_cache * va_base_rodata = (void __sparse_cache * )
82- mod -> segment [SOF_MAN_SEGMENT_RODATA ].v_base_addr ;
83- void * src_rodata =
84- (void * )(mod -> segment [SOF_MAN_SEGMENT_RODATA ].file_offset + load_offset );
85- size_t st_rodata_size = mod -> segment [SOF_MAN_SEGMENT_RODATA ].flags .r .length ;
74+ const struct ext_library * const ext_lib = ext_lib_get ();
75+ const uint32_t lib_id = LIB_MANAGER_GET_LIB_ID (module_id );
76+ const uintptr_t load_offset = POINTER_TO_UINT (ext_lib -> desc [lib_id ]);
77+ void * src , * va_base ;
78+ size_t size ;
79+ uint32_t flags ;
80+ int ret , idx ;
81+
82+ for (idx = 0 ; idx < ARRAY_SIZE (mod -> segment ); ++ idx ) {
83+ if (!mod -> segment [idx ].flags .r .load )
84+ continue ;
85+
86+ flags = 0 ;
87+
88+ if (mod -> segment [idx ].flags .r .code )
89+ flags = SYS_MM_MEM_PERM_EXEC ;
90+ else if (!mod -> segment [idx ].flags .r .readonly )
91+ flags |= SYS_MM_MEM_PERM_RW ;
92+
93+ src = UINT_TO_POINTER (mod -> segment [idx ].file_offset + load_offset );
94+ va_base = UINT_TO_POINTER (mod -> segment [idx ].v_base_addr );
95+ size = mod -> segment [idx ].flags .r .length * PAGE_SZ ;
96+ ret = lib_manager_load_data_from_storage (va_base , src , size , flags );
97+ if (ret < 0 )
98+ goto err ;
99+ }
100+
101+ return 0 ;
102+
103+ err :
104+ for (-- idx ; idx >= 0 ; -- idx ) {
105+ if (!mod -> segment [idx ].flags .r .load )
106+ continue ;
107+
108+ va_base = UINT_TO_POINTER (mod -> segment [idx ].v_base_addr );
109+ size = mod -> segment [idx ].flags .r .length * PAGE_SZ ;
110+ sys_mm_drv_unmap_region (va_base , size );
111+ }
112+
113+ return ret ;
114+ }
115+
116+ static int lib_manager_unload_module (const struct sof_man_module * const mod )
117+ {
118+ void * va_base ;
119+ size_t size ;
120+ uint32_t idx ;
86121 int ret ;
87122
88- st_text_size = st_text_size * PAGE_SZ ;
89- st_rodata_size = st_rodata_size * PAGE_SZ ;
123+ for (idx = 0 ; idx < ARRAY_SIZE (mod -> segment ); ++ idx ) {
124+ if (!mod -> segment [idx ].flags .r .load )
125+ continue ;
90126
91- /* Copy Code */
92- ret = lib_manager_load_data_from_storage (va_base_text , src_txt , st_text_size ,
93- SYS_MM_MEM_PERM_RW | SYS_MM_MEM_PERM_EXEC );
94- if (ret < 0 )
95- goto err ;
127+ va_base = UINT_TO_POINTER (mod -> segment [idx ].v_base_addr );
128+ size = mod -> segment [idx ].flags .r .length * PAGE_SZ ;
129+ ret = sys_mm_drv_unmap_region (va_base , size );
130+ if (ret < 0 )
131+ return ret ;
132+ }
96133
97- /* Copy RODATA */
98- ret = lib_manager_load_data_from_storage (va_base_rodata , src_rodata ,
99- st_rodata_size , SYS_MM_MEM_PERM_RW );
100- if (ret < 0 )
101- goto err ;
134+ return 0 ;
135+ }
102136
103- /* There are modules marked as lib_code. This is code shared between several modules inside
104- * the library. Load all lib_code modules with first none lib_code module load.
105- */
106- if (!mod -> type .lib_code )
107- ext_lib -> mods_exec_load_cnt ++ ;
108-
109- if (ext_lib -> mods_exec_load_cnt == 1 ) {
110- struct sof_man_module * module_entry =
111- (struct sof_man_module * )((char * )desc + SOF_MAN_MODULE_OFFSET (0 ));
112- for (size_t idx = 0 ; idx < desc -> header .num_module_entries ;
113- ++ idx , ++ module_entry ) {
114- if (module_entry -> type .lib_code ) {
115- ret = lib_manager_load_module (lib_id << LIB_MANAGER_LIB_ID_SHIFT |
116- idx , mod , desc );
117- if (ret < 0 )
118- goto err ;
119- }
137+ /* There are modules marked as lib_code. This is code shared between several modules inside
138+ * the library. Load all lib_code modules with first none lib_code module load.
139+ */
140+ static int lib_manager_load_code_modules (const uint32_t module_id ,
141+ const struct sof_man_fw_desc * const desc )
142+ {
143+ struct ext_library * const ext_lib = ext_lib_get ();
144+ const struct sof_man_module * module_entry = (struct sof_man_module * )
145+ ((char * )desc + SOF_MAN_MODULE_OFFSET (0 ));
146+ const uint32_t lib_id = LIB_MANAGER_GET_LIB_ID (module_id );
147+ int ret , idx ;
148+
149+ if (++ ext_lib -> mods_exec_load_cnt > 1 )
150+ return 0 ;
151+
152+ for (idx = 0 ; idx < desc -> header .num_module_entries ; ++ idx , ++ module_entry ) {
153+ if (module_entry -> type .lib_code ) {
154+ ret = lib_manager_load_module (lib_id << LIB_MANAGER_LIB_ID_SHIFT | idx ,
155+ module_entry );
156+ if (ret < 0 )
157+ goto err ;
120158 }
121159 }
122160
123161 return 0 ;
124162
125163err :
126- sys_mm_drv_unmap_region ((__sparse_force void * )va_base_text , st_text_size );
127- sys_mm_drv_unmap_region ((__sparse_force void * )va_base_rodata , st_rodata_size );
164+ for (-- idx , -- module_entry ; idx >= 0 ; -- idx , -- module_entry ) {
165+ if (module_entry -> type .lib_code ) {
166+ ret = lib_manager_unload_module (module_entry );
167+ if (ret < 0 )
168+ goto err ;
169+ }
170+ }
128171
129172 return ret ;
130173}
131174
132- static int lib_manager_unload_module (uint32_t module_id , struct sof_man_module * mod ,
133- struct sof_man_fw_desc * desc )
175+ /* There are modules marked as lib_code. This is code shared between several modules inside
176+ * the library. Unload all lib_code modules with last none lib_code module unload.
177+ */
178+ static int lib_manager_unload_code_modules (const uint32_t module_id ,
179+ const struct sof_man_fw_desc * const desc )
134180{
135- struct ext_library * ext_lib = ext_lib_get ();
136- uint32_t lib_id = LIB_MANAGER_GET_LIB_ID (module_id );
137- void __sparse_cache * va_base_text = (void __sparse_cache * )
138- mod -> segment [SOF_MAN_SEGMENT_TEXT ].v_base_addr ;
139- size_t st_text_size = mod -> segment [SOF_MAN_SEGMENT_TEXT ].flags .r .length ;
140- void __sparse_cache * va_base_rodata = (void __sparse_cache * )
141- mod -> segment [SOF_MAN_SEGMENT_RODATA ].v_base_addr ;
142- size_t st_rodata_size = mod -> segment [SOF_MAN_SEGMENT_RODATA ].flags .r .length ;
143- int ret ;
144-
145- st_text_size = st_text_size * PAGE_SZ ;
146- st_rodata_size = st_rodata_size * PAGE_SZ ;
147-
148- ret = sys_mm_drv_unmap_region ((__sparse_force void * )va_base_text , st_text_size );
149- if (ret < 0 )
150- return ret ;
151-
152- ret = sys_mm_drv_unmap_region ((__sparse_force void * )va_base_rodata , st_rodata_size );
153- if (ret < 0 )
154- return ret ;
181+ struct ext_library * const ext_lib = ext_lib_get ();
182+ const struct sof_man_module * module_entry = (struct sof_man_module * )
183+ ((char * )desc + SOF_MAN_MODULE_OFFSET (0 ));
184+ const uint32_t lib_id = LIB_MANAGER_GET_LIB_ID (module_id );
185+ int ret , idx ;
155186
156- /* There are modules marked as lib_code. This is code shared between several modules inside
157- * the library. Unload all lib_code modules with last none lib_code module unload.
158- */
159- if (mod -> type .lib_code )
160- return ret ;
187+ if (-- ext_lib -> mods_exec_load_cnt > 0 )
188+ return 0 ;
161189
162- if (!mod -> type .lib_code && ext_lib -> mods_exec_load_cnt > 0 )
163- ext_lib -> mods_exec_load_cnt -- ;
164-
165- if (ext_lib -> mods_exec_load_cnt == 0 ) {
166- struct sof_man_module * module_entry =
167- (struct sof_man_module * )((char * )desc + SOF_MAN_MODULE_OFFSET (0 ));
168- for (size_t idx = 0 ; idx < desc -> header .num_module_entries ;
169- ++ idx , ++ module_entry ) {
170- if (module_entry -> type .lib_code ) {
171- ret =
172- lib_manager_unload_module (lib_id << LIB_MANAGER_LIB_ID_SHIFT |
173- idx , mod , desc );
174- }
190+ for (idx = 0 ; idx < desc -> header .num_module_entries ; ++ idx , ++ module_entry ) {
191+ if (module_entry -> type .lib_code ) {
192+ ret = lib_manager_unload_module (module_entry );
193+ if (ret < 0 )
194+ return ret ;
175195 }
176196 }
177197
178- return ret ;
198+ return 0 ;
179199}
180200
181201static void __sparse_cache * lib_manager_get_instance_bss_address (uint32_t module_id ,
@@ -261,10 +281,16 @@ uint32_t lib_manager_allocate_module(const struct comp_driver *drv,
261281
262282 mod = (struct sof_man_module * )((char * )desc + SOF_MAN_MODULE_OFFSET (entry_index ));
263283
264- ret = lib_manager_load_module (module_id , mod , desc );
284+ ret = lib_manager_load_module (module_id , mod );
265285 if (ret < 0 )
266286 return 0 ;
267287
288+ ret = lib_manager_load_code_modules (module_id , desc );
289+ if (ret < 0 ) {
290+ lib_manager_unload_module (mod );
291+ return ret ;
292+ }
293+
268294 ret = lib_manager_allocate_module_instance (module_id , IPC4_INST_ID (ipc_config -> id ),
269295 base_cfg -> is_pages , mod );
270296 if (ret < 0 ) {
@@ -289,7 +315,11 @@ int lib_manager_free_module(const struct comp_driver *drv,
289315 desc = lib_manager_get_library_module_desc (module_id );
290316 mod = (struct sof_man_module * )((char * )desc + SOF_MAN_MODULE_OFFSET (entry_index ));
291317
292- ret = lib_manager_unload_module (module_id , mod , desc );
318+ ret = lib_manager_unload_module (mod );
319+ if (ret < 0 )
320+ return ret ;
321+
322+ ret = lib_manager_unload_code_modules (module_id , desc );
293323 if (ret < 0 )
294324 return ret ;
295325
0 commit comments