@@ -1731,11 +1731,37 @@ virtualized_indirect_csr_t::virtualized_indirect_csr_t(processor_t* const proc,
1731
1731
}
1732
1732
1733
1733
void 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
+ }
1735
1742
if (state->v )
1736
1743
virt_csr->verify_permissions (insn, write );
1737
1744
else
1738
1745
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 );
1739
1765
}
1740
1766
1741
1767
sscsrind_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
1744
1770
}
1745
1771
1746
1772
void 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
+ }
1750
1798
1751
1799
csr_t_p proxy_csr = get_reg ();
1752
1800
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 ());
1758
1803
}
1759
1804
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
+
1760
1810
}
1761
1811
1762
1812
@@ -1777,6 +1827,36 @@ bool sscsrind_reg_csr_t::unlogged_write(const reg_t val) noexcept {
1777
1827
}
1778
1828
1779
1829
// 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
1780
1860
csr_t_p sscsrind_reg_csr_t::get_reg () const noexcept {
1781
1861
auto proxy = ireg_proxy;
1782
1862
auto isel = iselect->read ();
0 commit comments