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:
parent
7eb726d57f
commit
8a4881c4e5
@ -312,5 +312,3 @@ config MPFS_DMA
|
||||
menu "MPFS Others"
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user