You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/01/25 12:22:48 UTC

[incubator-nuttx] 04/06: Implement CONFIG_BUILD_PROTECTED with MMU

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 8a4881c4e59bd53ab73853bdd3d42a8c4b9499e9
Author: Ville Juven <vi...@unikie.com>
AuthorDate: Mon Dec 13 13:35:18 2021 +0200

    Implement CONFIG_BUILD_PROTECTED with MMU
    
    NOTE: THIS ONLY WORKS WHEN KERNEL RUNS IN M-MODE FOR NOW
    
    This frees the PMP for other use, e.g. HART memory separation.
    
    The page tables are statically allocated, 1 per level.
    
    This feature is now behind CONFIG_MPFS_USE_MMU_AS_MPU, because
    only the MPFS target supports this (others are not tested).
    
    If the MMU is used for memory separation within a HART, the PMP must
    still be configured to allow user access to the memory mapped for the
    HART, because PMP *rekoves* access by default. At this point all of
    the user memory as well as the kernel RAM are opened.
    
    A more flexible solution for PMP configuration will follow.
---
 arch/risc-v/src/mpfs/Kconfig                      |   2 -
 arch/risc-v/src/mpfs/mpfs_userspace.c             | 130 +++++++++++++++++++++-
 boards/risc-v/mpfs/icicle/configs/knsh/defconfig  |   1 +
 boards/risc-v/mpfs/icicle/scripts/kernel-space.ld |   7 +-
 4 files changed, 132 insertions(+), 8 deletions(-)

diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig
index a6126fb..8074909 100755
--- a/arch/risc-v/src/mpfs/Kconfig
+++ b/arch/risc-v/src/mpfs/Kconfig
@@ -312,5 +312,3 @@ config MPFS_DMA
 menu "MPFS Others"
 
 endmenu
-
-
diff --git a/arch/risc-v/src/mpfs/mpfs_userspace.c b/arch/risc-v/src/mpfs/mpfs_userspace.c
index 138fcc5..c69cb1c 100755
--- a/arch/risc-v/src/mpfs/mpfs_userspace.c
+++ b/arch/risc-v/src/mpfs/mpfs_userspace.c
@@ -31,6 +31,7 @@
 
 #include "mpfs_userspace.h"
 #include "riscv_internal.h"
+#include "riscv_mmu.h"
 
 #ifdef CONFIG_BUILD_PROTECTED
 
@@ -38,18 +39,79 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+/* Physical and virtual addresses to page tables (vaddr = paddr mapping) */
+
+#define PGT_BASE_PADDR      (uint64_t)&m_l1_pgtable
+#define PGT_L2_PBASE        (uint64_t)&m_l2_pgtable
+#define PGT_L3_PBASE        (uint64_t)&m_l3_pgtable
+#define PGT_L2_VBASE        PGT_L2_PBASE
+#define PGT_L3_VBASE        PGT_L3_PBASE
+
+/* Flags for user FLASH (RX) and user RAM (RW) */
+
+#define MMU_UFLASH_FLAGS    (PTE_R | PTE_X | PTE_U | PTE_G)
+#define MMU_USRAM_FLAGS     (PTE_R | PTE_W | PTE_U | PTE_G)
+
 /****************************************************************************
- * Public Functions
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: configure_mpu
+ *
+ * Description:
+ *   This function configures the MPU for for kernel- / userspace separation.
+ *   It will also grant access to the page table memory for the supervisor.
+ *
+ ****************************************************************************/
+
+static void configure_mpu(void);
+
+/****************************************************************************
+ * Name: configure_mmu
+ *
+ * Description:
+ *   This function configures the MMU and page tables for kernel- / userspace
+ *   separation.
+ *
  ****************************************************************************/
 
+static void configure_mmu(void);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* With a 3 level page table setup the total available memory is 512GB.
+ * However, this is overkill. A single L3 page table can map 2MB of memory,
+ * and for MPFS, this user space is plenty enough. If more memory is needed,
+ * simply increase the size of the L3 page table (n * 512), where each 'n'
+ * provides 2MB of memory.
+ */
+
+/* L1-L3 tables must be in memory always for this to work */
+
+static uint64_t             m_l1_pgtable[512] locate_data(".pgtables");
+static uint64_t             m_l2_pgtable[512] locate_data(".pgtables");
+static uint64_t             m_l3_pgtable[512] locate_data(".pgtables");
+
 /****************************************************************************
  * Public Data
  ****************************************************************************/
 
-extern uintptr_t __uflash_start;
-extern uintptr_t __uflash_size;
-extern uintptr_t __usram_start;
-extern uintptr_t __usram_size;
+extern uintptr_t            __uflash_start;
+extern uintptr_t            __uflash_size;
+extern uintptr_t            __usram_start;
+extern uintptr_t            __usram_size;
+
+/* Needed to allow access to the page tables, which reside in kernel RAM */
+
+extern uintptr_t            __ksram_start;
+extern uintptr_t            __ksram_size;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
 
 /****************************************************************************
  * Name: mpfs_userspace
@@ -96,6 +158,23 @@ void mpfs_userspace(void)
       *dest++ = *src++;
     }
 
+  /* Configure MPU / PMP to grant access to the userspace */
+
+  configure_mpu();
+  configure_mmu();
+}
+
+/****************************************************************************
+ * Name: configure_mpu
+ *
+ * Description:
+ *   This function configures the MPU for for kernel- / userspace separation.
+ *   It will also grant access to the page table memory for the supervisor.
+ *
+ ****************************************************************************/
+
+static void configure_mpu(void)
+{
   /* Configure the PMP to permit user-space access to its ROM and RAM.
    *
    * Note: PMP by default revokes access, thus if different privilege modes
@@ -126,6 +205,47 @@ void mpfs_userspace(void)
   riscv_config_pmp_region(1, PMPCFG_A_NAPOT | PMPCFG_W | PMPCFG_R,
                           (uintptr_t)&__usram_start,
                           (uintptr_t)&__usram_size);
+
+  /* The supervisor must have access to the page tables */
+
+  riscv_config_pmp_region(2, PMPCFG_A_NAPOT | PMPCFG_W | PMPCFG_R,
+                          (uintptr_t)&__ksram_start,
+                          (uintptr_t)&__ksram_size);
+}
+
+/****************************************************************************
+ * Name: configure_mmu
+ *
+ * Description:
+ *   This function configures the MMU and page tables for kernel- / userspace
+ *   separation.
+ *
+ ****************************************************************************/
+
+static void configure_mmu(void)
+{
+  /* Setup MMU for user */
+
+  /* Setup the L3 references for executable memory */
+
+  mmu_ln_map_region(3, PGT_L3_VBASE, (uintptr_t)&__uflash_start,
+                    (uintptr_t)&__uflash_start, (uintptr_t)&__uflash_size,
+                    MMU_UFLASH_FLAGS);
+
+  /* Setup the L3 references for data memory */
+
+  mmu_ln_map_region(3, PGT_L3_VBASE, (uintptr_t)&__usram_start,
+                    (uintptr_t)&__usram_start, (uintptr_t)&__usram_size,
+                    MMU_USRAM_FLAGS);
+
+  /* Setup the L2 and L1 references */
+
+  mmu_ln_setentry(2, PGT_L2_VBASE, PGT_L3_PBASE, PGT_L3_VBASE, PTE_G);
+  mmu_ln_setentry(1, PGT_BASE_PADDR, PGT_L2_PBASE, PGT_L2_VBASE, PTE_G);
+
+  /* Enable MMU */
+
+  mmu_enable(PGT_BASE_PADDR, 0);
 }
 
 #endif /* CONFIG_BUILD_PROTECTED */
diff --git a/boards/risc-v/mpfs/icicle/configs/knsh/defconfig b/boards/risc-v/mpfs/icicle/configs/knsh/defconfig
index cc39b5a..dadf67d 100644
--- a/boards/risc-v/mpfs/icicle/configs/knsh/defconfig
+++ b/boards/risc-v/mpfs/icicle/configs/knsh/defconfig
@@ -16,6 +16,7 @@ CONFIG_ARCH_CHIP_MPFS=y
 CONFIG_ARCH_INTERRUPTSTACK=2048
 CONFIG_ARCH_RISCV=y
 CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_USE_MMU=y
 CONFIG_ARCH_USE_MPU=y
 CONFIG_BOARD_LOOPSPERMSEC=54000
 CONFIG_BUILD_PROTECTED=y
diff --git a/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld b/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld
index f4da505..6b1e486 100755
--- a/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld
+++ b/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld
@@ -86,7 +86,12 @@ SECTIONS
         *(.gnu.linkonce.b.*)
         *(.gnu.linkonce.sb.*)
         *(COMMON)
-        . = ALIGN(4);
+    } > ksram
+
+    /* Page tables here, align to 4K boundary */
+    .pgtables : ALIGN(0x1000) {
+        *(.pgtables)
+         . = ALIGN(4);
         _ebss = ABSOLUTE(.);
     } > ksram