From bc5842f94517c5fa760409cf8c956bbc7c37ead5 Mon Sep 17 00:00:00 2001 From: Atul Khare Date: Tue, 11 Jul 2023 13:31:12 -0700 Subject: Add Smcsrind/Sscsrind support This adds the following CSRs: miselect (0x350), mireg (0x351), mireg2/3 (0x352, 0x353), mireg4-6 (0x355 - 0x357), siselect (0x150), sireg (0x151), sireg2/3 (0x152, 0x153), sireg4-6 (0x155 - 0x157), vsiselect (0x250), vsireg (0x251), mireg2/3 (0x252, 0x253), vsireg4-6 (0x255 - 0x257). Presently, attempts to read / write from ireg? registers will fail, and future extensions will provide proxy CSR mappings for the respective ?ireg CSRs. --- riscv/csrs.cc | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ riscv/csrs.h | 28 ++++++++++++++++++++++++ riscv/processor.cc | 40 +++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 7ea07d1..4d1e546 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1574,3 +1574,65 @@ void jvt_csr_t::verify_permissions(insn_t insn, bool write) const { } } } + +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) { +} + +void virtualized_indirect_csr_t::verify_permissions(insn_t insn, bool write) const { + virtualized_csr_t::verify_permissions(insn, write); + if (state->v) + virt_csr->verify_permissions(insn, write); + else + orig_csr->verify_permissions(insn, write); +} + +sscsrind_reg_csr_t::sscsrind_reg_csr_t(processor_t* const proc, const reg_t addr, csr_t_p iselect) : + csr_t(proc, addr), + iselect(iselect) { +} + +void sscsrind_reg_csr_t::verify_permissions(insn_t insn, bool write) const { + // Don't call base verify_permission for VS registers remapped to S-mode + if (insn.csr() == address) + csr_t::verify_permissions(insn, write); + + csr_t_p proxy_csr = get_reg(); + if (proxy_csr == nullptr) { + if (!state->v) { + throw trap_illegal_instruction(insn.bits()); + } else { + throw trap_virtual_instruction(insn.bits()); + } + } + proxy_csr->verify_permissions(insn, write); +} + + +reg_t sscsrind_reg_csr_t::read() const noexcept { + csr_t_p target_csr = get_reg(); + if (target_csr != nullptr) { + return target_csr->read(); + } + return 0; +} + +bool sscsrind_reg_csr_t::unlogged_write(const reg_t val) noexcept { + csr_t_p proxy_csr = get_reg(); + if (proxy_csr != nullptr) { + proxy_csr->write(val); + } + return false; +} + +// Returns the actual CSR that maps to value in *siselect or nullptr if no mapping exists +csr_t_p sscsrind_reg_csr_t::get_reg() const noexcept { + auto proxy = ireg_proxy; + auto isel = iselect->read(); + auto it = proxy.find(isel); + return it != proxy.end() ? it->second : nullptr; +} + +void sscsrind_reg_csr_t::add_ireg_proxy(const reg_t iselect_value, csr_t_p csr) { + ireg_proxy[iselect_value] = csr; +} diff --git a/riscv/csrs.h b/riscv/csrs.h index 07d6d82..d28d124 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -6,8 +6,12 @@ #include "encoding.h" // For reg_t: #include "decode.h" +// For std::unordered_map +#include // For std::shared_ptr #include +// For std::optional +#include // For access_type: #include "memtracer.h" #include @@ -787,4 +791,28 @@ class jvt_csr_t: public basic_csr_t { jvt_csr_t(processor_t* const proc, const reg_t addr, 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 { + public: + virtualized_indirect_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt); + virtual void verify_permissions(insn_t insn, bool write) const override; +}; + +class sscsrind_reg_csr_t : public csr_t { + public: + typedef std::shared_ptr sscsrind_reg_csr_t_p; + sscsrind_reg_csr_t(processor_t* const proc, const reg_t addr, csr_t_p iselect); + reg_t read() const noexcept override; + virtual void verify_permissions(insn_t insn, bool write) const override; + void add_ireg_proxy(const reg_t iselect_val, csr_t_p proxy_csr); + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; + private: + csr_t_p iselect; + std::unordered_map ireg_proxy; + csr_t_p get_reg() const noexcept; +}; + #endif diff --git a/riscv/processor.cc b/riscv/processor.cc index e81375a..c41b3cf 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -524,6 +524,46 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) if (proc->extension_enabled(EXT_ZCMT)) csrmap[CSR_JVT] = jvt = std::make_shared(proc, CSR_JVT, 0); + + // Smcsrind / Sscsrind + csr_t_p miselect; + csr_t_p siselect; + csr_t_p vsiselect; + sscsrind_reg_csr_t::sscsrind_reg_csr_t_p mireg[6]; + sscsrind_reg_csr_t::sscsrind_reg_csr_t_p sireg[6]; + sscsrind_reg_csr_t::sscsrind_reg_csr_t_p vsireg[6]; + + if (proc->extension_enabled_const(EXT_SMCSRIND)) { + const reg_t mireg_csrs[] = { CSR_MIREG, CSR_MIREG2, CSR_MIREG3, CSR_MIREG4, CSR_MIREG5, CSR_MIREG6 }; + auto i = 0; + for (auto csr : mireg_csrs) { + csrmap[csr] = mireg[i] = std::make_shared(proc, csr, miselect); + i++; + } + } + + if (proc->extension_enabled_const(EXT_SSCSRIND)) { + vsiselect = std::make_shared(proc, CSR_VSISELECT, 0); + csrmap[CSR_VSISELECT] = vsiselect; + siselect = std::make_shared(proc, CSR_SISELECT, 0); + csrmap[CSR_SISELECT] = std::make_shared(proc, siselect, vsiselect); + + const reg_t vsireg_csrs[] = { CSR_VSIREG, CSR_VSIREG2, CSR_VSIREG3, CSR_VSIREG4, CSR_VSIREG5, CSR_VSIREG6 }; + auto i = 0; + for (auto csr : vsireg_csrs) { + csrmap[csr] = vsireg[i] = std::make_shared(proc, csr, vsiselect); + i++; + } + + const reg_t sireg_csrs[] = { CSR_SIREG, CSR_SIREG2, CSR_SIREG3, CSR_SIREG4, CSR_SIREG5, CSR_SIREG6 }; + i = 0; + for (auto csr : sireg_csrs) { + sireg[i] = std::make_shared(proc, csr, siselect); + csrmap[csr] = std::make_shared(proc, sireg[i], vsireg[i]); + i++; + } + } + serialized = false; log_reg_write.clear(); -- cgit v1.1