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:
Masayuki Ishikawa
2022-05-09 11:00:56 +09:00
committed by Xiang Xiao
parent 77e36d1acc
commit 3193aa3c97
13 changed files with 594 additions and 33 deletions
+6
View File
@@ -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---
+35 -1
View File
@@ -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
+8
View File
@@ -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
View File
@@ -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)
{
}
+4
View File
@@ -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 */
+20 -23
View File
@@ -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;
+171
View File
@@ -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);
}
+58
View File
@@ -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 */
+67
View File
@@ -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;
}
+53
View File
@@ -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
}