[V3,1/1] riscv: Increase the upper bound of NR_CPUS to 4095
Heinrich Schuchardt
heinrich.schuchardt at canonical.com
Tue May 16 15:54:38 CEST 2023
On 2/13/23 09:43, Leo Yu-Chi Liang wrote:
> From: Xiang W <wxjstz at 126.com>
>
> The maximum hart number is 32 and is determined by
> the type of gd->arch.available_harts. However, various
> RISC-V specifications allow the hart number to be greater
> than 32. We can eliminate this limitation through bitmaps.
>
> The patch modifies the upper bound of the hart number to 4095,
> which is also the maximum hart number RISC-V Advanced Core Local
> Interruptor Specification gives.
>
> Some defconfigs, (e.g. qemu-riscv32_smode_defconfig,
> qemu-riscv64_smode_defconfig, openpiton_riscv64_defconfig, ...)
> do not define CONFIG_NR_CPUS, and may result in compile error,
> so define CONFIG_NR_CPUS to be 1 if CONFIG_NR_CPUS is not defined.
>
> Tested on sifive unmatched.
>
> Signed-off-by: Xiang W <wxjstz at 126.com>
> Signed-off-by: Leo Yu-Chi Liang <ycliang at andestech.com>
> ---
> Changes v2 -> v3:
> - Fix the calculation of the GD_AVAILABLE_HARTS start address
> - Fix compilation error for defconfigs that do not define CONFIG_NR_CPUS
> ---
> arch/riscv/Kconfig | 4 ++--
> arch/riscv/cpu/start.S | 20 +++++++++++++++-----
> arch/riscv/include/asm/global_data.h | 8 +++++++-
> arch/riscv/lib/smp.c | 2 +-
> 4 files changed, 25 insertions(+), 9 deletions(-)
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index ebc4bef220..063734cbb9 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -232,8 +232,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
Looking at patch
776e8aca0bad ("riscv: alloc space exhausted")
SYS_MALLOC_F_LEN needs to be increased if the number of CPUs is increased.
You could add an architecture specific rule to config.mk to adjust
SYS_MALLOC_F_LEN.
> depends on SMP || SPL_SMP
> default 8
> help
> diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
> index 4687bca3c9..ae19c2b43d 100644
> --- a/arch/riscv/cpu/start.S
> +++ b/arch/riscv/cpu/start.S
> @@ -172,11 +172,21 @@ wait_for_gd_init:
> bnez t1, 1b
>
> /* 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)
> + li t1, GD_AVAILABLE_HARTS
> + add t1, t1, 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
If QEMU provides > XLEN harts, this will result in a buffer overrun. You
must check against the size of available_harts.
> + 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)
> #endif
> diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
> index 6fdc86dd8b..7e37e90db0 100644
> --- a/arch/riscv/include/asm/global_data.h
> +++ b/arch/riscv/include/asm/global_data.h
> @@ -10,9 +10,15 @@
> #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>
> +
> +#ifndef CONFIG_NR_CPUS
> +#define CONFIG_NR_CPUS 1
CONFIG_ constants should not be defined in C code. Please, move this to
Kconfig.
The chosen value will create problems for QEMU. The fallback value
should be XLEN (BITS_PER_LONG) at least.
Best regards
Heinrich
> +#endif
>
> /* Architecture-specific global data */
> struct arch_global_data {
> @@ -29,7 +35,7 @@ struct arch_global_data {
> #endif
> #if !CONFIG_IS_ENABLED(XIP)
> #ifdef CONFIG_AVAILABLE_HARTS
> - ulong available_harts;
> + ulong available_harts[BITS_TO_LONGS(CONFIG_NR_CPUS)];
> #endif
> #endif
> };
> diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c
> index 4f073a016f..511e3ed98d 100644
> --- a/arch/riscv/lib/smp.c
> +++ b/arch/riscv/lib/smp.c
> @@ -48,7 +48,7 @@ static int send_ipi_many(struct ipi_data *ipi, int wait)
> #if !CONFIG_IS_ENABLED(XIP)
> #ifdef CONFIG_AVAILABLE_HARTS
> /* skip if hart is not available */
> - if (!(gd->arch.available_harts & (1 << reg)))
> + if (!test_bit(reg, gd->arch.available_harts))
> continue;
> #endif
> #endif
More information about the U-Boot
mailing list