diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 4783646991..e76b153a96 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1127,6 +1127,22 @@ void counter_proxy_csr_t::verify_permissions(insn_t insn, bool write) const { } } +context_proxy_csr_t::context_proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate): + proxy_csr_t(proc, addr, delegate) { +} + +void context_proxy_csr_t::verify_permissions(insn_t insn, bool write) const { + if (proc->extension_enabled(EXT_SMSTATEEN)) { + if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_HCONTEXT)) + throw trap_illegal_instruction(insn.bits()); + + if (state->v && !(state->hstateen[0]->read() & HSTATEEN0_SCONTEXT)) + throw trap_virtual_instruction(insn.bits()); + } + + proxy_csr_t::verify_permissions(insn, write); +} + mevent_csr_t::mevent_csr_t(processor_t* const proc, const reg_t addr): basic_csr_t(proc, addr, 0) { } @@ -1252,6 +1268,31 @@ void debug_mode_csr_t::verify_permissions(insn_t insn, bool write) const { throw trap_illegal_instruction(insn.bits()); } +mscontext_csr_t::mscontext_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate): + proxy_csr_t(proc, addr, delegate) { +} + +void mscontext_csr_t::verify_permissions(insn_t insn, bool write) const { + if (proc->extension_enabled(EXT_SMSTATEEN)) { + if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_HCONTEXT)) + throw trap_illegal_instruction(insn.bits()); + + if (state->v && !(state->hstateen[0]->read() & HSTATEEN0_SCONTEXT)) + throw trap_virtual_instruction(insn.bits()); + } + + // Address of mscontext does not conform to the CSR conventions, i.e., csr_priv == PRV_S + if (!proc->extension_enabled('S')) + throw trap_illegal_instruction(insn.bits()); + + unsigned priv = state->prv == PRV_S && !state->v ? PRV_HS : state->prv; + if (priv < PRV_S) { + if (state->v) + throw trap_virtual_instruction(insn.bits()); + throw trap_illegal_instruction(insn.bits()); + } +} + dpc_csr_t::dpc_csr_t(processor_t* const proc, const reg_t addr): epc_csr_t(proc, addr) { } @@ -1614,6 +1655,22 @@ void jvt_csr_t::verify_permissions(insn_t insn, bool write) const { } } +context_csr_t::context_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init): + masked_csr_t(proc, addr, mask, init) { +} + +void context_csr_t::verify_permissions(insn_t insn, bool write) const { + if (proc->extension_enabled(EXT_SMSTATEEN)) { + if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_HCONTEXT)) + throw trap_illegal_instruction(insn.bits()); + + if (state->v && !(state->hstateen[0]->read() & HSTATEEN0_SCONTEXT)) + throw trap_virtual_instruction(insn.bits()); + } + + basic_csr_t::verify_permissions(insn, write); +} + virtualized_indirect_csr_t::virtualized_indirect_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt): virtualized_csr_t(proc, orig, virt) { } diff --git a/riscv/csrs.h b/riscv/csrs.h index 887749a613..3715b39306 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -588,6 +588,12 @@ class counter_proxy_csr_t: public proxy_csr_t { bool myenable(csr_t_p counteren) const noexcept; }; +class context_proxy_csr_t: public proxy_csr_t { + public: + context_proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate); + virtual void verify_permissions(insn_t insn, bool write) const override; +}; + class mevent_csr_t: public basic_csr_t { public: mevent_csr_t(processor_t* const proc, const reg_t addr); @@ -664,6 +670,12 @@ class debug_mode_csr_t: public basic_csr_t { virtual void verify_permissions(insn_t insn, bool write) const override; }; +class mscontext_csr_t: public proxy_csr_t { + public: + mscontext_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate); + virtual void verify_permissions(insn_t insn, bool write) const override; +}; + class dpc_csr_t: public epc_csr_t { public: dpc_csr_t(processor_t* const proc, const reg_t addr); @@ -808,6 +820,12 @@ class jvt_csr_t: public basic_csr_t { virtual void verify_permissions(insn_t insn, bool write) const override; }; +class context_csr_t: public masked_csr_t { + public: + context_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init); + virtual void verify_permissions(insn_t insn, bool write) const override; +}; + // Sscsrind registers needs permissions checked // (the original virtualized_csr_t does not call verify_permission of the underlying CSRs) class virtualized_indirect_csr_t: public virtualized_csr_t { diff --git a/riscv/processor.cc b/riscv/processor.cc index 1bb1fc9e95..aec6adcacf 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -418,10 +418,11 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) csrmap[CSR_TINFO] = std::make_shared(proc, CSR_TINFO, 0); } unsigned scontext_length = (xlen == 32 ? 16 : 34); // debug spec suggests 16-bit for RV32 and 34-bit for RV64 - csrmap[CSR_SCONTEXT] = scontext = std::make_shared(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0); + csrmap[CSR_SCONTEXT] = scontext = std::make_shared(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0); 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 - csrmap[CSR_HCONTEXT] = std::make_shared(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0); - csrmap[CSR_MCONTEXT] = mcontext = std::make_shared(proc, CSR_MCONTEXT, csrmap[CSR_HCONTEXT]); + csrmap[CSR_HCONTEXT] = std::make_shared(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0); + csrmap[CSR_MCONTEXT] = mcontext = std::make_shared(proc, CSR_MCONTEXT, csrmap[CSR_HCONTEXT]); + csrmap[CSR_MSCONTEXT] = std::make_shared(proc, CSR_MSCONTEXT, scontext); debug_mode = false; single_step = STEP_NONE; @@ -482,7 +483,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) const reg_t sstateen0_mask = (proc->extension_enabled(EXT_ZFINX) ? SSTATEEN0_FCSR : 0) | (proc->extension_enabled(EXT_ZCMT) ? SSTATEEN0_JVT : 0) | SSTATEEN0_CS; - const reg_t hstateen0_mask = sstateen0_mask | HSTATEEN0_SENVCFG | HSTATEEN_SSTATEEN; + const reg_t hstateen0_mask = sstateen0_mask | HSTATEEN0_SCONTEXT | HSTATEEN0_SENVCFG | HSTATEEN_SSTATEEN; 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;