• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: Apache-2.0 OR MIT
2 
3 /*
4 Run-time CPU feature detection on AArch64 Fuchsia by using zx_system_get_features.
5 
6 As of nightly-2024-09-07, is_aarch64_feature_detected doesn't support run-time detection on Fuchsia.
7 https://github.com/rust-lang/stdarch/blob/d9466edb4c53cece8686ee6e17b028436ddf4151/crates/std_detect/src/detect/mod.rs
8 
9 Refs:
10 - https://fuchsia.dev/reference/syscalls/system_get_features
11 - https://github.com/llvm/llvm-project/commit/4e731abc55681751b5d736b613f7720e50eb1ad4
12 */
13 
14 include!("common.rs");
15 
16 #[allow(non_camel_case_types)]
17 mod ffi {
18     // https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/types.h
19     pub(crate) type zx_status_t = i32;
20 
21     // https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/errors.h
22     pub(crate) const ZX_OK: zx_status_t = 0;
23 
24     // https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/features.h
25     pub(crate) const ZX_FEATURE_KIND_CPU: u32 = 0;
26     pub(crate) const ZX_ARM64_FEATURE_ISA_ATOMICS: u32 = 1 << 8;
27 
28     #[link(name = "zircon")]
29     extern "C" {
30         // https://fuchsia.dev/reference/syscalls/system_get_features
zx_system_get_features(kind: u32, features: *mut u32) -> zx_status_t31         pub(crate) fn zx_system_get_features(kind: u32, features: *mut u32) -> zx_status_t;
32     }
33 }
34 
zx_system_get_features(kind: u32) -> u3235 fn zx_system_get_features(kind: u32) -> u32 {
36     let mut out = 0_u32;
37     // SAFETY: the pointer is valid because we got it from a reference.
38     let res = unsafe { ffi::zx_system_get_features(kind, &mut out) };
39     if res != ffi::ZX_OK {
40         return 0;
41     }
42     out
43 }
44 
45 #[cold]
_detect(info: &mut CpuInfo)46 fn _detect(info: &mut CpuInfo) {
47     let features = zx_system_get_features(ffi::ZX_FEATURE_KIND_CPU);
48     if features & ffi::ZX_ARM64_FEATURE_ISA_ATOMICS != 0 {
49         info.set(CpuInfo::HAS_LSE);
50     }
51 }
52 
53 #[allow(
54     clippy::alloc_instead_of_core,
55     clippy::std_instead_of_alloc,
56     clippy::std_instead_of_core,
57     clippy::undocumented_unsafe_blocks,
58     clippy::wildcard_imports
59 )]
60 #[cfg(test)]
61 mod tests {
62     use super::*;
63 
64     #[test]
test_fuchsia()65     fn test_fuchsia() {
66         let features = zx_system_get_features(ffi::ZX_FEATURE_KIND_CPU);
67         assert_ne!(features, 0);
68         std::eprintln!("features: {:b}", features);
69     }
70 
71     // Static assertions for FFI bindings.
72     // This checks that FFI bindings defined in this crate and FFI bindings
73     // generated for the platform's latest header file using bindgen have
74     // compatible signatures (or the same values if constants).
75     // Since this is static assertion, we can detect problems with
76     // `cargo check --tests --target <target>` run in CI (via TESTS=1 build.sh)
77     // without actually running tests on these platforms.
78     // See also tools/codegen/src/ffi.rs.
79     // TODO(codegen): auto-generate this test
80     #[allow(
81         clippy::cast_possible_wrap,
82         clippy::cast_sign_loss,
83         clippy::cast_possible_truncation,
84         clippy::no_effect_underscore_binding
85     )]
86     const _: fn() = || {
87         use test_helper::sys;
88         // TODO(codegen): zx_system_get_features
89         let _: ffi::zx_status_t = 0 as sys::zx_status_t;
90         static_assert!(ffi::ZX_OK == sys::ZX_OK as ffi::zx_status_t);
91         static_assert!(ffi::ZX_FEATURE_KIND_CPU == sys::ZX_FEATURE_KIND_CPU);
92         static_assert!(ffi::ZX_ARM64_FEATURE_ISA_ATOMICS == sys::ZX_ARM64_FEATURE_ISA_ATOMICS);
93     };
94 }
95