diff --git a/crates/std_detect/README.md b/crates/std_detect/README.md
index 5191b2f665..0053d777aa 100644
--- a/crates/std_detect/README.md
+++ b/crates/std_detect/README.md
@@ -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
diff --git a/crates/std_detect/src/detect/arch/riscv.rs b/crates/std_detect/src/detect/arch/riscv.rs
index 2368131fea..cab1b60705 100644
--- a/crates/std_detect/src/detect/arch/riscv.rs
+++ b/crates/std_detect/src/detect/arch/riscv.rs
@@ -79,14 +79,6 @@ features! {
     /// * P: `"p"`
     /// * Zam: `"zam"`
     ///
-    /// Defined by Privileged Specification:
-    ///
-    /// * Supervisor: `"s"`
-    /// * Svnapot: `"svnapot"`
-    /// * Svpbmt: `"svpbmt"`
-    /// * Svinval: `"svinval"`
-    /// * Hypervisor: `"h"`
-    ///
     /// [ISA manual]: https://github.com/riscv/riscv-isa-manual/
     #[stable(feature = "riscv_ratified", since = "1.78.0")]
 
@@ -125,6 +117,10 @@ features! {
 
     @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")] zacas: "zacas";
+    /// Atomic Compare-And-Swap Instructions
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zawrs: "zawrs";
+    /// Wait on Reservation Set
     @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zam: "zam";
     without cfg check: true;
     /// "Zam" Extension for Misaligned Atomics
@@ -194,23 +190,59 @@ 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")] zvfh: "zvfh";
+    /// Vector Extension for Half-Precision Floating-Point
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvfhmin: "zvfhmin";
+    /// Vector Extension for Minimal Half-Precision Floating-Point
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zve32x: "zve32x";
+    /// Vector Extensions for Embedded Processors
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zve32f: "zve32f";
+    /// Vector Extensions for Embedded Processors
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zve64x: "zve64x";
+    /// Vector Extensions for Embedded Processors
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zve64f: "zve64f";
+    /// Vector Extensions for Embedded Processors
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zve64d: "zve64d";
+    /// Vector Extensions for Embedded Processors
 
-    @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")] zvkb: "zvkb";
+    /// Vector Bit-manipulation used in Cryptography
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvbb: "zvbb";
+    /// Vector basic bit-manipulation instructions
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvbc: "zvbc";
+    /// Vector Carryless Multiplication
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvkg: "zvkg";
+    /// Vector GCM instructions for Cryptography
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvkned: "zvkned";
+    /// Vector AES Encryption & Decryption (Single Round)
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvknha: "zvknha";
+    /// Vector SHA-2 (SHA-256 only))
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvknhb: "zvknhb";
+    /// Vector SHA-2 (SHA-256 and SHA-512)
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvksed: "zvksed";
+    /// SM4 Block Cipher Instructions
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvksh: "zvksh";
+    /// SM3 Hash Function Instructions
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvkn: "zvkn";
+    /// Shorthand for 'Zvkned', 'Zvknhb', 'Zvkb', and 'Zvkt'
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvknc: "zvknc";
+    /// Shorthand for 'Zvkn' and 'Zvbc'
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvkng: "zvkng";
+    /// Shorthand for 'Zvkn' and 'Zvkg'
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvks: "zvks";
+    /// Shorthand for 'Zvksed', 'Zvksh', 'Zvkb', and 'Zvkt'
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvksc: "zvksc";
+    /// Shorthand for 'Zvks' and 'Zvbc'
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvksg: "zvksg";
+    /// Shorthand for 'Zvks' and 'Zvkg'
+    @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvkt: "zvkt";
+    /// Vector Data-Independent Execution Latency
+
+    @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")] 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
diff --git a/crates/std_detect/src/detect/os/linux/riscv.rs b/crates/std_detect/src/detect/os/linux/riscv.rs
index 2a9671d75d..ae364e8804 100644
--- a/crates/std_detect/src/detect/os/linux/riscv.rs
+++ b/crates/std_detect/src/detect/os/linux/riscv.rs
@@ -1,11 +1,118 @@
 //! Run-time feature detection for RISC-V on Linux.
+//!
+//! On RISC-V, detection using auxv only supports single-letter extensions.
+//! So, we use riscv_hwprobe that supports multi-letter extensions if available.
+//! <https://www.kernel.org/doc/html/latest/arch/riscv/hwprobe.html>
+
+use core::ptr;
 
 use super::auxvec;
 use crate::detect::{Feature, bit, cache};
 
-/// Read list of supported features from the auxiliary vector.
+// See <https://github.com/torvalds/linux/blob/master/arch/riscv/include/uapi/asm/hwprobe.h>
+// for riscv_hwprobe struct and RISCV_HWPROBE_* constants.
+
+#[repr(C)]
+struct riscv_hwprobe {
+    key: i64,
+    value: u64,
+}
+
+#[allow(non_upper_case_globals)]
+const __NR_riscv_hwprobe: libc::c_long = 258;
+
+// const RISCV_HWPROBE_KEY_BASE_BEHAVIOR: i64 = 3;
+// const RISCV_HWPROBE_BASE_BEHAVIOR_IMA: u64 = 1 << 0;
+
+const RISCV_HWPROBE_KEY_IMA_EXT_0: i64 = 4;
+// const RISCV_HWPROBE_IMA_FD: u64 = 1 << 0;
+// const RISCV_HWPROBE_IMA_C: u64 = 1 << 1;
+// const RISCV_HWPROBE_IMA_V: u64 = 1 << 2;
+const RISCV_HWPROBE_EXT_ZBA: u64 = 1 << 3;
+const RISCV_HWPROBE_EXT_ZBB: u64 = 1 << 4;
+const RISCV_HWPROBE_EXT_ZBS: u64 = 1 << 5;
+// const RISCV_HWPROBE_EXT_ZICBOZ: u64 = 1 << 6;
+const RISCV_HWPROBE_EXT_ZBC: u64 = 1 << 7;
+const RISCV_HWPROBE_EXT_ZBKB: u64 = 1 << 8;
+const RISCV_HWPROBE_EXT_ZBKC: u64 = 1 << 9;
+const RISCV_HWPROBE_EXT_ZBKX: u64 = 1 << 10;
+const RISCV_HWPROBE_EXT_ZKND: u64 = 1 << 11;
+const RISCV_HWPROBE_EXT_ZKNE: u64 = 1 << 12;
+const RISCV_HWPROBE_EXT_ZKNH: u64 = 1 << 13;
+const RISCV_HWPROBE_EXT_ZKSED: u64 = 1 << 14;
+const RISCV_HWPROBE_EXT_ZKSH: u64 = 1 << 15;
+const RISCV_HWPROBE_EXT_ZKT: u64 = 1 << 16;
+const RISCV_HWPROBE_EXT_ZVBB: u64 = 1 << 17;
+const RISCV_HWPROBE_EXT_ZVBC: u64 = 1 << 18;
+const RISCV_HWPROBE_EXT_ZVKB: u64 = 1 << 19;
+const RISCV_HWPROBE_EXT_ZVKG: u64 = 1 << 20;
+const RISCV_HWPROBE_EXT_ZVKNED: u64 = 1 << 21;
+const RISCV_HWPROBE_EXT_ZVKNHA: u64 = 1 << 22;
+const RISCV_HWPROBE_EXT_ZVKNHB: u64 = 1 << 23;
+const RISCV_HWPROBE_EXT_ZVKSED: u64 = 1 << 24;
+const RISCV_HWPROBE_EXT_ZVKSH: u64 = 1 << 25;
+const RISCV_HWPROBE_EXT_ZVKT: u64 = 1 << 26;
+const RISCV_HWPROBE_EXT_ZFH: u64 = 1 << 27;
+const RISCV_HWPROBE_EXT_ZFHMIN: u64 = 1 << 28;
+// const RISCV_HWPROBE_EXT_ZIHINTNTL: u64 = 1 << 29;
+const RISCV_HWPROBE_EXT_ZVFH: u64 = 1 << 30;
+const RISCV_HWPROBE_EXT_ZVFHMIN: u64 = 1 << 31;
+// const RISCV_HWPROBE_EXT_ZFA: u64 = 1 << 32;
+const RISCV_HWPROBE_EXT_ZTSO: u64 = 1 << 33;
+const RISCV_HWPROBE_EXT_ZACAS: u64 = 1 << 34;
+// const RISCV_HWPROBE_EXT_ZICOND: u64 = 1 << 35;
+const RISCV_HWPROBE_EXT_ZIHINTPAUSE: u64 = 1 << 36;
+// const RISCV_HWPROBE_EXT_ZVE32X: u64 = 1 << 37;
+// const RISCV_HWPROBE_EXT_ZVE32F: u64 = 1 << 38;
+// const RISCV_HWPROBE_EXT_ZVE64X: u64 = 1 << 39;
+// const RISCV_HWPROBE_EXT_ZVE64F: u64 = 1 << 40;
+// const RISCV_HWPROBE_EXT_ZVE64D: u64 = 1 << 41;
+// const RISCV_HWPROBE_EXT_ZIMOP: u64 = 1 << 42;
+// const RISCV_HWPROBE_EXT_ZCA: u64 = 1 << 43;
+// const RISCV_HWPROBE_EXT_ZCB: u64 = 1 << 44;
+// const RISCV_HWPROBE_EXT_ZCD: u64 = 1 << 45;
+// const RISCV_HWPROBE_EXT_ZCF: u64 = 1 << 46;
+// const RISCV_HWPROBE_EXT_ZCMOP: u64 = 1 << 47;
+const RISCV_HWPROBE_EXT_ZAWRS: u64 = 1 << 48;
+// const RISCV_HWPROBE_EXT_SUPM: u64 = 1 << 49;
+
+const RISCV_HWPROBE_KEY_CPUPERF_0: i64 = 5;
+const RISCV_HWPROBE_MISALIGNED_FAST: u64 = 3;
+const RISCV_HWPROBE_MISALIGNED_MASK: u64 = 7;
+
+const RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF: i64 = 10;
+const RISCV_HWPROBE_MISALIGNED_VECTOR_FAST: u64 = 3;
+
+// syscall returns an unsupported error if riscv_hwprobe is not supported,
+// so we can safely use this function on older versions of Linux.
+fn _riscv_hwprobe(out: &mut [riscv_hwprobe]) -> bool {
+    unsafe fn __riscv_hwprobe(
+        pairs: *mut riscv_hwprobe,
+        pair_count: libc::size_t,
+        cpu_set_size: libc::size_t,
+        cpus: *mut libc::c_ulong,
+        flags: libc::c_uint,
+    ) -> libc::c_long {
+        unsafe {
+            libc::syscall(
+                __NR_riscv_hwprobe,
+                pairs,
+                pair_count,
+                cpu_set_size,
+                cpus,
+                flags,
+            )
+        }
+    }
+
+    let len = out.len();
+    unsafe { __riscv_hwprobe(out.as_mut_ptr(), len, 0, ptr::null_mut(), 0) == 0 }
+}
+
+/// Read list of supported features from riscv_hwprobe or the auxiliary vector.
 pub(crate) fn detect_features() -> cache::Initializer {
     let mut value = cache::Initializer::default();
+
     let enable_feature = |value: &mut cache::Initializer, feature, enable| {
         if enable {
             value.set(feature as u32);
@@ -46,29 +153,172 @@ pub(crate) fn detect_features() -> cache::Initializer {
     );
     let has_i = bit::test(auxv.hwcap, (b'i' - b'a').into());
     // If future RV128I is supported, implement with `enable_feature` here
-    #[cfg(target_pointer_width = "64")]
+    // Checking target_pointer_width instead of target_arch is incorrect since
+    // there are RV64ILP32* ABIs.
+    #[cfg(target_arch = "riscv64")]
     enable_feature(&mut value, Feature::rv64i, has_i);
-    #[cfg(target_pointer_width = "32")]
+    #[cfg(target_arch = "riscv32")]
     enable_feature(&mut value, Feature::rv32i, has_i);
-    #[cfg(target_pointer_width = "32")]
+    // FIXME: e is not exposed in any of asm/hwcap.h, uapi/asm/hwcap.h, uapi/asm/hwprobe.h
+    #[cfg(target_arch = "riscv32")]
     enable_feature(
         &mut value,
         Feature::rv32e,
         bit::test(auxv.hwcap, (b'e' - b'a').into()),
     );
-    enable_feature(
-        &mut value,
-        Feature::h,
-        bit::test(auxv.hwcap, (b'h' - b'a').into()),
-    );
     enable_feature(
         &mut value,
         Feature::m,
         bit::test(auxv.hwcap, (b'm' - b'a').into()),
     );
-    // FIXME: Auxvec does not show supervisor feature support, but this mode may be useful
-    // to detect when Rust is used to write Linux kernel modules.
-    // These should be more than Auxvec way to detect supervisor features.
+    let has_v = bit::test(auxv.hwcap, (b'v' - b'a').into());
+    enable_features(
+        &mut value,
+        &[
+            Feature::v,
+            Feature::zve32f,
+            Feature::zve32x,
+            Feature::zve64d,
+            Feature::zve64f,
+            Feature::zve64x,
+        ],
+        has_v,
+    );
+
+    let mut out = [
+        riscv_hwprobe {
+            key: RISCV_HWPROBE_KEY_IMA_EXT_0,
+            value: 0,
+        },
+        riscv_hwprobe {
+            key: RISCV_HWPROBE_KEY_CPUPERF_0,
+            value: 0,
+        },
+        riscv_hwprobe {
+            key: RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF,
+            value: 0,
+        },
+    ];
+    if _riscv_hwprobe(&mut out) {
+        let mut enable_feature = |feature, enable| {
+            if enable {
+                value.set(feature as u32);
+            }
+        };
+        if out[0].key != -1 {
+            let ima_ext_0 = out[0].value;
+            // i, m, a, f, d, zicsr, and c extensions are detected by hwcap.
+            // let fd = ima_ext_0 & RISCV_HWPROBE_IMA_FD != 0;
+            // enable_feature(Feature::f, fd);
+            // enable_feature(Feature::d, fd);
+            // enable_feature(Feature::zicsr, fd); // implied by f
+            // enable_feature(Feature::c, ima_ext_0 & RISCV_HWPROBE_IMA_C != 0);
+            // enable_feature(Feature::zicboz, ima_ext_0 & RISCV_HWPROBE_EXT_ZICBOZ != 0);
+            enable_feature(Feature::zfh, ima_ext_0 & RISCV_HWPROBE_EXT_ZFH != 0);
+            enable_feature(Feature::zfhmin, ima_ext_0 & RISCV_HWPROBE_EXT_ZFHMIN != 0);
+            // enable_feature(Feature::zihintntl, ima_ext_0 & RISCV_HWPROBE_EXT_ZIHINTNTL != 0);
+            // enable_feature(Feature::zfa, ima_ext_0 & RISCV_HWPROBE_EXT_ZFA != 0);
+            enable_feature(Feature::ztso, ima_ext_0 & RISCV_HWPROBE_EXT_ZTSO != 0);
+            enable_feature(Feature::zacas, ima_ext_0 & RISCV_HWPROBE_EXT_ZACAS != 0);
+            // enable_feature(Feature::zicond, ima_ext_0 & RISCV_HWPROBE_EXT_ZICOND != 0);
+            enable_feature(
+                Feature::zihintpause,
+                ima_ext_0 & RISCV_HWPROBE_EXT_ZIHINTPAUSE != 0,
+            );
+            // enable_feature(Feature::zimop, ima_ext_0 & RISCV_HWPROBE_EXT_ZIMOP != 0);
+            // enable_feature(Feature::zca, ima_ext_0 & RISCV_HWPROBE_EXT_ZCA != 0);
+            // enable_feature(Feature::zcb, ima_ext_0 & RISCV_HWPROBE_EXT_ZCB != 0);
+            // enable_feature(Feature::zcd, ima_ext_0 & RISCV_HWPROBE_EXT_ZCD != 0);
+            // enable_feature(Feature::zcf, ima_ext_0 & RISCV_HWPROBE_EXT_ZCF != 0);
+            // enable_feature(Feature::zcmop, ima_ext_0 & RISCV_HWPROBE_EXT_ZCMOP != 0);
+            enable_feature(Feature::zawrs, ima_ext_0 & RISCV_HWPROBE_EXT_ZAWRS != 0);
+            // enable_feature(Feature::supm, ima_ext_0 & RISCV_HWPROBE_EXT_SUPM != 0);
+            // Bit-Manipulation ISA extensions
+            enable_feature(Feature::zba, ima_ext_0 & RISCV_HWPROBE_EXT_ZBA != 0);
+            enable_feature(Feature::zbb, ima_ext_0 & RISCV_HWPROBE_EXT_ZBB != 0);
+            enable_feature(Feature::zbs, ima_ext_0 & RISCV_HWPROBE_EXT_ZBS != 0);
+            enable_feature(Feature::zbc, ima_ext_0 & RISCV_HWPROBE_EXT_ZBC != 0);
+            // Scalar Crypto ISA extensions
+            let zbkb = ima_ext_0 & RISCV_HWPROBE_EXT_ZBKB != 0;
+            enable_feature(Feature::zbkb, zbkb);
+            let zbkc = ima_ext_0 & RISCV_HWPROBE_EXT_ZBKC != 0;
+            enable_feature(Feature::zbkc, zbkc);
+            let zbkx = ima_ext_0 & RISCV_HWPROBE_EXT_ZBKX != 0;
+            enable_feature(Feature::zbkx, zbkx);
+            let zknd = ima_ext_0 & RISCV_HWPROBE_EXT_ZKND != 0;
+            enable_feature(Feature::zknd, zknd);
+            let zkne = ima_ext_0 & RISCV_HWPROBE_EXT_ZKNE != 0;
+            enable_feature(Feature::zkne, zkne);
+            let zknh = ima_ext_0 & RISCV_HWPROBE_EXT_ZKNH != 0;
+            enable_feature(Feature::zknh, zknh);
+            let zksed = ima_ext_0 & RISCV_HWPROBE_EXT_ZKSED != 0;
+            enable_feature(Feature::zksed, zksed);
+            let zksh = ima_ext_0 & RISCV_HWPROBE_EXT_ZKSH != 0;
+            enable_feature(Feature::zksh, zksh);
+            let zkt = ima_ext_0 & RISCV_HWPROBE_EXT_ZKT != 0;
+            enable_feature(Feature::zkt, zkt);
+            let zkn = zbkb & zbkc & zbkx & zkne & zknd & zknh;
+            enable_feature(Feature::zkn, zkn);
+            // enable_feature(Feature::zk, zkn & zkr & zkt);
+            enable_feature(Feature::zks, zbkb & zbkc & zbkx & zksed & zksh);
+            // Refer result from hwcap because it reflects Vector enablement status, unlike hwprobe.
+            // prctl(PR_RISCV_V_GET_CONTROL) is another way to check this but it doesn't work with
+            // qemu-user (as of 9.2.1).
+            // See https://docs.kernel.org/arch/riscv/vector.html for more.
+            if has_v {
+                // Standard Vector Extensions
+                // v and zve{32,64}* extensions are detected by hwcap.
+                // enable_feature(Feature::v, ima_ext_0 & RISCV_HWPROBE_IMA_V != 0);
+                enable_feature(Feature::zvfh, ima_ext_0 & RISCV_HWPROBE_EXT_ZVFH != 0);
+                enable_feature(Feature::zvfhmin, ima_ext_0 & RISCV_HWPROBE_EXT_ZVFHMIN != 0);
+                // enable_feature(Feature::zve32x, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE32X != 0);
+                // enable_feature(Feature::zve32f, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE32F != 0);
+                // enable_feature(Feature::zve64x, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE64X != 0);
+                // enable_feature(Feature::zve64f, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE64F != 0);
+                // enable_feature(Feature::zve64d, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE64D != 0);
+                // Vector Cryptography and Bit-manipulation Extensions
+                let zvbb = ima_ext_0 & RISCV_HWPROBE_EXT_ZVBB != 0;
+                enable_feature(Feature::zvbb, zvbb);
+                let zvbc = ima_ext_0 & RISCV_HWPROBE_EXT_ZVBC != 0;
+                enable_feature(Feature::zvbc, zvbc);
+                let zvkb = zvbb || ima_ext_0 & RISCV_HWPROBE_EXT_ZVKB != 0;
+                enable_feature(Feature::zvkb, zvkb);
+                let zvkg = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKG != 0;
+                enable_feature(Feature::zvkg, zvkg);
+                let zvkned = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKNED != 0;
+                enable_feature(Feature::zvkned, zvkned);
+                enable_feature(Feature::zvknha, ima_ext_0 & RISCV_HWPROBE_EXT_ZVKNHA != 0);
+                let zvknhb = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKNHB != 0;
+                enable_feature(Feature::zvknhb, zvknhb);
+                let zvksed = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKSED != 0;
+                enable_feature(Feature::zvksed, zvksed);
+                let zvksh = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKSH != 0;
+                enable_feature(Feature::zvksh, zvksh);
+                let zvkt = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKT != 0;
+                enable_feature(Feature::zvkt, zvkt);
+                let zvkn = zvkned & zvknhb & zvkb & zvkt;
+                enable_feature(Feature::zvkn, zvkn);
+                enable_feature(Feature::zvknc, zvkn & zvbc);
+                enable_feature(Feature::zvkng, zvkn & zvkg);
+                let zvks = zvksed & zvksh & zvkb & zvkt;
+                enable_feature(Feature::zvks, zvks);
+                enable_feature(Feature::zvksc, zvks & zvbc);
+                enable_feature(Feature::zvksg, zvks & zvkg);
+            }
+        }
+        if out[1].key != -1 {
+            enable_feature(
+                Feature::unaligned_scalar_mem,
+                out[1].value & RISCV_HWPROBE_MISALIGNED_MASK == RISCV_HWPROBE_MISALIGNED_FAST,
+            );
+        }
+        if out[2].key != -1 {
+            enable_feature(
+                Feature::unaligned_vector_mem,
+                out[2].value == RISCV_HWPROBE_MISALIGNED_VECTOR_FAST,
+            );
+        }
+    }
 
     value
 }
diff --git a/crates/std_detect/tests/cpu-detection.rs b/crates/std_detect/tests/cpu-detection.rs
index 2c9cd95d29..9176f8f5b7 100644
--- a/crates/std_detect/tests/cpu-detection.rs
+++ b/crates/std_detect/tests/cpu-detection.rs
@@ -5,6 +5,10 @@
     any(target_arch = "aarch64", target_arch = "arm64ec"),
     feature(stdarch_aarch64_feature_detection)
 )]
+#![cfg_attr(
+    any(target_arch = "riscv32", target_arch = "riscv64"),
+    feature(stdarch_riscv_feature_detection)
+)]
 #![cfg_attr(target_arch = "powerpc", feature(stdarch_powerpc_feature_detection))]
 #![cfg_attr(target_arch = "powerpc64", feature(stdarch_powerpc_feature_detection))]
 #![cfg_attr(target_arch = "s390x", feature(stdarch_s390x_feature_detection))]
@@ -15,6 +19,8 @@
         target_arch = "arm",
         target_arch = "aarch64",
         target_arch = "arm64ec",
+        target_arch = "riscv32",
+        target_arch = "riscv64",
         target_arch = "powerpc",
         target_arch = "powerpc64",
         target_arch = "s390x",
@@ -220,6 +226,92 @@ fn aarch64_darwin() {
     println!("sha3: {:?}", is_aarch64_feature_detected!("sha3"));
 }
 
+#[test]
+#[cfg(all(
+    any(target_arch = "riscv32", target_arch = "riscv64"),
+    any(target_os = "linux", target_os = "android")
+))]
+fn riscv_linux() {
+    println!("rv32i: {}", is_riscv_feature_detected!("rv32i"));
+    println!("rv32e: {}", is_riscv_feature_detected!("rv32e"));
+    println!("rv64i: {}", is_riscv_feature_detected!("rv64i"));
+    println!("rv128i: {}", is_riscv_feature_detected!("rv128i"));
+    println!("zicsr: {}", is_riscv_feature_detected!("zicsr"));
+    println!("zicntr: {}", is_riscv_feature_detected!("zicntr"));
+    println!("zihpm: {}", is_riscv_feature_detected!("zihpm"));
+    println!("zifencei: {}", is_riscv_feature_detected!("zifencei"));
+    println!("zihintpause: {}", is_riscv_feature_detected!("zihintpause"));
+    println!("m: {}", is_riscv_feature_detected!("m"));
+    println!("a: {}", is_riscv_feature_detected!("a"));
+    println!("zacas: {}", is_riscv_feature_detected!("zacas"));
+    println!("zawrs: {}", is_riscv_feature_detected!("zawrs"));
+    println!("zam: {}", is_riscv_feature_detected!("zam"));
+    println!("ztso: {}", is_riscv_feature_detected!("ztso"));
+    println!("f: {}", is_riscv_feature_detected!("f"));
+    println!("d: {}", is_riscv_feature_detected!("d"));
+    println!("q: {}", is_riscv_feature_detected!("q"));
+    println!("zfh: {}", is_riscv_feature_detected!("zfh"));
+    println!("zfhmin: {}", is_riscv_feature_detected!("zfhmin"));
+    println!("zfinx: {}", is_riscv_feature_detected!("zfinx"));
+    println!("zdinx: {}", is_riscv_feature_detected!("zdinx"));
+    println!("zhinx: {}", is_riscv_feature_detected!("zhinx"));
+    println!("zhinxmin: {}", is_riscv_feature_detected!("zhinxmin"));
+    println!("c: {}", is_riscv_feature_detected!("c"));
+    println!("zba: {}", is_riscv_feature_detected!("zba"));
+    println!("zbb: {}", is_riscv_feature_detected!("zbb"));
+    println!("zbc: {}", is_riscv_feature_detected!("zbc"));
+    println!("zbs: {}", is_riscv_feature_detected!("zbs"));
+    println!("zbkb: {}", is_riscv_feature_detected!("zbkb"));
+    println!("zbkc: {}", is_riscv_feature_detected!("zbkc"));
+    println!("zbkx: {}", is_riscv_feature_detected!("zbkx"));
+    println!("zknd: {}", is_riscv_feature_detected!("zknd"));
+    println!("zkne: {}", is_riscv_feature_detected!("zkne"));
+    println!("zknh: {}", is_riscv_feature_detected!("zknh"));
+    println!("zksed: {}", is_riscv_feature_detected!("zksed"));
+    println!("zksh: {}", is_riscv_feature_detected!("zksh"));
+    println!("zkr: {}", is_riscv_feature_detected!("zkr"));
+    println!("zksed: {}", is_riscv_feature_detected!("zksed"));
+    println!("zksh: {}", is_riscv_feature_detected!("zksh"));
+    println!("zkr: {}", is_riscv_feature_detected!("zkr"));
+    println!("zkn: {}", is_riscv_feature_detected!("zkn"));
+    println!("zks: {}", is_riscv_feature_detected!("zks"));
+    println!("zkt: {}", is_riscv_feature_detected!("zkt"));
+    println!("v: {}", is_riscv_feature_detected!("v"));
+    println!("zvfh: {}", is_riscv_feature_detected!("zvfh"));
+    println!("zvfhmin: {}", is_riscv_feature_detected!("zvfhmin"));
+    println!("zve32x: {}", is_riscv_feature_detected!("zve32x"));
+    println!("zve32f: {}", is_riscv_feature_detected!("zve32f"));
+    println!("zve64x: {}", is_riscv_feature_detected!("zve64x"));
+    println!("zve64f: {}", is_riscv_feature_detected!("zve64f"));
+    println!("zve64d: {}", is_riscv_feature_detected!("zve64d"));
+    println!("zvkb: {}", is_riscv_feature_detected!("zvkb"));
+    println!("zvbb: {}", is_riscv_feature_detected!("zvbb"));
+    println!("zvbc: {}", is_riscv_feature_detected!("zvbc"));
+    println!("zvkg: {}", is_riscv_feature_detected!("zvkg"));
+    println!("zvkned: {}", is_riscv_feature_detected!("zvkned"));
+    println!("zvknha: {}", is_riscv_feature_detected!("zvknha"));
+    println!("zvknhb: {}", is_riscv_feature_detected!("zvknhb"));
+    println!("zvksed: {}", is_riscv_feature_detected!("zvksed"));
+    println!("zvksh: {}", is_riscv_feature_detected!("zvksh"));
+    println!("zvkn: {}", is_riscv_feature_detected!("zvkn"));
+    println!("zvknc: {}", is_riscv_feature_detected!("zvknc"));
+    println!("zvkng: {}", is_riscv_feature_detected!("zvkng"));
+    println!("zvks: {}", is_riscv_feature_detected!("zvks"));
+    println!("zvksc: {}", is_riscv_feature_detected!("zvksc"));
+    println!("zvksg: {}", is_riscv_feature_detected!("zvksg"));
+    println!("zvkt: {}", is_riscv_feature_detected!("zvkt"));
+    println!(
+        "unaligned-scalar-mem: {}",
+        is_riscv_feature_detected!("unaligned-scalar-mem")
+    );
+    println!(
+        "unaligned-vector-mem: {}",
+        is_riscv_feature_detected!("unaligned-vector-mem")
+    );
+    println!("j: {}", is_riscv_feature_detected!("j"));
+    println!("p: {}", is_riscv_feature_detected!("p"));
+}
+
 #[test]
 #[cfg(all(target_arch = "powerpc", target_os = "linux"))]
 fn powerpc_linux() {