about summary refs log tree commit diff
path: root/library/stdarch/crates/std_detect
diff options
context:
space:
mode:
authormiki <mikael.urankar@gmail.com>2019-04-26 17:16:12 +0200
committergnzlbg <gnzlbg@users.noreply.github.com>2019-05-09 16:03:06 +0200
commita62067658ddcdbd085be256e3800cabd267fc79b (patch)
treec749cb56833dac6852509c91eb7112004ba5d8f8 /library/stdarch/crates/std_detect
parentd418d5e1f8d5506b8ad1cec8b7ac62da6674803b (diff)
downloadrust-a62067658ddcdbd085be256e3800cabd267fc79b.tar.gz
rust-a62067658ddcdbd085be256e3800cabd267fc79b.zip
Add std_detect for FreeBSD armv6, armv7 and powerpc64
Diffstat (limited to 'library/stdarch/crates/std_detect')
-rw-r--r--library/stdarch/crates/std_detect/src/detect/os/freebsd/arm.rs27
-rw-r--r--library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs86
-rw-r--r--library/stdarch/crates/std_detect/src/detect/os/freebsd/mod.rs8
-rw-r--r--library/stdarch/crates/std_detect/src/detect/os/freebsd/powerpc.rs27
4 files changed, 148 insertions, 0 deletions
diff --git a/library/stdarch/crates/std_detect/src/detect/os/freebsd/arm.rs b/library/stdarch/crates/std_detect/src/detect/os/freebsd/arm.rs
new file mode 100644
index 00000000000..e13847dcbd8
--- /dev/null
+++ b/library/stdarch/crates/std_detect/src/detect/os/freebsd/arm.rs
@@ -0,0 +1,27 @@
+//! Run-time feature detection for ARM on FreeBSD
+
+use crate::detect::{Feature, cache};
+use super::{auxvec};
+
+/// Performs run-time feature detection.
+#[inline]
+pub fn check_for(x: Feature) -> bool {
+    cache::test(x as u32, detect_features)
+}
+
+/// Try to read the features from the auxiliary vector
+fn detect_features() -> cache::Initializer {
+    let mut value = cache::Initializer::default();
+    let enable_feature = |value: &mut cache::Initializer, f, enable| {
+        if enable {
+            value.set(f as u32);
+        }
+    };
+
+    if let Ok(auxv) = auxvec::auxv() {
+        enable_feature(&mut value, Feature::neon, auxv.hwcap & 0x00001000 != 0);
+        enable_feature(&mut value, Feature::pmull, auxv.hwcap2 & 0x00000002 != 0);
+        return value;
+    }
+    value
+}
diff --git a/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs b/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs
new file mode 100644
index 00000000000..fd2bd500bfa
--- /dev/null
+++ b/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs
@@ -0,0 +1,86 @@
+//! Parses ELF auxiliary vectors.
+#![cfg_attr(any(target_arch = "arm", target_arch = "powerpc64"), allow(dead_code))]
+
+/// Key to access the CPU Hardware capabilities bitfield.
+pub(crate) const AT_HWCAP: usize = 25;
+/// Key to access the CPU Hardware capabilities 2 bitfield.
+pub(crate) const AT_HWCAP2: usize = 26;
+
+/// Cache HWCAP bitfields of the ELF Auxiliary Vector.
+///
+/// If an entry cannot be read all the bits in the bitfield are set to zero.
+/// This should be interpreted as all the features being disabled.
+#[derive(Debug, Copy, Clone)]
+pub(crate) struct AuxVec {
+    pub hwcap: usize,
+    pub hwcap2: usize,
+}
+
+/// ELF Auxiliary Vector
+///
+/// The auxiliary vector is a memory region in a running ELF program's stack
+/// composed of (key: usize, value: usize) pairs.
+///
+/// The keys used in the aux vector are platform dependent. For FreeBSD, they are
+/// defined in [sys/elf_common.h][elf_common_h]. The hardware capabilities of a given
+/// CPU can be queried with the  `AT_HWCAP` and `AT_HWCAP2` keys.
+///
+/// Note that run-time feature detection is not invoked for features that can
+/// be detected at compile-time.
+///
+/// [elf_common.h]: https://svnweb.freebsd.org/base/release/12.0.0/sys/sys/elf_common.h?revision=341707
+pub(crate) fn auxv() -> Result<AuxVec, ()> {
+    if let Ok(hwcap) = archauxv(AT_HWCAP) {
+        if let Ok(hwcap2) = archauxv(AT_HWCAP2) {
+            if hwcap != 0 && hwcap2 != 0 {
+                return Ok(AuxVec { hwcap, hwcap2 });
+            }
+        }
+    }
+    Err(())
+}
+
+/// Tries to read the `key` from the auxiliary vector.
+fn archauxv(key: usize) -> Result<usize, ()> {
+    use mem;
+
+    #[derive (Copy, Clone)]
+    #[repr(C)]
+    pub struct Elf_Auxinfo {
+        pub a_type: usize,
+        pub a_un: unnamed,
+    }
+    #[derive (Copy, Clone)]
+    #[repr(C)]
+    pub union unnamed {
+        pub a_val: libc::c_long,
+        pub a_ptr: *mut libc::c_void,
+        pub a_fcn: Option<unsafe extern "C" fn() -> ()>,
+    }
+
+    let mut auxv: [Elf_Auxinfo; 27] =
+        [Elf_Auxinfo{a_type: 0, a_un: unnamed{a_val: 0,},}; 27];
+
+    let mut len: libc::c_uint = mem::size_of_val(&auxv) as libc::c_uint;
+
+    unsafe {
+        let mut mib = [libc::CTL_KERN, libc::KERN_PROC, libc::KERN_PROC_AUXV, libc::getpid()];
+    
+        let ret = libc::sysctl(mib.as_mut_ptr(),
+                       mib.len() as u32,
+                       &mut auxv as *mut _ as *mut _,
+                       &mut len as *mut _ as *mut _,
+                       0 as *mut libc::c_void,
+                       0,
+                );
+    
+        if ret != -1 {
+            for i in 0..auxv.len() {
+                if auxv[i].a_type == key {
+                    return Ok(auxv[i].a_un.a_val as usize);
+                }
+            }
+        }
+    }
+    return Ok(0);
+}
diff --git a/library/stdarch/crates/std_detect/src/detect/os/freebsd/mod.rs b/library/stdarch/crates/std_detect/src/detect/os/freebsd/mod.rs
index 952b4baf0fd..1a5338a3555 100644
--- a/library/stdarch/crates/std_detect/src/detect/os/freebsd/mod.rs
+++ b/library/stdarch/crates/std_detect/src/detect/os/freebsd/mod.rs
@@ -1,9 +1,17 @@
 //! Run-time feature detection on FreeBSD
 
+mod auxvec;
+
 cfg_if! {
     if #[cfg(target_arch = "aarch64")] {
         mod aarch64;
         pub use self::aarch64::check_for;
+    } else if #[cfg(target_arch = "arm")] {
+        mod arm;
+        pub use self::arm::check_for;
+    } else if #[cfg(target_arch = "powerpc64")] {
+        mod powerpc;
+        pub use self::powerpc::check_for;
     } else {
         use crate::arch::detect::Feature;
         /// Performs run-time feature detection.
diff --git a/library/stdarch/crates/std_detect/src/detect/os/freebsd/powerpc.rs b/library/stdarch/crates/std_detect/src/detect/os/freebsd/powerpc.rs
new file mode 100644
index 00000000000..c7f761d4d60
--- /dev/null
+++ b/library/stdarch/crates/std_detect/src/detect/os/freebsd/powerpc.rs
@@ -0,0 +1,27 @@
+//! Run-time feature detection for PowerPC on FreeBSD.
+
+use crate::detect::{Feature, cache};
+use super::{auxvec};
+
+/// Performs run-time feature detection.
+#[inline]
+pub fn check_for(x: Feature) -> bool {
+    cache::test(x as u32, detect_features)
+}
+
+fn detect_features() -> cache::Initializer {
+    let mut value = cache::Initializer::default();
+    let enable_feature = |value: &mut cache::Initializer, f, enable| {
+        if enable {
+            value.set(f as u32);
+        }
+    };
+
+    if let Ok(auxv) = auxvec::auxv() {
+        enable_feature(&mut value, Feature::altivec, auxv.hwcap & 0x10000000 != 0);
+        enable_feature(&mut value, Feature::vsx, auxv.hwcap & 0x00000080 != 0);
+        enable_feature(&mut value, Feature::power8, auxv.hwcap2 & 0x80000000 != 0);
+        return value;
+    }
+    value
+}