@@ -5,19 +5,11 @@ use crate::detect::{Feature, bit, cache};
5
5
6
6
/// Try to read the features from the auxiliary vector
7
7
pub ( 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)
14
11
}
15
12
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
21
13
#[ derive( Debug , Default , PartialEq ) ]
22
14
struct AtHwcap {
23
15
esan3 : bool ,
@@ -76,57 +68,85 @@ impl From<auxvec::AuxVec> for AtHwcap {
76
68
}
77
69
}
78
70
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
+ }
112
88
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
+ }
114
94
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
117
115
118
- // bit 73 of the extended facility list
119
- enable_feature ( Feature :: transactional_execution, self . te ) ;
116
+ enable_if_set ( 129 , Feature :: vector) ;
120
117
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) ;
123
121
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) ;
126
126
127
- // bit 151 of the extended facility list
128
- enable_feature ( Feature :: deflate_conversion, self . dflt ) ;
127
+ enable_if_set ( 165 , Feature :: nnp_assist) ;
129
128
}
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) ;
131
149
}
150
+
151
+ value
132
152
}
0 commit comments