Skip to content

Commit

Permalink
detect: Support run-time detection on aarch64 Fuchsia
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Feb 11, 2023
1 parent a5deb26 commit 2b92b70
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 25 deletions.
4 changes: 4 additions & 0 deletions src/imp/atomic128/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,15 @@ include!("macros.rs");
)]
#[cfg_attr(target_os = "windows", path = "detect/aarch64_windows.rs")]
#[cfg_attr(any(target_os = "freebsd", target_os = "openbsd"), path = "detect/aarch64_aa64reg.rs")]
#[cfg_attr(target_os = "fuchsia", path = "detect/aarch64_fuchsia.rs")]
#[cfg_attr(
not(any(
all(target_os = "linux", target_env = "gnu"),
target_os = "android",
target_os = "windows",
target_os = "freebsd",
target_os = "openbsd",
target_os = "fuchsia",
)),
path = "detect/aarch64_std.rs"
)]
Expand Down Expand Up @@ -309,6 +311,7 @@ unsafe fn atomic_compare_exchange(
target_os = "windows",
target_os = "freebsd",
target_os = "openbsd",
target_os = "fuchsia",
)
)))]
#[cfg(not(any(target_feature = "lse", portable_atomic_target_feature = "lse")))]
Expand All @@ -324,6 +327,7 @@ unsafe fn atomic_compare_exchange(
target_os = "windows",
target_os = "freebsd",
target_os = "openbsd",
target_os = "fuchsia",
)
))]
#[cfg(not(any(target_feature = "lse", portable_atomic_target_feature = "lse")))]
Expand Down
89 changes: 89 additions & 0 deletions src/imp/atomic128/detect/aarch64_fuchsia.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Run-time feature detection on aarch64 Fuchsia by using zx_system_get_features.
//
// As of nightly-2023-01-23, is_aarch64_feature_detected doesn't support run-time detection on Fuchsia.
// https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/mod.rs
//
// Refs:
// - https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_features
// - https://github.com/llvm/llvm-project/commit/4e731abc55681751b5d736b613f7720e50eb1ad4

#![cfg_attr(
any(
portable_atomic_no_aarch64_target_feature,
any(target_feature = "lse", portable_atomic_target_feature = "lse")
),
allow(dead_code)
)]

include!("common.rs");

#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
mod ffi {
// https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/types.h
pub(crate) type zx_status_t = i32;

// https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/errors.h
pub(crate) const ZX_OK: zx_status_t = 0;
// https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/features.h
pub(crate) const ZX_FEATURE_KIND_CPU: u32 = 0;
pub(crate) const ZX_ARM64_FEATURE_ISA_ATOMICS: u32 = 1 << 8;

#[link(name = "zircon")]
extern "C" {
// https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_features
pub(crate) fn zx_system_get_features(kind: u32, features: *mut u32) -> zx_status_t;
}
}

#[inline]
fn _detect(info: &mut CpuInfo) {
let mut features: u32 = 0;
// SAFETY: we've passed a valid pointer.
let res = unsafe { ffi::zx_system_get_features(ffi::ZX_FEATURE_KIND_CPU, &mut features) };
if res != ffi::ZX_OK {
return;
}
if (features & ffi::ZX_ARM64_FEATURE_ISA_ATOMICS) != 0 {
info.set(CpuInfo::HAS_LSE);
}
}

#[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 <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 crate::tests::sys::*;
// TODO: zx_status_t, zx_system_get_features
let [] = [(); (ffi::ZX_OK - zircon_system_public_zircon_errors::ZX_OK as ffi::zx_status_t)
as usize];
let [] = [(); (ffi::ZX_FEATURE_KIND_CPU
- zircon_system_public_zircon_features::ZX_FEATURE_KIND_CPU)
as usize];
let [] = [(); (ffi::ZX_ARM64_FEATURE_ISA_ATOMICS
- zircon_system_public_zircon_features::ZX_ARM64_FEATURE_ISA_ATOMICS)
as usize];
};
}
8 changes: 7 additions & 1 deletion src/imp/atomic128/detect/aarch64_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,13 @@ fn _detect(info: &mut CpuInfo) {
}
}

#[allow(clippy::undocumented_unsafe_blocks)]
#[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::*;
Expand Down
7 changes: 7 additions & 0 deletions src/tests/gen/sys/aarch64_fuchsia/mod.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/tests/gen/sys/mod.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tools/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ default_targets=(
aarch64-pc-windows-gnullvm
aarch64-pc-windows-msvc
aarch64-unknown-freebsd
aarch64-unknown-fuchsia
aarch64-unknown-linux-gnu
aarch64-unknown-linux-musl
aarch64-unknown-linux-uclibc # custom target
Expand Down
21 changes: 21 additions & 0 deletions tools/codegen/patches/fuchsia.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
diff --git a/zircon/system/public/zircon/features.h b/zircon/system/public/zircon/features.h
--- a/zircon/system/public/zircon/features.h
+++ b/zircon/system/public/zircon/features.h
@@ -8,7 +8,7 @@
// clang-format off

// types of features that can be retrieved via |zx_system_get_features|
-#define ZX_FEATURE_KIND_CPU ((uint32_t)0)
+#define ZX_FEATURE_KIND_CPU 0
#define ZX_FEATURE_KIND_HW_BREAKPOINT_COUNT ((uint32_t)1)
#define ZX_FEATURE_KIND_HW_WATCHPOINT_COUNT ((uint32_t)2)
#define ZX_FEATURE_KIND_ADDRESS_TAGGING ((uint32_t)3)
@@ -35,7 +35,7 @@
#define ZX_ARM64_FEATURE_ISA_SHA1 ((uint32_t)(1u << 5))
#define ZX_ARM64_FEATURE_ISA_SHA256 ((uint32_t)(1u << 6))
#define ZX_ARM64_FEATURE_ISA_CRC32 ((uint32_t)(1u << 7))
-#define ZX_ARM64_FEATURE_ISA_ATOMICS ((uint32_t)(1u << 8))
+#define ZX_ARM64_FEATURE_ISA_ATOMICS (1u << 8)
#define ZX_ARM64_FEATURE_ISA_RDM ((uint32_t)(1u << 9))
#define ZX_ARM64_FEATURE_ISA_SHA3 ((uint32_t)(1u << 10))
#define ZX_ARM64_FEATURE_ISA_SM3 ((uint32_t)(1u << 11))
62 changes: 39 additions & 23 deletions tools/codegen/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
// platform APIs, and we define our own FFI bindings to those APIs.
//
// We use only one function and a few constants per platform, but
// technically OS can change these APIs so it is preferable to be able
// to detect them.
// technically OS can change these APIs (unfortunately, some operating
// systems don't care about breaking API/ABI between releases), so it is
// preferable to be able to detect them.
//
// See also https://github.com/rust-lang/libc/issues/570.

Expand All @@ -29,15 +30,9 @@ static TARGETS: &[Target] = &[
"aarch64-linux-android",
],
headers: &[
// TODO
// Header {
// // https://github.com/bminor/glibc/blob/HEAD/misc/sys/auxv.h
// // https://github.com/bminor/musl/blob/HEAD/include/sys/auxv.h
// path: "sys/auxv.h",
// types: &[],
// vars: &[],
// functions: &["getauxval"],
// },
// TODO: getauxval
// https://github.com/bminor/glibc/blob/HEAD/misc/sys/auxv.h
// https://github.com/bminor/musl/blob/HEAD/include/sys/auxv.h
Header {
// https://github.com/torvalds/linux/blob/HEAD/include/uapi/linux/auxvec.h
path: "include/uapi/linux/auxvec.h",
Expand Down Expand Up @@ -73,6 +68,28 @@ static TARGETS: &[Target] = &[
},
],
},
Target {
triples: &["aarch64-unknown-fuchsia"],
headers: &[
// TODO: zx_system_get_features
// TODO: zx_status_t
// https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/types.h
Header {
// https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/errors.h
path: "zircon/system/public/zircon/errors.h",
types: &[],
vars: &["ZX_OK"],
functions: &[],
},
Header {
// https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/features.h
path: "zircon/system/public/zircon/features.h",
types: &[],
vars: &["ZX_FEATURE_KIND_CPU", "ZX_ARM64_FEATURE_ISA_ATOMICS"],
functions: &[],
},
],
},
];

#[derive(Clone, Copy)]
Expand Down Expand Up @@ -139,6 +156,7 @@ pub(crate) fn gen() -> Result<()> {
vec![src_dir.join("arch").join(arch).join("include/uapi")]
}
openbsd => vec![src_dir.join("sys")],
fuchsia => vec![src_dir.join("zircon/system/public")],
_ => todo!("{target:?}"),
};
for include in &include {
Expand All @@ -158,6 +176,7 @@ pub(crate) fn gen() -> Result<()> {
let header_path = match target.os {
linux | android => src_dir.join(header.path),
openbsd => src_dir.join(format!("sys/{}", header.path)),
fuchsia => src_dir.join(header.path),
_ => todo!("{target:?}"),
};

Expand Down Expand Up @@ -205,28 +224,24 @@ pub(crate) fn gen() -> Result<()> {

fn git_clone(target: &TargetSpec, download_cache_dir: &Utf8Path) -> Result<Utf8PathBuf> {
fn clone(download_cache_dir: &Utf8Path, repository: &str) -> Result<Utf8PathBuf> {
let src_dir = download_cache_dir.join(repository.replace('/', "-"));
let name = repository.strip_suffix(".git").unwrap_or(repository);
let name = name.strip_prefix("https://github.com/").unwrap_or(name);
let name = name.strip_prefix("https://fuchsia.googlesource.com/").unwrap_or(name);
let src_dir = download_cache_dir.join(name.replace('/', "-"));
if src_dir.exists() {
cmd!("git", "clean", "-df",).dir(&src_dir).run()?;
// TODO: use stash?
cmd!("git", "checkout", ".",).dir(&src_dir).run()?;
} else {
// TODO: use sparse-checkout
cmd!(
"git",
"clone",
"--depth",
"1",
format!("https://github.com/{repository}.git"),
&src_dir
)
.run()?;
cmd!("git", "clone", "--depth", "1", repository, &src_dir).run()?;
}
Ok(src_dir)
}
let src_dir = match target.os {
linux | android => clone(download_cache_dir, "torvalds/linux")?,
openbsd => clone(download_cache_dir, "openbsd/src")?,
linux | android => clone(download_cache_dir, "https://github.com/torvalds/linux.git")?,
openbsd => clone(download_cache_dir, "https://github.com/openbsd/src.git")?,
fuchsia => clone(download_cache_dir, "https://fuchsia.googlesource.com/fuchsia")?,
_ => todo!("{target:?}"),
};
// TODO: remove needs of patches.
Expand Down Expand Up @@ -254,6 +269,7 @@ fn arch_symlink(target: &TargetSpec, src_dir: &Utf8Path) -> Result<()> {
let link = &src_dir.join("sys/machine");
fs::os::unix::fs::symlink(src_dir.join("sys/arch").join(arch).join("include"), link)?;
}
fuchsia => {}
_ => todo!("{target:?}"),
}
Ok(())
Expand Down
7 changes: 6 additions & 1 deletion tools/codegen/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#![warn(rust_2018_idioms, single_use_lifetimes)]
#![allow(clippy::match_on_vec_items, clippy::needless_pass_by_value, clippy::unnecessary_wraps)]
#![allow(
clippy::match_on_vec_items,
clippy::needless_pass_by_value,
clippy::single_match,
clippy::unnecessary_wraps
)]

#[cfg(unix)]
#[macro_use]
Expand Down

0 comments on commit 2b92b70

Please sign in to comment.