std_detect/detect/os/linux/
s390x.rs1use super::auxvec;
4use crate::detect::{Feature, bit, cache};
5
6pub(crate) fn detect_features() -> cache::Initializer {
8 let opt_hwcap: Option<AtHwcap> = auxvec::auxv().ok().map(Into::into);
9 let facilities = ExtendedFacilityList::new();
10 cache(opt_hwcap, facilities)
11}
12
13#[derive(Debug, Default, PartialEq)]
14struct AtHwcap {
15 esan3: bool,
16 zarch: bool,
17 stfle: bool,
18 msa: bool,
19 ldisp: bool,
20 eimm: bool,
21 dfp: bool,
22 hpage: bool,
23 etf3eh: bool,
24 high_gprs: bool,
25 te: bool,
26 vxrs: bool,
27 vxrs_bcd: bool,
28 vxrs_ext: bool,
29 gs: bool,
30 vxrs_ext2: bool,
31 vxrs_pde: bool,
32 sort: bool,
33 dflt: bool,
34 vxrs_pde2: bool,
35 nnpa: bool,
36 pci_mio: bool,
37 sie: bool,
38}
39
40impl From<auxvec::AuxVec> for AtHwcap {
41 fn from(auxv: auxvec::AuxVec) -> Self {
43 AtHwcap {
44 esan3: bit::test(auxv.hwcap, 0),
45 zarch: bit::test(auxv.hwcap, 1),
46 stfle: bit::test(auxv.hwcap, 2),
47 msa: bit::test(auxv.hwcap, 3),
48 ldisp: bit::test(auxv.hwcap, 4),
49 eimm: bit::test(auxv.hwcap, 5),
50 dfp: bit::test(auxv.hwcap, 6),
51 hpage: bit::test(auxv.hwcap, 7),
52 etf3eh: bit::test(auxv.hwcap, 8),
53 high_gprs: bit::test(auxv.hwcap, 9),
54 te: bit::test(auxv.hwcap, 10),
55 vxrs: bit::test(auxv.hwcap, 11),
56 vxrs_bcd: bit::test(auxv.hwcap, 12),
57 vxrs_ext: bit::test(auxv.hwcap, 13),
58 gs: bit::test(auxv.hwcap, 14),
59 vxrs_ext2: bit::test(auxv.hwcap, 15),
60 vxrs_pde: bit::test(auxv.hwcap, 16),
61 sort: bit::test(auxv.hwcap, 17),
62 dflt: bit::test(auxv.hwcap, 18),
63 vxrs_pde2: bit::test(auxv.hwcap, 19),
64 nnpa: bit::test(auxv.hwcap, 20),
65 pci_mio: bit::test(auxv.hwcap, 21),
66 sie: bit::test(auxv.hwcap, 22),
67 }
68 }
69}
70
71struct ExtendedFacilityList([u64; 4]);
72
73impl ExtendedFacilityList {
74 fn new() -> Self {
75 let mut result: [u64; 4] = [0; 4];
76 unsafe {
78 core::arch::asm!(
79 "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 }
88
89 const fn get_bit(&self, n: usize) -> bool {
90 self.0[n / 64] & (1 << (63 - (n % 64))) != 0
92 }
93}
94
95fn 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 if let Some(AtHwcap { vxrs: true, .. }) = hwcap {
114 enable_if_set(129, Feature::vector);
117
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);
121
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);
126
127 enable_if_set(165, Feature::nnp_assist);
128 }
129
130 enable_if_set(76, Feature::message_security_assist_extension3);
133 enable_if_set(77, Feature::message_security_assist_extension4);
134 enable_if_set(57, Feature::message_security_assist_extension5);
135 enable_if_set(146, Feature::message_security_assist_extension8);
136 enable_if_set(155, Feature::message_security_assist_extension9);
137 enable_if_set(86, Feature::message_security_assist_extension12);
138
139 enable_if_set(58, Feature::miscellaneous_extensions_2);
140 enable_if_set(61, Feature::miscellaneous_extensions_3);
141 enable_if_set(84, Feature::miscellaneous_extensions_4);
142
143 enable_if_set(45, Feature::high_word);
144 enable_if_set(73, Feature::transactional_execution);
145 enable_if_set(133, Feature::guarded_storage);
146 enable_if_set(150, Feature::enhanced_sort);
147 enable_if_set(151, Feature::deflate_conversion);
148 enable_if_set(201, Feature::concurrent_functions);
149 }
150
151 value
152}