From 2659a324f006956af1da147b5b9969ef055c2a5e Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Wed, 11 Jan 2023 15:58:49 +0900 Subject: [PATCH] Add CPU detection for macOS/aarch64. --- crates/std_detect/src/detect/mod.rs | 3 + .../std_detect/src/detect/os/macos/aarch64.rs | 98 +++++++++++++++++++ crates/std_detect/tests/cpu-detection.rs | 32 ++++++ 3 files changed, 133 insertions(+) create mode 100644 crates/std_detect/src/detect/os/macos/aarch64.rs diff --git a/crates/std_detect/src/detect/mod.rs b/crates/std_detect/src/detect/mod.rs index 5ce4e54e23..c938abf17d 100644 --- a/crates/std_detect/src/detect/mod.rs +++ b/crates/std_detect/src/detect/mod.rs @@ -66,6 +66,9 @@ cfg_if! { } else if #[cfg(all(target_os = "windows", target_arch = "aarch64"))] { #[path = "os/windows/aarch64.rs"] mod os; + } else if #[cfg(all(target_os = "macos", target_arch = "aarch64", feature = "libc"))] { + #[path = "os/macos/aarch64.rs"] + mod os; } else { #[path = "os/other.rs"] mod os; diff --git a/crates/std_detect/src/detect/os/macos/aarch64.rs b/crates/std_detect/src/detect/os/macos/aarch64.rs new file mode 100644 index 0000000000..d7ebd956d6 --- /dev/null +++ b/crates/std_detect/src/detect/os/macos/aarch64.rs @@ -0,0 +1,98 @@ +//! Run-time feature detection for aarch64 on macOS. + +use crate::detect::{cache, Feature}; + +#[inline] +fn _sysctlbyname(name: &str) -> bool { + use libc; + + let mut enabled: i32 = 0; + let mut enabled_len: usize = 4; + let enabled_ptr = &mut enabled as *mut i32 as *mut libc::c_void; + + let ret = unsafe { + libc::sysctlbyname( + name.as_ptr() as *const i8, + enabled_ptr, + &mut enabled_len, + core::ptr::null_mut(), + 0, + ) + }; + + match ret { + 0 => enabled != 0, + _ => false, + } +} + +/// Try to read the features using sysctlbyname. +pub(crate) fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + + let mut enable_feature = |f, enable| { + if enable { + value.set(f as u32); + } + }; + + let asimd = _sysctlbyname("hw.optional.AdvSIMD\0"); + let pmull = _sysctlbyname("hw.optional.arm.FEAT_PMULL\0"); + let fp = _sysctlbyname("hw.optional.floatingpoint\0"); + let fp16 = _sysctlbyname("hw.optional.arm.FEAT_FP16\0"); + let crc = _sysctlbyname("hw.optional.armv8_crc32\0"); + let lse = _sysctlbyname("hw.optional.arm.FEAT_LSE\0"); + let lse2 = _sysctlbyname("hw.optional.arm.FEAT_LSE2\0"); + let rdm = _sysctlbyname("hw.optional.arm.FEAT_RDM\0"); + let rcpc = _sysctlbyname("hw.optional.arm.FEAT_LRCPC\0"); + let rcpc2 = _sysctlbyname("hw.optional.arm.FEAT_LRCPC2\0"); + let dotprod = _sysctlbyname("hw.optional.arm.FEAT_DotProd\0"); + let fhm = _sysctlbyname("hw.optional.arm.FEAT_FHM\0"); + let flagm = _sysctlbyname("hw.optional.arm.FEAT_FlagM\0"); + let ssbs = _sysctlbyname("hw.optional.arm.FEAT_SSBS\0"); + let sb = _sysctlbyname("hw.optional.arm.FEAT_SB\0"); + let paca = _sysctlbyname("hw.optional.arm.FEAT_PAuth\0"); + let dpb = _sysctlbyname("hw.optional.arm.FEAT_DPB\0"); + let dpb2 = _sysctlbyname("hw.optional.arm.FEAT_DPB2\0"); + let frintts = _sysctlbyname("hw.optional.arm.FEAT_FRINTTS\0"); + let i8mm = _sysctlbyname("hw.optional.arm.FEAT_I8MM\0"); + let bf16 = _sysctlbyname("hw.optional.arm.FEAT_BF16\0"); + let bti = _sysctlbyname("hw.optional.arm.FEAT_BTI\0"); + let fcma = _sysctlbyname("hw.optional.arm.FEAT_FCMA\0"); + let aes = _sysctlbyname("hw.optional.arm.FEAT_AES\0"); + let sha1 = _sysctlbyname("hw.optional.arm.FEAT_SHA1\0"); + let sha2 = _sysctlbyname("hw.optional.arm.FEAT_SHA256\0"); + let sha3 = _sysctlbyname("hw.optional.arm.FEAT_SHA3\0"); + let sha512 = _sysctlbyname("hw.optional.arm.FEAT_SHA512\0"); + let jsconv = _sysctlbyname("hw.optional.arm.FEAT_JSCVT\0"); + + enable_feature(Feature::asimd, asimd); + enable_feature(Feature::pmull, pmull); + enable_feature(Feature::fp, fp); + enable_feature(Feature::fp16, fp16); + enable_feature(Feature::crc, crc); + enable_feature(Feature::lse, lse); + enable_feature(Feature::lse2, lse2); + enable_feature(Feature::rdm, rdm); + enable_feature(Feature::rcpc, rcpc); + enable_feature(Feature::rcpc2, rcpc2); + enable_feature(Feature::dotprod, dotprod); + enable_feature(Feature::fhm, fhm); + enable_feature(Feature::flagm, flagm); + enable_feature(Feature::ssbs, ssbs); + enable_feature(Feature::sb, sb); + enable_feature(Feature::paca, paca); + enable_feature(Feature::dpb, dpb); + enable_feature(Feature::dpb2, dpb2); + enable_feature(Feature::frintts, frintts); + enable_feature(Feature::i8mm, i8mm); + enable_feature(Feature::bf16, bf16); + enable_feature(Feature::bti, bti); + enable_feature(Feature::fcma, fcma); + enable_feature(Feature::aes, aes); + enable_feature(Feature::jsconv, jsconv); + enable_feature(Feature::sha2, sha1 && sha2 && asimd); + enable_feature(Feature::sha3, sha512 && sha3 && asimd); + + value +} diff --git a/crates/std_detect/tests/cpu-detection.rs b/crates/std_detect/tests/cpu-detection.rs index cb57b849d6..1ad897a2e2 100644 --- a/crates/std_detect/tests/cpu-detection.rs +++ b/crates/std_detect/tests/cpu-detection.rs @@ -139,6 +139,38 @@ fn aarch64_bsd() { println!("sha2: {:?}", is_aarch64_feature_detected!("sha2")); } +#[test] +#[cfg(all(target_arch = "aarch64", target_os = "macos"))] +fn aarch64_macos() { + println!("asimd: {:?}", is_aarch64_feature_detected!("asimd")); + println!("fp: {:?}", is_aarch64_feature_detected!("fp")); + println!("fp16: {:?}", is_aarch64_feature_detected!("fp16")); + println!("pmull: {:?}", is_aarch64_feature_detected!("pmull")); + 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!("rcpc2: {:?}", is_aarch64_feature_detected!("rcpc2")); + println!("dotprod: {:?}", is_aarch64_feature_detected!("dotprod")); + println!("fhm: {:?}", is_aarch64_feature_detected!("fhm")); + println!("flagm: {:?}", is_aarch64_feature_detected!("flagm")); + println!("ssbs: {:?}", is_aarch64_feature_detected!("ssbs")); + println!("sb: {:?}", is_aarch64_feature_detected!("sb")); + println!("paca: {:?}", is_aarch64_feature_detected!("paca")); + println!("dpb: {:?}", is_aarch64_feature_detected!("dpb")); + println!("dpb2: {:?}", is_aarch64_feature_detected!("dpb2")); + println!("frintts: {:?}", is_aarch64_feature_detected!("frintts")); + println!("i8mm: {:?}", is_aarch64_feature_detected!("i8mm")); + println!("bf16: {:?}", is_aarch64_feature_detected!("bf16")); + println!("bti: {:?}", is_aarch64_feature_detected!("bti")); + println!("fcma: {:?}", is_aarch64_feature_detected!("fcma")); + println!("jsconv: {:?}", is_aarch64_feature_detected!("jsconv")); + println!("aes: {:?}", is_aarch64_feature_detected!("aes")); + println!("sha2: {:?}", is_aarch64_feature_detected!("sha2")); + println!("sha3: {:?}", is_aarch64_feature_detected!("sha3")); +} + #[test] #[cfg(all(target_arch = "powerpc", target_os = "linux"))] fn powerpc_linux() {