You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/02/14 15:30:03 UTC

[incubator-nuttx] 03/04: arch: risc-v: Add support for PROTECTED build to k210

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

gnutt pushed a commit to branch pr282
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 382cc29c72700871302486ff36ea62372b84e46f
Author: Masayuki Ishikawa <ma...@gmail.com>
AuthorDate: Fri Feb 14 16:10:50 2020 +0900

    arch: risc-v: Add support for PROTECTED build to k210
---
 arch/risc-v/Kconfig                         |  1 +
 arch/risc-v/src/k210/Make.defs              | 10 +++-
 arch/risc-v/src/k210/k210_allocateheap.c    | 49 ++++++++++++++++
 arch/risc-v/src/k210/k210_irq.c             | 12 +++-
 arch/risc-v/src/k210/k210_irq_dispatch.c    |  4 +-
 arch/risc-v/src/k210/k210_start.c           | 12 ++++
 arch/risc-v/src/k210/k210_userspace.c       | 90 +++++++++++++++++++++++++++++
 arch/risc-v/src/k210/k210_userspace.h       | 49 ++++++++++++++++
 arch/risc-v/src/k210/up_schedulesigaction.c | 12 +++-
 9 files changed, 232 insertions(+), 7 deletions(-)

diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig
index bfc4c66..0e601a1 100644
--- a/arch/risc-v/Kconfig
+++ b/arch/risc-v/Kconfig
@@ -19,6 +19,7 @@ config ARCH_CHIP_FE310
 config ARCH_CHIP_K210
 	bool "Kendryte K210"
 	select ARCH_RV64GC
+	select ARCH_HAVE_MPU
 	select ARCH_HAVE_TESTSET
 	select ARCH_HAVE_MULTICPU
 	select ARCH_GLOBAL_IRQDISABLE
diff --git a/arch/risc-v/src/k210/Make.defs b/arch/risc-v/src/k210/Make.defs
index c8dd3cf..8b3032f 100644
--- a/arch/risc-v/src/k210/Make.defs
+++ b/arch/risc-v/src/k210/Make.defs
@@ -35,7 +35,7 @@
 HEAD_ASRC = k210_vectors.S
 
 # Specify our general Assembly files
-CHIP_ASRCS = k210_head.S up_syscall.S
+CHIP_ASRCS = k210_head.S
 
 CMN_ASRCS  += up_testset.S
 
@@ -66,3 +66,11 @@ ifeq ($(CONFIG_SMP), y)
 CHIP_CSRCS += k210_cpuidlestack.c k210_cpuindex.c
 CHIP_CSRCS += k210_cpupause.c k210_cpustart.c
 endif
+
+ifeq ($(CONFIG_BUILD_PROTECTED),y)
+CMN_CSRCS  += up_task_start.c up_pthread_start.c
+CMN_CSRCS  += up_signal_dispatch.c
+CMN_UASRCS += up_signal_handler.S
+
+CHIP_CSRCS += k210_userspace.c
+endif
diff --git a/arch/risc-v/src/k210/k210_allocateheap.c b/arch/risc-v/src/k210/k210_allocateheap.c
index eca9365..e2f420e 100644
--- a/arch/risc-v/src/k210/k210_allocateheap.c
+++ b/arch/risc-v/src/k210/k210_allocateheap.c
@@ -35,16 +35,65 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/userspace.h>
 
 #include <arch/board/board.h>
 
 #include "k210.h"
 
 /****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define SRAM1_END CONFIG_RAM_END
+
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
+ * Name: up_allocate_kheap
+ *
+ * Description:
+ *   For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and
+ *   user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function allocates
+ *   (and protects) the kernel-space heap.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP)
+void up_allocate_kheap(FAR void **heap_start, size_t *heap_size)
+{
+  /* Get the unaligned size and position of the user-space heap.
+   * This heap begins after the user-space .bss section at an offset
+   * of CONFIG_MM_KERNEL_HEAPSIZE (subject to alignment).
+   */
+
+  uintptr_t ubase = (uintptr_t)USERSPACE->us_bssend;
+  ubase          += CONFIG_MM_KERNEL_HEAPSIZE;
+
+  size_t    usize = SRAM1_END - ubase;
+
+  DEBUGASSERT(ubase < (uintptr_t)SRAM1_END);
+
+  /* TODO: Adjust that size to account for MPU alignment requirements.
+   * NOTE that there is an implicit assumption that the SRAM1_END
+   * is aligned to the MPU requirement.
+   */
+
+  ubase = SRAM1_END - usize;
+
+  /* Return the kernel heap settings (i.e., the part of the heap region
+   * that was not dedicated to the user heap).
+   */
+
+  *heap_start = (FAR void *)USERSPACE->us_bssend;
+  *heap_size  = ubase - (uintptr_t)USERSPACE->us_bssend;
+}
+#endif
+
+/****************************************************************************
  * Name: up_addregion
  ****************************************************************************/
 
diff --git a/arch/risc-v/src/k210/k210_irq.c b/arch/risc-v/src/k210/k210_irq.c
index 6d064c3..7812351 100644
--- a/arch/risc-v/src/k210/k210_irq.c
+++ b/arch/risc-v/src/k210/k210_irq.c
@@ -122,6 +122,10 @@ void up_irqinitialize(void)
 
   irq_attach(K210_IRQ_ECALLM, up_swint, NULL);
 
+#ifdef CONFIG_BUILD_PROTECTED
+  irq_attach(K210_IRQ_ECALLU, up_swint, NULL);
+#endif
+
 #ifdef CONFIG_SMP
   /* Clear MSOFT for CPU0 */
 
@@ -237,8 +241,12 @@ void up_enable_irq(int irq)
 
 uint32_t up_get_newintctx(void)
 {
-  /* Set machine previous privilege mode to machine mode.
-   * Also set machine previous interrupt enable
+  /* Set machine previous privilege mode to machine mode. Reegardless of
+   * how NuttX is configured and of what kind of thread is being started.
+   * That is because all threads, even user-mode threads will start in
+   * kernel trampoline at nxtask_start() or pthread_start().
+   * The thread's privileges will be dropped before transitioning to
+   * user code. Also set machine previous interrupt enable.
    */
 
   return (MSTATUS_MPPM | MSTATUS_MPIE);
diff --git a/arch/risc-v/src/k210/k210_irq_dispatch.c b/arch/risc-v/src/k210/k210_irq_dispatch.c
index 04b16f0..ced4c40 100644
--- a/arch/risc-v/src/k210/k210_irq_dispatch.c
+++ b/arch/risc-v/src/k210/k210_irq_dispatch.c
@@ -70,7 +70,7 @@ void *k210_dispatch_irq(uint64_t vector, uint64_t *regs)
 
   /* Check if fault happened */
 
-  if (vector < 11)
+  if (vector < K210_IRQ_ECALLU)
     {
       up_fault((int)irq, regs);
     }
@@ -88,7 +88,7 @@ void *k210_dispatch_irq(uint64_t vector, uint64_t *regs)
 
   /* NOTE: In case of ecall, we need to adjust mepc in the context */
 
-  if (K210_IRQ_ECALLM == irq)
+  if (K210_IRQ_ECALLM == irq || K210_IRQ_ECALLU == irq)
     {
       *mepc += 4;
     }
diff --git a/arch/risc-v/src/k210/k210_start.c b/arch/risc-v/src/k210/k210_start.c
index f1289f1..194bbd1 100644
--- a/arch/risc-v/src/k210/k210_start.c
+++ b/arch/risc-v/src/k210/k210_start.c
@@ -41,6 +41,7 @@
 
 #include "up_arch.h"
 #include "k210_clockconfig.h"
+#include "k210_userspace.h"
 #include "k210.h"
 #include "chip.h"
 
@@ -137,6 +138,17 @@ void __k210_start(uint32_t mhartid)
 
   showprogress('C');
 
+  /* For the case of the separate user-/kernel-space build, perform whatever
+   * platform specific initialization of the user memory is required.
+   * Normally this just means initializing the user space .data and .bss
+   * segments.
+   */
+
+#ifdef CONFIG_BUILD_PROTECTED
+  k210_userspace();
+  showprogress('D');
+#endif
+
   /* Call nx_start() */
 
   nx_start();
diff --git a/arch/risc-v/src/k210/k210_userspace.c b/arch/risc-v/src/k210/k210_userspace.c
new file mode 100644
index 0000000..00575d2
--- /dev/null
+++ b/arch/risc-v/src/k210/k210_userspace.c
@@ -0,0 +1,90 @@
+/****************************************************************************
+ * arch/risc-v/src/k210/k210_userspace.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <assert.h>
+
+#include <nuttx/userspace.h>
+
+#include "k210_userspace.h"
+
+#ifdef CONFIG_BUILD_PROTECTED
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: k210_userspace
+ *
+ * Description:
+ *   For the case of the separate user-/kernel-space build, perform whatever
+ *   platform specific initialization of the user memory is required.
+ *   Normally this just means initializing the user space .data and .bss
+ *   segments.
+ *
+ ****************************************************************************/
+
+void k210_userspace(void)
+{
+  uint8_t *src;
+  uint8_t *dest;
+  uint8_t *end;
+
+  /* Clear all of user-space .bss */
+
+  DEBUGASSERT(USERSPACE->us_bssstart != 0 && USERSPACE->us_bssend != 0 &&
+              USERSPACE->us_bssstart <= USERSPACE->us_bssend);
+
+  dest = (uint8_t *)USERSPACE->us_bssstart;
+  end  = (uint8_t *)USERSPACE->us_bssend;
+
+  while (dest != end)
+    {
+      *dest++ = 0;
+    }
+
+  /* Initialize all of user-space .data */
+
+  DEBUGASSERT(USERSPACE->us_datasource != 0 &&
+              USERSPACE->us_datastart != 0 && USERSPACE->us_dataend != 0 &&
+              USERSPACE->us_datastart <= USERSPACE->us_dataend);
+
+  src  = (uint8_t *)USERSPACE->us_datasource;
+  dest = (uint8_t *)USERSPACE->us_datastart;
+  end  = (uint8_t *)USERSPACE->us_dataend;
+
+  while (dest != end)
+    {
+      *dest++ = *src++;
+    }
+
+  /* TODO:
+   * Configure the MPU to permit user-space access to its FLASH and RAM
+   */
+}
+
+#endif /* CONFIG_BUILD_PROTECTED */
diff --git a/arch/risc-v/src/k210/k210_userspace.h b/arch/risc-v/src/k210/k210_userspace.h
new file mode 100644
index 0000000..b184ac2
--- /dev/null
+++ b/arch/risc-v/src/k210/k210_userspace.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+ * arch/risc-v/src/k210/k210_userspace.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_K210_K210_USERSPACE_H
+#define __ARCH_RISCV_SRC_K210_K210_USERSPACE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Public Functions Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: k210_userspace
+ *
+ * Description:
+ *   For the case of the separate user-/kernel-space build, perform whatever
+ *   platform specific initialization of the user memory is required.
+ *   Normally this just means initializing the user space .data and .bss
+ *   segments.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_BUILD_PROTECTED
+void k210_userspace(void);
+#endif
+
+#endif /* __ARCH_RISCV_SRC_K210_K210_USERSPACE_H */
diff --git a/arch/risc-v/src/k210/up_schedulesigaction.c b/arch/risc-v/src/k210/up_schedulesigaction.c
index 24f3896..8ab12b6 100644
--- a/arch/risc-v/src/k210/up_schedulesigaction.c
+++ b/arch/risc-v/src/k210/up_schedulesigaction.c
@@ -152,13 +152,17 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
               tcb->xcp.saved_int_ctx    = CURRENT_REGS[REG_INT_CTX];
 
               /* Then set up to vector to the trampoline with interrupts
-               * disabled
+               * disabled.  The kernel-space trampoline must run in
+               * privileged thread mode.
                */
 
               CURRENT_REGS[REG_EPC]     = (uintptr_t)up_sigdeliver;
 
               int_ctx                     = CURRENT_REGS[REG_INT_CTX];
               int_ctx                    &= ~MSTATUS_MIE;
+#ifdef CONFIG_BUILD_PROTECTED
+              int_ctx                    |= MSTATUS_MPPM;
+#endif
 
               CURRENT_REGS[REG_INT_CTX] = int_ctx;
 
@@ -192,7 +196,8 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
           tcb->xcp.saved_int_ctx    = tcb->xcp.regs[REG_INT_CTX];
 
           /* Then set up to vector to the trampoline with interrupts
-           * disabled
+           * disabled.  We must already be in privileged thread mode to be
+           * here.
            */
 
           tcb->xcp.regs[REG_EPC]      = (uintptr_t)up_sigdeliver;
@@ -324,6 +329,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 
                   int_ctx                   = CURRENT_REGS[REG_INT_CTX];
                   int_ctx                   &= ~MSTATUS_MIE;
+#ifdef CONFIG_BUILD_PROTECTED
+                  int_ctx                   |= MSTATUS_MPPM;
+#endif
 
                   CURRENT_REGS[REG_INT_CTX] = int_ctx;