Skip to content

Commit

Permalink
std_detect: Support run-time detection of FEAT_LSE2 on aarch64 BSD (r…
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e authored Feb 11, 2023
1 parent 5b169ef commit f2ce94c
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 10 deletions.
21 changes: 18 additions & 3 deletions crates/std_detect/src/detect/os/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
//!
//! - [Zircon implementation](https://fuchsia.googlesource.com/zircon/+/master/kernel/arch/arm64/feature.cpp)
//! - [Linux documentation](https://www.kernel.org/doc/Documentation/arm64/cpu-feature-registers.txt)
//! - [ARM documentation](https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers?lang=en)
use crate::detect::{cache, Feature};
use core::arch::asm;
Expand Down Expand Up @@ -43,6 +44,16 @@ pub(crate) fn detect_features() -> cache::Initializer {
);
}

// ID_AA64MMFR2_EL1 - AArch64 Memory Model Feature Register 2
let aa64mmfr2: u64;
unsafe {
asm!(
"mrs {}, ID_AA64MMFR2_EL1",
out(reg) aa64mmfr2,
options(pure, nomem, preserves_flags, nostack)
);
}

// ID_AA64PFR0_EL1 - Processor Feature Register 0
let aa64pfr0: u64;
unsafe {
Expand All @@ -53,12 +64,13 @@ pub(crate) fn detect_features() -> cache::Initializer {
);
}

parse_system_registers(aa64isar0, aa64isar1, Some(aa64pfr0))
parse_system_registers(aa64isar0, aa64isar1, aa64mmfr2, Some(aa64pfr0))
}

pub(crate) fn parse_system_registers(
aa64isar0: u64,
aa64isar1: u64,
aa64mmfr2: u64,
aa64pfr0: Option<u64>,
) -> cache::Initializer {
let mut value = cache::Initializer::default();
Expand All @@ -72,7 +84,7 @@ pub(crate) fn parse_system_registers(
// ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0
enable_feature(Feature::pmull, bits_shift(aa64isar0, 7, 4) >= 2);
enable_feature(Feature::tme, bits_shift(aa64isar0, 27, 24) == 1);
enable_feature(Feature::lse, bits_shift(aa64isar0, 23, 20) >= 1);
enable_feature(Feature::lse, bits_shift(aa64isar0, 23, 20) >= 2);
enable_feature(Feature::crc, bits_shift(aa64isar0, 19, 16) >= 1);

// ID_AA64PFR0_EL1 - Processor Feature Register 0
Expand All @@ -99,13 +111,16 @@ pub(crate) fn parse_system_registers(
enable_feature(Feature::sve, asimd && bits_shift(aa64pfr0, 35, 32) >= 1);
}

// ID_AA64PFR0_EL1 - Processor Feature Register 0
// ID_AA64ISAR1_EL1 - Instruction Set Attribute Register 1
// Check for either APA or API field
enable_feature(Feature::paca, bits_shift(aa64isar1, 11, 4) >= 1);
enable_feature(Feature::rcpc, bits_shift(aa64isar1, 23, 20) >= 1);
// Check for either GPA or GPI field
enable_feature(Feature::pacg, bits_shift(aa64isar1, 31, 24) >= 1);

// ID_AA64MMFR2_EL1 - AArch64 Memory Model Feature Register 2
enable_feature(Feature::lse2, bits_shift(aa64mmfr2, 35, 32) >= 1);

value
}

Expand Down
13 changes: 6 additions & 7 deletions crates/std_detect/src/detect/os/openbsd/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@
use crate::detect::cache;
use core::{mem::MaybeUninit, ptr};

// Defined in sys/sysctl.h.
// https://github.com/openbsd/src/blob/72ccc03bd11da614f31f7ff76e3f6fce99bc1c79/sys/sys/sysctl.h#L82
const CTL_MACHDEP: libc::c_int = 7;
// Defined in machine/cpu.h.
// https://github.com/openbsd/src/blob/72ccc03bd11da614f31f7ff76e3f6fce99bc1c79/sys/arch/arm64/include/cpu.h#L25-L40
const CPU_ID_AA64ISAR0: libc::c_int = 2;
const CPU_ID_AA64ISAR1: libc::c_int = 3;
const CPU_ID_AA64MMFR2: libc::c_int = 7;
const CPU_ID_AA64PFR0: libc::c_int = 8;

/// Try to read the features from the system registers.
Expand All @@ -24,13 +22,14 @@ pub(crate) fn detect_features() -> cache::Initializer {
// https://github.com/openbsd/src/commit/c7654cd65262d532212f65123ee3905ba200365c
// sysctl returns an unsupported error if operation is not supported,
// so we can safely use this function on older versions of OpenBSD.
let aa64isar0 = sysctl64(&[CTL_MACHDEP, CPU_ID_AA64ISAR0]).unwrap_or(0);
let aa64isar1 = sysctl64(&[CTL_MACHDEP, CPU_ID_AA64ISAR1]).unwrap_or(0);
let aa64isar0 = sysctl64(&[libc::CTL_MACHDEP, CPU_ID_AA64ISAR0]).unwrap_or(0);
let aa64isar1 = sysctl64(&[libc::CTL_MACHDEP, CPU_ID_AA64ISAR1]).unwrap_or(0);
let aa64mmfr2 = sysctl64(&[libc::CTL_MACHDEP, CPU_ID_AA64MMFR2]).unwrap_or(0);
// Do not use unwrap_or(0) because in fp and asimd fields, 0 indicates that
// the feature is available.
let aa64pfr0 = sysctl64(&[CTL_MACHDEP, CPU_ID_AA64PFR0]);
let aa64pfr0 = sysctl64(&[libc::CTL_MACHDEP, CPU_ID_AA64PFR0]);

super::aarch64::parse_system_registers(aa64isar0, aa64isar1, aa64pfr0)
super::aarch64::parse_system_registers(aa64isar0, aa64isar1, aa64mmfr2, aa64pfr0)
}

#[inline]
Expand Down
1 change: 1 addition & 0 deletions crates/std_detect/tests/cpu-detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ fn aarch64_bsd() {
println!("sve: {:?}", is_aarch64_feature_detected!("sve"));
println!("crc: {:?}", is_aarch64_feature_detected!("crc"));
println!("lse: {:?}", is_aarch64_feature_detected!("lse"));
println!("lse2: {:?}", is_aarch64_feature_detected!("lse2"));
println!("rdm: {:?}", is_aarch64_feature_detected!("rdm"));
println!("rcpc: {:?}", is_aarch64_feature_detected!("rcpc"));
println!("dotprod: {:?}", is_aarch64_feature_detected!("dotprod"));
Expand Down

0 comments on commit f2ce94c

Please sign in to comment.