@@ -1731,11 +1731,29 @@ virtualized_indirect_csr_t::virtualized_indirect_csr_t(processor_t* const proc,
17311731}
17321732
17331733void virtualized_indirect_csr_t::verify_permissions (insn_t insn, bool write) const {
1734- virtualized_csr_t::verify_permissions (insn, write);
17351734 if (state->v )
17361735 virt_csr->verify_permissions (insn, write);
17371736 else
17381737 orig_csr->verify_permissions (insn, write);
1738+ virtualized_csr_t::verify_permissions (insn, write);
1739+ }
1740+
1741+ virtualized_select_indirect_csr_t ::virtualized_select_indirect_csr_t (processor_t *const proc,
1742+ csr_t_p orig,
1743+ csr_t_p virt)
1744+ : virtualized_csr_t (proc, orig, virt) {}
1745+
1746+ void virtualized_select_indirect_csr_t::verify_permissions (insn_t insn,
1747+ bool write) const {
1748+ if (proc->extension_enabled (EXT_SMSTATEEN)) {
1749+ if ((state->prv < PRV_M) &&
1750+ !(state->mstateen [0 ]->read () & MSTATEEN0_CSRIND))
1751+ throw trap_illegal_instruction (insn.bits ());
1752+
1753+ if (state->v && !(state->hstateen [0 ]->read () & HSTATEEN0_CSRIND))
1754+ throw trap_virtual_instruction (insn.bits ());
1755+ }
1756+ virtualized_csr_t::verify_permissions (insn, write);
17391757}
17401758
17411759sscsrind_reg_csr_t ::sscsrind_reg_csr_t (processor_t * const proc, const reg_t addr, csr_t_p iselect) :
@@ -1744,19 +1762,43 @@ sscsrind_reg_csr_t::sscsrind_reg_csr_t(processor_t* const proc, const reg_t addr
17441762}
17451763
17461764void sscsrind_reg_csr_t::verify_permissions (insn_t insn, bool write) const {
1747- // Don't call base verify_permission for VS registers remapped to S-mode
1748- if (insn.csr () == address)
1749- csr_t::verify_permissions (insn, write);
1765+ const auto csr_priv = get_field (insn.csr (), 0x300 );
1766+ const bool is_vsi = csr_priv == PRV_HS;
1767+ // csr_priv checked due to mireg using the same class
1768+ if (csr_priv < PRV_M && state->prv < PRV_M){
1769+ // The CSRIND bit in mstateen0 controls access to the siselect, sireg*, vsiselect, and the vsireg*
1770+ // Stateen takes precedence over general sscsrind rules
1771+ if (proc->extension_enabled (EXT_SMSTATEEN)) {
1772+ const bool m_csrind = state->mstateen [0 ]->read () & MSTATEEN0_CSRIND;
1773+ const bool h_csrind = state->hstateen [0 ]->read () & HSTATEEN0_CSRIND;
1774+ if (!m_csrind)
1775+ throw trap_illegal_instruction (insn.bits ());
1776+
1777+ if (state->v && !h_csrind)
1778+ throw trap_virtual_instruction (insn.bits ());
1779+ }
1780+ }
1781+
1782+ // A virtual instruction exception is raised for attempts from VS-mode or VU-mode to directly access
1783+ // vsiselect or vsireg*, or attempts from VU-mode to access siselect or sireg*.
1784+ if (state->v and csr_priv < PRV_M){
1785+ if (is_vsi)
1786+ throw trap_virtual_instruction (insn.bits ());
1787+ else if (state->prv == PRV_U)
1788+ throw trap_virtual_instruction (insn.bits ());
1789+ }
17501790
17511791 csr_t_p proxy_csr = get_reg ();
17521792 if (proxy_csr == nullptr ) {
1753- if (!state->v ) {
1754- throw trap_illegal_instruction (insn.bits ());
1755- } else {
1756- throw trap_virtual_instruction (insn.bits ());
1757- }
1793+ // The spec recomends raising illegal if the proxy csr is not implemented.
1794+ throw trap_illegal_instruction (insn.bits ());
17581795 }
17591796 proxy_csr->verify_permissions (insn, write);
1797+
1798+ // Don't call base verify_permission for VS registers remapped to S-mode
1799+ if (insn.csr () == address)
1800+ csr_t::verify_permissions (insn, write);
1801+
17601802}
17611803
17621804
@@ -1777,6 +1819,36 @@ bool sscsrind_reg_csr_t::unlogged_write(const reg_t val) noexcept {
17771819}
17781820
17791821// Returns the actual CSR that maps to value in *siselect or nullptr if no mapping exists
1822+ sscsrind_select_csr_t ::sscsrind_select_csr_t (processor_t *const proc, const reg_t addr,
1823+ const reg_t init)
1824+ : basic_csr_t (proc, addr, init) {}
1825+
1826+ void sscsrind_select_csr_t::verify_permissions (insn_t insn, bool write) const {
1827+ const auto csr_priv = get_field (insn.csr (), 0x300 );
1828+ const bool is_vsi = csr_priv == PRV_HS;
1829+ // The CSRIND bit in mstateen0 controls access to the siselect, sireg*, vsiselect, and the vsireg*
1830+ if (proc->extension_enabled (EXT_SMSTATEEN) && state->prv < PRV_M) {
1831+ const bool m_csrind = state->mstateen [0 ]->read () & MSTATEEN0_CSRIND;
1832+ const bool h_csrind = state->hstateen [0 ]->read () & HSTATEEN0_CSRIND;
1833+ if (!m_csrind)
1834+ throw trap_illegal_instruction (insn.bits ());
1835+
1836+ if (state->v && !h_csrind)
1837+ throw trap_virtual_instruction (insn.bits ());
1838+ }
1839+ // A virtual instruction exception is raised for attempts from VS-mode or VU-mode to directly access
1840+ // vsiselect or vsireg*, or attempts from VU-mode to access siselect or sireg*.
1841+ if (state->v ){
1842+ if (is_vsi){
1843+ throw trap_virtual_instruction (insn.bits ());
1844+ } else if (state->prv == PRV_U)
1845+ throw trap_virtual_instruction (insn.bits ());
1846+ }
1847+ basic_csr_t::verify_permissions (insn, write);
1848+ };
1849+
1850+ // Returns the actual CSR that maps to value in *siselect or nullptr if no
1851+ // mapping exists
17801852csr_t_p sscsrind_reg_csr_t::get_reg () const noexcept {
17811853 auto proxy = ireg_proxy;
17821854 auto isel = iselect->read ();
@@ -1878,3 +1950,31 @@ bool hstatus_csr_t::unlogged_write(const reg_t val) noexcept {
18781950 proc->get_mmu ()->flush_tlb ();
18791951 return basic_csr_t::unlogged_write (new_hstatus);
18801952}
1953+
1954+ scontext_csr_t ::scontext_csr_t (processor_t * const proc, const reg_t addr, const reg_t mask, const reg_t init) :
1955+ masked_csr_t(proc, addr, mask, init){};
1956+ void scontext_csr_t::verify_permissions (insn_t insn, bool write) const {
1957+ if (proc->extension_enabled (EXT_SMSTATEEN)) {
1958+ if ((state->prv < PRV_M) &&
1959+ !(state->mstateen [0 ]->read () & MSTATEEN0_HCONTEXT))
1960+ throw trap_illegal_instruction (insn.bits ());
1961+
1962+ if (state->v && !(state->hstateen [0 ]->read () & HSTATEEN0_SCONTEXT))
1963+ throw trap_virtual_instruction (insn.bits ());
1964+ }
1965+ masked_csr_t::verify_permissions (insn, write);
1966+
1967+ }
1968+
1969+ hcontext_csr_t ::hcontext_csr_t (processor_t * const proc, const reg_t addr, const reg_t mask, const reg_t init) :
1970+ masked_csr_t (proc, addr, mask, init){};
1971+ void hcontext_csr_t::verify_permissions (insn_t insn, bool write) const {
1972+ if (proc->extension_enabled (EXT_SMSTATEEN)) {
1973+ if ((state->prv < PRV_M) &&
1974+ !(state->mstateen [0 ]->read () & MSTATEEN0_HCONTEXT))
1975+ throw trap_illegal_instruction (insn.bits ());
1976+
1977+ }
1978+ masked_csr_t::verify_permissions (insn, write);
1979+
1980+ }
0 commit comments