On Mon, May 11, 2026 at 09:34:53PM -0400, Guodong Xu wrote:
> Introduce a per-hart and host-wide bitmap of conformant ISA "bases" --
> named profile-class sets such as IMA and RVA23U64 -- and compute
> both at init time.
> 
> This is the cache that subsequent consumers (hwprobe's
> RVA23U64 base behavior bit, /proc/cpuinfo's "isa bases" lines, etc.)
> read without recomputing.
> 
> riscv_init_isa_bases() iterates over all possible cpus to populate
> each hart_isa[cpu].isa_bases, then computes the host-wide
> riscv_isa_bases against the AND-across-harts riscv_isa bitmap.  It is
> registered as a subsys_initcall so it executes after
> core_initcall(tagged_addr_init), which probes senvcfg.PMM and
> populates have_user_pmlen_*.  Without that ordering,
> riscv_have_user_pmlen(7) would still return its default false and the
> RVA23U64 detection path would always bail.
> 
> The detection itself is encapsulated in riscv_set_isa_bases(), which
> takes an output bases bitmap and an input ISA bitmap.
> 
> Signed-off-by: Andrew Jones <[email protected]>
> Signed-off-by: Guodong Xu <[email protected]>
> ---
> v2:
> - Implement riscv_init_isa_bases() that runs at system init time,
>   after tagged_addr_init() populates have_user_pmlen_*.
> - Split RVA23S64 placeholder into a future patch.
> ---
>  arch/riscv/include/asm/cpufeature.h | 14 ++++++
>  arch/riscv/kernel/cpufeature.c      | 92 
> +++++++++++++++++++++++++++++++++++++
>  2 files changed, 106 insertions(+)

Sashiko points out a few things about this patch which I think I
agree with

https://sashiko.dev/#/patchset/20260511-rva23u64-hwprobe-v2-v2-0-21c5a544f1dc%40riscstar.com?part=8

Additional nit below.

> 
> diff --git a/arch/riscv/include/asm/cpufeature.h 
> b/arch/riscv/include/asm/cpufeature.h
> index 739fcc84bf7b2..facc31b2960c6 100644
> --- a/arch/riscv/include/asm/cpufeature.h
> +++ b/arch/riscv/include/asm/cpufeature.h
> @@ -25,10 +25,24 @@ struct riscv_cpuinfo {
>       unsigned long mimpid;
>  };
>  
> +enum {
> +     RISCV_ISA_BASE_IMA,
> +     RISCV_ISA_BASE_RVA23U64,
> +     RISCV_NR_ISA_BASES,
> +};
> +
> +/**
> + * struct riscv_isainfo - per-hart ISA state
> + * @isa: bitmap of ISA extensions this hart implements
> + * @isa_bases: bitmap of profile bases this hart conforms to
> + */
>  struct riscv_isainfo {
>       DECLARE_BITMAP(isa, RISCV_ISA_EXT_MAX);
> +     DECLARE_BITMAP(isa_bases, RISCV_NR_ISA_BASES);
>  };
>  
> +extern unsigned long riscv_isa_bases[BITS_TO_LONGS(RISCV_NR_ISA_BASES)];
> +
>  DECLARE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo);
>  
>  extern const struct seq_operations cpuinfo_op;
> diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
> index 81145621dc378..6e8dd33aa3888 100644
> --- a/arch/riscv/kernel/cpufeature.c
> +++ b/arch/riscv/kernel/cpufeature.c
> @@ -41,6 +41,9 @@ unsigned long elf_hwcap __read_mostly;
>  /* Host ISA bitmap */
>  static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;
>  
> +/* Host ISA bases bitmap */
> +DECLARE_BITMAP(riscv_isa_bases, RISCV_NR_ISA_BASES) __read_mostly;
> +
>  /* Per-cpu ISA extensions. */
>  struct riscv_isainfo hart_isa[NR_CPUS];
>  
> @@ -1305,3 +1308,92 @@ void __init_or_module 
> riscv_cpufeature_patch_func(struct alt_entry *begin,
>       }
>  }
>  #endif
> +
> +/*
> + * Compute the set of profile bases (IMA, RVA23U64, ...) a hart
> + * conforms to, given its resolved ISA bitmap.
> + *
> + * If @isa_bitmap is NULL, the host ISA bitmap (the AND across all harts) is
> + * used.
> + */
> +static void riscv_set_isa_bases(unsigned long *bases, const unsigned long 
> *isa_bitmap)
> +{
> +     const unsigned long *isa = isa_bitmap ? isa_bitmap : riscv_isa;
> +     DECLARE_BITMAP(ext_mask, RISCV_ISA_EXT_MAX) = { 0 };
> +     DECLARE_BITMAP(tmp, RISCV_ISA_EXT_MAX);
> +
> +     /* IMA */
> +     set_bit(RISCV_ISA_EXT_I, ext_mask);
> +     set_bit(RISCV_ISA_EXT_M, ext_mask);
> +     set_bit(RISCV_ISA_EXT_A, ext_mask);
> +
> +     if (bitmap_andnot(tmp, ext_mask, isa, RISCV_ISA_EXT_MAX))
> +             return;
> +
> +     set_bit(RISCV_ISA_BASE_IMA, bases);
> +
> +     /* RVA23U64 */
> +
> +     /* Zic64b and Supm with PMLEN=7 */
> +     if (riscv_cbom_block_size != 64 ||
> +         riscv_cbop_block_size != 64 ||
> +         riscv_cboz_block_size != 64 ||
> +         !riscv_have_user_pmlen(7))
> +             return;
> +
> +     set_bit(RISCV_ISA_EXT_F, ext_mask);
> +     set_bit(RISCV_ISA_EXT_D, ext_mask);
> +     set_bit(RISCV_ISA_EXT_C, ext_mask);
> +     set_bit(RISCV_ISA_EXT_B, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZICSR, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZICNTR, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZIHPM, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZICCIF, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZICCRSE, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZICCAMOA, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZICCLSM, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZA64RS, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZIHINTPAUSE, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZICBOM, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZICBOP, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZICBOZ, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZFHMIN, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZKT, ext_mask);
> +     set_bit(RISCV_ISA_EXT_V, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZVFHMIN, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZVBB, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZVKT, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZIHINTNTL, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZICOND, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZIMOP, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZCMOP, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZCB, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZFA, ext_mask);
> +     set_bit(RISCV_ISA_EXT_ZAWRS, ext_mask);
> +     set_bit(RISCV_ISA_EXT_SUPM, ext_mask);
> +
> +     if (bitmap_andnot(tmp, ext_mask, isa, RISCV_ISA_EXT_MAX))
> +             return;
> +
> +     set_bit(RISCV_ISA_BASE_RVA23U64, bases);
> +}
> +
> +/*
> + * Populate the host ISA bases bitmap (riscv_isa_bases) and each
> + * hart's per-cpu isa_bases.
> + */
> +static int __init riscv_init_isa_bases(void)
> +{
> +     int cpu;
> +
> +     for_each_possible_cpu(cpu)
> +             riscv_set_isa_bases(hart_isa[cpu].isa_bases, hart_isa[cpu].isa);
> +
> +     riscv_set_isa_bases(riscv_isa_bases, NULL);
> +     return 0;
> +}

Missing blank line here.

Thanks,
drew

> +/*
> + * Registered as subsys_initcall so it runs after
> + * core_initcall(tagged_addr_init) populates have_user_pmlen_*.
> + */
> +subsys_initcall(riscv_init_isa_bases);
> 
> -- 
> 2.43.0
> 

Reply via email to