[RFC PATCH v1 08/11] riscv: hwprobe: Introduce rva23u64 base behavior

Guodong Xu guodong at riscstar.com
Sat Feb 21 02:51:25 PST 2026


Hi, Drew

On Fri, Feb 6, 2026 at 8:24 AM Andrew Jones
<andrew.jones at oss.qualcomm.com> wrote:
>
> Provide a bit to conveniently determine when RVA23U64 is supported.
> While it's already possible to determine RVA23U64 support with five
> hwprobe calls and four prctl calls it would be error-prone to require
> anything (and we presume eventually almost everything) that needs to
> check for RVA23U64 support to all implement those calls and specific
> checks. And, while RVA23U64 is the IMA base with mandated extensions,
> most software will consider it a new base. For these reasons, add
> the RVA23U64 bit as a base behavior bit.
>
> Signed-off-by: Andrew Jones <andrew.jones at oss.qualcomm.com>
> ---
>  Documentation/arch/riscv/hwprobe.rst          |  8 +++
>  arch/riscv/include/uapi/asm/hwprobe.h         |  3 +-
>  arch/riscv/kernel/sys_hwprobe.c               | 72 +++++++++++++++++++
>  .../selftests/riscv/hwprobe/which-cpus.c      |  2 +-
>  4 files changed, 83 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
> index 97226b7c5936..6d915e7ba58a 100644
> --- a/Documentation/arch/riscv/hwprobe.rst
> +++ b/Documentation/arch/riscv/hwprobe.rst
> @@ -67,6 +67,14 @@ The following keys are defined:
>        programs (it may still be executed in userspace via a
>        kernel-controlled mechanism such as the vDSO).
>
> +  * :c:macro:`RISCV_HWPROBE_BASE_BEHAVIOR_RVA23U64`: Support for all mandatory
> +    extensions of RVA23U64, as defined in the RISC-V Profiles specification
> +    starting from commit b1d80660 ("Updated to ratified state.")

Should we reference the commit which ratifies RVA23 to its 1.0 version?
I mean commit 0273f3c9 ("rva23/rvb23 ratified"), Oct 2024.

At commit b1d80660, rva23-profile.adoc exists and covers RVA23U64,
however, it is still at revnumber 0.1-draft ("Development stage"). As
its evolving nature, the content revolves from 0.1 to 1.0. I believe
it's more useful to people to point them to a ratified version, instead
of introducing history to them.

Another suggestion, how about just referring to the ratified 1.0
document itself, which can be found at RISC-V International's official
website [1], following the link "Ratified Profiles Specification".

Link: https://riscv.org/specifications/ratified/ [1]

> +
> +    The RVA23U64 base is based upon the IMA base and therefore IMA extension
> +    keys (e.g. :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0`:) may be used to probe
> +    optional extensions.
> +
>  * :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0`: A bitmask containing the extensions
>    that are compatible with the :c:macro:`RISCV_HWPROBE_BASE_BEHAVIOR_IMA`:
>    base system behavior.
> diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
> index fed9ea6fd2b5..72d2a4d0b733 100644
> --- a/arch/riscv/include/uapi/asm/hwprobe.h
> +++ b/arch/riscv/include/uapi/asm/hwprobe.h
> @@ -21,7 +21,8 @@ struct riscv_hwprobe {
>  #define RISCV_HWPROBE_KEY_MARCHID      1
>  #define RISCV_HWPROBE_KEY_MIMPID       2
>  #define RISCV_HWPROBE_KEY_BASE_BEHAVIOR        3
> -#define                RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1 << 0)
> +#define                RISCV_HWPROBE_BASE_BEHAVIOR_IMA         (1 << 0)
> +#define                RISCV_HWPROBE_BASE_BEHAVIOR_RVA23U64    (1 << 1)
>  #define RISCV_HWPROBE_KEY_IMA_EXT_0    4
>  #define                RISCV_HWPROBE_IMA_FD            (1 << 0)
>  #define                RISCV_HWPROBE_IMA_C             (1 << 1)
> diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
> index 31d222301bf0..4b9981b15ebe 100644
> --- a/arch/riscv/kernel/sys_hwprobe.c
> +++ b/arch/riscv/kernel/sys_hwprobe.c
> @@ -23,6 +23,7 @@
>  #include <asm/vendor_extensions/thead_hwprobe.h>
>  #include <vdso/vsyscall.h>
>
> +extern bool riscv_have_user_pmlen_7;

Suggest to put this in a header, like <asm/processor.h>

>
>  #define EXT_KEY(isa_arg, ext, pv, missing)                                     \
>         do {                                                                            \
> @@ -222,6 +223,75 @@ static bool hwprobe_ext0_has(const struct cpumask *cpus, u64 ext)
>         return (pair.value & ext);
>  }
>
> +#define HWPROBE_EXT0_RVA23U64 (                                        \
> +       /* IMA is always supported */                           \
> +       RISCV_HWPROBE_IMA_FD                            |       \
> +       RISCV_HWPROBE_IMA_C                             |       \
> +       /* B is Zba, Zbb and Zbs */                             \
> +       RISCV_HWPROBE_EXT_ZBA                           |       \
> +       RISCV_HWPROBE_EXT_ZBB                           |       \
> +       RISCV_HWPROBE_EXT_ZBS                           |       \
> +       /* ZICSR is always supported */                         \
> +       RISCV_HWPROBE_EXT_ZICNTR                        |       \
> +       RISCV_HWPROBE_EXT_ZIHPM                         |       \
> +       /* ZICCIF is in EXT1 */                                 \
> +       /* ZICCRSE is in EXT1 */                                \
> +       /* ZICCAMOA is in EXT1 */                               \
> +       RISCV_HWPROBE_EXT_ZICCLSM                       |       \
> +       /* ZA64RS is in EXT1 */                                 \
> +       RISCV_HWPROBE_EXT_ZIHINTPAUSE                   |       \
> +       /* ZIC64B (check block sizes are 64b) */                \
> +       RISCV_HWPROBE_EXT_ZICBOM                        |       \
> +       RISCV_HWPROBE_EXT_ZICBOP                        |       \
> +       RISCV_HWPROBE_EXT_ZICBOZ                        |       \
> +       RISCV_HWPROBE_EXT_ZFHMIN                        |       \
> +       RISCV_HWPROBE_EXT_ZKT                           |       \
> +       RISCV_HWPROBE_IMA_V                             |       \
> +       RISCV_HWPROBE_EXT_ZVFHMIN                       |       \
> +       RISCV_HWPROBE_EXT_ZVBB                          |       \
> +       RISCV_HWPROBE_EXT_ZVKT                          |       \
> +       RISCV_HWPROBE_EXT_ZIHINTNTL                     |       \
> +       RISCV_HWPROBE_EXT_ZICOND                        |       \
> +       RISCV_HWPROBE_EXT_ZIMOP                         |       \
> +       RISCV_HWPROBE_EXT_ZCMOP                         |       \
> +       RISCV_HWPROBE_EXT_ZCB                           |       \
> +       RISCV_HWPROBE_EXT_ZFA                           |       \
> +       RISCV_HWPROBE_EXT_ZAWRS                         |       \
> +       RISCV_HWPROBE_EXT_SUPM /* (check PMLEN=7 support) */    \
> +)
> +
> +#define HWPROBE_EXT1_RVA23U64 (                                        \
> +       RISCV_HWPROBE_EXT_ZICCIF                        |       \
> +       RISCV_HWPROBE_EXT_ZICCRSE                       |       \
> +       RISCV_HWPROBE_EXT_ZICCAMOA                      |       \
> +       RISCV_HWPROBE_EXT_ZA64RS                                \
> +)
> +
> +static bool hwprobe_has_rva23u64(const struct cpumask *cpus)
> +{
> +       struct riscv_hwprobe pair;
> +
> +       if (!IS_ENABLED(CONFIG_64BIT))
> +               return false;
> +
> +       /* Additional mandates for Zic64b and Supm */
> +       if (riscv_cbom_block_size != 64 ||
> +           riscv_cbop_block_size != 64 ||
> +           riscv_cboz_block_size != 64 ||
> +           !riscv_have_user_pmlen_7)
> +               return false;
> +
> +       hwprobe_isa_ext0(&pair, cpus);
> +       if ((pair.value & HWPROBE_EXT0_RVA23U64) != HWPROBE_EXT0_RVA23U64)
> +               return false;
> +
> +       hwprobe_isa_ext1(&pair, cpus);
> +       if ((pair.value & HWPROBE_EXT1_RVA23U64) != HWPROBE_EXT1_RVA23U64)
> +               return false;
> +
> +       return true;
> +}
> +
>  #if defined(CONFIG_RISCV_PROBE_UNALIGNED_ACCESS)
>  static u64 hwprobe_misaligned(const struct cpumask *cpus)
>  {
> @@ -312,6 +382,8 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
>          */
>         case RISCV_HWPROBE_KEY_BASE_BEHAVIOR:
>                 pair->value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA;
> +               if (hwprobe_has_rva23u64(cpus))
> +                       pair->value |= RISCV_HWPROBE_BASE_BEHAVIOR_RVA23U64;

There are two separate implementations of RVA23U64 detection in
your patchset:
1. In this patch: hwprobe_has_rva23u64(), which checks against
RISCV_HWPROBE_EXT_* bits.
2. In [Patch 10/11]: riscv_set_isa_bases(), which checks against
RISCV_ISA_EXT_*.

I'm not sure I fully understand your reasoning behind this
duplication (it's too obvious for me not to doubt myself). At
least for now, I think the hwprobe version is not good from an
architecture viewpoint.

My logic is this: RVA23U64 is a hardware implementation feature.
It exists no matter whether you export its sub-components (those
mandatory extensions required by RVA23 Profile) through hwprobe or
not. Profile conformance vs. per-extension export should stay
independent.

DT/ACPI -> RISCV_ISA_EXT_*: these are ground truth.
RISCV_HWPROBE_EXT_*: these are a filtered subset.

We shouldn't be pushed to export (hwprobe) an extension just
to make the RVA23U64 calculation correct. The criteria for
exporting an extension through hwprobe should be based on
whether there is a userspace consumer who needs it
individually.

BR,
Guodong


>                 break;
>
>         case RISCV_HWPROBE_KEY_IMA_EXT_0:
> diff --git a/tools/testing/selftests/riscv/hwprobe/which-cpus.c b/tools/testing/selftests/riscv/hwprobe/which-cpus.c
> index 587feb198c04..f8c797b1d0fd 100644
> --- a/tools/testing/selftests/riscv/hwprobe/which-cpus.c
> +++ b/tools/testing/selftests/riscv/hwprobe/which-cpus.c
> @@ -105,7 +105,7 @@ int main(int argc, char **argv)
>         pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, };
>         rc = riscv_hwprobe(pairs, 1, 0, NULL, 0);
>         assert(rc == 0 && pairs[0].key == RISCV_HWPROBE_KEY_BASE_BEHAVIOR &&
> -              pairs[0].value == RISCV_HWPROBE_BASE_BEHAVIOR_IMA);
> +              (pairs[0].value & RISCV_HWPROBE_BASE_BEHAVIOR_IMA));
>
>         pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, };
>         rc = riscv_hwprobe(pairs, 1, 0, NULL, 0);
> --
> 2.43.0
>



More information about the linux-riscv mailing list