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