From: Icenowy Zheng Date: Wed, 28 Jan 2026 08:13:56 +0000 (+0800) Subject: riscv: features: add support for detecting V/Zbc via hwprobe X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c699fa666a2eb8598acd24002d1f720c8d4633f4;p=thirdparty%2Fzlib-ng.git riscv: features: add support for detecting V/Zbc via hwprobe Adding support for riscv_hwprobe and detecting V/Zbc via it. The needed macros should be in Linux 6.12 UAPI headers, which are shipped by Debian Trixie. Tested via qemu-user that the Zbc codepath is examined by adding some code there. Signed-off-by: Icenowy Zheng --- diff --git a/arch/riscv/riscv_features.c b/arch/riscv/riscv_features.c index 99837349d..b23f10a69 100644 --- a/arch/riscv/riscv_features.c +++ b/arch/riscv/riscv_features.c @@ -1,5 +1,7 @@ #ifdef RISCV_FEATURES +#define _DEFAULT_SOURCE 1 /* For syscall() */ + #include "zbuild.h" #include "riscv_features.h" @@ -9,9 +11,49 @@ # include #endif +#if defined(__linux__) && defined(HAVE_ASM_HWPROBE_H) +# include +# include /* For __NR_riscv_hwprobe */ +# include /* For syscall() */ +#endif + #define ISA_V_HWCAP (1 << ('v' - 'a')) #define ISA_ZBC_HWCAP (1 << 29) +static int riscv_check_features_runtime_hwprobe(struct riscv_cpu_features *features) { +#if defined(__NR_riscv_hwprobe) && defined(RISCV_HWPROBE_KEY_IMA_EXT_0) + struct riscv_hwprobe probes[] = { + {RISCV_HWPROBE_KEY_IMA_EXT_0, 0}, + }; + int ret; + unsigned i; + + ret = syscall(__NR_riscv_hwprobe, probes, sizeof(probes) / sizeof(probes[0]), 0, NULL, 0); + + if (ret != 0) { + /* Kernel does not support hwprobe */ + return 0; + } + + for (i = 0; i < sizeof(probes) / sizeof(probes[0]); i++) { + switch (probes[i].key) { + case RISCV_HWPROBE_KEY_IMA_EXT_0: +# ifdef RISCV_HWPROBE_IMA_V + features->has_rvv = !!(probes[i].value & RISCV_HWPROBE_IMA_V); +# endif +# ifdef RISCV_HWPROBE_EXT_ZBC + features->has_zbc = !!(probes[i].value & RISCV_HWPROBE_EXT_ZBC); +# endif + break; + } + } + + return 1; +#else + return 0; +#endif +} + static int riscv_check_features_runtime_hwcap(struct riscv_cpu_features *features) { #if defined(__linux__) && defined(HAVE_SYS_AUXV_H) unsigned long hw_cap = getauxval(AT_HWCAP); @@ -26,6 +68,9 @@ static int riscv_check_features_runtime_hwcap(struct riscv_cpu_features *feature } static void riscv_check_features_runtime(struct riscv_cpu_features *features) { + if (riscv_check_features_runtime_hwprobe(features)) + return; + riscv_check_features_runtime_hwcap(features); }