forked from Imagelibrary/rtems
libdl/rtl-obj.c: synchronize cache after code relocation.
Memory content changes caused by relocation has to be propagated to memory/cache level which is used/snooped during instruction cache fill. Closes #2438
This commit is contained in:
@@ -941,6 +941,8 @@ rtems_rtl_elf_file_load (rtems_rtl_obj_t* obj, int fd)
|
|||||||
if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocator, &ehdr))
|
if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocator, &ehdr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
rtems_rtl_obj_synchronize_cache (obj);
|
||||||
|
|
||||||
rtems_rtl_symbol_obj_erase_local (obj);
|
rtems_rtl_symbol_obj_erase_local (obj);
|
||||||
|
|
||||||
if (!rtems_rtl_elf_load_details (obj))
|
if (!rtems_rtl_elf_load_details (obj))
|
||||||
|
|||||||
@@ -558,6 +558,69 @@ rtems_rtl_obj_relocate (rtems_rtl_obj_t* obj,
|
|||||||
return rtems_rtl_obj_section_handler (mask, obj, fd, handler, data);
|
return rtems_rtl_obj_section_handler (mask, obj, fd, handler, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache synchronization after runtime object load (dlopen)
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t mask;
|
||||||
|
void *start_va;
|
||||||
|
void *end_va;
|
||||||
|
} rtems_rtl_obj_sect_sync_ctx_t;
|
||||||
|
|
||||||
|
static bool
|
||||||
|
rtems_rtl_obj_sect_sync_handler (rtems_chain_node* node, void* data)
|
||||||
|
{
|
||||||
|
rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
|
||||||
|
rtems_rtl_obj_sect_sync_ctx_t* sync_ctx = data;
|
||||||
|
uintptr_t old_end;
|
||||||
|
uintptr_t new_start;
|
||||||
|
|
||||||
|
if ( !(sect->flags & sync_ctx->mask) || !sect->size)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (sync_ctx->end_va == sync_ctx->start_va) {
|
||||||
|
sync_ctx->start_va = sect->base;
|
||||||
|
} else {
|
||||||
|
old_end = (uintptr_t)sync_ctx->end_va & ~(CPU_CACHE_LINE_BYTES - 1);
|
||||||
|
new_start = (uintptr_t)sect->base & ~(CPU_CACHE_LINE_BYTES - 1);
|
||||||
|
if ( (sect->base < sync_ctx->start_va) ||
|
||||||
|
(new_start - old_end > CPU_CACHE_LINE_BYTES) ) {
|
||||||
|
rtems_cache_instruction_sync_after_code_change(sync_ctx->start_va,
|
||||||
|
sync_ctx->end_va - sync_ctx->start_va + 1);
|
||||||
|
sync_ctx->start_va = sect->base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_ctx->end_va = sect->base + sect->size;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rtems_rtl_obj_synchronize_cache (rtems_rtl_obj_t* obj)
|
||||||
|
{
|
||||||
|
rtems_rtl_obj_sect_sync_ctx_t sync_ctx;
|
||||||
|
|
||||||
|
if (rtems_cache_get_instruction_line_size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sync_ctx.mask = RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_CONST |
|
||||||
|
RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_BSS |
|
||||||
|
RTEMS_RTL_OBJ_SECT_EXEC;
|
||||||
|
|
||||||
|
sync_ctx.start_va = 0;
|
||||||
|
sync_ctx.end_va = sync_ctx.start_va;
|
||||||
|
rtems_rtl_chain_iterate (&obj->sections,
|
||||||
|
rtems_rtl_obj_sect_sync_handler,
|
||||||
|
&sync_ctx);
|
||||||
|
|
||||||
|
if (sync_ctx.end_va != sync_ctx.start_va) {
|
||||||
|
rtems_cache_instruction_sync_after_code_change(sync_ctx.start_va,
|
||||||
|
sync_ctx.end_va - sync_ctx.start_va);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
rtems_rtl_obj_load_symbols (rtems_rtl_obj_t* obj,
|
rtems_rtl_obj_load_symbols (rtems_rtl_obj_t* obj,
|
||||||
int fd,
|
int fd,
|
||||||
@@ -618,8 +681,6 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
|
|||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtems_cache_instruction_sync_after_code_change(base, base_offset);
|
|
||||||
|
|
||||||
node = rtems_chain_next (node);
|
node = rtems_chain_next (node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -493,6 +493,13 @@ bool rtems_rtl_obj_relocate (rtems_rtl_obj_t* obj,
|
|||||||
rtems_rtl_obj_sect_handler_t handler,
|
rtems_rtl_obj_sect_handler_t handler,
|
||||||
void* data);
|
void* data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronize caches to make code visible to CPU(s)
|
||||||
|
*
|
||||||
|
* @param obj The object file's descriptor.
|
||||||
|
*/
|
||||||
|
void rtems_rtl_obj_synchronize_cache (rtems_rtl_obj_t* obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Relocate an object file's unresolved reference.
|
* Relocate an object file's unresolved reference.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -970,6 +970,8 @@ rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd)
|
|||||||
if (!rtems_rtl_rap_relocate (&rap, obj))
|
if (!rtems_rtl_rap_relocate (&rap, obj))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
rtems_rtl_obj_synchronize_cache (obj);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user