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 #include +/**************************************************************************** + * 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; }