Skip to content

RISC-V: riscv_hwprobe-based feature detection on Linux / Android #1770

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 16, 2025
5 changes: 4 additions & 1 deletion crates/std_detect/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,14 @@ crate from working on applications in which `std` is not available.
[`cupid`](https://crates.io/crates/cupid) crate.

* Linux/Android:
* `arm{32, 64}`, `mips{32,64}{,el}`, `powerpc{32,64}{,le}`, `riscv{32,64}`, `loongarch64`, `s390x`:
* `arm{32, 64}`, `mips{32,64}{,el}`, `powerpc{32,64}{,le}`, `loongarch64`, `s390x`:
`std_detect` supports these on Linux by querying ELF auxiliary vectors (using `getauxval`
when available), and if that fails, by querying `/proc/cpuinfo`.
* `arm64`: partial support for doing run-time feature detection by directly
querying `mrs` is implemented for Linux >= 4.11, but not enabled by default.
* `riscv{32,64}`:
`std_detect` supports these on Linux by querying `riscv_hwprobe`, and
by querying ELF auxiliary vectors (using `getauxval` when available).

* FreeBSD:
* `arm32`, `powerpc64`: `std_detect` supports these on FreeBSD by querying ELF
Expand Down
161 changes: 138 additions & 23 deletions crates/std_detect/src/detect/arch/riscv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,47 @@ features! {
/// * RV32I: `"rv32i"`
/// * RV64I: `"rv64i"`
/// * A: `"a"`
/// * Bit-Manipulation Extensions:
/// * Zaamo: `"zaamo"`
/// * Zalrsc: `"zalrsc"`
/// * B: `"b"`
/// * Zba: `"zba"`
/// * Zbb: `"zbb"`
/// * Zbc: `"zbc"`
/// * Zbs: `"zbs"`
/// * C: `"c"`
/// * Zca: `"zca"`
/// * Zcd: `"zcd"` (if D is enabled)
/// * Zcf: `"zcf"` (if F is enabled on RV32)
/// * D: `"d"`
/// * F: `"f"`
/// * M: `"m"`
/// * Q: `"q"`
/// * V: `"v"`
/// * Zve32x: `"zve32x"`
/// * Zve32f: `"zve32f"`
/// * Zve64x: `"zve64x"`
/// * Zve64f: `"zve64f"`
/// * Zve64d: `"zve64d"`
/// * Zicboz: `"zicboz"`
/// * Zicntr: `"zicntr"`
/// * Zicond: `"zicond"`
/// * Zicsr: `"zicsr"`
/// * Zifencei: `"zifencei"`
/// * Zihintntl: `"zihintntl"`
/// * Zihintpause: `"zihintpause"`
/// * Zihpm: `"zihpm"`
/// * Zimop: `"zimop"`
/// * Zacas: `"zacas"`
/// * Zawrs: `"zawrs"`
/// * Zfa: `"zfa"`
/// * Zfh: `"zfh"`
/// * Zfhmin: `"zfhmin"`
/// * Zfinx: `"zfinx"`
/// * Zdinx: `"zdinx"`
/// * Zhinx: `"zhinx"`
/// * Zhinxmin: `"zhinxmin"`
/// * Zcb: `"zcb"`
/// * Zcmop: `"zcmop"`
/// * Zbc: `"zbc"`
/// * Zbkb: `"zbkb"`
/// * Zbkc: `"zbkc"`
/// * Zbkx: `"zbkx"`
Expand All @@ -65,6 +84,24 @@ features! {
/// * Zksed: `"zksed"`
/// * Zksh: `"zksh"`
/// * Zkt: `"zkt"`
/// * Zvbb: `"zvbb"`
/// * Zvbc: `"zvbc"`
/// * Zvfh: `"zvfh"`
/// * Zvfhmin: `"zvfhmin"`
/// * Zvkb: `"zvkb"`
/// * Zvkg: `"zvkg"`
/// * Zvkn: `"zvkn"`
/// * Zvkned: `"zvkned"`
/// * Zvknha: `"zvknha"`
/// * Zvknhb: `"zvknhb"`
/// * Zvknc: `"zvknc"`
/// * Zvkng: `"zvkng"`
/// * Zvks: `"zvks"`
/// * Zvksed: `"zvksed"`
/// * Zvksh: `"zvksh"`
/// * Zvksc: `"zvksc"`
/// * Zvksg: `"zvksg"`
/// * Zvkt: `"zvkt"`
/// * Ztso: `"ztso"`
///
/// There's also bases and extensions marked as standard instruction set,
Expand All @@ -78,13 +115,14 @@ features! {
/// * P: `"p"`
/// * Zam: `"zam"`
///
/// Defined by Privileged Specification:
/// # Performance Hints
///
/// * *Supervisor-Level ISA* (not "S" extension): `"s"`
/// * H (hypervisor): `"h"`
/// * Svnapot: `"svnapot"`
/// * Svpbmt: `"svpbmt"`
/// * Svinval: `"svinval"`
/// The two features below define performance hints for unaligned
/// scalar/vector memory accesses, respectively. If enabled, it denotes that
/// corresponding unaligned memory access is reasonably fast.
///
/// * `"unaligned-scalar-mem"`
/// * `"unaligned-vector-mem"`
#[stable(feature = "riscv_ratified", since = "1.78.0")]

@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] rv32i: "rv32i";
Expand All @@ -100,6 +138,11 @@ features! {
without cfg check: true;
/// RV128I Base Integer Instruction Set

@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] unaligned_scalar_mem: "unaligned-scalar-mem";
/// Has reasonably performant unaligned scalar
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] unaligned_vector_mem: "unaligned-vector-mem";
/// Has reasonably performant unaligned vector

@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zicsr: "zicsr";
without cfg check: true;
/// "Zicsr" Extension for Control and Status Register (CSR) Instructions
Expand All @@ -113,15 +156,35 @@ features! {
without cfg check: true;
/// "Zifencei" Extension for Instruction-Fetch Fence

@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zihintntl: "zihintntl";
without cfg check: true;
/// "Zihintntl" Extension for Non-Temporal Locality Hints
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zihintpause: "zihintpause";
without cfg check: true;
/// "Zihintpause" Extension for Pause Hint
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zimop: "zimop";
without cfg check: true;
/// "Zimop" Extension for May-Be-Operations
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zicboz: "zicboz";
without cfg check: true;
/// "Zicboz" Extension for Cache-Block Zero Instruction
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zicond: "zicond";
without cfg check: true;
/// "Zicond" Extension for Integer Conditional Operations

@FEATURE: #[stable(feature = "riscv_ratified", since = "1.78.0")] m: "m";
/// "M" Extension for Integer Multiplication and Division

@FEATURE: #[stable(feature = "riscv_ratified", since = "1.78.0")] a: "a";
/// "A" Extension for Atomic Instructions
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zalrsc: "zalrsc";
/// "Zalrsc" Extension for Load-Reserved/Store-Conditional Instructions
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zaamo: "zaamo";
/// "Zaamo" Extension for Atomic Memory Operations
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zawrs: "zawrs";
/// "Zawrs" Extension for Wait-on-Reservation-Set Instructions
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zacas: "zacas";
/// "Zacas" Extension for Atomic Compare-and-Swap (CAS) Instructions
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zam: "zam";
without cfg check: true;
/// "Zam" Extension for Misaligned Atomics
Expand All @@ -140,6 +203,9 @@ features! {
/// "Zfh" Extension for Half-Precision Floating-Point
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zfhmin: "zfhmin";
/// "Zfhmin" Extension for Minimal Half-Precision Floating-Point
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zfa: "zfa";
without cfg check: true;
/// "Zfa" Extension for Additional Floating-Point Instructions

@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zfinx: "zfinx";
/// "Zfinx" Extension for Single-Precision Floating-Point in Integer Registers
Expand All @@ -152,7 +218,25 @@ features! {

@FEATURE: #[stable(feature = "riscv_ratified", since = "1.78.0")] c: "c";
/// "C" Extension for Compressed Instructions
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zca: "zca";
without cfg check: true;
/// "Zca" Compressed Instructions excluding Floating-Point Loads/Stores
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zcf: "zcf";
without cfg check: true;
/// "Zcf" Compressed Instructions for Single-Precision Floating-Point Loads/Stores on RV32
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zcd: "zcd";
without cfg check: true;
/// "Zcd" Compressed Instructions for Double-Precision Floating-Point Loads/Stores
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zcb: "zcb";
without cfg check: true;
/// "Zcb" Simple Code-size Saving Compressed Instructions
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zcmop: "zcmop";
without cfg check: true;
/// "Zcmop" Extension for Compressed May-Be-Operations

@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] b: "b";
without cfg check: true;
/// "B" Extension for Bit Manipulation
@FEATURE: #[stable(feature = "riscv_ratified", since = "1.78.0")] zba: "zba";
/// "Zba" Extension for Address Generation
@FEATURE: #[stable(feature = "riscv_ratified", since = "1.78.0")] zbb: "zbb";
Expand Down Expand Up @@ -191,23 +275,54 @@ features! {

@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] v: "v";
/// "V" Extension for Vector Operations
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zve32x: "zve32x";
/// "Zve32x" Vector Extension for Embedded Processors (32-bit+; Integer)
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zve32f: "zve32f";
/// "Zve32f" Vector Extension for Embedded Processors (32-bit+; with Single-Precision Floating-Point)
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zve64x: "zve64x";
/// "Zve64x" Vector Extension for Embedded Processors (64-bit+; Integer)
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zve64f: "zve64f";
/// "Zve64f" Vector Extension for Embedded Processors (64-bit+; with Single-Precision Floating-Point)
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zve64d: "zve64d";
/// "Zve64d" Vector Extension for Embedded Processors (64-bit+; with Double-Precision Floating-Point)
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvfh: "zvfh";
/// "Zvfh" Vector Extension for Half-Precision Floating-Point
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvfhmin: "zvfhmin";
/// "Zvfhmin" Vector Extension for Minimal Half-Precision Floating-Point

@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] svnapot: "svnapot";
without cfg check: true;
/// "Svnapot" Extension for NAPOT Translation Contiguity
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] svpbmt: "svpbmt";
without cfg check: true;
/// "Svpbmt" Extension for Page-Based Memory Types
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] svinval: "svinval";
without cfg check: true;
/// "Svinval" Extension for Fine-Grained Address-Translation Cache Invalidation
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] h: "h";
without cfg check: true;
/// "H" Extension for Hypervisor Support
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvbb: "zvbb";
/// "Zvbb" Extension for Vector Basic Bit-Manipulation
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvbc: "zvbc";
/// "Zvbc" Extension for Vector Carryless Multiplication
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvkb: "zvkb";
/// "Zvkb" Extension for Vector Cryptography Bit-Manipulation
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvkg: "zvkg";
/// "Zvkg" Cryptography Extension for Vector GCM/GMAC
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvkned: "zvkned";
/// "Zvkned" Cryptography Extension for NIST Suite: Vector AES Block Cipher
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvknha: "zvknha";
/// "Zvknha" Cryptography Extension for Vector SHA-2 Secure Hash (SHA-256)
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvknhb: "zvknhb";
/// "Zvknhb" Cryptography Extension for Vector SHA-2 Secure Hash (SHA-256/512)
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvksed: "zvksed";
/// "Zvksed" Cryptography Extension for ShangMi Suite: Vector SM4 Block Cipher
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvksh: "zvksh";
/// "Zvksh" Cryptography Extension for ShangMi Suite: Vector SM3 Secure Hash
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvkn: "zvkn";
/// "Zvkn" Cryptography Extension for NIST Algorithm Suite
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvknc: "zvknc";
/// "Zvknc" Cryptography Extension for NIST Algorithm Suite with Carryless Multiply
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvkng: "zvkng";
/// "Zvkng" Cryptography Extension for NIST Algorithm Suite with GCM
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvks: "zvks";
/// "Zvks" Cryptography Extension for ShangMi Algorithm Suite
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvksc: "zvksc";
/// "Zvksc" Cryptography Extension for ShangMi Algorithm Suite with Carryless Multiply
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvksg: "zvksg";
/// "Zvksg" Cryptography Extension for ShangMi Algorithm Suite with GCM
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvkt: "zvkt";
/// "Zvkt" Extension for Vector Data-Independent Execution Latency

@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] s: "s";
without cfg check: true;
/// Supervisor-Level ISA
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] j: "j";
without cfg check: true;
/// "J" Extension for Dynamically Translated Languages
Expand Down
2 changes: 1 addition & 1 deletion crates/std_detect/src/detect/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const CACHE_CAPACITY: u32 = 93;
/// This type is used to initialize the cache
// The derived `Default` implementation will initialize the field to zero,
// which is what we want.
#[derive(Copy, Clone, Default)]
#[derive(Copy, Clone, Default, PartialEq, Eq)]
pub(crate) struct Initializer(u128);

// NOTE: the `debug_assert!` would catch that we do not add more Features than
Expand Down
3 changes: 3 additions & 0 deletions crates/std_detect/src/detect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ cfg_if! {
#[path = "os/x86.rs"]
mod os;
} else if #[cfg(all(any(target_os = "linux", target_os = "android"), feature = "libc"))] {
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
#[path = "os/riscv.rs"]
mod riscv;
#[path = "os/linux/mod.rs"]
mod os;
} else if #[cfg(all(target_os = "freebsd", feature = "libc"))] {
Expand Down
Loading