You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/10/03 15:26:18 UTC
[incubator-nuttx] branch master updated: arch: qemu-rv: Add M-timer handling for BUILD_KERNEL
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 2fa872e304 arch: qemu-rv: Add M-timer handling for BUILD_KERNEL
2fa872e304 is described below
commit 2fa872e304bf2360638ce46fbc7ec1534ead4ce4
Author: Masayuki Ishikawa <ma...@gmail.com>
AuthorDate: Mon Oct 3 12:15:01 2022 +0900
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 <Ma...@jp.sony.com>
---
arch/risc-v/src/qemu-rv/Make.defs | 1 +
.../{qemu_rv_timerisr.c => qemu_rv_exception_m.S} | 90 +++++++++++------
arch/risc-v/src/qemu-rv/qemu_rv_irq.c | 8 ++
arch/risc-v/src/qemu-rv/qemu_rv_start.c | 75 ++++++++++----
arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c | 109 +++++++++++++++++++++
5 files changed, 235 insertions(+), 48 deletions(-)
diff --git a/arch/risc-v/src/qemu-rv/Make.defs b/arch/risc-v/src/qemu-rv/Make.defs
index 3033111cc3..3c5982a8b0 100644
--- a/arch/risc-v/src/qemu-rv/Make.defs
+++ b/arch/risc-v/src/qemu-rv/Make.defs
@@ -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)
diff --git a/arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c b/arch/risc-v/src/qemu-rv/qemu_rv_exception_m.S
similarity index 55%
copy from arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
copy to arch/risc-v/src/qemu-rv/qemu_rv_exception_m.S
index fd594f4ca6..3d6a0fcc75 100644
--- a/arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_exception_m.S
@@ -1,5 +1,5 @@
/****************************************************************************
- * arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
+ * 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
@@ -24,50 +24,82 @@
#include <nuttx/config.h>
-#include <assert.h>
-#include <stdint.h>
-#include <time.h>
-#include <debug.h>
+#include <arch/arch.h>
+#include <arch/irq.h>
+#include <arch/mode.h>
-#include <nuttx/arch.h>
-#include <nuttx/clock.h>
-#include <nuttx/spinlock.h>
-#include <nuttx/timers/arch_alarm.h>
-#include <arch/board/board.h>
+#include <sys/types.h>
-#include "riscv_internal.h"
-#include "riscv_mtimer.h"
-#include "hardware/qemu_rv_memorymap.h"
-#include "hardware/qemu_rv_clint.h"
+#include "chip.h"
+
+#include "riscv_macros.S"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
-#define MTIMER_FREQ 10000000
+/* 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
/****************************************************************************
- * Public Functions
+ * 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: up_timer_initialize
+ * Name: exception_m
*
* Description:
- * This function is called during start-up to initialize
- * the timer interrupt.
+ * Handles interrupts for m-mode
*
****************************************************************************/
-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);
+.section EXCEPTION_SECTION
+.global exception_m
+.align 8
- DEBUGASSERT(lower);
+exception_m:
- up_alarm_set_lowerhalf(lower);
-#endif
-}
+ /* 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
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 424ec2fef3..6cdffcbb2c 100644
--- a/arch/risc-v/src/qemu-rv/qemu_rv_irq.c
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_irq.c
@@ -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;
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 d9aacda827..f88ed108fa 100644
--- a/arch/risc-v/src/qemu-rv/qemu_rv_start.c
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_start.c
@@ -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
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 fd594f4ca6..2e8e0a6f61 100644
--- a/arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_timerisr.c
@@ -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 */