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.
We don't need to put the length of the `riscv_hwprobe` array into a
variable. This commit removes that variable and gives the length
of the output slice to the `__riscv_hwprobe` directly.
Since [1], this will come automatically from `rustc-std-workspace-core`
and the crates.io dependency should no longer be specified.
[1]: https://github.com/rust-lang/rust/pull/141993
This commit adds support for `riscv_hwprobe` on the Linux kernel 6.15.
It adds feature detection of 8 extensions (4 of them are new in this).
Existing RISC-V Extensions:
1. "Zicntr"
2. "Zihpm"
3. "Zalrsc"
4. "Zaamo"
New RISC-V Extensions:
5. "Zicbom"
6. "Zfbfmin"
7. "Zvfbfmin"
8. "Zvfbfwma"
As the author confirmed as in:
<https://lists.infradead.org/pipermail/linux-riscv/2025-May/070844.html>,
runtime detection of the Zicntr extension (as in the Linux kernel 6.15)
is currently (and technically) redundant on the current base IMA behavior
(although can be meaningful if new base behavior is added).
This commit implies the Zicntr extension from the base IMA behavior.
This reverts commit e907456b2e10622ccd854a3bba8d02ce170b5dbb.
This is due to a CI failure (technically broken HTML with duplicate IDs)
caused by this commit (visibly fine but invalid per the HTML specification
and detected by the LinkCheck tool on the Rust CI process).
The author independently working on a rustdoc enhancement to enable writing
multiple references to a single footnote. Once that change makes it to the
stage0 compiler (the next beta), the original change will be acceptable
again (postponed for possibly the version 1.89 cycle).
Since there's no architectural feature detection on RISC-V (unlike `CPUID`
on x86 architectures and some system registers on Arm/AArch64), runtime
feature detection entirely depends on the platform-specific facility.
As a result, availability of each feature heavily depends on the platform
and its version.
To help users make a decision for feature checking on a RISC-V system, this
commit adds a platform guide with minimum supported platform versions.
Note:
It intentionally omits the description of the reverse implication related
to *extension groups* (such like implication of `B` *from* its members:
`Zba`, `Zbb` and `Zbs` extensions) because it currently does not synchronize
well with the `-Ctarget-feature` compiler option (due to missing reverse
implication checks using `cfg` and due to constraints of the current Rust's
feature handling).
Instead, it only describes forward implications (like `D` implying `F`) due
to the fact that it relatively synchronizes well between Rust and `stdarch`
for this kind of feature handling (not fully synchronized though).
Still, an extension group is considered "supported" once the
platform/version supports runtime detection of all members in it.
Because the current lowest requirements to run the Linux kernel on RISC-V is
RV{32,64}IMA (with 32 general purpose registers) plus some features,
RV32E (with only 16 GPRs) is not currently supported.
Since it's not sure whether current implemented method will work for future
Linux versions even if the minimum requirements are lowered, the support for
RV32E (to be more specific, an attempt to do that) is removed for now.
Until in-kernel feature detection is implemented, runtime detection of
privileged extensions is temporally removed along with features themselves
since none of such privileged features are stable.
Co-Authored-By: Taiki Endo <te316e89@gmail.com>
Co-Authored-By: Amanieu d'Antras <amanieu@gmail.com>
This commit implements `riscv_hwprobe`-based feature detection as available
on newer versions of the Linux kernel. It also queries whether the vector
extensions are enabled using `prctl` but this is not supported on QEMU's
userland emulator (as of version 9.2.3) and use the auxiliary vector
as a fallback.
Currently, all extensions discoverable from the Linux kernel version 6.14
and related extension groups (except "Supm", which reports the existence of
`prctl`-based pointer masking control and too OS-dependent) are implemented.
Co-Authored-By: Taiki Endo <te316e89@gmail.com>
This commit adds the OS-independent extension implication logic for RISC-V.
It implements:
1. Regular implication (A → B)
a. "the extension A implies the extension B"
b. "the extension A requires the extension B"
c. "the extension A depends on the extension B"
2. Extension group or shorthand (A == B1 & B2...)
a. "the extension A is shorthand for other extensions: B1, B2..."
b. "the extension A comprises instructions provided by B1, B2..."
This is implemented as (A → B1 & B2... + B1 & B2... → A)
where the former is a regular implication as required by specifications
and the latter is a "reverse" implication to improve usability.
and prepares for:
3. Implication with multiple requirements (A1 & A2... → B)
a. "A1 + A2 implies B"
b. (implicitly used to implement reverse implication of case 2)
Although it uses macros and iterators, good optimizers turn the series of
implications into fast bit-manipulation operations.
In the case 2 (extension group or shorthand; where a superset extension
is just a collection of other subextensions and provides no features by
a superset itself), specifications do specify that an extension group
implies its members but not vice versa. However, implying an extension
group from its members would improve usability on the feature detection
(especially when the feature provider does not provide existence of such
extension group but provides existence of its members).
Similar "reverse implication" on RISC-V is implemented on LLVM.
Case 3 is implicitly used to implement reverse implication of case 2 but
there's another use case: implication with multiple requirements like
"Zcf" and "Zcd" extensions (not yet implemented in this crate for now).
To handle extension groups perfectly, we need to loop implication several
times (until they converge; normally 2 times and up to 4 times when we add
most of `riscv_hwprobe`-based features).
To make implementation of that loop possible, `cache::Initializer` is
modified to implement `PartialEq` and `Eq`.
This is ported from Taiki Endo's branch and sorted by the `@FEATURE` order
as in `src/detect/arch/riscv.rs`.
Co-Authored-By: Taiki Endo <te316e89@gmail.com>
The "B" extension is once abandoned (instead, it is ratified as a collection
of "Zb*" extensions). However, it is later redefined and ratified as a
superset of "Zba", "Zbb" and "Zbs" extensions (but not "Zbc" carry-less
multiplication for limited benefits and implementation cost).
Although non-functional (because feature detection is not yet implemented),
it provides the foundation to implement this extension (along with
straightforward documentation showing subsets of "B").
The "A" extension comprises instructions provided by the "Zaamo" and
"Zalrsc" extensions. To prepare for the "Zacas" extension (which provides
compare-and-swap instructions and discoverable from Linux) which depends on
the "Zaamo" extension, it would be better to support those subsets.
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.
Because this function will be no longer auxvec-only, this commit adds a
comment to mark auxvec-based part.
It *does not* add a comment to "base ISA" part because it may also use
`riscv_hwprobe`-based results.
1. Use canonical kernel.org repository instead of the GitHub mirror.
2. Refer to the fixed commit to guarantee access.
3. Use `uapi` part to ensure that the feature detection is primarily
intended for user-mode programs.
The author intended to split:
1. Former "I" extensions
2. Other "I"-related extensions
but incorrectly separated between "Zihpm" (a supplement of "Zicntr" which is
a former "I" extension) and "Zifencei" (a former "I" extension) while the
author intended making a separation between "Zifencei" and "Zihintpause"
(not a part of "I").
This commit fixes the separation.
Not only moving the link to the end of the section, this commit changes
the link so that we can reach to the *ratified* ISA manuals (note that,
while the original URL (GitHub) is a good place to browse the latest
draft, it's not easy to know which is the ratified version; even
"Releases" page is not helpful since it's regularly updated).
Some extensions are ratified at least on the ISA specification version
20240411. This commit moves such extensions.
This commit also changes that:
1. Lower indentation of "Zk*" and "Zbk*" extensions to avoid extension
groups from being misleading inside this section.
2. Raise indentation of "Zfhmin" and "Zhinxmin" extensions to show that
they are a strict subset of "Zfh" and "Zhinx" (respectively).
3. Clarify that "s" is not an extension but a feature notifying
the existence of the supervisor-level ISA.
4. Clarify that "h" is not just an existence of the hypervisor-level ISA
but is also an extension name ("H").
rust-lang/rust#138823 added five new extensions as compiler target features.
This commit reflects that fact and now checks static target features on
`std::arch::is_riscv_feature_detected!` as well.
* "Zicsr"
* "Zicntr"
* "Zihpm"
* "Zifencei"
* "Zihintpause"
Although the "B" extension is redefined and ratified, keeping this in the
documentation as-is have two issues:
* "B" extension is not added to `riscv.rs` yet (to be added later).
* "B" extension is ratified as a combination of "Zba", "Zbb" and "Zbs"
extensions and "Zbc" is *not* a part of "B" itself (despite that
it is listed under "B"), which makes the documentation misleading.
This commit tentatively removes the reference to the "B" extension and
replaced with "Bit Manipulation Extensions" without an extension name.