diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index 99d52ae8fa..a796f48b9d 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -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 diff --git a/arch/risc-v/include/irq.h b/arch/risc-v/include/irq.h index 7d21cdce5c..a06a57f276 100644 --- a/arch/risc-v/include/irq.h +++ b/arch/risc-v/include/irq.h @@ -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 diff --git a/arch/risc-v/src/common/CMakeLists.txt b/arch/risc-v/src/common/CMakeLists.txt index b7713708e0..8044dd5d97 100644 --- a/arch/risc-v/src/common/CMakeLists.txt +++ b/arch/risc-v/src/common/CMakeLists.txt @@ -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() diff --git a/arch/risc-v/src/common/Make.defs b/arch/risc-v/src/common/Make.defs index 7b1cafdaa0..a812ecd401 100644 --- a/arch/risc-v/src/common/Make.defs +++ b/arch/risc-v/src/common/Make.defs @@ -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 diff --git a/arch/risc-v/src/common/riscv_cpuindex.c b/arch/risc-v/src/common/riscv_cpuindex.c index 891a554517..fc6f51b017 100644 --- a/arch/risc-v/src/common/riscv_cpuindex.c +++ b/arch/risc-v/src/common/riscv_cpuindex.c @@ -26,8 +26,6 @@ #include -#include - #include #include @@ -45,12 +43,10 @@ * ****************************************************************************/ -#ifdef CONFIG_RISCV_PERCPU_SCRATCH int up_cpu_index(void) { return (int)riscv_mhartid(); } -#endif /**************************************************************************** * Name: up_this_cpu diff --git a/arch/risc-v/src/common/riscv_internal.h b/arch/risc-v/src/common/riscv_internal.h index e94688214d..e1dece58f4 100644 --- a/arch/risc-v/src/common/riscv_internal.h +++ b/arch/risc-v/src/common/riscv_internal.h @@ -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 */