mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 08:36:24 +08:00
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.
This commit is contained in:
@@ -312,5 +312,3 @@ config MPFS_DMA
|
|||||||
menu "MPFS Others"
|
menu "MPFS Others"
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "mpfs_userspace.h"
|
#include "mpfs_userspace.h"
|
||||||
#include "riscv_internal.h"
|
#include "riscv_internal.h"
|
||||||
|
#include "riscv_mmu.h"
|
||||||
|
|
||||||
#ifdef CONFIG_BUILD_PROTECTED
|
#ifdef CONFIG_BUILD_PROTECTED
|
||||||
|
|
||||||
@@ -38,18 +39,79 @@
|
|||||||
* Pre-processor Definitions
|
* 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
|
* Public Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
extern uintptr_t __uflash_start;
|
extern uintptr_t __uflash_start;
|
||||||
extern uintptr_t __uflash_size;
|
extern uintptr_t __uflash_size;
|
||||||
extern uintptr_t __usram_start;
|
extern uintptr_t __usram_start;
|
||||||
extern uintptr_t __usram_size;
|
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
|
* Name: mpfs_userspace
|
||||||
@@ -96,6 +158,23 @@ void mpfs_userspace(void)
|
|||||||
*dest++ = *src++;
|
*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.
|
/* Configure the PMP to permit user-space access to its ROM and RAM.
|
||||||
*
|
*
|
||||||
* Note: PMP by default revokes access, thus if different privilege modes
|
* 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,
|
riscv_config_pmp_region(1, PMPCFG_A_NAPOT | PMPCFG_W | PMPCFG_R,
|
||||||
(uintptr_t)&__usram_start,
|
(uintptr_t)&__usram_start,
|
||||||
(uintptr_t)&__usram_size);
|
(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 */
|
#endif /* CONFIG_BUILD_PROTECTED */
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ CONFIG_ARCH_CHIP_MPFS=y
|
|||||||
CONFIG_ARCH_INTERRUPTSTACK=2048
|
CONFIG_ARCH_INTERRUPTSTACK=2048
|
||||||
CONFIG_ARCH_RISCV=y
|
CONFIG_ARCH_RISCV=y
|
||||||
CONFIG_ARCH_STACKDUMP=y
|
CONFIG_ARCH_STACKDUMP=y
|
||||||
|
CONFIG_ARCH_USE_MMU=y
|
||||||
CONFIG_ARCH_USE_MPU=y
|
CONFIG_ARCH_USE_MPU=y
|
||||||
CONFIG_BOARD_LOOPSPERMSEC=54000
|
CONFIG_BOARD_LOOPSPERMSEC=54000
|
||||||
CONFIG_BUILD_PROTECTED=y
|
CONFIG_BUILD_PROTECTED=y
|
||||||
|
|||||||
@@ -86,7 +86,12 @@ SECTIONS
|
|||||||
*(.gnu.linkonce.b.*)
|
*(.gnu.linkonce.b.*)
|
||||||
*(.gnu.linkonce.sb.*)
|
*(.gnu.linkonce.sb.*)
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
. = ALIGN(4);
|
} > ksram
|
||||||
|
|
||||||
|
/* Page tables here, align to 4K boundary */
|
||||||
|
.pgtables : ALIGN(0x1000) {
|
||||||
|
*(.pgtables)
|
||||||
|
. = ALIGN(4);
|
||||||
_ebss = ABSOLUTE(.);
|
_ebss = ABSOLUTE(.);
|
||||||
} > ksram
|
} > ksram
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user