Skip to content

Commit 5aa3dbe

Browse files
committed
library_manager: Update module load flow
The previous code have several issues: * Did not support empty data segment. * It assumed that certain types of segments would be at fixed indexes, without taking into account their flags/types. * Incorrect handling of mapping error. If the virtual address cannot be mapped because is already in use, the error handler will unmap this address. * If there is an error loading one of the modules marked as lib_code, previously loaded modules are not unloaded. This commit fixes the above issues. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
1 parent 5c0f8bd commit 5aa3dbe

File tree

1 file changed

+119
-89
lines changed

1 file changed

+119
-89
lines changed

src/library_manager/lib_manager.c

Lines changed: 119 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -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

125163
err:
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

181201
static 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

Comments
 (0)