I cannot understand source code in legalize_privilege() shown below:
reg_t processor_t::legalize_privilege(reg_t prv)
{
if (!supports_extension('U'))
return PRV_M;
if (prv == PRV_HS || (prv == PRV_S && !supports_extension('S')))
return PRV_U;
//according to my understanding, HS mode actually works in Supervisor mode. So PRV_S should be returned here.
return prv;
}
PRV_HS
is only used as a dummy privilege level within the simulator for CSR permission checks.
In the H-extension specification, HS-mode takes the place of S-mode (level 1
).
The integer value 2
is used for PRV_HS
to distinguish it from PRV_S
, but that is a reserved value in the RISC-V Privileged Architecture (ISA Manual Vol. 2 § 1.2 Privilege Levels) and not used by the H-extension.
It is therefore illegal to actually set this mode. To set either HS- or S-mode, always use PRV_S
.
In the same condition, you can also see that it is illegal to set S-mode if the S-extension is not supported.
Both of these cases are illegal, so the privilege level is instead forced to the lowest level, which is PRV_U
.
The only use of PRV_HS
is in the permission check segment of processor_t::get_csr
(here), where it is used instead of PRV_S
if the processor is not in a virtual state (as set by processor_t::set_virt
), to permit access to Hypervisor CSRs.
This is because the CSR address encodes the minimum privilege level required for access in bits [9:8], which is defined as 10b = 2
for Hypervisor CSRs, even though there is no such distinct privilege level (ISA Manual Vol. 2 § 2.1 CSR Address Mapping Conventions).