Skip to content

Commit 79b9eee

Browse files
committed
Initial PowerPC support
Rely mainly on parsing auxv since the cpuinfo information is incomplete.
1 parent 0f2fdb1 commit 79b9eee

File tree

4 files changed

+139
-2
lines changed

4 files changed

+139
-2
lines changed

src/runtime/linux/cpuinfo.rs

+33
Original file line numberDiff line numberDiff line change
@@ -214,4 +214,37 @@ CPU revision : 1";
214214
assert!(cpuinfo.field("Features").has("neon"));
215215
assert!(cpuinfo.field("Features").has("asimd"));
216216
}
217+
218+
const POWER8E_POWERKVM: &str = r"processor : 0
219+
cpu : POWER8E (raw), altivec supported
220+
clock : 3425.000000MHz
221+
revision : 2.1 (pvr 004b 0201)
222+
223+
processor : 1
224+
cpu : POWER8E (raw), altivec supported
225+
clock : 3425.000000MHz
226+
revision : 2.1 (pvr 004b 0201)
227+
228+
processor : 2
229+
cpu : POWER8E (raw), altivec supported
230+
clock : 3425.000000MHz
231+
revision : 2.1 (pvr 004b 0201)
232+
233+
processor : 3
234+
cpu : POWER8E (raw), altivec supported
235+
clock : 3425.000000MHz
236+
revision : 2.1 (pvr 004b 0201)
237+
238+
timebase : 512000000
239+
platform : pSeries
240+
model : IBM pSeries (emulated by qemu)
241+
machine : CHRP IBM pSeries (emulated by qemu)";
242+
243+
#[test]
244+
fn test_cpuinfo_linux_power8_powerkvm() {
245+
let cpuinfo = CpuInfo::from_str(POWER8E_POWERKVM).unwrap();
246+
assert_eq!(cpuinfo.field("cpu"), "POWER8E (raw), altivec supported");
247+
248+
assert!(cpuinfo.field("cpu").has("altivec"));
249+
}
217250
}

src/runtime/linux/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ fn detect_features_impl<T: FeatureQuery>(x: T) -> usize {
2020
{
2121
super::aarch64::detect_features(x)
2222
}
23+
#[cfg(target_arch = "powerpc64")]
24+
{
25+
super::powerpc64::detect_features(x)
26+
}
2327
}
2428

2529
/// Detects CPU features:

src/runtime/mod.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,18 @@ mod aarch64;
1717
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
1818
pub use self::aarch64::__Feature;
1919

20+
#[cfg(all(target_arch = "powerpc64", target_os = "linux"))]
21+
#[macro_use]
22+
mod powerpc64;
23+
#[cfg(all(target_arch = "powerpc64", target_os = "linux"))]
24+
pub use self::powerpc64::__Feature;
25+
2026
#[cfg(all(target_os = "linux",
21-
any(target_arch = "arm", target_arch = "aarch64")))]
27+
any(target_arch = "arm", target_arch = "aarch64", target_arch = "powerpc64")))]
2228
mod linux;
2329

2430
#[cfg(all(target_os = "linux",
25-
any(target_arch = "arm", target_arch = "aarch64")))]
31+
any(target_arch = "arm", target_arch = "aarch64", target_arch = "powerpc64")))]
2632
pub use self::linux::detect_features;
2733

2834
/// Performs run-time feature detection.

src/runtime/powerpc64.rs

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//! Run-time feature detection on PowerPC64.
2+
use super::{bit, linux};
3+
4+
#[macro_export]
5+
#[doc(hidden)]
6+
macro_rules! __unstable_detect_feature {
7+
("altivec") => {
8+
$crate::vendor::__unstable_detect_feature($crate::vendor::__Feature::altivec{})
9+
};
10+
("vsx") => {
11+
$crate::vendor::__unstable_detect_feature($crate::vendor::__Feature::vsx{})
12+
};
13+
("power8") => {
14+
$crate::vendor::__unstable_detect_feature($crate::vendor::__Feature::power8{})
15+
};
16+
($t:tt) => { compile_error!(concat!("unknown PowerPC target feature: ", $t)) };
17+
}
18+
19+
/// PowerPC CPU Feature enum. Each variant denotes a position in a bitset
20+
/// for a particular feature.
21+
///
22+
/// PLEASE: do not use this, it is an implementation detail subject to change.
23+
#[doc(hidden)]
24+
#[allow(non_camel_case_types)]
25+
#[repr(u8)]
26+
pub enum __Feature {
27+
/// Altivec
28+
altivec,
29+
/// VSX
30+
vsx,
31+
/// Power8
32+
power8,
33+
}
34+
35+
pub fn detect_features<T: linux::FeatureQuery>(mut x: T) -> usize {
36+
let mut value: usize = 0;
37+
{
38+
let mut enable_feature = |f| {
39+
if x.has_feature(&f) {
40+
value = bit::set(value, f as u32);
41+
}
42+
};
43+
enable_feature(__Feature::altivec);
44+
enable_feature(__Feature::vsx);
45+
enable_feature(__Feature::power8);
46+
}
47+
value
48+
}
49+
50+
/// Probe the ELF Auxiliary vector for hardware capabilities
51+
///
52+
/// The values are part of the platform-specific [asm/cputable.h][cputable]
53+
///
54+
/// [cputable]: https://github.com/torvalds/linux/blob/master/arch/powerpc/include/uapi/asm/cputable.h
55+
impl linux::FeatureQuery for linux::AuxVec {
56+
fn has_feature(&mut self, x: &__Feature) -> bool {
57+
use self::__Feature::*;
58+
match *x {
59+
altivec => self.lookup(linux::AT::HWCAP)
60+
.map(|caps| caps & 0x10000000 != 0)
61+
.unwrap_or(false),
62+
vsx => self.lookup(linux::AT::HWCAP)
63+
.map(|caps| caps & 0x00000080 != 0)
64+
.unwrap_or(false),
65+
power8 => self.lookup(linux::AT::HWCAP2)
66+
.map(|caps| caps & 0x80000000 != 0)
67+
.unwrap_or(false),
68+
}
69+
}
70+
}
71+
72+
/// Check for altivec support only
73+
///
74+
/// PowerPC's /proc/cpuinfo lacks a proper Feature field,
75+
/// but `altivec` support is indicated in the `cpu` field.
76+
impl linux::FeatureQuery for linux::CpuInfo {
77+
fn has_feature(&mut self, x: &__Feature) -> bool {
78+
use self::__Feature::*;
79+
match *x {
80+
altivec => self.field("cpu").has("altivec"),
81+
_ => false
82+
}
83+
}
84+
}
85+
86+
#[cfg(test)]
87+
mod tests {
88+
#[test]
89+
fn detect_feature() {
90+
println!("altivec {}", __unstable_detect_feature!("altivec"));
91+
println!("vsx {}", __unstable_detect_feature!("vsx"));
92+
println!("power8 {}", __unstable_detect_feature!("power8"));
93+
}
94+
}

0 commit comments

Comments
 (0)