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:44 UTC

[incubator-nuttx] branch master updated (ad25c43 -> fc3cd30)

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

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


    from ad25c43  net/tcp/sendfile: fast retransmit on duplicate acknowledgments (RFC 5681). (the same as it was implemented in tcp_send_unbuffered.c)
     new 3fa0834  Fix PROTECTED_BUILD build errors for mpfs target
     new 356ae98  Add knsh target for icicle
     new 7eb726d  Add proper user/kernel space linker scripts for knsh target
     new 8a4881c  Implement CONFIG_BUILD_PROTECTED with MMU
     new 81188d9  Extend the RISC-V PMP functionality
     new fc3cd30  Wipe the PMP configuration in MPFS bootloader start routine

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/risc-v/Kconfig                                |  24 +
 arch/risc-v/include/csr.h                          |   1 +
 arch/risc-v/src/common/riscv_internal.h            |  14 +-
 arch/risc-v/src/common/riscv_pmp.c                 | 562 ++++++++++++++++++++-
 arch/risc-v/src/mpfs/Kconfig                       |  12 +
 arch/risc-v/src/mpfs/mpfs_head.S                   |   4 +
 arch/risc-v/src/mpfs/mpfs_userspace.c              | 212 +++++++-
 boards/risc-v/mpfs/common/kernel/mpfs_userspace.c  |   7 -
 .../mpfs/icicle/configs/{nsh => knsh}/defconfig    |  12 +-
 boards/risc-v/mpfs/icicle/scripts/Make.defs        |  16 +-
 .../icicle/scripts/{ld.script => kernel-space.ld}  |  45 +-
 boards/risc-v/mpfs/icicle/scripts/memory.ld        |  11 +-
 boards/risc-v/mpfs/icicle/scripts/user-space.ld    |   2 +-
 13 files changed, 855 insertions(+), 67 deletions(-)
 copy boards/risc-v/mpfs/icicle/configs/{nsh => knsh}/defconfig (87%)
 copy boards/risc-v/mpfs/icicle/scripts/{ld.script => kernel-space.ld} (77%)

[incubator-nuttx] 03/06: Add proper user/kernel space linker scripts for knsh target

Posted by xi...@apache.org.
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 7eb726d57fafcfdc6bb3d773c313c98841e2cf65
Author: Ville Juven <vi...@unikie.com>
AuthorDate: Mon Jan 24 10:00:48 2022 +0200

    Add proper user/kernel space linker scripts for knsh target
    
    The old implementation used the default ld.script for the kernel side
    which did not obey the memory.ld limits whatsoever.
    
    Also, provide the user space addresses from the linker script to get rid
    of the pre-processor macros that define (incorrect) default values for
    the user space composition.
---
 arch/risc-v/src/mpfs/mpfs_userspace.c              | 66 ++++++++++++----------
 boards/risc-v/mpfs/common/kernel/mpfs_userspace.c  |  4 --
 boards/risc-v/mpfs/icicle/configs/knsh/defconfig   | 13 +++--
 boards/risc-v/mpfs/icicle/scripts/Make.defs        | 16 +++++-
 .../scripts/{user-space.ld => kernel-space.ld}     | 63 ++++++++++++---------
 boards/risc-v/mpfs/icicle/scripts/memory.ld        | 11 +---
 boards/risc-v/mpfs/icicle/scripts/user-space.ld    |  2 +-
 7 files changed, 95 insertions(+), 80 deletions(-)

diff --git a/arch/risc-v/src/mpfs/mpfs_userspace.c b/arch/risc-v/src/mpfs/mpfs_userspace.c
index eb3c5cd..138fcc5 100755
--- a/arch/risc-v/src/mpfs/mpfs_userspace.c
+++ b/arch/risc-v/src/mpfs/mpfs_userspace.c
@@ -38,27 +38,20 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
-/* Configuration ************************************************************/
-
-/* TODO: get user space mem layout info from ld script or Configuration ? */
-
-#ifndef CONFIG_NUTTX_USERSPACE_SIZE
-#  define CONFIG_NUTTX_USERSPACE_SIZE        (0x00100000)
-#endif
-
-#ifndef CONFIG_NUTTX_USERSPACE_RAM_START
-#  define CONFIG_NUTTX_USERSPACE_RAM_START   (0x00100000)
-#endif
-
-#ifndef CONFIG_NUTTX_USERSPACE_RAM_SIZE
-#  define CONFIG_NUTTX_USERSPACE_RAM_SIZE    (0x00100000)
-#endif
-
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+extern uintptr_t __uflash_start;
+extern uintptr_t __uflash_size;
+extern uintptr_t __usram_start;
+extern uintptr_t __usram_size;
+
+/****************************************************************************
  * Name: mpfs_userspace
  *
  * Description:
@@ -104,24 +97,35 @@ void mpfs_userspace(void)
     }
 
   /* Configure the PMP to permit user-space access to its ROM and RAM.
-   * Now this is done by simply adding the whole memory area to PMP.
-   * 1. no access for the 1st 4KB
-   * 2. "RX" for the left space until 1MB
-   * 3. "RW" for the user RAM area
-   * TODO: more accurate memory size control.
+   *
+   * Note: PMP by default revokes access, thus if different privilege modes
+   * are in use (mstatus.mprv is set), the the user space _must_ be granted
+   * access here, otherwise an exception will fire when the user space task
+   * is started.
+   *
+   * Note: according to the Polarfire reference manual, address bits [1:0]
+   * are not considered (due to 4 octet alignment), so strictly they don't
+   * have to be cleared here.
+   *
+   * Note: do not trust the stext / etc sections to be correctly aligned
+   * here, they should be but it is simpler and safer to handle the user
+   * region as a whole
+   *
+   * Access is currently granted by simply adding each userspace memory area
+   * to PMP, without further granularity.
+   *
+   * "RX" for the user progmem
+   * "RW" for the user RAM area
+   *
    */
 
-  riscv_config_pmp_region(0, PMPCFG_A_NAPOT,
-                          0,
-                          0x1000);
-
-  riscv_config_pmp_region(1, PMPCFG_A_TOR | PMPCFG_X | PMPCFG_R,
-                          0 + CONFIG_NUTTX_USERSPACE_SIZE,
-                          0);
+  riscv_config_pmp_region(0, PMPCFG_A_NAPOT | PMPCFG_X | PMPCFG_R,
+                          (uintptr_t)&__uflash_start,
+                          (uintptr_t)&__uflash_size);
 
-  riscv_config_pmp_region(2, PMPCFG_A_NAPOT | PMPCFG_W | PMPCFG_R,
-                          CONFIG_NUTTX_USERSPACE_RAM_START,
-                          CONFIG_NUTTX_USERSPACE_RAM_SIZE);
+  riscv_config_pmp_region(1, PMPCFG_A_NAPOT | PMPCFG_W | PMPCFG_R,
+                          (uintptr_t)&__usram_start,
+                          (uintptr_t)&__usram_size);
 }
 
 #endif /* CONFIG_BUILD_PROTECTED */
diff --git a/boards/risc-v/mpfs/common/kernel/mpfs_userspace.c b/boards/risc-v/mpfs/common/kernel/mpfs_userspace.c
index 8860ed5..0186bbd 100755
--- a/boards/risc-v/mpfs/common/kernel/mpfs_userspace.c
+++ b/boards/risc-v/mpfs/common/kernel/mpfs_userspace.c
@@ -43,10 +43,6 @@
 #  error "CONFIG_NUTTX_USERSPACE not defined"
 #endif
 
-#if CONFIG_NUTTX_USERSPACE != 0x00001000
-#  error "CONFIG_NUTTX_USERSPACE must match the value in memory.ld"
-#endif
-
 /****************************************************************************
  * Public Data
  ****************************************************************************/
diff --git a/boards/risc-v/mpfs/icicle/configs/knsh/defconfig b/boards/risc-v/mpfs/icicle/configs/knsh/defconfig
index deaffc9..cc39b5a 100644
--- a/boards/risc-v/mpfs/icicle/configs/knsh/defconfig
+++ b/boards/risc-v/mpfs/icicle/configs/knsh/defconfig
@@ -11,16 +11,14 @@ CONFIG_ARCH="risc-v"
 CONFIG_ARCH_BOARD="icicle"
 CONFIG_ARCH_BOARD_ICICLE_MPFS=y
 CONFIG_ARCH_CHIP="mpfs"
+CONFIG_ARCH_CHIP_MPFS250T_FCVG484=y
 CONFIG_ARCH_CHIP_MPFS=y
 CONFIG_ARCH_INTERRUPTSTACK=2048
 CONFIG_ARCH_RISCV=y
 CONFIG_ARCH_STACKDUMP=y
 CONFIG_ARCH_USE_MPU=y
-CONFIG_BUILD_PROTECTED=y
-CONFIG_SYS_RESERVED=9
-CONFIG_PASS1_BUILDIR="boards/risc-v/mpfs/common/kernel"
-CONFIG_NUTTX_USERSPACE=0x80040000
 CONFIG_BOARD_LOOPSPERMSEC=54000
+CONFIG_BUILD_PROTECTED=y
 CONFIG_BUILTIN=y
 CONFIG_DEBUG_ASSERTIONS=y
 CONFIG_DEBUG_ERROR=y
@@ -54,9 +52,11 @@ CONFIG_NSH_DISABLE_RMDIR=y
 CONFIG_NSH_DISABLE_UMOUNT=y
 CONFIG_NSH_LINELEN=160
 CONFIG_NSH_STRERROR=y
+CONFIG_NUTTX_USERSPACE=0x80040000
+CONFIG_PASS1_BUILDIR="boards/risc-v/mpfs/common/kernel"
 CONFIG_PREALLOC_TIMERS=4
-CONFIG_RAM_SIZE=1048576
-CONFIG_RAM_START=0x80200000
+CONFIG_RAM_SIZE=262144
+CONFIG_RAM_START=0x80080000
 CONFIG_RAW_BINARY=y
 CONFIG_READLINE_CMD_HISTORY=y
 CONFIG_READLINE_TABCOMPLETION=y
@@ -73,6 +73,7 @@ CONFIG_SYSTEM_CLE_CMD_HISTORY=y
 CONFIG_SYSTEM_COLOR_CLE=y
 CONFIG_SYSTEM_NSH=y
 CONFIG_SYSTEM_TIME64=y
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=20
 CONFIG_TESTING_GETPRIME=y
 CONFIG_TESTING_OSTEST=y
diff --git a/boards/risc-v/mpfs/icicle/scripts/Make.defs b/boards/risc-v/mpfs/icicle/scripts/Make.defs
index 26f1cc3..48261fb 100755
--- a/boards/risc-v/mpfs/icicle/scripts/Make.defs
+++ b/boards/risc-v/mpfs/icicle/scripts/Make.defs
@@ -23,20 +23,32 @@ include $(TOPDIR)/tools/Config.mk
 include $(TOPDIR)/tools/mpfs/Config.mk
 include $(TOPDIR)/arch/risc-v/src/common/Toolchain.defs
 
+LDMEMORY =
+ARCHSCRIPT =
+
 ifeq ($(CONFIG_MPFS_BOOTLOADER),y)
   ifeq ($(CONFIG_MPFS_OPENSBI),y)
     LDSCRIPT = ld-envm-opensbi.script
   else
     LDSCRIPT = ld-envm.script
   endif
+else ifeq ($(CONFIG_BUILD_PROTECTED),y)
+  LDMEMORY = memory.ld
+  LDSCRIPT = kernel-space.ld
 else
   LDSCRIPT = ld.script
 endif
 
 ifeq ($(CONFIG_CYGWIN_WINTOOL),y)
-  ARCHSCRIPT = -T "${shell cygpath -w $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT)}"
+  ifneq ($(LDMEMORY),)
+    ARCHSCRIPT += -T "${shell cygpath -w $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDMEMORY)}"
+  endif
+  ARCHSCRIPT += -T "${shell cygpath -w $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT)}"
 else
-  ARCHSCRIPT = -T$(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT)
+  ifneq ($(LDMEMORY),)
+    ARCHSCRIPT += -T$(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDMEMORY)
+  endif
+  ARCHSCRIPT += -T$(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT)
 endif
 
 ifeq ($(CONFIG_DEBUG_SYMBOLS),y)
diff --git a/boards/risc-v/mpfs/icicle/scripts/user-space.ld b/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld
similarity index 71%
copy from boards/risc-v/mpfs/icicle/scripts/user-space.ld
copy to boards/risc-v/mpfs/icicle/scripts/kernel-space.ld
index 0e12049..f4da505 100755
--- a/boards/risc-v/mpfs/icicle/scripts/user-space.ld
+++ b/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/risc-v/mpfs/icicle/scripts/user-space.ld
+ * boards/risc-v/mpfs/icicle/scripts/ld.script
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -21,31 +21,34 @@
 /* NOTE:  This depends on the memory.ld script having been included prior to
  * this script.
  */
-
+ 
 OUTPUT_ARCH("riscv")
 
-SECTIONS
-{
-    /* section info */
+/* Provide these so there is no need for using config files for this */
 
-    __ld_uflash_start = ORIGIN(uflash);
-    __ld_uflash_end = ORIGIN(uflash)+ LENGTH(uflash);
-    __ld_uflash_size = LENGTH(uflash);
+__uflash_start = ORIGIN(uflash);
+__uflash_size = LENGTH(uflash);
+__usram_start = ORIGIN(usram);
+__usram_size = LENGTH(usram);
 
-    __ld_usram_start = ORIGIN(usram);
-    __ld_usram_end = ORIGIN(usram)+ LENGTH(usram);
-    __ld_usram_size = LENGTH(usram);
+/* Provide the kernel boundaries as well */
 
-    .userspace : {
-        *(.userspace)
-    } > uflash
+__kflash_start = ORIGIN(kflash);
+__kflash_size = LENGTH(kflash);
+__ksram_start = ORIGIN(ksram);
+__ksram_size = LENGTH(ksram);
 
+ENTRY(_stext)
+EXTERN(_vectors)
+SECTIONS
+{
     .text : {
         _stext = ABSOLUTE(.);
+        *(.vectors)
         *(.text .text.*)
         *(.fixup)
         *(.gnu.warning)
-        *(.rodata .rodata.*)
+        *(.rodata .rodata.* .srodata .srodata.*)
         *(.gnu.linkonce.t.*)
         *(.glue_7)
         *(.glue_7t)
@@ -53,41 +56,47 @@ SECTIONS
         *(.gcc_except_table)
         *(.gnu.linkonce.r.*)
         _etext = ABSOLUTE(.);
-    } > uflash
+    } > kflash
 
-    .init_section : {
+    .init_section : ALIGN(4) {
         _sinit = ABSOLUTE(.);
         KEEP(*(.init_array .init_array.*))
         _einit = ABSOLUTE(.);
-    } > uflash
-
-    __exidx_start = ABSOLUTE(.);
-
-    __exidx_end = ABSOLUTE(.);
+    } > kflash
 
     _eronly = ABSOLUTE(.);
 
-    .data : {
+    .data : ALIGN(4) {
         _sdata = ABSOLUTE(.);
         *(.data .data.*)
         *(.sdata .sdata.* .sdata2.*)
         *(.gnu.linkonce.d.*)
+        *(.gnu.linkonce.s.*)
         CONSTRUCTORS
         . = ALIGN(4);
         _edata = ABSOLUTE(.);
-    } > usram AT > uflash
+    } > ksram AT > kflash
 
-    .bss : {
+    PROVIDE(__global_pointer$ = _sdata + ((_edata - _sdata) / 2));
+
+    .bss : ALIGN(4) {
         _sbss = ABSOLUTE(.);
         *(.bss .bss.*)
         *(.sbss .sbss.*)
         *(.gnu.linkonce.b.*)
+        *(.gnu.linkonce.sb.*)
         *(COMMON)
         . = ALIGN(4);
         _ebss = ABSOLUTE(.);
-    } > usram
+    } > ksram
+
+    /* Stack top */
+    .stack_top : {
+        . = ALIGN(32);
+        _default_stack_limit = ABSOLUTE(.);
+    } > ksram
 
-    /* Stabs debugging sections */
+    /* Stabs debugging sections. */
 
     .stab 0 : { *(.stab) }
     .stabstr 0 : { *(.stabstr) }
diff --git a/boards/risc-v/mpfs/icicle/scripts/memory.ld b/boards/risc-v/mpfs/icicle/scripts/memory.ld
index 3b38cc4..890ba73 100755
--- a/boards/risc-v/mpfs/icicle/scripts/memory.ld
+++ b/boards/risc-v/mpfs/icicle/scripts/memory.ld
@@ -18,18 +18,11 @@
  *
  ****************************************************************************/
 
-/* Reg   Access        Start addr    End addr     Size
- * QEMU  CPU w/  cache  0x00000000 - 0x003fffff : 4MB
- * QEMU  CPU w/o cache  0x1f000000 - 0x1f01ffff : 128KB
- */
-
 MEMORY
 {
   kflash (rx)  : ORIGIN = 0x80000000, LENGTH = 256K /* w/ cache */
   uflash (rx)  : ORIGIN = 0x80040000, LENGTH = 256K /* w/ cache */
-  xflash (rx)  : ORIGIN = 0x80080000, LENGTH = 256K   /* w/o cache */
 
-  ksram (rwx)  : ORIGIN = 0x800C0000, LENGTH = 256K /* w/ cache */
-  usram (rwx)  : ORIGIN = 0x80100000, LENGTH = 256K /* w/ cache */
-  xsram (rwx)  : ORIGIN = 0x80140000, LENGTH = 256K   /* w/o cache */
+  ksram (rwx)  : ORIGIN = 0x80080000, LENGTH = 256K /* w/ cache */
+  usram (rwx)  : ORIGIN = 0x800C0000, LENGTH = 256K /* w/ cache */
 }
diff --git a/boards/risc-v/mpfs/icicle/scripts/user-space.ld b/boards/risc-v/mpfs/icicle/scripts/user-space.ld
index 0e12049..1b3aa8b 100755
--- a/boards/risc-v/mpfs/icicle/scripts/user-space.ld
+++ b/boards/risc-v/mpfs/icicle/scripts/user-space.ld
@@ -45,7 +45,7 @@ SECTIONS
         *(.text .text.*)
         *(.fixup)
         *(.gnu.warning)
-        *(.rodata .rodata.*)
+        *(.rodata .rodata.* .srodata .srodata.*)
         *(.gnu.linkonce.t.*)
         *(.glue_7)
         *(.glue_7t)

[incubator-nuttx] 02/06: Add knsh target for icicle

Posted by xi...@apache.org.
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 356ae984ac57d7f1209d1582771eb310ec7d9546
Author: Ville Juven <vi...@unikie.com>
AuthorDate: Wed Dec 1 13:19:01 2021 +0200

    Add knsh target for icicle
    
    Template for knsh target (e.g. protected build with user space nsh)
    
    Requires MPU and linker script updates to work
---
 boards/risc-v/mpfs/icicle/configs/knsh/defconfig | 80 ++++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/boards/risc-v/mpfs/icicle/configs/knsh/defconfig b/boards/risc-v/mpfs/icicle/configs/knsh/defconfig
new file mode 100644
index 0000000..deaffc9
--- /dev/null
+++ b/boards/risc-v/mpfs/icicle/configs/knsh/defconfig
@@ -0,0 +1,80 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_DISABLE_OS_API is not set
+# CONFIG_NSH_DISABLE_LOSMART is not set
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="icicle"
+CONFIG_ARCH_BOARD_ICICLE_MPFS=y
+CONFIG_ARCH_CHIP="mpfs"
+CONFIG_ARCH_CHIP_MPFS=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_USE_MPU=y
+CONFIG_BUILD_PROTECTED=y
+CONFIG_SYS_RESERVED=9
+CONFIG_PASS1_BUILDIR="boards/risc-v/mpfs/common/kernel"
+CONFIG_NUTTX_USERSPACE=0x80040000
+CONFIG_BOARD_LOOPSPERMSEC=54000
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_ASSERTIONS=y
+CONFIG_DEBUG_ERROR=y
+CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEBUG_WARN=y
+CONFIG_DEV_ZERO=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_FS_PROCFS=y
+CONFIG_FS_ROMFS=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INIT_STACKSIZE=3072
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_FLOATINGPOINT=y
+CONFIG_LIBC_HOSTNAME="icicle"
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_MEMSET_64BIT=y
+CONFIG_MEMSET_OPTSPEED=y
+CONFIG_MPFS_ENABLE_DPFPU=y
+CONFIG_MPFS_UART1=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_DISABLE_IFUPDOWN=y
+CONFIG_NSH_DISABLE_MKDIR=y
+CONFIG_NSH_DISABLE_RM=y
+CONFIG_NSH_DISABLE_RMDIR=y
+CONFIG_NSH_DISABLE_UMOUNT=y
+CONFIG_NSH_LINELEN=160
+CONFIG_NSH_STRERROR=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_RAM_SIZE=1048576
+CONFIG_RAM_START=0x80200000
+CONFIG_RAW_BINARY=y
+CONFIG_READLINE_CMD_HISTORY=y
+CONFIG_READLINE_TABCOMPLETION=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_LPWORK=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SERIAL_NPOLLWAITERS=2
+CONFIG_STACK_COLORATION=y
+CONFIG_START_MONTH=4
+CONFIG_START_YEAR=2021
+CONFIG_SYSLOG_COLOR_OUTPUT=y
+CONFIG_SYSTEM_CLE_CMD_HISTORY=y
+CONFIG_SYSTEM_COLOR_CLE=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_TIME64=y
+CONFIG_TASK_NAME_SIZE=20
+CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_TESTING_OSTEST_FPUSIZE=264
+CONFIG_UART1_SERIAL_CONSOLE=y

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

Posted by xi...@apache.org.
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
 

[incubator-nuttx] 01/06: Fix PROTECTED_BUILD build errors for mpfs target

Posted by xi...@apache.org.
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 3fa0834e7d2c153247ce0ffbfc91e329404c23fe
Author: Ville Juven <vi...@unikie.com>
AuthorDate: Mon Jan 24 09:56:47 2022 +0200

    Fix PROTECTED_BUILD build errors for mpfs target
    
    Userspace struct definition did not have pthread_startup
    The definition for up_pthread_exit was not compiled ever
---
 boards/risc-v/mpfs/common/kernel/mpfs_userspace.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/boards/risc-v/mpfs/common/kernel/mpfs_userspace.c b/boards/risc-v/mpfs/common/kernel/mpfs_userspace.c
index 6971b10..8860ed5 100755
--- a/boards/risc-v/mpfs/common/kernel/mpfs_userspace.c
+++ b/boards/risc-v/mpfs/common/kernel/mpfs_userspace.c
@@ -99,9 +99,6 @@ const struct userspace_s userspace locate_data(".userspace") =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 

[incubator-nuttx] 05/06: Extend the RISC-V PMP functionality

Posted by xi...@apache.org.
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 81188d9c942d238129c8f58355259e4767322514
Author: Ville Juven <vi...@unikie.com>
AuthorDate: Mon Jan 24 10:17:08 2022 +0200

    Extend the RISC-V PMP functionality
    
    - Add test for mode support, which is architecture dependent
    - Add tests for address alignment and region size
    - Add option to query for access rights
     - The function goes through every PMP entry and tests if an address
       range from [base, base+size] has been configured for desired
       access rights.
     - If several PMP entries match the range and access rights, the
       information is combined
     - End result is either no access, a partial match was found, or a full
       match was found. Details about the partial match are not provided.
    
    The intent for testing access rights and not just blindly applying them
    is a case where they are already set in e.g. a bootloader. In this
    case, nothing should be done, unless the configuration does not match,
    in which case the software must not continue further.
---
 arch/risc-v/Kconfig                     |  24 ++
 arch/risc-v/include/csr.h               |   1 +
 arch/risc-v/src/common/riscv_internal.h |  14 +-
 arch/risc-v/src/common/riscv_pmp.c      | 562 +++++++++++++++++++++++++++++++-
 arch/risc-v/src/mpfs/Kconfig            |  14 +
 arch/risc-v/src/mpfs/mpfs_userspace.c   |  80 +++--
 6 files changed, 666 insertions(+), 29 deletions(-)

diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig
index 72bc2b2..4fac78e 100644
--- a/arch/risc-v/Kconfig
+++ b/arch/risc-v/Kconfig
@@ -101,6 +101,7 @@ config ARCH_CHIP_MPFS
 	select ARCH_HAVE_RESET
 	select ARCH_HAVE_SPI_CS_CONTROL
 	select ARCH_HAVE_PWM_MULTICHAN
+	select PMP_HAS_LIMITED_FEATURES
 	---help---
 		MicroChip Polarfire processor (RISC-V 64bit core with GCVX extensions).
 
@@ -188,6 +189,29 @@ config ARCH_MMU_TYPE_SV39
 	bool
 	default n
 
+# MPU has certain architecture dependent configurations, which are presented
+# here. Default is that the full RISC-V PMP specification is supported.
+
+config PMP_HAS_LIMITED_FEATURES
+	bool
+	default n
+
+config ARCH_MPU_MIN_BLOCK_SIZE
+	int "Minimum MPU (PMP) block size"
+	default 4	if !PMP_HAS_LIMITED_FEATURES
+
+config ARCH_MPU_HAS_TOR
+	bool "PMP supports TOR"
+	default y	if !PMP_HAS_LIMITED_FEATURES
+
+config ARCH_MPU_HAS_NO4
+	bool "PMP supports NO4"
+	default y	if !PMP_HAS_LIMITED_FEATURES
+
+config ARCH_MPU_HAS_NAPOT
+	bool "PMP supports NAPOT"
+	default y	if !PMP_HAS_LIMITED_FEATURES
+
 source "arch/risc-v/src/opensbi/Kconfig"
 source "arch/risc-v/src/common/Kconfig"
 
diff --git a/arch/risc-v/include/csr.h b/arch/risc-v/include/csr.h
index 5d023ed..d1c1c70 100644
--- a/arch/risc-v/include/csr.h
+++ b/arch/risc-v/include/csr.h
@@ -346,6 +346,7 @@
 #define PMPCFG_R        (1 << 0)  /* readable ? */
 #define PMPCFG_W        (1 << 1)  /* writeable ? */
 #define PMPCFG_X        (1 << 2)  /* excutable ? */
+#define PMPCFG_RWX_MASK (7 << 0)  /* access rights mask */
 #define PMPCFG_A_OFF    (0 << 3)  /* null region (disabled) */
 #define PMPCFG_A_TOR    (1 << 3)  /* top of range */
 #define PMPCFG_A_NA4    (2 << 3)  /* naturally aligned four-byte region */
diff --git a/arch/risc-v/src/common/riscv_internal.h b/arch/risc-v/src/common/riscv_internal.h
index 87c4158..596dcae 100644
--- a/arch/risc-v/src/common/riscv_internal.h
+++ b/arch/risc-v/src/common/riscv_internal.h
@@ -91,6 +91,12 @@
 #  endif
 #endif
 
+/* Return values from riscv_check_pmp_access */
+
+#define PMP_ACCESS_OFF      (0)     /* Access for area not set */
+#define PMP_ACCESS_DENIED   (-1)    /* Access set and denied */
+#define PMP_ACCESS_FULL     (1)     /* Access set and allowed */
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
@@ -177,8 +183,12 @@ void riscv_restorefpu(const uintptr_t *regs);
 
 /* RISC-V PMP Config ********************************************************/
 
-void riscv_config_pmp_region(uintptr_t region, uintptr_t attr,
-                             uintptr_t base, uintptr_t size);
+int riscv_config_pmp_region(uintptr_t region, uintptr_t attr,
+                            uintptr_t base, uintptr_t size);
+
+int riscv_check_pmp_access(uintptr_t attr, uintptr_t base, uintptr_t size);
+int riscv_configured_pmp_regions(void);
+int riscv_next_free_pmp_region(void);
 
 /* Power management *********************************************************/
 
diff --git a/arch/risc-v/src/common/riscv_pmp.c b/arch/risc-v/src/common/riscv_pmp.c
index 1fa0daf..b746e7f 100644
--- a/arch/risc-v/src/common/riscv_pmp.c
+++ b/arch/risc-v/src/common/riscv_pmp.c
@@ -22,6 +22,9 @@
  * Included Files
  ****************************************************************************/
 
+#include <stdbool.h>
+
+#include <nuttx/compiler.h>
 #include <nuttx/config.h>
 #include <nuttx/arch.h>
 #include <arch/csr.h>
@@ -32,6 +35,18 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+/* Minimum supported block size */
+
+#if !defined CONFIG_ARCH_MPU_MIN_BLOCK_SIZE
+#define MIN_BLOCK_SIZE          (__riscv_xlen / 8)
+#else
+#define MIN_BLOCK_SIZE          CONFIG_ARCH_MPU_MIN_BLOCK_SIZE
+#endif
+
+/* Address and block size alignment mask */
+
+#define BLOCK_ALIGN_MASK        (MIN_BLOCK_SIZE - 1)
+
 #define PMP_CFG_BITS_CNT        (8)
 #define PMP_CFG_FLAG_MASK       (0xFF)
 
@@ -44,6 +59,361 @@
       reg |= attr << (offset * PMP_CFG_BITS_CNT); \
     } while(0);
 
+#define PMP_READ_REGION_FROM_REG(region, reg) \
+  ({ \
+    uintptr_t tmp = READ_CSR(reg); \
+    tmp >>= ((region % PMP_CFG_CNT_IN_REG) * PMP_CFG_BITS_CNT); \
+    tmp &= PMP_CFG_FLAG_MASK; \
+    tmp; \
+  })
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* Helper structure for handling a PMP entry */
+
+struct pmp_entry_s
+{
+  uintptr_t base;   /* Base address of region */
+  uintptr_t end;    /* End address of region */
+  uintptr_t size;   /* Region size */
+  uint8_t   mode;   /* Address matching mode */
+  uint8_t   rwx;    /* Access rights */
+};
+
+typedef struct pmp_entry_s pmp_entry_t;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pmp_check_addrmatch_type
+ *
+ * Description:
+ *   Test if an address matching type is supported by the architecture.
+ *
+ * Input Parameters:
+ *   type - The type to test.
+ *
+ * Returned Value:
+ *   true if it is, false otherwise.
+ *
+ ****************************************************************************/
+
+static bool pmp_check_addrmatch_type(uintptr_t type)
+{
+  /* Parameter is potentially unused */
+
+  UNUSED(type);
+#ifdef CONFIG_ARCH_MPU_HAS_TOR
+  if (type == PMPCFG_A_TOR)
+    {
+      return true;
+    }
+
+#endif
+#ifdef CONFIG_ARCH_MPU_HAS_NO4
+  if (type == PMPCFG_A_NA4)
+    {
+      return true;
+    }
+
+#endif
+#ifdef CONFIG_ARCH_MPU_HAS_NAPOT
+  if (type == PMPCFG_A_NAPOT)
+    {
+      return true;
+    }
+#endif
+
+  /* None of the supported types match */
+
+  return false;
+}
+
+/****************************************************************************
+ * Name: pmp_check_region_attrs
+ *
+ * Description:
+ *   Test if the base address and size of region meet alignment requirements.
+ *
+ * Input Parameters:
+ *   base - The base address of the region.
+ *   size - The memory length of the region.
+ *
+ * Returned Value:
+ *   true if it is, false otherwise.
+ *
+ ****************************************************************************/
+
+static bool pmp_check_region_attrs(uintptr_t base, uintptr_t size)
+{
+  /* Check that the size is not too small */
+
+  if (size < MIN_BLOCK_SIZE)
+    {
+      return false;
+    }
+
+  /* Check that the base address is aligned properly */
+
+  if ((base & BLOCK_ALIGN_MASK) != 0)
+    {
+      return false;
+    }
+
+  /* Check that the size is aligned properly */
+
+  if ((size & BLOCK_ALIGN_MASK) != 0)
+    {
+      return false;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pmp_read_region_cfg
+ *
+ * Description:
+ *   Read PMP configuration for region
+ *
+ * Input Parameters:
+ *   region - Region number.
+ *
+ * Returned Value:
+ *   Configuration value from pmpcfg+region
+ *
+ ****************************************************************************/
+
+static uintptr_t pmp_read_region_cfg(uintptr_t region)
+{
+# if (__riscv_xlen == 32)
+  switch (region)
+    {
+      case 0 ... 3:
+        return PMP_READ_REGION_FROM_REG(region, pmpcfg0);
+
+      case 4 ... 7:
+        return PMP_READ_REGION_FROM_REG(region, pmpcfg1);
+
+      case 8 ... 11:
+        return PMP_READ_REGION_FROM_REG(region, pmpcfg2);
+
+      case 12 ... 15:
+        return PMP_READ_REGION_FROM_REG(region, pmpcfg3);
+
+      default:
+        break;
+    }
+# elif (__riscv_xlen == 64)
+  switch (region)
+    {
+      case 0 ... 7:
+        return PMP_READ_REGION_FROM_REG(region, pmpcfg0);
+
+      case 8 ... 15:
+        return PMP_READ_REGION_FROM_REG(region, pmpcfg2);
+
+      default:
+        break;
+    }
+#endif
+
+  /* Never executed */
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: pmp_read_addr
+ *
+ * Description:
+ *   Read address for region
+ *
+ * Input Parameters:
+ *   region - Region number.
+ *
+ * Returned Value:
+ *   Address value from pmpcfg+region
+ *
+ ****************************************************************************/
+
+static uintptr_t pmp_read_addr(uintptr_t region)
+{
+  switch (region)
+      {
+        case 0:
+          return READ_CSR(pmpaddr0);
+
+        case 1:
+          return READ_CSR(pmpaddr1);
+
+        case 2:
+          return READ_CSR(pmpaddr2);
+
+        case 3:
+          return READ_CSR(pmpaddr3);
+
+        case 4:
+          return READ_CSR(pmpaddr4);
+
+        case 5:
+          return READ_CSR(pmpaddr5);
+
+        case 6:
+          return READ_CSR(pmpaddr6);
+
+        case 7:
+          return READ_CSR(pmpaddr7);
+
+        case 8:
+          return READ_CSR(pmpaddr8);
+
+        case 9:
+          return READ_CSR(pmpaddr9);
+
+        case 10:
+          return READ_CSR(pmpaddr10);
+
+        case 11:
+          return READ_CSR(pmpaddr11);
+
+        case 12:
+          return READ_CSR(pmpaddr12);
+
+        case 13:
+          return READ_CSR(pmpaddr13);
+
+        case 14:
+          return READ_CSR(pmpaddr14);
+
+        case 15:
+          return READ_CSR(pmpaddr15);
+
+        default:
+          break;
+      }
+
+  /* Never executed */
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: pmp_napot_decode
+ *
+ * Description:
+ *   Decode base and size from NAPOT value
+ *
+ * Input Parameters:
+ *   val  - Value to decode.
+ *   base - Base out.
+ *   size - Size out.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void pmp_napot_decode(uintptr_t val, uintptr_t * base,
+                             uintptr_t * size)
+{
+  uint64_t mask = (uint64_t)(-1) >> 1;
+  uint64_t pot  = __riscv_xlen + 2;
+
+  while (mask)
+    {
+      if ((val & mask) == mask)
+        {
+          break;
+        }
+
+      pot--;
+      mask >>= 1;
+    }
+
+  val &= ~mask;
+  *base = (val << 2);
+  *size = (1 << pot);
+}
+
+/****************************************************************************
+ * Name: pmp_read
+ *
+ * Description:
+ *   Read PMP region into PMP entry
+ *
+ * Input Parameters:
+ *   region - Region number.
+ *   entry  - Entry out
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void pmp_read(uintptr_t region, pmp_entry_t * entry)
+{
+  uintptr_t addr = 0;
+  uintptr_t size = 0;
+  uintptr_t mode = 0;
+  uintptr_t rwx  = 0;
+  uintptr_t cfg  = 0;
+
+  addr = pmp_read_addr(region);
+  cfg  = pmp_read_region_cfg(region);
+  mode = cfg & PMPCFG_A_MASK;
+  rwx  = cfg & PMPCFG_RWX_MASK;
+
+  switch (mode)
+  {
+    case PMPCFG_A_TOR:
+      addr <<= 2;
+
+      /* TOR region, must peek into prior region for size */
+
+      if (region == 0)
+        {
+          size = addr;
+        }
+      else
+        {
+          size = addr - pmp_read_addr(region - 1);
+        }
+
+      break;
+
+    case PMPCFG_A_NA4:
+      addr <<= 2;
+      size = 4;
+      break;
+
+    case PMPCFG_A_NAPOT:
+      pmp_napot_decode(addr, &addr, &size);
+      break;
+
+    default:
+      break;
+  }
+
+  entry->base = addr;
+  entry->end  = addr + size;
+  entry->size = size;
+  entry->rwx  = rwx;
+  entry->mode = mode;
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -63,17 +433,32 @@
  *   and the size must be power-of-two according to the the PMP spec.
  *
  * Returned Value:
- *   None.
+ *   0 on succeess; negated error on failure
  *
  ****************************************************************************/
 
-void riscv_config_pmp_region(uintptr_t region, uintptr_t attr,
-                             uintptr_t base, uintptr_t size)
+int riscv_config_pmp_region(uintptr_t region, uintptr_t attr,
+                            uintptr_t base, uintptr_t size)
 {
-  uintptr_t addr = 0;
-  uintptr_t cfg = 0;
+  uintptr_t addr    = 0;
+  uintptr_t cfg     = 0;
+  uintptr_t type    = (attr & PMPCFG_A_MASK);
+
+  /* Check that the architecture supports address matching type */
+
+  if (pmp_check_addrmatch_type(type) == false)
+    {
+      return -EINVAL;
+    }
+
+  /* Check the region attributes */
+
+  if (pmp_check_region_attrs(base, size))
+    {
+      return -EINVAL;
+    }
 
-  /* TODO: check the base address alignment and size */
+  /* Calculate new base address from type */
 
   addr = base >> 2;
   if (PMPCFG_A_NAPOT == (attr & PMPCFG_A_MASK))
@@ -81,6 +466,8 @@ void riscv_config_pmp_region(uintptr_t region, uintptr_t attr,
       addr |= (size - 1) >> 3;
     }
 
+  /* Set the address value */
+
   switch (region)
     {
       case 0:
@@ -151,6 +538,8 @@ void riscv_config_pmp_region(uintptr_t region, uintptr_t attr,
         break;
     }
 
+  /* Set the configuration register value */
+
 # if (__riscv_xlen == 32)
   switch (region)
     {
@@ -206,4 +595,165 @@ void riscv_config_pmp_region(uintptr_t region, uintptr_t attr,
   /* fence is needed when page-based virtual memory is implemented */
 
   __asm volatile("sfence.vma x0, x0" : : : "memory");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: riscv_check_pmp_access
+ *
+ * Description:
+ *   This function will set the specific PMP region with the desired cfg.
+ *
+ * Input Parameters:
+ *   attr - The region configurations.
+ *   base - The base address of the region.
+ *   size - The memory length of the region.
+ *   For the NAPOT mode, the base address must aligned to the size boundary,
+ *   and the size must be power-of-two according to the the PMP spec.
+ *
+ * Returned Value:
+ *   0 if access rights are not set at all
+ *   < 0 if access rights are set and match match partially
+ *   > 0 if access rights are set and match fully
+ *
+ ****************************************************************************/
+
+int riscv_check_pmp_access(uintptr_t attr, uintptr_t base, uintptr_t size)
+{
+  pmp_entry_t   entry;
+  uintptr_t     end;
+  uintptr_t     orgsize;
+  unsigned int  region;
+
+  /* Go through every single configured region and test the attributes */
+
+  attr    = (attr & PMPCFG_RWX_MASK);
+  end     = base + size;
+  orgsize = size;
+
+  for (region = 0; region < 16 && size > 0; region++)
+    {
+      /* Find matching configuration first */
+
+      pmp_read(region, &entry);
+
+      /* Check if any configuration at all */
+
+      if (entry.mode == PMPCFG_A_OFF)
+        {
+          continue;
+        }
+
+      /* Does this address range match ? Take partial matches into account.
+       *
+       * There are four possibilities:
+       * 1: Full match; region inside mapped area
+       * 2: Partial match; mapped area inside region
+       * 3: Partial match; base inside mapped region, end outside
+       * 4: Partial match; base outside mapped region, end inside
+       */
+
+      if ((base >= entry.base && end  <= entry.end) ||
+          (base <= entry.base && end  >= entry.end) ||
+          (base >= entry.base && base <= entry.end) ||
+          (end  >= entry.base && end  <= entry.end))
+        {
+          /* Found a matching splice, check rights */
+
+          if ((entry.rwx & attr) == attr)
+            {
+              /* Found matching region that allows access */
+
+              size -= min(end, entry.end) - max(base, entry.base);
+            }
+          else
+            {
+              /* Found matching region that does not allow access */
+
+              return PMP_ACCESS_DENIED;
+            }
+        }
+    }
+
+  /* Check if nothing configured at all ? */
+
+  if (size == orgsize)
+    {
+      return PMP_ACCESS_OFF;
+    }
+
+  /* If size is non-positive, the requested range is accessible */
+
+  if (size <= 0)
+    {
+      return PMP_ACCESS_FULL;
+    }
+
+  /* The requested range is either fully or partially inaccessible */
+
+  return PMP_ACCESS_DENIED;
+}
+
+/****************************************************************************
+ * Name: riscv_configured_pmp_regions
+ *
+ * Description:
+ *   Count amount of configured PMP regions, note: is not atomic
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *   Amount of configured PMP regions
+ *
+ ****************************************************************************/
+
+int riscv_configured_pmp_regions(void)
+{
+  pmp_entry_t   entry;
+  unsigned int  region;
+  int           ret = 0;
+
+  for (region = 0; region < 16; region++)
+    {
+      pmp_read(region, &entry);
+
+      if (entry.mode != PMPCFG_A_OFF)
+        {
+          ret++;
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: riscv_next_free_pmp_region
+ *
+ * Description:
+ *   Returns next free PMP region, note: is not atomic
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *   Next free PMP region, or -1 if none found
+ *
+ ****************************************************************************/
+
+int riscv_next_free_pmp_region(void)
+{
+  pmp_entry_t   entry;
+  unsigned int  region;
+
+  for (region = 0; region < 16; region++)
+    {
+      pmp_read(region, &entry);
+
+      if (entry.mode == PMPCFG_A_OFF)
+        {
+          return region;
+        }
+    }
+
+  return -1;
 }
diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig
index 8074909..3c03635 100755
--- a/arch/risc-v/src/mpfs/Kconfig
+++ b/arch/risc-v/src/mpfs/Kconfig
@@ -312,3 +312,17 @@ config MPFS_DMA
 menu "MPFS Others"
 
 endmenu
+
+# Override the default values for MPU / PMP parameters here
+
+config ARCH_MPU_MIN_BLOCK_SIZE
+	default 4096
+
+config ARCH_MPU_HAS_TOR
+	default n
+
+config ARCH_MPU_HAS_NO4
+	default n
+
+config ARCH_MPU_HAS_NAPOT
+	default y
diff --git a/arch/risc-v/src/mpfs/mpfs_userspace.c b/arch/risc-v/src/mpfs/mpfs_userspace.c
index c69cb1c..c375d59 100755
--- a/arch/risc-v/src/mpfs/mpfs_userspace.c
+++ b/arch/risc-v/src/mpfs/mpfs_userspace.c
@@ -39,11 +39,20 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+#define PMP_UFLASH_FLAGS    (PMPCFG_A_NAPOT | PMPCFG_X | PMPCFG_R)
+#define PMP_USRAM_FLAGS     (PMPCFG_A_NAPOT | PMPCFG_W | PMPCFG_R)
+
+#define UFLASH_START        (uintptr_t)&__uflash_start
+#define UFLASH_SIZE         (uintptr_t)&__uflash_size
+#define USRAM_START         (uintptr_t)&__usram_start
+#define USRAM_SIZE          (uintptr_t)&__usram_size
+
 /* Physical and virtual addresses to page tables (vaddr = paddr mapping) */
 
-#define PGT_BASE_PADDR      (uint64_t)&m_l1_pgtable
+#define PGT_L1_PBASE        (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_L1_VBASE        PGT_L1_PBASE
 #define PGT_L2_VBASE        PGT_L2_PBASE
 #define PGT_L3_VBASE        PGT_L3_PBASE
 
@@ -52,6 +61,11 @@
 #define MMU_UFLASH_FLAGS    (PTE_R | PTE_X | PTE_U | PTE_G)
 #define MMU_USRAM_FLAGS     (PTE_R | PTE_W | PTE_U | PTE_G)
 
+/* Kernel RAM needs to be opened (the page tables) */
+
+#define KSRAM_START         (uintptr_t)&__ksram_start
+#define KSRAM_SIZE          (uintptr_t)&__ksram_size
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
@@ -178,9 +192,8 @@ 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
-   * are in use (mstatus.mprv is set), the the user space _must_ be granted
-   * access here, otherwise an exception will fire when the user space task
-   * is started.
+   * are in use, the user space _must_ be granted access here, otherwise
+   * an exception will fire when the user space task is started.
    *
    * Note: according to the Polarfire reference manual, address bits [1:0]
    * are not considered (due to 4 octet alignment), so strictly they don't
@@ -198,19 +211,46 @@ static void configure_mpu(void)
    *
    */
 
-  riscv_config_pmp_region(0, PMPCFG_A_NAPOT | PMPCFG_X | PMPCFG_R,
-                          (uintptr_t)&__uflash_start,
-                          (uintptr_t)&__uflash_size);
+  int ret;
+  int idx;
+
+  /* First, test access to user flash */
+
+  ret = riscv_check_pmp_access(PMP_UFLASH_FLAGS, UFLASH_START, UFLASH_SIZE);
+
+  /* No access or partial access means we must crash */
+
+  DEBUGASSERT(ret != PMP_ACCESS_DENIED);
 
-  riscv_config_pmp_region(1, PMPCFG_A_NAPOT | PMPCFG_W | PMPCFG_R,
-                          (uintptr_t)&__usram_start,
-                          (uintptr_t)&__usram_size);
+  if (ret == PMP_ACCESS_OFF)
+    {
+      idx = riscv_next_free_pmp_region();
+      DEBUGASSERT(idx >= 0);
+      riscv_config_pmp_region(idx, PMP_UFLASH_FLAGS, UFLASH_START,
+                              UFLASH_SIZE);
+    }
+
+  /* Then, test access to user RAM */
+
+  ret = riscv_check_pmp_access(PMP_USRAM_FLAGS, USRAM_START, USRAM_SIZE);
+  DEBUGASSERT(ret != PMP_ACCESS_DENIED);
+  if (ret == PMP_ACCESS_OFF)
+    {
+      idx = riscv_next_free_pmp_region();
+      DEBUGASSERT(idx >= 0);
+      riscv_config_pmp_region(idx, PMP_USRAM_FLAGS, USRAM_START, 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);
+  ret = riscv_check_pmp_access(PMP_USRAM_FLAGS, KSRAM_START, KSRAM_SIZE);
+  DEBUGASSERT(ret != PMP_ACCESS_DENIED);
+  if (ret == PMP_ACCESS_OFF)
+    {
+      idx = riscv_next_free_pmp_region();
+      DEBUGASSERT(idx >= 0);
+      riscv_config_pmp_region(idx, PMP_USRAM_FLAGS, KSRAM_START, KSRAM_SIZE);
+    }
 }
 
 /****************************************************************************
@@ -228,24 +268,22 @@ static void configure_mmu(void)
 
   /* 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);
+  mmu_ln_map_region(3, PGT_L3_VBASE, UFLASH_START, UFLASH_START,
+                    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);
+  mmu_ln_map_region(3, PGT_L3_VBASE, USRAM_START, USRAM_START,
+                    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);
+  mmu_ln_setentry(1, PGT_L1_VBASE, PGT_L2_PBASE, PGT_L2_VBASE, PTE_G);
 
   /* Enable MMU */
 
-  mmu_enable(PGT_BASE_PADDR, 0);
+  mmu_enable(PGT_L1_PBASE, 0);
 }
 
 #endif /* CONFIG_BUILD_PROTECTED */

[incubator-nuttx] 06/06: Wipe the PMP configuration in MPFS bootloader start routine

Posted by xi...@apache.org.
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 fc3cd308d57fb76203575e9fc6d4d2d9e5296571
Author: Ville Juven <vi...@unikie.com>
AuthorDate: Fri Jan 14 11:49:07 2022 +0200

    Wipe the PMP configuration in MPFS bootloader start routine
    
    This way old PMP configurations are removed upon warm reset.
---
 arch/risc-v/src/mpfs/mpfs_head.S | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/risc-v/src/mpfs/mpfs_head.S b/arch/risc-v/src/mpfs/mpfs_head.S
index c3591a6..fe851b7 100755
--- a/arch/risc-v/src/mpfs/mpfs_head.S
+++ b/arch/risc-v/src/mpfs/mpfs_head.S
@@ -192,6 +192,10 @@ __start:
 
 .continue_boot:
 
+    /* Clear PMP */
+
+    csrw pmpcfg0, zero
+    csrw pmpcfg2, zero
 #endif
 
   /* Set stack pointer to the idle thread stack */