diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 1a23ff978c..45b9c4a5b6 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1311,8 +1311,48 @@ fcsr_csr_t::fcsr_csr_t(processor_t* const proc, const reg_t addr, csr_t_p upper_ composite_csr_t(proc, addr, upper_csr, lower_csr, upper_lsb) { } +void fcsr_csr_t::verify_permissions(insn_t insn, bool write) const { + composite_csr_t::verify_permissions(insn, write); + + if (proc->extension_enabled(EXT_SMSTATEEN) && proc->extension_enabled(EXT_ZFINX)) { + if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_FCSR)) + throw trap_illegal_instruction(insn.bits()); + + if (state->v && !(state->hstateen[0]->read() & HSTATEEN0_FCSR)) + throw trap_virtual_instruction(insn.bits()); + + if ((proc->extension_enabled('S') && state->prv < PRV_S) && !(state->sstateen[0]->read() & SSTATEEN0_FCSR)) { + if (state->v) + throw trap_virtual_instruction(insn.bits()); + else + throw trap_illegal_instruction(insn.bits()); + } + } +} + // implement class senvcfg_csr_t senvcfg_csr_t::senvcfg_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 senvcfg_csr_t::verify_permissions(insn_t insn, bool write) const { + masked_csr_t::verify_permissions(insn, write); + + if (proc->extension_enabled(EXT_SMSTATEEN)) { + if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_HENVCFG)) + throw trap_illegal_instruction(insn.bits()); + + if (state->v && !(state->hstateen[0]->read() & HSTATEEN0_SENVCFG)) + throw trap_virtual_instruction(insn.bits()); + } +} + +void henvcfg_csr_t::verify_permissions(insn_t insn, bool write) const { + masked_csr_t::verify_permissions(insn, write); + + if (proc->extension_enabled(EXT_SMSTATEEN)) { + if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_HENVCFG)) + throw trap_illegal_instruction(insn.bits()); + } +} diff --git a/riscv/csrs.h b/riscv/csrs.h index 2b8a2fb758..bde31da35a 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -439,6 +439,8 @@ class henvcfg_csr_t final: public masked_csr_t { return (menvcfg->read() | ~MENVCFG_PBMTE) & masked_csr_t::read(); } + virtual void verify_permissions(insn_t insn, bool write) const override; + private: csr_t_p menvcfg; }; @@ -699,11 +701,13 @@ class sstateen_csr_t: public hstateen_csr_t { class fcsr_csr_t: public composite_csr_t { public: fcsr_csr_t(processor_t* const proc, const reg_t addr, csr_t_p upper_csr, csr_t_p lower_csr, const unsigned upper_lsb); + virtual void verify_permissions(insn_t insn, bool write) const override; }; class senvcfg_csr_t final: public masked_csr_t { public: senvcfg_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; }; #endif