Skip to content

Commit c9b298b

Browse files
committed
Fix issues with smcsrind not considering stateen, throw illegal on
missing proxy csr and check for csr privilege in sscsring_reg_csr_t since mireg uses the same class. Fix for issue: 1893
1 parent 49727e8 commit c9b298b

File tree

3 files changed

+108
-13
lines changed

3 files changed

+108
-13
lines changed

riscv/csr_init.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,8 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
284284
const reg_t sstateen0_mask = (proc->extension_enabled(EXT_ZFINX) ? SSTATEEN0_FCSR : 0) |
285285
(proc->extension_enabled(EXT_ZCMT) ? SSTATEEN0_JVT : 0) |
286286
SSTATEEN0_CS;
287-
const reg_t hstateen0_mask = sstateen0_mask | HSTATEEN0_SENVCFG | HSTATEEN_SSTATEEN;
287+
const reg_t hstateen0_mask = sstateen0_mask | HSTATEEN0_SENVCFG | HSTATEEN_SSTATEEN |
288+
(proc->extension_enabled(EXT_SSCSRIND) ? HSTATEEN0_CSRIND : 0);
288289
const reg_t mstateen0_mask = hstateen0_mask | (proc->extension_enabled(EXT_SSQOSID) ? MSTATEEN0_PRIV114 : 0);
289290
for (int i = 0; i < 4; i++) {
290291
const reg_t mstateen_mask = i == 0 ? mstateen0_mask : MSTATEEN_HSTATEEN;
@@ -349,11 +350,12 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
349350
}
350351

351352
if (proc->extension_enabled_const(EXT_SSCSRIND)) {
352-
csr_t_p vsiselect = std::make_shared<basic_csr_t>(proc, CSR_VSISELECT, 0);
353+
auto vsiselect = std::make_shared<sscsrind_select_csr_t>(proc, CSR_VSISELECT, 0);
353354
add_hypervisor_csr(CSR_VSISELECT, vsiselect);
354355

355-
csr_t_p siselect = std::make_shared<basic_csr_t>(proc, CSR_SISELECT, 0);
356-
add_supervisor_csr(CSR_SISELECT, std::make_shared<virtualized_csr_t>(proc, siselect, vsiselect));
356+
auto siselect = std::make_shared<sscsrind_select_csr_t>(proc, CSR_SISELECT, 0);
357+
// Correct virtualized type?
358+
add_supervisor_csr(CSR_SISELECT, std::make_shared<virtualized_select_indirect_csr_t>(proc, siselect, vsiselect));
357359

358360
const reg_t vsireg_csrs[] = { CSR_VSIREG, CSR_VSIREG2, CSR_VSIREG3, CSR_VSIREG4, CSR_VSIREG5, CSR_VSIREG6 };
359361
const reg_t sireg_csrs[] = { CSR_SIREG, CSR_SIREG2, CSR_SIREG3, CSR_SIREG4, CSR_SIREG5, CSR_SIREG6 };

riscv/csrs.cc

Lines changed: 89 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,11 +1731,37 @@ virtualized_indirect_csr_t::virtualized_indirect_csr_t(processor_t* const proc,
17311731
}
17321732

17331733
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+
}
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

17411767
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
17441770
}
17451771

17461772
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+
}
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
17801860
csr_t_p sscsrind_reg_csr_t::get_reg() const noexcept {
17811861
auto proxy = ireg_proxy;
17821862
auto isel = iselect->read();

riscv/csrs.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,19 @@ class sscsrind_reg_csr_t : public csr_t {
849849
csr_t_p get_reg() const noexcept;
850850
};
851851

852+
class sscsrind_select_csr_t: public basic_csr_t {
853+
public:
854+
sscsrind_select_csr_t(processor_t* const proc, const reg_t addr, const reg_t init);
855+
protected:
856+
virtual void verify_permissions(insn_t insn, bool write) const override;
857+
};
858+
859+
class virtualized_select_indirect_csr_t: public virtualized_csr_t {
860+
public:
861+
virtualized_select_indirect_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt);
862+
virtual void verify_permissions(insn_t insn, bool write) const override;
863+
};
864+
852865
// smcntrpmf_csr_t caches the previous state of the CSR in case a CSRW instruction
853866
// modifies the state that should not be immediately visible to bump()
854867
class smcntrpmf_csr_t : public masked_csr_t {

0 commit comments

Comments
 (0)