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

commit c60257bcc2350cbfe628306ee93d4bab717a8c2b
Author: Justin Hammond <[email protected]>
AuthorDate: Sun Aug 16 18:01:43 2026 +0800

    arch/risc-v/eic7700x: Correct the kernel memory map.
    
    Three faults in how the kernel maps itself.
    
    The page pool covered the RAM disk, which the boot loader appends above
    the kernel, so the BSS clear destroyed it before anything searched for it.
    The pool now covers only pgram, and the RAM disk is mapped on its own
    account.
    
    The kernel data region is mapped with 2 MiB pages rather than 4 KiB ones.
    Everything in it carries the same permissions, so the finer granularity
    bought nothing while costing one L3 slab per 2 MiB from a pool of two.
    
    The linker script and Kconfig describe the page pool separately and both
    descriptions are used, so they now agree.  When they disagree, pages
    outside the smaller of the two get a virtual address of zero and are
    written through, which on this SoC lands on identity mapped low memory
    rather than faulting.
    
    Assisted-by: Claude:claude-opus-5
    Signed-off-by: Justin Hammond <[email protected]>
---
 arch/risc-v/src/eic7700x/eic7700x_mm_init.c | 18 +++++++++++++++++-
 arch/risc-v/src/eic7700x/eic7700x_pgalloc.c | 27 +++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/arch/risc-v/src/eic7700x/eic7700x_mm_init.c 
b/arch/risc-v/src/eic7700x/eic7700x_mm_init.c
index 2b68d6c721c..60ea2ee6f6d 100644
--- a/arch/risc-v/src/eic7700x/eic7700x_mm_init.c
+++ b/arch/risc-v/src/eic7700x/eic7700x_mm_init.c
@@ -237,8 +237,16 @@ void eic7700x_kernel_mappings(void)
   binfo("map kernel text\n");
   map_region(KFLASH_START, KFLASH_START, KFLASH_SIZE, MMU_KTEXT_FLAGS);
 
+  /* The kernel data region is mapped with 2 MiB pages rather than through
+   * map_region()'s 4 KiB ones.  Everything in it, data, bss, the page
+   * tables, the idle stacks and the whole kernel heap, carries the same
+   * permissions, so the finer granularity buys nothing while costing one L3
+   * slab per 2 MiB from a pool of exactly two.
+   */
+
   binfo("map kernel data\n");
-  map_region(KSRAM_START, KSRAM_START, KSRAM_SIZE, MMU_KDATA_FLAGS);
+  mmu_ln_map_region(2, PGT_L2_VBASE, KSRAM_START, KSRAM_START,
+                    KSRAM_SIZE, MMU_KDATA_FLAGS);
 
   /* Connect the L1 and L2 page tables for the kernel text and data */
 
@@ -250,6 +258,14 @@ void eic7700x_kernel_mappings(void)
   binfo("map the page pool\n");
   mmu_ln_map_region(2, PGT_L2_VBASE, PGPOOL_START, PGPOOL_START,
                     PGPOOL_SIZE, MMU_KDATA_FLAGS);
+
+  /* Map the RAM disk.  The page pool no longer covers it, so it needs its
+   * own mapping or the first read of /dev/ram0 faults.
+   */
+
+  binfo("map the RAM disk\n");
+  mmu_ln_map_region(2, PGT_L2_VBASE, RAMDISK_START, RAMDISK_START,
+                    RAMDISK_SIZE, MMU_KDATA_FLAGS);
 }
 
 /****************************************************************************
diff --git a/arch/risc-v/src/eic7700x/eic7700x_pgalloc.c 
b/arch/risc-v/src/eic7700x/eic7700x_pgalloc.c
index 463b39d6ccf..81095a6c4e7 100644
--- a/arch/risc-v/src/eic7700x/eic7700x_pgalloc.c
+++ b/arch/risc-v/src/eic7700x/eic7700x_pgalloc.c
@@ -31,6 +31,21 @@
 #include <nuttx/debug.h>
 #include <arch/board/board_memorymap.h>
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* The granule allocator behind mm_pgalloc() counts its pages in a uint16_t,
+ * and gran_initialize() refuses a pool with more than UINT16_MAX of them,
+ * returning NULL.  mm_pginitialize() then asserts, so an oversized pool is a
+ * board that does not boot rather than a board with less memory than asked
+ * for.  See mm/mm_gran/mm_gran.h and mm/mm_gran/mm_graninit.c.
+ */
+
+#if (CONFIG_ARCH_PGPOOL_SIZE / CONFIG_MM_PGSIZE) > 65535
+#  error "Page pool has more pages than the granule allocator can count"
+#endif
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -50,6 +65,18 @@ void up_allocate_pgheap(void **heap_start, size_t *heap_size)
 {
   DEBUGASSERT(heap_start && heap_size);
 
+  /* The linker script and Kconfig describe this pool separately, and both
+   * descriptions are used: the size below comes from the linker, while
+   * riscv_pgvaddr() decides whether a page is in the pool using the Kconfig
+   * values.  If they disagree, pages outside the smaller of the two get a
+   * virtual address of zero and are then written through, which on this SoC
+   * lands on the identity mapped low memory rather than faulting.  Say so
+   * here instead of finding out that way.
+   */
+
+  DEBUGASSERT(PGPOOL_START == CONFIG_ARCH_PGPOOL_PBASE);
+  DEBUGASSERT(PGPOOL_SIZE  == CONFIG_ARCH_PGPOOL_SIZE);
+
   *heap_start = (void *)PGPOOL_START;
   *heap_size  = (size_t)PGPOOL_SIZE;
 }

Reply via email to