This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 612fcb5c5a2 fs/mmap: back user anonymous mappings with pages in a
kernel build
612fcb5c5a2 is described below
commit 612fcb5c5a29125dfe48f05693ad65710271be38
Author: Royyan Zahir <[email protected]>
AuthorDate: Wed Sep 30 11:33:31 2026 +0400
fs/mmap: back user anonymous mappings with pages in a kernel build
The kernel ran the process's own heap allocator on metadata the process
controls, and at teardown freed it from whatever address space was
current. User anonymous mappings are now fresh pages mapped into the
process, as the REVISIT asked.
Signed-off-by: Royyan Zahir <[email protected]>
---
fs/mmap/fs_anonmap.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 114 insertions(+), 5 deletions(-)
diff --git a/fs/mmap/fs_anonmap.c b/fs/mmap/fs_anonmap.c
index ccef1c299be..a78f4f42b9b 100644
--- a/fs/mmap/fs_anonmap.c
+++ b/fs/mmap/fs_anonmap.c
@@ -26,7 +26,10 @@
#include <nuttx/config.h>
#include <nuttx/fs/fs.h>
+#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
+#include <nuttx/mm/map.h>
+#include <nuttx/pgalloc.h>
#include <nuttx/sched.h>
#include <assert.h>
#include <nuttx/debug.h>
@@ -115,6 +118,111 @@ static int unmap_anonymous(FAR struct task_group_s *group,
return ret;
}
+#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_ARCH_VMA_MAPPING)
+static int unmap_anonymous_pages(FAR struct task_group_s *group,
+ FAR struct mm_map_entry_s *entry,
+ FAR void *start,
+ size_t length)
+{
+ FAR uintptr_t *pages = entry->priv.p;
+ size_t npages = MM_NPAGES(entry->length);
+ size_t first;
+ size_t i;
+
+ if (!MM_ISALIGNED(start) || start < entry->vaddr)
+ {
+ return -EINVAL;
+ }
+
+ first = ((uintptr_t)start - (uintptr_t)entry->vaddr) >> MM_PGSHIFT;
+ if (first + MM_NPAGES(length) < npages)
+ {
+ ferr("ERROR: Cannot umap without unmapping to the end\n");
+ return -ENOSYS;
+ }
+
+ if (group != NULL)
+ {
+ up_shmdt((uintptr_t)start, npages - first);
+ vm_release_region(get_group_mm(group), start,
+ (npages - first) << MM_PGSHIFT);
+ }
+
+ for (i = first; i < npages; i++)
+ {
+ mm_pgfree(pages[i], 1);
+ }
+
+ if (first > 0)
+ {
+ entry->length = first << MM_PGSHIFT;
+ return OK;
+ }
+
+ kmm_free(pages);
+ return group != NULL ? mm_map_remove(get_group_mm(group), entry) : OK;
+}
+
+static int map_anonymous_pages(FAR struct mm_map_entry_s *entry)
+{
+ FAR struct mm_map_s *mm = get_current_mm();
+ size_t npages = MM_NPAGES(entry->length);
+ FAR uintptr_t *pages;
+ size_t i;
+ int ret = -ENOMEM;
+
+ pages = kmm_zalloc(npages * sizeof(*pages));
+ if (pages == NULL)
+ {
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < npages; i++)
+ {
+ pages[i] = mm_pgalloc(1);
+ if (pages[i] == 0)
+ {
+ goto errout;
+ }
+
+ up_addrenv_page_wipe(pages[i]);
+ }
+
+ entry->length = npages << MM_PGSHIFT;
+ entry->vaddr = vm_alloc_region(mm, NULL, entry->length);
+ if (entry->vaddr == NULL)
+ {
+ goto errout;
+ }
+
+ ret = up_shmat(pages, npages, (uintptr_t)entry->vaddr);
+ if (ret >= 0)
+ {
+ entry->munmap = unmap_anonymous_pages;
+ entry->priv.p = pages;
+ ret = mm_map_add(mm, entry);
+ if (ret >= 0)
+ {
+ return ret;
+ }
+
+ up_shmdt((uintptr_t)entry->vaddr, npages);
+ }
+
+ vm_release_region(mm, entry->vaddr, entry->length);
+ entry->vaddr = NULL;
+
+errout:
+ while (i-- > 0)
+ {
+ mm_pgfree(pages[i], 1);
+ }
+
+ kmm_free(pages);
+ return ret;
+}
+#endif
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -123,11 +231,12 @@ int map_anonymous(FAR struct mm_map_entry_s *entry, bool
kernel)
{
int ret;
- /* REVISIT: Should reside outside of the heap. That is really the
- * only purpose of MAP_ANONYMOUS: To get non-heap memory. In KERNEL
- * build, this could be accomplished using pgalloc(), provided that
- * you had logic in place to assign a virtual address to the mapping.
- */
+#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_ARCH_VMA_MAPPING)
+ if (!kernel)
+ {
+ return map_anonymous_pages(entry);
+ }
+#endif
entry->vaddr = kernel ?
fs_heap_zalloc(entry->length) : kumm_zalloc(entry->length);