mirror of
https://github.com/rust-lang/rust.git
synced 2025-11-17 07:06:37 +00:00
Add std_detect for FreeBSD armv6, armv7 and powerpc64
This commit is contained in:
parent
d418d5e1f8
commit
a62067658d
@ -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
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user