aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Johnson <scott.johnson@arilinc.com>2021-03-04 21:12:41 -0800
committerAndrew Waterman <aswaterman@gmail.com>2021-09-08 07:59:02 -0700
commitdc7dfc7015dfa983e62f8ad0aa1d0f4accc7e500 (patch)
tree11510630b41319e22264c3cd1e9a6b506caa6c38
parent36f62570b64d66cea6d7772c34abcd944a004adf (diff)
downloadspike-dc7dfc7015dfa983e62f8ad0aa1d0f4accc7e500.zip
spike-dc7dfc7015dfa983e62f8ad0aa1d0f4accc7e500.tar.gz
spike-dc7dfc7015dfa983e62f8ad0aa1d0f4accc7e500.tar.bz2
Convert sstatus to virtualized_csr_t
Step 5 of plan in csrs.h. This changes the commitlog to properly report when the architectural `vsstatus` register is written, e.g. by `csrw sstatus` in VS-mode.
-rw-r--r--riscv/csrs.h4
-rw-r--r--riscv/mmu.cc9
-rw-r--r--riscv/processor.cc17
-rw-r--r--riscv/processor.h2
4 files changed, 13 insertions, 19 deletions
diff --git a/riscv/csrs.h b/riscv/csrs.h
index 0afdd0c..6f60555 100644
--- a/riscv/csrs.h
+++ b/riscv/csrs.h
@@ -138,6 +138,8 @@ class virtualized_csr_t: public csr_t {
csr_t_p virt_csr;
};
+typedef std::shared_ptr<virtualized_csr_t> virtualized_csr_t_p;
+
// For mepc, sepc, and vsepc
class epc_csr_t: public logged_csr_t {
@@ -207,7 +209,7 @@ typedef std::shared_ptr<vsstatus_csr_t> vsstatus_csr_t_p;
// need to be virtualized will be through this object.
// 3. [done] Convert mstatus into a csr_t subclass.
// 4. Refactor common code into base class.
-// 5. Convert sstatus to a virtualized_csr_t, with a
+// 5. [done] Convert sstatus to a virtualized_csr_t, with a
// nonvirtual_sstatus of type sstatus_proxy_csr_t, and
// simultaneously remove the swapping of mstatus & vsstatus from
// set_priv().
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index a9c056c..7f2858c 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -267,8 +267,7 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty
if (vm.levels == 0)
return gpa;
- reg_t arch_sstatus = proc->state.v ? proc->state.vsstatus->read() : proc->state.sstatus->read();
- bool mxr = arch_sstatus & MSTATUS_MXR;
+ bool mxr = proc->state.sstatus->readvirt(false) & MSTATUS_MXR;
reg_t base = vm.ptbase;
for (int i = vm.levels - 1; i >= 0; i--) {
@@ -347,9 +346,9 @@ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode, bool virt, bool hlvx
return s2xlate(addr, addr & ((reg_t(2) << (proc->xlen-1))-1), type, type, virt, hlvx) & ~page_mask; // zero-extend from xlen
bool s_mode = mode == PRV_S;
- reg_t arch_vsstatus = proc->state.v ? proc->state.sstatus->read() : proc->state.vsstatus->read();
- reg_t arch_sstatus = proc->state.v ? proc->state.vsstatus->read() : proc->state.sstatus->read();
- bool sum = (virt ? arch_vsstatus : arch_sstatus) & MSTATUS_SUM;
+ bool sum = proc->state.sstatus->readvirt(virt) & MSTATUS_SUM;
+ reg_t arch_vsstatus = proc->state.sstatus->readvirt(true);
+ reg_t arch_sstatus = proc->state.sstatus->readvirt(false);
bool mxr = (arch_sstatus | (virt ? arch_vsstatus : 0)) & MSTATUS_MXR;
// verify bits xlen-1:va_bits-1 are all equal
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 7cf7d88..2b21f39 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -377,8 +377,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
htinst = 0;
hgatp = 0;
nonvirtual_sstatus = std::make_shared<sstatus_proxy_csr_t>(proc, CSR_SSTATUS);
- csrmap[CSR_SSTATUS] = sstatus = nonvirtual_sstatus;
csrmap[CSR_VSSTATUS] = vsstatus = std::make_shared<vsstatus_csr_t>(proc, CSR_VSSTATUS);
+ csrmap[CSR_SSTATUS] = sstatus = std::make_shared<virtualized_csr_t>(proc, nonvirtual_sstatus, vsstatus);
vsatp = 0;
dpc = 0;
@@ -609,17 +609,13 @@ void processor_t::take_interrupt(reg_t pending_interrupts)
if (enabled_interrupts == 0) {
// HS-ints have higher priority over VS-ints
deleg = state.mideleg & ~state.hideleg;
- // NB: this is always looking at architectural sstatus. Because when
- // state.v, vsstatus & mstatus have been swapped.
- status = (state.v) ? state.vsstatus->read() : state.sstatus->read();
+ status = state.nonvirtual_sstatus->read();
hsie = get_field(status, MSTATUS_SIE);
hs_enabled = state.v || state.prv < PRV_S || (state.prv == PRV_S && hsie);
enabled_interrupts = pending_interrupts & deleg & -hs_enabled;
if (state.v && enabled_interrupts == 0) {
// VS-ints have least priority and can only be taken with virt enabled
deleg = state.mideleg & state.hideleg;
- // NB: this is actually looking at architectural vsstatus.
- // Because when state.v, vsstatus & mstatus have been swapped.
vsie = get_field(state.sstatus->read(), MSTATUS_SIE);
vs_enabled = state.prv < PRV_S || (state.prv == PRV_S && vsie);
enabled_interrupts = pending_interrupts & deleg & -vs_enabled;
@@ -696,13 +692,10 @@ void processor_t::set_virt(bool virt)
* Ideally, we should flush TLB here but we don't need it because
* set_virt() is always used in conjucter with set_privilege() and
* set_privilege() will flush TLB unconditionally.
+ *
+ * The virtualized sstatus register also relies on this TLB flush,
+ * since changing V might change sstatus.MXR and sstatus.SUM.
*/
- mask = SSTATUS_VS_MASK;
- mask |= (supports_extension('V') ? SSTATUS_VS : 0);
- mask |= (xlen == 64 ? SSTATUS64_SD : SSTATUS32_SD);
- tmp = state.mstatus->read() & mask;
- state.mstatus->backdoor_write((state.mstatus->read() & ~mask) | (state.vsstatus->read() & mask));
- state.vsstatus->backdoor_write(tmp);
state.v = virt;
}
}
diff --git a/riscv/processor.h b/riscv/processor.h
index c61bb94..4697ca4 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -197,7 +197,7 @@ struct state_t
reg_t htinst;
reg_t hgatp;
csr_t_p nonvirtual_sstatus;
- csr_t_p sstatus;
+ virtualized_csr_t_p sstatus;
vsstatus_csr_t_p vsstatus;
csr_t_p vstvec;
csr_t_p vsepc;