@@ -1731,11 +1731,29 @@ 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);
1735
1734
if (state->v )
1736
1735
virt_csr->verify_permissions (insn, write);
1737
1736
else
1738
1737
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);
1739
1757
}
1740
1758
1741
1759
sscsrind_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
1744
1762
}
1745
1763
1746
1764
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);
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
+ }
1750
1790
1751
1791
csr_t_p proxy_csr = get_reg ();
1752
1792
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 ());
1758
1795
}
1759
1796
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
+
1760
1802
}
1761
1803
1762
1804
@@ -1777,6 +1819,36 @@ bool sscsrind_reg_csr_t::unlogged_write(const reg_t val) noexcept {
1777
1819
}
1778
1820
1779
1821
// 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
1780
1852
csr_t_p sscsrind_reg_csr_t::get_reg () const noexcept {
1781
1853
auto proxy = ireg_proxy;
1782
1854
auto isel = iselect->read ();
@@ -1878,3 +1950,31 @@ bool hstatus_csr_t::unlogged_write(const reg_t val) noexcept {
1878
1950
proc->get_mmu ()->flush_tlb ();
1879
1951
return basic_csr_t::unlogged_write (new_hstatus);
1880
1952
}
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