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:50 UTC
[incubator-nuttx] branch master updated (c37474b -> 71ced1f)
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.
from c37474b risc-v/esp32c3: Fix regression on IRQ handling for ECALL instruction
new c15b670 RISC-V: Implement option to run NuttX in supervisor mode (S-mode)
new 71ced1f RISC-V: Implement skeleton for a per CPU structure
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
arch/risc-v/Kconfig | 26 ++++
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 | 10 ++
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 +++++++
.../bl602_systemreset.c => common/riscv_percpu.c} | 83 ++++++------
.../src/common/riscv_percpu.h} | 88 ++++++------
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 +-
.../risc-v/src/common/supervisor}/Make.defs | 17 +--
.../riscv_perform_syscall.c} | 45 ++++---
.../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 +
33 files changed, 775 insertions(+), 303 deletions(-)
create mode 100644 arch/risc-v/include/mode.h
create mode 100644 arch/risc-v/src/common/riscv_exception_macros.S
copy arch/risc-v/src/{bl602/bl602_systemreset.c => common/riscv_percpu.c} (63%)
copy arch/{arm/src/stm32/stm32_fdcan.h => risc-v/src/common/riscv_percpu.h} (64%)
copy {drivers/crypto => arch/risc-v/src/common/supervisor}/Make.defs (74%)
copy arch/risc-v/src/common/{addrenv.h => supervisor/riscv_perform_syscall.c} (65%)
create mode 100644 arch/risc-v/src/common/supervisor/riscv_syscall_dispatch.S
[incubator-nuttx] 01/02: RISC-V: Implement option to run NuttX in supervisor mode (S-mode)
Posted by ac...@apache.org.
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
****************************************************************************/
[incubator-nuttx] 02/02: RISC-V: Implement skeleton for a per CPU structure
Posted by ac...@apache.org.
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 71ced1f1a98dc7cef31043c76efd61778ed47b62
Author: Ville Juven <vi...@unikie.com>
AuthorDate: Tue Mar 29 16:37:19 2022 +0300
RISC-V: Implement skeleton for a per CPU structure
It might be useful to store things in memory per CPU. The tricky part
is that all CPUs run the same code and see the same memory, so some
kind of centralized access is required.
For now, the structure contains the hart id.
Access to the structure elements is provided via sscratch, which is
unique for every hart!
---
arch/risc-v/Kconfig | 4 +
arch/risc-v/src/common/riscv_cpuindex.c | 3 +-
.../common/{riscv_cpuindex.c => riscv_percpu.c} | 89 ++++++++++++------
arch/risc-v/src/common/riscv_percpu.h | 104 +++++++++++++++++++++
4 files changed, 171 insertions(+), 29 deletions(-)
diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig
index 97c66bd..7eef93d 100644
--- a/arch/risc-v/Kconfig
+++ b/arch/risc-v/Kconfig
@@ -234,6 +234,10 @@ config ARCH_MPU_HAS_NAPOT
bool "PMP supports NAPOT"
default y if !PMP_HAS_LIMITED_FEATURES
+config ARCH_CPU_COUNT
+ int "Amount of CPUs in SoC"
+ default 5 if ARCH_CHIP_MPFS
+
source "arch/risc-v/src/opensbi/Kconfig"
source "arch/risc-v/src/common/Kconfig"
diff --git a/arch/risc-v/src/common/riscv_cpuindex.c b/arch/risc-v/src/common/riscv_cpuindex.c
index fe49065..5f06c2c 100644
--- a/arch/risc-v/src/common/riscv_cpuindex.c
+++ b/arch/risc-v/src/common/riscv_cpuindex.c
@@ -30,6 +30,7 @@
#include <nuttx/irq.h>
#include "riscv_internal.h"
+#include "riscv_percpu.h"
/****************************************************************************
* Public Functions
@@ -51,7 +52,7 @@ uintptr_t riscv_mhartid(void)
#ifdef CONFIG_ARCH_USE_S_MODE
/* Kernel is in S-mode */
-#error "Missing functionality..."
+ return riscv_percpu_get_hartid();
#else
/* Kernel is in M-mode */
diff --git a/arch/risc-v/src/common/riscv_cpuindex.c b/arch/risc-v/src/common/riscv_percpu.c
similarity index 51%
copy from arch/risc-v/src/common/riscv_cpuindex.c
copy to arch/risc-v/src/common/riscv_percpu.c
index fe49065..25e4ef9 100644
--- a/arch/risc-v/src/common/riscv_cpuindex.c
+++ b/arch/risc-v/src/common/riscv_percpu.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * arch/risc-v/src/common/riscv_cpuindex.c
+ * arch/risc-v/src/common/riscv_percpu.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -23,62 +23,95 @@
****************************************************************************/
#include <nuttx/config.h>
+#include <nuttx/irq.h>
-#include <stdint.h>
+#include <arch/barriers.h>
-#include <nuttx/arch.h>
-#include <nuttx/irq.h>
+#include <assert.h>
+#include <stdint.h>
#include "riscv_internal.h"
+#include "riscv_percpu.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define HART_CNT (CONFIG_ARCH_CPU_COUNT)
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct riscv_percpu_s g_scratch[HART_CNT];
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
- * Name: riscv_mhartid
+ * Name: riscv_percpu_init
*
* Description:
- * Context aware way to query hart id
+ * Initialize the per CPU structures, should only be done on the boot
+ * hart.
*
- * Returned Value:
- * Hart id
+ ****************************************************************************/
+
+void riscv_percpu_init(void)
+{
+ int i;
+
+ for (i = 0; i < HART_CNT; i++)
+ {
+ g_scratch[i].hartid = i;
+ }
+}
+
+/****************************************************************************
+ * Name: riscv_percpu_get_addr
+ *
+ * Description:
+ * Get add a hart to the per CPU area
+ *
+ * Input Parameters:
+ * hartid - Hart number
*
****************************************************************************/
-uintptr_t riscv_mhartid(void)
+void riscv_percpu_add_hart(uintptr_t hartid)
{
-#ifdef CONFIG_ARCH_USE_S_MODE
- /* Kernel is in S-mode */
+ /* Hart IDs go from 0...4 */
+
+ DEBUGASSERT(hartid < HART_CNT);
-#error "Missing functionality..."
+ /* Set the scratch register value to point to the scratch area */
-#else
- /* Kernel is in M-mode */
+ WRITE_CSR(sscratch, &g_scratch[hartid]);
- return READ_CSR(mhartid);
-#endif
+ /* Make sure it sticks */
+
+ __DMB();
}
/****************************************************************************
- * Name: up_cpu_index
+ * Name: riscv_percpu_get_hartid
*
* Description:
- * Return an index in the range of 0 through (CONFIG_SMP_NCPUS-1) that
- * corresponds to the currently executing CPU.
- *
- * Input Parameters:
- * None
+ * Get harts own hartid by reading it from the per CPU area. This is safe
+ * to use from lower privilege modes (than M-mode).
*
* Returned Value:
- * An integer index in the range of 0 through (CONFIG_SMP_NCPUS-1) that
- * corresponds to the currently executing CPU.
+ * Hart id
*
****************************************************************************/
-#ifdef CONFIG_SMP
-int up_cpu_index(void)
+uintptr_t riscv_percpu_get_hartid(void)
{
- return (int)riscv_mhartid();
+ uintptr_t scratch = READ_CSR(sscratch);
+
+ DEBUGASSERT(scratch >= (uintptr_t) &g_scratch &&
+ scratch <= (uintptr_t) &g_scratch + sizeof(g_scratch));
+
+ return ((struct riscv_percpu_s *)scratch)->hartid;
}
-#endif
diff --git a/arch/risc-v/src/common/riscv_percpu.h b/arch/risc-v/src/common/riscv_percpu.h
new file mode 100644
index 0000000..ddb35a5
--- /dev/null
+++ b/arch/risc-v/src/common/riscv_percpu.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+ * arch/risc-v/src/common/riscv_percpu.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_COMMON_RISCV_PERCPU_H
+#define __ARCH_RISC_V_SRC_COMMON_RISCV_PERCPU_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <arch/irq.h>
+
+#ifndef __ASSEMBLY__
+# include <stdint.h>
+# include <nuttx/arch.h>
+#endif /* __ASSEMBLY__ */
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef __ASSEMBLY__
+#define SCRATCH_HARTID_OFFSET (0 * INT_REG_SIZE)
+#else
+#define SCRATCH_HARTID_OFFSET offsetof(riscv_percpu_s, hartid)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Per CPU save area. Access to this structure can be gained via the
+ * supervisor scratch (sscratch) register. Prior to this, every CPU that
+ * wishes to access this information must call riscv_percpu_add_hart() which
+ * will set up sscratch to point to the CPUs own area
+ */
+
+struct riscv_percpu_s
+{
+ uintptr_t hartid; /* Hart ID */
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: riscv_percpu_init
+ *
+ * Description:
+ * Initialize the per CPU structures, should only be done on the boot
+ * hart.
+ *
+ ****************************************************************************/
+
+void riscv_percpu_init(void);
+
+/****************************************************************************
+ * Name: riscv_percpu_get_addr
+ *
+ * Description:
+ * Get add a hart to the per CPU area
+ *
+ * Input Parameters:
+ * hartid - Hart number
+ *
+ ****************************************************************************/
+
+void riscv_percpu_add_hart(uintptr_t hartid);
+
+/****************************************************************************
+ * Name: riscv_percpu_get_hartid
+ *
+ * Description:
+ * Get harts own hartid by reading it from the per CPU area. This is safe
+ * to use from lower privilege modes than M-mode.
+ *
+ * Returned Value:
+ * Hart id
+ *
+ ****************************************************************************/
+
+uintptr_t riscv_percpu_get_hartid(void);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_RISC_V_SRC_COMMON_RISCV_PERCPU_H */