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