riscvspike

why processor_t::egalize_privilege(ret_t prv) returns PRV_U if (prv == PRV_HS || (prv == PRV_S && !supports_extension('S')))


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;
}

Solution

  • 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).