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 <[email protected]> --- app/test/test_cpuflags.c | 167 +++++++++++++++++ lib/eal/riscv/include/rte_cpuflags.h | 79 +++++++- lib/eal/riscv/rte_cpuflags.c | 261 +++++++++++++++++++++++---- 3 files changed, 473 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..88272a1b99 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 (CMO) */ + 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 (wrs.nto/wrs.sto) */ + 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..96b8eca96c 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,161 @@ 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

