binfmt/modlib: support loading each sections to different memory for Relocate object

The feature depends on ARCH_USE_SEPARATED_SECTION
the different memory area has different access speed and cache
capability, so the arch can custom allocate them based on
section names to achieve performance optimization

test:
sim:elf
sim:sotest

Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu1
2023-11-29 22:25:47 +08:00
committed by Xiang Xiao
parent 6e746ed364
commit 1f1d90de1c
18 changed files with 507 additions and 48 deletions
+8
View File
@@ -89,6 +89,14 @@ static void dldump_loadinfo(FAR struct mod_loadinfo_s *loadinfo)
{
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
binfo("Sections %d:\n", i);
# ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->ehdr.e_type == ET_REL)
{
binfo(" sh_alloc: %08jx\n",
(uintmax_t)loadinfo->sectalloc[i]);
}
# endif
binfo(" sh_name: %08x\n", shdr->sh_name);
binfo(" sh_type: %08x\n", shdr->sh_type);
binfo(" sh_flags: %08x\n", shdr->sh_flags);
+22 -2
View File
@@ -964,8 +964,28 @@ int modlib_bind(FAR struct module_s *modp,
* contents to memory and invalidating the I cache).
*/
up_coherent_dcache(loadinfo->textalloc, loadinfo->textsize);
up_coherent_dcache(loadinfo->datastart, loadinfo->datasize);
if (loadinfo->textsize > 0)
{
up_coherent_dcache(loadinfo->textalloc, loadinfo->textsize);
}
if (loadinfo->datasize > 0)
{
up_coherent_dcache(loadinfo->datastart, loadinfo->datasize);
}
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
for (i = 0; loadinfo->ehdr.e_type == ET_REL && i < loadinfo->ehdr.e_shnum;
i++)
{
if (loadinfo->sectalloc[i] == 0)
{
continue;
}
up_coherent_dcache(loadinfo->sectalloc[i], loadinfo->shdr[i].sh_size);
}
#endif
return ret;
}
+124 -25
View File
@@ -56,6 +56,69 @@
* Private Functions
****************************************************************************/
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
static int modlib_section_alloc(FAR struct mod_loadinfo_s *loadinfo,
FAR Elf_Shdr *shdr, uint8_t idx)
{
if (loadinfo->ehdr.e_type != ET_REL)
{
return -EINVAL;
}
if (loadinfo->sectalloc == NULL)
{
/* Allocate memory info for all sections */
loadinfo->sectalloc = lib_zalloc(sizeof(uintptr_t) *
loadinfo->ehdr.e_shnum);
if (loadinfo->sectalloc == NULL)
{
return -ENOMEM;
}
}
modlib_sectname(loadinfo, shdr);
if ((shdr->sh_flags & SHF_WRITE) != 0)
{
# ifdef CONFIG_ARCH_USE_DATA_HEAP
loadinfo->sectalloc[idx] = (uintptr_t)
up_dataheap_memalign(
(FAR const char *)loadinfo->iobuffer,
shdr->sh_addralign,
shdr->sh_size);
# else
loadinfo->sectalloc[idx] = (uintptr_t)lib_memalign(shdr->sh_addralign,
shdr->sh_size);
# endif
if (loadinfo->datastart == 0)
{
loadinfo->datastart = loadinfo->sectalloc[idx];
}
}
else
{
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
loadinfo->sectalloc[idx] = (uintptr_t)
up_textheap_memalign(
(FAR const char *)loadinfo->iobuffer,
shdr->sh_addralign,
shdr->sh_size);
# else
loadinfo->sectalloc[idx] = (uintptr_t)lib_memalign(shdr->sh_addralign,
shdr->sh_size);
# endif
if (loadinfo->textalloc == 0)
{
loadinfo->textalloc = loadinfo->sectalloc[idx];
}
}
return 0;
}
#endif
/****************************************************************************
* Name: modlib_elfsize
*
@@ -70,7 +133,10 @@ static void modlib_elfsize(FAR struct mod_loadinfo_s *loadinfo)
size_t datasize = 0;
int i;
/* Accumulate the size each section into memory that is marked SHF_ALLOC */
/* Accumulate the size each section into memory that is marked SHF_ALLOC
* if CONFIG_ARCH_USE_SEPARATED_SECTION is enabled, allocate
* (and zero) memory for the each section.
*/
if (loadinfo->ehdr.e_phnum > 0)
{
@@ -118,6 +184,13 @@ static void modlib_elfsize(FAR struct mod_loadinfo_s *loadinfo)
#endif
)
{
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
if (modlib_section_alloc(loadinfo, shdr, i) >= 0)
{
continue;
}
#endif
datasize = _ALIGN_UP(datasize, shdr->sh_addralign);
datasize += ELF_ALIGNUP(shdr->sh_size);
if (loadinfo->dataalign < shdr->sh_addralign)
@@ -127,6 +200,13 @@ static void modlib_elfsize(FAR struct mod_loadinfo_s *loadinfo)
}
else
{
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
if (modlib_section_alloc(loadinfo, shdr, i) >= 0)
{
continue;
}
#endif
textsize = _ALIGN_UP(textsize, shdr->sh_addralign);
textsize += ELF_ALIGNUP(shdr->sh_size);
if (loadinfo->textalign < shdr->sh_addralign)
@@ -161,7 +241,6 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s *loadinfo)
{
FAR uint8_t *text = (FAR uint8_t *)loadinfo->textalloc;
FAR uint8_t *data = (FAR uint8_t *)loadinfo->datastart;
FAR uint8_t **pptr;
int ret;
int i;
@@ -204,6 +283,7 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s *loadinfo)
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
FAR uint8_t **pptr = NULL;
/* SHF_ALLOC indicates that the section requires memory during
* execution
@@ -214,25 +294,35 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s *loadinfo)
continue;
}
/* SHF_WRITE indicates that the section address space is write-
* able
*/
if ((shdr->sh_flags & SHF_WRITE) != 0
#ifdef CONFIG_ARCH_HAVE_TEXT_HEAP_WORD_ALIGNED_READ
|| (shdr->sh_flags & SHF_EXECINSTR) == 0
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->ehdr.e_type == ET_REL)
{
pptr = (FAR uint8_t **)&loadinfo->sectalloc[i];
}
#endif
)
{
pptr = &data;
}
else
{
pptr = &text;
}
*pptr = (FAR uint8_t *)_ALIGN_UP((uintptr_t)*pptr,
shdr->sh_addralign);
if (pptr == NULL)
{
/* SHF_WRITE indicates that the section address space is
* writeable
*/
if ((shdr->sh_flags & SHF_WRITE) != 0
#ifdef CONFIG_ARCH_HAVE_TEXT_HEAP_WORD_ALIGNED_READ
|| (shdr->sh_flags & SHF_EXECINSTR) == 0
#endif
)
{
pptr = &data;
}
else
{
pptr = &text;
}
*pptr = (FAR uint8_t *)_ALIGN_UP((uintptr_t)*pptr,
shdr->sh_addralign);
}
/* SHT_NOBITS indicates that there is no data in the file for the
* section.
@@ -267,9 +357,16 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s *loadinfo)
shdr->sh_addr = (uintptr_t)*pptr;
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->ehdr.e_type != ET_REL)
{
*pptr += ELF_ALIGNUP(shdr->sh_size);
}
#else
/* Setup the memory pointer for the next time through the loop */
*pptr += ELF_ALIGNUP(shdr->sh_size);
#endif
}
}
@@ -324,18 +421,19 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo)
if (loadinfo->ehdr.e_type == ET_REL)
{
#ifndef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->textsize > 0)
{
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
loadinfo->textalloc = (uintptr_t)
up_textheap_memalign(loadinfo->textalign,
loadinfo->textsize +
loadinfo->segpad);
#else
# else
loadinfo->textalloc = (uintptr_t)lib_memalign(loadinfo->textalign,
loadinfo->textsize +
loadinfo->segpad);
#endif
# endif
if (!loadinfo->textalloc)
{
berr("ERROR: Failed to allocate memory for the module text\n");
@@ -346,14 +444,14 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo)
if (loadinfo->datasize > 0)
{
#if defined(CONFIG_ARCH_USE_DATA_HEAP)
# ifdef CONFIG_ARCH_USE_DATA_HEAP
loadinfo->datastart = (uintptr_t)
up_dataheap_memalign(loadinfo->dataalign,
loadinfo->datasize);
#else
# else
loadinfo->datastart = (uintptr_t)lib_memalign(loadinfo->dataalign,
loadinfo->datasize);
#endif
# endif
if (!loadinfo->datastart)
{
berr("ERROR: Failed to allocate memory for the module data\n");
@@ -361,6 +459,7 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo)
goto errout_with_buffers;
}
}
#endif
}
else
{
+28
View File
@@ -62,6 +62,33 @@ int modlib_unload(FAR struct mod_loadinfo_s *loadinfo)
if (loadinfo->ehdr.e_type != ET_DYN)
{
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
int i;
for (i = 0; loadinfo->sectalloc[i] != 0 &&
i < loadinfo->ehdr.e_shnum; i++)
{
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
if (up_textheap_heapmember((FAR void *)loadinfo->sectalloc[i]))
{
up_textheap_free((FAR void *)loadinfo->sectalloc[i]);
continue;
}
# endif
# ifdef CONFIG_ARCH_USE_DATA_HEAP
if (up_dataheap_heapmember((FAR void *)loadinfo->sectalloc[i]))
{
up_dataheap_free((FAR void *)loadinfo->sectalloc[i]);
continue;
}
# endif
lib_free((FAR void *)loadinfo->sectalloc[i]);
}
lib_free(loadinfo->sectalloc);
#else
if (loadinfo->textalloc != 0)
{
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
@@ -79,6 +106,7 @@ int modlib_unload(FAR struct mod_loadinfo_s *loadinfo)
lib_free((FAR void *)loadinfo->datastart);
#endif
}
#endif
}
else
{