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 <[email protected]> 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
