You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/04/11 17:59:41 UTC
[incubator-nuttx] 01/03: RISC-V: Combine 3 variables that depend on CPU amount into one
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit d5ea2598282fce6da8eafe4398cb03ad1719d759
Author: Ville Juven <vi...@unikie.com>
AuthorDate: Tue Apr 5 13:24:28 2022 +0300
RISC-V: Combine 3 variables that depend on CPU amount into one
IRQ_NSTACKS, ARCH_CPU_COUNT, CONFIG_SMP_NCPUS all relate to each
other. However, a bit of clean up can be done and everything can
be merged into SMP_NCPUS.
The MPFS bootloader case works also as it requires only 1 IRQ stack
for the hart that executes as bootloader.
---
arch/risc-v/Kconfig | 4 -
arch/risc-v/include/irq.h | 10 --
arch/risc-v/src/common/riscv_exception_common.S | 33 +++----
arch/risc-v/src/common/riscv_macros.S | 24 +++++
arch/risc-v/src/common/riscv_percpu.c | 102 ++++++++++++++++++---
arch/risc-v/src/common/riscv_percpu.h | 49 ++++++----
.../src/common/supervisor/riscv_dispatch_syscall.S | 14 +--
arch/risc-v/src/mpfs/Kconfig | 15 +--
arch/risc-v/src/mpfs/chip.h | 27 ++++++
9 files changed, 192 insertions(+), 86 deletions(-)
diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig
index 7eef93dd00..97c66bd56d 100644
--- a/arch/risc-v/Kconfig
+++ b/arch/risc-v/Kconfig
@@ -234,10 +234,6 @@ 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/include/irq.h b/arch/risc-v/include/irq.h
index 78799adae6..34f49dc00c 100644
--- a/arch/risc-v/include/irq.h
+++ b/arch/risc-v/include/irq.h
@@ -98,16 +98,6 @@
# 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
diff --git a/arch/risc-v/src/common/riscv_exception_common.S b/arch/risc-v/src/common/riscv_exception_common.S
index 664c235770..a088b66c41 100644
--- a/arch/risc-v/src/common/riscv_exception_common.S
+++ b/arch/risc-v/src/common/riscv_exception_common.S
@@ -28,9 +28,14 @@
#include <arch/irq.h>
#include <arch/mode.h>
+#include <sys/types.h>
+
#include "chip.h"
+
#include "riscv_macros.S"
+#include "riscv_internal.h"
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -99,27 +104,9 @@ exception_common:
#if CONFIG_ARCH_INTERRUPTSTACK > 15
- /* Offset to hartid */
-
- mv s0, a0 /* save cause */
-#ifdef CONFIG_SMP
- jal x1, riscv_mhartid /* get hartid */
-#else
- li a0, 0
-#endif
-
/* Switch to interrupt stack */
-#if IRQ_NSTACKS > 1
- li t0, (CONFIG_ARCH_INTERRUPTSTACK & ~15)
- mul t0, a0, t0
- la a0, g_intstacktop
- sub sp, a0, t0
-#else
- la sp, g_intstacktop
-#endif
-
- mv a0, s0 /* restore cause */
+ setintstack t0, t1
/* Call interrupt handler in C */
@@ -165,6 +152,10 @@ exception_common:
* Name: g_intstackalloc and g_intstacktop
****************************************************************************/
+/* Total required interrupt stack size */
+
+#define STACK_ALLOC_SIZE (CONFIG_ARCH_INTERRUPTSTACK * CONFIG_SMP_NCPUS)
+
#if CONFIG_ARCH_INTERRUPTSTACK > 15
.bss
.balign 16
@@ -173,8 +164,8 @@ exception_common:
.type g_intstackalloc, object
.type g_intstacktop, object
g_intstackalloc:
- .skip (((CONFIG_ARCH_INTERRUPTSTACK * IRQ_NSTACKS) + 8) & ~15)
+ .skip STACK_ALIGN_UP(STACK_ALLOC_SIZE)
g_intstacktop:
.size g_intstacktop, 0
- .size g_intstackalloc, ((CONFIG_ARCH_INTERRUPTSTACK * IRQ_NSTACKS) & ~15)
+ .size g_intstackalloc, STACK_ALIGN_DOWN(STACK_ALLOC_SIZE)
#endif
diff --git a/arch/risc-v/src/common/riscv_macros.S b/arch/risc-v/src/common/riscv_macros.S
index 2243698690..7a675ab262 100644
--- a/arch/risc-v/src/common/riscv_macros.S
+++ b/arch/risc-v/src/common/riscv_macros.S
@@ -29,6 +29,11 @@
#include <arch/arch.h>
#include <arch/irq.h>
+#include <sys/types.h>
+
+#include "riscv_internal.h"
+#include "riscv_percpu.h"
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -128,3 +133,22 @@
REGLOAD x31, REG_X31(\out) /* t6 */
.endm
+
+/****************************************************************************
+ * Name: setintstack
+ *
+ * Description:
+ * Set the current stack pointer to the "top" the interrupt stack. Works
+ * for single CPU case in flat mode.
+ * Must be provided by MCU-specific logic in the SMP case, or the kernel
+ * runs in supervisor mode (S-mode).
+ *
+ ****************************************************************************/
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 15
+#if !defined(CONFIG_SMP) && !defined(CONFIG_ARCH_USE_S_MODE)
+.macro setintstack tmp0, tmp1
+ la sp, g_intstacktop
+.endm
+#endif /* !defined(CONFIG_SMP) && !defined(CONFIG_ARCH_USE_S_MODE) */
+#endif /* CONFIG_ARCH_INTERRUPTSTACK > 15 */
diff --git a/arch/risc-v/src/common/riscv_percpu.c b/arch/risc-v/src/common/riscv_percpu.c
index 2b2b04d942..82c6fb0333 100644
--- a/arch/risc-v/src/common/riscv_percpu.c
+++ b/arch/risc-v/src/common/riscv_percpu.c
@@ -24,6 +24,7 @@
#include <nuttx/config.h>
#include <nuttx/irq.h>
+#include <nuttx/spinlock.h>
#include <arch/barriers.h>
#include <arch/mode.h>
@@ -31,6 +32,8 @@
#include <assert.h>
#include <stdint.h>
+#include <queue.h>
+
#include "riscv_internal.h"
#include "riscv_percpu.h"
@@ -38,41 +41,75 @@
* Pre-processor Definitions
****************************************************************************/
-#define HART_CNT (CONFIG_ARCH_CPU_COUNT)
+#define HART_CNT (CONFIG_SMP_NCPUS)
+#define STACK_SIZE (STACK_ALIGN_DOWN(CONFIG_ARCH_INTERRUPTSTACK))
-static_assert(RISCV_PERCPU_HARTID_OFFSET ==
- offsetof(struct riscv_percpu_s, hartid),
- "RISCV_PERCPU_HARTID_OFFSET with a wrong value");
+static_assert(RISCV_PERCPU_HARTID == offsetof(riscv_percpu_t, hartid),
+ "RISCV_PERCPU_HARTID offset is wrong");
+static_assert(RISCV_PERCPU_IRQSTACK == offsetof(riscv_percpu_t, irq_stack),
+ "RISCV_PERCPU_IRQSTACK offset is wrong");
/****************************************************************************
* Private Data
****************************************************************************/
-static struct riscv_percpu_s g_percpu[HART_CNT];
+static riscv_percpu_t g_percpu[HART_CNT];
+static sq_queue_t g_freelist;
+static uintptr_t g_initialized;
/****************************************************************************
- * Public Functions
+ * Private Functions
****************************************************************************/
/****************************************************************************
* Name: riscv_percpu_init
*
* Description:
- * Initialize the per CPU structures, should only be done on the boot
- * hart.
+ * Initialize the per CPU structures, the first to get here does the init.
*
****************************************************************************/
-void riscv_percpu_init(void)
+static void riscv_percpu_init(void)
{
- uintptr_t i;
+ uintptr_t i;
+ uintptr_t initialized;
+ irqstate_t flags;
+
+ /* Need to lock access during configuration */
+
+ flags = spin_lock_irqsave(NULL);
+
+ /* Initialize if not done so already */
+
+ initialized = g_initialized;
+ g_initialized = 1;
+
+ if (initialized == 1)
+ {
+ goto out_with_lock;
+ }
+
+ sq_init(&g_freelist);
for (i = 0; i < HART_CNT; i++)
{
- g_percpu[i].hartid = i;
+ /* Set interrupt stack (if any) */
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 15
+ g_percpu[i].irq_stack = (uintptr_t)&g_intstacktop - i * STACK_SIZE;
+#endif
+
+ sq_addlast((struct sq_entry_s *) &g_percpu[i], &g_freelist);
}
+
+out_with_lock:
+ spin_unlock_irqrestore(NULL, flags);
}
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
/****************************************************************************
* Name: riscv_percpu_add_hart
*
@@ -86,13 +123,27 @@ void riscv_percpu_init(void)
void riscv_percpu_add_hart(uintptr_t hartid)
{
- /* Hart IDs go from 0...4 */
+ riscv_percpu_t *percpu;
+ irqstate_t flags;
+
+ /* Make sure we are initialized */
+
+ riscv_percpu_init();
- DEBUGASSERT(hartid < HART_CNT);
+ /* Get free entry for this hart, this must not fail */
+
+ flags = spin_lock_irqsave(NULL);
+ percpu = (riscv_percpu_t *)sq_remfirst(&g_freelist);
+ spin_unlock_irqrestore(NULL, flags);
+ DEBUGASSERT(percpu);
+
+ /* Assign hartid, stack has already been assigned */
+
+ percpu->hartid = hartid;
/* Set the scratch register value to point to the scratch area */
- WRITE_CSR(CSR_SCRATCH, &g_percpu[hartid]);
+ WRITE_CSR(CSR_SCRATCH, percpu);
/* Make sure it sticks */
@@ -118,5 +169,26 @@ uintptr_t riscv_percpu_get_hartid(void)
DEBUGASSERT(scratch >= (uintptr_t) &g_percpu &&
scratch < (uintptr_t) &g_percpu + sizeof(g_percpu));
- return ((struct riscv_percpu_s *)scratch)->hartid;
+ return ((riscv_percpu_t *)scratch)->hartid;
+}
+
+/****************************************************************************
+ * Name: riscv_percpu_get_irqstack
+ *
+ * Description:
+ * Get harts own IRQ stack by reading it from the per CPU area.
+ *
+ * Returned Value:
+ * IRQ stack, or 0 if no IRQ stack is assigned
+ *
+ ****************************************************************************/
+
+uintptr_t riscv_percpu_get_irqstack(void)
+{
+ uintptr_t scratch = READ_CSR(CSR_SCRATCH);
+
+ DEBUGASSERT(scratch >= (uintptr_t) &g_percpu &&
+ scratch < (uintptr_t) &g_percpu + sizeof(g_percpu));
+
+ return ((riscv_percpu_t *)scratch)->irq_stack;
}
diff --git a/arch/risc-v/src/common/riscv_percpu.h b/arch/risc-v/src/common/riscv_percpu.h
index 76edfe6941..61e1ea66b1 100644
--- a/arch/risc-v/src/common/riscv_percpu.h
+++ b/arch/risc-v/src/common/riscv_percpu.h
@@ -38,7 +38,18 @@
* Pre-processor Definitions
****************************************************************************/
-#define RISCV_PERCPU_HARTID_OFFSET (0 * INT_REG_SIZE)
+/* Can be used by assembly code to access the structure, example:
+ *
+ * Get percpu structure:
+ * 1: csrr a0, CSR_SCRATCH
+ *
+ * Get hartid:
+ * 2: REGLOAD a0, RISCV_PERCPU_HARTID(a0)
+ */
+
+#define RISCV_PERCPU_LIST (0 * INT_REG_SIZE)
+#define RISCV_PERCPU_HARTID (1 * INT_REG_SIZE)
+#define RISCV_PERCPU_IRQSTACK (2 * INT_REG_SIZE)
#ifndef __ASSEMBLY__
@@ -46,32 +57,25 @@
* 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
+/* Per CPU save area. Access to this structure can be gained via the scratch
+ * ([m/s]scratch) 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
+ * will set up [m/s]scratch to point to the CPUs own area
*/
struct riscv_percpu_s
{
- uintptr_t hartid; /* Hart ID */
+ struct riscv_percpu_s *next; /* For sl list linkage */
+ uintptr_t hartid; /* Hart ID */
+ uintptr_t irq_stack; /* Interrupt stack */
};
+typedef struct riscv_percpu_s riscv_percpu_t;
+
/****************************************************************************
* 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_add_hart
*
@@ -99,5 +103,18 @@ void riscv_percpu_add_hart(uintptr_t hartid);
uintptr_t riscv_percpu_get_hartid(void);
+/****************************************************************************
+ * Name: riscv_percpu_get_irqstack
+ *
+ * Description:
+ * Get harts own IRQ stack by reading it from the per CPU area.
+ *
+ * Returned Value:
+ * IRQ stack, or 0 if no IRQ stack is assigned
+ *
+ ****************************************************************************/
+
+uintptr_t riscv_percpu_get_irqstack(void);
+
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_RISC_V_SRC_COMMON_RISCV_PERCPU_H */
diff --git a/arch/risc-v/src/common/supervisor/riscv_dispatch_syscall.S b/arch/risc-v/src/common/supervisor/riscv_dispatch_syscall.S
index 791048e3be..d4322eed40 100644
--- a/arch/risc-v/src/common/supervisor/riscv_dispatch_syscall.S
+++ b/arch/risc-v/src/common/supervisor/riscv_dispatch_syscall.S
@@ -27,6 +27,8 @@
#include <nuttx/config.h>
#include <arch/mode.h>
+#include "chip.h"
+
#include "riscv_macros.S"
/****************************************************************************
@@ -96,18 +98,10 @@ riscv_dispatch_syscall:
mv a0, sp /* a0 = context */
+#if CONFIG_ARCH_INTERRUPTSTACK > 15
/* 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
+ setintstack t0, t1
#endif
/* Run the handler */
diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig
index 14898d3045..d269a8b828 100755
--- a/arch/risc-v/src/mpfs/Kconfig
+++ b/arch/risc-v/src/mpfs/Kconfig
@@ -46,17 +46,12 @@ config MPFS_BOOTLOADER
---help---
This NuttX image is used as a bootloader, which will boot only on one hart, putting the others in WFI
-config IRQ_NSTACKS
- int
- depends on MPFS_BOOTLOADER
- default 5
-
config MPFS_OPENSBI
- bool "Use OpenSBI"
- depends on MPFS_BOOTLOADER && OPENSBI
- default n
- ---help---
- This uses a ld-envm-opensbi.script linker script and the mpfs_opensbi.c code to use external OpenSBI.
+ bool "Use OpenSBI"
+ depends on MPFS_BOOTLOADER && OPENSBI
+ default n
+ ---help---
+ This uses a ld-envm-opensbi.script linker script and the mpfs_opensbi.c code to use external OpenSBI.
config MPFS_HART0_SBI
bool "HART0 boots via SBI"
diff --git a/arch/risc-v/src/mpfs/chip.h b/arch/risc-v/src/mpfs/chip.h
index 960c76b8f2..6c9d32e1ff 100755
--- a/arch/risc-v/src/mpfs/chip.h
+++ b/arch/risc-v/src/mpfs/chip.h
@@ -29,4 +29,31 @@
#include "mpfs_memorymap.h"
+#include "riscv_percpu.h"
+
+/****************************************************************************
+ * Macro Definitions
+ ****************************************************************************/
+
+#ifdef __ASSEMBLY__
+
+/****************************************************************************
+ * Name: setintstack
+ *
+ * Description:
+ * Set the current stack pointer to the "top" the correct interrupt stack
+ * for the current CPU.
+ *
+ ****************************************************************************/
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 15
+#if defined(CONFIG_SMP) || defined(CONFIG_ARCH_USE_S_MODE)
+.macro setintstack tmp0, tmp1
+ csrr \tmp0, CSR_SCRATCH
+ REGLOAD sp, RISCV_PERCPU_IRQSTACK(\tmp0)
+.endm
+#endif /* defined(CONFIG_SMP) || defined(CONFIG_ARCH_USE_S_MODE) */
+#endif /* CONFIG_ARCH_INTERRUPTSTACK > 15 */
+
+#endif /* __ASSEMBLY__ */
#endif /* __ARCH_RISCV_SRC_MPFS_CHIP_H */