@@ -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,85 @@ 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 ) ;
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+ }
11288
113- // others
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+ }
11494
115- // bit 45 of the extended facility list
116- enable_feature ( Feature :: high_word, self . high_gprs ) ;
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
117115
118- // bit 73 of the extended facility list
119- enable_feature ( Feature :: transactional_execution, self . te ) ;
116+ enable_if_set ( 129 , Feature :: vector) ;
120117
121- // bit 133 of the extended facility list
122- enable_feature ( Feature :: guarded_storage, self . gs ) ;
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) ;
123121
124- // bit 150 of the extended facility list
125- enable_feature ( Feature :: enhanced_sort, self . sort ) ;
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) ;
126126
127- // bit 151 of the extended facility list
128- enable_feature ( Feature :: deflate_conversion, self . dflt ) ;
127+ enable_if_set ( 165 , Feature :: nnp_assist) ;
129128 }
130- value
129+
130+ // others
131+
132+ 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 , miscellaneous_extensions_2) ;
140+ enable_if_set ( 61 , miscellaneous_extensions_3) ;
141+ enable_if_set ( 84 , 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) ;
131149 }
150+
151+ value
132152}
0 commit comments