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.
This commit is contained in:
parent
bb6279fe60
commit
d5ea259828
@ -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"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
DEBUGASSERT(hartid < HART_CNT);
|
||||
/* Make sure we are initialized */
|
||||
|
||||
riscv_percpu_init();
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user