Skip to content

Commit e8c0822

Browse files
committed
s390x: add feature detection for the z17 target features
1 parent 1b4d15d commit e8c0822

File tree

1 file changed

+66
-55
lines changed
  • crates/std_detect/src/detect/os/linux

1 file changed

+66
-55
lines changed

crates/std_detect/src/detect/os/linux/s390x.rs

Lines changed: 66 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,11 @@ use crate::detect::{Feature, bit, cache};
55

66
/// Try to read the features from the auxiliary vector
77
pub(crate) fn detect_features() -> cache::Initializer {
8-
if let Ok(auxv) = auxvec::auxv() {
9-
let hwcap: AtHwcap = auxv.into();
10-
return hwcap.cache();
11-
}
12-
13-
cache::Initializer::default()
8+
let opt_hwcap: Option<AtHwcap> = auxvec::auxv().ok().map(Into::into);
9+
let facilities = ExtendedFacilityList::new();
10+
cache(opt_hwcap, facilities)
1411
}
1512

16-
/// These values are part of the platform-specific [asm/elf.h][kernel], and are a selection of the
17-
/// fields found in the [Facility Indications].
18-
///
19-
/// [Facility Indications]: https://www.ibm.com/support/pages/sites/default/files/2021-05/SA22-7871-10.pdf#page=63
20-
/// [kernel]: https://github.com/torvalds/linux/blob/b62cef9a5c673f1b8083159f5dc03c1c5daced2f/arch/s390/include/asm/elf.h#L129
2113
#[derive(Debug, Default, PartialEq)]
2214
struct AtHwcap {
2315
esan3: bool,
@@ -76,57 +68,76 @@ impl From<auxvec::AuxVec> for AtHwcap {
7668
}
7769
}
7870

79-
impl AtHwcap {
80-
/// Initializes the cache from the feature bits.
81-
fn cache(self) -> cache::Initializer {
82-
let mut value = cache::Initializer::default();
83-
{
84-
let mut enable_feature = |f, enable| {
85-
if enable {
86-
value.set(f as u32);
87-
}
88-
};
89-
90-
// vector and related
91-
92-
// bit 129 of the extended facility list
93-
enable_feature(Feature::vector, self.vxrs);
94-
95-
// bit 135 of the extended facility list
96-
enable_feature(Feature::vector_enhancements_1, self.vxrs_ext);
97-
98-
// bit 148 of the extended facility list
99-
enable_feature(Feature::vector_enhancements_2, self.vxrs_ext2);
100-
101-
// bit 134 of the extended facility list
102-
enable_feature(Feature::vector_packed_decimal, self.vxrs_bcd);
103-
104-
// bit 152 of the extended facility list
105-
enable_feature(Feature::vector_packed_decimal_enhancement, self.vxrs_pde);
71+
struct ExtendedFacilityList([u64; 4]);
72+
73+
impl ExtendedFacilityList {
74+
fn new() -> Self {
75+
let mut result: [u64; 4] = [0; 4];
76+
// SAFETY: rust/llvm only support s390x version with the `stfle` instruction.
77+
unsafe {
78+
core::arch::asm!(
79+
// equivalently ".insn s, 0xb2b00000, 0({1})",
80+
"stfle 0({})",
81+
in(reg_addr) result.as_mut_ptr() ,
82+
inout("r0") result.len() as u64 - 1 => _,
83+
options(nostack)
84+
);
85+
}
86+
Self(result)
87+
}
10688

107-
// bit 192 of the extended facility list
108-
enable_feature(Feature::vector_packed_decimal_enhancement_2, self.vxrs_pde2);
89+
const fn get_bit(&self, n: usize) -> bool {
90+
// NOTE: bits are numbered from the left.
91+
self.0[n / 64] & (1 << (63 - (n % 64))) != 0
92+
}
93+
}
10994

110-
// bit 165 of the extended facility list
111-
enable_feature(Feature::nnp_assist, self.nnpa);
95+
/// Initializes the cache from the feature bits.
96+
///
97+
/// These values are part of the platform-specific [asm/elf.h][kernel], and are a selection of the
98+
/// fields found in the [Facility Indications].
99+
///
100+
/// [Facility Indications]: https://www.ibm.com/support/pages/sites/default/files/2021-05/SA22-7871-10.pdf#page=63
101+
/// [kernel]: https://github.com/torvalds/linux/blob/b62cef9a5c673f1b8083159f5dc03c1c5daced2f/arch/s390/include/asm/elf.h#L129
102+
fn cache(hwcap: Option<AtHwcap>, facilities: ExtendedFacilityList) -> cache::Initializer {
103+
let mut value = cache::Initializer::default();
104+
105+
{
106+
let mut enable_if_set = |bit_index, f| {
107+
if facilities.get_bit(bit_index) {
108+
value.set(f as u32);
109+
}
110+
};
111+
112+
// We use HWCAP for `vector` because it requires both hardware and kernel support.
113+
if let Some(AtHwcap { vxrs: true, .. }) = hwcap {
114+
// vector and related
112115

113-
// others
116+
enable_if_set(129, Feature::vector);
114117

115-
// bit 45 of the extended facility list
116-
enable_feature(Feature::high_word, self.high_gprs);
118+
enable_if_set(135, Feature::vector_enhancements_1);
119+
enable_if_set(148, Feature::vector_enhancements_2);
120+
enable_if_set(198, Feature::vector_enhancements_3);
117121

118-
// bit 73 of the extended facility list
119-
enable_feature(Feature::transactional_execution, self.te);
122+
enable_if_set(134, Feature::vector_packed_decimal);
123+
enable_if_set(152, Feature::vector_packed_decimal_enhancement);
124+
enable_if_set(192, Feature::vector_packed_decimal_enhancement_2);
125+
enable_if_set(199, Feature::vector_packed_decimal_enhancement_3);
120126

121-
// bit 133 of the extended facility list
122-
enable_feature(Feature::guarded_storage, self.gs);
127+
enable_if_set(165, Feature::nnp_assist);
128+
}
123129

124-
// bit 150 of the extended facility list
125-
enable_feature(Feature::enhanced_sort, self.sort);
130+
// others
126131

127-
// bit 151 of the extended facility list
128-
enable_feature(Feature::deflate_conversion, self.dflt);
129-
}
130-
value
132+
enable_if_set(45, Feature::high_word);
133+
enable_if_set(73, Feature::transactional_execution);
134+
enable_if_set(133, Feature::guarded_storage);
135+
enable_if_set(150, Feature::enhanced_sort);
136+
enable_if_set(151, Feature::deflate_conversion);
137+
enable_if_set(84, Feature::miscellaneous_extensions_4);
138+
enable_if_set(86, Feature::message_security_assist_extension12);
139+
enable_if_set(201, Feature::concurrent_functions);
131140
}
141+
142+
value
132143
}

0 commit comments

Comments
 (0)