summaryrefslogtreecommitdiffstats
path: root/vendor/portable-atomic/src/imp/atomic128/detect
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/portable-atomic/src/imp/atomic128/detect')
-rw-r--r--vendor/portable-atomic/src/imp/atomic128/detect/aarch64_aa64reg.rs352
-rw-r--r--vendor/portable-atomic/src/imp/atomic128/detect/aarch64_fuchsia.rs2
-rw-r--r--vendor/portable-atomic/src/imp/atomic128/detect/aarch64_macos.rs16
-rw-r--r--vendor/portable-atomic/src/imp/atomic128/detect/aarch64_windows.rs2
-rw-r--r--vendor/portable-atomic/src/imp/atomic128/detect/auxv.rs404
-rw-r--r--vendor/portable-atomic/src/imp/atomic128/detect/common.rs38
-rw-r--r--vendor/portable-atomic/src/imp/atomic128/detect/x86_64.rs60
7 files changed, 789 insertions, 85 deletions
diff --git a/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_aa64reg.rs b/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_aa64reg.rs
index f32c38837..4cbdb51ff 100644
--- a/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_aa64reg.rs
+++ b/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_aa64reg.rs
@@ -1,6 +1,8 @@
-// Run-time feature detection on aarch64 Linux/FreeBSD/OpenBSD by parsing system registers.
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+// Run-time feature detection on aarch64 Linux/FreeBSD/NetBSD/OpenBSD by parsing system registers.
//
-// As of nightly-2023-01-23, is_aarch64_feature_detected doesn't support run-time detection on OpenBSD.
+// As of nightly-2023-01-23, is_aarch64_feature_detected doesn't support run-time detection on NetBSD/OpenBSD.
// https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/mod.rs
// https://github.com/rust-lang/stdarch/pull/1374
//
@@ -14,10 +16,12 @@
// https://github.com/torvalds/linux/commit/77c97b4ee21290f5f083173d957843b615abbff2
// - FreeBSD 12.0+ (emulate mrs instruction)
// https://github.com/freebsd/freebsd-src/commit/398810619cb32abf349f8de23f29510b2ee0839b
+// - NetBSD 9.0+ (through sysctl)
+// https://github.com/NetBSD/src/commit/0e9d25528729f7fea53e78275d1bc5039dfe8ffb
// - OpenBSD 7.1+ (through sysctl)
// https://github.com/openbsd/src/commit/d335af936b9d7dd9cf655cae1ce19560c45de6c8
//
-// For now, this module is only used on OpenBSD.
+// For now, this module is only used on NetBSD/OpenBSD.
// On Linux/FreeBSD, this module is test-only:
// - On Linux, this approach requires a higher kernel version than Rust supports,
// and also does not work with qemu-user (as of QEMU 7.2) and Valgrind.
@@ -28,11 +32,14 @@
include!("common.rs");
+#[cfg_attr(test, derive(Debug, PartialEq))]
struct AA64Reg {
aa64isar0: u64,
#[cfg(test)]
aa64isar1: u64,
- #[cfg(test)]
+ // OpenBSD has an API to get this, but currently always returns 0.
+ // https://github.com/openbsd/src/blob/6a233889798dc3ecb18acc52dce1e57862af2957/sys/arch/arm64/arm64/machdep.c#L371-L377
+ #[cfg_attr(target_os = "openbsd", cfg(test))]
aa64mmfr2: u64,
}
@@ -42,7 +49,7 @@ fn _detect(info: &mut CpuInfo) {
aa64isar0,
#[cfg(test)]
aa64isar1,
- #[cfg(test)]
+ #[cfg_attr(target_os = "openbsd", cfg(test))]
aa64mmfr2,
} = imp::aa64reg();
@@ -51,7 +58,7 @@ fn _detect(info: &mut CpuInfo) {
let atomic = extract(aa64isar0, 23, 20);
if atomic >= 2 {
info.set(CpuInfo::HAS_LSE);
- // we currently only use FEAT_LSE in outline-atomics.
+ // we currently only use FEAT_LSE and FEAT_LSE2 in outline-atomics.
#[cfg(test)]
{
if atomic >= 3 {
@@ -59,7 +66,7 @@ fn _detect(info: &mut CpuInfo) {
}
}
}
- // we currently only use FEAT_LSE in outline-atomics.
+ // we currently only use FEAT_LSE and FEAT_LSE2 in outline-atomics.
#[cfg(test)]
{
// ID_AA64ISAR1_EL1, Instruction Set Attribute Register 1
@@ -67,6 +74,11 @@ fn _detect(info: &mut CpuInfo) {
if extract(aa64isar1, 23, 20) >= 3 {
info.set(CpuInfo::HAS_RCPC3);
}
+ }
+ // OpenBSD has an API to get this, but currently always returns 0.
+ // https://github.com/openbsd/src/blob/6a233889798dc3ecb18acc52dce1e57862af2957/sys/arch/arm64/arm64/machdep.c#L371-L377
+ #[cfg_attr(target_os = "openbsd", cfg(test))]
+ {
// ID_AA64MMFR2_EL1, AArch64 Memory Model Feature Register 2
// https://developer.arm.com/documentation/ddi0601/2023-06/AArch64-Registers/ID-AA64MMFR2-EL1--AArch64-Memory-Model-Feature-Register-2?lang=en
if extract(aa64mmfr2, 35, 32) >= 1 {
@@ -79,7 +91,7 @@ fn extract(x: u64, high: usize, low: usize) -> u64 {
(x >> low) & ((1 << (high - low + 1)) - 1)
}
-#[cfg(not(target_os = "openbsd"))]
+#[cfg(not(any(target_os = "netbsd", target_os = "openbsd")))]
mod imp {
// This module is test-only. See parent module docs for details.
@@ -95,7 +107,7 @@ mod imp {
unsafe {
let aa64isar0: u64;
asm!(
- "mrs {}, ID_AA64ISAR0_EL1",
+ "mrs {0}, ID_AA64ISAR0_EL1",
out(reg) aa64isar0,
options(pure, nomem, nostack, preserves_flags)
);
@@ -104,31 +116,140 @@ mod imp {
#[cfg(test)]
{
asm!(
- "mrs {}, ID_AA64ISAR1_EL1",
+ "mrs {0}, ID_AA64ISAR1_EL1",
out(reg) aa64isar1,
options(pure, nomem, nostack, preserves_flags)
);
}
- #[cfg(test)]
let aa64mmfr2: u64;
- #[cfg(test)]
- {
- asm!(
- "mrs {}, ID_AA64MMFR2_EL1",
- out(reg) aa64mmfr2,
- options(pure, nomem, nostack, preserves_flags)
- );
- }
+ asm!(
+ "mrs {0}, ID_AA64MMFR2_EL1",
+ out(reg) aa64mmfr2,
+ options(pure, nomem, nostack, preserves_flags)
+ );
AA64Reg {
aa64isar0,
#[cfg(test)]
aa64isar1,
- #[cfg(test)]
aa64mmfr2,
}
}
}
}
+#[cfg(target_os = "netbsd")]
+mod imp {
+ // NetBSD doesn't trap the mrs instruction, but exposes the system registers through sysctl.
+ // https://github.com/NetBSD/src/commit/0e9d25528729f7fea53e78275d1bc5039dfe8ffb
+ // https://github.com/golang/sys/commit/ef9fd89ba245e184bdd308f7f2b4f3c551fa5b0f
+
+ use core::ptr;
+
+ use super::AA64Reg;
+
+ // core::ffi::c_* (except c_void) requires Rust 1.64, libc will soon require Rust 1.47
+ #[allow(non_camel_case_types)]
+ pub(super) mod ffi {
+ pub(crate) use super::super::c_types::{c_char, c_int, c_size_t, c_void};
+
+ extern "C" {
+ // Defined in sys/sysctl.h.
+ // https://man.netbsd.org/sysctl.3
+ // https://github.com/NetBSD/src/blob/167403557cf60bed09a63fc84d941a1a4bd7d52e/sys/sys/sysctl.h
+ // https://github.com/rust-lang/libc/blob/0.2.139/src/unix/bsd/netbsdlike/netbsd/mod.rs#L2582
+ pub(crate) fn sysctlbyname(
+ name: *const c_char,
+ old_p: *mut c_void,
+ old_len_p: *mut c_size_t,
+ new_p: *const c_void,
+ new_len: c_size_t,
+ ) -> c_int;
+ }
+
+ // Defined in aarch64/armreg.h.
+ // https://github.com/NetBSD/src/blob/167403557cf60bed09a63fc84d941a1a4bd7d52e/sys/arch/aarch64/include/armreg.h#L1626
+ #[derive(Clone, Copy)]
+ #[repr(C)]
+ pub(crate) struct aarch64_sysctl_cpu_id {
+ // NetBSD 9.0+
+ // https://github.com/NetBSD/src/commit/0e9d25528729f7fea53e78275d1bc5039dfe8ffb
+ pub(crate) midr: u64,
+ pub(crate) revidr: u64,
+ pub(crate) mpidr: u64,
+ pub(crate) aa64dfr0: u64,
+ pub(crate) aa64dfr1: u64,
+ pub(crate) aa64isar0: u64,
+ pub(crate) aa64isar1: u64,
+ pub(crate) aa64mmfr0: u64,
+ pub(crate) aa64mmfr1: u64,
+ pub(crate) aa64mmfr2: u64,
+ pub(crate) aa64pfr0: u64,
+ pub(crate) aa64pfr1: u64,
+ pub(crate) aa64zfr0: u64,
+ pub(crate) mvfr0: u32,
+ pub(crate) mvfr1: u32,
+ pub(crate) mvfr2: u32,
+ // NetBSD 10.0+
+ // https://github.com/NetBSD/src/commit/0c7bdc13f0e332cccec56e307f023b4888638973
+ pub(crate) pad: u32,
+ pub(crate) clidr: u64,
+ pub(crate) ctr: u64,
+ }
+ }
+
+ pub(super) unsafe fn sysctl_cpu_id(name: &[u8]) -> Option<AA64Reg> {
+ const OUT_LEN: ffi::c_size_t =
+ core::mem::size_of::<ffi::aarch64_sysctl_cpu_id>() as ffi::c_size_t;
+
+ debug_assert_eq!(name.last(), Some(&0), "{:?}", name);
+ debug_assert_eq!(name.iter().filter(|&&v| v == 0).count(), 1, "{:?}", name);
+
+ // SAFETY: all fields of aarch64_sysctl_cpu_id are zero-able and we use
+ // the result when machdep.cpuN.cpu_id sysctl was successful.
+ let mut buf: ffi::aarch64_sysctl_cpu_id = unsafe { core::mem::zeroed() };
+ let mut out_len = OUT_LEN;
+ // SAFETY:
+ // - the caller must guarantee that `name` is ` machdep.cpuN.cpu_id` in a C string.
+ // - `out_len` does not exceed the size of the value at `buf`.
+ // - `sysctlbyname` is thread-safe.
+ let res = unsafe {
+ ffi::sysctlbyname(
+ name.as_ptr().cast::<ffi::c_char>(),
+ (&mut buf as *mut ffi::aarch64_sysctl_cpu_id).cast::<ffi::c_void>(),
+ &mut out_len,
+ ptr::null_mut(),
+ 0,
+ )
+ };
+ if res != 0 {
+ return None;
+ }
+ Some(AA64Reg {
+ aa64isar0: buf.aa64isar0,
+ #[cfg(test)]
+ aa64isar1: buf.aa64isar1,
+ aa64mmfr2: buf.aa64mmfr2,
+ })
+ }
+
+ pub(super) fn aa64reg() -> AA64Reg {
+ // Get system registers for cpu0.
+ // If failed, returns default because machdep.cpuN.cpu_id sysctl is not available.
+ // machdep.cpuN.cpu_id sysctl was added on NetBSD 9.0 so it is not available on older versions.
+ // SAFETY: we passed a valid name in a C string.
+ // It is ok to check only cpu0, even if there are more CPUs.
+ // https://github.com/NetBSD/src/commit/bd9707e06ea7d21b5c24df6dfc14cb37c2819416
+ // https://github.com/golang/sys/commit/ef9fd89ba245e184bdd308f7f2b4f3c551fa5b0f
+ match unsafe { sysctl_cpu_id(b"machdep.cpu0.cpu_id\0") } {
+ Some(cpu_id) => cpu_id,
+ None => AA64Reg {
+ aa64isar0: 0,
+ #[cfg(test)]
+ aa64isar1: 0,
+ aa64mmfr2: 0,
+ },
+ }
+ }
+}
#[cfg(target_os = "openbsd")]
mod imp {
// OpenBSD doesn't trap the mrs instruction, but exposes the system registers through sysctl.
@@ -152,6 +273,8 @@ mod imp {
pub(crate) const CPU_ID_AA64ISAR0: c_int = 2;
#[cfg(test)]
pub(crate) const CPU_ID_AA64ISAR1: c_int = 3;
+ // OpenBSD has an API to get this, but currently always returns 0.
+ // https://github.com/openbsd/src/blob/6a233889798dc3ecb18acc52dce1e57862af2957/sys/arch/arm64/arm64/machdep.c#L371-L377
#[cfg(test)]
pub(crate) const CPU_ID_AA64MMFR2: c_int = 7;
@@ -276,6 +399,145 @@ mod tests {
}
}
+ #[allow(clippy::cast_possible_wrap)]
+ #[cfg(target_os = "netbsd")]
+ #[test]
+ fn test_netbsd() {
+ use c_types::*;
+ use core::{arch::asm, mem, ptr};
+ use imp::ffi;
+ use test_helper::sys;
+
+ // Call syscall using asm instead of libc.
+ // Note that NetBSD does not guarantee the stability of raw syscall as
+ // much as Linux does (It may actually be stable enough, though: https://lists.llvm.org/pipermail/llvm-dev/2019-June/133393.html).
+ //
+ // This is currently used only for testing.
+ unsafe fn sysctl_cpu_id_asm_syscall(name: &[&[u8]]) -> Result<AA64Reg, c_int> {
+ // https://github.com/golang/go/blob/4badad8d477ffd7a6b762c35bc69aed82faface7/src/syscall/asm_netbsd_arm64.s
+ #[inline]
+ unsafe fn sysctl(
+ name: *const c_int,
+ name_len: c_uint,
+ old_p: *mut c_void,
+ old_len_p: *mut c_size_t,
+ new_p: *const c_void,
+ new_len: c_size_t,
+ ) -> Result<c_int, c_int> {
+ #[allow(clippy::cast_possible_truncation)]
+ // SAFETY: the caller must uphold the safety contract.
+ unsafe {
+ let mut n = sys::SYS___sysctl as u64;
+ let r: i64;
+ asm!(
+ "svc 0",
+ "b.cc 2f",
+ "mov x17, x0",
+ "mov x0, #-1",
+ "2:",
+ inout("x17") n,
+ inout("x0") ptr_reg!(name) => r,
+ inout("x1") name_len as u64 => _,
+ in("x2") ptr_reg!(old_p),
+ in("x3") ptr_reg!(old_len_p),
+ in("x4") ptr_reg!(new_p),
+ in("x5") new_len as u64,
+ options(nostack),
+ );
+ if r as c_int == -1 {
+ Err(n as c_int)
+ } else {
+ Ok(r as c_int)
+ }
+ }
+ }
+
+ // https://github.com/golang/sys/blob/4badad8d477ffd7a6b762c35bc69aed82faface7/cpu/cpu_netbsd_arm64.go.
+ use std::{vec, vec::Vec};
+ fn sysctl_nodes(mib: &mut Vec<i32>) -> Result<Vec<sys::sysctlnode>, i32> {
+ mib.push(sys::CTL_QUERY);
+ let mut q_node = sys::sysctlnode {
+ sysctl_flags: sys::SYSCTL_VERS_1,
+ ..unsafe { mem::zeroed() }
+ };
+ let qp = (&mut q_node as *mut sys::sysctlnode).cast::<ffi::c_void>();
+ let sz = mem::size_of::<sys::sysctlnode>();
+ let mut olen = 0;
+ #[allow(clippy::cast_possible_truncation)]
+ unsafe {
+ sysctl(mib.as_ptr(), mib.len() as c_uint, ptr::null_mut(), &mut olen, qp, sz)?;
+ }
+
+ let mut nodes = Vec::<sys::sysctlnode>::with_capacity(olen / sz);
+ let np = nodes.as_mut_ptr().cast::<ffi::c_void>();
+ #[allow(clippy::cast_possible_truncation)]
+ unsafe {
+ sysctl(mib.as_ptr(), mib.len() as c_uint, np, &mut olen, qp, sz)?;
+ nodes.set_len(olen / sz);
+ }
+
+ mib.pop(); // pop CTL_QUERY
+ Ok(nodes)
+ }
+ fn name_to_mib(parts: &[&[u8]]) -> Result<Vec<i32>, i32> {
+ let mut mib = vec![];
+ for (part_no, &part) in parts.iter().enumerate() {
+ let nodes = sysctl_nodes(&mut mib)?;
+ for node in nodes {
+ let mut n = vec![];
+ for b in node.sysctl_name {
+ if b != 0 {
+ n.push(b);
+ }
+ }
+ if n == part {
+ mib.push(node.sysctl_num);
+ break;
+ }
+ }
+ if mib.len() != part_no + 1 {
+ return Err(0);
+ }
+ }
+
+ Ok(mib)
+ }
+
+ const OUT_LEN: ffi::c_size_t =
+ core::mem::size_of::<ffi::aarch64_sysctl_cpu_id>() as ffi::c_size_t;
+
+ let mib = name_to_mib(name)?;
+
+ let mut buf: ffi::aarch64_sysctl_cpu_id = unsafe { core::mem::zeroed() };
+ let mut out_len = OUT_LEN;
+ #[allow(clippy::cast_possible_truncation)]
+ unsafe {
+ sysctl(
+ mib.as_ptr(),
+ mib.len() as c_uint,
+ (&mut buf as *mut ffi::aarch64_sysctl_cpu_id).cast::<ffi::c_void>(),
+ &mut out_len,
+ ptr::null_mut(),
+ 0,
+ )?;
+ }
+ Ok(AA64Reg {
+ aa64isar0: buf.aa64isar0,
+ #[cfg(test)]
+ aa64isar1: buf.aa64isar1,
+ #[cfg(test)]
+ aa64mmfr2: buf.aa64mmfr2,
+ })
+ }
+
+ unsafe {
+ assert_eq!(
+ imp::sysctl_cpu_id(b"machdep.cpu0.cpu_id\0").unwrap(),
+ sysctl_cpu_id_asm_syscall(&[b"machdep", b"cpu0", b"cpu_id"]).unwrap()
+ );
+ }
+ }
+
// Static assertions for FFI bindings.
// This checks that FFI bindings defined in this crate, FFI bindings defined
// in libc, and FFI bindings generated for the platform's latest header file
@@ -285,6 +547,56 @@ mod tests {
// without actually running tests on these platforms.
// See also tools/codegen/src/ffi.rs.
// TODO(codegen): auto-generate this test
+ #[cfg(target_os = "netbsd")]
+ #[allow(
+ clippy::cast_possible_wrap,
+ clippy::cast_sign_loss,
+ clippy::no_effect_underscore_binding,
+ clippy::used_underscore_binding
+ )]
+ const _: fn() = || {
+ use core::mem::size_of;
+ use imp::ffi;
+ use test_helper::{libc, sys};
+ let mut _sysctlbyname: unsafe extern "C" fn(
+ *const ffi::c_char,
+ *mut ffi::c_void,
+ *mut ffi::c_size_t,
+ *const ffi::c_void,
+ ffi::c_size_t,
+ ) -> ffi::c_int = ffi::sysctlbyname;
+ _sysctlbyname = libc::sysctlbyname;
+ _sysctlbyname = sys::sysctlbyname;
+ // libc doesn't have this
+ // static_assert!(
+ // size_of::<ffi::aarch64_sysctl_cpu_id>() == size_of::<libc::aarch64_sysctl_cpu_id>()
+ // );
+ static_assert!(
+ size_of::<ffi::aarch64_sysctl_cpu_id>() == size_of::<sys::aarch64_sysctl_cpu_id>()
+ );
+ let ffi: ffi::aarch64_sysctl_cpu_id = unsafe { core::mem::zeroed() };
+ let _ = sys::aarch64_sysctl_cpu_id {
+ ac_midr: ffi.midr,
+ ac_revidr: ffi.revidr,
+ ac_mpidr: ffi.mpidr,
+ ac_aa64dfr0: ffi.aa64dfr0,
+ ac_aa64dfr1: ffi.aa64dfr1,
+ ac_aa64isar0: ffi.aa64isar0,
+ ac_aa64isar1: ffi.aa64isar1,
+ ac_aa64mmfr0: ffi.aa64mmfr0,
+ ac_aa64mmfr1: ffi.aa64mmfr1,
+ ac_aa64mmfr2: ffi.aa64mmfr2,
+ ac_aa64pfr0: ffi.aa64pfr0,
+ ac_aa64pfr1: ffi.aa64pfr1,
+ ac_aa64zfr0: ffi.aa64zfr0,
+ ac_mvfr0: ffi.mvfr0,
+ ac_mvfr1: ffi.mvfr1,
+ ac_mvfr2: ffi.mvfr2,
+ ac_pad: ffi.pad,
+ ac_clidr: ffi.clidr,
+ ac_ctr: ffi.ctr,
+ };
+ };
#[cfg(target_os = "openbsd")]
#[allow(
clippy::cast_possible_wrap,
diff --git a/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_fuchsia.rs b/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_fuchsia.rs
index 69aa74ebd..978418c5b 100644
--- a/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_fuchsia.rs
+++ b/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_fuchsia.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
// 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.
diff --git a/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_macos.rs b/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_macos.rs
index 0bf0e6b0f..d6bf9d002 100644
--- a/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_macos.rs
+++ b/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_macos.rs
@@ -1,10 +1,12 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
// Run-time feature detection on aarch64 macOS by using sysctl.
//
// This module is currently only enabled on tests because aarch64 macOS always supports FEAT_LSE and FEAT_LSE2.
-// https://github.com/llvm/llvm-project/blob/llvmorg-16.0.0/llvm/include/llvm/TargetParser/AArch64TargetParser.h#L458
+// https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/include/llvm/TargetParser/AArch64TargetParser.h#L494
//
// If macOS supporting Armv9.4-a becomes popular in the future, this module will
-// be used to support outline atomics for FEAT_LSE128/FEAT_LRCPC3.
+// be used to support outline-atomics for FEAT_LSE128/FEAT_LRCPC3.
//
// Refs: https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
//
@@ -77,14 +79,14 @@ fn _detect(info: &mut CpuInfo) {
} {
info.set(CpuInfo::HAS_LSE);
}
- // we currently only use FEAT_LSE in outline-atomics.
+ // SAFETY: we passed a valid C string.
+ if unsafe { sysctlbyname32(b"hw.optional.arm.FEAT_LSE2\0").unwrap_or(0) != 0 } {
+ info.set(CpuInfo::HAS_LSE2);
+ }
+ // we currently only use FEAT_LSE and FEAT_LSE2 in outline-atomics.
#[cfg(test)]
{
// SAFETY: we passed a valid C string.
- if unsafe { sysctlbyname32(b"hw.optional.arm.FEAT_LSE2\0").unwrap_or(0) != 0 } {
- info.set(CpuInfo::HAS_LSE2);
- }
- // SAFETY: we passed a valid C string.
if unsafe { sysctlbyname32(b"hw.optional.arm.FEAT_LSE128\0").unwrap_or(0) != 0 } {
info.set(CpuInfo::HAS_LSE128);
}
diff --git a/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_windows.rs b/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_windows.rs
index 6922ce4a7..e19c4b8b7 100644
--- a/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_windows.rs
+++ b/vendor/portable-atomic/src/imp/atomic128/detect/aarch64_windows.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
// Run-time feature detection on aarch64 Windows by using IsProcessorFeaturePresent.
//
// As of nightly-2023-01-23, is_aarch64_feature_detected doesn't support run-time detection of FEAT_LSE on Windows.
diff --git a/vendor/portable-atomic/src/imp/atomic128/detect/auxv.rs b/vendor/portable-atomic/src/imp/atomic128/detect/auxv.rs
index a80350e47..a4455911b 100644
--- a/vendor/portable-atomic/src/imp/atomic128/detect/auxv.rs
+++ b/vendor/portable-atomic/src/imp/atomic128/detect/auxv.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
// Run-time feature detection on aarch64/powerpc64 Linux/Android/FreeBSD by parsing ELF auxiliary vectors.
//
// # Linux/Android
@@ -24,11 +26,13 @@
//
// - On musl with static linking. See the above for more.
// Also, in this case, dlsym(getauxval) always returns null.
-// - On uClibc-ng (*-linux-uclibc*, *-l4re-uclibc*), [uClibc-ng 1.0.43 (released in 2023-04-05) added getauxval](https://repo.or.cz/uclibc-ng.git/commitdiff/d869bb1600942c01a77539128f9ba5b5b55ad647).
+// - On uClibc-ng (*-linux-uclibc*, *-l4re-uclibc*), [uClibc-ng 1.0.43 (released in 2023-04-05) added getauxval](https://github.com/wbx-github/uclibc-ng/commit/d869bb1600942c01a77539128f9ba5b5b55ad647).
// - On Picolibc, [Picolibc 1.4.6 added getauxval stub](https://github.com/picolibc/picolibc#picolibc-version-146).
//
// See also https://github.com/rust-lang/stdarch/pull/1375
//
+// See tests::test_linux_like and aarch64_aa64reg.rs for (test-only) alternative implementations.
+//
// # FreeBSD
//
// As of nightly-2023-01-23, is_aarch64_feature_detected always uses mrs on
@@ -47,6 +51,8 @@
// https://www.freebsd.org/security/unsupported
// See also https://github.com/rust-lang/stdarch/pull/611#issuecomment-445464613
//
+// See tests::test_freebsd and aarch64_aa64reg.rs for (test-only) alternative implementations.
+//
// # PowerPC64
//
// On PowerPC64, outline-atomics is currently disabled by default mainly for
@@ -69,7 +75,7 @@ mod os {
// https://man7.org/linux/man-pages/man3/getauxval.3.html
// https://github.com/bminor/glibc/blob/801af9fafd4689337ebf27260aa115335a0cb2bc/misc/sys/auxv.h
// https://github.com/bminor/musl/blob/7d756e1c04de6eb3f2b3d3e1141a218bb329fcfb/include/sys/auxv.h
- // https://repo.or.cz/uclibc-ng.git/blob/9d549d7bc6a1b78498ee8d1f39f6a324fdfc9e5d:/include/sys/auxv.h
+ // https://github.com/wbx-github/uclibc-ng/blob/cdb07d2cd52af39feb425e6d36c02b30916b9f0a/include/sys/auxv.h
// https://github.com/aosp-mirror/platform_bionic/blob/d3ebc2f7c49a9893b114124d4a6b315f3a328764/libc/include/sys/auxv.h
// https://github.com/picolibc/picolibc/blob/7a8a58aeaa5946cb662577a518051091b691af3a/newlib/libc/picolib/getauxval.c
// https://github.com/rust-lang/libc/blob/0.2.139/src/unix/linux_like/linux/gnu/mod.rs#L1201
@@ -181,7 +187,6 @@ mod arch {
// https://github.com/freebsd/freebsd-src/blob/release/13.0.0/sys/arm64/include/elf.h
// https://github.com/freebsd/freebsd-src/blob/release/12.2.0/sys/arm64/include/elf.h
pub(super) const HWCAP_ATOMICS: ffi::c_ulong = 1 << 8;
- #[cfg(test)]
pub(super) const HWCAP_USCAT: ffi::c_ulong = 1 << 25;
#[cold]
@@ -191,12 +196,8 @@ mod arch {
if hwcap & HWCAP_ATOMICS != 0 {
info.set(CpuInfo::HAS_LSE);
}
- // we currently only use FEAT_LSE in outline-atomics.
- #[cfg(test)]
- {
- if hwcap & HWCAP_USCAT != 0 {
- info.set(CpuInfo::HAS_LSE2);
- }
+ if hwcap & HWCAP_USCAT != 0 {
+ info.set(CpuInfo::HAS_LSE2);
}
}
}
@@ -235,6 +236,120 @@ mod arch {
mod tests {
use super::*;
+ #[cfg(any(target_os = "linux", target_os = "android"))]
+ #[cfg(target_pointer_width = "64")]
+ #[test]
+ fn test_linux_like() {
+ use c_types::*;
+ use core::{arch::asm, mem};
+ use std::vec;
+ use test_helper::{libc, sys};
+
+ // Linux kernel 6.4 has added a way to read auxv without depending on either libc or mrs trap.
+ // https://github.com/torvalds/linux/commit/ddc65971bb677aa9f6a4c21f76d3133e106f88eb
+ //
+ // This is currently used only for testing.
+ fn getauxval_pr_get_auxv(type_: ffi::c_ulong) -> Result<ffi::c_ulong, c_int> {
+ #[cfg(target_arch = "aarch64")]
+ unsafe fn prctl_get_auxv(out: *mut c_void, len: usize) -> Result<usize, c_int> {
+ let r: i64;
+ unsafe {
+ asm!(
+ "svc 0",
+ in("x8") sys::__NR_prctl as u64,
+ inout("x0") sys::PR_GET_AUXV as u64 => r,
+ in("x1") ptr_reg!(out),
+ in("x2") len as u64,
+ // arg4 and arg5 must be zero.
+ in("x3") 0_u64,
+ in("x4") 0_u64,
+ options(nostack, preserves_flags)
+ );
+ }
+ #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
+ if (r as c_int) < 0 {
+ Err(r as c_int)
+ } else {
+ Ok(r as usize)
+ }
+ }
+ #[cfg(target_arch = "powerpc64")]
+ unsafe fn prctl_get_auxv(out: *mut c_void, len: usize) -> Result<usize, c_int> {
+ let r: i64;
+ unsafe {
+ asm!(
+ "sc",
+ "bns+ 2f",
+ "neg %r3, %r3",
+ "2:",
+ inout("r0") sys::__NR_prctl as u64 => _,
+ inout("r3") sys::PR_GET_AUXV as u64 => r,
+ inout("r4") ptr_reg!(out) => _,
+ inout("r5") len as u64 => _,
+ // arg4 and arg5 must be zero.
+ inout("r6") 0_u64 => _,
+ inout("r7") 0_u64 => _,
+ out("r8") _,
+ out("r9") _,
+ out("r10") _,
+ out("r11") _,
+ out("r12") _,
+ out("cr0") _,
+ options(nostack, preserves_flags)
+ );
+ }
+ #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
+ if (r as c_int) < 0 {
+ Err(r as c_int)
+ } else {
+ Ok(r as usize)
+ }
+ }
+
+ let mut auxv = vec![unsafe { mem::zeroed::<sys::Elf64_auxv_t>() }; 38];
+
+ let old_len = auxv.len() * mem::size_of::<sys::Elf64_auxv_t>();
+
+ // SAFETY:
+ // - `out_len` does not exceed the size of `auxv`.
+ let _len = unsafe { prctl_get_auxv(auxv.as_mut_ptr().cast::<c_void>(), old_len)? };
+
+ for aux in &auxv {
+ if aux.a_type == type_ {
+ // SAFETY: aux.a_un is #[repr(C)] union and all fields have
+ // the same size and can be safely transmuted to integers.
+ return Ok(unsafe { aux.a_un.a_val });
+ }
+ }
+ Err(0)
+ }
+
+ unsafe {
+ let mut u = mem::zeroed();
+ assert_eq!(libc::uname(&mut u), 0);
+ let release = std::ffi::CStr::from_ptr(u.release.as_ptr());
+ let release = core::str::from_utf8(release.to_bytes()).unwrap();
+ let mut digits = release.split('.');
+ let major = digits.next().unwrap().parse::<u32>().unwrap();
+ let minor = digits.next().unwrap().parse::<u32>().unwrap();
+ if (major, minor) < (6, 4) {
+ std::eprintln!("kernel version: {major}.{minor} (no pr_get_auxv)");
+ assert_eq!(getauxval_pr_get_auxv(ffi::AT_HWCAP).unwrap_err(), -22);
+ assert_eq!(getauxval_pr_get_auxv(ffi::AT_HWCAP2).unwrap_err(), -22);
+ } else {
+ std::eprintln!("kernel version: {major}.{minor} (has pr_get_auxv)");
+ assert_eq!(
+ os::getauxval(ffi::AT_HWCAP),
+ getauxval_pr_get_auxv(ffi::AT_HWCAP).unwrap()
+ );
+ assert_eq!(
+ os::getauxval(ffi::AT_HWCAP2),
+ getauxval_pr_get_auxv(ffi::AT_HWCAP2).unwrap()
+ );
+ }
+ }
+ }
+
#[allow(clippy::cast_sign_loss)]
#[cfg(all(target_arch = "aarch64", target_os = "android"))]
#[test]
@@ -256,6 +371,262 @@ mod tests {
}
}
+ #[allow(clippy::cast_possible_wrap)]
+ #[cfg(target_os = "freebsd")]
+ #[test]
+ fn test_freebsd() {
+ use c_types::*;
+ use core::{arch::asm, mem, ptr};
+ use test_helper::sys;
+
+ // This is almost equivalent to what elf_aux_info does.
+ // https://man.freebsd.org/elf_aux_info(3)
+ // On FreeBSD, [aarch64 support is available on FreeBSD 11.0+](https://www.freebsd.org/releases/11.0R/relnotes/#hardware-arm),
+ // but elf_aux_info is available on FreeBSD 12.0+ and 11.4+:
+ // https://github.com/freebsd/freebsd-src/commit/0b08ae2120cdd08c20a2b806e2fcef4d0a36c470
+ // https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/sys/auxv.h
+ // so use sysctl instead of elf_aux_info.
+ // Note that FreeBSD 11 (11.4) was EoL on 2021-09-30, and FreeBSD 11.3 was EoL on 2020-09-30:
+ // https://www.freebsd.org/security/unsupported
+ //
+ // std_detect uses this way, but it appears to be somewhat incorrect
+ // (the type of arg4 of sysctl, auxv is smaller than AT_COUNT, etc.).
+ // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/freebsd/auxvec.rs#L52
+ //
+ // This is currently used only for testing.
+ // If you want us to use this implementation for compatibility with the older FreeBSD
+ // version that came to EoL a few years ago, please open an issue.
+ fn getauxval_sysctl_libc(type_: ffi::c_int) -> ffi::c_ulong {
+ let mut auxv: [sys::Elf64_Auxinfo; sys::AT_COUNT as usize] = unsafe { mem::zeroed() };
+
+ let mut len = core::mem::size_of_val(&auxv) as c_size_t;
+
+ // SAFETY: calling getpid is safe.
+ let pid = unsafe { sys::getpid() };
+ let mib = [
+ sys::CTL_KERN as c_int,
+ sys::KERN_PROC as c_int,
+ sys::KERN_PROC_AUXV as c_int,
+ pid,
+ ];
+
+ #[allow(clippy::cast_possible_truncation)]
+ // SAFETY:
+ // - `mib.len()` does not exceed the size of `mib`.
+ // - `len` does not exceed the size of `auxv`.
+ // - `sysctl` is thread-safe.
+ let res = unsafe {
+ sys::sysctl(
+ mib.as_ptr(),
+ mib.len() as c_uint,
+ auxv.as_mut_ptr().cast::<c_void>(),
+ &mut len,
+ ptr::null_mut(),
+ 0,
+ )
+ };
+
+ if res != -1 {
+ for aux in &auxv {
+ if aux.a_type == type_ as c_long {
+ // SAFETY: aux.a_un is #[repr(C)] union and all fields have
+ // the same size and can be safely transmuted to integers.
+ return unsafe { aux.a_un.a_val as c_ulong };
+ }
+ }
+ }
+ 0
+ }
+ // Similar to the above, but call syscall using asm instead of libc.
+ // Note that FreeBSD does not guarantee the stability of raw syscall as
+ // much as Linux does (It may actually be stable enough, though:
+ // https://lists.llvm.org/pipermail/llvm-dev/2019-June/133393.html,
+ // https://github.com/ziglang/zig/issues/16590).
+ //
+ // This is currently used only for testing.
+ fn getauxval_sysctl_asm_syscall(type_: ffi::c_int) -> Result<ffi::c_ulong, c_int> {
+ #[allow(non_camel_case_types)]
+ type pid_t = c_int;
+
+ // https://github.com/freebsd/freebsd-src/blob/9888a79adad22ba06b5aff17d05abac0029c537a/lib/libc/aarch64/SYS.h
+ // https://github.com/golang/go/blob/4badad8d477ffd7a6b762c35bc69aed82faface7/src/syscall/asm_freebsd_arm64.s
+ #[cfg(target_arch = "aarch64")]
+ #[inline]
+ fn getpid() -> pid_t {
+ #[allow(clippy::cast_possible_truncation)]
+ // SAFETY: calling getpid is safe.
+ unsafe {
+ let n = sys::SYS_getpid;
+ let r: i64;
+ asm!(
+ "svc 0",
+ in("x8") n as u64,
+ out("x0") r,
+ options(nostack, readonly),
+ );
+ r as pid_t
+ }
+ }
+ #[cfg(target_arch = "aarch64")]
+ #[inline]
+ unsafe fn sysctl(
+ name: *const c_int,
+ name_len: c_uint,
+ old_p: *mut c_void,
+ old_len_p: *mut c_size_t,
+ new_p: *const c_void,
+ new_len: c_size_t,
+ ) -> Result<c_int, c_int> {
+ #[allow(clippy::cast_possible_truncation)]
+ // SAFETY: the caller must uphold the safety contract.
+ unsafe {
+ let mut n = sys::SYS___sysctl as u64;
+ let r: i64;
+ asm!(
+ "svc 0",
+ "b.cc 2f",
+ "mov x8, x0",
+ "mov x0, #-1",
+ "2:",
+ inout("x8") n,
+ inout("x0") ptr_reg!(name) => r,
+ inout("x1") name_len as u64 => _,
+ in("x2") ptr_reg!(old_p),
+ in("x3") ptr_reg!(old_len_p),
+ in("x4") ptr_reg!(new_p),
+ in("x5") new_len as u64,
+ options(nostack),
+ );
+ if r as c_int == -1 {
+ Err(n as c_int)
+ } else {
+ Ok(r as c_int)
+ }
+ }
+ }
+
+ // https://github.com/freebsd/freebsd-src/blob/9888a79adad22ba06b5aff17d05abac0029c537a/lib/libc/powerpc64/SYS.h
+ #[cfg(target_arch = "powerpc64")]
+ #[inline]
+ fn getpid() -> pid_t {
+ #[allow(clippy::cast_possible_truncation)]
+ // SAFETY: calling getpid is safe.
+ unsafe {
+ let n = sys::SYS_getpid;
+ let r: i64;
+ asm!(
+ "sc",
+ inout("r0") n as u64 => _,
+ out("r3") r,
+ out("r4") _,
+ out("r5") _,
+ out("r6") _,
+ out("r7") _,
+ out("r8") _,
+ out("r9") _,
+ out("r10") _,
+ out("r11") _,
+ out("r12") _,
+ out("cr0") _,
+ options(nostack, preserves_flags, readonly),
+ );
+ r as pid_t
+ }
+ }
+ #[cfg(target_arch = "powerpc64")]
+ #[inline]
+ unsafe fn sysctl(
+ name: *const c_int,
+ name_len: c_uint,
+ old_p: *mut c_void,
+ old_len_p: *mut c_size_t,
+ new_p: *const c_void,
+ new_len: c_size_t,
+ ) -> Result<c_int, c_int> {
+ #[allow(clippy::cast_possible_truncation)]
+ // SAFETY: the caller must uphold the safety contract.
+ unsafe {
+ let mut n = sys::SYS___sysctl as u64;
+ let r: i64;
+ asm!(
+ "sc",
+ "bns+ 2f",
+ "mr %r0, %r3",
+ "li %r3, -1",
+ "2:",
+ inout("r0") n,
+ inout("r3") ptr_reg!(name) => r,
+ inout("r4") name_len as u64 => _,
+ inout("r5") ptr_reg!(old_p) => _,
+ inout("r6") ptr_reg!(old_len_p) => _,
+ inout("r7") ptr_reg!(new_p) => _,
+ inout("r8") new_len as u64 => _,
+ out("r9") _,
+ out("r10") _,
+ out("r11") _,
+ out("r12") _,
+ out("cr0") _,
+ options(nostack, preserves_flags)
+ );
+ if r as c_int == -1 {
+ Err(n as c_int)
+ } else {
+ Ok(r as c_int)
+ }
+ }
+ }
+
+ let mut auxv: [sys::Elf64_Auxinfo; sys::AT_COUNT as usize] = unsafe { mem::zeroed() };
+
+ let mut len = core::mem::size_of_val(&auxv) as c_size_t;
+
+ let pid = getpid();
+ let mib = [
+ sys::CTL_KERN as c_int,
+ sys::KERN_PROC as c_int,
+ sys::KERN_PROC_AUXV as c_int,
+ pid,
+ ];
+
+ #[allow(clippy::cast_possible_truncation)]
+ // SAFETY:
+ // - `mib.len()` does not exceed the size of `mib`.
+ // - `len` does not exceed the size of `auxv`.
+ // - `sysctl` is thread-safe.
+ unsafe {
+ sysctl(
+ mib.as_ptr(),
+ mib.len() as c_uint,
+ auxv.as_mut_ptr().cast::<c_void>(),
+ &mut len,
+ ptr::null_mut(),
+ 0,
+ )?;
+ }
+
+ for aux in &auxv {
+ if aux.a_type == type_ as c_long {
+ // SAFETY: aux.a_un is #[repr(C)] union and all fields have
+ // the same size and can be safely transmuted to integers.
+ return Ok(unsafe { aux.a_un.a_val as c_ulong });
+ }
+ }
+ Err(0)
+ }
+
+ assert_eq!(os::getauxval(ffi::AT_HWCAP), getauxval_sysctl_libc(ffi::AT_HWCAP));
+ assert_eq!(os::getauxval(ffi::AT_HWCAP2), getauxval_sysctl_libc(ffi::AT_HWCAP2));
+ assert_eq!(
+ os::getauxval(ffi::AT_HWCAP),
+ getauxval_sysctl_asm_syscall(ffi::AT_HWCAP).unwrap()
+ );
+ assert_eq!(
+ os::getauxval(ffi::AT_HWCAP2),
+ // AT_HWCAP2 is only available on FreeBSD 13+, at least for aarch64.
+ getauxval_sysctl_asm_syscall(ffi::AT_HWCAP2).unwrap_or(0)
+ );
+ }
+
// Static assertions for FFI bindings.
// This checks that FFI bindings defined in this crate, FFI bindings defined
// in libc, and FFI bindings generated for the platform's latest header file
@@ -273,14 +644,15 @@ mod tests {
)]
const _: fn() = || {
use test_helper::{libc, sys};
+ #[cfg(not(target_os = "freebsd"))]
+ type AtType = ffi::c_ulong;
+ #[cfg(target_os = "freebsd")]
+ type AtType = ffi::c_int;
#[cfg(any(target_os = "linux", target_os = "android"))]
{
let mut _getauxval: unsafe extern "C" fn(ffi::c_ulong) -> ffi::c_ulong = ffi::getauxval;
_getauxval = libc::getauxval;
- #[cfg(any(target_env = "musl", target_os = "android"))] // TODO(codegen)
- {
- _getauxval = sys::getauxval;
- }
+ _getauxval = sys::getauxval;
}
#[cfg(all(target_arch = "aarch64", target_os = "android"))]
{
@@ -291,7 +663,7 @@ mod tests {
___system_property_get = libc::__system_property_get;
___system_property_get = sys::__system_property_get;
static_assert!(ffi::PROP_VALUE_MAX == libc::PROP_VALUE_MAX);
- static_assert!(ffi::PROP_VALUE_MAX == sys::PROP_VALUE_MAX as _);
+ static_assert!(ffi::PROP_VALUE_MAX == sys::PROP_VALUE_MAX as ffi::c_int);
}
#[cfg(target_os = "freebsd")]
{
@@ -305,10 +677,10 @@ mod tests {
}
#[cfg(not(target_os = "freebsd"))] // libc doesn't have this on FreeBSD
static_assert!(ffi::AT_HWCAP == libc::AT_HWCAP);
- static_assert!(ffi::AT_HWCAP == sys::AT_HWCAP as _);
+ static_assert!(ffi::AT_HWCAP == sys::AT_HWCAP as AtType);
#[cfg(not(target_os = "freebsd"))] // libc doesn't have this on FreeBSD
static_assert!(ffi::AT_HWCAP2 == libc::AT_HWCAP2);
- static_assert!(ffi::AT_HWCAP2 == sys::AT_HWCAP2 as _);
+ static_assert!(ffi::AT_HWCAP2 == sys::AT_HWCAP2 as AtType);
#[cfg(target_arch = "aarch64")]
{
// static_assert!(arch::HWCAP_ATOMICS == libc::HWCAP_ATOMICS); // libc doesn't have this
diff --git a/vendor/portable-atomic/src/imp/atomic128/detect/common.rs b/vendor/portable-atomic/src/imp/atomic128/detect/common.rs
index 504718718..b87caa351 100644
--- a/vendor/portable-atomic/src/imp/atomic128/detect/common.rs
+++ b/vendor/portable-atomic/src/imp/atomic128/detect/common.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
#[derive(Clone, Copy)]
pub(crate) struct CpuInfo(u32);
@@ -48,8 +50,7 @@ impl CpuInfo {
/// Whether FEAT_LSE is available
const HAS_LSE: u32 = 1;
/// Whether FEAT_LSE2 is available
- // This is currently only used in tests.
- #[cfg(test)]
+ #[cfg_attr(not(test), allow(dead_code))]
const HAS_LSE2: u32 = 2;
/// Whether FEAT_LSE128 is available
// This is currently only used in tests.
@@ -65,6 +66,22 @@ impl CpuInfo {
pub(crate) fn has_lse(self) -> bool {
self.test(CpuInfo::HAS_LSE)
}
+ #[cfg_attr(not(test), allow(dead_code))]
+ #[cfg(any(test, not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2"))))]
+ #[inline]
+ pub(crate) fn has_lse2(self) -> bool {
+ self.test(CpuInfo::HAS_LSE2)
+ }
+ #[cfg(test)]
+ #[inline]
+ pub(crate) fn has_lse128(self) -> bool {
+ self.test(CpuInfo::HAS_LSE128)
+ }
+ #[cfg(test)]
+ #[inline]
+ pub(crate) fn has_rcpc3(self) -> bool {
+ self.test(CpuInfo::HAS_RCPC3)
+ }
}
#[cfg(target_arch = "x86_64")]
@@ -128,12 +145,17 @@ mod c_types {
pub(crate) type c_ulong = u64;
#[cfg(not(target_pointer_width = "64"))]
pub(crate) type c_ulong = u32;
- // c_size_t is usize
+ // c_size_t is currently always usize
// https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/ffi/mod.rs#L88
pub(crate) type c_size_t = usize;
- // c_char is u8 on most non-Apple/non-Windows ARM/PowerPC/RISC-V targets
- // (Linux/Android/FreeBSD/NetBSD/OpenBSD/VxWorks/Fuchsia/QNX Neutrino/Horizon)
+ // c_char is u8 by default on most non-Apple/non-Windows ARM/PowerPC/RISC-V/s390x/Hexagon targets
+ // (Linux/Android/FreeBSD/NetBSD/OpenBSD/VxWorks/Fuchsia/QNX Neutrino/Horizon/AIX/z/OS)
// https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/ffi/mod.rs#L104
+ // https://github.com/llvm/llvm-project/blob/9734b2256d89cb4c61a4dbf4a3c3f3f942fe9b8c/lldb/source/Utility/ArchSpec.cpp#L712
+ // RISC-V https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/HEAD/riscv-cc.adoc#cc-type-representations
+ // Hexagon https://lists.llvm.org/pipermail/llvm-dev/attachments/20190916/21516a52/attachment-0001.pdf
+ // AIX https://www.ibm.com/docs/en/xl-c-aix/13.1.2?topic=descriptions-qchars
+ // z/OS https://www.ibm.com/docs/en/zos/2.5.0?topic=specifiers-character-types
// (macOS is currently the only Apple target that uses this module, and Windows currently doesn't use this module)
#[cfg(not(target_os = "macos"))]
pub(crate) type c_char = u8;
@@ -328,7 +350,7 @@ mod tests_common {
assert!(!proc_cpuinfo.lse);
}
}
- if detect().test(CpuInfo::HAS_LSE2) {
+ if detect().has_lse2() {
assert!(detect().test(CpuInfo::HAS_LSE));
assert!(detect().test(CpuInfo::HAS_LSE2));
if let Ok(test_helper::cpuinfo::ProcCpuinfo { lse2: Some(lse2), .. }) = proc_cpuinfo {
@@ -340,14 +362,14 @@ mod tests_common {
assert!(!lse2);
}
}
- if detect().test(CpuInfo::HAS_LSE128) {
+ if detect().has_lse128() {
assert!(detect().test(CpuInfo::HAS_LSE));
assert!(detect().test(CpuInfo::HAS_LSE2));
assert!(detect().test(CpuInfo::HAS_LSE128));
} else {
assert!(!detect().test(CpuInfo::HAS_LSE128));
}
- if detect().test(CpuInfo::HAS_RCPC3) {
+ if detect().has_rcpc3() {
assert!(detect().test(CpuInfo::HAS_RCPC3));
} else {
assert!(!detect().test(CpuInfo::HAS_RCPC3));
diff --git a/vendor/portable-atomic/src/imp/atomic128/detect/x86_64.rs b/vendor/portable-atomic/src/imp/atomic128/detect/x86_64.rs
index d162d6599..80eefed53 100644
--- a/vendor/portable-atomic/src/imp/atomic128/detect/x86_64.rs
+++ b/vendor/portable-atomic/src/imp/atomic128/detect/x86_64.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
// Adapted from https://github.com/rust-lang/stdarch.
#![cfg_attr(any(not(target_feature = "sse"), portable_atomic_sanitize_thread), allow(dead_code))]
@@ -5,13 +7,13 @@
// Miri doesn't support inline assembly used in __cpuid: https://github.com/rust-lang/miri/issues/932
// SGX doesn't support CPUID: https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/core_arch/src/x86/cpuid.rs#L102-L105
#[cfg(any(target_env = "sgx", miri))]
-compile_error!("internal error: this module is not supported on this target");
+compile_error!("internal error: this module is not supported on this environment");
include!("common.rs");
#[cfg(not(portable_atomic_no_asm))]
use core::arch::asm;
-use core::arch::x86_64::CpuidResult;
+use core::arch::x86_64::{CpuidResult, _xgetbv};
// Workaround for https://github.com/rust-lang/rust/issues/101346
// It is not clear if our use cases are affected, but we implement this just in case.
@@ -57,38 +59,31 @@ unsafe fn _vendor_id() -> [u8; 12] {
#[cold]
fn _detect(info: &mut CpuInfo) {
- // Miri doesn't support inline assembly used in __cpuid
- // SGX doesn't support CPUID: https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/core_arch/src/x86/cpuid.rs#L102-L105
- #[cfg(not(any(target_env = "sgx", miri)))]
- {
- use core::arch::x86_64::_xgetbv;
-
- // SAFETY: Calling `_vendor_id`` is safe because the CPU has `cpuid` support.
- let vendor_id = unsafe { _vendor_id() };
+ // SAFETY: Calling `_vendor_id`` is safe because the CPU has `cpuid` support.
+ let vendor_id = unsafe { _vendor_id() };
- // SAFETY: Calling `__cpuid`` is safe because the CPU has `cpuid` support.
- let proc_info_ecx = unsafe { __cpuid(0x0000_0001_u32).ecx };
+ // SAFETY: Calling `__cpuid`` is safe because the CPU has `cpuid` support.
+ let proc_info_ecx = unsafe { __cpuid(0x0000_0001_u32).ecx };
- // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/x86.rs#L111
- if test(proc_info_ecx, 13) {
- info.set(CpuInfo::HAS_CMPXCHG16B);
- }
+ // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/x86.rs#L111
+ if test(proc_info_ecx, 13) {
+ info.set(CpuInfo::HAS_CMPXCHG16B);
+ }
- // VMOVDQA is atomic on Intel and AMD CPUs with AVX.
- // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688 for details.
- if vendor_id == VENDOR_ID_INTEL || vendor_id == VENDOR_ID_AMD {
- // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/x86.rs#L131-L224
- let cpu_xsave = test(proc_info_ecx, 26);
- if cpu_xsave {
- let cpu_osxsave = test(proc_info_ecx, 27);
- if cpu_osxsave {
- // SAFETY: Calling `_xgetbv`` is safe because the CPU has `xsave` support
- // and OS has set `osxsave`.
- let xcr0 = unsafe { _xgetbv(0) };
- let os_avx_support = xcr0 & 6 == 6;
- if os_avx_support && test(proc_info_ecx, 28) {
- info.set(CpuInfo::HAS_VMOVDQA_ATOMIC);
- }
+ // VMOVDQA is atomic on Intel and AMD CPUs with AVX.
+ // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688 for details.
+ if vendor_id == VENDOR_ID_INTEL || vendor_id == VENDOR_ID_AMD {
+ // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/x86.rs#L131-L224
+ let cpu_xsave = test(proc_info_ecx, 26);
+ if cpu_xsave {
+ let cpu_osxsave = test(proc_info_ecx, 27);
+ if cpu_osxsave {
+ // SAFETY: Calling `_xgetbv`` is safe because the CPU has `xsave` support
+ // and OS has set `osxsave`.
+ let xcr0 = unsafe { _xgetbv(0) };
+ let os_avx_support = xcr0 & 6 == 6;
+ if os_avx_support && test(proc_info_ecx, 28) {
+ info.set(CpuInfo::HAS_VMOVDQA_ATOMIC);
}
}
}
@@ -109,9 +104,6 @@ mod tests {
#[cfg(not(portable_atomic_test_outline_atomics_detect_false))]
#[test]
- // SGX doesn't support CPUID.
- // Miri doesn't support inline assembly used in __cpuid.
- #[cfg_attr(any(target_env = "sgx", miri), ignore)]
fn test_cpuid() {
assert_eq!(std::is_x86_feature_detected!("cmpxchg16b"), detect().has_cmpxchg16b());
let vendor_id = unsafe { _vendor_id() };