@@ -21,13 +21,13 @@ struct riscv_hwprobe {
21
21
#[allow(non_upper_case_globals)]
22
22
const __NR_riscv_hwprobe: libc::c_long = 258;
23
23
24
- const RISCV_HWPROBE_KEY_BASE_BEHAVIOR: i64 = 3;
25
- const RISCV_HWPROBE_BASE_BEHAVIOR_IMA: u64 = 1 << 0;
24
+ // const RISCV_HWPROBE_KEY_BASE_BEHAVIOR: i64 = 3;
25
+ // const RISCV_HWPROBE_BASE_BEHAVIOR_IMA: u64 = 1 << 0;
26
26
27
27
const RISCV_HWPROBE_KEY_IMA_EXT_0: i64 = 4;
28
- const RISCV_HWPROBE_IMA_FD: u64 = 1 << 0;
29
- const RISCV_HWPROBE_IMA_C: u64 = 1 << 1;
30
- const RISCV_HWPROBE_IMA_V: u64 = 1 << 2;
28
+ // const RISCV_HWPROBE_IMA_FD: u64 = 1 << 0;
29
+ // const RISCV_HWPROBE_IMA_C: u64 = 1 << 1;
30
+ // const RISCV_HWPROBE_IMA_V: u64 = 1 << 2;
31
31
const RISCV_HWPROBE_EXT_ZBA: u64 = 1 << 3;
32
32
const RISCV_HWPROBE_EXT_ZBB: u64 = 1 << 4;
33
33
const RISCV_HWPROBE_EXT_ZBS: u64 = 1 << 5;
@@ -62,11 +62,11 @@ const RISCV_HWPROBE_EXT_ZTSO: u64 = 1 << 33;
62
62
const RISCV_HWPROBE_EXT_ZACAS: u64 = 1 << 34;
63
63
// const RISCV_HWPROBE_EXT_ZICOND: u64 = 1 << 35;
64
64
const RISCV_HWPROBE_EXT_ZIHINTPAUSE: u64 = 1 << 36;
65
- const RISCV_HWPROBE_EXT_ZVE32X: u64 = 1 << 37;
66
- const RISCV_HWPROBE_EXT_ZVE32F: u64 = 1 << 38;
67
- const RISCV_HWPROBE_EXT_ZVE64X: u64 = 1 << 39;
68
- const RISCV_HWPROBE_EXT_ZVE64F: u64 = 1 << 40;
69
- const RISCV_HWPROBE_EXT_ZVE64D: u64 = 1 << 41;
65
+ // const RISCV_HWPROBE_EXT_ZVE32X: u64 = 1 << 37;
66
+ // const RISCV_HWPROBE_EXT_ZVE32F: u64 = 1 << 38;
67
+ // const RISCV_HWPROBE_EXT_ZVE64X: u64 = 1 << 39;
68
+ // const RISCV_HWPROBE_EXT_ZVE64F: u64 = 1 << 40;
69
+ // const RISCV_HWPROBE_EXT_ZVE64D: u64 = 1 << 41;
70
70
// const RISCV_HWPROBE_EXT_ZIMOP: u64 = 1 << 42;
71
71
// const RISCV_HWPROBE_EXT_ZCA: u64 = 1 << 43;
72
72
// const RISCV_HWPROBE_EXT_ZCB: u64 = 1 << 44;
@@ -113,11 +113,79 @@ fn _riscv_hwprobe(out: &mut [riscv_hwprobe]) -> bool {
113
113
pub(crate) fn detect_features() -> cache::Initializer {
114
114
let mut value = cache::Initializer::default();
115
115
116
+ let enable_feature = |value: &mut cache::Initializer, feature, enable| {
117
+ if enable {
118
+ value.set(feature as u32);
119
+ }
120
+ };
121
+ let enable_features = |value: &mut cache::Initializer, feature_slice: &[Feature], enable| {
122
+ if enable {
123
+ for feature in feature_slice {
124
+ value.set(*feature as u32);
125
+ }
126
+ }
127
+ };
128
+
129
+ // The values are part of the platform-specific [asm/hwcap.h][hwcap]
130
+ //
131
+ // [hwcap]: https://github.com/torvalds/linux/blob/master/arch/riscv/include/asm/hwcap.h
132
+ let auxv = auxvec::auxv().expect("read auxvec"); // should not fail on RISC-V platform
133
+ #[allow(clippy::eq_op)]
134
+ enable_feature(
135
+ &mut value,
136
+ Feature::a,
137
+ bit::test(auxv.hwcap, (b'a' - b'a').into()),
138
+ );
139
+ enable_feature(
140
+ &mut value,
141
+ Feature::c,
142
+ bit::test(auxv.hwcap, (b'c' - b'a').into()),
143
+ );
144
+ enable_features(
145
+ &mut value,
146
+ &[Feature::d, Feature::f, Feature::zicsr],
147
+ bit::test(auxv.hwcap, (b'd' - b'a').into()),
148
+ );
149
+ enable_features(
150
+ &mut value,
151
+ &[Feature::f, Feature::zicsr],
152
+ bit::test(auxv.hwcap, (b'f' - b'a').into()),
153
+ );
154
+ let has_i = bit::test(auxv.hwcap, (b'i' - b'a').into());
155
+ // If future RV128I is supported, implement with `enable_feature` here
156
+ // Checking target_pointer_width instead of target_arch is incorrect since
157
+ // there are RV64ILP32* ABIs.
158
+ #[cfg(target_arch = "riscv64")]
159
+ enable_feature(&mut value, Feature::rv64i, has_i);
160
+ #[cfg(target_arch = "riscv32")]
161
+ enable_feature(&mut value, Feature::rv32i, has_i);
162
+ // FIXME: e is not exposed in any of asm/hwcap.h, uapi/asm/hwcap.h, uapi/asm/hwprobe.h
163
+ #[cfg(target_arch = "riscv32")]
164
+ enable_feature(
165
+ &mut value,
166
+ Feature::rv32e,
167
+ bit::test(auxv.hwcap, (b'e' - b'a').into()),
168
+ );
169
+ enable_feature(
170
+ &mut value,
171
+ Feature::m,
172
+ bit::test(auxv.hwcap, (b'm' - b'a').into()),
173
+ );
174
+ let has_v = bit::test(auxv.hwcap, (b'v' - b'a').into());
175
+ enable_features(
176
+ &mut value,
177
+ &[
178
+ Feature::v,
179
+ Feature::zve32f,
180
+ Feature::zve32x,
181
+ Feature::zve64d,
182
+ Feature::zve64f,
183
+ Feature::zve64x,
184
+ ],
185
+ has_v,
186
+ );
187
+
116
188
let mut out = [
117
- riscv_hwprobe {
118
- key: RISCV_HWPROBE_KEY_BASE_BEHAVIOR,
119
- value: 0,
120
- },
121
189
riscv_hwprobe {
122
190
key: RISCV_HWPROBE_KEY_IMA_EXT_0,
123
191
value: 0,
@@ -138,23 +206,13 @@ pub(crate) fn detect_features() -> cache::Initializer {
138
206
}
139
207
};
140
208
if out[0].key != -1 {
141
- let base_behavior = out[0].value;
142
- let ima = base_behavior & RISCV_HWPROBE_BASE_BEHAVIOR_IMA != 0;
143
- // If future RV128I is supported, implement with `enable_feature` here
144
- #[cfg(target_arch = "riscv32")]
145
- enable_feature(Feature::rv32i, ima);
146
- #[cfg(target_arch = "riscv64")]
147
- enable_feature(Feature::rv64i, ima);
148
- enable_feature(Feature::m, ima);
149
- enable_feature(Feature::a, ima);
150
- }
151
- if out[1].key != -1 {
152
- let ima_ext_0 = out[1].value;
153
- let fd = ima_ext_0 & RISCV_HWPROBE_IMA_FD != 0;
154
- enable_feature(Feature::f, fd);
155
- enable_feature(Feature::d, fd);
156
- enable_feature(Feature::zicsr, fd); // implied by f
157
- enable_feature(Feature::c, ima_ext_0 & RISCV_HWPROBE_IMA_C != 0);
209
+ let ima_ext_0 = out[0].value;
210
+ // i, m, a, f, d, zicsr, and c extensions are detected by hwcap.
211
+ // let fd = ima_ext_0 & RISCV_HWPROBE_IMA_FD != 0;
212
+ // enable_feature(Feature::f, fd);
213
+ // enable_feature(Feature::d, fd);
214
+ // enable_feature(Feature::zicsr, fd); // implied by f
215
+ // enable_feature(Feature::c, ima_ext_0 & RISCV_HWPROBE_IMA_C != 0);
158
216
// enable_feature(Feature::zicboz, ima_ext_0 & RISCV_HWPROBE_EXT_ZICBOZ != 0);
159
217
enable_feature(Feature::zfh, ima_ext_0 & RISCV_HWPROBE_EXT_ZFH != 0);
160
218
enable_feature(Feature::zfhmin, ima_ext_0 & RISCV_HWPROBE_EXT_ZFHMIN != 0);
@@ -203,129 +261,64 @@ pub(crate) fn detect_features() -> cache::Initializer {
203
261
enable_feature(Feature::zkn, zkn);
204
262
// enable_feature(Feature::zk, zkn & zkr & zkt);
205
263
enable_feature(Feature::zks, zbkb & zbkc & zbkx & zksed & zksh);
206
- // Standard Vector Extensions
207
- enable_feature(Feature::v, ima_ext_0 & RISCV_HWPROBE_IMA_V != 0);
208
- enable_feature(Feature::zvfh, ima_ext_0 & RISCV_HWPROBE_EXT_ZVFH != 0);
209
- enable_feature(Feature::zvfhmin, ima_ext_0 & RISCV_HWPROBE_EXT_ZVFHMIN != 0);
210
- enable_feature(Feature::zve32x, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE32X != 0);
211
- enable_feature(Feature::zve32f, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE32F != 0);
212
- enable_feature(Feature::zve64x, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE64X != 0);
213
- enable_feature(Feature::zve64f, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE64F != 0);
214
- enable_feature(Feature::zve64d, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE64D != 0);
215
- // Vector Cryptography and Bit-manipulation Extensions
216
- let zvbb = ima_ext_0 & RISCV_HWPROBE_EXT_ZVBB != 0;
217
- enable_feature(Feature::zvbb, zvbb);
218
- let zvbc = ima_ext_0 & RISCV_HWPROBE_EXT_ZVBC != 0;
219
- enable_feature(Feature::zvbc, zvbc);
220
- let zvkb = zvbb || ima_ext_0 & RISCV_HWPROBE_EXT_ZVKB != 0;
221
- enable_feature(Feature::zvkb, zvkb);
222
- let zvkg = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKG != 0;
223
- enable_feature(Feature::zvkg, zvkg);
224
- let zvkned = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKNED != 0;
225
- enable_feature(Feature::zvkned, zvkned);
226
- enable_feature(Feature::zvknha, ima_ext_0 & RISCV_HWPROBE_EXT_ZVKNHA != 0);
227
- let zvknhb = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKNHB != 0;
228
- enable_feature(Feature::zvknhb, zvknhb);
229
- let zvksed = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKSED != 0;
230
- enable_feature(Feature::zvksed, zvksed);
231
- let zvksh = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKSH != 0;
232
- enable_feature(Feature::zvksh, zvksh);
233
- let zvkt = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKT != 0;
234
- enable_feature(Feature::zvkt, zvkt);
235
- let zvkn = zvkned & zvknhb & zvkb & zvkt;
236
- enable_feature(Feature::zvkn, zvkn);
237
- enable_feature(Feature::zvknc, zvkn & zvbc);
238
- enable_feature(Feature::zvkng, zvkn & zvkg);
239
- let zvks = zvksed & zvksh & zvkb & zvkt;
240
- enable_feature(Feature::zvks, zvks);
241
- enable_feature(Feature::zvksc, zvks & zvbc);
242
- enable_feature(Feature::zvksg, zvks & zvkg);
264
+ // Refer result from hwcap because it reflects Vector enablement status, unlike hwprobe.
265
+ // prctl(PR_RISCV_V_GET_CONTROL) is another way to check this but it is unavailable on
266
+ // qemu-user (as of 9.2.1).
267
+ // See https://docs.kernel.org/arch/riscv/vector.html for more.
268
+ if has_v {
269
+ // Standard Vector Extensions
270
+ // v and zve{32,64}* extensions are detected by hwcap.
271
+ // enable_feature(Feature::v, ima_ext_0 & RISCV_HWPROBE_IMA_V != 0);
272
+ enable_feature(Feature::zvfh, ima_ext_0 & RISCV_HWPROBE_EXT_ZVFH != 0);
273
+ enable_feature(Feature::zvfhmin, ima_ext_0 & RISCV_HWPROBE_EXT_ZVFHMIN != 0);
274
+ // enable_feature(Feature::zve32x, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE32X != 0);
275
+ // enable_feature(Feature::zve32f, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE32F != 0);
276
+ // enable_feature(Feature::zve64x, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE64X != 0);
277
+ // enable_feature(Feature::zve64f, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE64F != 0);
278
+ // enable_feature(Feature::zve64d, ima_ext_0 & RISCV_HWPROBE_EXT_ZVE64D != 0);
279
+ // Vector Cryptography and Bit-manipulation Extensions
280
+ let zvbb = ima_ext_0 & RISCV_HWPROBE_EXT_ZVBB != 0;
281
+ enable_feature(Feature::zvbb, zvbb);
282
+ let zvbc = ima_ext_0 & RISCV_HWPROBE_EXT_ZVBC != 0;
283
+ enable_feature(Feature::zvbc, zvbc);
284
+ let zvkb = zvbb || ima_ext_0 & RISCV_HWPROBE_EXT_ZVKB != 0;
285
+ enable_feature(Feature::zvkb, zvkb);
286
+ let zvkg = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKG != 0;
287
+ enable_feature(Feature::zvkg, zvkg);
288
+ let zvkned = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKNED != 0;
289
+ enable_feature(Feature::zvkned, zvkned);
290
+ enable_feature(Feature::zvknha, ima_ext_0 & RISCV_HWPROBE_EXT_ZVKNHA != 0);
291
+ let zvknhb = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKNHB != 0;
292
+ enable_feature(Feature::zvknhb, zvknhb);
293
+ let zvksed = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKSED != 0;
294
+ enable_feature(Feature::zvksed, zvksed);
295
+ let zvksh = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKSH != 0;
296
+ enable_feature(Feature::zvksh, zvksh);
297
+ let zvkt = ima_ext_0 & RISCV_HWPROBE_EXT_ZVKT != 0;
298
+ enable_feature(Feature::zvkt, zvkt);
299
+ let zvkn = zvkned & zvknhb & zvkb & zvkt;
300
+ enable_feature(Feature::zvkn, zvkn);
301
+ enable_feature(Feature::zvknc, zvkn & zvbc);
302
+ enable_feature(Feature::zvkng, zvkn & zvkg);
303
+ let zvks = zvksed & zvksh & zvkb & zvkt;
304
+ enable_feature(Feature::zvks, zvks);
305
+ enable_feature(Feature::zvksc, zvks & zvbc);
306
+ enable_feature(Feature::zvksg, zvks & zvkg);
307
+ }
243
308
}
244
- if out[2 ].key != -1 {
309
+ if out[1 ].key != -1 {
245
310
enable_feature(
246
311
Feature::unaligned_scalar_mem,
247
- out[2 ].value & RISCV_HWPROBE_MISALIGNED_MASK == RISCV_HWPROBE_MISALIGNED_FAST,
312
+ out[1 ].value & RISCV_HWPROBE_MISALIGNED_MASK == RISCV_HWPROBE_MISALIGNED_FAST,
248
313
);
249
314
}
250
- if out[3 ].key != -1 {
315
+ if out[2 ].key != -1 {
251
316
enable_feature(
252
317
Feature::unaligned_vector_mem,
253
- out[3 ].value == RISCV_HWPROBE_MISALIGNED_VECTOR_FAST,
318
+ out[2 ].value == RISCV_HWPROBE_MISALIGNED_VECTOR_FAST,
254
319
);
255
320
}
256
- // FIXME: should be enough with hwprobe only, but our code below checks e
257
- // unavailable in neither uapi/asm/hwprobe.h nor uapi/asm/hwcap.h.
258
- // https://github.com/torvalds/linux/blob/master/arch/riscv/include/uapi/asm/hwcap.h
259
- // return value;
260
321
}
261
322
262
- // FIXME: As said in the above FIXME, we currently alway checks auxv too.
263
- // // riscv_hwprobe requires Linux 6.4, so we fallback to auxv-based detection on
264
- // // old Linux kernel.
265
-
266
- let enable_feature = |value: &mut cache::Initializer, feature, enable| {
267
- if enable {
268
- value.set(feature as u32);
269
- }
270
- };
271
- let enable_features = |value: &mut cache::Initializer, feature_slice: &[Feature], enable| {
272
- if enable {
273
- for feature in feature_slice {
274
- value.set(*feature as u32);
275
- }
276
- }
277
- };
278
-
279
- // The values are part of the platform-specific [asm/hwcap.h][hwcap]
280
- //
281
- // [hwcap]: https://github.com/torvalds/linux/blob/master/arch/riscv/include/asm/hwcap.h
282
- //
283
- // Note that there is no need to check b'v' - b'a' here for the case where riscv_hwprobe is unsupported,
284
- // since both RISCV_HWPROBE_IMA_V and COMPAT_HWCAP_ISA_V are only supported on Linux 6.5+.
285
- // https://github.com/torvalds/linux/commit/162e4df137c1fea6557fda3e4cdf5dc6ca6d5510
286
- // https://github.com/torvalds/linux/commit/dc6667a4e7e36f283bcd0264a0be55adae4d6f86
287
- let auxv = auxvec::auxv().expect("read auxvec"); // should not fail on RISC-V platform
288
- #[allow(clippy::eq_op)]
289
- enable_feature(
290
- &mut value,
291
- Feature::a,
292
- bit::test(auxv.hwcap, (b'a' - b'a').into()),
293
- );
294
- enable_feature(
295
- &mut value,
296
- Feature::c,
297
- bit::test(auxv.hwcap, (b'c' - b'a').into()),
298
- );
299
- enable_features(
300
- &mut value,
301
- &[Feature::d, Feature::f, Feature::zicsr],
302
- bit::test(auxv.hwcap, (b'd' - b'a').into()),
303
- );
304
- enable_features(
305
- &mut value,
306
- &[Feature::f, Feature::zicsr],
307
- bit::test(auxv.hwcap, (b'f' - b'a').into()),
308
- );
309
- let has_i = bit::test(auxv.hwcap, (b'i' - b'a').into());
310
- // If future RV128I is supported, implement with `enable_feature` here
311
- // Checking target_pointer_width instead of target_arch is incorrect since
312
- // there are RV64ILP32* ABIs.
313
- #[cfg(target_arch = "riscv64")]
314
- enable_feature(&mut value, Feature::rv64i, has_i);
315
- #[cfg(target_arch = "riscv32")]
316
- enable_feature(&mut value, Feature::rv32i, has_i);
317
- // FIXME: e is not exposed in any of asm/hwcap.h, uapi/asm/hwcap.h, uapi/asm/hwprobe.h
318
- #[cfg(target_arch = "riscv32")]
319
- enable_feature(
320
- &mut value,
321
- Feature::rv32e,
322
- bit::test(auxv.hwcap, (b'e' - b'a').into()),
323
- );
324
- enable_feature(
325
- &mut value,
326
- Feature::m,
327
- bit::test(auxv.hwcap, (b'm' - b'a').into()),
328
- );
329
-
330
323
value
331
324
}
0 commit comments