Initial PowerPC support
Rely mainly on parsing auxv since the cpuinfo information is incomplete.
This commit is contained in:
parent
f775bf3931
commit
baace2fc3f
4 changed files with 191 additions and 2 deletions
|
|
@ -214,4 +214,89 @@ CPU revision : 1";
|
|||
assert!(cpuinfo.field("Features").has("neon"));
|
||||
assert!(cpuinfo.field("Features").has("asimd"));
|
||||
}
|
||||
|
||||
const POWER8E_POWERKVM: &str = r"processor : 0
|
||||
cpu : POWER8E (raw), altivec supported
|
||||
clock : 3425.000000MHz
|
||||
revision : 2.1 (pvr 004b 0201)
|
||||
|
||||
processor : 1
|
||||
cpu : POWER8E (raw), altivec supported
|
||||
clock : 3425.000000MHz
|
||||
revision : 2.1 (pvr 004b 0201)
|
||||
|
||||
processor : 2
|
||||
cpu : POWER8E (raw), altivec supported
|
||||
clock : 3425.000000MHz
|
||||
revision : 2.1 (pvr 004b 0201)
|
||||
|
||||
processor : 3
|
||||
cpu : POWER8E (raw), altivec supported
|
||||
clock : 3425.000000MHz
|
||||
revision : 2.1 (pvr 004b 0201)
|
||||
|
||||
timebase : 512000000
|
||||
platform : pSeries
|
||||
model : IBM pSeries (emulated by qemu)
|
||||
machine : CHRP IBM pSeries (emulated by qemu)";
|
||||
|
||||
#[test]
|
||||
fn test_cpuinfo_linux_power8_powerkvm() {
|
||||
let cpuinfo = CpuInfo::from_str(POWER8E_POWERKVM).unwrap();
|
||||
assert_eq!(cpuinfo.field("cpu"), "POWER8E (raw), altivec supported");
|
||||
|
||||
assert!(cpuinfo.field("cpu").has("altivec"));
|
||||
}
|
||||
|
||||
const POWER5P: &str = r"processor : 0
|
||||
cpu : POWER5+ (gs)
|
||||
clock : 1900.098000MHz
|
||||
revision : 2.1 (pvr 003b 0201)
|
||||
|
||||
processor : 1
|
||||
cpu : POWER5+ (gs)
|
||||
clock : 1900.098000MHz
|
||||
revision : 2.1 (pvr 003b 0201)
|
||||
|
||||
processor : 2
|
||||
cpu : POWER5+ (gs)
|
||||
clock : 1900.098000MHz
|
||||
revision : 2.1 (pvr 003b 0201)
|
||||
|
||||
processor : 3
|
||||
cpu : POWER5+ (gs)
|
||||
clock : 1900.098000MHz
|
||||
revision : 2.1 (pvr 003b 0201)
|
||||
|
||||
processor : 4
|
||||
cpu : POWER5+ (gs)
|
||||
clock : 1900.098000MHz
|
||||
revision : 2.1 (pvr 003b 0201)
|
||||
|
||||
processor : 5
|
||||
cpu : POWER5+ (gs)
|
||||
clock : 1900.098000MHz
|
||||
revision : 2.1 (pvr 003b 0201)
|
||||
|
||||
processor : 6
|
||||
cpu : POWER5+ (gs)
|
||||
clock : 1900.098000MHz
|
||||
revision : 2.1 (pvr 003b 0201)
|
||||
|
||||
processor : 7
|
||||
cpu : POWER5+ (gs)
|
||||
clock : 1900.098000MHz
|
||||
revision : 2.1 (pvr 003b 0201)
|
||||
|
||||
timebase : 237331000
|
||||
platform : pSeries
|
||||
machine : CHRP IBM,9133-55A";
|
||||
|
||||
#[test]
|
||||
fn test_cpuinfo_linux_power5p() {
|
||||
let cpuinfo = CpuInfo::from_str(POWER5P).unwrap();
|
||||
assert_eq!(cpuinfo.field("cpu"), "POWER5+ (gs)");
|
||||
|
||||
assert!(!cpuinfo.field("cpu").has("altivec"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ fn detect_features_impl<T: FeatureQuery>(x: T) -> usize {
|
|||
{
|
||||
super::aarch64::detect_features(x)
|
||||
}
|
||||
#[cfg(target_arch = "powerpc64")]
|
||||
{
|
||||
super::powerpc64::detect_features(x)
|
||||
}
|
||||
}
|
||||
|
||||
/// Detects CPU features:
|
||||
|
|
|
|||
|
|
@ -17,12 +17,18 @@ mod aarch64;
|
|||
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
|
||||
pub use self::aarch64::__Feature;
|
||||
|
||||
#[cfg(all(target_arch = "powerpc64", target_os = "linux"))]
|
||||
#[macro_use]
|
||||
mod powerpc64;
|
||||
#[cfg(all(target_arch = "powerpc64", target_os = "linux"))]
|
||||
pub use self::powerpc64::__Feature;
|
||||
|
||||
#[cfg(all(target_os = "linux",
|
||||
any(target_arch = "arm", target_arch = "aarch64")))]
|
||||
any(target_arch = "arm", target_arch = "aarch64", target_arch = "powerpc64")))]
|
||||
mod linux;
|
||||
|
||||
#[cfg(all(target_os = "linux",
|
||||
any(target_arch = "arm", target_arch = "aarch64")))]
|
||||
any(target_arch = "arm", target_arch = "aarch64", target_arch = "powerpc64")))]
|
||||
pub use self::linux::detect_features;
|
||||
|
||||
/// Performs run-time feature detection.
|
||||
|
|
|
|||
94
library/stdarch/src/runtime/powerpc64.rs
Normal file
94
library/stdarch/src/runtime/powerpc64.rs
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
//! Run-time feature detection on PowerPC64.
|
||||
use super::{bit, linux};
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __unstable_detect_feature {
|
||||
("altivec") => {
|
||||
$crate::vendor::__unstable_detect_feature($crate::vendor::__Feature::altivec{})
|
||||
};
|
||||
("vsx") => {
|
||||
$crate::vendor::__unstable_detect_feature($crate::vendor::__Feature::vsx{})
|
||||
};
|
||||
("power8") => {
|
||||
$crate::vendor::__unstable_detect_feature($crate::vendor::__Feature::power8{})
|
||||
};
|
||||
($t:tt) => { compile_error!(concat!("unknown PowerPC target feature: ", $t)) };
|
||||
}
|
||||
|
||||
/// PowerPC CPU Feature enum. Each variant denotes a position in a bitset
|
||||
/// for a particular feature.
|
||||
///
|
||||
/// PLEASE: do not use this, it is an implementation detail subject to change.
|
||||
#[doc(hidden)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(u8)]
|
||||
pub enum __Feature {
|
||||
/// Altivec
|
||||
altivec,
|
||||
/// VSX
|
||||
vsx,
|
||||
/// Power8
|
||||
power8,
|
||||
}
|
||||
|
||||
pub fn detect_features<T: linux::FeatureQuery>(mut x: T) -> usize {
|
||||
let mut value: usize = 0;
|
||||
{
|
||||
let mut enable_feature = |f| {
|
||||
if x.has_feature(&f) {
|
||||
value = bit::set(value, f as u32);
|
||||
}
|
||||
};
|
||||
enable_feature(__Feature::altivec);
|
||||
enable_feature(__Feature::vsx);
|
||||
enable_feature(__Feature::power8);
|
||||
}
|
||||
value
|
||||
}
|
||||
|
||||
/// Probe the ELF Auxiliary vector for hardware capabilities
|
||||
///
|
||||
/// The values are part of the platform-specific [asm/cputable.h][cputable]
|
||||
///
|
||||
/// [cputable]: https://github.com/torvalds/linux/blob/master/arch/powerpc/include/uapi/asm/cputable.h
|
||||
impl linux::FeatureQuery for linux::AuxVec {
|
||||
fn has_feature(&mut self, x: &__Feature) -> bool {
|
||||
use self::__Feature::*;
|
||||
match *x {
|
||||
altivec => self.lookup(linux::AT::HWCAP)
|
||||
.map(|caps| caps & 0x10000000 != 0)
|
||||
.unwrap_or(false),
|
||||
vsx => self.lookup(linux::AT::HWCAP)
|
||||
.map(|caps| caps & 0x00000080 != 0)
|
||||
.unwrap_or(false),
|
||||
power8 => self.lookup(linux::AT::HWCAP2)
|
||||
.map(|caps| caps & 0x80000000 != 0)
|
||||
.unwrap_or(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check for altivec support only
|
||||
///
|
||||
/// PowerPC's /proc/cpuinfo lacks a proper Feature field,
|
||||
/// but `altivec` support is indicated in the `cpu` field.
|
||||
impl linux::FeatureQuery for linux::CpuInfo {
|
||||
fn has_feature(&mut self, x: &__Feature) -> bool {
|
||||
use self::__Feature::*;
|
||||
match *x {
|
||||
altivec => self.field("cpu").has("altivec"),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn detect_feature() {
|
||||
println!("altivec {}", __unstable_detect_feature!("altivec"));
|
||||
println!("vsx {}", __unstable_detect_feature!("vsx"));
|
||||
println!("power8 {}", __unstable_detect_feature!("power8"));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue