arch/riscv: Implement cpuid mapping

Implement hartid<->cpuid mapping for RISC-V. This is necessary for some
platforms which cannot use 1:1 mapping between logical and physical CPU /
core IDs. One example is MPFS where hart0 cannot be used for NuttX SMP as
it is a less capable "monitor" core (E51) compared to the application
cores hart1...3 (E54).

Why not just use a generic offset then? We also need the physical hart ID
for many things:
- Communication between harts (IPI)
- External interrupt acknowledgment (interrupt claim for specific CPU)
- Communication to SBI

Thus, create procedures that can do this translation:
- The default mapping is still logical=physical.
- Another flavor is to use the existing CONFIG_ARCH_RV_HARTID_BASE config
  variable, which is just a simple offset
- The final flavor is to overload hartid<->cpuid on a per chip basis (no
  example for this is provided yet)
This commit is contained in:
Ville Juven 2024-10-15 15:57:29 +03:00 committed by Xiang Xiao
parent 2195b47655
commit 737dc4fcdd
6 changed files with 83 additions and 7 deletions

View file

@ -95,6 +95,7 @@ config ARCH_RISCV
select ARCH_HAVE_THREAD_LOCAL
select ARCH_HAVE_POWEROFF
select ARCH_HAVE_LAZYFPU if ARCH_HAVE_FPU
select ARCH_HAVE_CPUID_MAPPING if ARCH_HAVE_MULTICPU
---help---
RISC-V 32 and 64-bit RV32 / RV64 architectures.

View file

@ -709,6 +709,17 @@ irqstate_t up_irq_enable(void);
int up_cpu_index(void) noinstrument_function;
#endif /* CONFIG_ARCH_HAVE_MULTICPU */
/****************************************************************************
* Name: up_this_cpu
*
* Description:
* Return the logical core number. Default implementation is 1:1 mapping,
* i.e. physical=logical.
*
****************************************************************************/
int up_this_cpu(void);
/****************************************************************************
* Inline Functions
****************************************************************************/
@ -716,7 +727,7 @@ int up_cpu_index(void) noinstrument_function;
static inline_function uintreg_t *up_current_regs(void)
{
#ifdef CONFIG_SMP
return (uintreg_t *)g_current_regs[up_cpu_index()];
return (uintreg_t *)g_current_regs[up_this_cpu()];
#else
return (uintreg_t *)g_current_regs[0];
#endif
@ -725,7 +736,7 @@ static inline_function uintreg_t *up_current_regs(void)
static inline_function void up_set_current_regs(uintreg_t *regs)
{
#ifdef CONFIG_SMP
g_current_regs[up_cpu_index()] = regs;
g_current_regs[up_this_cpu()] = regs;
#else
g_current_regs[0] = regs;
#endif

View file

@ -45,5 +45,47 @@
int up_cpu_index(void)
{
return (int)riscv_mhartid() - CONFIG_ARCH_RV_HARTID_BASE;
return (int)riscv_mhartid();
}
/****************************************************************************
* Name: up_this_cpu
*
* Description:
* Return the logical core number. Default implementation is 1:1 mapping,
* i.e. physical=logical.
*
****************************************************************************/
int up_this_cpu(void)
{
return riscv_hartid_to_cpuid((int)riscv_mhartid());
}
/****************************************************************************
* Name: riscv_hartid_to_cpuid
*
* Description:
* Convert physical core number to logical core number. Default
* implementation is 1:1 mapping, i.e. physical=logical.
*
****************************************************************************/
int weak_function riscv_hartid_to_cpuid(int cpu)
{
return cpu + CONFIG_ARCH_RV_HARTID_BASE;
}
/****************************************************************************
* Name: riscv_cpuid_to_hartid
*
* Description:
* Convert logical core number to physical core number. Default
* implementation is 1:1 mapping, i.e. physical=logical.
*
****************************************************************************/
int weak_function riscv_cpuid_to_hartid(int cpu)
{
return cpu - CONFIG_ARCH_RV_HARTID_BASE;
}

View file

@ -86,7 +86,7 @@ void riscv_cpu_boot(int cpu)
#ifdef CONFIG_RISCV_PERCPU_SCRATCH
/* Initialize the per CPU areas */
riscv_percpu_add_hart((uintptr_t)cpu);
riscv_percpu_add_hart(riscv_cpuid_to_hartid(cpu));
#endif
#ifdef CONFIG_BUILD_KERNEL

View file

@ -427,6 +427,28 @@ int riscv_smp_call_handler(int irq, void *c, void *arg);
uintptr_t riscv_mhartid(void);
/****************************************************************************
* Name: riscv_hartid_to_cpuid
*
* Description:
* Convert physical core number to logical core number. Default
* implementation is 1:1 mapping, i.e. physical=logical.
*
****************************************************************************/
int riscv_hartid_to_cpuid(int cpu);
/****************************************************************************
* Name: riscv_cpuid_to_hartid
*
* Description:
* Convert logical core number to physical core number. Default
* implementation is 1:1 mapping, i.e. physical=logical.
*
****************************************************************************/
int riscv_cpuid_to_hartid(int cpu);
/* If kernel runs in Supervisor mode, a system call trampoline is needed */
#ifdef CONFIG_ARCH_USE_S_MODE

View file

@ -36,9 +36,9 @@
static inline void riscv_ipi_send(int cpu)
{
#if defined(CONFIG_ARCH_USE_S_MODE)
riscv_sbi_send_ipi(0x1, cpu);
riscv_sbi_send_ipi(0x1, riscv_cpuid_to_hartid(cpu));
#elif defined(RISCV_IPI)
putreg32(1, (uintptr_t)RISCV_IPI + (4 * cpu));
putreg32(1, (uintptr_t)RISCV_IPI + (4 * riscv_cpuid_to_hartid(cpu)));
#else
# error "No IPI support for this SoC"
#endif
@ -47,7 +47,7 @@ static inline void riscv_ipi_send(int cpu)
static inline void riscv_ipi_clear(int cpu)
{
#if defined(RISCV_IPI) && !defined(CONFIG_ARCH_USE_S_MODE)
putreg32(0, (uintptr_t)RISCV_IPI + (4 * cpu));
putreg32(0, (uintptr_t)RISCV_IPI + (4 * riscv_cpuid_to_hartid(cpu)));
#endif
CLEAR_CSR(CSR_IP, IP_SIP);
}