diff options
author | Scott Johnson <scott.johnson@arilinc.com> | 2021-03-04 21:12:41 -0800 |
---|---|---|
committer | Andrew Waterman <aswaterman@gmail.com> | 2021-09-08 07:59:02 -0700 |
commit | dc7dfc7015dfa983e62f8ad0aa1d0f4accc7e500 (patch) | |
tree | 11510630b41319e22264c3cd1e9a6b506caa6c38 | |
parent | 36f62570b64d66cea6d7772c34abcd944a004adf (diff) | |
download | spike-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.h | 4 | ||||
-rw-r--r-- | riscv/mmu.cc | 9 | ||||
-rw-r--r-- | riscv/processor.cc | 17 | ||||
-rw-r--r-- | riscv/processor.h | 2 |
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; |