arch/risc-v: Make CPU index handling based on ARCH_RV_CPUID_MAP

This patch refactors the CPU index handling in the RISC-V architecture to be based on the ARCH_RV_CPUID_MAP configuration.

Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
This commit is contained in:
Huang Qi 2024-12-31 19:05:48 +08:00 committed by Ville Juven
parent cd83dc1317
commit 40bd8f9ad4
6 changed files with 75 additions and 47 deletions

View file

@ -461,19 +461,50 @@ config ARCH_RV_MMIO_BITS
default 32 if ARCH_RV32
default 64 if ARCH_RV64
config ARCH_RV_CPUID_MAP
bool "Enable CPUID mapping"
default n
---help---
Enable CPUID mapping for systems where the hardware CPU IDs
need to be mapped to logical CPU IDs. This is useful for
systems with non-contiguous or non-linear CPU numbering.
config ARCH_RV_HARTID_BASE
int "Base hartid of this cluster"
default 0
---help---
Some RV chips have multiple cluster of harts with
globally numbered mhartids, like qemu-rv, mpfs and
jh7110 etc. Clusters with SMP ability can be managed
by NuttX. As NuttX expects cluster-local hart ids,
we can shift mhartid by this value to derive such
local ids. The SMP_NCPUS still defines number of
harts in the cluster. Note that we assume that global
ids for each cluster are continuous. Note that there
are chips like k230 which don't have global mhartid.
This setting is used in multi-cluster RISC-V systems where each hardware
thread (hart) has a globally unique mhartid value.
Purpose:
- Maps global hardware thread IDs (mhartid) to cluster-local IDs
- Enables NuttX to work with cluster-local hart IDs while maintaining
global uniqueness across the system
Example:
In a system with:
- Cluster A: harts 100-103
- Cluster B: harts 200-203
- Cluster C: harts 300-303
If this is Cluster B's configuration, set ARCH_RV_HARTID_BASE=200.
NuttX will then map:
- Global hart 200 -> Local hart 0
- Global hart 201 -> Local hart 1
- Global hart 202 -> Local hart 2
- Global hart 203 -> Local hart 3
Key Points:
1. SMP_NCPUS defines the number of harts in this cluster
2. Global hart IDs within a cluster must be consecutive
3. Some chips like K230 don't use global mhartid numbering
4. The base value should match the starting mhartid of this cluster
5. Local hart IDs always start from 0 within each cluster
Special Cases:
- For chips like K230 that don't use global mhartid numbering,
this value should typically be set to 0
- In single-cluster systems, this can usually remain at default (0)
config ARCH_FAMILY
string

View file

@ -691,34 +691,16 @@ EXTERN volatile bool g_interrupt_context[CONFIG_SMP_NCPUS];
irqstate_t up_irq_enable(void);
#ifdef CONFIG_ARCH_RV_CPUID_MAP
/****************************************************************************
* Name: up_cpu_index
*
* Description:
* Return the real core number regardless CONFIG_SMP setting
*
* When CONFIG_RISCV_PERCPU_SCRATCH is enabled, this uses the percpu
* scratch area to store the hart ID. This is needed when the CSR_MHARTID
* register may not contain the actual hart ID.
*
* When CONFIG_RISCV_PERCPU_SCRATCH is not enabled, this directly reads
* the CSR_MHARTID register. Use this version when you can guarantee
* CSR_MHARTID contains the actual hart ID. This is the default behavior
* that can be achieved by single instruction to provide better
* performance.
*
****************************************************************************/
#ifdef CONFIG_ARCH_HAVE_MULTICPU
#ifdef CONFIG_RISCV_PERCPU_SCRATCH
int up_cpu_index(void) noinstrument_function;
#else
noinstrument_function static inline int up_cpu_index(void)
{
return READ_CSR(CSR_MHARTID);
}
#endif
#endif /* CONFIG_ARCH_HAVE_MULTICPU */
/****************************************************************************
* Name: up_this_cpu
@ -730,6 +712,14 @@ noinstrument_function static inline int up_cpu_index(void)
****************************************************************************/
int up_this_cpu(void);
#else
noinstrument_function static inline int up_cpu_index(void)
{
return READ_CSR(CSR_MHARTID);
}
#define up_this_cpu() up_cpu_index()
#endif /* CONFIG_ARCH_RV_CPUID_MAP */
/****************************************************************************
* Inline Functions

View file

@ -49,7 +49,7 @@ if(CONFIG_SMP)
list(APPEND SRCS riscv_smpcall.c riscv_cpustart.c)
endif()
if(CONFIG_ARCH_HAVE_MULTICPU)
if(CONFIG_ARCH_RV_CPUID_MAP)
list(APPEND SRCS riscv_cpuindex.c)
endif()

View file

@ -52,7 +52,7 @@ ifeq ($(CONFIG_SMP),y)
CMN_CSRCS += riscv_smpcall.c riscv_cpustart.c
endif
ifeq ($(CONFIG_ARCH_HAVE_MULTICPU),y)
ifeq ($(CONFIG_ARCH_RV_CPUID_MAP),y)
CMN_CSRCS += riscv_cpuindex.c
endif

View file

@ -26,8 +26,6 @@
#include <nuttx/config.h>
#include <stdint.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
@ -45,12 +43,10 @@
*
****************************************************************************/
#ifdef CONFIG_RISCV_PERCPU_SCRATCH
int up_cpu_index(void)
{
return (int)riscv_mhartid();
}
#endif
/****************************************************************************
* Name: up_this_cpu

View file

@ -362,6 +362,22 @@ int riscv_smp_call_handler(int irq, void *c, void *arg);
* Description:
* Context aware way to query hart id (physical core ID)
*
* The function riscv_mhartid is designed to retrieve the hardware thread
* ID (hartid) in different execution modes of RISC-V. Its behavior depends
* on the configuration and execution mode:
*
* - In machine mode, riscv_mhartid reads directly from the CSR mhartid.
* - In supervisor mode, the hartid is stored in the percpu structure
* during boot because supervisor mode does not have access to CSR
* `shartid`. The SBI (Supervisor Binary Interface) provides the hartid
* in the a0 register (as per SBI ABI requirements), and it is the
* responsibility of the payload OS to store this value internally.
* We use the percpu scratch register for this purpose, as it is the only
* location that is unique for each CPU and non-volatile.
*
* Note: In flat (machine) mode, you could still read the hartid from CSR
* mhartid even if CONFIG_RISCV_PERCPU_SCRATCH is enabled.
*
* Returned Value:
* Hart id
*
@ -369,27 +385,22 @@ int riscv_smp_call_handler(int irq, void *c, void *arg);
uintptr_t riscv_mhartid(void);
#ifdef CONFIG_ARCH_RV_CPUID_MAP
/****************************************************************************
* Name: riscv_hartid_to_cpuid
* Name: riscv_hartid_to_cpuid / riscv_cpuid_to_hartid
*
* Description:
* Convert physical core number to logical core number. Default
* implementation is 1:1 mapping, i.e. physical=logical.
* CPU ID mapping functions for systems where physical hart IDs don't match
* logical CPU IDs.
*
****************************************************************************/
int riscv_hartid_to_cpuid(int hart);
/****************************************************************************
* 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);
#else
#define riscv_hartid_to_cpuid(hart) (hart)
#define riscv_cpuid_to_hartid(cpu) (cpu)
#endif /* CONFIG_ARCH_RV_CPUID_MAP */
/* If kernel runs in Supervisor mode, a system call trampoline is needed */