From 51d4803a6fbae1d280885ed6b70683efadd12e81 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Mon, 5 Jan 2026 16:02:29 +0800 Subject: [PATCH] util/cpu: support detecting RISC-V FD/C/V/Zb[abs] with riscv_hwprobe Linux v6.4+ provides a syscall called riscv_hwprobe that could detect multiple characteristics of the running CPU on RISC-V platform. Implement real check_os_riscv_support() with it and support extensions detectable by it on Linux v6.5 . When the toolchain has no riscv_hwprobe definition or the kernel at runtime does not support it, the fallback code still assumes GC. Signed-off-by: Icenowy Zheng Part-of: --- src/util/u_cpu_detect.c | 67 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/src/util/u_cpu_detect.c b/src/util/u_cpu_detect.c index db261d29c7a..451881d1f7a 100644 --- a/src/util/u_cpu_detect.c +++ b/src/util/u_cpu_detect.c @@ -92,6 +92,15 @@ #include #endif +#if DETECT_OS_LINUX && DETECT_ARCH_RISCV && __has_include() +#include +#include +#if !defined(__NR_riscv_hwprobe) +#define __NR_riscv_hwprobe 258 +#endif +#define HAVE_RISCV_HWPROBE +#endif + // prevent inadvert infinite recursion #define util_get_cpu_caps() util_get_cpu_caps_DO_NOT_USE() @@ -443,12 +452,66 @@ check_os_loongarch64_support(void) #if DETECT_ARCH_RISCV static void -check_os_riscv_support(void) +check_os_riscv_support_default(void) { - /* Stub code assume GC (IMAFDC) */ + /* Failed to use hwprobe, assume GC (IMAFDC) */ util_cpu_caps.has_rv_fd = 1; util_cpu_caps.has_rv_c = 1; } +static void +check_os_riscv_support(void) +{ +#ifdef HAVE_RISCV_HWPROBE + struct riscv_hwprobe probes[] = { + /* + * IMA_EXT_0 come in the same kernel version with with the hwprobe + * interface (v6.4). + */ + {RISCV_HWPROBE_KEY_IMA_EXT_0, 0}, + }; + int ret; + + ret = syscall(__NR_riscv_hwprobe, probes, ARRAY_SIZE(probes), 0, NULL, 0); + + if (ret != 0) { + /* Kernel might be too old to have hwprobe */ + check_os_riscv_support_default(); + return; + } + + for (unsigned i = 0; i < ARRAY_SIZE(probes); i++) { + switch(probes[i].key) { + case RISCV_HWPROBE_KEY_IMA_EXT_0: + /* IMA_FD/IMA_C definition appear in v6.4 */ + if (probes[i].value & RISCV_HWPROBE_IMA_FD) + util_cpu_caps.has_rv_fd = 1; + if (probes[i].value & RISCV_HWPROBE_IMA_C) + util_cpu_caps.has_rv_c = 1; + /* IMA_V/EXT_ZBA/EXT_ZBB/EXT_ZBS definition appear in v6.5 */ +#if defined(RISCV_HWPROBE_IMA_V) + if (probes[i].value & RISCV_HWPROBE_IMA_V) + util_cpu_caps.has_rv_v = 1; +#endif +#if defined(RISCV_HWPROBE_EXT_ZBA) + if (probes[i].value & RISCV_HWPROBE_EXT_ZBA) + util_cpu_caps.has_rv_zba = 1; +#endif +#if defined(RISCV_HWPROBE_EXT_ZBB) + if (probes[i].value & RISCV_HWPROBE_EXT_ZBB) + util_cpu_caps.has_rv_zbb = 1; +#endif +#if defined(RISCV_HWPROBE_EXT_ZBS) + if (probes[i].value & RISCV_HWPROBE_EXT_ZBS) + util_cpu_caps.has_rv_zbs = 1; +#endif + break; + } + } +#else + /* Toolchain might be too old to have hwprobe */ + check_os_riscv_support_default(); +#endif +} #endif static void