From 3cc4c94d95a84101cafd81a05fa33c1d33def7e1 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Fri, 20 Sep 2024 03:31:39 +0900 Subject: [PATCH] detect: Support run-time detection on AArch64 illumos --- src/imp/atomic128/aarch64.rs | 22 +++++++++ src/imp/detect/README.md | 1 + src/imp/detect/aarch64_illumos.rs | 82 +++++++++++++++++++++++++++++++ src/imp/detect/common.rs | 5 +- tools/build.sh | 5 +- 5 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 src/imp/detect/aarch64_illumos.rs diff --git a/src/imp/atomic128/aarch64.rs b/src/imp/atomic128/aarch64.rs index 286f30ab..9eaebbe6 100644 --- a/src/imp/atomic128/aarch64.rs +++ b/src/imp/atomic128/aarch64.rs @@ -115,6 +115,18 @@ mod detect; #[path = "../detect/aarch64_aa64reg.rs"] mod detect; #[cfg(not(portable_atomic_no_outline_atomics))] +#[cfg(any(test, portable_atomic_outline_atomics))] // TODO(aarch64-illumos): currently disabled by default +#[cfg(any( + test, + not(all( + any(target_feature = "lse2", portable_atomic_target_feature = "lse2"), + any(target_feature = "lse", portable_atomic_target_feature = "lse"), + )), +))] +#[cfg(target_os = "illumos")] +#[path = "../detect/aarch64_illumos.rs"] +mod detect; +#[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any(test, not(any(target_feature = "lse", portable_atomic_target_feature = "lse"))))] #[cfg(target_os = "fuchsia")] #[path = "../detect/aarch64_fuchsia.rs"] @@ -176,6 +188,7 @@ macro_rules! debug_assert_lse { target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", + all(target_os = "illumos", portable_atomic_outline_atomics), target_os = "fuchsia", target_os = "windows", ), @@ -212,6 +225,7 @@ macro_rules! debug_assert_lse2 { target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", + all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LSE2. // target_os = "fuchsia", // target_os = "windows", @@ -252,6 +266,7 @@ macro_rules! debug_assert_lse128 { target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", + all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LSE128. // target_os = "fuchsia", // target_os = "windows", @@ -292,6 +307,7 @@ macro_rules! debug_assert_rcpc3 { target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", + all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LRCPC3. // target_os = "fuchsia", // target_os = "windows", @@ -504,6 +520,7 @@ unsafe fn atomic_load(src: *mut u128, order: Ordering) -> u128 { target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", + all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LSE2. // target_os = "fuchsia", // target_os = "windows", @@ -600,6 +617,7 @@ unsafe fn atomic_load(src: *mut u128, order: Ordering) -> u128 { target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", + all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LSE2. // target_os = "fuchsia", // target_os = "windows", @@ -925,6 +943,7 @@ unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) { target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", + all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LSE2. // target_os = "fuchsia", // target_os = "windows", @@ -1029,6 +1048,7 @@ unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) { target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", + all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LSE2. // target_os = "fuchsia", // target_os = "windows", @@ -1254,6 +1274,7 @@ unsafe fn atomic_compare_exchange( target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", + all(target_os = "illumos", portable_atomic_outline_atomics), target_os = "fuchsia", target_os = "windows", ), @@ -1392,6 +1413,7 @@ unsafe fn atomic_compare_exchange( target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", + all(target_os = "illumos", portable_atomic_outline_atomics), target_os = "fuchsia", target_os = "windows", ), diff --git a/src/imp/detect/README.md b/src/imp/detect/README.md index a918bd29..80866dab 100644 --- a/src/imp/detect/README.md +++ b/src/imp/detect/README.md @@ -13,6 +13,7 @@ Here is the table of targets that support run-time CPU feature detection and the | aarch64 | netbsd | sysctlbyname | all | Enabled by default | | aarch64 | openbsd | sysctl | all | Enabled by default | | aarch64 | macos/ios/tvos/watchos/visionos | sysctlbyname | all | Currently only used in tests (see [aarch64_apple.rs](aarch64_apple.rs)). | +| aarch64 | illumos | getisax | lse, lse2 | Disabled by default | | aarch64 | windows | IsProcessorFeaturePresent | lse | Enabled by default | | aarch64 | fuchsia | zx_system_get_features | lse | Enabled by default | | riscv32 | linux | riscv_hwprobe | all | Currently only used in tests due to LLVM marking zacas as experimental | diff --git a/src/imp/detect/aarch64_illumos.rs b/src/imp/detect/aarch64_illumos.rs new file mode 100644 index 00000000..f1bc3578 --- /dev/null +++ b/src/imp/detect/aarch64_illumos.rs @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +/* +Run-time CPU feature detection on AArch64 illumos by using getisax. + +As of nightly-2024-09-07, is_aarch64_feature_detected doesn't support run-time detection on illumos. +https://github.com/rust-lang/stdarch/blob/d9466edb4c53cece8686ee6e17b028436ddf4151/crates/std_detect/src/detect/mod.rs + +Run-time detection on AArch64 illumos is currently disabled by default as AArch64 port is experimental. +*/ + +include!("common.rs"); + +// core::ffi::c_* (except c_void) requires Rust 1.64, libc will soon require Rust 1.47 +#[allow(non_camel_case_types)] +mod ffi { + pub(crate) use super::c_types::c_uint; + + // Defined in sys/auxv_aarch64.h. + // https://github.com/richlowe/illumos-gate/blob/arm64-gate/usr/src/uts/common/sys/auxv_aarch64.h + pub(crate) const AV_AARCH64_LSE: u32 = 1 << 15; + pub(crate) const AV_AARCH64_2_LSE2: u32 = 1 << 2; + + extern "C" { + // Defined in sys/auxv.h. + // https://illumos.org/man/2/getisax + // https://github.com/richlowe/illumos-gate/blob/arm64-gate/usr/src/uts/common/sys/auxv.h + pub(crate) fn getisax(array: *mut u32, n: c_uint) -> c_uint; + } +} + +#[cold] +fn _detect(info: &mut CpuInfo) { + let mut out = [0_u32; 2]; + // SAFETY: the pointer is valid because we got it from a reference. + unsafe { + ffi::getisax(out.as_mut_ptr(), 2); + } + if out[0] & ffi::AV_AARCH64_LSE != 0 { + info.set(CpuInfo::HAS_LSE); + } + if out[1] & ffi::AV_AARCH64_2_LSE2 != 0 { + info.set(CpuInfo::HAS_LSE2); + } +} + +#[allow( + clippy::alloc_instead_of_core, + clippy::std_instead_of_alloc, + clippy::std_instead_of_core, + clippy::undocumented_unsafe_blocks, + clippy::wildcard_imports +)] +#[cfg(test)] +mod tests { + use super::*; + + // Static assertions for FFI bindings. + // This checks that FFI bindings defined in this crate and FFI bindings + // generated for the platform's latest header file using bindgen have + // compatible signatures (or the same values if constants). + // Since this is static assertion, we can detect problems with + // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) + // without actually running tests on these platforms. + // See also tools/codegen/src/ffi.rs. + // TODO(codegen): auto-generate this test + #[allow( + clippy::cast_possible_wrap, + clippy::cast_sign_loss, + clippy::cast_possible_truncation, + clippy::no_effect_underscore_binding + )] + const _: fn() = || { + use test_helper::sys; + let mut _getisax: unsafe extern "C" fn(*mut u32, ffi::c_uint) -> ffi::c_uint = ffi::getisax; + _getisax = sys::getisax; + // static_assert!(ffi::AV_AARCH64_LSE == libc::AV_AARCH64_LSE); + static_assert!(ffi::AV_AARCH64_LSE == sys::AV_AARCH64_LSE); + // static_assert!(ffi::AV_AARCH64_2_LSE2 == libc::AV_AARCH64_2_LSE2); + static_assert!(ffi::AV_AARCH64_2_LSE2 == sys::AV_AARCH64_2_LSE2); + }; +} diff --git a/src/imp/detect/common.rs b/src/imp/detect/common.rs index 9c9d2ebf..43904a16 100644 --- a/src/imp/detect/common.rs +++ b/src/imp/detect/common.rs @@ -170,9 +170,10 @@ mod c_types { let _: c_long = 0 as std::os::raw::c_long; let _: c_ulong = 0 as std::os::raw::c_ulong; let _: c_size_t = 0 as libc::size_t; // std::os::raw::c_size_t is unstable - #[cfg(not( + #[cfg(not(any( + all(target_arch = "aarch64", target_os = "illumos"), // TODO: https://github.com/rust-lang/rust/issues/129945 all(target_arch = "riscv64", target_os = "android"), // TODO: https://github.com/rust-lang/rust/issues/129945 - ))] + )))] let _: c_char = 0 as std::os::raw::c_char; let _: c_char = 0 as sys::c_char; }; diff --git a/tools/build.sh b/tools/build.sh index 49b7b566..b528724a 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -70,6 +70,7 @@ default_targets=( aarch64-unknown-linux-uclibc # custom target aarch64-unknown-netbsd aarch64-unknown-openbsd + aarch64-unknown-illumos # FEAT_LSE & FEAT_LSE2 aarch64-apple-darwin # big endian @@ -511,9 +512,9 @@ build() { ;; esac case "${target}" in - # portable_atomic_outline_atomics only affects aarch64 Linux and powerpc64. + # portable_atomic_outline_atomics only affects aarch64 Linux/illumos and powerpc64. # powerpc64le- (little-endian) is skipped because it is pwr8 by default - aarch64*-linux-* | powerpc64-*) + aarch64*-linux-* | aarch64*-illumos* | powerpc64-*) CARGO_TARGET_DIR="${target_dir}/outline-atomics" \ RUSTFLAGS="${target_rustflags} --cfg portable_atomic_outline_atomics" \ x_cargo "${args[@]}" "$@"