Skip to main content

std_detect/detect/os/darwin/
aarch64.rs

1//! Run-time feature detection for aarch64 on Darwin (macOS/iOS/tvOS/watchOS/visionOS).
2//!
3//! <https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics>
4
5use core::ffi::CStr;
6
7use crate::detect::{Feature, cache};
8
9#[inline]
10fn _sysctlbyname(name: &CStr) -> bool {
11    use libc;
12
13    let mut enabled: i32 = 0;
14    let mut enabled_len: usize = 4;
15    let enabled_ptr = &mut enabled as *mut i32 as *mut libc::c_void;
16
17    let ret = unsafe {
18        libc::sysctlbyname(name.as_ptr(), enabled_ptr, &mut enabled_len, core::ptr::null_mut(), 0)
19    };
20
21    match ret {
22        0 => enabled != 0,
23        _ => false,
24    }
25}
26
27/// Try to read the features using sysctlbyname.
28pub(crate) fn detect_features() -> cache::Initializer {
29    let mut value = cache::Initializer::default();
30
31    let mut enable_feature = |f, enable| {
32        if enable {
33            value.set(f as u32);
34        }
35    };
36
37    // Armv8.0 features not using the standard identifiers
38    let fp = _sysctlbyname(c"hw.optional.floatingpoint");
39    let asimd = _sysctlbyname(c"hw.optional.AdvSIMD");
40    let crc_old = _sysctlbyname(c"hw.optional.armv8_crc32");
41
42    // Armv8 and Armv9 features using the standard identifiers
43    let aes = _sysctlbyname(c"hw.optional.arm.FEAT_AES");
44    let bf16 = _sysctlbyname(c"hw.optional.arm.FEAT_BF16");
45    let bti = _sysctlbyname(c"hw.optional.arm.FEAT_BTI");
46    let crc = _sysctlbyname(c"hw.optional.arm.FEAT_CRC32");
47    let cssc = _sysctlbyname(c"hw.optional.arm.FEAT_CSSC");
48    let dit = _sysctlbyname(c"hw.optional.arm.FEAT_DIT");
49    let dotprod = _sysctlbyname(c"hw.optional.arm.FEAT_DotProd");
50    let dpb = _sysctlbyname(c"hw.optional.arm.FEAT_DPB");
51    let dpb2 = _sysctlbyname(c"hw.optional.arm.FEAT_DPB2");
52    let ecv = _sysctlbyname(c"hw.optional.arm.FEAT_ECV");
53    let fcma = _sysctlbyname(c"hw.optional.arm.FEAT_FCMA");
54    let fhm = _sysctlbyname(c"hw.optional.arm.FEAT_FHM");
55    let flagm = _sysctlbyname(c"hw.optional.arm.FEAT_FlagM");
56    let flagm2 = _sysctlbyname(c"hw.optional.arm.FEAT_FlagM2");
57    let fp16 = _sysctlbyname(c"hw.optional.arm.FEAT_FP16");
58    let frintts = _sysctlbyname(c"hw.optional.arm.FEAT_FRINTTS");
59    let hbc = _sysctlbyname(c"hw.optional.arm.FEAT_HBC");
60    let i8mm = _sysctlbyname(c"hw.optional.arm.FEAT_I8MM");
61    let jsconv = _sysctlbyname(c"hw.optional.arm.FEAT_JSCVT");
62    let rcpc = _sysctlbyname(c"hw.optional.arm.FEAT_LRCPC");
63    let rcpc2 = _sysctlbyname(c"hw.optional.arm.FEAT_LRCPC2");
64    let lse = _sysctlbyname(c"hw.optional.arm.FEAT_LSE");
65    let lse2 = _sysctlbyname(c"hw.optional.arm.FEAT_LSE2");
66    let mte = _sysctlbyname(c"hw.optional.arm.FEAT_MTE");
67    let mte2 = _sysctlbyname(c"hw.optional.arm.FEAT_MTE2");
68    let pauth = _sysctlbyname(c"hw.optional.arm.FEAT_PAuth");
69    let pmull = _sysctlbyname(c"hw.optional.arm.FEAT_PMULL");
70    let rdm = _sysctlbyname(c"hw.optional.arm.FEAT_RDM");
71    let sb = _sysctlbyname(c"hw.optional.arm.FEAT_SB");
72    let sha1 = _sysctlbyname(c"hw.optional.arm.FEAT_SHA1");
73    let sha256 = _sysctlbyname(c"hw.optional.arm.FEAT_SHA256");
74    let sha3 = _sysctlbyname(c"hw.optional.arm.FEAT_SHA3");
75    let sha512 = _sysctlbyname(c"hw.optional.arm.FEAT_SHA512");
76    let sme = _sysctlbyname(c"hw.optional.arm.FEAT_SME");
77    let sme2 = _sysctlbyname(c"hw.optional.arm.FEAT_SME2");
78    let sme2p1 = _sysctlbyname(c"hw.optional.arm.FEAT_SME2p1");
79    let sme_b16b16 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_B16B16");
80    let sme_f16f16 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_F16F16");
81    let sme_f64f64 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_F64F64");
82    let sme_i16i64 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_I16I64");
83    let ssbs = _sysctlbyname(c"hw.optional.arm.FEAT_SSBS");
84    let sve_b16b16 = _sysctlbyname(c"hw.optional.arm.FEAT_SVE_B16B16");
85    let wfxt = _sysctlbyname(c"hw.optional.arm.FEAT_WFxT");
86
87    // The following features are not exposed by `is_aarch64_feature_detected`,
88    // but *are* reported by `sysctl`. They are here as documentation that they
89    // exist, and may potentially be exposed later.
90    /*
91    let afp = _sysctlbyname(c"hw.optional.arm.FEAT_AFP");
92    let csv2 = _sysctlbyname(c"hw.optional.arm.FEAT_CSV2");
93    let csv3 = _sysctlbyname(c"hw.optional.arm.FEAT_CSV3");
94    let ebf16 = _sysctlbyname(c"hw.optional.arm.FEAT_EBF16");
95    let fpac = _sysctlbyname(c"hw.optional.arm.FEAT_FPAC");
96    let fpaccombine = _sysctlbyname(c"hw.optional.arm.FEAT_FPACCOMBINE");
97    let mte_async = _sysctlbyname(c"hw.optional.arm.FEAT_MTE_ASYNC");
98    let mte_canonical_tags = _sysctlbyname(c"hw.optional.arm.FEAT_MTE_CANONICAL_TAGS");
99    let mte_no_address_tags = _sysctlbyname(c"hw.optional.arm.FEAT_MTE_NO_ADDRESS_TAGS");
100    let mte_store_only = _sysctlbyname(c"hw.optional.arm.FEAT_MTE_STORE_ONLY");
101    let mte3 = _sysctlbyname(c"hw.optional.arm.FEAT_MTE3");
102    let mte4 = _sysctlbyname(c"hw.optional.arm.FEAT_MTE4");
103    let pacimp = _sysctlbyname(c"hw.optional.arm.FEAT_PACIMP");
104    let pauth2 = _sysctlbyname(c"hw.optional.arm.FEAT_PAuth2");
105    let rpres = _sysctlbyname(c"hw.optional.arm.FEAT_RPRES");
106    let specres = _sysctlbyname(c"hw.optional.arm.FEAT_SPECRES");
107    let specres2 = _sysctlbyname(c"hw.optional.arm.FEAT_SPECRES2");
108     */
109
110    // The following "features" are reported by `sysctl` but are mandatory parts
111    // of SME or SME2, and so are not exposed separately by
112    // `is_aarch64_feature_detected`.  They are here to document their
113    // existence, in case they're needed in the future.
114    /*
115    let sme_b16f32 = _sysctlbyname(c"hw.optional.arm.SME_B16F32");
116    let sme_bi32i32 = _sysctlbyname(c"hw.optional.arm.SME_BI32I32");
117    let sme_f16f32 = _sysctlbyname(c"hw.optional.arm.SME_F16F32");
118    let sme_f32f32 = _sysctlbyname(c"hw.optional.arm.SME_F32F32");
119    let sme_i16i32 = _sysctlbyname(c"hw.optional.arm.SME_I16I32");
120    let sme_i8i32 = _sysctlbyname(c"hw.optional.arm.SME_I8I32");
121     */
122
123    enable_feature(Feature::aes, aes && pmull);
124    enable_feature(Feature::asimd, asimd);
125    enable_feature(Feature::bf16, bf16);
126    enable_feature(Feature::bti, bti);
127    enable_feature(Feature::crc, crc_old || crc);
128    enable_feature(Feature::cssc, cssc);
129    enable_feature(Feature::dit, dit);
130    enable_feature(Feature::dotprod, dotprod);
131    enable_feature(Feature::dpb, dpb);
132    enable_feature(Feature::dpb2, dpb2);
133    enable_feature(Feature::ecv, ecv);
134    enable_feature(Feature::fcma, fcma);
135    enable_feature(Feature::fhm, fhm);
136    enable_feature(Feature::flagm, flagm);
137    enable_feature(Feature::flagm2, flagm2);
138    enable_feature(Feature::fp, fp);
139    enable_feature(Feature::fp16, fp16);
140    enable_feature(Feature::frintts, frintts);
141    enable_feature(Feature::hbc, hbc);
142    enable_feature(Feature::i8mm, i8mm);
143    enable_feature(Feature::jsconv, jsconv);
144    enable_feature(Feature::lse, lse);
145    enable_feature(Feature::lse2, lse2);
146    enable_feature(Feature::mte, mte && mte2);
147    enable_feature(Feature::paca, pauth);
148    enable_feature(Feature::pacg, pauth);
149    enable_feature(Feature::pmull, aes && pmull);
150    enable_feature(Feature::rcpc, rcpc);
151    enable_feature(Feature::rcpc2, rcpc2);
152    enable_feature(Feature::rdm, rdm);
153    enable_feature(Feature::sb, sb);
154    enable_feature(Feature::sha2, sha1 && sha256 && asimd);
155    enable_feature(Feature::sha3, sha512 && sha3 && asimd);
156    enable_feature(Feature::sme, sme);
157    enable_feature(Feature::sme2, sme2);
158    enable_feature(Feature::sme2p1, sme2p1);
159    enable_feature(Feature::sme_b16b16, sme_b16b16);
160    enable_feature(Feature::sme_f16f16, sme_f16f16);
161    enable_feature(Feature::sme_f64f64, sme_f64f64);
162    enable_feature(Feature::sme_i16i64, sme_i16i64);
163    enable_feature(Feature::ssbs, ssbs);
164    enable_feature(Feature::sve_b16b16, sve_b16b16);
165    enable_feature(Feature::wfxt, wfxt);
166
167    value
168}