diff --git a/include/nuttx/lib/modlib.h b/include/nuttx/lib/modlib.h index 3271a94b01..baf969ea9c 100644 --- a/include/nuttx/lib/modlib.h +++ b/include/nuttx/lib/modlib.h @@ -172,7 +172,12 @@ struct module_s mod_initializer_t initializer; /* Module initializer function */ #endif struct mod_info_s modinfo; /* Module information */ +#if defined(CONFIG_ARCH_USE_MODULE_TEXT) + FAR void *textalloc; /* Allocated kernel text memory */ + FAR void *dataalloc; /* Allocated kernel memory */ +#else FAR void *alloc; /* Allocated kernel memory */ +#endif #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE) size_t textsize; /* Size of the kernel .text memory allocation */ size_t datasize; /* Size of the kernel .bss/.data memory allocation */ diff --git a/libs/libc/modlib/Kconfig b/libs/libc/modlib/Kconfig index c03fdbb052..4f9e78d406 100644 --- a/libs/libc/modlib/Kconfig +++ b/libs/libc/modlib/Kconfig @@ -7,6 +7,7 @@ config LIBC_MODLIB bool default n select LIBC_ARCH_ELF + select ARCH_USE_MODULE_TEXT if ARCH_HAVE_MODULE_TEXT menu "Module library configuration" depends on LIBC_MODLIB diff --git a/libs/libc/modlib/modlib_load.c b/libs/libc/modlib/modlib_load.c index 8e163121b6..ecae40d374 100644 --- a/libs/libc/modlib/modlib_load.c +++ b/libs/libc/modlib/modlib_load.c @@ -262,6 +262,30 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo) /* Allocate memory to hold the ELF image */ +#if defined(CONFIG_ARCH_USE_MODULE_TEXT) + if (loadinfo->textsize > 0) + { + loadinfo->textalloc = (uintptr_t) + up_module_text_alloc(loadinfo->textsize); + if (!loadinfo->textalloc) + { + berr("ERROR: Failed to allocate memory for the module text\n"); + ret = -ENOMEM; + goto errout_with_buffers; + } + } + + if (loadinfo->datasize > 0) + { + loadinfo->datastart = (uintptr_t)lib_malloc(loadinfo->datasize); + if (!loadinfo->datastart) + { + berr("ERROR: Failed to allocate memory for the module data\n"); + ret = -ENOMEM; + goto errout_with_buffers; + } + } +#else loadinfo->textalloc = (uintptr_t)lib_malloc(loadinfo->textsize + loadinfo->datasize); if (!loadinfo->textalloc) @@ -272,6 +296,7 @@ int modlib_load(FAR struct mod_loadinfo_s *loadinfo) } loadinfo->datastart = loadinfo->textalloc + loadinfo->textsize; +#endif /* Load ELF section data into memory */ diff --git a/libs/libc/modlib/modlib_unload.c b/libs/libc/modlib/modlib_unload.c index 6288971ae4..8d31901716 100644 --- a/libs/libc/modlib/modlib_unload.c +++ b/libs/libc/modlib/modlib_unload.c @@ -73,10 +73,22 @@ int modlib_unload(struct mod_loadinfo_s *loadinfo) /* Release memory holding the relocated ELF image */ +#if defined(CONFIG_ARCH_USE_MODULE_TEXT) + if (loadinfo->textalloc != 0) + { + up_module_text_free((FAR void *)loadinfo->textalloc); + } + + if (loadinfo->datastart != 0) + { + lib_free((FAR void *)loadinfo->datastart); + } +#else if (loadinfo->textalloc != 0) { lib_free((FAR void *)loadinfo->textalloc); } +#endif /* Clear out all indications of the allocated address environment */ diff --git a/sched/Kconfig b/sched/Kconfig index 5093b083bb..5cebb24777 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -1572,6 +1572,7 @@ config MODULE bool "Enable loadable OS modules" default n select LIBC_MODLIB + select ARCH_USE_MODULE_TEXT if ARCH_HAVE_MODULE_TEXT ---help--- Enable support for loadable OS modules. Default: n diff --git a/sched/init/nx_start.c b/sched/init/nx_start.c index cffd033d24..bf8f7241f4 100644 --- a/sched/init/nx_start.c +++ b/sched/init/nx_start.c @@ -599,6 +599,10 @@ void nx_start(void) kmm_initialize(heap_start, heap_size); #endif +#ifdef CONFIG_ARCH_USE_MODULE_TEXT + up_module_text_init(); +#endif + #ifdef CONFIG_MM_PGALLOC /* If there is a page allocator in the configuration, then get the page * heap information from the platform-specific code and configure the diff --git a/sched/module/mod_insmod.c b/sched/module/mod_insmod.c index 3d0d266fc8..26bdb45b19 100644 --- a/sched/module/mod_insmod.c +++ b/sched/module/mod_insmod.c @@ -237,7 +237,12 @@ FAR void *insmod(FAR const char *filename, FAR const char *modname) /* Save the load information */ +#if defined(CONFIG_ARCH_USE_MODULE_TEXT) + modp->textalloc = (FAR void *)loadinfo.textalloc; + modp->dataalloc = (FAR void *)loadinfo.datastart; +#else modp->alloc = (FAR void *)loadinfo.textalloc; +#endif #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE) modp->textsize = loadinfo.textsize; modp->datasize = loadinfo.datasize; diff --git a/sched/module/mod_procfs.c b/sched/module/mod_procfs.c index b740dee0b7..8aece06a41 100644 --- a/sched/module/mod_procfs.c +++ b/sched/module/mod_procfs.c @@ -152,9 +152,18 @@ static int modprocfs_callback(FAR struct module_s *modp, FAR void *arg) "%s,%p,%p,%p,%u,%p,%lu,%p,%lu\n", modp->modname, modp->initializer, modp->modinfo.uninitializer, modp->modinfo.arg, - modp->modinfo.nexports, modp->alloc, + modp->modinfo.nexports, +#if defined(CONFIG_ARCH_USE_MODULE_TEXT) + modp->textalloc, +#else + modp->alloc, +#endif (unsigned long)modp->textsize, +#if defined(CONFIG_ARCH_USE_MODULE_TEXT) + (FAR uint8_t *)modp->dataalloc, +#else (FAR uint8_t *)modp->alloc + modp->textsize, +#endif (unsigned long)modp->datasize); copysize = procfs_memcpy(priv->line, linesize, priv->buffer, priv->remaining, &priv->offset); diff --git a/sched/module/mod_rmmod.c b/sched/module/mod_rmmod.c index 35d34a4d81..cdb2112b1f 100644 --- a/sched/module/mod_rmmod.c +++ b/sched/module/mod_rmmod.c @@ -128,15 +128,25 @@ int rmmod(FAR void *handle) /* Release resources held by the module */ +#if defined(CONFIG_ARCH_USE_MODULE_TEXT) + if (modp->textalloc != NULL || modp->dataalloc != NULL) +#else if (modp->alloc != NULL) +#endif { - /* Free the module memory */ + /* Free the module memory + * and nullify so that the memory cannot be freed again + */ +#if defined(CONFIG_ARCH_USE_MODULE_TEXT) + up_module_text_free((FAR void *)modp->textalloc); + kmm_free((FAR void *)modp->dataalloc); + modp->textalloc = NULL; + modp->dataalloc = NULL; +#else kmm_free((FAR void *)modp->alloc); - - /* Nullify so that the memory cannot be freed again */ - modp->alloc = NULL; +#endif #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE) modp->textsize = 0; modp->datasize = 0;