Skip to content

s390x: z17 target feature detection #1832

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 76 additions & 56 deletions crates/std_detect/src/detect/os/linux/s390x.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,11 @@ use crate::detect::{Feature, bit, cache};

/// Try to read the features from the auxiliary vector
pub(crate) fn detect_features() -> cache::Initializer {
if let Ok(auxv) = auxvec::auxv() {
let hwcap: AtHwcap = auxv.into();
return hwcap.cache();
}

cache::Initializer::default()
let opt_hwcap: Option<AtHwcap> = auxvec::auxv().ok().map(Into::into);
let facilities = ExtendedFacilityList::new();
cache(opt_hwcap, facilities)
}

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

impl AtHwcap {
/// Initializes the cache from the feature bits.
fn cache(self) -> cache::Initializer {
let mut value = cache::Initializer::default();
{
let mut enable_feature = |f, enable| {
if enable {
value.set(f as u32);
}
};

// vector and related

// bit 129 of the extended facility list
enable_feature(Feature::vector, self.vxrs);

// bit 135 of the extended facility list
enable_feature(Feature::vector_enhancements_1, self.vxrs_ext);

// bit 148 of the extended facility list
enable_feature(Feature::vector_enhancements_2, self.vxrs_ext2);

// bit 134 of the extended facility list
enable_feature(Feature::vector_packed_decimal, self.vxrs_bcd);

// bit 152 of the extended facility list
enable_feature(Feature::vector_packed_decimal_enhancement, self.vxrs_pde);

// bit 192 of the extended facility list
enable_feature(Feature::vector_packed_decimal_enhancement_2, self.vxrs_pde2);

// bit 165 of the extended facility list
enable_feature(Feature::nnp_assist, self.nnpa);
struct ExtendedFacilityList([u64; 4]);

impl ExtendedFacilityList {
fn new() -> Self {
let mut result: [u64; 4] = [0; 4];
// SAFETY: rust/llvm only support s390x version with the `stfle` instruction.
unsafe {
core::arch::asm!(
// equivalently ".insn s, 0xb2b00000, 0({1})",
"stfle 0({})",
in(reg_addr) result.as_mut_ptr() ,
inout("r0") result.len() as u64 - 1 => _,
options(nostack)
);
}
Self(result)
}

// others
const fn get_bit(&self, n: usize) -> bool {
// NOTE: bits are numbered from the left.
self.0[n / 64] & (1 << (63 - (n % 64))) != 0
}
}

// bit 45 of the extended facility list
enable_feature(Feature::high_word, self.high_gprs);
/// Initializes the cache from the feature bits.
///
/// These values are part of the platform-specific [asm/elf.h][kernel], and are a selection of the
/// fields found in the [Facility Indications].
///
/// [Facility Indications]: https://www.ibm.com/support/pages/sites/default/files/2021-05/SA22-7871-10.pdf#page=63
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did you get the information about the facility bits that will be added in z17? (It is not included in the documentation at this link.)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can confirm that the z17 facility bit values are correct. The new version of the Principles of Operation including z17 features will be released shortly after the general availability of the new machine (which is next week).

/// [kernel]: https://github.com/torvalds/linux/blob/b62cef9a5c673f1b8083159f5dc03c1c5daced2f/arch/s390/include/asm/elf.h#L129
fn cache(hwcap: Option<AtHwcap>, facilities: ExtendedFacilityList) -> cache::Initializer {
let mut value = cache::Initializer::default();

{
let mut enable_if_set = |bit_index, f| {
if facilities.get_bit(bit_index) {
value.set(f as u32);
}
};

// We use HWCAP for `vector` because it requires both hardware and kernel support.
if let Some(AtHwcap { vxrs: true, .. }) = hwcap {
// vector and related

// bit 73 of the extended facility list
enable_feature(Feature::transactional_execution, self.te);
enable_if_set(129, Feature::vector);

// bit 133 of the extended facility list
enable_feature(Feature::guarded_storage, self.gs);
enable_if_set(135, Feature::vector_enhancements_1);
enable_if_set(148, Feature::vector_enhancements_2);
enable_if_set(198, Feature::vector_enhancements_3);

// bit 150 of the extended facility list
enable_feature(Feature::enhanced_sort, self.sort);
enable_if_set(134, Feature::vector_packed_decimal);
enable_if_set(152, Feature::vector_packed_decimal_enhancement);
enable_if_set(192, Feature::vector_packed_decimal_enhancement_2);
enable_if_set(199, Feature::vector_packed_decimal_enhancement_3);

// bit 151 of the extended facility list
enable_feature(Feature::deflate_conversion, self.dflt);
enable_if_set(165, Feature::nnp_assist);
}
value

// others

enable_if_set(76, Feature::message_security_assist_extension3);
enable_if_set(77, Feature::message_security_assist_extension4);
enable_if_set(57, Feature::message_security_assist_extension5);
enable_if_set(146, Feature::message_security_assist_extension8);
enable_if_set(155, Feature::message_security_assist_extension9);
enable_if_set(86, Feature::message_security_assist_extension12);

enable_if_set(58, miscellaneous_extensions_2);
enable_if_set(61, miscellaneous_extensions_3);
enable_if_set(84, miscellaneous_extensions_4);

enable_if_set(45, Feature::high_word);
enable_if_set(73, Feature::transactional_execution);
enable_if_set(133, Feature::guarded_storage);
enable_if_set(150, Feature::enhanced_sort);
enable_if_set(151, Feature::deflate_conversion);
enable_if_set(201, Feature::concurrent_functions);
}

value
}
Loading