aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riscv/csrs.cc33
-rw-r--r--riscv/csrs.h10
-rw-r--r--riscv/mmu.cc2
-rw-r--r--riscv/processor.cc26
-rw-r--r--riscv/processor.h2
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;