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 2023/06/06 17:48:22 UTC

[nuttx] 01/03: RISC-V: Implement simple and native NuttX SBI

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/nuttx.git

commit ae64f28344266cbdcddb8830ad6e2543013a8ad5
Author: Ville Juven <vi...@unikie.com>
AuthorDate: Mon Apr 11 13:46:41 2022 +0300

    RISC-V: Implement simple and native NuttX SBI
    
    This is a minimalistic SBI implementation for NuttX.
    
    Provides a single service for now:
    - Access to machine timer
    
    Provides a start trampoline to start NuttX in S-mode:
    - Exceptions / faults are delegated to S-mode.
    - External interrupts are delegated to S-mode.
    
    Machine mode timer is used as follows:
    - The timer compare match register reload happens in M-mode, via
      call gate "riscv_sbi_set_timer"
    - The compare match event is dispatched to S-mode ISR, which will
      notify the kernel to advance time
    - Clearing the STIP interrupt does not work from S-mode,
      so the call gate does this from M-mode
    
    The only supported (tested) target for now is MPFS.
---
 arch/risc-v/Kconfig                      |   4 +
 arch/risc-v/src/Makefile                 |   2 +
 arch/risc-v/src/nuttsbi/Kconfig          |  30 ++++++
 arch/risc-v/src/nuttsbi/Make.defs        |  33 +++++++
 arch/risc-v/src/nuttsbi/sbi_head.S       | 131 ++++++++++++++++++++++++++
 arch/risc-v/src/nuttsbi/sbi_internal.h   | 144 +++++++++++++++++++++++++++++
 arch/risc-v/src/nuttsbi/sbi_mcall.c      |  81 ++++++++++++++++
 arch/risc-v/src/nuttsbi/sbi_mcall.h      | 134 +++++++++++++++++++++++++++
 arch/risc-v/src/nuttsbi/sbi_mexception.c |  37 ++++++++
 arch/risc-v/src/nuttsbi/sbi_mscratch.c   |  85 +++++++++++++++++
 arch/risc-v/src/nuttsbi/sbi_mtimer.c     | 100 ++++++++++++++++++++
 arch/risc-v/src/nuttsbi/sbi_mtrap.S      | 154 +++++++++++++++++++++++++++++++
 arch/risc-v/src/nuttsbi/sbi_start.c      | 125 +++++++++++++++++++++++++
 arch/risc-v/src/nuttsbi/sbi_vectors.S    |  39 ++++++++
 14 files changed, 1099 insertions(+)

diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig
index 422c61f88a..c45d64505c 100644
--- a/arch/risc-v/Kconfig
+++ b/arch/risc-v/Kconfig
@@ -282,6 +282,9 @@ config RISCV_MISALIGNED_HANDLER
 # Kernel mode requires this as M-mode uses flat addressing and the kernel
 # memory must be mapped in order to share memory between the kernel and
 # different user tasks which reside in virtual memory.
+#
+# Note that S-mode requires a companion software (SBI)
+#
 
 config ARCH_USE_S_MODE
 	bool "Run the NuttX kernel in S-mode"
@@ -378,6 +381,7 @@ endchoice
 endif
 
 source "arch/risc-v/src/opensbi/Kconfig"
+source "arch/risc-v/src/nuttsbi/Kconfig"
 
 if ARCH_CHIP_FE310
 source "arch/risc-v/src/fe310/Kconfig"
diff --git a/arch/risc-v/src/Makefile b/arch/risc-v/src/Makefile
index c61f29de56..4118775cf7 100644
--- a/arch/risc-v/src/Makefile
+++ b/arch/risc-v/src/Makefile
@@ -22,6 +22,8 @@ include $(TOPDIR)/Make.defs
 include chip/Make.defs
 ifeq ($(CONFIG_OPENSBI),y)
 include opensbi/Make.defs
+else ifeq ($(CONFIG_NUTTSBI),y)
+include nuttsbi/Make.defs
 endif
 
 # Kernel runs in supervisor mode or machine mode ?
diff --git a/arch/risc-v/src/nuttsbi/Kconfig b/arch/risc-v/src/nuttsbi/Kconfig
new file mode 100644
index 0000000000..004ef2745a
--- /dev/null
+++ b/arch/risc-v/src/nuttsbi/Kconfig
@@ -0,0 +1,30 @@
+
+# S-mode requires a Supervisor Binary Interface (SBI) in order to access
+# M-mode ISA. A minimalistic SBI is provided here natively.
+
+config NUTTSBI
+	bool "Use NuttX native SBI"
+	default n
+	depends on ARCH_RISCV && ARCH_USE_S_MODE
+	---help---
+		Use NuttX minimalistic SBI
+
+if NUTTSBI
+
+config NUTTSBI_HART_CNT
+	int "Amount of harts in SoC"
+	default 1
+
+config NUTTSBI_MTIME_BASE
+	hex "MTIME base address"
+	default 0
+	---help---
+		Sets the address of mtime memory mapped register
+
+config NUTTSBI_MTIMECMP_BASE
+	hex "MTIMECMP base address"
+	default 0
+	---help---
+		Sets the address of mtimecmp memory mapped register
+
+endif
diff --git a/arch/risc-v/src/nuttsbi/Make.defs b/arch/risc-v/src/nuttsbi/Make.defs
new file mode 100644
index 0000000000..2052c8e108
--- /dev/null
+++ b/arch/risc-v/src/nuttsbi/Make.defs
@@ -0,0 +1,33 @@
+############################################################################
+# arch/risc-v/src/nuttsbi/Make.defs
+#
+# 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.
+#
+############################################################################
+
+# If NuttX SBI is needed
+
+ifeq ($(CONFIG_NUTTSBI),y)
+
+SBI_ASRCS += sbi_mtrap.S sbi_vectors.S sbi_head.S
+SBI_CSRCS += sbi_mscratch.c sbi_mcall.c sbi_start.c
+SBI_CSRCS += sbi_mexception.c sbi_mtimer.c
+
+INCLUDES  += ${shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)nuttsbi}
+
+SBI_DIR   := nuttsbi
+
+endif
diff --git a/arch/risc-v/src/nuttsbi/sbi_head.S b/arch/risc-v/src/nuttsbi/sbi_head.S
new file mode 100644
index 0000000000..745565d29a
--- /dev/null
+++ b/arch/risc-v/src/nuttsbi/sbi_head.S
@@ -0,0 +1,131 @@
+/****************************************************************************
+ * arch/risc-v/src/nuttsbi/sbi_head.S
+ *
+ * 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 <nuttx/irq.h>
+
+#include "sbi_internal.h"
+
+/****************************************************************************
+ * Public Symbols
+ ****************************************************************************/
+
+  /* Imported symbols */
+
+  .extern __mtrap_vec
+
+  .section .text
+  .global __start
+
+__start:
+
+  /* Disable all interrupts (i.e. timer, external) in mie */
+
+  csrw mie, zero
+  csrw mip, zero
+
+  /* Initialize the Machine Trap Vector */
+
+  la   t0, __mtrap_vec
+  csrw mtvec, t0
+
+  /* Make sure that mtvec is updated before continuing */
+
+1:
+  csrr t1, mtvec
+  bne  t0, t1, 1b
+
+  /* mscratch must be init to zero- we are not using scratch memory */
+
+  csrw mscratch, zero
+  csrw mcause, zero
+  csrw mepc, zero
+  li   x1,  0
+  li   x2,  0
+  li   x3,  0
+  li   x4,  0
+  li   x5,  0
+  li   x6,  0
+  li   x7,  0
+  li   x8,  0
+  li   x9,  0
+  li   x10, 0
+  li   x11, 0
+  li   x12, 0
+  li   x13, 0
+  li   x14, 0
+  li   x15, 0
+  li   x16, 0
+  li   x17, 0
+  li   x18, 0
+  li   x19, 0
+  li   x20, 0
+  li   x21, 0
+  li   x22, 0
+  li   x23, 0
+  li   x24, 0
+  li   x25, 0
+  li   x26, 0
+  li   x27, 0
+  li   x28, 0
+  li   x29, 0
+  li   x30, 0
+  li   x31, 0
+
+  /* Delegation registers must be explicitly reset */
+
+  csrw mideleg, 0
+  csrw medeleg, 0
+
+  /* Remove MMU mappings (if any) */
+
+  csrw satp, zero
+  fence
+
+  /* Flush TLB (does not make a difference really) */
+
+  sfence.vma x0, x0
+
+  /* Clear PMP */
+
+  csrw pmpcfg0, 0
+  csrw pmpcfg2, 0
+
+  /* Set up a temporary stack */
+
+#if MMODE_HART_CNT > 1
+  /* REVISIT: This requires that hartID is sequential, and starts from 0 */
+
+  csrr a0, mhartid
+  li   s0, TEMP_STACK_SIZE
+  mul  s0, a0, s0
+  la   s1, TEMP_STACK_BASE
+  sub  sp, s1, s0
+#else
+  la   sp, TEMP_STACK_BASE
+#endif
+
+  /* Jump to start */
+
+  j sbi_start
diff --git a/arch/risc-v/src/nuttsbi/sbi_internal.h b/arch/risc-v/src/nuttsbi/sbi_internal.h
new file mode 100644
index 0000000000..79e4690135
--- /dev/null
+++ b/arch/risc-v/src/nuttsbi/sbi_internal.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+ * arch/risc-v/src/nuttsbi/sbi_internal.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_RISC_V_SRC_NUTTSBI_SBI_INTERNAL_H
+#define __ARCH_RISC_V_SRC_NUTTSBI_SBI_INTERNAL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifndef __ASSEMBLY__
+#  include <stdint.h>
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Amount of harts, based on chip capability, not utilization */
+
+#define MMODE_HART_CNT      (CONFIG_NUTTSBI_HART_CNT)
+
+/* The machine mode interrupts should not be too complex */
+
+#define MMODE_IRQSTACK      (1024)
+
+/* Timer interrupt is the only one we handle, others are discarded */
+
+#define MTIMER_IRQ          (7)
+
+/* Timer memory mapped registers */
+
+#define MTIMER_TIME_BASE    (CONFIG_NUTTSBI_MTIME_BASE)
+#define MTIMER_CMP_BASE     (CONFIG_NUTTSBI_MTIMECMP_BASE)
+
+/* For stack alignment */
+
+#define STACK_ALIGNMENT     16
+#define STACK_ALIGN_MASK    (STACK_ALIGNMENT - 1)
+#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK)
+#define STACK_ALIGN_UP(a)   (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK)
+
+/* Temporary stack placement and size */
+
+#define TEMP_STACK_BASE     (_ebss)
+#define TEMP_STACK          (1024)
+#define TEMP_STACK_SIZE     (STACK_ALIGN_DOWN(TEMP_STACK))
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/****************************************************************************
+ * Name: riscv_mscratch_assign
+ *
+ * Description:
+ *   Assign the mscratch register for hartid. Sets the M-mode interrupt stack
+ *   which is a must because M-mode deals with flat addressing and cannot
+ *   share the user stack for exception handling.
+ *
+ * Input Parameters:
+ *   hartid - Hartid.
+ *
+ ****************************************************************************/
+
+void sbi_mscratch_assign(uintptr_t hartid);
+
+/****************************************************************************
+ * Name: sbi_start
+ *
+ * Description:
+ *   Sets up entry to board specific start routine in S-mode. Mandatory
+ *   trampoline function when the native SBI is used. Called from M-mode.
+ *
+ ****************************************************************************/
+
+void sbi_start(void) noreturn_function;
+
+/****************************************************************************
+ * Name: sbi_init_mtimer
+ *
+ * Description:
+ *   Set up access to mtimer for SBI. This is an extremely light weight way
+ *   of provisioning the mtimer memory mapped registers to SBI.
+ *
+ * Input Parameters:
+ *   mtime    - Pointer to machine time memory mapped register.
+ *   mtimecmp - Pointer to the base of the mtimecmp memory mapped registers,
+ *              implementation assumes there is 1 per hart and that they
+ *              follow each other.
+ *
+ ****************************************************************************/
+
+void sbi_init_mtimer(uintptr_t mtime, uintptr_t mtimecmp);
+
+/****************************************************************************
+ * Name: sbi_get_mtime
+ *
+ * Description:
+ *   Read value of mtime
+ *
+ * Returned value:
+ *   Full 64-bit system time
+ *
+ ****************************************************************************/
+
+uint64_t sbi_get_mtime(void);
+
+/****************************************************************************
+ * Name: sbi_set_mtimecmp
+ *
+ * Description:
+ *   Set value of mtimecmp.
+ *
+ * Input Parameters:
+ *   value - Value for mtimecmp.
+ *
+ ****************************************************************************/
+
+void sbi_set_mtimecmp(uint64_t value);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_RISC_V_SRC_NUTTSBI_SBI_INTERNAL_H */
diff --git a/arch/risc-v/src/nuttsbi/sbi_mcall.c b/arch/risc-v/src/nuttsbi/sbi_mcall.c
new file mode 100644
index 0000000000..1f8596b3f5
--- /dev/null
+++ b/arch/risc-v/src/nuttsbi/sbi_mcall.c
@@ -0,0 +1,81 @@
+/****************************************************************************
+ * arch/risc-v/src/nuttsbi/sbi_mcall.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 <nuttx/irq.h>
+
+#include <stdint.h>
+
+#include "riscv_internal.h"
+
+#include "sbi_mcall.h"
+#include "sbi_internal.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sbi_mcall_handle
+ *
+ * Description:
+ *   Handle environment call to machine mode
+ *
+ * Input Parameters:
+ *   regs - User context
+ *
+ ****************************************************************************/
+
+void sbi_mcall_handle(uintptr_t *regs)
+{
+  /* Check the environment call number */
+
+  switch (regs[REG_A0])
+  {
+    case MCALL_GET_TIMER:
+#ifdef CONFIG_ARCH_RV64
+      regs[REG_A0]    = sbi_get_mtime();
+#else
+      {
+        uint64_t time = sbi_get_mtime();
+        regs[REG_A0]  = (uint32_t)time;
+        regs[REG_A1]  = (uint32_t)(time >> 32);
+      }
+#endif
+      break;
+
+    case MCALL_SET_TIMER:
+#ifdef CONFIG_ARCH_RV64
+      sbi_set_mtimecmp(regs[REG_A1]);
+#else
+      sbi_set_mtimecmp(regs[REG_A1] + ((uint64_t)regs[REG_A2] << 32));
+#endif
+      CLEAR_CSR(mip, MIP_STIP);
+      SET_CSR(mie, MIE_MTIE);
+      break;
+
+    default:
+      break;
+  }
+}
diff --git a/arch/risc-v/src/nuttsbi/sbi_mcall.h b/arch/risc-v/src/nuttsbi/sbi_mcall.h
new file mode 100644
index 0000000000..95154a2eac
--- /dev/null
+++ b/arch/risc-v/src/nuttsbi/sbi_mcall.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+ * arch/risc-v/src/nuttsbi/sbi_mcall.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_RISC_V_SRC_NUTTSBI_SBI_MCALL_H
+#define __ARCH_RISC_V_SRC_NUTTSBI_SBI_MCALL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+enum mcall_num_e
+{
+  MCALL_INVALID,
+  MCALL_GET_TIMER,
+  MCALL_SET_TIMER,
+  MCALL_LAST
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mcall0
+ *
+ * Description:
+ *   Generate an environment call to machine mode
+ *
+ * Input Parameters:
+ *   nbr - Environment call number
+ *
+ ****************************************************************************/
+
+static inline uintptr_t mcall0(unsigned int nbr)
+{
+  register long r0 asm("a0") = (long)(nbr);
+
+  asm volatile
+    (
+     "ecall"
+     :: "r"(r0)
+     : "memory"
+     );
+
+  asm volatile("nop" : "=r"(r0));
+
+  return r0;
+}
+
+/****************************************************************************
+ * Name: mcall1
+ *
+ * Description:
+ *   Generate an environment call to machine mode
+ *
+ * Input Parameters:
+ *   nbr - Environment call number
+ *   parm1 - Argument for ecall
+ *
+ ****************************************************************************/
+
+static inline uintptr_t mcall1(unsigned int nbr, uintptr_t parm1)
+{
+  register long r0 asm("a0") = (long)(nbr);
+  register long r1 asm("a1") = (long)(parm1);
+
+  asm volatile
+    (
+     "ecall"
+     :: "r"(r0), "r"(r1)
+     : "memory"
+     );
+
+  asm volatile("nop" : "=r"(r0));
+
+  return r0;
+}
+
+/****************************************************************************
+ * Name: sbi_mcall_get_time
+ *
+ * Description:
+ *   Read the current system time (mtime)
+ *
+ * Returned Value:
+ *   time - Value of mtime
+ *
+ ****************************************************************************/
+
+#define sbi_mcall_get_time() \
+  mcall0(MCALL_GET_TIMER)
+
+/****************************************************************************
+ * Name: sbi_mcall_set_timer
+ *
+ * Description:
+ *   Set new compare match value for timer. Time is in absolute time, so
+ *   user must either obtain system time and calculate the offset, or keep
+ *   the old compare match value in memory
+ *
+ * Input Parameters:
+ *   stime_value - Absolute time for next compare match event
+ *
+ ****************************************************************************/
+
+#define sbi_mcall_set_timer(stime_value) \
+  (void)mcall1(MCALL_SET_TIMER, stime_value)
+
+#endif /* __ARCH_RISC_V_SRC_NUTTSBI_SBI_MCALL_H */
diff --git a/arch/risc-v/src/nuttsbi/sbi_mexception.c b/arch/risc-v/src/nuttsbi/sbi_mexception.c
new file mode 100644
index 0000000000..27cd033a35
--- /dev/null
+++ b/arch/risc-v/src/nuttsbi/sbi_mexception.c
@@ -0,0 +1,37 @@
+/****************************************************************************
+ * arch/risc-v/src/nuttsbi/sbi_mexception.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>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void sbi_mexception(uintptr_t mcause, uintptr_t *mepc)
+{
+  (void) mcause;
+  (void) mepc;
+}
diff --git a/arch/risc-v/src/nuttsbi/sbi_mscratch.c b/arch/risc-v/src/nuttsbi/sbi_mscratch.c
new file mode 100644
index 0000000000..7010678a69
--- /dev/null
+++ b/arch/risc-v/src/nuttsbi/sbi_mscratch.c
@@ -0,0 +1,85 @@
+/****************************************************************************
+ * arch/risc-v/src/nuttsbi/sbi_mscratch.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 <nuttx/irq.h>
+
+#include <arch/barriers.h>
+
+#include <stdint.h>
+
+#include "riscv_internal.h"
+
+#include "sbi_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define STACK_SIZE  (STACK_ALIGN_DOWN(MMODE_IRQSTACK))
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+extern uintptr_t g_mintstacktop;
+extern uintptr_t g_mintstackalloc;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sbi_mscratch_assign
+ *
+ * Description:
+ *   Assign the mscratch register for hartid. Sets the M-mode interrupt stack
+ *   which is a must because M-mode deals with flat addressing and cannot
+ *   share the user stack for exception handling.
+ *
+ * Input Parameters:
+ *   hartid - Hartid
+ *
+ ****************************************************************************/
+
+void sbi_mscratch_assign(uintptr_t hartid)
+{
+  uintptr_t stack_top;
+#if MMODE_HART_CNT > 1
+  /* Calculate offset first (stack size * hartid) */
+
+  /* REVISIT: This requires that hartID is sequential, and starts from 0 */
+
+  stack_top = (uintptr_t)&g_mintstacktop - hartid * STACK_SIZE;
+#else
+  UNUSED(hartid);
+  stack_top = (uintptr_t)&g_mintstacktop;
+#endif
+
+  WRITE_CSR(mscratch, stack_top);
+
+  /* Make sure mscratch is updated before continuing */
+
+  __DMB();
+}
diff --git a/arch/risc-v/src/nuttsbi/sbi_mtimer.c b/arch/risc-v/src/nuttsbi/sbi_mtimer.c
new file mode 100644
index 0000000000..a6771bdbf5
--- /dev/null
+++ b/arch/risc-v/src/nuttsbi/sbi_mtimer.c
@@ -0,0 +1,100 @@
+/****************************************************************************
+ * arch/risc-v/src/nuttsbi/sbi_mtimer.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 <nuttx/compiler.h>
+#include <nuttx/irq.h>
+
+#include <arch/barriers.h>
+
+#include <stdint.h>
+
+#include "riscv_internal.h"
+
+#include "sbi_internal.h"
+#include "sbi_mcall.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Memory mapped register base addresses */
+
+static volatile uintptr_t g_mtimecmp locate_data(".noinit");
+static volatile uintptr_t g_mtime    locate_data(".noinit");
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void sbi_init_mtimer(uintptr_t mtime, uintptr_t mtimecmp)
+{
+  /* Set the memory mapped register bases */
+
+  g_mtimecmp = mtimecmp;
+  g_mtime    = mtime;
+}
+
+uint64_t sbi_get_mtime(void)
+{
+#ifdef CONFIG_ARCH_RV64
+  return getreg64(g_mtime);
+#else
+  uint32_t hi;
+  uint32_t lo;
+
+  do
+    {
+      hi = getreg32(g_mtime + 4);
+      lo = getreg32(g_mtime);
+    }
+  while (getreg32(g_mtime + 4) != hi);
+
+  return ((uint64_t)hi << 32) | lo;
+#endif
+}
+
+void sbi_set_mtimecmp(uint64_t value)
+{
+  uintptr_t mtimecmp = g_mtimecmp + READ_CSR(mhartid) * sizeof(uintptr_t);
+#ifdef CONFIG_ARCH_RV64
+  putreg64(value, mtimecmp);
+#else
+  putreg32(UINT32_MAX, mtimecmp + 4);
+  putreg32(value, mtimecmp);
+  putreg32(value >> 32, mtimecmp + 4);
+#endif
+
+  /* Make sure it sticks */
+
+  __DMB();
+}
diff --git a/arch/risc-v/src/nuttsbi/sbi_mtrap.S b/arch/risc-v/src/nuttsbi/sbi_mtrap.S
new file mode 100644
index 0000000000..52809cae0a
--- /dev/null
+++ b/arch/risc-v/src/nuttsbi/sbi_mtrap.S
@@ -0,0 +1,154 @@
+/****************************************************************************
+ * arch/risc-v/src/nuttsbi/sbi_machine_trap.S
+ *
+ * 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 <nuttx/irq.h>
+
+#include "riscv_macros.S"
+
+#include "riscv_internal.h"
+
+#include "sbi_internal.h"
+
+/****************************************************************************
+ * Public Symbols
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: machine_trap
+ *
+ * Description:
+ *   Machine mode trap handler. Handles Mtimer and simple mcall interface.
+ *
+ ****************************************************************************/
+
+  .section .text
+  .global  machine_trap
+  .align   8
+
+machine_trap:
+
+  /* Switch to M-mode IRQ stack */
+
+  csrrw      sp, mscratch, sp     /* mscratch has user stack */
+  beqz       sp, .Lmtrap          /* Detect recursive traps */
+
+  addi       sp, sp, -XCPTCONTEXT_SIZE
+  save_ctx   sp
+
+  csrr       a0, mcause           /* exception cause  */
+
+  csrrw      s0, mscratch, x0     /* read user stack */
+  REGSTORE   s0, REG_X2(sp)       /* original SP      */
+
+  /* Check if this is an exception */
+
+  bgez       a0, .Lmexception
+
+  /* Figure out which interrupt this is */
+
+  sll        a0, a0, 1            /* Shift msbit out */
+  li         a1, MTIMER_IRQ * 2   /* Machine timer irq ? (shifted left) */
+  bne        a0, a1, 1f
+
+  /* Delegate interrupt to S-mode handler */
+
+  li         a0, MIP_MTIP
+  csrc       mie, a0
+  li         a0, MIP_STIP
+  csrs       mip, a0
+
+1:
+  /* Restore mscratch */
+
+  addi       s0, sp, XCPTCONTEXT_SIZE
+  csrw       mscratch, s0         /* original mscratch */
+
+  /* Restore original context */
+
+  load_ctx   sp
+
+  REGLOAD    sp, REG_SP(sp)       /* restore original sp */
+
+  /* Return from Machine Interrupt */
+
+  mret
+
+.Lmexception:
+
+  /* Handle exception, only accepted source is ecall */
+
+  sll        a0, a0, 1
+  li         a1, RISCV_IRQ_ECALLS * 2
+  bne        a0, a1, .Lmtrap
+
+  /* Handle ecall */
+
+  mv         a0, sp
+  jal        x1, sbi_mcall_handle
+  csrr       a0, mepc
+  addi       a0, a0, 4
+  csrw       mepc, a0
+  j          1b
+
+  /* An unhandled trap to M-mode: this is an error and we cannot proceed */
+
+.Lmtrap:
+
+  csrr        a0, mcause         /* Interrupt cause [arg0] */
+  csrr        a1, mepc           /* Interrupt PC (instruction) [arg1] */
+  jal         x1, sbi_mexception
+  j           __start
+
+.Lmtraploop:
+
+  /* If we somehow get here, prevent the software from running away */
+
+  nop
+  nop
+  j           .Lmtraploop
+
+/*****************************************************************************
+ *  Name: m_intstackalloc / m_intstacktop
+ *
+ *  Description:
+ *    Allocate separate stack(s) for machine mode interrupts, only if kernel
+ *    runs in S-mode. Separate stacks are needed as M-mode interrupts can
+ *    pre-empt S-mode interrupts.
+ *
+ ****************************************************************************/
+
+#define STACK_ALLOC_SIZE (MMODE_IRQSTACK * CONFIG_SMP_NCPUS)
+
+  .bss
+  .balign 16
+  .global g_mintstackalloc
+  .global g_mintstacktop
+  .type   g_mintstackalloc, object
+  .type   g_mintstacktop, object
+g_mintstackalloc:
+  .skip  STACK_ALIGN_UP(STACK_ALLOC_SIZE)
+g_mintstacktop:
+  .size  g_mintstacktop, 0
+  .size  g_mintstackalloc, STACK_ALIGN_DOWN(STACK_ALLOC_SIZE)
diff --git a/arch/risc-v/src/nuttsbi/sbi_start.c b/arch/risc-v/src/nuttsbi/sbi_start.c
new file mode 100644
index 0000000000..b968302d03
--- /dev/null
+++ b/arch/risc-v/src/nuttsbi/sbi_start.c
@@ -0,0 +1,125 @@
+/****************************************************************************
+ * arch/risc-v/src/nuttsbi/sbi_start.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 <nuttx/compiler.h>
+#include <nuttx/irq.h>
+
+#include <assert.h>
+
+#include "riscv_internal.h"
+
+#include "sbi_internal.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void __trap_vec_tmp(void) noreturn_function;
+static void __trap_vec_tmp(void)
+{
+  for (; ; )
+    {
+      asm("WFI");
+    }
+}
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+extern void __start_s(void);
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void sbi_start(void)
+{
+  uintptr_t reg;
+  uintptr_t hartid;
+
+  /* Read hart ID */
+
+  hartid = READ_CSR(mhartid);
+
+  /* Set mscratch, mtimer */
+
+  sbi_mscratch_assign(hartid);
+  sbi_init_mtimer(MTIMER_TIME_BASE, MTIMER_CMP_BASE);
+
+  /* Setup system to enter S-mode */
+
+  reg  =  READ_CSR(mstatus);
+  reg &= ~MSTATUS_MPPM; /* Clear MPP */
+  reg &= ~MSTATUS_MPIE; /* Clear MPIE */
+  reg &= ~MSTATUS_TW;   /* Do not trap WFI */
+  reg &= ~MSTATUS_TSR;  /* Do not trap sret */
+  reg &= ~MSTATUS_TVM;  /* Allow satp writes from S-mode */
+  reg |=  MSTATUS_SUM;  /* Allow supervisor to access user memory */
+  reg |=  MSTATUS_MPPS; /* Set next context = supervisor */
+
+  /* Setup next context */
+
+  WRITE_CSR(mstatus, reg);
+
+  /* Setup a temporary S-mode interrupt vector */
+
+  WRITE_CSR(stvec, __trap_vec_tmp);
+
+  /* Delegate interrupts */
+
+  reg = (MIP_SSIP | MIP_STIP | MIP_SEIP);
+  WRITE_CSR(mideleg, reg);
+
+  /* Delegate exceptions (all of them) */
+
+  reg = ((1 << RISCV_IRQ_IAMISALIGNED) |
+         (1 << RISCV_IRQ_INSTRUCTIONPF) |
+         (1 << RISCV_IRQ_LOADPF) |
+         (1 << RISCV_IRQ_STOREPF) |
+         (1 << RISCV_IRQ_ECALLU));
+  WRITE_CSR(medeleg, reg);
+
+  /* Enable access to all counters for S- and U-mode */
+
+  WRITE_CSR(mcounteren, UINT32_C(~0));
+  WRITE_CSR(scounteren, UINT32_C(~0));
+
+  /* Set program counter to __start_s */
+
+  WRITE_CSR(mepc, __start_s);
+
+  /* Open everything for PMP */
+
+  WRITE_CSR(pmpaddr0, -1);
+  WRITE_CSR(pmpcfg0, (PMPCFG_A_NAPOT | PMPCFG_R | PMPCFG_W | PMPCFG_X));
+
+  /* Then jump to the S-mode start function */
+
+  register long r0 asm("a0") = (long) hartid;
+  __asm__ __volatile__("mret" : : "r"(r0));
+
+  PANIC();
+}
diff --git a/arch/risc-v/src/nuttsbi/sbi_vectors.S b/arch/risc-v/src/nuttsbi/sbi_vectors.S
new file mode 100644
index 0000000000..90d3f6c804
--- /dev/null
+++ b/arch/risc-v/src/nuttsbi/sbi_vectors.S
@@ -0,0 +1,39 @@
+/****************************************************************************
+ * arch/risc-v/src/nuttsbi/sbi_machine_vectors.S
+ *
+ * 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
+ ****************************************************************************/
+
+  .section .text
+  .balign  8
+  .global  __mtrap_vec
+
+/****************************************************************************
+ * Name: __mtrap_vec
+ *
+ * Description:
+ *   All M-mode exceptions and interrupts will be handled from here.
+ *
+ ****************************************************************************/
+
+__mtrap_vec:
+  j    machine_trap
+  nop