mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 23:03:27 +08:00
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:
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user