diff options
-rw-r--r-- | riscv/csrs.cc | 33 | ||||
-rw-r--r-- | riscv/csrs.h | 10 | ||||
-rw-r--r-- | riscv/mmu.cc | 2 | ||||
-rw-r--r-- | riscv/processor.cc | 26 | ||||
-rw-r--r-- | riscv/processor.h | 2 |
5 files changed, 46 insertions, 27 deletions
diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 2cd0299..1c47365 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -9,6 +9,10 @@ // For trap_virtual_instruction and trap_illegal_instruction: #include "trap.h" +// STATE macro used by require_privilege() macro: +#undef STATE +#define STATE (*state) + // implement class csr_t csr_t::csr_t(processor_t* const proc, const reg_t addr): @@ -929,3 +933,32 @@ void hypervisor_csr_t::verify_permissions(insn_t insn, bool write) const { if (!proc->extension_enabled('H')) throw trap_illegal_instruction(insn.bits()); } + + +hgatp_csr_t::hgatp_csr_t(processor_t* const proc, const reg_t addr): + basic_csr_t(proc, addr, 0) { +} + +void hgatp_csr_t::verify_permissions(insn_t insn, bool write) const { + basic_csr_t::verify_permissions(insn, write); + if (!state->v && get_field(state->mstatus->read(), MSTATUS_TVM)) + require_privilege(PRV_M); +} + +bool hgatp_csr_t::unlogged_write(const reg_t val) noexcept { + proc->get_mmu()->flush_tlb(); + + reg_t mask; + if (proc->get_const_xlen() == 32) { + mask = HGATP32_PPN | HGATP32_MODE; + } else { + mask = HGATP64_PPN & ((reg_t(1) << (MAX_PADDR_BITS - PGSHIFT)) - 1); + + if (get_field(val, HGATP64_MODE) == HGATP_MODE_OFF || + get_field(val, HGATP64_MODE) == HGATP_MODE_SV39X4 || + get_field(val, HGATP64_MODE) == HGATP_MODE_SV48X4) + mask |= HGATP64_MODE; + } + mask &= ~(reg_t)3; + return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask)); +} diff --git a/riscv/csrs.h b/riscv/csrs.h index ff9d85e..64b4716 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -499,4 +499,14 @@ class hypervisor_csr_t: public basic_csr_t { virtual void verify_permissions(insn_t insn, bool write) const override; }; + +class hgatp_csr_t: public basic_csr_t { + public: + hgatp_csr_t(processor_t* const proc, const reg_t addr); + virtual void verify_permissions(insn_t insn, bool write) const override; + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; +}; + + #endif diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 8cedd44..906694c 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -263,7 +263,7 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty if (!virt) return gpa; - vm_info vm = decode_vm_info(proc->get_const_xlen(), true, 0, proc->get_state()->hgatp); + vm_info vm = decode_vm_info(proc->get_const_xlen(), true, 0, proc->get_state()->hgatp->read()); if (vm.levels == 0) return gpa; diff --git a/riscv/processor.cc b/riscv/processor.cc index db55d51..39935f6 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -490,7 +490,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) csrmap[CSR_HCOUNTEREN] = hcounteren = std::make_shared<counteren_csr_t>(proc, CSR_HCOUNTEREN); csrmap[CSR_HTVAL] = htval = std::make_shared<basic_csr_t>(proc, CSR_HTVAL, 0); csrmap[CSR_HTINST] = htinst = std::make_shared<basic_csr_t>(proc, CSR_HTINST, 0); - hgatp = 0; + csrmap[CSR_HGATP] = hgatp = std::make_shared<hgatp_csr_t>(proc, CSR_HGATP); auto nonvirtual_sstatus = std::make_shared<sstatus_proxy_csr_t>(proc, CSR_SSTATUS, mstatus); csrmap[CSR_VSSTATUS] = vsstatus = std::make_shared<vsstatus_csr_t>(proc, CSR_VSSTATUS); csrmap[CSR_SSTATUS] = sstatus = std::make_shared<sstatus_csr_t>(proc, nonvirtual_sstatus, vsstatus); @@ -998,25 +998,6 @@ void processor_t::set_csr(int which, reg_t val) VU.vxsat = (val & VCSR_VXSAT) >> VCSR_VXSAT_SHIFT; VU.vxrm = (val & VCSR_VXRM) >> VCSR_VXRM_SHIFT; break; - case CSR_HGATP: { - mmu->flush_tlb(); - - reg_t mask; - if (max_xlen == 32) { - mask = HGATP32_PPN | HGATP32_MODE; - } else { - mask = HGATP64_PPN & ((reg_t(1) << (MAX_PADDR_BITS - PGSHIFT)) - 1); - - if (get_field(val, HGATP64_MODE) == HGATP_MODE_OFF || - get_field(val, HGATP64_MODE) == HGATP_MODE_SV39X4 || - get_field(val, HGATP64_MODE) == HGATP_MODE_SV48X4) - mask |= HGATP64_MODE; - } - mask &= ~(reg_t)3; - - state.hgatp = val & mask; - break; - } case CSR_TSELECT: if (val < state.num_triggers) { state.tselect = val; @@ -1186,11 +1167,6 @@ reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek) case CSR_MIMPID: ret(0); case CSR_MVENDORID: ret(0); case CSR_MHARTID: ret(id); - case CSR_HGATP: { - if (!state.v && get_field(state.mstatus->read(), MSTATUS_TVM)) - require_privilege(PRV_M); - ret(state.hgatp); - } case CSR_TSELECT: ret(state.tselect); case CSR_TDATA1: if (state.tselect < state.num_triggers) { diff --git a/riscv/processor.h b/riscv/processor.h index b34df1d..d1737c5 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -192,7 +192,7 @@ struct state_t csr_t_p hcounteren; csr_t_p htval; csr_t_p htinst; - reg_t hgatp; + csr_t_p hgatp; sstatus_csr_t_p sstatus; vsstatus_csr_t_p vsstatus; csr_t_p vstvec; |