Skip to content

Commit bfa5e4d

Browse files
committed
lib_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 705c614 commit bfa5e4d

1 file changed

Lines changed: 64 additions & 101 deletions

File tree

src/library_manager/lib_manager.c

Lines changed: 64 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -51,132 +51,91 @@ static struct ext_library loader_ext_lib;
5151

5252
#define PAGE_SZ CONFIG_MM_DRV_PAGE_SIZE
5353

54-
static int lib_manager_load_data_from_storage(void __sparse_cache *vma, void *s_addr,
55-
uint32_t size, uint32_t flags)
54+
static int lib_manager_load_data_from_storage(void *vma, void *s_addr, uint32_t size,
55+
uint32_t flags)
5656
{
57-
int ret = sys_mm_drv_map_region((__sparse_force void *)vma, POINTER_TO_UINT(NULL),
58-
size, flags);
57+
/* Region must be first mapped as writable in order to initialize its contents. */
58+
int ret = sys_mm_drv_map_region(vma, POINTER_TO_UINT(NULL), size,
59+
flags | SYS_MM_MEM_PERM_RW);
5960
if (ret < 0)
6061
return ret;
6162

62-
ret = memcpy_s((__sparse_force void *)vma, size, s_addr, size);
63+
ret = memcpy_s(vma, size, s_addr, size);
6364
if (ret < 0)
6465
return ret;
6566

6667
dcache_writeback_region(vma, size);
6768

68-
/* TODO: Change attributes for memory to FLAGS */
69+
/* TODO: Change attributes for memory to FLAGS. Implementation of required function in tlb
70+
* driver in progress.
71+
sys_mm_drv_update_region_flags(vma, size, flags); */
6972
return 0;
7073
}
7174

72-
static int lib_manager_load_module(uint32_t module_id, struct sof_man_module *mod,
73-
struct sof_man_fw_desc *desc)
75+
static int lib_manager_load_module(const uint32_t module_id,
76+
const struct sof_man_module *const mod)
7477
{
75-
struct ext_library *ext_lib = ext_lib_get();
76-
uint32_t lib_id = LIB_MANAGER_GET_LIB_ID(module_id);
77-
size_t load_offset = (size_t)((void *)ext_lib->desc[lib_id]);
78-
void __sparse_cache *va_base_text = (void __sparse_cache *)
79-
mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr;
80-
void *src_txt = (void *)(mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset + load_offset);
81-
size_t st_text_size = mod->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length;
82-
void __sparse_cache *va_base_rodata = (void __sparse_cache *)
83-
mod->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr;
84-
void *src_rodata =
85-
(void *)(mod->segment[SOF_MAN_SEGMENT_RODATA].file_offset + load_offset);
86-
size_t st_rodata_size = mod->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length;
87-
int ret;
88-
89-
st_text_size = st_text_size * PAGE_SZ;
90-
st_rodata_size = st_rodata_size * PAGE_SZ;
91-
92-
/* Copy Code */
93-
ret = lib_manager_load_data_from_storage(va_base_text, src_txt, st_text_size,
94-
SYS_MM_MEM_PERM_RW | SYS_MM_MEM_PERM_EXEC);
95-
if (ret < 0)
96-
goto err;
97-
98-
/* Copy RODATA */
99-
ret = lib_manager_load_data_from_storage(va_base_rodata, src_rodata,
100-
st_rodata_size, SYS_MM_MEM_PERM_RW);
101-
if (ret < 0)
102-
goto err;
103-
104-
/* There are modules marked as lib_code. This is code shared between several modules inside
105-
* the library. Load all lib_code modules with first none lib_code module load.
106-
*/
107-
if (!mod->type.lib_code)
108-
ext_lib->mods_exec_load_cnt++;
109-
110-
if (ext_lib->mods_exec_load_cnt == 1) {
111-
struct sof_man_module *module_entry =
112-
(struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(0));
113-
for (size_t idx = 0; idx < desc->header.num_module_entries;
114-
++idx, ++module_entry) {
115-
if (module_entry->type.lib_code) {
116-
ret = lib_manager_load_module(lib_id << LIB_MANAGER_LIB_ID_SHIFT |
117-
idx, mod, desc);
118-
if (ret < 0)
119-
goto err;
120-
}
121-
}
78+
const struct ext_library *const ext_lib = ext_lib_get();
79+
const uint32_t lib_id = LIB_MANAGER_GET_LIB_ID(module_id);
80+
const uintptr_t load_offset = POINTER_TO_UINT(ext_lib->desc[lib_id]);
81+
void *src, *va_base;
82+
size_t size;
83+
uint32_t flags;
84+
int ret, idx;
85+
86+
for (idx = 0; idx < ARRAY_SIZE(mod->segment); ++idx) {
87+
if (!mod->segment[idx].flags.r.load)
88+
continue;
89+
90+
flags = 0;
91+
92+
if (mod->segment[idx].flags.r.code)
93+
flags = SYS_MM_MEM_PERM_EXEC;
94+
else if (!mod->segment[idx].flags.r.readonly)
95+
flags = SYS_MM_MEM_PERM_RW;
96+
97+
src = UINT_TO_POINTER(mod->segment[idx].file_offset + load_offset);
98+
va_base = UINT_TO_POINTER(mod->segment[idx].v_base_addr);
99+
size = mod->segment[idx].flags.r.length * PAGE_SZ;
100+
ret = lib_manager_load_data_from_storage(va_base, src, size, flags);
101+
if (ret < 0)
102+
goto err;
122103
}
123104

124105
return 0;
125106

126107
err:
127-
sys_mm_drv_unmap_region((__sparse_force void *)va_base_text, st_text_size);
128-
sys_mm_drv_unmap_region((__sparse_force void *)va_base_rodata, st_rodata_size);
108+
for (--idx; idx >= 0; --idx) {
109+
if (!mod->segment[idx].flags.r.load)
110+
continue;
111+
112+
va_base = UINT_TO_POINTER(mod->segment[idx].v_base_addr);
113+
size = mod->segment[idx].flags.r.length * PAGE_SZ;
114+
sys_mm_drv_unmap_region(va_base, size);
115+
}
129116

130117
return ret;
131118
}
132119

133-
static int lib_manager_unload_module(uint32_t module_id, struct sof_man_module *mod,
134-
struct sof_man_fw_desc *desc)
120+
static int lib_manager_unload_module(const struct sof_man_module *const mod)
135121
{
136-
struct ext_library *ext_lib = ext_lib_get();
137-
uint32_t lib_id = LIB_MANAGER_GET_LIB_ID(module_id);
138-
void __sparse_cache *va_base_text = (void __sparse_cache *)
139-
mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr;
140-
size_t st_text_size = mod->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length;
141-
void __sparse_cache *va_base_rodata = (void __sparse_cache *)
142-
mod->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr;
143-
size_t st_rodata_size = mod->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length;
122+
void *va_base;
123+
size_t size;
124+
uint32_t idx;
144125
int ret;
145126

146-
st_text_size = st_text_size * PAGE_SZ;
147-
st_rodata_size = st_rodata_size * PAGE_SZ;
127+
for (idx = 0; idx < ARRAY_SIZE(mod->segment); ++idx) {
128+
if (!mod->segment[idx].flags.r.load)
129+
continue;
148130

149-
ret = sys_mm_drv_unmap_region((__sparse_force void *)va_base_text, st_text_size);
150-
if (ret < 0)
151-
return ret;
152-
153-
ret = sys_mm_drv_unmap_region((__sparse_force void *)va_base_rodata, st_rodata_size);
154-
if (ret < 0)
155-
return ret;
156-
157-
/* There are modules marked as lib_code. This is code shared between several modules inside
158-
* the library. Unload all lib_code modules with last none lib_code module unload.
159-
*/
160-
if (mod->type.lib_code)
161-
return ret;
162-
163-
if (!mod->type.lib_code && ext_lib->mods_exec_load_cnt > 0)
164-
ext_lib->mods_exec_load_cnt--;
165-
166-
if (ext_lib->mods_exec_load_cnt == 0) {
167-
struct sof_man_module *module_entry =
168-
(struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(0));
169-
for (size_t idx = 0; idx < desc->header.num_module_entries;
170-
++idx, ++module_entry) {
171-
if (module_entry->type.lib_code) {
172-
ret =
173-
lib_manager_unload_module(lib_id << LIB_MANAGER_LIB_ID_SHIFT |
174-
idx, mod, desc);
175-
}
176-
}
131+
va_base = UINT_TO_POINTER(mod->segment[idx].v_base_addr);
132+
size = mod->segment[idx].flags.r.length * PAGE_SZ;
133+
ret = sys_mm_drv_unmap_region(va_base, size);
134+
if (ret < 0)
135+
return ret;
177136
}
178137

179-
return ret;
138+
return 0;
180139
}
181140

182141
static void __sparse_cache *lib_manager_get_instance_bss_address(uint32_t module_id,
@@ -262,7 +221,7 @@ uint32_t lib_manager_allocate_module(const struct comp_driver *drv,
262221

263222
mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(entry_index));
264223

265-
ret = lib_manager_load_module(module_id, mod, desc);
224+
ret = lib_manager_load_module(module_id, mod);
266225
if (ret < 0)
267226
return 0;
268227

@@ -271,9 +230,13 @@ uint32_t lib_manager_allocate_module(const struct comp_driver *drv,
271230
if (ret < 0) {
272231
tr_err(&lib_manager_tr,
273232
"lib_manager_allocate_module(): module allocation failed: %d", ret);
274-
return 0;
233+
goto err;
275234
}
276235
return mod->entry_point;
236+
237+
err:
238+
lib_manager_unload_module(mod);
239+
return 0;
277240
}
278241

279242
int lib_manager_free_module(const struct comp_driver *drv,
@@ -290,7 +253,7 @@ int lib_manager_free_module(const struct comp_driver *drv,
290253
desc = lib_manager_get_library_module_desc(module_id);
291254
mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(entry_index));
292255

293-
ret = lib_manager_unload_module(module_id, mod, desc);
256+
ret = lib_manager_unload_module(mod);
294257
if (ret < 0)
295258
return ret;
296259

0 commit comments

Comments
 (0)