Various specifications of riscv allow the number of hart to be
greater than 32. The limit of 32 is determined by
gd->arch.available_harts. We can eliminate this limitation through
bitmaps. Currently, the number of hart is limited to 4095, and 4095
is the limit of the RISC-V Advanced Core Local Interruptor
Specification.

Test on sifive unmatched.

Signed-off-by: Xiang W <wxj...@126.com>
---
 arch/riscv/Kconfig                   |  4 ++--
 arch/riscv/cpu/start.S               | 19 ++++++++++++++-----
 arch/riscv/include/asm/global_data.h |  4 +++-
 arch/riscv/lib/smp.c                 |  2 +-
 4 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index ba29e70acf..7b9c7f5bca 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -220,8 +220,8 @@ config SPL_SMP
          all, single processor machines.
 
 config NR_CPUS
-       int "Maximum number of CPUs (2-32)"
-       range 2 32
+       int "Maximum number of CPUs (2-4095)"
+       range 2 4095
        depends on SMP || SPL_SMP
        default 8
        help
diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
index 76850ec9be..1f97240713 100644
--- a/arch/riscv/cpu/start.S
+++ b/arch/riscv/cpu/start.S
@@ -166,11 +166,20 @@ wait_for_gd_init:
        mv      gp, s0
 
        /* register available harts in the available_harts mask */
-       li      t1, 1
-       sll     t1, t1, tp
-       LREG    t2, GD_AVAILABLE_HARTS(gp)
-       or      t2, t2, t1
-       SREG    t2, GD_AVAILABLE_HARTS(gp)
+       LREG    t1, GD_AVAILABLE_HARTS(gp)
+#if defined(CONFIG_ARCH_RV64I)
+       srli    t2, tp, 6
+       slli    t2, t2, 3
+#elif defined(CONFIG_ARCH_RV32I)
+       srli    t2, tp, 5
+       slli    t2, t2, 2
+#endif
+       add     t1, t1, t2
+       LREG    t2, 0(t1)
+       li      t3, 1
+       sll     t3, t3, tp
+       or      t2, t2, t3
+       SREG    t2, 0(t1)
 
        amoswap.w.rl zero, zero, 0(t0)
 
diff --git a/arch/riscv/include/asm/global_data.h 
b/arch/riscv/include/asm/global_data.h
index 095484a635..6de2ee0b25 100644
--- a/arch/riscv/include/asm/global_data.h
+++ b/arch/riscv/include/asm/global_data.h
@@ -10,9 +10,11 @@
 #ifndef        __ASM_GBL_DATA_H
 #define __ASM_GBL_DATA_H
 
+#include <config.h>
 #include <asm/smp.h>
 #include <asm/u-boot.h>
 #include <compiler.h>
+#include <linux/bitops.h>
 
 /* Architecture-specific global data */
 struct arch_global_data {
@@ -28,7 +30,7 @@ struct arch_global_data {
        struct ipi_data ipi[CONFIG_NR_CPUS];
 #endif
 #ifndef CONFIG_XIP
-       ulong available_harts;
+       ulong available_harts[BITS_TO_LONGS(CONFIG_NR_CPUS)];
 #endif
 };
 
diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c
index ba992100ad..e8e391fd41 100644
--- a/arch/riscv/lib/smp.c
+++ b/arch/riscv/lib/smp.c
@@ -47,7 +47,7 @@ static int send_ipi_many(struct ipi_data *ipi, int wait)
 
 #ifndef CONFIG_XIP
                /* skip if hart is not available */
-               if (!(gd->arch.available_harts & (1 << reg)))
+               if (!test_bit(reg, gd->arch.available_harts))
                        continue;
 #endif
 
-- 
2.30.2

Reply via email to