@@ -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