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:06 UTC
[incubator-nuttx] 01/02: arch: risc-v: Add MMU support for qemu-rv
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
}