Question about `senvcfg` and `henvcfg` when V=1
lfiolhais opened this issue · 2 comments
Hi,
Apologies if this is a duplicated question or an already answer question. I tried to search both the specification, and the closed and open issues of the repo and couldn't find anything.
I'm a bit confused regarding the usage of the CSRs senvcfg
and henvcfg
when the hart is in V=1 mode.
The H extensions states (as of Release riscv-isa-release-3f725b5-2024-05-31)
Some standard supervisor CSRs (senvcfg, scounteren, and scontext, possibly others) have no matching VS CSR. These supervisor CSRs continue to have their usual function and accessibility even when V=1, except with VS-mode and VU-mode substituting for HS-mode and U-mode. Hypervisor software is expected to manually swap the contents of these registers as needed.
However, H defines a henvcfg
which should be used when V=1
The henvcfg CSR is a 64-bit read/write register, formatted as shown in Figure 82, that controls certain
characteristics of the execution environment when virtualization mode V=1.
Since senvcfg
and henvcfg
can be used when V=1, which should in fact be used for the execution environment? I first assumed that henvcfg
had precedence over the definition of senvcfg
when V=1, i.e., when V=1 the execution context is taken from henvcfg
. With the text in the H extension, it leads to me believe that there are cases where henvcfg
is overridden by senvcfg
when V=1 and priv=U (or possibly other privilege mode and virtualization combinations?).
Let's consider the that the hart implementes bit FIOM
in all *envcfg. Is this the correct behavior for FIOM
? P is the privilege and V is the virtualization enable.
- P = S & V = 0 => FIOM = menvcfg.fiom
- P = U & V = 0 => FIOM = senvcfg.fiom
- P = S & V = 1 (really VS) => FIOM = henvcfg.fiom
- P = U & V = 1 (really VU) => FIOM = senvcfg.fiom (?)
Consider these three statements from the spec literally:
"If bit FIOM is set to one in menvcfg, FENCE instructions executed in modes less privileged than M are modified [...]."
"If bit FIOM is set to one in henvcfg, FENCE instructions executed when V=1 are modified [...]."
"If bit FIOM is set to one in senvcfg, FENCE instructions executed in U-mode are modified [...]."
Note there's no statement that FIOM being set to zero in menvcfg or henvcfg suppresses this behavior: there's only a statement that it being set to one engages it. So each of those statements is sufficient (but not necessary) to engage the behavior.
As for VU-mode, there is a blanket statement makes senvcfg apply to VU-mode:
riscv-isa-manual/src/hypervisor.adoc
Line 140 in ad0a305
Taken together, we get:
[H]S-mode FIOM = menvcfg.FIOM
U-mode FIOM = menvcfg.FIOM || senvcfg.FIOM
VS-mode FIOM = menvcfg.FIOM || henvcfg.FIOM
VU-mode FIOM = menvcfg.FIOM || henvcfg.FIOM || senvcfg.FIOM
Got it. That clarifies it. Thanks!