RISC-V: Linux 6.15 riscv_hwprobe support

This commit adds support for `riscv_hwprobe` on the Linux kernel 6.15.
It adds feature detection of 8 extensions (4 of them are new in this).

Existing RISC-V Extensions:

1.  "Zicntr"
2.  "Zihpm"
3.  "Zalrsc"
4.  "Zaamo"

New RISC-V Extensions:

5.  "Zicbom"
6.  "Zfbfmin"
7.  "Zvfbfmin"
8.  "Zvfbfwma"
This commit is contained in:
Tsukasa OI 2025-05-31 12:27:22 +00:00 committed by Amanieu d'Antras
parent 52115419a3
commit bc4333545a
4 changed files with 39 additions and 3 deletions

View file

@ -63,6 +63,7 @@ features! {
/// * Zve64x: `"zve64x"`
/// * Zve64f: `"zve64f"`
/// * Zve64d: `"zve64d"`
/// * Zicbom: `"zicbom"`
/// * Zicboz: `"zicboz"`
/// * Zicntr: `"zicntr"`
/// * Zicond: `"zicond"`
@ -75,6 +76,7 @@ features! {
/// * Zacas: `"zacas"`
/// * Zawrs: `"zawrs"`
/// * Zfa: `"zfa"`
/// * Zfbfmin: `"zfbfmin"`
/// * Zfh: `"zfh"`
/// * Zfhmin: `"zfhmin"`
/// * Zfinx: `"zfinx"`
@ -99,6 +101,8 @@ features! {
/// * Zkt: `"zkt"`
/// * Zvbb: `"zvbb"`
/// * Zvbc: `"zvbc"`
/// * Zvfbfmin: `"zvfbfmin"`
/// * Zvfbfwma: `"zvfbfwma"`
/// * Zvfh: `"zvfh"`
/// * Zvfhmin: `"zvfhmin"`
/// * Zvkb: `"zvkb"`
@ -173,6 +177,8 @@ features! {
/// "Zihintpause" Extension for Pause Hint
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zimop: "zimop";
/// "Zimop" Extension for May-Be-Operations
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zicbom: "zicbom";
/// "Zicbom" Extension for Cache-Block Management Instructions
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zicboz: "zicboz";
/// "Zicboz" Extension for Cache-Block Zero Instruction
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zicond: "zicond";
@ -210,6 +216,8 @@ features! {
/// "Zfhmin" Extension for Minimal Half-Precision Floating-Point
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zfa: "zfa";
/// "Zfa" Extension for Additional Floating-Point Instructions
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zfbfmin: "zfbfmin";
/// "Zfbfmin" Extension for Scalar BF16 Converts
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zfinx: "zfinx";
/// "Zfinx" Extension for Single-Precision Floating-Point in Integer Registers
@ -289,6 +297,10 @@ features! {
/// "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")] zvfbfmin: "zvfbfmin";
/// "Zvfbfmin" Vector Extension for BF16 Converts
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvfbfwma: "zvfbfwma";
/// "Zvfbfwma" Vector Extension for BF16 Widening Multiply-Add
@FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zvbb: "zvbb";
/// "Zvbb" Extension for Vector Basic Bit-Manipulation

View file

@ -10,13 +10,13 @@ use super::super::riscv::imply_features;
use super::auxvec;
use crate::detect::{Feature, bit, cache};
// See <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/prctl.h?h=v6.14>
// See <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/prctl.h?h=v6.15>
// for runtime status query constants.
const PR_RISCV_V_GET_CONTROL: libc::c_int = 70;
const PR_RISCV_V_VSTATE_CTRL_ON: libc::c_int = 2;
const PR_RISCV_V_VSTATE_CTRL_CUR_MASK: libc::c_int = 3;
// See <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/include/uapi/asm/hwprobe.h?h=v6.14>
// See <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/include/uapi/asm/hwprobe.h?h=v6.15>
// for riscv_hwprobe struct and hardware probing constants.
#[repr(C)]
@ -83,6 +83,14 @@ const RISCV_HWPROBE_EXT_ZCMOP: u64 = 1 << 47;
const RISCV_HWPROBE_EXT_ZAWRS: u64 = 1 << 48;
// Excluded because it only reports the existence of `prctl`-based pointer masking control.
// const RISCV_HWPROBE_EXT_SUPM: u64 = 1 << 49;
const RISCV_HWPROBE_EXT_ZICNTR: u64 = 1 << 50;
const RISCV_HWPROBE_EXT_ZIHPM: u64 = 1 << 51;
const RISCV_HWPROBE_EXT_ZFBFMIN: u64 = 1 << 52;
const RISCV_HWPROBE_EXT_ZVFBFMIN: u64 = 1 << 53;
const RISCV_HWPROBE_EXT_ZVFBFWMA: u64 = 1 << 54;
const RISCV_HWPROBE_EXT_ZICBOM: u64 = 1 << 55;
const RISCV_HWPROBE_EXT_ZAAMO: u64 = 1 << 56;
const RISCV_HWPROBE_EXT_ZALRSC: u64 = 1 << 57;
const RISCV_HWPROBE_KEY_CPUPERF_0: i64 = 5;
const RISCV_HWPROBE_MISALIGNED_FAST: u64 = 3;
@ -133,7 +141,7 @@ pub(crate) fn detect_features() -> cache::Initializer {
// Use auxiliary vector to enable single-letter ISA extensions.
// The values are part of the platform-specific [asm/hwcap.h][hwcap]
//
// [hwcap]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/include/uapi/asm/hwcap.h?h=v6.14
// [hwcap]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/include/uapi/asm/hwcap.h?h=v6.15
let auxv = auxvec::auxv().expect("read auxvec"); // should not fail on RISC-V platform
let mut has_i = bit::test(auxv.hwcap, (b'i' - b'a').into());
#[allow(clippy::eq_op)]
@ -221,12 +229,18 @@ pub(crate) fn detect_features() -> cache::Initializer {
enable_feature(Feature::d, test(RISCV_HWPROBE_IMA_FD)); // F is implied.
enable_feature(Feature::c, test(RISCV_HWPROBE_IMA_C));
enable_feature(Feature::zicntr, test(RISCV_HWPROBE_EXT_ZICNTR));
enable_feature(Feature::zihpm, test(RISCV_HWPROBE_EXT_ZIHPM));
enable_feature(Feature::zihintntl, test(RISCV_HWPROBE_EXT_ZIHINTNTL));
enable_feature(Feature::zihintpause, test(RISCV_HWPROBE_EXT_ZIHINTPAUSE));
enable_feature(Feature::zimop, test(RISCV_HWPROBE_EXT_ZIMOP));
enable_feature(Feature::zicbom, test(RISCV_HWPROBE_EXT_ZICBOM));
enable_feature(Feature::zicboz, test(RISCV_HWPROBE_EXT_ZICBOZ));
enable_feature(Feature::zicond, test(RISCV_HWPROBE_EXT_ZICOND));
enable_feature(Feature::zalrsc, test(RISCV_HWPROBE_EXT_ZALRSC));
enable_feature(Feature::zaamo, test(RISCV_HWPROBE_EXT_ZAAMO));
enable_feature(Feature::zawrs, test(RISCV_HWPROBE_EXT_ZAWRS));
enable_feature(Feature::zacas, test(RISCV_HWPROBE_EXT_ZACAS));
enable_feature(Feature::ztso, test(RISCV_HWPROBE_EXT_ZTSO));
@ -255,6 +269,7 @@ pub(crate) fn detect_features() -> cache::Initializer {
enable_feature(Feature::zfh, test(RISCV_HWPROBE_EXT_ZFH));
enable_feature(Feature::zfhmin, test(RISCV_HWPROBE_EXT_ZFHMIN));
enable_feature(Feature::zfa, test(RISCV_HWPROBE_EXT_ZFA));
enable_feature(Feature::zfbfmin, test(RISCV_HWPROBE_EXT_ZFBFMIN));
// Use prctl (if any) to determine whether the vector extension
// is enabled on the current thread (assuming the entire process
@ -290,6 +305,8 @@ pub(crate) fn detect_features() -> cache::Initializer {
enable_feature(Feature::zvfh, test(RISCV_HWPROBE_EXT_ZVFH));
enable_feature(Feature::zvfhmin, test(RISCV_HWPROBE_EXT_ZVFHMIN));
enable_feature(Feature::zvfbfmin, test(RISCV_HWPROBE_EXT_ZVFBFMIN));
enable_feature(Feature::zvfbfwma, test(RISCV_HWPROBE_EXT_ZVFBFWMA));
}
is_v_set = true;
};

View file

@ -105,6 +105,8 @@ pub(crate) fn imply_features(mut value: cache::Initializer) -> cache::Initialize
imply!(zvfh => zvfhmin); // functional
imply!(zvfh => zve32f & zfhmin);
imply!(zvfhmin => zve32f);
imply!(zvfbfwma => zvfbfmin & zfbfmin);
imply!(zvfbfmin => zve32f);
imply!(v => zve64d);
imply!(zve64d => zve64f & d);
@ -115,6 +117,7 @@ pub(crate) fn imply_features(mut value: cache::Initializer) -> cache::Initialize
imply!(zfh => zfhmin);
imply!(q => d);
imply!(d | zfhmin | zfa => f);
imply!(zfbfmin => f); // and some of (not all) "Zfh" instructions.
// Relatively complex implication rules from the "C" extension.
imply!(c => zca);

View file

@ -251,6 +251,7 @@ fn riscv_linux() {
println!("zihintntl: {}", is_riscv_feature_detected!("zihintntl"));
println!("zihintpause: {}", is_riscv_feature_detected!("zihintpause"));
println!("zimop: {}", is_riscv_feature_detected!("zimop"));
println!("zicbom: {}", is_riscv_feature_detected!("zicbom"));
println!("zicboz: {}", is_riscv_feature_detected!("zicboz"));
println!("zicond: {}", is_riscv_feature_detected!("zicond"));
println!("m: {}", is_riscv_feature_detected!("m"));
@ -267,6 +268,7 @@ fn riscv_linux() {
println!("zfh: {}", is_riscv_feature_detected!("zfh"));
println!("zfhmin: {}", is_riscv_feature_detected!("zfhmin"));
println!("zfa: {}", is_riscv_feature_detected!("zfa"));
println!("zfbfmin: {}", is_riscv_feature_detected!("zfbfmin"));
println!("zfinx: {}", is_riscv_feature_detected!("zfinx"));
println!("zdinx: {}", is_riscv_feature_detected!("zdinx"));
println!("zhinx: {}", is_riscv_feature_detected!("zhinx"));
@ -303,6 +305,8 @@ fn riscv_linux() {
println!("zve64d: {}", is_riscv_feature_detected!("zve64d"));
println!("zvfh: {}", is_riscv_feature_detected!("zvfh"));
println!("zvfhmin: {}", is_riscv_feature_detected!("zvfhmin"));
println!("zvfbfmin: {}", is_riscv_feature_detected!("zvfbfmin"));
println!("zvfbfwma: {}", is_riscv_feature_detected!("zvfbfwma"));
println!("zvbb: {}", is_riscv_feature_detected!("zvbb"));
println!("zvbc: {}", is_riscv_feature_detected!("zvbc"));
println!("zvkb: {}", is_riscv_feature_detected!("zvkb"));