arch: qemu-rv: Add M-timer handling for BUILD_KERNEL
Summary: - In RISC-V, BUILD_KERNEL uses S-mode and to use M-mode timer we need to handle it by using OpenSBI or self-implementation. - This commit adds M-timer self-implementation for BUILD_KERNEL. Impact: - qemu-rv only Testing: - Tested with rv-virt:knsh64 on qemu-6.2 Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>
This commit is contained in:
parent
34b05804b0
commit
2fa872e304
@ -30,6 +30,7 @@ CHIP_CSRCS += qemu_rv_timerisr.c qemu_rv_allocateheap.c
|
||||
|
||||
ifeq ($(CONFIG_BUILD_KERNEL),y)
|
||||
CHIP_CSRCS += qemu_rv_mm_init.c
|
||||
CMN_ASRCS += qemu_rv_exception_m.S
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MM_PGALLOC),y)
|
||||
|
105
arch/risc-v/src/qemu-rv/qemu_rv_exception_m.S
Normal file
105
arch/risc-v/src/qemu-rv/qemu_rv_exception_m.S
Normal file
@ -0,0 +1,105 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/qemu-rv/qemu_rv_exception_m.S
|
||||
*
|
||||
* 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 <arch/arch.h>
|
||||
#include <arch/irq.h>
|
||||
#include <arch/mode.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#include "riscv_macros.S"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Provide a default section for the exeception handler. */
|
||||
|
||||
#ifndef EXCEPTION_SECTION
|
||||
# define EXCEPTION_SECTION .text
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
.section .text
|
||||
.balign 8
|
||||
.global __trap_vec_m
|
||||
|
||||
/****************************************************************************
|
||||
* Name: __trap_vec_m
|
||||
*
|
||||
* Description:
|
||||
* All M-mode exceptions and interrupts will be handled from here. If
|
||||
* kernel is in S-mode delegated exceptions and interrupts are handled.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
__trap_vec_m:
|
||||
j exception_m
|
||||
|
||||
/****************************************************************************
|
||||
* Name: exception_m
|
||||
*
|
||||
* Description:
|
||||
* Handles interrupts for m-mode
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.section EXCEPTION_SECTION
|
||||
.global exception_m
|
||||
.align 8
|
||||
|
||||
exception_m:
|
||||
|
||||
/* Swap mscratch with sp */
|
||||
/* NOTE: mscratch has been set in up_mtimer_initialize() */
|
||||
|
||||
csrrw sp, mscratch, sp
|
||||
|
||||
/* Save the context */
|
||||
|
||||
save_ctx sp
|
||||
|
||||
/* Handle the mtimer interrupt */
|
||||
/* NOTE: we assume exception/interrupt only happens for mtimer */
|
||||
|
||||
jal ra, qemu_rv_mtimer_interrupt
|
||||
|
||||
/* Restore the context */
|
||||
|
||||
load_ctx sp
|
||||
|
||||
/* Swap mscratch with sp */
|
||||
|
||||
csrrw sp, mscratch, sp
|
||||
|
||||
/* Return from exception */
|
||||
|
||||
mret
|
@ -163,6 +163,14 @@ void up_enable_irq(int irq)
|
||||
|
||||
SET_CSR(CSR_IE, IE_TIE);
|
||||
}
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
else if (irq == RISCV_IRQ_MTIMER)
|
||||
{
|
||||
/* Read m/sstatus & set timer interrupt enable in m/sie */
|
||||
|
||||
SET_CSR(mie, MIE_MTIE);
|
||||
}
|
||||
#endif
|
||||
else if (irq > RISCV_IRQ_EXT)
|
||||
{
|
||||
extirq = irq - RISCV_IRQ_EXT;
|
||||
|
@ -49,6 +49,34 @@
|
||||
# error "Target requires kernel in S-mode, enable CONFIG_ARCH_USE_S_MODE"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Extern Function Declarations
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
extern void __trap_vec(void);
|
||||
extern void __trap_vec_m(void);
|
||||
extern void up_mtimer_initialize(void);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: qemu_rv_clear_bss
|
||||
****************************************************************************/
|
||||
|
||||
void qemu_rv_clear_bss(void)
|
||||
{
|
||||
uint32_t *dest;
|
||||
|
||||
/* Clear .bss. We'll do this inline (vs. calling memset) just to be
|
||||
* certain that there are no issues with the state of global variables.
|
||||
*/
|
||||
|
||||
for (dest = (uint32_t *)_sbss; dest < (uint32_t *)_ebss; )
|
||||
{
|
||||
*dest++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
@ -69,8 +97,6 @@ uintptr_t g_idle_topstack = QEMU_RV_IDLESTACK_TOP;
|
||||
|
||||
void qemu_rv_start(int mhartid)
|
||||
{
|
||||
uint32_t *dest;
|
||||
|
||||
/* Configure FPU */
|
||||
|
||||
riscv_fpuconfig();
|
||||
@ -80,14 +106,9 @@ void qemu_rv_start(int mhartid)
|
||||
goto cpux;
|
||||
}
|
||||
|
||||
/* Clear .bss. We'll do this inline (vs. calling memset) just to be
|
||||
* certain that there are no issues with the state of global variables.
|
||||
*/
|
||||
|
||||
for (dest = (uint32_t *)_sbss; dest < (uint32_t *)_ebss; )
|
||||
{
|
||||
*dest++ = 0;
|
||||
}
|
||||
#ifndef CONFIG_BUILD_KERNEL
|
||||
qemu_rv_clear_bss();
|
||||
#endif
|
||||
|
||||
showprogress('A');
|
||||
|
||||
@ -99,12 +120,6 @@ 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
|
||||
@ -116,6 +131,7 @@ void qemu_rv_start(int mhartid)
|
||||
nx_start();
|
||||
|
||||
cpux:
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
riscv_cpu_boot(mhartid);
|
||||
#endif
|
||||
@ -126,9 +142,16 @@ cpux:
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_USE_S_MODE
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
|
||||
void qemu_rv_start_s(int mhartid)
|
||||
{
|
||||
qemu_rv_clear_bss();
|
||||
|
||||
/* Initialize the per CPU areas */
|
||||
|
||||
riscv_percpu_add_hart(mhartid);
|
||||
|
||||
/* Disable MMU and enable PMP */
|
||||
|
||||
WRITE_CSR(satp, 0x0);
|
||||
@ -151,13 +174,27 @@ void qemu_rv_start_s(int mhartid)
|
||||
|
||||
/* Set the trap vector for S-mode */
|
||||
|
||||
extern void __trap_vec(void);
|
||||
WRITE_CSR(stvec, (uintptr_t)__trap_vec);
|
||||
|
||||
/* Set the trap vector for M-mode */
|
||||
|
||||
WRITE_CSR(mtvec, (uintptr_t)__trap_vec_m);
|
||||
|
||||
/* Initialize mtimer before entering to S-mode */
|
||||
|
||||
up_mtimer_initialize();
|
||||
|
||||
/* Set mepc to the entry */
|
||||
|
||||
WRITE_CSR(mepc, (uintptr_t)qemu_rv_start);
|
||||
asm volatile("mret");
|
||||
|
||||
/* Set a0 to mhartid explicitly and enter to S-mode */
|
||||
|
||||
asm volatile (
|
||||
"mv a0, %0 \n"
|
||||
"mret \n"
|
||||
:: "r" (mhartid)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include "riscv_internal.h"
|
||||
#include "riscv_mtimer.h"
|
||||
#include "riscv_percpu.h"
|
||||
#include "hardware/qemu_rv_memorymap.h"
|
||||
#include "hardware/qemu_rv_clint.h"
|
||||
|
||||
@ -45,6 +46,55 @@
|
||||
****************************************************************************/
|
||||
|
||||
#define MTIMER_FREQ 10000000
|
||||
#define TICK_COUNT (10000000 / TICK_PER_SEC)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
|
||||
/****************************************************************************
|
||||
* Name: qemu_rv_ssoft_interrupt
|
||||
*
|
||||
* Description:
|
||||
* This function is S-mode software interrupt handler to proceed
|
||||
* the OS timer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int qemu_rv_ssoft_interrupt(int irq, void *context, void *arg)
|
||||
{
|
||||
/* Cleaer Supervisor Software Interrupt */
|
||||
|
||||
CLEAR_CSR(sip, SIP_SSIP);
|
||||
|
||||
/* Proceed the OS timer */
|
||||
|
||||
nxsched_process_timer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: qemu_rv_reload_mtimecmp
|
||||
*
|
||||
* Description:
|
||||
* This function is called during start-up to initialize mtimecmp
|
||||
* for CONFIG_BUILD_KERNEL=y
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void qemu_rv_reload_mtimecmp(void)
|
||||
{
|
||||
uint64_t current;
|
||||
uint64_t next;
|
||||
|
||||
current = READ_CSR(time);
|
||||
next = current + TICK_COUNT;
|
||||
putreg64(next, QEMU_RV_CLINT_MTIMECMP);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BUILD_KERNEL */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@ -69,5 +119,64 @@ void up_timer_initialize(void)
|
||||
DEBUGASSERT(lower);
|
||||
|
||||
up_alarm_set_lowerhalf(lower);
|
||||
#else
|
||||
/* NOTE: This function is called in S-mode */
|
||||
|
||||
irq_attach(RISCV_IRQ_SSOFT, qemu_rv_ssoft_interrupt, NULL);
|
||||
up_enable_irq(RISCV_IRQ_SSOFT);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_mtimer_initialize
|
||||
*
|
||||
* Description:
|
||||
* This function is called during start-up to initialize the M-mode timer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_mtimer_initialize(void)
|
||||
{
|
||||
uintptr_t irqstacktop = riscv_percpu_get_irqstack();
|
||||
|
||||
/* Set the irq stack base to mscratch */
|
||||
|
||||
WRITE_CSR(mscratch,
|
||||
irqstacktop - STACK_ALIGN_DOWN(CONFIG_ARCH_INTERRUPTSTACK));
|
||||
|
||||
/* NOTE: we do not attach a handler for mtimer,
|
||||
* because it is handled in the exception_m directly
|
||||
*/
|
||||
|
||||
up_enable_irq(RISCV_IRQ_MTIMER);
|
||||
qemu_rv_reload_mtimecmp();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: qemu_rv_mtimer_interrupt
|
||||
*
|
||||
* Description:
|
||||
* In RISC-V with S-mode, M-mode timer must be handled in M-mode
|
||||
* This function is called from exception_m in M-mode directly
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void qemu_rv_mtimer_interrupt(void)
|
||||
{
|
||||
uint64_t current;
|
||||
uint64_t next;
|
||||
|
||||
/* Update mtimercmp */
|
||||
|
||||
current = getreg64(QEMU_RV_CLINT_MTIMECMP);
|
||||
next = current + TICK_COUNT;
|
||||
putreg64(next, QEMU_RV_CLINT_MTIMECMP);
|
||||
|
||||
/* Post Supervisor Software Interrupt */
|
||||
|
||||
SET_CSR(sip, SIP_SSIP);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BUILD_KERNEL */
|
||||
|
Loading…
Reference in New Issue
Block a user