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/05/12 20:14:05 UTC

[incubator-nuttx] branch master updated (77e36d1acc -> dc2a01e75a)

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 77e36d1acc risc-v/mpfs: introduce IHC driver
     new 3193aa3c97 arch: risc-v: Add MMU support for qemu-rv
     new dc2a01e75a boards: rv-virt: Add knsh64 related files

The 2 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                                |  6 +++
 arch/risc-v/src/qemu-rv/Make.defs                  | 36 ++++++++++++-
 arch/risc-v/src/qemu-rv/chip.h                     |  8 +++
 arch/risc-v/src/qemu-rv/hardware/qemu_rv_plic.h    | 22 ++++++--
 .../qemu_rv_allocateheap.c}                        |  6 +--
 arch/risc-v/src/qemu-rv/qemu_rv_head.S             |  4 ++
 arch/risc-v/src/qemu-rv/qemu_rv_irq.c              | 43 +++++++--------
 arch/risc-v/src/qemu-rv/qemu_rv_irq_dispatch.c     | 10 ++--
 .../mpfs_mm_init.c => qemu-rv/qemu_rv_mm_init.c}   | 43 ++++++++++++---
 .../src/qemu-rv/qemu_rv_mm_init.h}                 | 33 +++++-------
 .../mpfs_pgalloc.c => qemu-rv/qemu_rv_pgalloc.c}   |  2 +-
 arch/risc-v/src/qemu-rv/qemu_rv_start.c            | 53 ++++++++++++++++++
 arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c         |  2 +
 .../rv-virt/configs/{nsh64 => knsh64}/defconfig    | 49 ++++++++++++-----
 .../rv-virt}/include/board_memorymap.h             | 12 ++---
 boards/risc-v/qemu-rv/rv-virt/scripts/Make.defs    |  4 ++
 .../scripts/{ld.script => ld-kernel.script}        | 62 +++++++++++++---------
 17 files changed, 288 insertions(+), 107 deletions(-)
 copy arch/risc-v/src/{mpfs/mpfs_allocateheap.c => qemu-rv/qemu_rv_allocateheap.c} (97%)
 copy arch/risc-v/src/{mpfs/mpfs_mm_init.c => qemu-rv/qemu_rv_mm_init.c} (80%)
 copy arch/{arm/src/stm32l4/stm32l4_mpuinit.h => risc-v/src/qemu-rv/qemu_rv_mm_init.h} (73%)
 copy arch/risc-v/src/{mpfs/mpfs_pgalloc.c => qemu-rv/qemu_rv_pgalloc.c} (98%)
 copy boards/risc-v/qemu-rv/rv-virt/configs/{nsh64 => knsh64}/defconfig (61%)
 copy boards/risc-v/{mpfs/icicle => qemu-rv/rv-virt}/include/board_memorymap.h (89%)
 copy boards/risc-v/qemu-rv/rv-virt/scripts/{ld.script => ld-kernel.script} (77%)
 mode change 100644 => 100755


[incubator-nuttx] 02/02: boards: rv-virt: Add knsh64 related files

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 dc2a01e75a89ea0e90dbc37aebbc7822f1d846e9
Author: Masayuki Ishikawa <ma...@gmail.com>
AuthorDate: Mon May 9 11:02:46 2022 +0900

    boards: rv-virt: Add knsh64 related files
    
    Summary:
    - This commit adds knsh64 related files
    
    Impact:
    - None
    
    Testing:
    - Tested with qemu-6.2
    
    Signed-off-by: Masayuki Ishikawa <Ma...@jp.sony.com>
---
 .../qemu-rv/rv-virt/configs/knsh64/defconfig       |  96 ++++++++++++++
 .../qemu-rv/rv-virt/include/board_memorymap.h      |  98 ++++++++++++++
 boards/risc-v/qemu-rv/rv-virt/scripts/Make.defs    |   4 +
 .../qemu-rv/rv-virt/scripts/ld-kernel.script       | 143 +++++++++++++++++++++
 4 files changed, 341 insertions(+)

diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/knsh64/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/knsh64/defconfig
new file mode 100644
index 0000000000..ce821e008a
--- /dev/null
+++ b/boards/risc-v/qemu-rv/rv-virt/configs/knsh64/defconfig
@@ -0,0 +1,96 @@
+#
+# 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_16550_ADDRWIDTH=0
+CONFIG_16550_UART0=y
+CONFIG_16550_UART0_BASE=0x10000000
+CONFIG_16550_UART0_CLOCK=3686400
+CONFIG_16550_UART0_IRQ=35
+CONFIG_16550_UART0_SERIAL_CONSOLE=y
+CONFIG_16550_UART=y
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_ADDRENV=y
+CONFIG_ARCH_BOARD="rv-virt"
+CONFIG_ARCH_BOARD_QEMU_RV_VIRT=y
+CONFIG_ARCH_CHIP="qemu-rv"
+CONFIG_ARCH_CHIP_QEMU_RV64=y
+CONFIG_ARCH_CHIP_QEMU_RV=y
+CONFIG_ARCH_CHIP_QEMU_RV_ISA_A=y
+CONFIG_ARCH_CHIP_QEMU_RV_ISA_C=y
+CONFIG_ARCH_CHIP_QEMU_RV_ISA_M=y
+CONFIG_ARCH_DATA_NPAGES=128
+CONFIG_ARCH_DATA_VBASE=0xC0000000
+CONFIG_ARCH_HEAP_NPAGES=128
+CONFIG_ARCH_HEAP_VBASE=0x00000000
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_KERNEL_STACKSIZE=3072
+CONFIG_ARCH_PGPOOL_MAPPING=y
+CONFIG_ARCH_PGPOOL_PBASE=0x80400000
+CONFIG_ARCH_PGPOOL_SIZE=4194304
+CONFIG_ARCH_PGPOOL_VBASE=0x80400000
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_TEXT_NPAGES=0
+CONFIG_ARCH_TEXT_VBASE=0x00000000
+CONFIG_ARCH_USE_MMU=y
+CONFIG_ARCH_USE_MPU=y
+CONFIG_ARCH_USE_S_MODE=y
+CONFIG_BOARD_LOOPSPERMSEC=6366
+CONFIG_BUILD_KERNEL=y
+CONFIG_DEBUG_ASSERTIONS=y
+CONFIG_DEBUG_ERROR=y
+CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEV_ZERO=y
+CONFIG_ELF=y
+CONFIG_EXAMPLES_HELLO=m
+CONFIG_FS_HOSTFS=y
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=3072
+CONFIG_INIT_FILEPATH="/system/bin/init"
+CONFIG_INIT_MOUNT=y
+CONFIG_INIT_MOUNT_DATA="fs=../apps"
+CONFIG_INIT_MOUNT_FLAGS=0x1
+CONFIG_INIT_MOUNT_FSTYPE="hostfs"
+CONFIG_INIT_MOUNT_SOURCE=""
+CONFIG_INIT_MOUNT_TARGET="/system"
+CONFIG_INIT_STACKSIZE=3072
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_ENVPATH=y
+CONFIG_LIBC_EXECFUNCS=y
+CONFIG_LIBC_FLOATINGPOINT=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_MEMSET_64BIT=y
+CONFIG_MEMSET_OPTSPEED=y
+CONFIG_MM_PGALLOC=y
+CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_FILE_APPS=y
+CONFIG_NSH_READLINE=y
+CONFIG_PATH_INITIAL="/system/bin"
+CONFIG_PREALLOC_TIMERS=0
+CONFIG_RAM_SIZE=1048576
+CONFIG_RAM_START=0x80100000
+CONFIG_READLINE_CMD_HISTORY=y
+CONFIG_RISCV_SEMIHOSTING_HOSTFS=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_SERIAL_UART_ARCH_MMIO=y
+CONFIG_STACK_COLORATION=y
+CONFIG_START_MONTH=12
+CONFIG_START_YEAR=2021
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_SYSLOG_TIMESTAMP=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_NSH_PROGNAME="init"
+CONFIG_TESTING_GETPRIME=y
+CONFIG_USEC_PER_TICK=1000
diff --git a/boards/risc-v/qemu-rv/rv-virt/include/board_memorymap.h b/boards/risc-v/qemu-rv/rv-virt/include/board_memorymap.h
new file mode 100644
index 0000000000..c0c6336b01
--- /dev/null
+++ b/boards/risc-v/qemu-rv/rv-virt/include/board_memorymap.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+ * boards/risc-v/qemu-rv/rv-virt/include/board_memorymap.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 __BOARDS_RISCV_QEMURV_RVVIRT_INCLUDE_BOARD_MEMORYMAP_H
+#define __BOARDS_RISCV_QEMURV_RVVIRT_INCLUDE_BOARD_MEMORYMAP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* DDR start address */
+
+#define QEMURV_DDR_BASE   (0x80000000)
+#define QEMURV_DDR_SIZE   (0x40000000)
+
+/* Kernel code memory (RX) */
+
+#define KFLASH_START    (uintptr_t)&__kflash_start
+#define KFLASH_SIZE     (uintptr_t)&__kflash_size
+#define KSRAM_START     (uintptr_t)&__ksram_start
+#define KSRAM_SIZE      (uintptr_t)&__ksram_size
+#define KSRAM_END       (uintptr_t)&__ksram_end
+
+/* Kernel RAM (RW) */
+
+#define PGPOOL_START    (uintptr_t)&__pgheap_start
+#define PGPOOL_SIZE     (uintptr_t)&__pgheap_size
+
+/* Page pool (RWX) */
+
+#define PGPOOL_START    (uintptr_t)&__pgheap_start
+#define PGPOOL_SIZE     (uintptr_t)&__pgheap_size
+#define PGPOOL_END      (PGPOOL_START + PGPOOL_SIZE)
+
+/* User flash */
+
+#define UFLASH_START    (uintptr_t)&__uflash_start
+#define UFLASH_SIZE     (uintptr_t)&__uflash_size
+
+/* User RAM */
+
+#define USRAM_START     (uintptr_t)&__usram_start
+#define USRAM_SIZE      (uintptr_t)&__usram_size
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* Kernel code memory (RX)  */
+
+extern uintptr_t        __kflash_start;
+extern uintptr_t        __kflash_size;
+
+/* Kernel RAM (RW) */
+
+extern uintptr_t        __ksram_start;
+extern uintptr_t        __ksram_size;
+extern uintptr_t        __ksram_end;
+
+/* Page pool (RWX) */
+
+extern uintptr_t        __pgheap_start;
+extern uintptr_t        __pgheap_size;
+
+/* User code memory (RX) */
+
+extern uintptr_t        __uflash_start;
+extern uintptr_t        __uflash_size;
+
+/* User RAM (RW) */
+
+extern uintptr_t        __usram_start;
+extern uintptr_t        __usram_size;
+
+#endif /* __BOARDS_RISC_V_QEMURV_RVVIRT_INCLUDE_BOARD_MEMORYMAP_H */
diff --git a/boards/risc-v/qemu-rv/rv-virt/scripts/Make.defs b/boards/risc-v/qemu-rv/rv-virt/scripts/Make.defs
index 596a800bbb..051f362e18 100644
--- a/boards/risc-v/qemu-rv/rv-virt/scripts/Make.defs
+++ b/boards/risc-v/qemu-rv/rv-virt/scripts/Make.defs
@@ -23,8 +23,12 @@ include $(TOPDIR)/tools/Config.mk
 include $(TOPDIR)/arch/risc-v/src/common/Toolchain.defs
 
 ifeq ($(CONFIG_ARCH_CHIP_QEMU_RV),y)
+ifeq ($(CONFIG_BUILD_KERNEL),y)
+  LDSCRIPT = ld-kernel.script
+else
   LDSCRIPT = ld.script
 endif
+endif
 
 ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT)
 
diff --git a/boards/risc-v/qemu-rv/rv-virt/scripts/ld-kernel.script b/boards/risc-v/qemu-rv/rv-virt/scripts/ld-kernel.script
new file mode 100755
index 0000000000..1c29fa58cf
--- /dev/null
+++ b/boards/risc-v/qemu-rv/rv-virt/scripts/ld-kernel.script
@@ -0,0 +1,143 @@
+/****************************************************************************
+ * boards/risc-v/qemu-rv/rv-virt/scripts/ld.script
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+MEMORY
+{
+    kflash (rx) : ORIGIN = 0x80000000, LENGTH = 2048K   /* w/ cache */
+    ksram (rwx) : ORIGIN = 0x80200000, LENGTH = 2048K   /* w/ cache */
+    pgram (rwx) : ORIGIN = 0x80400000, LENGTH = 4096K   /* w/ cache */
+}
+
+OUTPUT_ARCH("riscv")
+
+/* Provide the kernel boundaries */
+
+__kflash_start = ORIGIN(kflash);
+__kflash_size = LENGTH(kflash);
+__ksram_start = ORIGIN(ksram);
+__ksram_size = LENGTH(ksram);
+__ksram_end = ORIGIN(ksram) + LENGTH(ksram);
+
+/* Page heap */
+
+__pgheap_start = ORIGIN(pgram);
+__pgheap_size = LENGTH(pgram);
+
+SECTIONS
+{
+  . = 0x80000000;
+
+  .text :
+    {
+      _stext = . ;
+      *(.text)
+      *(.text.*)
+      *(.gnu.warning)
+      *(.stub)
+      *(.glue_7)
+      *(.glue_7t)
+      *(.jcr)
+
+      /* C++ support:  The .init and .fini sections contain specific logic
+       * to manage static constructors and destructors.
+       */
+
+      *(.gnu.linkonce.t.*)
+      *(.init)             /* Old ABI */
+      *(.fini)             /* Old ABI */
+      _etext = . ;
+    }
+
+  .rodata :
+    {
+      _srodata = . ;
+      *(.rodata)
+      *(.rodata1)
+      *(.rodata.*)
+      *(.gnu.linkonce.r*)
+      _erodata = . ;
+    }
+
+  .tdata : {
+      _stdata = ABSOLUTE(.);
+      *(.tdata .tdata.* .gnu.linkonce.td.*);
+      _etdata = ABSOLUTE(.);
+  }
+
+  .tbss : {
+      _stbss = ABSOLUTE(.);
+      *(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon);
+      _etbss = ABSOLUTE(.);
+  }
+
+  _eronly = ABSOLUTE(.);
+
+  .data :
+    {
+      _sdata = . ;
+      *(.data)
+      *(.data1)
+      *(.data.*)
+      *(.gnu.linkonce.d*)
+      . = ALIGN(4);
+      _edata = . ;
+    }
+
+  .bss :
+    {
+      _sbss = . ;
+      *(.bss)
+      *(.bss.*)
+      *(.sbss)
+      *(.sbss.*)
+      *(.gnu.linkonce.b*)
+      *(COMMON)
+      _ebss = . ;
+    } > ksram
+
+    /* Page tables here, align to 4K boundary */
+
+    .pgtables : ALIGN(0x1000) {
+        *(.pgtables)
+        . = ALIGN(4);
+    } > ksram
+
+    /* Stack top */
+
+    .stack_top : {
+        . = ALIGN(32);
+        _ebss = ABSOLUTE(.);
+    } > ksram
+
+    /* Stabs debugging sections.    */
+
+    .stab 0 : { *(.stab) }
+    .stabstr 0 : { *(.stabstr) }
+    .stab.excl 0 : { *(.stab.excl) }
+    .stab.exclstr 0 : { *(.stab.exclstr) }
+    .stab.index 0 : { *(.stab.index) }
+    .stab.indexstr 0 : { *(.stab.indexstr) }
+    .comment 0 : { *(.comment) }
+    .debug_abbrev 0 : { *(.debug_abbrev) }
+    .debug_info 0 : { *(.debug_info) }
+    .debug_line 0 : { *(.debug_line) }
+    .debug_pubnames 0 : { *(.debug_pubnames) }
+    .debug_aranges 0 : { *(.debug_aranges) }
+}


[incubator-nuttx] 01/02: arch: risc-v: Add MMU support for qemu-rv

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 3193aa3c97ed26e5cb9c5638c070282643531ad2
Author: Masayuki Ishikawa <ma...@gmail.com>
AuthorDate: Mon May 9 11:00:56 2022 +0900

    arch: risc-v: Add MMU support for qemu-rv
    
    Summary:
    - This commit adds MMU support for qemu-rv
    - Please note that mtimer is disabled for S-mode because
      the mtimer needs to be accessed in M-mode
    
    Impact:
    - qemu-rv only
    
    Testing:
    - Tested with rv-virt:knsh64 (will be pushed later)
    
    Signed-off-by: Masayuki Ishikawa <Ma...@jp.sony.com>
---
 arch/risc-v/Kconfig                                |   6 +
 arch/risc-v/src/qemu-rv/Make.defs                  |  36 ++++-
 arch/risc-v/src/qemu-rv/chip.h                     |   8 +
 arch/risc-v/src/qemu-rv/hardware/qemu_rv_plic.h    |  22 ++-
 arch/risc-v/src/qemu-rv/qemu_rv_allocateheap.c     | 147 ++++++++++++++++++
 arch/risc-v/src/qemu-rv/qemu_rv_head.S             |   4 +
 arch/risc-v/src/qemu-rv/qemu_rv_irq.c              |  43 +++---
 arch/risc-v/src/qemu-rv/qemu_rv_irq_dispatch.c     |  10 +-
 arch/risc-v/src/qemu-rv/qemu_rv_mm_init.c          | 171 +++++++++++++++++++++
 .../{qemu_rv_timerisr.c => qemu_rv_mm_init.h}      |  51 +++---
 .../{qemu_rv_timerisr.c => qemu_rv_pgalloc.c}      |  44 +++---
 arch/risc-v/src/qemu-rv/qemu_rv_start.c            |  53 +++++++
 arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c         |   2 +
 13 files changed, 508 insertions(+), 89 deletions(-)

diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig
index 82a4b649b0..025e186d97 100644
--- a/arch/risc-v/Kconfig
+++ b/arch/risc-v/Kconfig
@@ -136,6 +136,12 @@ config ARCH_CHIP_QEMU_RV
 	select ARCH_HAVE_FPU if EXPERIMENTAL
 	select ARCH_HAVE_DPFPU if EXPERIMENTAL
 	select ARCH_HAVE_MULTICPU
+	select ARCH_HAVE_MPU
+	select ARCH_HAVE_MMU
+	select ARCH_MMU_TYPE_SV39 if ARCH_CHIP_QEMU_RV64
+	select ARCH_HAVE_ADDRENV
+	select ARCH_NEED_ADDRENV_MAPPING
+	select ARCH_HAVE_S_MODE
 	select ONESHOT
 	select ALARM_ARCH
 	---help---
diff --git a/arch/risc-v/src/qemu-rv/Make.defs b/arch/risc-v/src/qemu-rv/Make.defs
index 74fc60a903..e48c85fcc8 100644
--- a/arch/risc-v/src/qemu-rv/Make.defs
+++ b/arch/risc-v/src/qemu-rv/Make.defs
@@ -22,6 +22,10 @@
 # the first object file, so it will appear at address 0
 HEAD_ASRC = qemu_rv_head.S
 
+ifeq ($(CONFIG_BUILD_KERNEL),y)
+STARTUP_OBJS = crt0$(OBJEXT)
+endif
+
 # Specify our general Assembly files
 CMN_ASRCS += riscv_vectors.S riscv_exception_common.S
 
@@ -75,4 +79,34 @@ endif
 
 # Specify our C code within this directory to be included
 CHIP_CSRCS  = qemu_rv_start.c qemu_rv_irq_dispatch.c qemu_rv_irq.c
-CHIP_CSRCS += qemu_rv_timerisr.c
+CHIP_CSRCS += qemu_rv_timerisr.c qemu_rv_allocateheap.c
+
+ifeq ($(CONFIG_BUILD_KERNEL),y)
+CHIP_CSRCS += qemu_rv_mm_init.c
+endif
+
+ifneq ($(CONFIG_BUILD_FLAT),y)
+CMN_CSRCS += riscv_task_start.c
+CMN_CSRCS += riscv_pthread_start.c
+CMN_CSRCS += riscv_signal_dispatch.c
+endif
+
+ifeq ($(CONFIG_ARCH_USE_MPU),y)
+CMN_CSRCS += riscv_pmp.c
+endif
+
+ifeq ($(CONFIG_ARCH_USE_MMU),y)
+CMN_CSRCS += riscv_mmu.c
+endif
+
+ifeq ($(CONFIG_ARCH_KERNEL_STACK),y)
+CMN_CSRCS += riscv_addrenv_kstack.c
+endif
+
+ifeq ($(CONFIG_ARCH_ADDRENV),y)
+CMN_CSRCS += riscv_addrenv.c riscv_pgalloc.c riscv_addrenv_perms.c
+endif
+
+ifeq ($(CONFIG_MM_PGALLOC),y)
+CHIP_CSRCS += qemu_rv_pgalloc.c
+endif
diff --git a/arch/risc-v/src/qemu-rv/chip.h b/arch/risc-v/src/qemu-rv/chip.h
index 3d8d05d75f..f8f78fbe51 100644
--- a/arch/risc-v/src/qemu-rv/chip.h
+++ b/arch/risc-v/src/qemu-rv/chip.h
@@ -47,6 +47,7 @@ extern void up_serialinit(void);
 #include "hardware/qemu_rv_plic.h"
 
 #include "riscv_internal.h"
+#include "riscv_percpu.h"
 
 /****************************************************************************
  * Macro Definitions
@@ -73,5 +74,12 @@ extern void up_serialinit(void);
 .endm
 #endif /* CONFIG_SMP && CONFIG_ARCH_INTERRUPTSTACK > 15 */
 
+#if defined(CONFIG_ARCH_USE_S_MODE) && CONFIG_ARCH_INTERRUPTSTACK > 15
+.macro  setintstack tmp0, tmp1
+  csrr    \tmp0, CSR_SCRATCH
+  REGLOAD sp, RISCV_PERCPU_IRQSTACK(\tmp0)
+.endm
+#endif /* CONFIG_ARCH_USE_S_MODE && CONFIG_ARCH_INTERRUPTSTACK > 15 */
+
 #endif /* __ASSEMBLY__  */
 #endif /* __ARCH_RISCV_SRC_QEMU_RV_CHIP_H */
diff --git a/arch/risc-v/src/qemu-rv/hardware/qemu_rv_plic.h b/arch/risc-v/src/qemu-rv/hardware/qemu_rv_plic.h
index 7c010dd90b..eac61f8fd1 100644
--- a/arch/risc-v/src/qemu-rv/hardware/qemu_rv_plic.h
+++ b/arch/risc-v/src/qemu-rv/hardware/qemu_rv_plic.h
@@ -21,15 +21,29 @@
 #ifndef __ARCH_RISCV_SRC_QEMU_RV_HARDWARE_QEMU_RV_PLIC_H
 #define __ARCH_RISCV_SRC_QEMU_RV_HARDWARE_QEMU_RV_PLIC_H
 
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
 
 #define QEMU_RV_PLIC_PRIORITY    (QEMU_RV_PLIC_BASE + 0x000000)
 #define QEMU_RV_PLIC_PENDING1    (QEMU_RV_PLIC_BASE + 0x001000)
-#define QEMU_RV_PLIC_ENABLE1     (QEMU_RV_PLIC_BASE + 0x002000)
-#define QEMU_RV_PLIC_ENABLE2     (QEMU_RV_PLIC_BASE + 0x002004)
-#define QEMU_RV_PLIC_THRESHOLD   (QEMU_RV_PLIC_BASE + 0x200000)
-#define QEMU_RV_PLIC_CLAIM       (QEMU_RV_PLIC_BASE + 0x200004)
+
+#ifdef CONFIG_ARCH_USE_S_MODE
+#  define QEMU_RV_PLIC_ENABLE1   (QEMU_RV_PLIC_BASE + 0x002080)
+#  define QEMU_RV_PLIC_ENABLE2   (QEMU_RV_PLIC_BASE + 0x002084)
+#  define QEMU_RV_PLIC_THRESHOLD (QEMU_RV_PLIC_BASE + 0x201000)
+#  define QEMU_RV_PLIC_CLAIM     (QEMU_RV_PLIC_BASE + 0x201004)
+#else
+#  define QEMU_RV_PLIC_ENABLE1   (QEMU_RV_PLIC_BASE + 0x002000)
+#  define QEMU_RV_PLIC_ENABLE2   (QEMU_RV_PLIC_BASE + 0x002004)
+#  define QEMU_RV_PLIC_THRESHOLD (QEMU_RV_PLIC_BASE + 0x200000)
+#  define QEMU_RV_PLIC_CLAIM     (QEMU_RV_PLIC_BASE + 0x200004)
+#endif
 
 #endif /* __ARCH_RISCV_SRC_QEMU_RV_HARDWARE_QEMU_RV_PLIC_H */
diff --git a/arch/risc-v/src/qemu-rv/qemu_rv_allocateheap.c b/arch/risc-v/src/qemu-rv/qemu_rv_allocateheap.c
new file mode 100755
index 0000000000..bf61de105b
--- /dev/null
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_allocateheap.c
@@ -0,0 +1,147 @@
+/****************************************************************************
+ * arch/risc-v/src/qemu-rv/qemu_rv_allocateheap.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/kmalloc.h>
+#include <nuttx/userspace.h>
+
+#include <nuttx/arch.h>
+
+#ifdef CONFIG_MM_KERNEL_HEAP
+#include <arch/board/board_memorymap.h>
+#endif
+
+#include "riscv_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_MM_KERNEL_HEAP
+#define KRAM_END    KSRAM_END
+#else
+#define KRAM_END    CONFIG_RAM_END
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_allocate_heap
+ *
+ * Description:
+ *   This function will be called to dynamically set aside the heap region.
+ *
+ *   For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and
+ *   user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the
+ *   size of the unprotected, user-space heap.
+ *
+ *   If a protected kernel-space heap is provided, the kernel heap must be
+ *   allocated (and protected) by an analogous up_allocate_kheap().
+ *
+ *   The following memory map is assumed for the flat build:
+ *
+ *   .data region.  Size determined at link time.
+ *   .bss  region  Size determined at link time.
+ *   IDLE thread stack.  Size determined by CONFIG_IDLETHREAD_STACKSIZE.
+ *   Heap.  Extends to the end of User SRAM.
+ *
+ *   The following memory map is assumed for the protect build.
+ *   The kernel and user space have it's own dedicated heap space.
+ *
+ *   User .data region         Size determined at link time
+ *   User .bss region          Size determined at link time
+ *   User heap                 Extends to the end of User SRAM
+ *   Kernel .data region       Size determined at link time
+ *   Kernel .bss  region       Size determined at link time
+ *   Kernel IDLE thread stack  Size determined by CONFIG_IDLETHREAD_STACKSIZE
+ *   Kernel heap               Size determined by CONFIG_MM_KERNEL_HEAPSIZE
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_BUILD_KERNEL
+void up_allocate_kheap(void **heap_start, size_t *heap_size)
+#else
+void up_allocate_heap(void **heap_start, size_t *heap_size)
+#endif /* CONFIG_BUILD_KERNEL */
+{
+#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP)
+  /* Get the size and position of the user-space heap.
+   * This heap begins after the user-space .bss section.
+   */
+
+  uintptr_t ubase = (uintptr_t)USERSPACE->us_bssend;
+  size_t    usize = (uintptr_t)USERSPACE->us_heapend - ubase;
+
+  /* Return the user-space heap settings */
+
+  *heap_start = (void *)ubase;
+  *heap_size  = usize;
+
+  /* Allow user-mode access to the user heap memory in PMP
+   * is already done in qemu_rv_userspace().
+   */
+
+#else
+  /* Return the heap settings */
+
+  *heap_start = (void *)g_idle_topstack;
+  *heap_size = KRAM_END - g_idle_topstack;
+#endif /* CONFIG_BUILD_PROTECTED && CONFIG_MM_KERNEL_HEAP */
+}
+
+/****************************************************************************
+ * 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) && \
+    defined(__KERNEL__)
+void up_allocate_kheap(void **heap_start, size_t *heap_size)
+{
+  /* Return the kernel heap settings. */
+
+  *heap_start = (void *)g_idle_topstack;
+  *heap_size = KRAM_END - g_idle_topstack;
+}
+#endif /* CONFIG_BUILD_PROTECTED && CONFIG_MM_KERNEL_HEAP */
+
+/****************************************************************************
+ * Name: up_addregion
+ ****************************************************************************/
+
+void up_addregion(void)
+{
+}
diff --git a/arch/risc-v/src/qemu-rv/qemu_rv_head.S b/arch/risc-v/src/qemu-rv/qemu_rv_head.S
index 7c2bba94ca..ebfe5d1c68 100644
--- a/arch/risc-v/src/qemu-rv/qemu_rv_head.S
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_head.S
@@ -97,7 +97,11 @@ __start:
 
   /* Jump to qemu_rv_start */
 
+#ifdef CONFIG_ARCH_USE_S_MODE
+  jal  x1, qemu_rv_start_s
+#else
   jal  x1, qemu_rv_start
+#endif
 
   /* We shouldn't return from _start */
 
diff --git a/arch/risc-v/src/qemu-rv/qemu_rv_irq.c b/arch/risc-v/src/qemu-rv/qemu_rv_irq.c
index 4951ab6eab..c9ea8a94bc 100644
--- a/arch/risc-v/src/qemu-rv/qemu_rv_irq.c
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_irq.c
@@ -119,21 +119,21 @@ void up_disable_irq(int irq)
 {
   int extirq;
 
-  if (irq == RISCV_IRQ_MSOFT)
+  if (irq == RISCV_IRQ_SOFT)
     {
-      /* Read mstatus & clear machine software interrupt enable in mie */
+      /* Read m/sstatus & clear machine software interrupt enable in m/sie */
 
-      CLEAR_CSR(mie, MIE_MSIE);
+      CLEAR_CSR(CSR_IE, IE_SIE);
     }
-  else if (irq == RISCV_IRQ_MTIMER)
+  else if (irq == RISCV_IRQ_TIMER)
     {
-      /* Read mstatus & clear machine timer interrupt enable in mie */
+      /* Read m/sstatus & clear timer interrupt enable in m/sie */
 
-      CLEAR_CSR(mie, MIE_MTIE);
+      CLEAR_CSR(CSR_IE, IE_TIE);
     }
-  else if (irq > RISCV_IRQ_MEXT)
+  else if (irq > RISCV_IRQ_EXT)
     {
-      extirq = irq - RISCV_IRQ_MEXT;
+      extirq = irq - RISCV_IRQ_EXT;
 
       /* Clear enable bit for the irq */
 
@@ -161,21 +161,21 @@ void up_enable_irq(int irq)
 {
   int extirq;
 
-  if (irq == RISCV_IRQ_MSOFT)
+  if (irq == RISCV_IRQ_SOFT)
     {
-      /* Read mstatus & set machine software interrupt enable in mie */
+      /* Read m/sstatus & set machine software interrupt enable in m/sie */
 
-      SET_CSR(mie, MIE_MSIE);
+      SET_CSR(CSR_IE, IE_SIE);
     }
-  else if (irq == RISCV_IRQ_MTIMER)
+  else if (irq == RISCV_IRQ_TIMER)
     {
-      /* Read mstatus & set machine timer interrupt enable in mie */
+      /* Read m/sstatus & set timer interrupt enable in m/sie */
 
-      SET_CSR(mie, MIE_MTIE);
+      SET_CSR(CSR_IE, IE_TIE);
     }
-  else if (irq > RISCV_IRQ_MEXT)
+  else if (irq > RISCV_IRQ_EXT)
     {
-      extirq = irq - RISCV_IRQ_MEXT;
+      extirq = irq - RISCV_IRQ_EXT;
 
       /* Set enable bit for the irq */
 
@@ -195,16 +195,13 @@ irqstate_t up_irq_enable(void)
 {
   irqstate_t oldstat;
 
-#if 1
-  /* Enable MEIE (machine external interrupt enable) */
+  /* Enable external interrupts (mie/sie) */
 
-  /* TODO: should move to up_enable_irq() */
+  SET_CSR(CSR_IE, IE_EIE);
 
-  SET_CSR(mie, MIE_MEIE);
-#endif
+  /* Read and enable global interrupts (M/SIE) in m/sstatus */
 
-  /* Read mstatus & set machine interrupt enable (MIE) in mstatus */
+  oldstat = READ_AND_SET_CSR(CSR_STATUS, STATUS_IE);
 
-  oldstat = READ_AND_SET_CSR(mstatus, MSTATUS_MIE);
   return oldstat;
 }
diff --git a/arch/risc-v/src/qemu-rv/qemu_rv_irq_dispatch.c b/arch/risc-v/src/qemu-rv/qemu_rv_irq_dispatch.c
index 37037fd06c..f73f672169 100644
--- a/arch/risc-v/src/qemu-rv/qemu_rv_irq_dispatch.c
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_irq_dispatch.c
@@ -59,7 +59,7 @@ void *riscv_dispatch_irq(uintptr_t vector, uintptr_t *regs)
 
   /* Firstly, check if the irq is machine external interrupt */
 
-  if (RISCV_IRQ_MEXT == irq)
+  if (RISCV_IRQ_EXT == irq)
     {
       uintptr_t val = getreg32(QEMU_RV_PLIC_CLAIM);
 
@@ -68,20 +68,20 @@ void *riscv_dispatch_irq(uintptr_t vector, uintptr_t *regs)
       irq += val;
     }
 
-  /* MEXT means no interrupt */
+  /* EXT means no interrupt */
 
-  if (RISCV_IRQ_MEXT != irq)
+  if (RISCV_IRQ_EXT != irq)
     {
       /* Deliver the IRQ */
 
       regs = riscv_doirq(irq, regs);
     }
 
-  if (RISCV_IRQ_MEXT <= irq)
+  if (RISCV_IRQ_EXT <= irq)
     {
       /* Then write PLIC_CLAIM to clear pending in PLIC */
 
-      putreg32(irq - RISCV_IRQ_MEXT, QEMU_RV_PLIC_CLAIM);
+      putreg32(irq - RISCV_IRQ_EXT, QEMU_RV_PLIC_CLAIM);
     }
 
   return regs;
diff --git a/arch/risc-v/src/qemu-rv/qemu_rv_mm_init.c b/arch/risc-v/src/qemu-rv/qemu_rv_mm_init.c
new file mode 100644
index 0000000000..0065f9539b
--- /dev/null
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_mm_init.c
@@ -0,0 +1,171 @@
+/****************************************************************************
+ * arch/risc-v/src/qemu-rv/qemu_rv_mm_init.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/arch.h>
+
+#include <stdint.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <arch/board/board_memorymap.h>
+
+#include "qemu_rv_memorymap.h"
+
+#include "riscv_internal.h"
+#include "riscv_mmu.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Map the whole I/O memory with vaddr = paddr mappings */
+
+#define MMU_IO_BASE     (0x00000000)
+#define MMU_IO_SIZE     (0x80000000)
+
+/* Physical and virtual addresses to page tables (vaddr = paddr mapping) */
+
+#define PGT_L1_PBASE    (uintptr_t)&m_l1_pgtable
+#define PGT_L2_PBASE    (uintptr_t)&m_l2_pgtable
+#define PGT_L3_PBASE    (uintptr_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
+
+#define PGT_L1_SIZE     (512)  /* Enough to map 512 GiB */
+#define PGT_L2_SIZE     (512)  /* Enough to map 1 GiB */
+#define PGT_L3_SIZE     (1024) /* Enough to map 4 MiB (2MiB x 2) */
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Kernel mappings simply here, mapping is vaddr=paddr */
+
+static uint64_t         m_l1_pgtable[PGT_L1_SIZE] locate_data(".pgtables");
+static uint64_t         m_l2_pgtable[PGT_L2_SIZE] locate_data(".pgtables");
+static uint64_t         m_l3_pgtable[PGT_L3_SIZE] locate_data(".pgtables");
+
+/* Kernel mappings (L1 base) */
+
+uintptr_t               g_kernel_mappings  = PGT_L1_VBASE;
+uintptr_t               g_kernel_pgt_pbase = PGT_L1_PBASE;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void map_region(uintptr_t paddr, uintptr_t vaddr, size_t size,
+                       uint32_t mmuflags)
+{
+  uintptr_t l3base;
+  uintptr_t end_vaddr;
+
+  /* Start index for the L3 table, kernel flash is always first */
+
+  l3base = PGT_L3_PBASE + ((paddr - KFLASH_START) / RV_MMU_PAGE_ENTRIES);
+
+  /* Map the region to the L3 table as a whole */
+
+  mmu_ln_map_region(3, l3base, paddr, vaddr, size, mmuflags);
+
+  /* Connect to L2 table */
+
+  end_vaddr = vaddr + size;
+  while (vaddr < end_vaddr)
+    {
+      mmu_ln_setentry(2, PGT_L2_VBASE, l3base, vaddr, PTE_G);
+      l3base += RV_MMU_L3_PAGE_SIZE;
+      vaddr += RV_MMU_L2_PAGE_SIZE;
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: qemu_rv_kernel_mappings
+ *
+ * Description:
+ *  Setup kernel mappings when usinc CONFIG_BUILD_KERNEL. Sets up the kernel
+ *  MMU mappings.
+ *
+ ****************************************************************************/
+
+void qemu_rv_kernel_mappings(void)
+{
+  /* Begin mapping memory to MMU; note that at this point the MMU is not yet
+   * active, so the page table virtual addresses are actually physical
+   * addresses and so forth. M-mode does not perform translations anyhow, so
+   * this mapping is quite simple to do
+   */
+
+  /* Map I/O region, use 2 L1 entries (i.e. 2 * 1GB address space) */
+
+  binfo("map I/O regions\n");
+  mmu_ln_map_region(1, PGT_L1_VBASE, MMU_IO_BASE, MMU_IO_BASE,
+                    MMU_IO_SIZE, MMU_IO_FLAGS);
+
+  /* Map the kernel text and data for L2/L3 */
+
+  binfo("map kernel text\n");
+  map_region(KFLASH_START, KFLASH_START, KFLASH_SIZE, MMU_KTEXT_FLAGS);
+
+  binfo("map kernel data\n");
+  map_region(KSRAM_START, KSRAM_START, KSRAM_SIZE, MMU_KDATA_FLAGS);
+
+  /* Connect the L1 and L2 page tables for the kernel text and data */
+
+  binfo("connect the L1 and L2 page tables\n");
+  mmu_ln_setentry(1, PGT_L1_VBASE, PGT_L2_PBASE, KFLASH_START, PTE_G);
+
+  /* Map the page pool */
+
+  binfo("map the page pool\n");
+  mmu_ln_map_region(2, PGT_L2_VBASE, PGPOOL_START, PGPOOL_START, PGPOOL_SIZE,
+                    MMU_KDATA_FLAGS);
+}
+
+/****************************************************************************
+ * Name: qemu_rv_mm_init
+ *
+ * Description:
+ *  Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up kernel MMU
+ *  mappings. Function also sets the first address environment (satp value).
+ *
+ ****************************************************************************/
+
+void qemu_rv_mm_init(void)
+{
+  /* Setup the kernel mappings */
+
+  qemu_rv_kernel_mappings();
+
+  /* Enable MMU (note: system is still in M-mode) */
+
+  binfo("mmu_enable: satp=%lx\n", g_kernel_pgt_pbase);
+  mmu_enable(g_kernel_pgt_pbase, 0);
+}
diff --git a/arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c b/arch/risc-v/src/qemu-rv/qemu_rv_mm_init.h
similarity index 66%
copy from arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
copy to arch/risc-v/src/qemu-rv/qemu_rv_mm_init.h
index ef1d622980..3c3c7378b2 100644
--- a/arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_mm_init.h
@@ -1,5 +1,5 @@
 /****************************************************************************
- * arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
+ * arch/risc-v/src/qemu-rv/qemu_rv_mm_init.h
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -18,54 +18,41 @@
  *
  ****************************************************************************/
 
+#ifndef __ARCH_RISC_V_SRC_QEMURV_QEMURV_MM_INIT_H
+#define __ARCH_RISC_V_SRC_QEMURV_QEMURV_MM_INIT_H
+
 /****************************************************************************
  * Included Files
  ****************************************************************************/
 
 #include <nuttx/config.h>
 
-#include <assert.h>
-#include <stdint.h>
-#include <time.h>
-#include <debug.h>
-
-#include <nuttx/arch.h>
-#include <nuttx/clock.h>
-#include <nuttx/spinlock.h>
-#include <nuttx/timers/arch_alarm.h>
-#include <arch/board/board.h>
-
-#include "riscv_internal.h"
-#include "riscv_mtimer.h"
-#include "hardware/qemu_rv_memorymap.h"
-#include "hardware/qemu_rv_clint.h"
+#include "riscv_mmu.h"
 
 /****************************************************************************
- * Pre-processor Definitions
+ * Public Functions Prototypes
  ****************************************************************************/
 
-#define MTIMER_FREQ 10000000
-
 /****************************************************************************
- * Public Functions
+ * Name: qemu_rv_kernel_mappings
+ *
+ * Description:
+ *  Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up the kernel
+ *  MMU mappings.
+ *
  ****************************************************************************/
 
+void qemu_rv_kernel_mappings(void);
+
 /****************************************************************************
- * Name: up_timer_initialize
+ * Name: qemu_rv_mm_init
  *
  * Description:
- *   This function is called during start-up to initialize
- *   the timer interrupt.
+ *  Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up kernel MMU
+ *  mappings. Function also sets the first address environment (satp value).
  *
  ****************************************************************************/
 
-void up_timer_initialize(void)
-{
-  struct oneshot_lowerhalf_s *lower = riscv_mtimer_initialize(
-    QEMU_RV_CLINT_MTIME, QEMU_RV_CLINT_MTIMECMP,
-    RISCV_IRQ_MTIMER, MTIMER_FREQ);
-
-  DEBUGASSERT(lower);
+void qemu_rv_mm_init(void);
 
-  up_alarm_set_lowerhalf(lower);
-}
+#endif /* __ARCH_RISC_V_SRC_QEMURV_QEMURV_MM_INIT_H */
diff --git a/arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c b/arch/risc-v/src/qemu-rv/qemu_rv_pgalloc.c
similarity index 64%
copy from arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
copy to arch/risc-v/src/qemu-rv/qemu_rv_pgalloc.c
index ef1d622980..8b04758ac5 100644
--- a/arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_pgalloc.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
+ * arch/risc-v/src/qemu-rv/qemu_rv_pgalloc.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -22,50 +22,46 @@
  * Included Files
  ****************************************************************************/
 
+#include <nuttx/arch.h>
 #include <nuttx/config.h>
+#include <nuttx/pgalloc.h>
 
 #include <assert.h>
-#include <stdint.h>
-#include <time.h>
 #include <debug.h>
 
-#include <nuttx/arch.h>
-#include <nuttx/clock.h>
-#include <nuttx/spinlock.h>
-#include <nuttx/timers/arch_alarm.h>
-#include <arch/board/board.h>
-
-#include "riscv_internal.h"
-#include "riscv_mtimer.h"
-#include "hardware/qemu_rv_memorymap.h"
-#include "hardware/qemu_rv_clint.h"
+#include <arch/board/board_memorymap.h>
 
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
 
-#define MTIMER_FREQ 10000000
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: up_timer_initialize
+ * Name: up_allocate_pgheap
  *
  * Description:
- *   This function is called during start-up to initialize
- *   the timer interrupt.
+ *   If there is a page allocator in the configuration, then this function
+ *   must be provided by the platform-specific code.  The OS initialization
+ *   logic will call this function early in the initialization sequence to
+ *   get the page heap information needed to configure the page allocator.
  *
  ****************************************************************************/
 
-void up_timer_initialize(void)
+void up_allocate_pgheap(void **heap_start, size_t *heap_size)
 {
-  struct oneshot_lowerhalf_s *lower = riscv_mtimer_initialize(
-    QEMU_RV_CLINT_MTIME, QEMU_RV_CLINT_MTIMECMP,
-    RISCV_IRQ_MTIMER, MTIMER_FREQ);
-
-  DEBUGASSERT(lower);
+  DEBUGASSERT(heap_start && heap_size);
 
-  up_alarm_set_lowerhalf(lower);
+  *heap_start = (void *)PGPOOL_START;
+  *heap_size  = (size_t)PGPOOL_SIZE;
 }
diff --git a/arch/risc-v/src/qemu-rv/qemu_rv_start.c b/arch/risc-v/src/qemu-rv/qemu_rv_start.c
index f1a9f4e73d..57d014a612 100644
--- a/arch/risc-v/src/qemu-rv/qemu_rv_start.c
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_start.c
@@ -31,6 +31,10 @@
 #include "riscv_internal.h"
 #include "chip.h"
 
+#ifdef CONFIG_BUILD_KERNEL
+#  include "qemu_rv_mm_init.h"
+#endif
+
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
@@ -41,6 +45,10 @@
 #define showprogress(c)
 #endif
 
+#if defined (CONFIG_BUILD_KERNEL) && !defined (CONFIG_ARCH_USE_S_MODE)
+#  error "Target requires kernel in S-mode, enable CONFIG_ARCH_USE_S_MODE"
+#endif
+
 /****************************************************************************
  * Public Data
  ****************************************************************************/
@@ -91,8 +99,18 @@ void qemu_rv_start(int mhartid)
 
   /* Do board initialization */
 
+#ifdef CONFIG_ARCH_USE_S_MODE
+  /* Initialize the per CPU areas */
+
+  riscv_percpu_add_hart(mhartid);
+#endif
+
   showprogress('C');
 
+#ifdef CONFIG_BUILD_KERNEL
+  qemu_rv_mm_init();
+#endif
+
   /* Call nx_start() */
 
   nx_start();
@@ -109,6 +127,41 @@ cpux:
     }
 }
 
+#ifdef CONFIG_ARCH_USE_S_MODE
+void qemu_rv_start_s(int mhartid)
+{
+  /* Disable MMU and enable PMP */
+
+  SET_CSR(satp, 0x0);
+  SET_CSR(pmpaddr0, 0x3fffffffffffffull);
+  SET_CSR(pmpcfg0, 0xf);
+
+  /* Set exception and interrupt delegation for S-mode */
+
+  SET_CSR(medeleg, 0xffff);
+  SET_CSR(mideleg, 0xffff);
+
+  /* Allow to write satp from S-mode */
+
+  CLEAR_CSR(mstatus, MSTATUS_TVM);
+
+  /* Set mstatus to S-mode and enable SUM */
+
+  CLEAR_CSR(mstatus, ~MSTATUS_MPP_MASK);
+  SET_CSR(mstatus, MSTATUS_MPPS | SSTATUS_SUM);
+
+  /* Set the trap vector for S-mode */
+
+  extern void __trap_vec(void);
+  SET_CSR(stvec, (uintptr_t)__trap_vec);
+
+  /* Set mepc to the entry */
+
+  SET_CSR(mepc, (uintptr_t)qemu_rv_start);
+  asm volatile("mret");
+}
+#endif
+
 void riscv_serialinit(void)
 {
   up_serialinit();
diff --git a/arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c b/arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
index ef1d622980..fd594f4ca6 100644
--- a/arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
@@ -61,6 +61,7 @@
 
 void up_timer_initialize(void)
 {
+#ifndef CONFIG_BUILD_KERNEL
   struct oneshot_lowerhalf_s *lower = riscv_mtimer_initialize(
     QEMU_RV_CLINT_MTIME, QEMU_RV_CLINT_MTIMECMP,
     RISCV_IRQ_MTIMER, MTIMER_FREQ);
@@ -68,4 +69,5 @@ void up_timer_initialize(void)
   DEBUGASSERT(lower);
 
   up_alarm_set_lowerhalf(lower);
+#endif
 }