[PATCH v2] eal/riscv: add Z sub-extension detection via hwprobe syscall
dangshiwei
1138222970gg at gmail.com
Mon Mar 23 05:07:54 CET 2026
The existing RISC-V rte_cpuflags implementation only detects
single-letter ISA extensions (A, C, D, F, M, V, etc.) via
AT_HWCAP. Z sub-extensions such as Zba, Zbb, Zbc, Zawrs and
cryptography extensions (Zksed, Zksh, Zknd, Zkne) are not
visible through AT_HWCAP and therefore cannot be used for
runtime dispatch.
Linux 6.4 introduced the riscv_hwprobe syscall (NR 258) which
exposes Z sub-extensions via the RISCV_HWPROBE_KEY_IMA_EXT_0
key as a 64-bit bitmask. This patch adds support for querying
Z sub-extensions through this interface.
Changes:
- Add REG_HWPROBE_EXT0 source to cpu_register_t
- Fix hwcap_registers_t type from uint32_t to uint64_t to
avoid truncation of AT_HWCAP on 64-bit platforms
- Call riscv_hwprobe at EAL init via RTE_INIT and cache the
result; falls back silently on kernels older than 6.4
- Add 56 new enum values for Z sub-extensions in rte_cpuflags.h
- Extend cpuflags_autotest to cover all new flags
Signed-off-by: dangshiwei <1138222970gg at gmail.com>
---
app/test/test_cpuflags.c | 167 +++++++++++++++++
lib/eal/riscv/include/rte_cpuflags.h | 79 +++++++-
lib/eal/riscv/rte_cpuflags.c | 262 +++++++++++++++++++++++----
3 files changed, 474 insertions(+), 34 deletions(-)
diff --git a/app/test/test_cpuflags.c b/app/test/test_cpuflags.c
index a0ad099815..d83c54e9f6 100644
--- a/app/test/test_cpuflags.c
+++ b/app/test/test_cpuflags.c
@@ -281,6 +281,173 @@ test_cpuflags(void)
printf("Check for RISCV_ISA_Z:\t");
CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ISA_Z);
+ printf("Check for RISCV_ZBA:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZBA);
+
+ printf("Check for RISCV_ZBB:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZBB);
+
+ printf("Check for RISCV_ZBC:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZBC);
+
+ printf("Check for RISCV_ZBS:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZBS);
+
+ printf("Check for RISCV_ZBKB:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZBKB);
+
+ printf("Check for RISCV_ZBKC:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZBKC);
+
+ printf("Check for RISCV_ZBKX:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZBKX);
+
+ printf("Check for RISCV_ZICBOM:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZICBOM);
+
+ printf("Check for RISCV_ZICBOZ:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZICBOZ);
+
+ printf("Check for RISCV_ZKND:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZKND);
+
+ printf("Check for RISCV_ZKNE:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZKNE);
+
+ printf("Check for RISCV_ZKNH:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZKNH);
+
+ printf("Check for RISCV_ZKSED:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZKSED);
+
+ printf("Check for RISCV_ZKSH:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZKSH);
+
+ printf("Check for RISCV_ZKT:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZKT);
+
+ printf("Check for RISCV_ZFA:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZFA);
+
+ printf("Check for RISCV_ZFH:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZFH);
+
+ printf("Check for RISCV_ZFHMIN:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZFHMIN);
+
+ printf("Check for RISCV_ZFBFMIN:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZFBFMIN);
+
+ printf("Check for RISCV_ZCA:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZCA);
+
+ printf("Check for RISCV_ZCB:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZCB);
+
+ printf("Check for RISCV_ZCD:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZCD);
+
+ printf("Check for RISCV_ZCF:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZCF);
+
+ printf("Check for RISCV_ZCMOP:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZCMOP);
+
+ printf("Check for RISCV_ZAAMO:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZAAMO);
+
+ printf("Check for RISCV_ZALRSC:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZALRSC);
+
+ printf("Check for RISCV_ZABHA:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZABHA);
+
+ printf("Check for RISCV_ZACAS:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZACAS);
+
+ printf("Check for RISCV_ZAWRS:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZAWRS);
+
+ printf("Check for RISCV_ZICOND:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZICOND);
+
+ printf("Check for RISCV_ZIHINTNTL:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZIHINTNTL);
+
+ printf("Check for RISCV_ZIHINTPAUSE:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZIHINTPAUSE);
+
+ printf("Check for RISCV_ZIMOP:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZIMOP);
+
+ printf("Check for RISCV_ZICNTR:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZICNTR);
+
+ printf("Check for RISCV_ZIHPM:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZIHPM);
+
+ printf("Check for RISCV_ZTSO:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZTSO);
+
+ printf("Check for RISCV_SUPM:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_SUPM);
+
+ printf("Check for RISCV_ZVBB:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVBB);
+
+ printf("Check for RISCV_ZVBC:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVBC);
+
+ printf("Check for RISCV_ZVKB:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVKB);
+
+ printf("Check for RISCV_ZVKG:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVKG);
+
+ printf("Check for RISCV_ZVKNED:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVKNED);
+
+ printf("Check for RISCV_ZVKNHA:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVKNHA);
+
+ printf("Check for RISCV_ZVKNHB:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVKNHB);
+
+ printf("Check for RISCV_ZVKSED:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVKSED);
+
+ printf("Check for RISCV_ZVKSH:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVKSH);
+
+ printf("Check for RISCV_ZVKT:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVKT);
+
+ printf("Check for RISCV_ZVFH:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVFH);
+
+ printf("Check for RISCV_ZVFHMIN:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVFHMIN);
+
+ printf("Check for RISCV_ZVFBFMIN:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVFBFMIN);
+
+ printf("Check for RISCV_ZVFBFWMA:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVFBFWMA);
+
+ printf("Check for RISCV_ZVE32X:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVE32X);
+
+ printf("Check for RISCV_ZVE32F:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVE32F);
+
+ printf("Check for RISCV_ZVE64X:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVE64X);
+
+ printf("Check for RISCV_ZVE64F:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVE64F);
+
+ printf("Check for RISCV_ZVE64D:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_RISCV_ZVE64D);
#endif
#if defined(RTE_ARCH_LOONGARCH)
diff --git a/lib/eal/riscv/include/rte_cpuflags.h b/lib/eal/riscv/include/rte_cpuflags.h
index b1bd7953d4..58477fdb63 100644
--- a/lib/eal/riscv/include/rte_cpuflags.h
+++ b/lib/eal/riscv/include/rte_cpuflags.h
@@ -4,7 +4,6 @@
* Copyright(c) 2022 SiFive
* Copyright(c) 2022 Semihalf
*/
-
#ifndef RTE_CPUFLAGS_RISCV_H
#define RTE_CPUFLAGS_RISCV_H
@@ -12,10 +11,11 @@
* Enumeration of all CPU features supported
*/
enum rte_cpu_flag_t {
+ /* Single-letter ISA extensions (detected via AT_HWCAP) */
RTE_CPUFLAG_RISCV_ISA_A, /* Atomic */
RTE_CPUFLAG_RISCV_ISA_B, /* Bit-Manipulation */
RTE_CPUFLAG_RISCV_ISA_C, /* Compressed instruction */
- RTE_CPUFLAG_RISCV_ISA_D, /* Double precision floating-point */
+ RTE_CPUFLAG_RISCV_ISA_D, /* Double precision floating-point */
RTE_CPUFLAG_RISCV_ISA_E, /* RV32E ISA */
RTE_CPUFLAG_RISCV_ISA_F, /* Single precision floating-point */
RTE_CPUFLAG_RISCV_ISA_G, /* Extension pack (IMAFD, Zicsr, Zifencei) */
@@ -38,8 +38,81 @@ enum rte_cpu_flag_t {
RTE_CPUFLAG_RISCV_ISA_X, /* Non-standard extension present */
RTE_CPUFLAG_RISCV_ISA_Y, /* Reserved */
RTE_CPUFLAG_RISCV_ISA_Z, /* Reserved */
+
+ /* Z sub-extensions (detected via riscv_hwprobe syscall) */
+
+ /* Bit-manipulation */
+ RTE_CPUFLAG_RISCV_ZBA, /* Address generation (sh1add/sh2add/sh3add) */
+ RTE_CPUFLAG_RISCV_ZBB, /* Basic bit-manipulation (clz/ctz/cpop/rev8) */
+ RTE_CPUFLAG_RISCV_ZBC, /* Carry-less multiply (clmul/clmulh/clmulr) */
+ RTE_CPUFLAG_RISCV_ZBS, /* Single-bit instructions (bset/bclr/binv/bext) */
+ RTE_CPUFLAG_RISCV_ZBKB, /* Bit-manipulation for cryptography */
+ RTE_CPUFLAG_RISCV_ZBKC, /* Carry-less multiply for cryptography */
+ RTE_CPUFLAG_RISCV_ZBKX, /* Crossbar permutations */
+
+ /* Cache management */
+ RTE_CPUFLAG_RISCV_ZICBOM, /* Cache-block management operations */
+ RTE_CPUFLAG_RISCV_ZICBOZ, /* Cache-block zero */
+
+ /* Scalar cryptography */
+ RTE_CPUFLAG_RISCV_ZKND, /* AES decryption */
+ RTE_CPUFLAG_RISCV_ZKNE, /* AES encryption */
+ RTE_CPUFLAG_RISCV_ZKNH, /* SHA-256/512 hash */
+ RTE_CPUFLAG_RISCV_ZKSED, /* SM4 block cipher */
+ RTE_CPUFLAG_RISCV_ZKSH, /* SM3 hash */
+ RTE_CPUFLAG_RISCV_ZKT, /* Data-independent execution latency */
+
+ /* Floating-point */
+ RTE_CPUFLAG_RISCV_ZFA, /* Additional floating-point instructions */
+ RTE_CPUFLAG_RISCV_ZFH, /* Half-precision floating-point */
+ RTE_CPUFLAG_RISCV_ZFHMIN, /* Minimal half-precision floating-point */
+ RTE_CPUFLAG_RISCV_ZFBFMIN, /* BFloat16 conversions */
+
+ /* Compressed instructions */
+ RTE_CPUFLAG_RISCV_ZCA, /* Compressed integer instructions */
+ RTE_CPUFLAG_RISCV_ZCB, /* Additional compressed instructions */
+ RTE_CPUFLAG_RISCV_ZCD, /* Compressed double-precision float */
+ RTE_CPUFLAG_RISCV_ZCF, /* Compressed single-precision float */
+ RTE_CPUFLAG_RISCV_ZCMOP, /* Compressed may-be-operations */
+
+ /* Atomic extensions */
+ RTE_CPUFLAG_RISCV_ZAAMO, /* Atomic memory operations */
+ RTE_CPUFLAG_RISCV_ZALRSC, /* Load-reserved/store-conditional */
+ RTE_CPUFLAG_RISCV_ZABHA, /* Byte/halfword atomics */
+ RTE_CPUFLAG_RISCV_ZACAS, /* Compare-and-swap */
+
+ /* Hints and misc */
+ RTE_CPUFLAG_RISCV_ZAWRS, /* Wait-on-reservation-set instructions */
+ RTE_CPUFLAG_RISCV_ZICOND, /* Integer conditional operations */
+ RTE_CPUFLAG_RISCV_ZIHINTNTL,/* Non-temporal locality hints */
+ RTE_CPUFLAG_RISCV_ZIHINTPAUSE, /* Pause hint */
+ RTE_CPUFLAG_RISCV_ZIMOP, /* May-be-operations */
+ RTE_CPUFLAG_RISCV_ZICNTR, /* Base counters and timers */
+ RTE_CPUFLAG_RISCV_ZIHPM, /* Hardware performance counters */
+ RTE_CPUFLAG_RISCV_ZTSO, /* Total store ordering */
+ RTE_CPUFLAG_RISCV_SUPM, /* Pointer masking for U-mode */
+
+ /* Vector sub-extensions */
+ RTE_CPUFLAG_RISCV_ZVBB, /* Vector bit-manipulation */
+ RTE_CPUFLAG_RISCV_ZVBC, /* Vector carry-less multiply */
+ RTE_CPUFLAG_RISCV_ZVKB, /* Vector cryptography bit-manipulation */
+ RTE_CPUFLAG_RISCV_ZVKG, /* Vector GCM/GMAC */
+ RTE_CPUFLAG_RISCV_ZVKNED, /* Vector AES block cipher */
+ RTE_CPUFLAG_RISCV_ZVKNHA, /* Vector SHA-256 */
+ RTE_CPUFLAG_RISCV_ZVKNHB, /* Vector SHA-512 */
+ RTE_CPUFLAG_RISCV_ZVKSED, /* Vector SM4 block cipher */
+ RTE_CPUFLAG_RISCV_ZVKSH, /* Vector SM3 hash */
+ RTE_CPUFLAG_RISCV_ZVKT, /* Vector data-independent execution latency */
+ RTE_CPUFLAG_RISCV_ZVFH, /* Vector half-precision float */
+ RTE_CPUFLAG_RISCV_ZVFHMIN, /* Vector minimal half-precision float */
+ RTE_CPUFLAG_RISCV_ZVFBFMIN, /* Vector BFloat16 conversions */
+ RTE_CPUFLAG_RISCV_ZVFBFWMA, /* Vector BFloat16 widening mul-add */
+ RTE_CPUFLAG_RISCV_ZVE32X, /* Vector 32-bit integer */
+ RTE_CPUFLAG_RISCV_ZVE32F, /* Vector 32-bit float */
+ RTE_CPUFLAG_RISCV_ZVE64X, /* Vector 64-bit integer */
+ RTE_CPUFLAG_RISCV_ZVE64F, /* Vector 64-bit float */
+ RTE_CPUFLAG_RISCV_ZVE64D, /* Vector 64-bit double */
};
#include "generic/rte_cpuflags.h"
-
#endif /* RTE_CPUFLAGS_RISCV_H */
diff --git a/lib/eal/riscv/rte_cpuflags.c b/lib/eal/riscv/rte_cpuflags.c
index 4dec491b0d..6b79af3d13 100644
--- a/lib/eal/riscv/rte_cpuflags.c
+++ b/lib/eal/riscv/rte_cpuflags.c
@@ -3,7 +3,6 @@
* Copyright(c) 2022 SiFive
* Copyright(c) 2022 Semihalf
*/
-
#include <eal_export.h>
#include "rte_cpuflags.h"
@@ -12,6 +11,8 @@
#include <assert.h>
#include <unistd.h>
#include <string.h>
+#include <sys/syscall.h>
+#include <stdbool.h>
#ifndef AT_HWCAP
#define AT_HWCAP 16
@@ -25,15 +26,93 @@
#define AT_PLATFORM 15
#endif
+/*
+ * riscv_hwprobe syscall (Linux 6.4+, syscall number 258).
+ * Allows userspace to query ISA extensions not visible via AT_HWCAP.
+ * See: linux/arch/riscv/include/uapi/asm/hwprobe.h
+ */
+#ifndef __NR_riscv_hwprobe
+#define __NR_riscv_hwprobe 258
+#endif
+
+#ifndef RISCV_HWPROBE_KEY_IMA_EXT_0
+#define RISCV_HWPROBE_KEY_IMA_EXT_0 4
+#endif
+
+/*
+ * Extension bitmasks for RISCV_HWPROBE_KEY_IMA_EXT_0.
+ * Defined here for cross-compilation compatibility; guarded to avoid
+ * conflicts when the system hwprobe.h is available.
+ */
+#ifndef RISCV_HWPROBE_EXT_ZBA
+#define RISCV_HWPROBE_EXT_ZBA (1ULL << 3)
+#define RISCV_HWPROBE_EXT_ZBB (1ULL << 4)
+#define RISCV_HWPROBE_EXT_ZBS (1ULL << 5)
+#define RISCV_HWPROBE_EXT_ZICBOZ (1ULL << 6)
+#define RISCV_HWPROBE_EXT_ZBC (1ULL << 7)
+#define RISCV_HWPROBE_EXT_ZBKB (1ULL << 8)
+#define RISCV_HWPROBE_EXT_ZBKC (1ULL << 9)
+#define RISCV_HWPROBE_EXT_ZBKX (1ULL << 10)
+#define RISCV_HWPROBE_EXT_ZKND (1ULL << 11)
+#define RISCV_HWPROBE_EXT_ZKNE (1ULL << 12)
+#define RISCV_HWPROBE_EXT_ZKNH (1ULL << 13)
+#define RISCV_HWPROBE_EXT_ZKSED (1ULL << 14)
+#define RISCV_HWPROBE_EXT_ZKSH (1ULL << 15)
+#define RISCV_HWPROBE_EXT_ZKT (1ULL << 16)
+#define RISCV_HWPROBE_EXT_ZVBB (1ULL << 17)
+#define RISCV_HWPROBE_EXT_ZVBC (1ULL << 18)
+#define RISCV_HWPROBE_EXT_ZVKB (1ULL << 19)
+#define RISCV_HWPROBE_EXT_ZVKG (1ULL << 20)
+#define RISCV_HWPROBE_EXT_ZVKNED (1ULL << 21)
+#define RISCV_HWPROBE_EXT_ZVKNHA (1ULL << 22)
+#define RISCV_HWPROBE_EXT_ZVKNHB (1ULL << 23)
+#define RISCV_HWPROBE_EXT_ZVKSED (1ULL << 24)
+#define RISCV_HWPROBE_EXT_ZVKSH (1ULL << 25)
+#define RISCV_HWPROBE_EXT_ZVKT (1ULL << 26)
+#define RISCV_HWPROBE_EXT_ZFH (1ULL << 27)
+#define RISCV_HWPROBE_EXT_ZFHMIN (1ULL << 28)
+#define RISCV_HWPROBE_EXT_ZIHINTNTL (1ULL << 29)
+#define RISCV_HWPROBE_EXT_ZVFH (1ULL << 30)
+#define RISCV_HWPROBE_EXT_ZVFHMIN (1ULL << 31)
+#define RISCV_HWPROBE_EXT_ZFA (1ULL << 32)
+#define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33)
+#define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34)
+#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35)
+#define RISCV_HWPROBE_EXT_ZIHINTPAUSE (1ULL << 36)
+#define RISCV_HWPROBE_EXT_ZVE32X (1ULL << 37)
+#define RISCV_HWPROBE_EXT_ZVE32F (1ULL << 38)
+#define RISCV_HWPROBE_EXT_ZVE64X (1ULL << 39)
+#define RISCV_HWPROBE_EXT_ZVE64F (1ULL << 40)
+#define RISCV_HWPROBE_EXT_ZVE64D (1ULL << 41)
+#define RISCV_HWPROBE_EXT_ZIMOP (1ULL << 42)
+#define RISCV_HWPROBE_EXT_ZCA (1ULL << 43)
+#define RISCV_HWPROBE_EXT_ZCB (1ULL << 44)
+#define RISCV_HWPROBE_EXT_ZCD (1ULL << 45)
+#define RISCV_HWPROBE_EXT_ZCF (1ULL << 46)
+#define RISCV_HWPROBE_EXT_ZCMOP (1ULL << 47)
+#define RISCV_HWPROBE_EXT_ZAWRS (1ULL << 48)
+#define RISCV_HWPROBE_EXT_SUPM (1ULL << 49)
+#define RISCV_HWPROBE_EXT_ZICNTR (1ULL << 50)
+#define RISCV_HWPROBE_EXT_ZIHPM (1ULL << 51)
+#define RISCV_HWPROBE_EXT_ZFBFMIN (1ULL << 52)
+#define RISCV_HWPROBE_EXT_ZVFBFMIN (1ULL << 53)
+#define RISCV_HWPROBE_EXT_ZVFBFWMA (1ULL << 54)
+#define RISCV_HWPROBE_EXT_ZICBOM (1ULL << 55)
+#define RISCV_HWPROBE_EXT_ZAAMO (1ULL << 56)
+#define RISCV_HWPROBE_EXT_ZALRSC (1ULL << 57)
+#define RISCV_HWPROBE_EXT_ZABHA (1ULL << 58)
+#endif /* RISCV_HWPROBE_EXT_ZBA */
+
enum cpu_register_t {
REG_NONE = 0,
REG_HWCAP,
REG_HWCAP2,
REG_PLATFORM,
+ REG_HWPROBE_EXT0, /* riscv_hwprobe RISCV_HWPROBE_KEY_IMA_EXT_0 */
REG_MAX
};
-typedef uint32_t hwcap_registers_t[REG_MAX];
+typedef uint64_t hwcap_registers_t[REG_MAX];
/**
* Struct to hold a processor feature entry
@@ -51,41 +130,162 @@ struct feature_entry {
typedef Elf64_auxv_t _Elfx_auxv_t;
const struct feature_entry rte_cpu_feature_table[] = {
- FEAT_DEF(RISCV_ISA_A, REG_HWCAP, 0)
- FEAT_DEF(RISCV_ISA_B, REG_HWCAP, 1)
- FEAT_DEF(RISCV_ISA_C, REG_HWCAP, 2)
- FEAT_DEF(RISCV_ISA_D, REG_HWCAP, 3)
- FEAT_DEF(RISCV_ISA_E, REG_HWCAP, 4)
- FEAT_DEF(RISCV_ISA_F, REG_HWCAP, 5)
- FEAT_DEF(RISCV_ISA_G, REG_HWCAP, 6)
- FEAT_DEF(RISCV_ISA_H, REG_HWCAP, 7)
- FEAT_DEF(RISCV_ISA_I, REG_HWCAP, 8)
- FEAT_DEF(RISCV_ISA_J, REG_HWCAP, 9)
- FEAT_DEF(RISCV_ISA_K, REG_HWCAP, 10)
- FEAT_DEF(RISCV_ISA_L, REG_HWCAP, 11)
- FEAT_DEF(RISCV_ISA_M, REG_HWCAP, 12)
- FEAT_DEF(RISCV_ISA_N, REG_HWCAP, 13)
- FEAT_DEF(RISCV_ISA_O, REG_HWCAP, 14)
- FEAT_DEF(RISCV_ISA_P, REG_HWCAP, 15)
- FEAT_DEF(RISCV_ISA_Q, REG_HWCAP, 16)
- FEAT_DEF(RISCV_ISA_R, REG_HWCAP, 17)
- FEAT_DEF(RISCV_ISA_S, REG_HWCAP, 18)
- FEAT_DEF(RISCV_ISA_T, REG_HWCAP, 19)
- FEAT_DEF(RISCV_ISA_U, REG_HWCAP, 20)
- FEAT_DEF(RISCV_ISA_V, REG_HWCAP, 21)
- FEAT_DEF(RISCV_ISA_W, REG_HWCAP, 22)
- FEAT_DEF(RISCV_ISA_X, REG_HWCAP, 23)
- FEAT_DEF(RISCV_ISA_Y, REG_HWCAP, 24)
- FEAT_DEF(RISCV_ISA_Z, REG_HWCAP, 25)
+ /* Single-letter ISA extensions via AT_HWCAP */
+ FEAT_DEF(RISCV_ISA_A, REG_HWCAP, 0)
+ FEAT_DEF(RISCV_ISA_B, REG_HWCAP, 1)
+ FEAT_DEF(RISCV_ISA_C, REG_HWCAP, 2)
+ FEAT_DEF(RISCV_ISA_D, REG_HWCAP, 3)
+ FEAT_DEF(RISCV_ISA_E, REG_HWCAP, 4)
+ FEAT_DEF(RISCV_ISA_F, REG_HWCAP, 5)
+ FEAT_DEF(RISCV_ISA_G, REG_HWCAP, 6)
+ FEAT_DEF(RISCV_ISA_H, REG_HWCAP, 7)
+ FEAT_DEF(RISCV_ISA_I, REG_HWCAP, 8)
+ FEAT_DEF(RISCV_ISA_J, REG_HWCAP, 9)
+ FEAT_DEF(RISCV_ISA_K, REG_HWCAP, 10)
+ FEAT_DEF(RISCV_ISA_L, REG_HWCAP, 11)
+ FEAT_DEF(RISCV_ISA_M, REG_HWCAP, 12)
+ FEAT_DEF(RISCV_ISA_N, REG_HWCAP, 13)
+ FEAT_DEF(RISCV_ISA_O, REG_HWCAP, 14)
+ FEAT_DEF(RISCV_ISA_P, REG_HWCAP, 15)
+ FEAT_DEF(RISCV_ISA_Q, REG_HWCAP, 16)
+ FEAT_DEF(RISCV_ISA_R, REG_HWCAP, 17)
+ FEAT_DEF(RISCV_ISA_S, REG_HWCAP, 18)
+ FEAT_DEF(RISCV_ISA_T, REG_HWCAP, 19)
+ FEAT_DEF(RISCV_ISA_U, REG_HWCAP, 20)
+ FEAT_DEF(RISCV_ISA_V, REG_HWCAP, 21)
+ FEAT_DEF(RISCV_ISA_W, REG_HWCAP, 22)
+ FEAT_DEF(RISCV_ISA_X, REG_HWCAP, 23)
+ FEAT_DEF(RISCV_ISA_Y, REG_HWCAP, 24)
+ FEAT_DEF(RISCV_ISA_Z, REG_HWCAP, 25)
+
+ /* Z sub-extensions via riscv_hwprobe syscall */
+
+ /* Bit-manipulation */
+ FEAT_DEF(RISCV_ZBA, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZBA))
+ FEAT_DEF(RISCV_ZBB, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZBB))
+ FEAT_DEF(RISCV_ZBC, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZBC))
+ FEAT_DEF(RISCV_ZBS, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZBS))
+ FEAT_DEF(RISCV_ZBKB, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZBKB))
+ FEAT_DEF(RISCV_ZBKC, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZBKC))
+ FEAT_DEF(RISCV_ZBKX, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZBKX))
+
+ /* Cache management */
+ FEAT_DEF(RISCV_ZICBOM, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZICBOM))
+ FEAT_DEF(RISCV_ZICBOZ, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZICBOZ))
+
+ /* Scalar cryptography */
+ FEAT_DEF(RISCV_ZKND, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZKND))
+ FEAT_DEF(RISCV_ZKNE, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZKNE))
+ FEAT_DEF(RISCV_ZKNH, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZKNH))
+ FEAT_DEF(RISCV_ZKSED, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZKSED))
+ FEAT_DEF(RISCV_ZKSH, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZKSH))
+ FEAT_DEF(RISCV_ZKT, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZKT))
+
+ /* Floating-point */
+ FEAT_DEF(RISCV_ZFA, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZFA))
+ FEAT_DEF(RISCV_ZFH, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZFH))
+ FEAT_DEF(RISCV_ZFHMIN, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZFHMIN))
+ FEAT_DEF(RISCV_ZFBFMIN, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZFBFMIN))
+
+ /* Compressed instructions */
+ FEAT_DEF(RISCV_ZCA, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZCA))
+ FEAT_DEF(RISCV_ZCB, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZCB))
+ FEAT_DEF(RISCV_ZCD, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZCD))
+ FEAT_DEF(RISCV_ZCF, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZCF))
+ FEAT_DEF(RISCV_ZCMOP, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZCMOP))
+
+ /* Atomic extensions */
+ FEAT_DEF(RISCV_ZAAMO, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZAAMO))
+ FEAT_DEF(RISCV_ZALRSC, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZALRSC))
+ FEAT_DEF(RISCV_ZABHA, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZABHA))
+ FEAT_DEF(RISCV_ZACAS, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZACAS))
+
+ /* Hints and misc */
+ FEAT_DEF(RISCV_ZAWRS, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZAWRS))
+ FEAT_DEF(RISCV_ZICOND, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZICOND))
+ FEAT_DEF(RISCV_ZIHINTNTL, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZIHINTNTL))
+ FEAT_DEF(RISCV_ZIHINTPAUSE, REG_HWPROBE_EXT0,
+ __builtin_ctzll(RISCV_HWPROBE_EXT_ZIHINTPAUSE))
+ FEAT_DEF(RISCV_ZIMOP, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZIMOP))
+ FEAT_DEF(RISCV_ZICNTR, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZICNTR))
+ FEAT_DEF(RISCV_ZIHPM, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZIHPM))
+ FEAT_DEF(RISCV_ZTSO, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZTSO))
+ FEAT_DEF(RISCV_SUPM, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_SUPM))
+
+ /* Vector sub-extensions */
+ FEAT_DEF(RISCV_ZVBB, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVBB))
+ FEAT_DEF(RISCV_ZVBC, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVBC))
+ FEAT_DEF(RISCV_ZVKB, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVKB))
+ FEAT_DEF(RISCV_ZVKG, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVKG))
+ FEAT_DEF(RISCV_ZVKNED, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVKNED))
+ FEAT_DEF(RISCV_ZVKNHA, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVKNHA))
+ FEAT_DEF(RISCV_ZVKNHB, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVKNHB))
+ FEAT_DEF(RISCV_ZVKSED, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVKSED))
+ FEAT_DEF(RISCV_ZVKSH, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVKSH))
+ FEAT_DEF(RISCV_ZVKT, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVKT))
+ FEAT_DEF(RISCV_ZVFH, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVFH))
+ FEAT_DEF(RISCV_ZVFHMIN, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVFHMIN))
+ FEAT_DEF(RISCV_ZVFBFMIN, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVFBFMIN))
+ FEAT_DEF(RISCV_ZVFBFWMA, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVFBFWMA))
+ FEAT_DEF(RISCV_ZVE32X, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVE32X))
+ FEAT_DEF(RISCV_ZVE32F, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVE32F))
+ FEAT_DEF(RISCV_ZVE64X, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVE64X))
+ FEAT_DEF(RISCV_ZVE64F, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVE64F))
+ FEAT_DEF(RISCV_ZVE64D, REG_HWPROBE_EXT0, __builtin_ctzll(RISCV_HWPROBE_EXT_ZVE64D))
};
+
+/*
+ * Cache for riscv_hwprobe result. hwprobe is a syscall (unlike getauxval
+ * which reads in-process memory), so we call it once at startup and cache
+ * the result here.
+ */
+static uint64_t hwprobe_ext0_value;
+static bool hwprobe_ext0_valid;
+
+/*
+ * Minimal struct matching the kernel's riscv_hwprobe layout.
+ * Defined locally for cross-compilation compatibility.
+ */
+struct rte_riscv_hwprobe {
+ int64_t key;
+ uint64_t value;
+};
+
+/*
+ * Call riscv_hwprobe syscall to query ISA extensions.
+ * cpusetsize=0, cpus=NULL means: query all CPUs, return intersection.
+ * Silently fails on kernels < 6.4 (returns -ENOSYS); all Z sub-extension
+ * flags will report unsupported in that case.
+ */
+static void
+riscv_hwprobe_init(void)
+{
+ struct rte_riscv_hwprobe pairs[1] = {
+ { .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = 0 },
+ };
+ long ret;
+
+ ret = syscall(__NR_riscv_hwprobe, pairs, 1, 0, NULL, 0);
+ if (ret == 0 && pairs[0].key >= 0) {
+ hwprobe_ext0_value = pairs[0].value;
+ hwprobe_ext0_valid = true;
+ }
+}
+
+RTE_INIT(riscv_cpu_init)
+{
+ riscv_hwprobe_init();
+}
+
/*
- * Read AUXV software register and get cpu features for ARM
+ * Read all CPU feature sources into the registers array.
*/
static void
rte_cpu_get_features(hwcap_registers_t out)
{
- out[REG_HWCAP] = rte_cpu_getauxval(AT_HWCAP);
- out[REG_HWCAP2] = rte_cpu_getauxval(AT_HWCAP2);
+ out[REG_HWCAP] = rte_cpu_getauxval(AT_HWCAP);
+ out[REG_HWCAP2] = rte_cpu_getauxval(AT_HWCAP2);
+ out[REG_HWPROBE_EXT0] = hwprobe_ext0_valid ? hwprobe_ext0_value : 0;
}
/*
--
2.43.0
More information about the dev
mailing list