aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Johnson <scott.johnson@arilinc.com>2022-07-13 21:18:08 -0500
committerGitHub <noreply@github.com>2022-07-13 21:18:08 -0500
commitd02b285c8858e33c7f9a79207127c8374c4ddc62 (patch)
tree1a481ce817e2e5e2ecd4c9badb5cf2e1385bff00
parent5eada616d48e1e0f1f9f5add53dfca76dc29de68 (diff)
parent3688fd8302d1b7b8eea1dd8f6206ceab1bedfb2c (diff)
downloadspike-d02b285c8858e33c7f9a79207127c8374c4ddc62.zip
spike-d02b285c8858e33c7f9a79207127c8374c4ddc62.tar.gz
spike-d02b285c8858e33c7f9a79207127c8374c4ddc62.tar.bz2
Merge pull request #1045 from scottj97/fix1044
Fix #1044
-rw-r--r--riscv/csrs.cc35
-rw-r--r--riscv/csrs.h18
-rw-r--r--riscv/processor.cc23
-rw-r--r--riscv/processor.h1
4 files changed, 62 insertions, 15 deletions
diff --git a/riscv/csrs.cc b/riscv/csrs.cc
index 83906cc..6f8f260 100644
--- a/riscv/csrs.cc
+++ b/riscv/csrs.cc
@@ -455,6 +455,10 @@ 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);
+ // 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);
+
mstatus->write(new_mstatus);
return false; // avoid double logging: already logged by mstatus->write()
}
@@ -493,15 +497,32 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept {
return true;
}
+// implement class rv32_low_csr_t
+rv32_low_csr_t::rv32_low_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig):
+ csr_t(proc, addr),
+ orig(orig) {
+}
+
+reg_t rv32_low_csr_t::read() const noexcept {
+ return orig->read() & 0xffffffffU;
+}
+
+void rv32_low_csr_t::verify_permissions(insn_t insn, bool write) const {
+ orig->verify_permissions(insn, write);
+}
+
+bool rv32_low_csr_t::unlogged_write(const reg_t val) noexcept {
+ return orig->unlogged_write((orig->written_value() >> 32 << 32) | (val & 0xffffffffU));
+}
+
// implement class rv32_high_csr_t
-rv32_high_csr_t::rv32_high_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, csr_t_p orig):
+rv32_high_csr_t::rv32_high_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig):
csr_t(proc, addr),
- orig(orig),
- mask(mask) {
+ orig(orig) {
}
reg_t rv32_high_csr_t::read() const noexcept {
- return (orig->read() >> 32) & mask;
+ return (orig->read() >> 32) & 0xffffffffU;
}
void rv32_high_csr_t::verify_permissions(insn_t insn, bool write) const {
@@ -509,7 +530,7 @@ void rv32_high_csr_t::verify_permissions(insn_t insn, bool write) const {
}
bool rv32_high_csr_t::unlogged_write(const reg_t val) noexcept {
- return orig->unlogged_write((orig->written_value() & ~(mask << 32)) | ((val & mask) << 32));
+ return orig->unlogged_write((orig->written_value() << 32 >> 32) | ((val & 0xffffffffU) << 32));
}
// implement class sstatus_csr_t
@@ -595,7 +616,9 @@ bool misa_csr_t::unlogged_write(const reg_t val) noexcept {
| (1 << CAUSE_STORE_GUEST_PAGE_FAULT)
;
state->medeleg->write(state->medeleg->read() & ~hypervisor_exceptions);
- state->mstatus->write(state->mstatus->read() & ~(MSTATUS_GVA | MSTATUS_MPV));
+ const reg_t new_mstatus = state->mstatus->read() & ~(MSTATUS_GVA | MSTATUS_MPV);
+ state->mstatus->write(new_mstatus);
+ if (state->mstatush) state->mstatush->write(new_mstatus >> 32); // log mstatush change
state->mie->write_with_mask(MIP_HS_MASK, 0); // also takes care of hie, sie
state->mip->write_with_mask(MIP_HS_MASK, 0); // also takes care of hip, sip, hvip
state->hstatus->write(0);
diff --git a/riscv/csrs.h b/riscv/csrs.h
index bde31da..500bde7 100644
--- a/riscv/csrs.h
+++ b/riscv/csrs.h
@@ -54,7 +54,9 @@ class csr_t {
const unsigned csr_priv;
const bool csr_read_only;
+ // For access to written_value() and unlogged_write():
friend class rv32_high_csr_t;
+ friend class rv32_low_csr_t;
};
typedef std::shared_ptr<csr_t> csr_t_p;
@@ -249,16 +251,28 @@ class mstatus_csr_t final: public base_status_csr_t {
typedef std::shared_ptr<mstatus_csr_t> mstatus_csr_t_p;
+// For RV32 CSRs that are split into two, e.g. mstatus/mstatush
+// CSRW should only modify the lower half
+class rv32_low_csr_t: public csr_t {
+ public:
+ rv32_low_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig);
+ virtual reg_t read() const noexcept override;
+ virtual void verify_permissions(insn_t insn, bool write) const override;
+ protected:
+ virtual bool unlogged_write(const reg_t val) noexcept override;
+ private:
+ csr_t_p orig;
+};
+
class rv32_high_csr_t: public csr_t {
public:
- rv32_high_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, csr_t_p orig);
+ rv32_high_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig);
virtual reg_t read() const noexcept override;
virtual void verify_permissions(insn_t insn, bool write) const override;
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
private:
csr_t_p orig;
- const reg_t mask;
};
class sstatus_proxy_csr_t final: public base_status_csr_t {
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 5973baf..8f77b47 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -189,11 +189,13 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
prv = PRV_M;
v = false;
csrmap[CSR_MISA] = misa = std::make_shared<misa_csr_t>(proc, CSR_MISA, max_isa);
- csrmap[CSR_MSTATUS] = mstatus = std::make_shared<mstatus_csr_t>(proc, CSR_MSTATUS);
+ mstatus = std::make_shared<mstatus_csr_t>(proc, CSR_MSTATUS);
if (xlen == 32) {
- const reg_t mstatush_mask = MSTATUSH_MPV | MSTATUSH_GVA | MSTATUSH_SBE | MSTATUSH_MBE;
- csrmap[CSR_MSTATUSH] = std::make_shared<rv32_high_csr_t>(proc, CSR_MSTATUSH, mstatush_mask, mstatus);
+ csrmap[CSR_MSTATUS] = std::make_shared<rv32_low_csr_t>(proc, CSR_MSTATUS, mstatus);
+ csrmap[CSR_MSTATUSH] = mstatush = std::make_shared<rv32_high_csr_t>(proc, CSR_MSTATUSH, mstatus);
+ } else {
+ csrmap[CSR_MSTATUS] = mstatus;
}
csrmap[CSR_MEPC] = mepc = std::make_shared<epc_csr_t>(proc, CSR_MEPC);
csrmap[CSR_MTVAL] = mtval = std::make_shared<basic_csr_t>(proc, CSR_MTVAL, 0);
@@ -403,15 +405,21 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
const reg_t mstateen0_mask = hstateen0_mask;
for (int i = 0; i < 4; i++) {
const reg_t mstateen_mask = i == 0 ? mstateen0_mask : MSTATEEN_HSTATEEN;
- csrmap[CSR_MSTATEEN0 + i] = mstateen[i] = std::make_shared<masked_csr_t>(proc, CSR_MSTATEEN0 + i, mstateen_mask, 0);
+ mstateen[i] = std::make_shared<masked_csr_t>(proc, CSR_MSTATEEN0 + i, mstateen_mask, 0);
if (xlen == 32) {
- csrmap[CSR_MSTATEEN0H + i] = std::make_shared<rv32_high_csr_t>(proc, CSR_MSTATEEN0H + i, -1, mstateen[i]);
+ csrmap[CSR_MSTATEEN0 + i] = std::make_shared<rv32_low_csr_t>(proc, CSR_MSTATEEN0 + i, mstateen[i]);
+ csrmap[CSR_MSTATEEN0H + i] = std::make_shared<rv32_high_csr_t>(proc, CSR_MSTATEEN0H + i, mstateen[i]);
+ } else {
+ csrmap[CSR_MSTATEEN0 + i] = mstateen[i];
}
const reg_t hstateen_mask = i == 0 ? hstateen0_mask : HSTATEEN_SSTATEEN;
- csrmap[CSR_HSTATEEN0 + i] = hstateen[i] = std::make_shared<hstateen_csr_t>(proc, CSR_HSTATEEN0 + i, hstateen_mask, 0, i);
+ hstateen[i] = std::make_shared<hstateen_csr_t>(proc, CSR_HSTATEEN0 + i, hstateen_mask, 0, i);
if (xlen == 32) {
- csrmap[CSR_HSTATEEN0H + i] = std::make_shared<rv32_high_csr_t>(proc, CSR_HSTATEEN0H + i, -1, hstateen[i]);
+ csrmap[CSR_HSTATEEN0 + i] = std::make_shared<rv32_low_csr_t>(proc, CSR_HSTATEEN0 + i, hstateen[i]);
+ csrmap[CSR_HSTATEEN0H + i] = std::make_shared<rv32_high_csr_t>(proc, CSR_HSTATEEN0H + i, hstateen[i]);
+ } else {
+ csrmap[CSR_HSTATEEN0 + i] = hstateen[i];
}
const reg_t sstateen_mask = i == 0 ? sstateen0_mask : 0;
@@ -816,6 +824,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
s = set_field(s, MSTATUS_MPV, curr_virt);
s = set_field(s, MSTATUS_GVA, t.has_gva());
state.mstatus->write(s);
+ if (state.mstatush) state.mstatush->write(s >> 32); // log mstatush change
set_privilege(PRV_M);
}
}
diff --git a/riscv/processor.h b/riscv/processor.h
index 727c404..347ae16 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -133,6 +133,7 @@ struct state_t
bool v;
misa_csr_t_p misa;
mstatus_csr_t_p mstatus;
+ csr_t_p mstatush;
csr_t_p mepc;
csr_t_p mtval;
csr_t_p mtvec;