aboutsummaryrefslogtreecommitdiff
path: root/riscv/csrs.cc
diff options
context:
space:
mode:
Diffstat (limited to 'riscv/csrs.cc')
-rw-r--r--riscv/csrs.cc41
1 files changed, 37 insertions, 4 deletions
diff --git a/riscv/csrs.cc b/riscv/csrs.cc
index e99ae84..01720eb 100644
--- a/riscv/csrs.cc
+++ b/riscv/csrs.cc
@@ -421,6 +421,7 @@ reg_t base_status_csr_t::compute_sstatus_write_mask() const noexcept {
| (proc->any_custom_extensions() ? SSTATUS_XS : 0)
| (has_vs ? SSTATUS_VS : 0)
| (proc->extension_enabled(EXT_ZICFILP) ? SSTATUS_SPELP : 0)
+ | (proc->extension_enabled(EXT_SSDBLTRP) ? SSTATUS_SDT : 0)
;
}
@@ -464,12 +465,23 @@ vsstatus_csr_t::vsstatus_csr_t(processor_t* const proc, const reg_t addr):
}
bool vsstatus_csr_t::unlogged_write(const reg_t val) noexcept {
- const reg_t newval = (this->val & ~sstatus_write_mask) | (val & sstatus_write_mask);
+ const reg_t hDTE = (state->henvcfg->read() & HENVCFG_DTE);
+ const reg_t adj_write_mask = sstatus_write_mask & ~(hDTE ? 0 : SSTATUS_SDT);
+ reg_t newval = (this->val & ~adj_write_mask) | (val & adj_write_mask);
+
+ newval = (newval & SSTATUS_SDT) ? (newval & ~SSTATUS_SIE) : newval;
+
if (state->v) maybe_flush_tlb(newval);
this->val = adjust_sd(newval);
return true;
}
+reg_t vsstatus_csr_t::read() const noexcept {
+ const reg_t hDTE = state->henvcfg->read() & HENVCFG_DTE;
+ const reg_t adj_read_mask = sstatus_read_mask & ~(hDTE ? 0 : SSTATUS_SDT);
+ return this->val & adj_read_mask;
+}
+
// implement class sstatus_proxy_csr_t
sstatus_proxy_csr_t::sstatus_proxy_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus):
base_status_csr_t(proc, addr),
@@ -477,16 +489,26 @@ sstatus_proxy_csr_t::sstatus_proxy_csr_t(processor_t* const proc, const reg_t ad
}
bool sstatus_proxy_csr_t::unlogged_write(const reg_t val) noexcept {
- const reg_t new_mstatus = (mstatus->read() & ~sstatus_write_mask) | (val & sstatus_write_mask);
+ const reg_t mDTE = (state->menvcfg->read() & MENVCFG_DTE);
+ const reg_t adj_write_mask = sstatus_write_mask & ~(mDTE ? 0 : SSTATUS_SDT);
+ reg_t new_mstatus = (mstatus->read() & ~adj_write_mask) | (val & adj_write_mask);
+
+ new_mstatus = (new_mstatus & SSTATUS_SDT) ? (new_mstatus & ~SSTATUS_SIE) : new_mstatus;
// On RV32 this will only log the low 32 bits, so make sure we're
// not modifying anything in the upper 32 bits.
- assert((sstatus_write_mask & 0xffffffffU) == sstatus_write_mask);
+ assert((adj_write_mask & 0xffffffffU) == adj_write_mask);
mstatus->write(new_mstatus);
return false; // avoid double logging: already logged by mstatus->write()
}
+reg_t sstatus_proxy_csr_t::read() const noexcept {
+ const reg_t mDTE = state->menvcfg->read() & MENVCFG_DTE;
+ const reg_t adj_read_mask = sstatus_read_mask & ~(mDTE ? 0 : SSTATUS_SDT);
+ return mstatus->read() & adj_read_mask;
+}
+
// implement class mstatus_csr_t
mstatus_csr_t::mstatus_csr_t(processor_t* const proc, const reg_t addr):
base_status_csr_t(proc, addr),
@@ -506,6 +528,7 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept {
| (has_gva ? MSTATUS_GVA : 0)
| (has_mpv ? MSTATUS_MPV : 0)
| (proc->extension_enabled(EXT_ZICFILP) ? (MSTATUS_SPELP | MSTATUS_MPELP) : 0)
+ | (proc->extension_enabled(EXT_SSDBLTRP) ? SSTATUS_SDT : 0)
;
const reg_t requested_mpp = proc->legalize_privilege(get_field(val, MSTATUS_MPP));
@@ -1548,7 +1571,7 @@ void henvcfg_csr_t::verify_permissions(insn_t insn, bool write) const {
}
bool henvcfg_csr_t::unlogged_write(const reg_t val) noexcept {
- const reg_t mask = menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE);
+ const reg_t mask = menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE | MENVCFG_DTE);
return envcfg_csr_t::unlogged_write((masked_csr_t::read() & ~mask) | (val & mask));
}
@@ -1765,3 +1788,13 @@ void ssp_csr_t::verify_permissions(insn_t insn, bool write) const {
DECLARE_XENVCFG_VARS(SSE);
require_envcfg(SSE);
}
+
+mtval2_csr_t::mtval2_csr_t(processor_t* const proc, const reg_t addr):
+ hypervisor_csr_t(proc, addr) {
+}
+
+void mtval2_csr_t::verify_permissions(insn_t insn, bool write) const {
+ basic_csr_t::verify_permissions(insn, write);
+ if (!proc->extension_enabled('H') && !proc->extension_enabled(EXT_SSDBLTRP))
+ throw trap_illegal_instruction(insn.bits());
+}