diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index 82a4b649b0a..025e186d97d 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 74fc60a9038..e48c85fcc86 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 3d8d05d75f3..f8f78fbe516 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 7c010dd90b0..eac61f8fd1c 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 + /**************************************************************************** * 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 00000000000..bf61de105b6 --- /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 + +#include +#include + +#include + +#ifdef CONFIG_MM_KERNEL_HEAP +#include +#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 7c2bba94caa..ebfe5d1c68c 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 4951ab6eab1..c9ea8a94bcb 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 37037fd06c3..f73f6721695 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 00000000000..0065f9539b9 --- /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 +#include + +#include +#include +#include + +#include + +#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_mm_init.h b/arch/risc-v/src/qemu-rv/qemu_rv_mm_init.h new file mode 100644 index 00000000000..3c3c7378b26 --- /dev/null +++ b/arch/risc-v/src/qemu-rv/qemu_rv_mm_init.h @@ -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 + +#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 */ diff --git a/arch/risc-v/src/qemu-rv/qemu_rv_pgalloc.c b/arch/risc-v/src/qemu-rv/qemu_rv_pgalloc.c new file mode 100644 index 00000000000..8b04758ac5f --- /dev/null +++ b/arch/risc-v/src/qemu-rv/qemu_rv_pgalloc.c @@ -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 +#include +#include + +#include +#include + +#include + +/**************************************************************************** + * 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; +} 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 f1a9f4e73d7..57d014a6123 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 ef1d6229804..fd594f4ca6c 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 }