std_detect: Support run-time detection of FEAT_LSE2 on aarch64 BSD (#1379)
This commit is contained in:
parent
57c492180d
commit
dc49234574
3 changed files with 25 additions and 10 deletions
|
|
@ -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;
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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();
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue