@@ -1731,11 +1731,37 @@ 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);
1734+ if (proc->extension_enabled (EXT_SMSTATEEN)) {
1735+ if ((state->prv < PRV_M) &&
1736+ !(state->mstateen [0 ]->read () & MSTATEEN0_CSRIND))
1737+ throw trap_illegal_instruction (insn.bits ());
1738+
1739+ if (state->v && !(state->hstateen [0 ]->read () & HSTATEEN0_CSRIND))
1740+ throw trap_virtual_instruction (insn.bits ());
1741+ }
17351742 if (state->v )
17361743 virt_csr->verify_permissions (insn, write);
17371744 else
17381745 orig_csr->verify_permissions (insn, write);
1746+ virtualized_csr_t::verify_permissions (insn, write);
1747+ }
1748+
1749+ virtualized_select_indirect_csr_t ::virtualized_select_indirect_csr_t (processor_t *const proc,
1750+ csr_t_p orig,
1751+ csr_t_p virt)
1752+ : virtualized_csr_t (proc, orig, virt) {}
1753+
1754+ void virtualized_select_indirect_csr_t::verify_permissions (insn_t insn,
1755+ bool write) const {
1756+ if (proc->extension_enabled (EXT_SMSTATEEN)) {
1757+ if ((state->prv < PRV_M) &&
1758+ !(state->mstateen [0 ]->read () & MSTATEEN0_CSRIND))
1759+ throw trap_illegal_instruction (insn.bits ());
1760+
1761+ if (state->v && !(state->hstateen [0 ]->read () & HSTATEEN0_CSRIND))
1762+ throw trap_virtual_instruction (insn.bits ());
1763+ }
1764+ virtualized_csr_t::verify_permissions (insn, write);
17391765}
17401766
17411767sscsrind_reg_csr_t ::sscsrind_reg_csr_t (processor_t * const proc, const reg_t addr, csr_t_p iselect) :
@@ -1744,19 +1770,43 @@ sscsrind_reg_csr_t::sscsrind_reg_csr_t(processor_t* const proc, const reg_t addr
17441770}
17451771
17461772void 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);
1773+ auto csr_priv = get_field (insn.csr (), 0x300 );
1774+ bool is_vsi = csr_priv == PRV_HS;
1775+ // csr_priv checked due to mireg using the same class
1776+ if (csr_priv < PRV_M && state->prv < PRV_M){
1777+ // The CSRIND bit in mstateen0 controls access to the siselect, sireg*, vsiselect, and the vsireg*
1778+ // Stateen takes precedence over general sscsrind rules
1779+ if (proc->extension_enabled (EXT_SMSTATEEN)) {
1780+ const bool m_csrind = state->mstateen [0 ]->read () & MSTATEEN0_CSRIND;
1781+ const bool h_csrind = state->hstateen [0 ]->read () & HSTATEEN0_CSRIND;
1782+ if (!m_csrind)
1783+ throw trap_illegal_instruction (insn.bits ());
1784+
1785+ if (state->v && !h_csrind)
1786+ throw trap_virtual_instruction (insn.bits ());
1787+ }
1788+ }
1789+
1790+ // A virtual instruction exception is raised for attempts from VS-mode or VU-mode to directly access
1791+ // vsiselect or vsireg*, or attempts from VU-mode to access siselect or sireg*.
1792+ if (state->v and csr_priv < PRV_M){
1793+ if (is_vsi)
1794+ throw trap_virtual_instruction (insn.bits ());
1795+ else if (state->prv == PRV_U)
1796+ throw trap_virtual_instruction (insn.bits ());
1797+ }
17501798
17511799 csr_t_p proxy_csr = get_reg ();
17521800 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- }
1801+ // The spec recomends raising illegal if the proxy csr is not implemented.
1802+ throw trap_illegal_instruction (insn.bits ());
17581803 }
17591804 proxy_csr->verify_permissions (insn, write);
1805+
1806+ // Don't call base verify_permission for VS registers remapped to S-mode
1807+ if (insn.csr () == address)
1808+ csr_t::verify_permissions (insn, write);
1809+
17601810}
17611811
17621812
@@ -1777,6 +1827,36 @@ bool sscsrind_reg_csr_t::unlogged_write(const reg_t val) noexcept {
17771827}
17781828
17791829// Returns the actual CSR that maps to value in *siselect or nullptr if no mapping exists
1830+ sscsrind_select_csr_t ::sscsrind_select_csr_t (processor_t *const proc, const reg_t addr,
1831+ const reg_t init)
1832+ : basic_csr_t (proc, addr, init) {}
1833+
1834+ void sscsrind_select_csr_t::verify_permissions (insn_t insn, bool write) const {
1835+ const auto csr_priv = get_field (insn.csr (), 0x300 );
1836+ const bool is_vsi = csr_priv == PRV_HS;
1837+ // The CSRIND bit in mstateen0 controls access to the siselect, sireg*, vsiselect, and the vsireg*
1838+ if (proc->extension_enabled (EXT_SMSTATEEN) && state->prv < PRV_M) {
1839+ const bool m_csrind = state->mstateen [0 ]->read () & MSTATEEN0_CSRIND;
1840+ const bool h_csrind = state->hstateen [0 ]->read () & HSTATEEN0_CSRIND;
1841+ if (!m_csrind)
1842+ throw trap_illegal_instruction (insn.bits ());
1843+
1844+ if (state->v && !h_csrind)
1845+ throw trap_virtual_instruction (insn.bits ());
1846+ }
1847+ // A virtual instruction exception is raised for attempts from VS-mode or VU-mode to directly access
1848+ // vsiselect or vsireg*, or attempts from VU-mode to access siselect or sireg*.
1849+ if (state->v ){
1850+ if (is_vsi){
1851+ throw trap_virtual_instruction (insn.bits ());
1852+ } else if (state->prv == PRV_U)
1853+ throw trap_virtual_instruction (insn.bits ());
1854+ }
1855+ basic_csr_t::verify_permissions (insn, write);
1856+ };
1857+
1858+ // Returns the actual CSR that maps to value in *siselect or nullptr if no
1859+ // mapping exists
17801860csr_t_p sscsrind_reg_csr_t::get_reg () const noexcept {
17811861 auto proxy = ireg_proxy;
17821862 auto isel = iselect->read ();
0 commit comments