Skip to content

Commit 2e09850

Browse files
a4lgAmanieu
authored andcommitted
std_detect: RISC-V Linux: Ergonomic querying with riscv_hwprobe
Originally, we used an array of `riscv_hwprobe` directly and indexed using raw numbers, making correspondence between the index and the query key less obvious. We also frequently used `out[idx].key != -1` to test whether the key is supported by the `riscv_hwprobe` system call (on the Linux kernel version we are testing) but we'd better to integrate with an operation to retrieve the value. This commit improves the ergonomics of feature querying by: 1. Utilizing macros to a. enable indexing by identifier names and b. encapsulate accesses to the `riscv_hwprobe` array to query and 2. New method `riscv_hwprobe::get()` returning `Option<u64>`, integrating availability checking and value retrieval. It also removes `has_ima` for now because it's redundant if we only need to test for single base behavior.
1 parent 29e37bd commit 2e09850

File tree

1 file changed

+42
-41
lines changed
  • crates/std_detect/src/detect/os/linux

1 file changed

+42
-41
lines changed

crates/std_detect/src/detect/os/linux/riscv.rs

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ struct riscv_hwprobe {
2525
value: u64,
2626
}
2727

28+
impl riscv_hwprobe {
29+
// key is overwritten to -1 if not supported by riscv_hwprobe syscall.
30+
pub fn get(&self) -> Option<u64> {
31+
(self.key != -1).then_some(self.value)
32+
}
33+
}
34+
2835
#[allow(non_upper_case_globals)]
2936
const __NR_riscv_hwprobe: libc::c_long = 258;
3037

@@ -155,49 +162,45 @@ pub(crate) fn detect_features() -> cache::Initializer {
155162
// Use riscv_hwprobe syscall to query more extensions and
156163
// performance-related capabilities.
157164
'hwprobe: {
158-
let mut out = [
159-
riscv_hwprobe {
160-
key: RISCV_HWPROBE_KEY_BASE_BEHAVIOR,
161-
value: 0,
162-
},
163-
riscv_hwprobe {
164-
key: RISCV_HWPROBE_KEY_IMA_EXT_0,
165-
value: 0,
166-
},
167-
riscv_hwprobe {
168-
key: RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF,
169-
value: 0,
170-
},
171-
riscv_hwprobe {
172-
key: RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF,
173-
value: 0,
174-
},
175-
riscv_hwprobe {
176-
key: RISCV_HWPROBE_KEY_CPUPERF_0,
177-
value: 0,
178-
},
179-
];
180-
if !_riscv_hwprobe(&mut out) {
165+
macro_rules! init {
166+
{ $($name: ident : $key: expr),* $(,)? } => {
167+
#[repr(usize)]
168+
enum Indices { $($name),* }
169+
let mut t = [$(riscv_hwprobe { key: $key, value: 0 }),*];
170+
macro_rules! data_mut { () => { &mut t } }
171+
macro_rules! query { [$idx: ident] => { t[Indices::$idx as usize].get() } }
172+
}
173+
}
174+
init! {
175+
BaseBehavior: RISCV_HWPROBE_KEY_BASE_BEHAVIOR,
176+
Extensions: RISCV_HWPROBE_KEY_IMA_EXT_0,
177+
MisalignedScalarPerf: RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF,
178+
MisalignedVectorPerf: RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF,
179+
MisalignedScalarPerfFallback: RISCV_HWPROBE_KEY_CPUPERF_0,
180+
};
181+
if !_riscv_hwprobe(data_mut!()) {
181182
break 'hwprobe;
182183
}
183184

184-
// Query scalar/vector misaligned behavior.
185-
if out[2].key != -1 {
185+
// Query scalar misaligned behavior.
186+
if let Some(value) = query![MisalignedScalarPerf] {
186187
enable_feature(
187188
Feature::unaligned_scalar_mem,
188-
out[2].value == RISCV_HWPROBE_MISALIGNED_SCALAR_FAST,
189+
value == RISCV_HWPROBE_MISALIGNED_SCALAR_FAST,
189190
);
190-
} else if out[4].key != -1 {
191+
} else if let Some(value) = query![MisalignedScalarPerfFallback] {
191192
// Deprecated method for fallback
192193
enable_feature(
193194
Feature::unaligned_scalar_mem,
194-
out[4].value & RISCV_HWPROBE_MISALIGNED_MASK == RISCV_HWPROBE_MISALIGNED_FAST,
195+
value & RISCV_HWPROBE_MISALIGNED_MASK == RISCV_HWPROBE_MISALIGNED_FAST,
195196
);
196197
}
197-
if out[3].key != -1 {
198+
199+
// Query vector misaligned behavior.
200+
if let Some(value) = query![MisalignedVectorPerf] {
198201
enable_feature(
199202
Feature::unaligned_vector_mem,
200-
out[3].value == RISCV_HWPROBE_MISALIGNED_VECTOR_FAST,
203+
value == RISCV_HWPROBE_MISALIGNED_VECTOR_FAST,
201204
);
202205
}
203206

@@ -207,22 +210,20 @@ pub(crate) fn detect_features() -> cache::Initializer {
207210
// 20240411).
208211
// This is a current requirement of
209212
// `RISCV_HWPROBE_KEY_IMA_EXT_0`-based tests.
210-
let has_ima = (out[0].key != -1) && (out[0].value & RISCV_HWPROBE_BASE_BEHAVIOR_IMA != 0);
211-
if !has_ima {
213+
if query![BaseBehavior].is_none_or(|value| value & RISCV_HWPROBE_BASE_BEHAVIOR_IMA == 0) {
212214
break 'hwprobe;
213215
}
214-
has_i |= has_ima;
215-
enable_feature(Feature::zicsr, has_ima);
216-
enable_feature(Feature::zicntr, has_ima);
217-
enable_feature(Feature::zifencei, has_ima);
218-
enable_feature(Feature::m, has_ima);
219-
enable_feature(Feature::a, has_ima);
216+
has_i = true;
217+
enable_feature(Feature::zicsr, true);
218+
enable_feature(Feature::zicntr, true);
219+
enable_feature(Feature::zifencei, true);
220+
enable_feature(Feature::m, true);
221+
enable_feature(Feature::a, true);
220222

221223
// Enable features based on `RISCV_HWPROBE_KEY_IMA_EXT_0`.
222-
if out[1].key == -1 {
224+
let Some(ima_ext_0) = query![Extensions] else {
223225
break 'hwprobe;
224-
}
225-
let ima_ext_0 = out[1].value;
226+
};
226227
let test = |mask| (ima_ext_0 & mask) != 0;
227228

228229
enable_feature(Feature::d, test(RISCV_HWPROBE_IMA_FD)); // F is implied.

0 commit comments

Comments
 (0)