Skip to content

Commit a8e9876

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. Add stateen checks for scontext/hcontext Fix for issue: 1893
1 parent 49727e8 commit a8e9876

File tree

3 files changed

+142
-15
lines changed

3 files changed

+142
-15
lines changed

riscv/csr_init.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,9 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
215215
add_csr(CSR_TINFO, std::make_shared<const_csr_t>(proc, CSR_TINFO, 0));
216216
}
217217
unsigned scontext_length = (xlen == 32 ? 16 : 32); // debug spec suggests 16-bit for RV32 and 32-bit for RV64
218-
add_supervisor_csr(CSR_SCONTEXT, scontext = std::make_shared<masked_csr_t>(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0));
218+
add_supervisor_csr(CSR_SCONTEXT, scontext = std::make_shared<scontext_csr_t>(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0));
219219
unsigned hcontext_length = (xlen == 32 ? 6 : 13) + (proc->extension_enabled('H') ? 1 : 0); // debug spec suggest 7-bit (6-bit) for RV32 and 14-bit (13-bit) for RV64 with (without) H extension
220-
auto hcontext = std::make_shared<masked_csr_t>(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0);
220+
auto hcontext = std::make_shared<hcontext_csr_t>(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0);
221221
add_hypervisor_csr(CSR_HCONTEXT, hcontext);
222222
add_csr(CSR_MCONTEXT, mcontext = std::make_shared<proxy_csr_t>(proc, CSR_MCONTEXT, hcontext));
223223
add_csr(CSR_MSECCFG, mseccfg = std::make_shared<mseccfg_csr_t>(proc, CSR_MSECCFG));
@@ -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: 109 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,11 +1731,29 @@ 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);
17351734
if (state->v)
17361735
virt_csr->verify_permissions(insn, write);
17371736
else
17381737
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);
17391757
}
17401758

17411759
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
17441762
}
17451763

17461764
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+
}
17501790

17511791
csr_t_p proxy_csr = get_reg();
17521792
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());
17581795
}
17591796
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+
17601802
}
17611803

17621804

@@ -1777,6 +1819,36 @@ bool sscsrind_reg_csr_t::unlogged_write(const reg_t val) noexcept {
17771819
}
17781820

17791821
// 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
17801852
csr_t_p sscsrind_reg_csr_t::get_reg() const noexcept {
17811853
auto proxy = ireg_proxy;
17821854
auto isel = iselect->read();
@@ -1878,3 +1950,31 @@ bool hstatus_csr_t::unlogged_write(const reg_t val) noexcept {
18781950
proc->get_mmu()->flush_tlb();
18791951
return basic_csr_t::unlogged_write(new_hstatus);
18801952
}
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+
}

riscv/csrs.h

Lines changed: 25 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 {
@@ -899,4 +912,16 @@ class hstatus_csr_t final: public basic_csr_t {
899912
protected:
900913
virtual bool unlogged_write(const reg_t val) noexcept override;
901914
};
915+
916+
class scontext_csr_t: public masked_csr_t {
917+
public:
918+
scontext_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init);
919+
virtual void verify_permissions(insn_t insn, bool write) const override;
920+
};
921+
922+
class hcontext_csr_t: public masked_csr_t {
923+
public:
924+
hcontext_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init);
925+
virtual void verify_permissions(insn_t insn, bool write) const override;
926+
};
902927
#endif

0 commit comments

Comments
 (0)