s390x: add feature detection for the z17 target features
diff --git a/crates/std_detect/src/detect/arch/s390x.rs b/crates/std_detect/src/detect/arch/s390x.rs
index f05081d..4c20d01 100644
--- a/crates/std_detect/src/detect/arch/s390x.rs
+++ b/crates/std_detect/src/detect/arch/s390x.rs
@@ -22,9 +22,30 @@
     @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] high_word: "high-word";
     /// s390x high-word facility
     #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")]
+    @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension3: "message-security-assist-extension3";
+    /// s390x message-security-assist-extension3 facility
+    #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")]
+    @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension4: "message-security-assist-extension4";
+    /// s390x message-security-assist-extension4 facility
+    #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")]
+    @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension5: "message-security-assist-extension5";
+    /// s390x message-security-assist-extension5 facility
+    #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")]
+    @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension8: "message-security-assist-extension8";
+    /// s390x message-security-assist-extension8 facility
+    #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")]
+    @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension9: "message-security-assist-extension9";
+    /// s390x message-security-assist-extension9 facility
+    #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")]
     @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension12: "message-security-assist-extension12";
     /// s390x message-security-assist-extension12 facility
     #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")]
+    @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] miscellaneous_extensions_2: "miscellaneous-extensions-2";
+    /// s390x miscellaneous-extensions-2 facility
+    #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")]
+    @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] miscellaneous_extensions_3: "miscellaneous-extensions-3";
+    /// s390x miscellaneous-extensions-3 facility
+    #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")]
     @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] miscellaneous_extensions_4: "miscellaneous-extensions-4";
     /// s390x miscellaneous-extensions-4 facility
     #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")]
diff --git a/crates/std_detect/src/detect/os/linux/s390x.rs b/crates/std_detect/src/detect/os/linux/s390x.rs
index 5cc35fd..9b53f52 100644
--- a/crates/std_detect/src/detect/os/linux/s390x.rs
+++ b/crates/std_detect/src/detect/os/linux/s390x.rs
@@ -5,19 +5,11 @@
 
 /// 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,
@@ -76,57 +68,85 @@
     }
 }
 
-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);
-                }
-            };
+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)
+    }
+
+    const fn get_bit(&self, n: usize) -> bool {
+        // NOTE: bits are numbered from the left.
+        self.0[n / 64] & (1 << (63 - (n % 64))) != 0
+    }
+}
+
+/// 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
+/// [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 129 of the extended facility list
-            enable_feature(Feature::vector, self.vxrs);
+            enable_if_set(129, Feature::vector);
 
-            // bit 135 of the extended facility list
-            enable_feature(Feature::vector_enhancements_1, self.vxrs_ext);
+            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 148 of the extended facility list
-            enable_feature(Feature::vector_enhancements_2, self.vxrs_ext2);
+            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 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);
-
-            // others
-
-            // bit 45 of the extended facility list
-            enable_feature(Feature::high_word, self.high_gprs);
-
-            // bit 73 of the extended facility list
-            enable_feature(Feature::transactional_execution, self.te);
-
-            // bit 133 of the extended facility list
-            enable_feature(Feature::guarded_storage, self.gs);
-
-            // bit 150 of the extended facility list
-            enable_feature(Feature::enhanced_sort, self.sort);
-
-            // 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, Feature::miscellaneous_extensions_2);
+        enable_if_set(61, Feature::miscellaneous_extensions_3);
+        enable_if_set(84, Feature::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
 }