You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2022/04/01 19:19:51 UTC
[incubator-nuttx] 01/02: RISC-V: Implement option to run NuttX in supervisor mode (S-mode)
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit c15b6701ce2bd5ed9cfb8dd9a1ab248e5acd9948
Author: Ville Juven <vi...@unikie.com>
AuthorDate: Thu Mar 17 11:20:42 2022 +0200
RISC-V: Implement option to run NuttX in supervisor mode (S-mode)
- Add config "ARCH_USE_S_MODE" which controls whether the kernel
runs in M-mode or S-mode
- Add more MSTATUS and most of the SSTATUS register definitions
- Add more MIP flags for interrupt delegation
- Add handling of interrupts from S-mode
- Add handling of FPU from S-mode
- Add new context handling functions that are not dependent on the trap
handlers / ecall
NOTE: S-mode requires a companion SW (SBI) which is not yet implemented,
thus S-mode is not usable as is, yet.
---
arch/risc-v/Kconfig | 22 +++
arch/risc-v/include/csr.h | 51 ++++++-
arch/risc-v/include/irq.h | 24 +++-
arch/risc-v/include/mode.h | 101 ++++++++++++++
arch/risc-v/include/syscall.h | 69 +++-------
arch/risc-v/src/Makefile | 6 +
arch/risc-v/src/bl602/Make.defs | 1 +
arch/risc-v/src/c906/Make.defs | 2 +-
arch/risc-v/src/common/riscv_cpuindex.c | 9 ++
arch/risc-v/src/common/riscv_exception_common.S | 142 ++++++--------------
arch/risc-v/src/common/riscv_exception_macros.S | 130 ++++++++++++++++++
arch/risc-v/src/common/riscv_fpu.S | 3 +-
arch/risc-v/src/common/riscv_getnewintctx.c | 14 +-
arch/risc-v/src/common/riscv_internal.h | 48 +++++++
arch/risc-v/src/common/riscv_schedulesigaction.c | 25 ++--
arch/risc-v/src/common/riscv_swint.c | 20 +--
arch/risc-v/src/common/riscv_vectors.S | 9 +-
arch/risc-v/src/common/supervisor/Make.defs | 28 ++++
.../riscv_perform_syscall.c} | 46 +++++--
.../src/common/supervisor/riscv_syscall_dispatch.S | 148 +++++++++++++++++++++
arch/risc-v/src/esp32c3/Make.defs | 1 +
arch/risc-v/src/fe310/Make.defs | 1 +
arch/risc-v/src/k210/Make.defs | 1 +
arch/risc-v/src/litex/Make.defs | 1 +
arch/risc-v/src/mpfs/mpfs_irq_dispatch.c | 2 +-
arch/risc-v/src/qemu-rv/Make.defs | 1 +
arch/risc-v/src/rv32m1/Make.defs | 1 +
boards/risc-v/bl602/bl602evb/src/bl602_ostest.c | 2 +
boards/risc-v/c906/smartl-c906/src/c906_ostest.c | 2 +
boards/risc-v/mpfs/common/src/mpfs_ostest.c | 2 +
boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_ostest.c | 2 +
31 files changed, 714 insertions(+), 200 deletions(-)
diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig
index 6bc640e..97c66bd 100644
--- a/arch/risc-v/Kconfig
+++ b/arch/risc-v/Kconfig
@@ -102,6 +102,7 @@ config ARCH_CHIP_MPFS
select ARCH_HAVE_RESET
select ARCH_HAVE_SPI_CS_CONTROL
select ARCH_HAVE_PWM_MULTICHAN
+ select ARCH_HAVE_S_MODE
select PMP_HAS_LIMITED_FEATURES
---help---
MicroChip Polarfire processor (RISC-V 64bit core with GCVX extensions).
@@ -189,6 +190,27 @@ config ARCH_MMU_TYPE_SV39
bool
default n
+config ARCH_HAVE_S_MODE
+ bool
+ default n
+
+# Option to run NuttX in supervisor mode. This is obviously not usable in
+# flat mode, is questionable in protected mode, but is mandatory in kernel
+# mode.
+#
+# Kernel mode requires this as M-mode uses flat addressing and the kernel
+# memory must be mapped in order to share memory between the kernel and
+# different user tasks which reside in virtual memory.
+
+config ARCH_USE_S_MODE
+ bool "Run the NuttX kernel in S-mode"
+ default n
+ depends on ARCH_HAVE_S_MODE && BUILD_KERNEL && ARCH_USE_MMU
+ ---help---
+ Most of the RISC-V implementations run in M-mode (flat addressing)
+ and/or U-mode (in case of separate kernel-/userspaces). This provides
+ an option to run the kernel in S-mode, if the target supports it.
+
# MPU has certain architecture dependent configurations, which are presented
# here. Default is that the full RISC-V PMP specification is supported.
diff --git a/arch/risc-v/include/csr.h b/arch/risc-v/include/csr.h
index 25b6316..ea17adb 100644
--- a/arch/risc-v/include/csr.h
+++ b/arch/risc-v/include/csr.h
@@ -299,13 +299,27 @@
/* In mstatus register */
+#define MSTATUS_UIE (0x1 << 0) /* User Interrupt Enable */
+#define MSTATUS_SIE (0x1 << 1) /* Supervisor Interrupt Enable */
#define MSTATUS_MIE (0x1 << 3) /* Machine Interrupt Enable */
+#define MSTATUS_SPIE (0x1 << 5) /* Supervisor Previous Interrupt Enable */
#define MSTATUS_MPIE (0x1 << 7) /* Machine Previous Interrupt Enable */
+#define MSTATUS_SPPU (0x0 << 8) /* Supervisor Previous Privilege (u-mode) */
+#define MSTATUS_SPPS (0x1 << 8) /* Supervisor Previous Privilege (s-mode) */
+#define MSTATUS_MPPU (0x0 << 11) /* Machine Previous Privilege (u-mode) */
+#define MSTATUS_MPPS (0x1 << 11) /* Machine Previous Privilege (s-mode) */
#define MSTATUS_MPPM (0x3 << 11) /* Machine Previous Privilege (m-mode) */
+#define MSTATUS_MPP_MASK (0x3 << 11)
#define MSTATUS_FS (0x3 << 13) /* Machine Floating-point Status */
#define MSTATUS_FS_INIT (0x1 << 13)
#define MSTATUS_FS_CLEAN (0x2 << 13)
#define MSTATUS_FS_DIRTY (0x3 << 13)
+#define MSTATUS_MPRV (0x1 << 17) /* Modify Privilege */
+#define MSTATUS_SUM (0x1 << 18) /* S mode access to U mode memory */
+#define MSTATUS_MXR (0x1 << 19) /* Make executable / readable */
+#define MSTATUS_TVM (0x1 << 20) /* Trap access to satp from S mode */
+#define MSTATUS_TW (0x1 << 21) /* Trap WFI instruction from S mode */
+#define MSTATUS_TSR (0x1 << 22) /* Trap supervisor return (sret) */
/* Mask of preserved bits for mstatus */
@@ -317,19 +331,50 @@
/* In mie (machine interrupt enable) register */
+#define MIE_SSIE (0x1 << 1) /* Supervisor Software Interrupt Enable */
#define MIE_MSIE (0x1 << 3) /* Machine Software Interrupt Enable */
+#define MIE_STIE (0x1 << 5) /* Supervisor Timer Interrupt Enable */
#define MIE_MTIE (0x1 << 7) /* Machine Timer Interrupt Enable */
+#define MIE_SEIE (0x1 << 9) /* Supervisor External Interrupt Enable */
#define MIE_MEIE (0x1 << 11) /* Machine External Interrupt Enable */
/* In mip (machine interrupt pending) register */
-#define MIP_MTIP (0x1 << 7)
+#define MIP_SSIP (0x1 << 1)
+#define MIP_STIP (0x1 << 5)
+#define MIP_MTIP (0x1 << 7)
+#define MIP_SEIP (0x1 << 9)
+
+/* In sstatus register (which is a view of mstatus) */
+
+#define SSTATUS_SIE MSTATUS_SIE
+#define SSTATUS_SPIE MSTATUS_SPIE
+#define SSTATUS_SPPU MSTATUS_SPPU
+#define SSTATUS_SPPS MSTATUS_SPPS
+#define SSTATUS_FS MSTATUS_FS
+#define SSTATUS_FS_INIT MSTATUS_FS_INIT
+#define SSTATUS_FS_CLEAN MSTATUS_FS_CLEAN
+#define SSTATUS_FS_DIRTY MSTATUS_FS_DIRTY
+#define SSTATUS_SUM MSTATUS_SUM
+#define SSTATUS_MXR MSTATUS_MXR
+
+/* In sie register (which is a view of mie) */
+
+#define SIE_SSIE MIE_SSIE
+#define SIE_STIE MIE_STIE
+#define SIE_SEIE MIE_SEIE
+
+/* In sip register (which is a view of mip) */
+
+#define SIP_SSIP MIP_SSIP
+#define SIP_STIP MIP_STIP
+#define SIP_SEIP MIP_SEIP
/* In pmpcfg (PMP configuration) register */
#define PMPCFG_R (1 << 0) /* readable ? */
-#define PMPCFG_W (1 << 1) /* writeable ? */
-#define PMPCFG_X (1 << 2) /* excutable ? */
+#define PMPCFG_W (1 << 1) /* writable ? */
+#define PMPCFG_X (1 << 2) /* executable ? */
#define PMPCFG_RWX_MASK (7 << 0) /* access rights mask */
#define PMPCFG_A_OFF (0 << 3) /* null region (disabled) */
#define PMPCFG_A_TOR (1 << 3) /* top of range */
diff --git a/arch/risc-v/include/irq.h b/arch/risc-v/include/irq.h
index dd97222..78799ad 100644
--- a/arch/risc-v/include/irq.h
+++ b/arch/risc-v/include/irq.h
@@ -35,8 +35,10 @@
#include <arch/types.h>
+#include <arch/arch.h>
#include <arch/csr.h>
#include <arch/chip/irq.h>
+#include <arch/mode.h>
/****************************************************************************
* Pre-processor Definitions
@@ -47,7 +49,7 @@
/* IRQ 0-15 : (exception:interrupt=0) */
#define RISCV_IRQ_IAMISALIGNED (0) /* Instruction Address Misaligned */
-#define RISCV_IRQ_IAFAULT (1) /* Instruction Address Fault */
+#define RISCV_IRQ_IAFAULT (1) /* Instruction Access Fault */
#define RISCV_IRQ_IINSTRUCTION (2) /* Illegal Instruction */
#define RISCV_IRQ_BPOINT (3) /* Break Point */
#define RISCV_IRQ_LAMISALIGNED (4) /* Load Address Misaligned */
@@ -61,7 +63,7 @@
#define RISCV_IRQ_INSTRUCTIONPF (12) /* Instruction page fault */
#define RISCV_IRQ_LOADPF (13) /* Load page fault */
#define RISCV_IRQ_RESERVED (14) /* Reserved */
-#define RISCV_IRQ_SROREPF (15) /* Store/AMO page fault */
+#define RISCV_IRQ_STOREPF (15) /* Store/AMO page fault */
#define RISCV_MAX_EXCEPTION (15)
@@ -96,6 +98,16 @@
# define CONFIG_SYS_NNEST 2
#endif
+/* Amount of interrupt stacks (amount of harts) */
+
+#ifdef CONFIG_IRQ_NSTACKS
+# define IRQ_NSTACKS CONFIG_IRQ_NSTACKS
+#elif defined CONFIG_SMP
+# define IRQ_NSTACKS CONFIG_SMP_NCPUS
+#else
+# define IRQ_NSTACKS 1
+#endif
+
/* Processor PC */
#define REG_EPC_NDX 0
@@ -469,7 +481,7 @@ struct xcpt_syscall_s
{
uintptr_t sysreturn; /* The return PC */
#ifndef CONFIG_BUILD_FLAT
- uintptr_t int_ctx; /* Interrupt context (i.e. mstatus) */
+ uintptr_t int_ctx; /* Interrupt context (i.e. m-/sstatus) */
#endif
};
#endif
@@ -577,9 +589,9 @@ static inline irqstate_t up_irq_save(void)
__asm__ __volatile__
(
- "csrrc %0, mstatus, %1\n"
+ "csrrc %0, " __XSTR(CSR_STATUS) ", %1\n"
: "=r" (flags)
- : "r"(MSTATUS_MIE)
+ : "r"(STATUS_IE)
: "memory"
);
@@ -602,7 +614,7 @@ static inline void up_irq_restore(irqstate_t flags)
{
__asm__ __volatile__
(
- "csrw mstatus, %0\n"
+ "csrw " __XSTR(CSR_STATUS) ", %0\n"
: /* no output */
: "r" (flags)
: "memory"
diff --git a/arch/risc-v/include/mode.h b/arch/risc-v/include/mode.h
new file mode 100644
index 0000000..144fd73
--- /dev/null
+++ b/arch/risc-v/include/mode.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+ * arch/risc-v/include/mode.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_RISCV_INCLUDE_MODE_H
+#define __ARCH_RISCV_INCLUDE_MODE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/irq.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_USE_S_MODE
+
+/* CSR definitions */
+
+# define CSR_STATUS sstatus /* Global status register */
+# define CSR_EPC sepc /* Exception program counter */
+# define CSR_IE sie /* Interrupt enable register */
+# define CSR_CAUSE scause /* Interrupt cause register */
+
+/* In status register */
+
+# define STATUS_IE SSTATUS_SIE /* Global interrupt enable */
+# define STATUS_PIE SSTATUS_SPIE /* Previous interrupt enable */
+# define STATUS_PPP SSTATUS_SPPS /* Previous privilege */
+# define STATUS_SUM SSTATUS_SUM /* Access to user memory */
+
+/* Interrupt bits */
+
+# define IE_EIE SIE_SEIE /* External interrupt enable */
+# define IE_SIE SIE_SSIE /* Software interrupt enable */
+# define IE_TIE SIE_STIE /* Timer interrupt enable */
+
+/* External, timer and software interrupt */
+
+# define RISCV_IRQ_EXT RISCV_IRQ_SEXT /* PLIC IRQ */
+# define RISCV_IRQ_TIMER RISCV_IRQ_STIMER /* Timer IRQ */
+# define RISCV_IRQ_SOFT RISCV_IRQ_SSOFT /* SW IRQ */
+
+/* Define return from exception */
+
+# define ERET sret
+
+#else
+
+/* CSR definitions */
+
+# define CSR_STATUS mstatus /* Global status register */
+# define CSR_EPC mepc /* Exception program counter */
+# define CSR_IE mie /* Interrupt enable register */
+# define CSR_CAUSE mcause /* Interrupt cause register */
+
+/* In status register */
+
+# define STATUS_IE MSTATUS_MIE /* Global interrupt enable */
+# define STATUS_PIE MSTATUS_MPIE /* Previous interrupt enable */
+# define STATUS_PPP MSTATUS_MPPM /* Previous privilege */
+# define STATUS_SUM 0 /* Not needed in M-mode */
+
+/* Interrupt bits */
+
+# define IE_EIE MIE_MEIE /* External interrupt enable */
+# define IE_SIE MIE_MSIE /* Software interrupt enable */
+# define IE_TIE MIE_MTIE /* Timer interrupt enable */
+
+/* External, timer and software interrupt */
+
+# define RISCV_IRQ_EXT RISCV_IRQ_MEXT /* PLIC IRQ */
+# define RISCV_IRQ_TIMER RISCV_IRQ_MTIMER /* Timer IRQ */
+# define RISCV_IRQ_SOFT RISCV_IRQ_MSOFT /* SW IRQ */
+
+/* Define return from exception */
+
+# define ERET mret
+
+#endif
+
+#endif /* __ARCH_RISCV_INCLUDE_MODE_H */
diff --git a/arch/risc-v/include/syscall.h b/arch/risc-v/include/syscall.h
index a357d1d..0a212a6 100644
--- a/arch/risc-v/include/syscall.h
+++ b/arch/risc-v/include/syscall.h
@@ -31,6 +31,8 @@
#include <nuttx/config.h>
+#include <arch/arch.h>
+
#ifndef __ASSEMBLY__
# include <stdint.h>
#endif
@@ -122,50 +124,17 @@
#define SYS_signal_handler_return (7)
#endif /* !CONFIG_BUILD_FLAT */
-/* sys_call macros **********************************************************/
-
-#ifndef __ASSEMBLY__
-
-/* Context switching system calls *******************************************/
-
-/* SYS call 0:
- *
- * int riscv_saveusercontext(uintptr_t *saveregs);
- *
- * Return:
- * 0: Normal Return
- * 1: Context Switch Return
- */
-
-#define riscv_saveusercontext(saveregs) \
- (int)sys_call1(SYS_save_context, (uintptr_t)(saveregs))
-
-/* SYS call 1:
- *
- * void riscv_fullcontextrestore(uintptr_t *restoreregs) noreturn_function;
- */
-
-#define riscv_fullcontextrestore(restoreregs) \
- sys_call1(SYS_restore_context, (uintptr_t)(restoreregs))
-
-/* SYS call 2:
- *
- * void riscv_switchcontext(uintptr_t **saveregs, uintptr_t *restoreregs);
- */
-
-#define riscv_switchcontext(saveregs, restoreregs) \
- sys_call2(SYS_switch_context, (uintptr_t)(saveregs), (uintptr_t)(restoreregs))
-
-#ifdef CONFIG_BUILD_KERNEL
-/* SYS call 3:
- *
- * void riscv_syscall_return(void);
- */
-
-#define riscv_syscall_return() sys_call0(SYS_syscall_return)
-
+#if defined (CONFIG_ARCH_USE_S_MODE) && defined (__KERNEL__)
+# define ASM_SYS_CALL \
+ " addi sp, sp, -16\n" /* Make room */ \
+ REGSTORE " ra, 0(sp)\n" /* Save ra */ \
+ " jal ra, riscv_syscall_dispatch\n" /* Dispatch (modifies ra) */ \
+ REGLOAD " ra, 0(sp)\n" /* Restore ra */ \
+ " addi sp, sp, 16\n" /* Restore sp */
+#else
+# define ASM_SYS_CALL \
+ "ecall"
#endif
-#endif /* __ASSEMBLY__ */
/****************************************************************************
* Public Types
@@ -207,7 +176,7 @@ static inline uintptr_t sys_call0(unsigned int nbr)
asm volatile
(
- "ecall"
+ ASM_SYS_CALL
:: "r"(r0)
: "memory"
);
@@ -232,7 +201,7 @@ static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1)
asm volatile
(
- "ecall"
+ ASM_SYS_CALL
:: "r"(r0), "r"(r1)
: "memory"
);
@@ -259,7 +228,7 @@ static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1,
asm volatile
(
- "ecall"
+ ASM_SYS_CALL
:: "r"(r0), "r"(r1), "r"(r2)
: "memory"
);
@@ -287,7 +256,7 @@ static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1,
asm volatile
(
- "ecall"
+ ASM_SYS_CALL
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3)
: "memory"
);
@@ -317,7 +286,7 @@ static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1,
asm volatile
(
- "ecall"
+ ASM_SYS_CALL
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)
: "memory"
);
@@ -348,7 +317,7 @@ static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1,
asm volatile
(
- "ecall"
+ ASM_SYS_CALL
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)
: "memory"
);
@@ -381,7 +350,7 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1,
asm volatile
(
- "ecall"
+ ASM_SYS_CALL
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5), "r"(r6)
: "memory"
);
diff --git a/arch/risc-v/src/Makefile b/arch/risc-v/src/Makefile
index f598c6f..ad45227 100644
--- a/arch/risc-v/src/Makefile
+++ b/arch/risc-v/src/Makefile
@@ -24,6 +24,12 @@ ifeq ($(CONFIG_OPENSBI),y)
include opensbi/Make.defs
endif
+# Kernel runs in supervisor mode or machine mode ?
+
+ifeq ($(CONFIG_ARCH_USE_S_MODE),y)
+include common/supervisor/Make.defs
+endif
+
ARCH_SRCDIR = $(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src
INCLUDES += ${shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip}
diff --git a/arch/risc-v/src/bl602/Make.defs b/arch/risc-v/src/bl602/Make.defs
index b33f44c..5f4c854 100644
--- a/arch/risc-v/src/bl602/Make.defs
+++ b/arch/risc-v/src/bl602/Make.defs
@@ -34,6 +34,7 @@ CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c
CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
CMN_CSRCS += riscv_sigdeliver.c riscv_udelay.c riscv_unblocktask.c riscv_usestack.c
CMN_CSRCS += riscv_idle.c riscv_tcbinfo.c riscv_getnewintctx.c riscv_doirq.c
+CMN_CSRCS += riscv_cpuindex.c
ifeq ($(CONFIG_SCHED_BACKTRACE),y)
CMN_CSRCS += riscv_backtrace.c
diff --git a/arch/risc-v/src/c906/Make.defs b/arch/risc-v/src/c906/Make.defs
index 889bdcb..6406e8c 100644
--- a/arch/risc-v/src/c906/Make.defs
+++ b/arch/risc-v/src/c906/Make.defs
@@ -34,7 +34,7 @@ CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c
CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
CMN_CSRCS += riscv_sigdeliver.c riscv_unblocktask.c riscv_usestack.c
CMN_CSRCS += riscv_mdelay.c riscv_idle.c riscv_doirq.c
-CMN_CSRCS += riscv_tcbinfo.c riscv_getnewintctx.c
+CMN_CSRCS += riscv_tcbinfo.c riscv_getnewintctx.c riscv_cpuindex.c
ifeq ($(CONFIG_SCHED_BACKTRACE),y)
CMN_CSRCS += riscv_backtrace.c
diff --git a/arch/risc-v/src/common/riscv_cpuindex.c b/arch/risc-v/src/common/riscv_cpuindex.c
index 45e252f..fe49065 100644
--- a/arch/risc-v/src/common/riscv_cpuindex.c
+++ b/arch/risc-v/src/common/riscv_cpuindex.c
@@ -48,7 +48,16 @@
uintptr_t riscv_mhartid(void)
{
+#ifdef CONFIG_ARCH_USE_S_MODE
+ /* Kernel is in S-mode */
+
+#error "Missing functionality..."
+
+#else
+ /* Kernel is in M-mode */
+
return READ_CSR(mhartid);
+#endif
}
/****************************************************************************
diff --git a/arch/risc-v/src/common/riscv_exception_common.S b/arch/risc-v/src/common/riscv_exception_common.S
index 3daa5ce..f0603f9 100644
--- a/arch/risc-v/src/common/riscv_exception_common.S
+++ b/arch/risc-v/src/common/riscv_exception_common.S
@@ -26,6 +26,9 @@
#include <arch/arch.h>
#include <arch/irq.h>
+#include <arch/mode.h>
+
+#include "riscv_exception_macros.S"
/****************************************************************************
* Pre-processor Definitions
@@ -50,16 +53,13 @@
* Public Symbols
****************************************************************************/
-#ifdef CONFIG_IRQ_NSTACKS
-# define IRQ_NSTACKS CONFIG_IRQ_NSTACKS
-#elif defined CONFIG_SMP
-# define IRQ_NSTACKS CONFIG_SMP_NCPUS
-#else
-# define IRQ_NSTACKS 1
-#endif
-
/****************************************************************************
* Name: exception_common
+ *
+ * Description:
+ * Handles interrupts. If kernel is in S-mode, handles delegated interrupts
+ * in S-mode interrupt handler.
+ *
****************************************************************************/
.section .text
@@ -69,48 +69,16 @@
exception_common:
addi sp, sp, -XCPTCONTEXT_SIZE
+ save_ctx sp
- REGSTORE x1, REG_X1(sp) /* ra */
-#ifdef RISCV_SAVE_GP
- REGSTORE x3, REG_X3(sp) /* gp */
-#endif
- REGSTORE x4, REG_X4(sp) /* tp */
- REGSTORE x5, REG_X5(sp) /* t0 */
- REGSTORE x6, REG_X6(sp) /* t1 */
- REGSTORE x7, REG_X7(sp) /* t2 */
- REGSTORE x8, REG_X8(sp) /* s0 */
- REGSTORE x9, REG_X9(sp) /* s1 */
- REGSTORE x10, REG_X10(sp) /* a0 */
- REGSTORE x11, REG_X11(sp) /* a1 */
- REGSTORE x12, REG_X12(sp) /* a2 */
- REGSTORE x13, REG_X13(sp) /* a3 */
- REGSTORE x14, REG_X14(sp) /* a4 */
- REGSTORE x15, REG_X15(sp) /* a5 */
- REGSTORE x16, REG_X16(sp) /* a6 */
- REGSTORE x17, REG_X17(sp) /* a7 */
- REGSTORE x18, REG_X18(sp) /* s2 */
- REGSTORE x19, REG_X19(sp) /* s3 */
- REGSTORE x20, REG_X20(sp) /* s4 */
- REGSTORE x21, REG_X21(sp) /* s5 */
- REGSTORE x22, REG_X22(sp) /* s6 */
- REGSTORE x23, REG_X23(sp) /* s7 */
- REGSTORE x24, REG_X24(sp) /* s8 */
- REGSTORE x25, REG_X25(sp) /* s9 */
- REGSTORE x26, REG_X26(sp) /* s10 */
- REGSTORE x27, REG_X27(sp) /* s11 */
- REGSTORE x28, REG_X28(sp) /* t3 */
- REGSTORE x29, REG_X29(sp) /* t4 */
- REGSTORE x30, REG_X30(sp) /* t5 */
- REGSTORE x31, REG_X31(sp) /* t6 */
-
- csrr s0, mstatus
- REGSTORE s0, REG_INT_CTX(sp) /* mstatus */
+ csrr s0, CSR_STATUS
+ REGSTORE s0, REG_INT_CTX(sp) /* status */
addi s0, sp, XCPTCONTEXT_SIZE
- REGSTORE s0, REG_X2(sp) /* original SP */
+ REGSTORE s0, REG_X2(sp) /* original SP */
- csrr s0, mepc
- REGSTORE s0, REG_EPC(sp) /* exception PC */
+ csrr s0, CSR_EPC
+ REGSTORE s0, REG_EPC(sp) /* exception PC */
#ifdef CONFIG_ARCH_FPU
mv a0, sp
@@ -119,24 +87,29 @@ exception_common:
/* Setup arg0(exception cause), arg1(context) */
- csrr a0, mcause /* exception cause */
+ csrr a0, CSR_CAUSE /* exception cause */
mv a1, sp /* context = sp */
#if CONFIG_ARCH_INTERRUPTSTACK > 15
- /* Load mhartid (cpuid) */
- csrr s0, mhartid
+ /* Offset to hartid */
+
+ mv s0, a0 /* save cause */
+ jal x1, riscv_mhartid /* get hartid */
/* Switch to interrupt stack */
+
#if IRQ_NSTACKS > 1
li t0, (CONFIG_ARCH_INTERRUPTSTACK & ~15)
- mul t0, s0, t0
- la s0, g_intstacktop
- sub sp, s0, t0
+ mul t0, a0, t0
+ la a0, g_intstacktop
+ sub sp, a0, t0
#else
la sp, g_intstacktop
#endif
+ mv a0, s0 /* restore cause */
+
/* Call interrupt handler in C */
jal x1, riscv_dispatch_irq
@@ -159,62 +132,27 @@ exception_common:
jal x1, riscv_restorefpu /* restore FPU context */
#endif
- /* If context switch is needed, return a new sp */
+ /* If context switch is needed, return a new sp */
mv sp, a0
- REGLOAD s0, REG_EPC(sp) /* restore mepc */
- csrw mepc, s0
- REGLOAD s0, REG_INT_CTX(sp) /* restore mstatus */
- csrw mstatus, s0
+ REGLOAD s0, REG_EPC(sp) /* restore sepc */
+ csrw CSR_EPC, s0
-#ifdef RISCV_SAVE_GP
- REGLOAD x3, REG_X3(sp) /* gp */
-#endif
- REGLOAD x4, REG_X4(sp) /* tp */
- REGLOAD x5, REG_X5(sp) /* t0 */
- REGLOAD x6, REG_X6(sp) /* t1 */
- REGLOAD x7, REG_X7(sp) /* t2 */
- REGLOAD x8, REG_X8(sp) /* s0 */
- REGLOAD x9, REG_X9(sp) /* s1 */
- REGLOAD x10, REG_X10(sp) /* a0 */
- REGLOAD x11, REG_X11(sp) /* a1 */
- REGLOAD x12, REG_X12(sp) /* a2 */
- REGLOAD x13, REG_X13(sp) /* a3 */
- REGLOAD x14, REG_X14(sp) /* a4 */
- REGLOAD x15, REG_X15(sp) /* a5 */
- REGLOAD x16, REG_X16(sp) /* a6 */
- REGLOAD x17, REG_X17(sp) /* a7 */
- REGLOAD x18, REG_X18(sp) /* s2 */
- REGLOAD x19, REG_X19(sp) /* s3 */
- REGLOAD x20, REG_X20(sp) /* s4 */
- REGLOAD x21, REG_X21(sp) /* s5 */
- REGLOAD x22, REG_X22(sp) /* s6 */
- REGLOAD x23, REG_X23(sp) /* s7 */
- REGLOAD x24, REG_X24(sp) /* s8 */
- REGLOAD x25, REG_X25(sp) /* s9 */
- REGLOAD x26, REG_X26(sp) /* s10 */
- REGLOAD x27, REG_X27(sp) /* s11 */
- REGLOAD x28, REG_X28(sp) /* t3 */
- REGLOAD x29, REG_X29(sp) /* t4 */
- REGLOAD x30, REG_X30(sp) /* t5 */
- REGLOAD x31, REG_X31(sp) /* t6 */
-
- REGLOAD x1, REG_X1(sp) /* ra */
-
- REGLOAD sp, REG_X2(sp) /* restore original sp */
-
- /* Return from Machine Interrupt */
-
- mret
-
-/************************************************************************************
- * Name: g_intstackalloc and g_intstacktop
- ************************************************************************************/
+ REGLOAD s0, REG_INT_CTX(sp) /* restore sstatus */
+ csrw CSR_STATUS, s0
+
+ load_ctx sp
-/************************************************************************************
+ REGLOAD sp, REG_SP(sp) /* restore original sp */
+
+ /* Return from exception */
+
+ ERET
+
+/*****************************************************************************
* Name: g_intstackalloc and g_intstacktop
- ************************************************************************************/
+ ****************************************************************************/
#if CONFIG_ARCH_INTERRUPTSTACK > 15
.bss
diff --git a/arch/risc-v/src/common/riscv_exception_macros.S b/arch/risc-v/src/common/riscv_exception_macros.S
new file mode 100644
index 0000000..d2f3291
--- /dev/null
+++ b/arch/risc-v/src/common/riscv_exception_macros.S
@@ -0,0 +1,130 @@
+/****************************************************************************
+ * arch/risc-v/src/common/supervisor/riscv_exception_macros.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.
+ *
+ ****************************************************************************/
+
+.file "riscv_exception_macros.S"
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <arch/arch.h>
+#include <arch/irq.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: save_ctx
+ *
+ * Parameter:
+ * in - Pointer to where the save is performed (e.g. sp)
+ *
+ * Description:
+ * Save the common context registers (i.e. work / temp / etc).
+ *
+ ****************************************************************************/
+
+.macro save_ctx in
+
+ REGSTORE x1, REG_X1(\in) /* ra */
+#ifdef RISCV_SAVE_GP
+ REGSTORE x3, REG_X3(\in) /* gp */
+#endif
+ REGSTORE x4, REG_X4(\in) /* tp */
+ REGSTORE x5, REG_X5(\in) /* t0 */
+ REGSTORE x6, REG_X6(\in) /* t1 */
+ REGSTORE x7, REG_X7(\in) /* t2 */
+ REGSTORE x8, REG_X8(\in) /* s0 */
+ REGSTORE x9, REG_X9(\in) /* s1 */
+ REGSTORE x10, REG_X10(\in) /* a0 */
+ REGSTORE x11, REG_X11(\in) /* a1 */
+ REGSTORE x12, REG_X12(\in) /* a2 */
+ REGSTORE x13, REG_X13(\in) /* a3 */
+ REGSTORE x14, REG_X14(\in) /* a4 */
+ REGSTORE x15, REG_X15(\in) /* a5 */
+ REGSTORE x16, REG_X16(\in) /* a6 */
+ REGSTORE x17, REG_X17(\in) /* a7 */
+ REGSTORE x18, REG_X18(\in) /* s2 */
+ REGSTORE x19, REG_X19(\in) /* s3 */
+ REGSTORE x20, REG_X20(\in) /* s4 */
+ REGSTORE x21, REG_X21(\in) /* s5 */
+ REGSTORE x22, REG_X22(\in) /* s6 */
+ REGSTORE x23, REG_X23(\in) /* s7 */
+ REGSTORE x24, REG_X24(\in) /* s8 */
+ REGSTORE x25, REG_X25(\in) /* s9 */
+ REGSTORE x26, REG_X26(\in) /* s10 */
+ REGSTORE x27, REG_X27(\in) /* s11 */
+ REGSTORE x28, REG_X28(\in) /* t3 */
+ REGSTORE x29, REG_X29(\in) /* t4 */
+ REGSTORE x30, REG_X30(\in) /* t5 */
+ REGSTORE x31, REG_X31(\in) /* t6 */
+
+.endm
+
+/****************************************************************************
+ * Name: load_ctx
+ *
+ * Parameter:
+ * out - Pointer to where the load is performed (e.g. sp)
+ *
+ * Description:
+ * Load the common context registers (i.e. work / temp / etc).
+ *
+ ****************************************************************************/
+
+.macro load_ctx out
+
+ REGLOAD x1, REG_X1(\out) /* ra */
+#ifdef RISCV_SAVE_GP
+ REGLOAD x3, REG_X3(\out) /* gp */
+#endif
+ REGLOAD x4, REG_X4(\out) /* tp */
+ REGLOAD x5, REG_X5(\out) /* t0 */
+ REGLOAD x6, REG_X6(\out) /* t1 */
+ REGLOAD x7, REG_X7(\out) /* t2 */
+ REGLOAD x8, REG_X8(\out) /* s0 */
+ REGLOAD x9, REG_X9(\out) /* s1 */
+ REGLOAD x10, REG_X10(\out) /* a0 */
+ REGLOAD x11, REG_X11(\out) /* a1 */
+ REGLOAD x12, REG_X12(\out) /* a2 */
+ REGLOAD x13, REG_X13(\out) /* a3 */
+ REGLOAD x14, REG_X14(\out) /* a4 */
+ REGLOAD x15, REG_X15(\out) /* a5 */
+ REGLOAD x16, REG_X16(\out) /* a6 */
+ REGLOAD x17, REG_X17(\out) /* a7 */
+ REGLOAD x18, REG_X18(\out) /* s2 */
+ REGLOAD x19, REG_X19(\out) /* s3 */
+ REGLOAD x20, REG_X20(\out) /* s4 */
+ REGLOAD x21, REG_X21(\out) /* s5 */
+ REGLOAD x22, REG_X22(\out) /* s6 */
+ REGLOAD x23, REG_X23(\out) /* s7 */
+ REGLOAD x24, REG_X24(\out) /* s8 */
+ REGLOAD x25, REG_X25(\out) /* s9 */
+ REGLOAD x26, REG_X26(\out) /* s10 */
+ REGLOAD x27, REG_X27(\out) /* s11 */
+ REGLOAD x28, REG_X28(\out) /* t3 */
+ REGLOAD x29, REG_X29(\out) /* t4 */
+ REGLOAD x30, REG_X30(\out) /* t5 */
+ REGLOAD x31, REG_X31(\out) /* t6 */
+
+.endm
diff --git a/arch/risc-v/src/common/riscv_fpu.S b/arch/risc-v/src/common/riscv_fpu.S
index 2d3de5b..3c29465 100644
--- a/arch/risc-v/src/common/riscv_fpu.S
+++ b/arch/risc-v/src/common/riscv_fpu.S
@@ -26,6 +26,7 @@
#include <arch/arch.h>
#include <arch/irq.h>
+#include <arch/mode.h>
#ifdef CONFIG_ARCH_FPU
@@ -74,7 +75,7 @@
riscv_fpuconfig:
li a0, FS_INITIAL
- csrs mstatus, a0
+ csrs CSR_STATUS, a0
csrwi fcsr, 0
ret
diff --git a/arch/risc-v/src/common/riscv_getnewintctx.c b/arch/risc-v/src/common/riscv_getnewintctx.c
index 6b7619a..f1fa4cf 100644
--- a/arch/risc-v/src/common/riscv_getnewintctx.c
+++ b/arch/risc-v/src/common/riscv_getnewintctx.c
@@ -32,6 +32,8 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
+#include <arch/mode.h>
+
#include "riscv_internal.h"
/****************************************************************************
@@ -48,23 +50,23 @@
uintptr_t riscv_get_newintctx(void)
{
- /* Set machine previous privilege mode to machine mode. Reegardless of
+ /* Set machine previous privilege mode to privileged mode. Regardless of
* how NuttX is configured and of what kind of thread is being started.
* That is because all threads, even user-mode threads will start in
* kernel trampoline at nxtask_start() or pthread_start().
* The thread's privileges will be dropped before transitioning to
- * user code. Also set machine previous interrupt enable.
+ * user code. Also set machine / supervisor previous interrupt enable.
*
* Mask the bits which should be preserved (from ISA spec)
*/
- uintptr_t mstatus = READ_CSR(mstatus);
+ uintptr_t status = READ_CSR(CSR_STATUS);
- mstatus &= MSTATUS_WPRI;
+ status &= MSTATUS_WPRI;
- return (mstatus | MSTATUS_MPPM | MSTATUS_MPIE
+ return (status | STATUS_PPP | STATUS_SUM | STATUS_PIE
#ifdef CONFIG_ARCH_FPU
- | MSTATUS_FS_INIT
+ | MSTATUS_FS_INIT
#endif
);
}
diff --git a/arch/risc-v/src/common/riscv_internal.h b/arch/risc-v/src/common/riscv_internal.h
index 34317d7..976a7f6 100644
--- a/arch/risc-v/src/common/riscv_internal.h
+++ b/arch/risc-v/src/common/riscv_internal.h
@@ -32,6 +32,7 @@
# include <nuttx/arch.h>
# include <sys/types.h>
# include <stdint.h>
+# include <syscall.h>
#endif
/****************************************************************************
@@ -315,6 +316,53 @@ int riscv_pause_handler(int irq, void *c, void *arg);
uintptr_t riscv_mhartid(void);
+/* If kernel runs in Supervisor mode, a system call trampoline is needed */
+
+#ifdef CONFIG_ARCH_USE_S_MODE
+void riscv_syscall_dispatch(void) noreturn_function;
+void *riscv_perform_syscall(uintptr_t *regs);
+#endif
+
+/* Context switching via system calls ***************************************/
+
+/* SYS call 0:
+ *
+ * int riscv_saveusercontext(uintptr_t *saveregs);
+ *
+ * Return:
+ * 0: Normal Return
+ * 1: Context Switch Return
+ */
+
+#define riscv_saveusercontext(saveregs) \
+ sys_call1(SYS_save_context, (uintptr_t)saveregs)
+
+/* SYS call 1:
+ *
+ * void riscv_fullcontextrestore(uintptr_t *restoreregs) noreturn_function;
+ */
+
+#define riscv_fullcontextrestore(restoreregs) \
+ sys_call1(SYS_restore_context, (uintptr_t)restoreregs)
+
+/* SYS call 2:
+ *
+ * void riscv_switchcontext(uintptr_t *saveregs, uintptr_t *restoreregs);
+ */
+
+#define riscv_switchcontext(saveregs, restoreregs) \
+ sys_call2(SYS_switch_context, (uintptr_t)saveregs, (uintptr_t)restoreregs)
+
+#ifdef CONFIG_BUILD_KERNEL
+/* SYS call 3:
+ *
+ * void riscv_syscall_return(void);
+ */
+
+#define riscv_syscall_return() sys_call0(SYS_syscall_return)
+
+#endif /* CONFIG_BUILD_KERNEL */
+
#undef EXTERN
#ifdef __cplusplus
}
diff --git a/arch/risc-v/src/common/riscv_schedulesigaction.c b/arch/risc-v/src/common/riscv_schedulesigaction.c
index e8c5eab..a68b077 100644
--- a/arch/risc-v/src/common/riscv_schedulesigaction.c
+++ b/arch/risc-v/src/common/riscv_schedulesigaction.c
@@ -146,12 +146,13 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* privileged thread mode.
*/
- tcb->xcp.sigdeliver = sigdeliver;
- CURRENT_REGS[REG_EPC] = (uintptr_t)riscv_sigdeliver;
- int_ctx = CURRENT_REGS[REG_INT_CTX];
- int_ctx &= ~MSTATUS_MPIE;
+ tcb->xcp.sigdeliver = sigdeliver;
+ CURRENT_REGS[REG_EPC] = (uintptr_t)riscv_sigdeliver;
+
+ int_ctx = CURRENT_REGS[REG_INT_CTX];
+ int_ctx &= ~STATUS_PIE;
#ifndef CONFIG_BUILD_FLAT
- int_ctx |= MSTATUS_MPPM;
+ int_ctx |= STATUS_PPP;
#endif
CURRENT_REGS[REG_INT_CTX] = int_ctx;
@@ -201,7 +202,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver;
int_ctx = tcb->xcp.regs[REG_INT_CTX];
- int_ctx &= ~MSTATUS_MPIE;
+ int_ctx &= ~STATUS_PIE;
tcb->xcp.regs[REG_INT_CTX] = int_ctx;
@@ -312,9 +313,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver;
int_ctx = tcb->xcp.regs[REG_INT_CTX];
- int_ctx &= ~MSTATUS_MPIE;
-#ifdef CONFIG_BUILD_PROTECTED
- int_ctx |= MSTATUS_MPPM;
+ int_ctx &= ~STATUS_PIE;
+#ifndef CONFIG_BUILD_FLAT
+ int_ctx |= STATUS_PPP;
#endif
tcb->xcp.regs[REG_INT_CTX] = int_ctx;
}
@@ -353,9 +354,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
CURRENT_REGS[REG_EPC] = (uintptr_t)riscv_sigdeliver;
int_ctx = CURRENT_REGS[REG_INT_CTX];
- int_ctx &= ~MSTATUS_MPIE;
+ int_ctx &= ~STATUS_PIE;
#ifndef CONFIG_BUILD_FLAT
- int_ctx |= MSTATUS_MPPM;
+ int_ctx |= STATUS_PPP;
#endif
CURRENT_REGS[REG_INT_CTX] = int_ctx;
@@ -429,7 +430,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver;
int_ctx = tcb->xcp.regs[REG_INT_CTX];
- int_ctx &= ~MSTATUS_MPIE;
+ int_ctx &= ~STATUS_PIE;
tcb->xcp.regs[REG_INT_CTX] = int_ctx;
}
diff --git a/arch/risc-v/src/common/riscv_swint.c b/arch/risc-v/src/common/riscv_swint.c
index d2955a4..c01866d 100644
--- a/arch/risc-v/src/common/riscv_swint.c
+++ b/arch/risc-v/src/common/riscv_swint.c
@@ -122,13 +122,17 @@ static void dispatch_syscall(void)
"slli a0, a0, 3\n" /* a0=Offset for the stub lookup table */
#endif
"add t0, t0, a0\n" /* t0=The address in the table */
- REGLOAD " t0, 0(t0)\n" /* t0=The address of the stub for this syscall */
+ REGLOAD " t0, 0(t0)\n" /* t0=The address of the stub for this syscall */
"jalr ra, t0\n" /* Call the stub (modifies ra) */
REGLOAD " ra, 0(sp)\n" /* Restore ra */
"addi sp, sp, " STACK_FRAME_SIZE "\n" /* Destroy the stack frame */
"mv a2, a0\n" /* a2=Save return value in a0 */
"li a0, 3\n" /* a0=SYS_syscall_return (3) */
- "ecall" /* Return from the syscall */
+#ifdef CONFIG_ARCH_USE_S_MODE
+ " j riscv_syscall_dispatch" /* Return from the syscall */
+#else
+ " ecall" /* Return from the syscall */
+#endif
);
}
#endif
@@ -332,7 +336,7 @@ int riscv_swint(int irq, void *context, void *arg)
regs[REG_A0] = regs[REG_A2]; /* argc */
regs[REG_A1] = regs[REG_A3]; /* argv */
#endif
- regs[REG_INT_CTX] &= ~MSTATUS_MPPM; /* User mode */
+ regs[REG_INT_CTX] &= ~STATUS_PPP; /* User mode */
}
break;
#endif
@@ -364,7 +368,7 @@ int riscv_swint(int irq, void *context, void *arg)
regs[REG_A0] = regs[REG_A2]; /* pthread entry */
regs[REG_A1] = regs[REG_A3]; /* arg */
- regs[REG_INT_CTX] &= ~MSTATUS_MPPM; /* User mode */
+ regs[REG_INT_CTX] &= ~STATUS_PPP; /* User mode */
}
break;
#endif
@@ -403,7 +407,7 @@ int riscv_swint(int irq, void *context, void *arg)
regs[REG_EPC] =
(uintptr_t)ARCH_DATA_RESERVE->ar_sigtramp & ~1;
#endif
- regs[REG_INT_CTX] &= ~MSTATUS_MPPM; /* User mode */
+ regs[REG_INT_CTX] &= ~STATUS_PPP; /* User mode */
/* Change the parameter ordering to match the expectation of struct
* userpace_s signal_handler.
@@ -453,7 +457,7 @@ int riscv_swint(int irq, void *context, void *arg)
DEBUGASSERT(rtcb->xcp.sigreturn != 0);
regs[REG_EPC] = rtcb->xcp.sigreturn & ~1;
- regs[REG_INT_CTX] |= MSTATUS_MPPM; /* Machine mode */
+ regs[REG_INT_CTX] |= STATUS_PPP; /* Privileged mode */
rtcb->xcp.sigreturn = 0;
@@ -501,7 +505,7 @@ int riscv_swint(int irq, void *context, void *arg)
rtcb->xcp.syscall[index].sysreturn = regs[REG_EPC];
#ifndef CONFIG_BUILD_FLAT
- rtcb->xcp.syscall[index].int_ctx = regs[REG_INT_CTX];
+ rtcb->xcp.syscall[index].int_ctx = regs[REG_INT_CTX];
#endif
rtcb->xcp.nsyscalls = index + 1;
@@ -509,7 +513,7 @@ int riscv_swint(int irq, void *context, void *arg)
regs[REG_EPC] = (uintptr_t)dispatch_syscall & ~1;
#ifndef CONFIG_BUILD_FLAT
- regs[REG_INT_CTX] |= MSTATUS_MPPM; /* Machine mode */
+ regs[REG_INT_CTX] |= STATUS_PPP; /* Privileged mode */
#endif
/* Offset A0 to account for the reserved values */
diff --git a/arch/risc-v/src/common/riscv_vectors.S b/arch/risc-v/src/common/riscv_vectors.S
index d7f0163..8f68eda 100644
--- a/arch/risc-v/src/common/riscv_vectors.S
+++ b/arch/risc-v/src/common/riscv_vectors.S
@@ -23,11 +23,16 @@
****************************************************************************/
.section .text
- .balign 4
+ .balign 8
.global __trap_vec
/****************************************************************************
- * Name: exception_common
+ * Name: __trap_vec
+ *
+ * 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:
diff --git a/arch/risc-v/src/common/supervisor/Make.defs b/arch/risc-v/src/common/supervisor/Make.defs
new file mode 100644
index 0000000..3146d4e
--- /dev/null
+++ b/arch/risc-v/src/common/supervisor/Make.defs
@@ -0,0 +1,28 @@
+############################################################################
+# arch/risc-v/src/common/supervisor/Make.defs
+#
+# 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.
+#
+############################################################################
+
+# If the NuttX kernel runs in S-mode
+
+CMN_ASRCS += riscv_syscall_dispatch.S
+CMN_CSRCS += riscv_sbi.c riscv_perform_syscall.c
+CMN_CSRCS += riscv_percpu.c
+
+INCLUDES += ${shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)common$(DELIM)supervisor}
+VPATH += common$(DELIM)supervisor
diff --git a/arch/risc-v/src/common/riscv_vectors.S b/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c
similarity index 60%
copy from arch/risc-v/src/common/riscv_vectors.S
copy to arch/risc-v/src/common/supervisor/riscv_perform_syscall.c
index d7f0163..af32ec2 100644
--- a/arch/risc-v/src/common/riscv_vectors.S
+++ b/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * arch/risc-v/src/common/riscv_vectors.S
+ * arch/risc-v/src/common/supervisor/riscv_perform_syscall.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -22,14 +22,44 @@
* Included Files
****************************************************************************/
- .section .text
- .balign 4
- .global __trap_vec
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+#include "riscv_internal.h"
+#include "group/group.h"
/****************************************************************************
- * Name: exception_common
+ * Public Functions
****************************************************************************/
-__trap_vec:
- j exception_common
- nop
+void *riscv_perform_syscall(uintptr_t *regs)
+{
+ /* Set up the interrupt register set needed by swint() */
+
+ CURRENT_REGS = regs;
+
+ /* Run the system call handler (swint) */
+
+ riscv_swint(0, regs, NULL);
+
+#ifdef CONFIG_ARCH_ADDRENV
+ if (regs != CURRENT_REGS)
+ {
+ /* Make sure that the address environment for the previously
+ * running task is closed down gracefully (data caches dump,
+ * MMU flushed) and set up the address environment for the new
+ * thread at the head of the ready-to-run list.
+ */
+
+ group_addrenv(NULL);
+ }
+#endif
+
+ /* Set new context */
+
+ regs = (uintptr_t *)CURRENT_REGS;
+ CURRENT_REGS = NULL;
+
+ return regs;
+}
diff --git a/arch/risc-v/src/common/supervisor/riscv_syscall_dispatch.S b/arch/risc-v/src/common/supervisor/riscv_syscall_dispatch.S
new file mode 100644
index 0000000..5e2fd2f
--- /dev/null
+++ b/arch/risc-v/src/common/supervisor/riscv_syscall_dispatch.S
@@ -0,0 +1,148 @@
+/****************************************************************************
+ * arch/risc-v/src/common/supervisor/riscv_syscall_dispatch.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.
+ *
+ ****************************************************************************/
+
+.file "riscv_syscall_dispatch.S"
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <arch/mode.h>
+
+#include "riscv_exception_macros.S"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Symbols
+ ****************************************************************************/
+
+ .globl riscv_syscall_dispatch
+
+/****************************************************************************
+ * Name: riscv_syscall_dispatch
+ *
+ * Description:
+ * Dispatch syscall from kernel
+ *
+ * C Function Prototype:
+ * void riscv_syscall_dispatch(void);
+ *
+ * Input Parameters:
+ * Assumes the context to return is already set up
+ *
+ * Returned Value:
+ * Return value of system call is returned into contex
+ *
+ * Assumptions:
+ * Task is running in privileged mode
+ *
+ ****************************************************************************/
+
+.type riscv_syscall_dispatch, function
+
+riscv_syscall_dispatch:
+
+ addi sp, sp, -XCPTCONTEXT_SIZE /* make room */
+ save_ctx sp /* save current context */
+
+ /* Mask interrupts and store the status register to context */
+
+ li s1, STATUS_IE /* move IE -> PIE */
+ csrrc s0, CSR_STATUS, s1
+ and s1, s0, s1 /* if (STATUS & IE) */
+ beqz s1, 1f
+ li s1, ~STATUS_IE /* clear IE */
+ and s0, s0, s1
+ li s1, STATUS_PIE /* set PIE */
+ or s0, s0, s1
+
+ 1:
+ /* Set previous privilege, we are in privileged mode now */
+
+ li s1, STATUS_PPP /* set previous privilege */
+ or s0, s0, s1
+ REGSTORE s0, REG_INT_CTX(sp) /* store status to context */
+
+ REGSTORE x1, REG_EPC(sp) /* save ra to epc */
+
+ addi s0, sp, XCPTCONTEXT_SIZE
+ REGSTORE s0, REG_SP(sp) /* original SP */
+
+#ifdef CONFIG_ARCH_FPU
+ mv a0, sp
+ jal x1, riscv_savefpu /* FP registers */
+#endif
+
+ mv a0, sp /* a0 = context */
+
+ /* Switch to interrupt stack */
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 15
+#if IRQ_NSTACKS > 1
+ jal x1, riscv_mhartid /* get hartid */
+ li t0, (CONFIG_ARCH_INTERRUPTSTACK & ~15)
+ mul t0, a0, t0
+ la a0, g_intstacktop
+ sub sp, a0, t0
+#else
+ la sp, g_intstacktop
+#endif
+#endif
+
+ /* Run the handler */
+
+ jal x1, riscv_perform_syscall
+
+ /* Restore (potentially new) context */
+
+ mv sp, a0 /* use sp, as a0 gets wiped */
+
+#ifdef CONFIG_ARCH_FPU
+ jal x1, riscv_restorefpu /* FP registers */
+#endif
+
+ REGLOAD s0, REG_EPC(sp) /* restore epc */
+ csrw CSR_EPC, s0
+
+ /* Restore status register, but don't enable interrupts yet */
+
+ REGLOAD s0, REG_INT_CTX(sp) /* restore status */
+ li s1, STATUS_IE /* move IE -> PIE */
+ and s1, s0, s1 /* if (STATUS & IE) */
+ beqz s1, 1f
+ li s1, ~STATUS_IE /* clear IE */
+ and s0, s0, s1
+ li s1, STATUS_PIE /* set PIE */
+ or s0, s0, s1
+
+1:
+ csrw CSR_STATUS, s0
+
+ load_ctx sp
+
+ REGLOAD sp, REG_SP(sp) /* restore original sp */
+
+ /* return from exception, which updates the status register */
+
+ ERET
diff --git a/arch/risc-v/src/esp32c3/Make.defs b/arch/risc-v/src/esp32c3/Make.defs
index 0161d90..74e83b5 100644
--- a/arch/risc-v/src/esp32c3/Make.defs
+++ b/arch/risc-v/src/esp32c3/Make.defs
@@ -37,6 +37,7 @@ CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c
CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
CMN_CSRCS += riscv_sigdeliver.c riscv_udelay.c riscv_unblocktask.c riscv_usestack.c
CMN_CSRCS += riscv_tcbinfo.c riscv_getnewintctx.c riscv_doirq.c
+CMN_CSRCS += riscv_cpuindex.c
ifeq ($(CONFIG_SCHED_BACKTRACE),y)
CMN_CSRCS += riscv_backtrace.c
diff --git a/arch/risc-v/src/fe310/Make.defs b/arch/risc-v/src/fe310/Make.defs
index 8ebd460..751d3ed 100644
--- a/arch/risc-v/src/fe310/Make.defs
+++ b/arch/risc-v/src/fe310/Make.defs
@@ -34,6 +34,7 @@ CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c
CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
CMN_CSRCS += riscv_sigdeliver.c riscv_udelay.c riscv_unblocktask.c riscv_usestack.c
CMN_CSRCS += riscv_idle.c riscv_tcbinfo.c riscv_getnewintctx.c riscv_doirq.c
+CMN_CSRCS += riscv_cpuindex.c
ifeq ($(CONFIG_SCHED_BACKTRACE),y)
CMN_CSRCS += riscv_backtrace.c
diff --git a/arch/risc-v/src/k210/Make.defs b/arch/risc-v/src/k210/Make.defs
index c1f3e89..df63897 100644
--- a/arch/risc-v/src/k210/Make.defs
+++ b/arch/risc-v/src/k210/Make.defs
@@ -35,6 +35,7 @@ CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
CMN_CSRCS += riscv_sigdeliver.c riscv_unblocktask.c riscv_usestack.c
CMN_CSRCS += riscv_mdelay.c riscv_idle.c riscv_doirq.c
CMN_CSRCS += riscv_tcbinfo.c riscv_cpuidlestack.c riscv_getnewintctx.c
+CMN_CSRCS += riscv_cpuindex.c
ifeq ($(CONFIG_SMP), y)
CMN_CSRCS += riscv_cpuindex.c riscv_cpupause.c riscv_cpustart.c
diff --git a/arch/risc-v/src/litex/Make.defs b/arch/risc-v/src/litex/Make.defs
index 667fe01..c9727e8 100644
--- a/arch/risc-v/src/litex/Make.defs
+++ b/arch/risc-v/src/litex/Make.defs
@@ -34,6 +34,7 @@ CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c
CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
CMN_CSRCS += riscv_sigdeliver.c riscv_udelay.c riscv_unblocktask.c riscv_usestack.c
CMN_CSRCS += riscv_idle.c riscv_tcbinfo.c riscv_getnewintctx.c
+CMN_CSRCS += riscv_cpuindex.c
ifeq ($(CONFIG_SCHED_BACKTRACE),y)
CMN_CSRCS += riscv_backtrace.c
diff --git a/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c b/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c
index 77849ff..01e471c 100755
--- a/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c
+++ b/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c
@@ -58,7 +58,7 @@ void *riscv_dispatch_irq(uintptr_t vector, uintptr_t *regs)
if (vector < RISCV_IRQ_ECALLU ||
vector == RISCV_IRQ_INSTRUCTIONPF ||
vector == RISCV_IRQ_LOADPF ||
- vector == RISCV_IRQ_SROREPF ||
+ vector == RISCV_IRQ_STOREPF ||
vector == RISCV_IRQ_RESERVED)
{
riscv_fault(irq, regs);
diff --git a/arch/risc-v/src/qemu-rv/Make.defs b/arch/risc-v/src/qemu-rv/Make.defs
index 7813400..3d2e6db 100644
--- a/arch/risc-v/src/qemu-rv/Make.defs
+++ b/arch/risc-v/src/qemu-rv/Make.defs
@@ -35,6 +35,7 @@ CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
CMN_CSRCS += riscv_sigdeliver.c riscv_unblocktask.c riscv_usestack.c
CMN_CSRCS += riscv_idle.c riscv_tcbinfo.c riscv_cpuidlestack.c
CMN_CSRCS += riscv_fault.c riscv_getnewintctx.c riscv_doirq.c
+CMN_CSRCS += riscv_cpuindex.c
ifeq ($(CONFIG_SMP), y)
CMN_CSRCS += riscv_cpuindex.c riscv_cpupause.c riscv_cpustart.c
diff --git a/arch/risc-v/src/rv32m1/Make.defs b/arch/risc-v/src/rv32m1/Make.defs
index 4adb7c4..745bae6 100644
--- a/arch/risc-v/src/rv32m1/Make.defs
+++ b/arch/risc-v/src/rv32m1/Make.defs
@@ -34,6 +34,7 @@ CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c
CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
CMN_CSRCS += riscv_sigdeliver.c riscv_unblocktask.c riscv_usestack.c
CMN_CSRCS += riscv_idle.c riscv_tcbinfo.c riscv_getnewintctx.c
+CMN_CSRCS += riscv_cpuindex.c
ifeq ($(CONFIG_SCHED_BACKTRACE),y)
CMN_CSRCS += riscv_backtrace.c
diff --git a/boards/risc-v/bl602/bl602evb/src/bl602_ostest.c b/boards/risc-v/bl602/bl602evb/src/bl602_ostest.c
index 3d3f029..bd11c4e 100644
--- a/boards/risc-v/bl602/bl602evb/src/bl602_ostest.c
+++ b/boards/risc-v/bl602/bl602evb/src/bl602_ostest.c
@@ -31,6 +31,8 @@
#include <nuttx/irq.h>
+#include "riscv_internal.h"
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
diff --git a/boards/risc-v/c906/smartl-c906/src/c906_ostest.c b/boards/risc-v/c906/smartl-c906/src/c906_ostest.c
index f3a5c8a..dd6bc11 100644
--- a/boards/risc-v/c906/smartl-c906/src/c906_ostest.c
+++ b/boards/risc-v/c906/smartl-c906/src/c906_ostest.c
@@ -31,6 +31,8 @@
#include <nuttx/irq.h>
+#include "riscv_internal.h"
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
diff --git a/boards/risc-v/mpfs/common/src/mpfs_ostest.c b/boards/risc-v/mpfs/common/src/mpfs_ostest.c
index 587b441..6b4e3db 100755
--- a/boards/risc-v/mpfs/common/src/mpfs_ostest.c
+++ b/boards/risc-v/mpfs/common/src/mpfs_ostest.c
@@ -31,6 +31,8 @@
#include <nuttx/irq.h>
+#include "riscv_internal.h"
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
diff --git a/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_ostest.c b/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_ostest.c
index d06f3e1..4fefb06 100644
--- a/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_ostest.c
+++ b/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_ostest.c
@@ -31,6 +31,8 @@
#include <nuttx/irq.h>
+#include "riscv_internal.h"
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/