]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Support RVV hwcap detect at runtime
authorXeonacid <h.dwwwwww@gmail.com>
Sun, 8 Oct 2023 03:30:54 +0000 (11:30 +0800)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Fri, 13 Oct 2023 11:03:44 +0000 (13:03 +0200)
Fallback to compile-time detect if kernel version lower than 6.5.

Co-authored-by: Hans Kristian Rosbach <hk-git@circlestorm.org>
Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>
arch/riscv/README.md
arch/riscv/riscv_features.c

index b4309e1a0aa9d031cce550b9aa32a4024f3bfa29..013095c3732fe08511510231ed0f7bd6d587400f 100644 (file)
@@ -1,10 +1,10 @@
 # Building RISC-V Target with Cmake #
 
 > **Warning**
-> We cannot detect rvv support at runtime, running the rvv code on a no-rvv target is a risk. Users should disable the rvv when the target does not support it. 
+> Runtime rvv detection (using `hwcap`) requires linux kernel 6.5 or newer.
 >
-> We will have a better solution when the kernels update `hwcap` or `hwprobe` for risc-v.
-
+> When running on older kernels, we fall back to compile-time detection, potentially this can cause crashes if rvv is enabled at compile but not supported by the target cpu.
+> Therefore if older kernel support is needed, rvv should be disabled if the target cpu does not support it.
 ## Prerequisite: Build RISC-V Clang Toolchain and QEMU ##
 
 If you don't have prebuilt clang and riscv64 qemu, you can refer to the [script](https://github.com/sifive/prepare-riscv-toolchain-qemu/blob/main/prepare_riscv_toolchain_qemu.sh) to get the source. Copy the script to the zlib-ng root directory, and run it to download the source and build them. Modify the content according to your conditions (e.g., toolchain version).
index 362d71483566c1a9f81ec66525cd798542e408c4..b066f427e0fc3e8bffbe7747b0f910e72c265f5e 100644 (file)
@@ -1,15 +1,45 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/auxv.h>
+#include <sys/utsname.h>
 
 #include "../../zbuild.h"
 #include "riscv_features.h"
 
-/* TODO: detect risc-v cpu info at runtime when the kernel updates hwcap or hwprobe for risc-v */
-void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features) {
+#define ISA_V_HWCAP (1 << ('v' - 'a'))
+
+int Z_INTERNAL is_kernel_version_greater_or_equal_to_6_5() {
+    struct utsname buffer;
+    uname(&buffer);
+
+    int major, minor;
+    if (sscanf(buffer.release, "%d.%d", &major, &minor) != 2) {
+        // Something bad with uname()
+        return 0;
+    }
+
+    if (major > 6 || major == 6 && minor >= 5)
+        return 1;
+    return 0;
+}
+
+void Z_INTERNAL riscv_check_features_compile_time(struct riscv_cpu_features *features) {
 #if defined(__riscv_v) && defined(__linux__)
     features->has_rvv = 1;
 #else
     features->has_rvv = 0;
 #endif
 }
+
+void Z_INTERNAL riscv_check_features_runtime(struct riscv_cpu_features *features) {
+    unsigned long hw_cap = getauxval(AT_HWCAP);
+    features->has_rvv = hw_cap & ISA_V_HWCAP;
+}
+
+void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features) {
+    if (is_kernel_version_greater_or_equal_to_6_5())
+        riscv_check_features_runtime(features);
+    else
+        riscv_check_features_compile_time(features);
+}