Provide a hwprobe base-behavior bit so userspace can check RVA23U64 support in one call. Without it, a consumer needs five hwprobe calls and four prctl calls, which is error-prone to require of every caller. Most software treats RVA23U64 as a new base anyway, so expose it directly. Signed-off-by: Andrew Jones Signed-off-by: Guodong Xu --- v2: - Detect RVA23U64 by reading from the cached hart_isa[].isa_bases bitmap populated by riscv_init_isa_bases() at init time, sharing one source of truth with /proc/cpuinfo. --- Documentation/arch/riscv/hwprobe.rst | 8 ++++++++ arch/riscv/include/uapi/asm/hwprobe.h | 3 ++- arch/riscv/kernel/sys_hwprobe.c | 23 +++++++++++++++------- tools/testing/selftests/riscv/hwprobe/which-cpus.c | 2 +- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst index cb31fd3b12017..9b901bf8bab9a 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 0273f3c921b6 ("rva23/rvb23 ratified"). + + 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 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 430dc49a82863..d940ba4f6a1e8 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 dcc102bf8f183..c43fcad737b73 100644 --- a/arch/riscv/kernel/sys_hwprobe.c +++ b/arch/riscv/kernel/sys_hwprobe.c @@ -225,6 +225,17 @@ static bool hwprobe_ext0_has(const struct cpumask *cpus, u64 ext) return (pair.value & ext); } +static bool hwprobe_has_isa_base(const struct cpumask *cpus, unsigned int base) +{ + int cpu; + + for_each_cpu(cpu, cpus) { + if (!test_bit(base, hart_isa[cpu].isa_bases)) + return false; + } + return true; +} + #if defined(CONFIG_RISCV_PROBE_UNALIGNED_ACCESS) static u64 hwprobe_misaligned(const struct cpumask *cpus) { @@ -307,14 +318,12 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair, case RISCV_HWPROBE_KEY_MIMPID: hwprobe_arch_id(pair, cpus); break; - /* - * The kernel already assumes that the base single-letter ISA - * extensions are supported on all harts, and only supports the - * IMA base, so just cheat a bit here and tell that to - * userspace. - */ case RISCV_HWPROBE_KEY_BASE_BEHAVIOR: - pair->value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA; + pair->value = 0; + if (hwprobe_has_isa_base(cpus, RISCV_ISA_BASE_IMA)) + pair->value |= RISCV_HWPROBE_BASE_BEHAVIOR_IMA; + if (hwprobe_has_isa_base(cpus, RISCV_ISA_BASE_RVA23U64)) + pair->value |= RISCV_HWPROBE_BASE_BEHAVIOR_RVA23U64; 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 587feb198c049..f8c797b1d0fd9 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