mirror of
https://github.com/apache/nuttx.git
synced 2026-05-23 23:28:29 +08:00
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 <Masayuki.Ishikawa@jp.sony.com>
This commit is contained in:
committed by
Xiang Xiao
parent
77e36d1acc
commit
3193aa3c97
@@ -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---
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
+147
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/****************************************************************************
|
||||
* 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
|
||||
* 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_QEMURV_QEMURV_MM_INIT_H
|
||||
#define __ARCH_RISC_V_SRC_QEMURV_QEMURV_MM_INIT_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "riscv_mmu.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* 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: 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);
|
||||
|
||||
#endif /* __ARCH_RISC_V_SRC_QEMURV_QEMURV_MM_INIT_H */
|
||||
@@ -0,0 +1,67 @@
|
||||
/****************************************************************************
|
||||
* 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
|
||||
* 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/arch.h>
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/pgalloc.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <arch/board/board_memorymap.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_allocate_pgheap
|
||||
*
|
||||
* Description:
|
||||
* 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_allocate_pgheap(void **heap_start, size_t *heap_size)
|
||||
{
|
||||
DEBUGASSERT(heap_start && heap_size);
|
||||
|
||||
*heap_start = (void *)PGPOOL_START;
|
||||
*heap_size = (size_t)PGPOOL_SIZE;
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user