From 0a627fcde9ccb7243d11ecfd93f61b6c06afa03b Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 30 Apr 2023 20:07:13 +0900 Subject: [PATCH] detect: Support run-time detection on powerpc64 AIX --- .github/.cspell/project-dictionary.txt | 1 + src/imp/atomic128/README.md | 1 + src/imp/atomic128/detect/powerpc64_aix.rs | 68 +++++++++++++++++++++++ src/imp/atomic128/powerpc64.rs | 12 ++++ src/imp/fallback/mod.rs | 1 + src/imp/mod.rs | 3 + src/utils.rs | 2 + tools/build.sh | 4 +- 8 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 src/imp/atomic128/detect/powerpc64_aix.rs diff --git a/.github/.cspell/project-dictionary.txt b/.github/.cspell/project-dictionary.txt index f8d351ae..32b1cb60 100644 --- a/.github/.cspell/project-dictionary.txt +++ b/.github/.cspell/project-dictionary.txt @@ -45,6 +45,7 @@ espup exynos FIQs getauxval +getsystemcfg HWCAP ifunc includepath diff --git a/src/imp/atomic128/README.md b/src/imp/atomic128/README.md index 6e0c8798..6d449ce7 100644 --- a/src/imp/atomic128/README.md +++ b/src/imp/atomic128/README.md @@ -46,6 +46,7 @@ Here is the table of targets that support run-time feature detection and the ins | aarch64 | fuchsia | zx_system_get_features | Enabled by default | | powerpc64 | linux | getauxval | Disabled by default | | powerpc64 | freebsd | elf_aux_info | Disabled by default | +| powerpc64 | aix | getsystemcfg | Disabled by default | Run-time detection is enabled by default on most targets and can be disabled with `--cfg portable_atomic_no_outline_atomics`. diff --git a/src/imp/atomic128/detect/powerpc64_aix.rs b/src/imp/atomic128/detect/powerpc64_aix.rs new file mode 100644 index 00000000..d134c680 --- /dev/null +++ b/src/imp/atomic128/detect/powerpc64_aix.rs @@ -0,0 +1,68 @@ +// Run-time feature detection on powerpc64 AIX by using getsystemcfg. +// +// Refs: +// - https://github.com/golang/go/blob/master/src/internal/cpu/cpu_ppc64x_aix.go + +include!("common.rs"); + +// core::ffi::c_* (except c_void) requires Rust 1.64, libc will soon require Rust 1.47 +mod ffi { + pub(crate) use super::c_types::{c_int, c_ulong}; + + // https://github.com/rust-lang/libc/blob/0.2.140/src/unix/aix/mod.rs#L1576 + // https://github.com/golang/go/blob/master/src/internal/cpu/cpu_ppc64x_aix.go + pub(crate) const SC_IMPL: c_int = 2; + pub(crate) const POWER_8: c_ulong = 0x10000; + + extern "C" { + // https://www.ibm.com/docs/en/aix/7.2?topic=g-getsystemcfg-subroutine + // https://github.com/rust-lang/libc/blob/0.2.140/src/unix/aix/powerpc64.rs#L569 + pub(crate) fn getsystemcfg(name: c_int) -> c_ulong; + } +} + +#[cold] +fn _detect(info: &mut CpuInfo) { + // SAFETY: calling getsystemcfg is safe. + let impl_ = unsafe { ffi::getsystemcfg(ffi::SC_IMPL) }; + if impl_ == ffi::c_ulong::MAX { + return; + } + if impl_ & ffi::POWER_8 != 0 { + info.set(CpuInfo::HAS_QUADWORD_ATOMICS); + } +} + +#[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 defined + // in libc 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: 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::libc; + let mut _getsystemcfg: unsafe extern "C" fn(ffi::c_int) -> ffi::c_ulong = ffi::getsystemcfg; + _getsystemcfg = libc::getsystemcfg; + static_assert!(ffi::SC_IMPL == libc::SC_IMPL); + static_assert!(ffi::POWER_8 == libc::POWER_8); + }; +} diff --git a/src/imp/atomic128/powerpc64.rs b/src/imp/atomic128/powerpc64.rs index d9a04abd..b315c8c6 100644 --- a/src/imp/atomic128/powerpc64.rs +++ b/src/imp/atomic128/powerpc64.rs @@ -58,6 +58,18 @@ mod fallback; ))] #[path = "detect/auxv.rs"] mod detect; +#[cfg(not(portable_atomic_no_outline_atomics))] +#[cfg(any(test, portable_atomic_outline_atomics))] // TODO(powerpc64): currently disabled by default +#[cfg(any( + test, + not(any( + target_feature = "quadword-atomics", + portable_atomic_target_feature = "quadword-atomics", + )), +))] +#[cfg(target_os = "aix")] +#[path = "detect/powerpc64_aix.rs"] +mod detect; use core::{arch::asm, sync::atomic::Ordering}; diff --git a/src/imp/fallback/mod.rs b/src/imp/fallback/mod.rs index 6bd42d75..7630bc93 100644 --- a/src/imp/fallback/mod.rs +++ b/src/imp/fallback/mod.rs @@ -32,6 +32,7 @@ ), ), target_os = "freebsd", + target_os = "aix", ), not(any(miri, portable_atomic_sanitize_thread)), ), diff --git a/src/imp/mod.rs b/src/imp/mod.rs index 178a1d39..dc82ea53 100644 --- a/src/imp/mod.rs +++ b/src/imp/mod.rs @@ -72,6 +72,7 @@ mod x86_64; ), ), target_os = "freebsd", + target_os = "aix", ), not(any(miri, portable_atomic_sanitize_thread)), ), @@ -417,6 +418,7 @@ pub(crate) use self::x86_64::{AtomicI128, AtomicU128}; ), ), target_os = "freebsd", + target_os = "aix", ), not(any(miri, portable_atomic_sanitize_thread)), ), @@ -464,6 +466,7 @@ pub(crate) use self::s390x::{AtomicI128, AtomicU128}; ), ), target_os = "freebsd", + target_os = "aix", ), not(any(miri, portable_atomic_sanitize_thread)), ), diff --git a/src/utils.rs b/src/utils.rs index dc2cb69c..78679e94 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -465,6 +465,7 @@ mod atomic_64_macros { ), ), target_os = "freebsd", + target_os = "aix", ), not(any(miri, portable_atomic_sanitize_thread)), ), @@ -544,6 +545,7 @@ mod atomic_128_macros { ), ), target_os = "freebsd", + target_os = "aix", ), not(any(miri, portable_atomic_sanitize_thread)), ), diff --git a/tools/build.sh b/tools/build.sh index b440a8d2..fccff246 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -100,6 +100,7 @@ default_targets=( powerpc64le-unknown-linux-musl powerpc64-unknown-freebsd powerpc64le-unknown-freebsd + powerpc64-ibm-aix # s390x # rustc --print target-list | grep -E '^s390x' @@ -154,7 +155,8 @@ is_no_std() { case "$1" in # https://github.com/rust-lang/rust/blob/1.70.0/library/std/build.rs#L41 # TODO: aarch64-unknown-linux-uclibc is a custom target and libc/std currently doesn't support it. - *-none* | *-uefi* | *-psp* | *-psx* | *-cuda* | avr-* | aarch64-unknown-linux-uclibc) return 0 ;; + # TODO: std currently doesn't support AIX: https://github.com/rust-lang/rust/pull/109882 + *-none* | *-uefi* | *-psp* | *-psx* | *-cuda* | avr-* | aarch64-unknown-linux-uclibc | *-aix) return 0 ;; *) return 1 ;; esac }