@@ -5,19 +5,11 @@ use crate::detect::{Feature, bit, cache};
55
66/// Try to read the features from the auxiliary vector
77pub ( 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 ) ]
2214struct AtHwcap {
2315 esan3 : bool ,
@@ -76,57 +68,80 @@ 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 ) ;
106-
107- // bit 192 of the extended facility list
108- enable_feature ( Feature :: vector_packed_decimal_enhancement_2, self . vxrs_pde2 ) ;
109-
110- // bit 165 of the extended facility list
111- enable_feature ( Feature :: nnp_assist, self . nnpa ) ;
112-
113- // others
114-
115- // bit 45 of the extended facility list
116- enable_feature ( Feature :: high_word, self . high_gprs ) ;
117-
118- // bit 73 of the extended facility list
119- enable_feature ( Feature :: transactional_execution, self . te ) ;
120-
121- // bit 133 of the extended facility list
122- enable_feature ( Feature :: guarded_storage, self . gs ) ;
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+ }
12388
124- // bit 150 of the extended facility list
125- enable_feature ( Feature :: enhanced_sort, self . sort ) ;
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+ }
12694
127- // bit 151 of the extended facility list
128- enable_feature ( Feature :: deflate_conversion, self . dflt ) ;
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+ // bit 129 of the extended facility list
106+ if let Some ( hwcap) = hwcap {
107+ // We use HWCAP for this feature because it requires both hardware and kernel support.
108+ if hwcap. vxrs {
109+ value. set ( Feature :: vector as u32 ) ;
129110 }
130- value
131111 }
112+
113+ {
114+ let mut enable_if_set = |bit_index, f| {
115+ if facilities. get_bit ( bit_index) {
116+ value. set ( f as u32 ) ;
117+ }
118+ } ;
119+
120+ // vector and related
121+
122+ enable_if_set ( 135 , Feature :: vector_enhancements_1) ;
123+ enable_if_set ( 148 , Feature :: vector_enhancements_2) ;
124+ enable_if_set ( 198 , Feature :: vector_enhancements_3) ;
125+
126+ enable_if_set ( 134 , Feature :: vector_packed_decimal) ;
127+ enable_if_set ( 152 , Feature :: vector_packed_decimal_enhancement) ;
128+ enable_if_set ( 192 , Feature :: vector_packed_decimal_enhancement_2) ;
129+ enable_if_set ( 199 , Feature :: vector_packed_decimal_enhancement_3) ;
130+
131+ enable_if_set ( 165 , Feature :: nnp_assist) ;
132+
133+ // others
134+
135+ enable_if_set ( 45 , Feature :: high_word) ;
136+ enable_if_set ( 73 , Feature :: transactional_execution) ;
137+ enable_if_set ( 133 , Feature :: guarded_storage) ;
138+ enable_if_set ( 150 , Feature :: enhanced_sort) ;
139+ enable_if_set ( 151 , Feature :: deflate_conversion) ;
140+ // added in z17
141+ enable_if_set ( 84 , Feature :: miscellaneous_extensions_4) ;
142+ enable_if_set ( 86 , Feature :: message_security_assist_extension12) ;
143+ enable_if_set ( 201 , Feature :: concurrent_functions) ;
144+ }
145+
146+ value
132147}
0 commit comments