RISC-V: Remove enable_features

This commit prepares common infrastructure for extension implication by
removing `enable_features` closure which makes each feature test longer
(because it needs extra `value` argument each time we test a feature).

It comes with the overhead to enable each feature separately but later
mitigated by the OS-independent extension implication logic.
This commit is contained in:
Tsukasa OI 2025-04-11 01:13:44 +00:00 committed by Amanieu d'Antras
parent 5c0c7ac77c
commit 2759545fda

View file

@ -6,18 +6,11 @@ use crate::detect::{Feature, bit, cache};
/// Read list of supported features from the auxiliary vector.
pub(crate) fn detect_features() -> cache::Initializer {
let mut value = cache::Initializer::default();
let enable_feature = |value: &mut cache::Initializer, feature, enable| {
let mut enable_feature = |feature, enable| {
if enable {
value.set(feature as u32);
}
};
let enable_features = |value: &mut cache::Initializer, feature_slice: &[Feature], enable| {
if enable {
for feature in feature_slice {
value.set(*feature as u32);
}
}
};
// Use auxiliary vector to enable single-letter ISA extensions and Zicsr.
// The values are part of the platform-specific [asm/hwcap.h][hwcap]
@ -25,51 +18,26 @@ pub(crate) fn detect_features() -> cache::Initializer {
// [hwcap]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/include/uapi/asm/hwcap.h?h=v6.14
let auxv = auxvec::auxv().expect("read auxvec"); // should not fail on RISC-V platform
#[allow(clippy::eq_op)]
enable_feature(
&mut value,
Feature::a,
bit::test(auxv.hwcap, (b'a' - b'a').into()),
);
enable_feature(
&mut value,
Feature::c,
bit::test(auxv.hwcap, (b'c' - b'a').into()),
);
enable_features(
&mut value,
&[Feature::d, Feature::f, Feature::zicsr],
bit::test(auxv.hwcap, (b'd' - b'a').into()),
);
enable_features(
&mut value,
&[Feature::f, Feature::zicsr],
bit::test(auxv.hwcap, (b'f' - b'a').into()),
);
enable_feature(
&mut value,
Feature::h,
bit::test(auxv.hwcap, (b'h' - b'a').into()),
);
enable_feature(
&mut value,
Feature::m,
bit::test(auxv.hwcap, (b'm' - b'a').into()),
);
enable_feature(Feature::a, bit::test(auxv.hwcap, (b'a' - b'a').into()));
enable_feature(Feature::c, bit::test(auxv.hwcap, (b'c' - b'a').into()));
let has_d = bit::test(auxv.hwcap, (b'd' - b'a').into());
let has_f = bit::test(auxv.hwcap, (b'f' - b'a').into());
enable_feature(Feature::d, has_d);
enable_feature(Feature::f, has_d | has_f);
enable_feature(Feature::zicsr, has_d | has_f);
enable_feature(Feature::h, bit::test(auxv.hwcap, (b'h' - b'a').into()));
enable_feature(Feature::m, bit::test(auxv.hwcap, (b'm' - b'a').into()));
// Handle base ISA.
let has_i = bit::test(auxv.hwcap, (b'i' - b'a').into());
// If future RV128I is supported, implement with `enable_feature` here
#[cfg(target_pointer_width = "64")]
enable_feature(&mut value, Feature::rv64i, has_i);
enable_feature(Feature::rv64i, has_i);
#[cfg(target_pointer_width = "32")]
enable_feature(&mut value, Feature::rv32i, has_i);
enable_feature(Feature::rv32i, has_i);
// FIXME: e is not exposed in any of asm/hwcap.h, uapi/asm/hwcap.h, uapi/asm/hwprobe.h
#[cfg(target_pointer_width = "32")]
enable_feature(
&mut value,
Feature::rv32e,
bit::test(auxv.hwcap, (b'e' - b'a').into()),
);
enable_feature(Feature::rv32e, bit::test(auxv.hwcap, (b'e' - b'a').into()));
// FIXME: Auxvec does not show supervisor feature support, but this mode may be useful
// to detect when Rust is used to write Linux kernel modules.