aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riscv/csrs.cc15
-rw-r--r--riscv/csrs.h8
-rw-r--r--riscv/insns/hlv_b.h2
-rw-r--r--riscv/insns/hlv_bu.h2
-rw-r--r--riscv/insns/hlv_d.h2
-rw-r--r--riscv/insns/hlv_h.h2
-rw-r--r--riscv/insns/hlv_hu.h2
-rw-r--r--riscv/insns/hlv_w.h2
-rw-r--r--riscv/insns/hlv_wu.h2
-rw-r--r--riscv/insns/hlvx_hu.h2
-rw-r--r--riscv/insns/hlvx_wu.h2
-rw-r--r--riscv/insns/hsv_b.h2
-rw-r--r--riscv/insns/hsv_d.h2
-rw-r--r--riscv/insns/hsv_h.h2
-rw-r--r--riscv/insns/hsv_w.h2
-rw-r--r--riscv/insns/sfence_vma.h2
-rw-r--r--riscv/insns/sret.h4
-rw-r--r--riscv/insns/wfi.h2
-rw-r--r--riscv/mmu.cc2
-rw-r--r--riscv/processor.cc18
-rw-r--r--riscv/processor.h2
21 files changed, 45 insertions, 34 deletions
diff --git a/riscv/csrs.cc b/riscv/csrs.cc
index 3d2a465..a5781f1 100644
--- a/riscv/csrs.cc
+++ b/riscv/csrs.cc
@@ -497,7 +497,7 @@ bool misa_csr_t::unlogged_write(const reg_t val) noexcept {
state->mstatus->write(state->mstatus->read() & ~(MSTATUS_GVA | MSTATUS_MPV));
state->mie->write_with_mask(MIP_HS_MASK, 0); // also takes care of hie, sie
state->mip->write_with_mask(MIP_HS_MASK, 0); // also takes care of hip, sip, hvip
- proc->set_csr(CSR_HSTATUS, 0);
+ state->hstatus->write(0);
}
return basic_csr_t::unlogged_write(new_misa);
@@ -703,3 +703,16 @@ bool medeleg_csr_t::unlogged_write(const reg_t val) noexcept {
;
return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask));
}
+
+
+// implement class hstatus_csr_t
+hstatus_csr_t::hstatus_csr_t(processor_t* const proc, const reg_t addr):
+ basic_csr_t(proc, addr, set_field((reg_t)0, HSTATUS_VSXL, xlen_to_uxl(proc->get_const_xlen()))) {
+}
+
+bool hstatus_csr_t::unlogged_write(const reg_t val) noexcept {
+ const reg_t mask = HSTATUS_VTSR | HSTATUS_VTW
+ | (proc->supports_impl(IMPL_MMU) ? HSTATUS_VTVM : 0)
+ | HSTATUS_HU | HSTATUS_SPVP | HSTATUS_SPV | HSTATUS_GVA;
+ return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask));
+}
diff --git a/riscv/csrs.h b/riscv/csrs.h
index 81fd5c3..0f69f2a 100644
--- a/riscv/csrs.h
+++ b/riscv/csrs.h
@@ -369,4 +369,12 @@ class medeleg_csr_t: public basic_csr_t {
};
+class hstatus_csr_t: public basic_csr_t {
+ public:
+ hstatus_csr_t(processor_t* const proc, const reg_t addr);
+ protected:
+ virtual bool unlogged_write(const reg_t val) noexcept override;
+};
+
+
#endif
diff --git a/riscv/insns/hlv_b.h b/riscv/insns/hlv_b.h
index 86192c6..2ccb046 100644
--- a/riscv/insns/hlv_b.h
+++ b/riscv/insns/hlv_b.h
@@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
-require_privilege(get_field(STATE.hstatus, HSTATUS_HU) ? PRV_U : PRV_S);
+require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_int8(RS1));
diff --git a/riscv/insns/hlv_bu.h b/riscv/insns/hlv_bu.h
index 2f95194..560f94a 100644
--- a/riscv/insns/hlv_bu.h
+++ b/riscv/insns/hlv_bu.h
@@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
-require_privilege(get_field(STATE.hstatus, HSTATUS_HU) ? PRV_U : PRV_S);
+require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_uint8(RS1));
diff --git a/riscv/insns/hlv_d.h b/riscv/insns/hlv_d.h
index 1bbd027..f432b65 100644
--- a/riscv/insns/hlv_d.h
+++ b/riscv/insns/hlv_d.h
@@ -1,5 +1,5 @@
require_extension('H');
require_rv64;
require_novirt();
-require_privilege(get_field(STATE.hstatus, HSTATUS_HU) ? PRV_U : PRV_S);
+require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_int64(RS1));
diff --git a/riscv/insns/hlv_h.h b/riscv/insns/hlv_h.h
index 6825fe4..4cb07e9 100644
--- a/riscv/insns/hlv_h.h
+++ b/riscv/insns/hlv_h.h
@@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
-require_privilege(get_field(STATE.hstatus, HSTATUS_HU) ? PRV_U : PRV_S);
+require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_int16(RS1));
diff --git a/riscv/insns/hlv_hu.h b/riscv/insns/hlv_hu.h
index 3d9d98e..adec2f0 100644
--- a/riscv/insns/hlv_hu.h
+++ b/riscv/insns/hlv_hu.h
@@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
-require_privilege(get_field(STATE.hstatus, HSTATUS_HU) ? PRV_U : PRV_S);
+require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_uint16(RS1));
diff --git a/riscv/insns/hlv_w.h b/riscv/insns/hlv_w.h
index be420d3..b2e102f 100644
--- a/riscv/insns/hlv_w.h
+++ b/riscv/insns/hlv_w.h
@@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
-require_privilege(get_field(STATE.hstatus, HSTATUS_HU) ? PRV_U : PRV_S);
+require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_int32(RS1));
diff --git a/riscv/insns/hlv_wu.h b/riscv/insns/hlv_wu.h
index 851be27..1f921c0 100644
--- a/riscv/insns/hlv_wu.h
+++ b/riscv/insns/hlv_wu.h
@@ -1,5 +1,5 @@
require_extension('H');
require_rv64;
require_novirt();
-require_privilege(get_field(STATE.hstatus, HSTATUS_HU) ? PRV_U : PRV_S);
+require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_uint32(RS1));
diff --git a/riscv/insns/hlvx_hu.h b/riscv/insns/hlvx_hu.h
index 19dbcfb..3eb699c 100644
--- a/riscv/insns/hlvx_hu.h
+++ b/riscv/insns/hlvx_hu.h
@@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
-require_privilege(get_field(STATE.hstatus, HSTATUS_HU) ? PRV_U : PRV_S);
+require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_x_uint16(RS1));
diff --git a/riscv/insns/hlvx_wu.h b/riscv/insns/hlvx_wu.h
index a395230..33e2fa1 100644
--- a/riscv/insns/hlvx_wu.h
+++ b/riscv/insns/hlvx_wu.h
@@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
-require_privilege(get_field(STATE.hstatus, HSTATUS_HU) ? PRV_U : PRV_S);
+require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(sext_xlen(MMU.guest_load_x_uint32(RS1)));
diff --git a/riscv/insns/hsv_b.h b/riscv/insns/hsv_b.h
index a5c34ff..15f6a26 100644
--- a/riscv/insns/hsv_b.h
+++ b/riscv/insns/hsv_b.h
@@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
-require_privilege(get_field(STATE.hstatus, HSTATUS_HU) ? PRV_U : PRV_S);
+require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
MMU.guest_store_uint8(RS1, RS2);
diff --git a/riscv/insns/hsv_d.h b/riscv/insns/hsv_d.h
index 14c6d5d..83c3376 100644
--- a/riscv/insns/hsv_d.h
+++ b/riscv/insns/hsv_d.h
@@ -1,5 +1,5 @@
require_extension('H');
require_rv64;
require_novirt();
-require_privilege(get_field(STATE.hstatus, HSTATUS_HU) ? PRV_U : PRV_S);
+require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
MMU.guest_store_uint64(RS1, RS2);
diff --git a/riscv/insns/hsv_h.h b/riscv/insns/hsv_h.h
index 1cfe77a..eaa2a2c 100644
--- a/riscv/insns/hsv_h.h
+++ b/riscv/insns/hsv_h.h
@@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
-require_privilege(get_field(STATE.hstatus, HSTATUS_HU) ? PRV_U : PRV_S);
+require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
MMU.guest_store_uint16(RS1, RS2);
diff --git a/riscv/insns/hsv_w.h b/riscv/insns/hsv_w.h
index d54f673..0d2c3d4 100644
--- a/riscv/insns/hsv_w.h
+++ b/riscv/insns/hsv_w.h
@@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
-require_privilege(get_field(STATE.hstatus, HSTATUS_HU) ? PRV_U : PRV_S);
+require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
MMU.guest_store_uint32(RS1, RS2);
diff --git a/riscv/insns/sfence_vma.h b/riscv/insns/sfence_vma.h
index a14865f..7d6c01a 100644
--- a/riscv/insns/sfence_vma.h
+++ b/riscv/insns/sfence_vma.h
@@ -1,7 +1,7 @@
require_extension('S');
require_impl(IMPL_MMU);
if (STATE.v) {
- if (STATE.prv == PRV_U || get_field(STATE.hstatus, HSTATUS_VTVM))
+ if (STATE.prv == PRV_U || get_field(STATE.hstatus->read(), HSTATUS_VTVM))
require_novirt();
} else {
require_privilege(get_field(STATE.mstatus->read(), MSTATUS_TVM) ? PRV_M : PRV_S);
diff --git a/riscv/insns/sret.h b/riscv/insns/sret.h
index 8436cda..72b44ef 100644
--- a/riscv/insns/sret.h
+++ b/riscv/insns/sret.h
@@ -1,6 +1,6 @@
require_extension('S');
if (STATE.v) {
- if (STATE.prv == PRV_U || get_field(STATE.hstatus, HSTATUS_VTSR))
+ if (STATE.prv == PRV_U || get_field(STATE.hstatus->read(), HSTATUS_VTSR))
require_novirt();
} else {
require_privilege(get_field(STATE.mstatus->read(), MSTATUS_TSR) ? PRV_M : PRV_S);
@@ -17,6 +17,6 @@ s = set_field(s, MSTATUS_SPP, PRV_U);
STATE.sstatus->write(s);
p->set_privilege(prev_prv);
if (!STATE.v) {
- reg_t prev_virt = get_field(STATE.hstatus, HSTATUS_SPV);
+ reg_t prev_virt = get_field(STATE.hstatus->read(), HSTATUS_SPV);
p->set_virt(prev_virt);
}
diff --git a/riscv/insns/wfi.h b/riscv/insns/wfi.h
index efe62fd..299cb01 100644
--- a/riscv/insns/wfi.h
+++ b/riscv/insns/wfi.h
@@ -3,7 +3,7 @@ if (STATE.v && STATE.prv == PRV_U) {
} else if (get_field(STATE.mstatus->read(), MSTATUS_TW)) {
require_privilege(PRV_M);
} else if (STATE.v) { // VS-mode
- if (get_field(STATE.hstatus, HSTATUS_VTW))
+ if (get_field(STATE.hstatus->read(), HSTATUS_VTW))
require_novirt();
} else {
require_privilege(PRV_S);
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index 0d6509a..b880739 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -64,7 +64,7 @@ reg_t mmu_t::translate(reg_t addr, reg_t len, access_type type, uint32_t xlate_f
}
if (xlate_flags & RISCV_XLATE_VIRT) {
virt = true;
- mode = get_field(proc->state.hstatus, HSTATUS_SPVP);
+ mode = get_field(proc->state.hstatus->read(), HSTATUS_SPVP);
}
}
diff --git a/riscv/processor.cc b/riscv/processor.cc
index cca1396..e84ef4d 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -416,7 +416,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
csrmap[CSR_SCAUSE] = scause = std::make_shared<virtualized_csr_t>(proc, nonvirtual_scause, vscause);
mtval2 = 0;
mtinst = 0;
- hstatus = 0;
+ csrmap[CSR_HSTATUS] = hstatus = std::make_shared<hstatus_csr_t>(proc, CSR_HSTATUS);
hideleg = 0;
hedeleg = 0;
hcounteren = 0;
@@ -545,7 +545,6 @@ void processor_t::reset()
state.reset(this, max_isa);
state.dcsr.halt = halt_on_reset;
halt_on_reset = false;
- set_csr(CSR_HSTATUS, state.hstatus); // set VSXL
VU.reset();
if (n_pmp > 0) {
@@ -828,12 +827,12 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
s = set_field(s, MSTATUS_SIE, 0);
state.sstatus->write(s);
if (extension_enabled('H')) {
- s = state.hstatus;
+ s = state.hstatus->read();
if (curr_virt)
s = set_field(s, HSTATUS_SPVP, state.prv);
s = set_field(s, HSTATUS_SPV, curr_virt);
s = set_field(s, HSTATUS_GVA, t.has_gva());
- set_csr(CSR_HSTATUS, s);
+ state.hstatus->write(s);
}
set_privilege(PRV_S);
} else {
@@ -1012,14 +1011,6 @@ void processor_t::set_csr(int which, reg_t val)
break;
case CSR_MTVAL2: state.mtval2 = val; break;
case CSR_MTINST: state.mtinst = val; break;
- case CSR_HSTATUS: {
- reg_t mask = HSTATUS_VTSR | HSTATUS_VTW
- | (supports_impl(IMPL_MMU) ? HSTATUS_VTVM : 0)
- | HSTATUS_HU | HSTATUS_SPVP | HSTATUS_SPV | HSTATUS_GVA;
- state.hstatus = set_field(state.hstatus, HSTATUS_VSXL, xlen_to_uxl(max_xlen));
- state.hstatus = (state.hstatus & ~mask) | (val & mask);
- break;
- }
case CSR_HEDELEG: {
reg_t mask =
(1 << CAUSE_MISALIGNED_FETCH) |
@@ -1330,7 +1321,7 @@ reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek)
case CSR_MCOUNTINHIBIT: ret(0);
case CSR_SATP: {
if (state.v) {
- if (get_field(state.hstatus, HSTATUS_VTVM))
+ if (get_field(state.hstatus->read(), HSTATUS_VTVM))
goto throw_virtual;
ret(state.vsatp);
} else {
@@ -1355,7 +1346,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_HSTATUS: ret(state.hstatus);
case CSR_HEDELEG: ret(state.hedeleg);
case CSR_HIDELEG: ret(state.hideleg);
case CSR_HCOUNTEREN: ret(state.hcounteren);
diff --git a/riscv/processor.h b/riscv/processor.h
index df34319..9123976 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -189,7 +189,7 @@ struct state_t
reg_t mtval2;
reg_t mtinst;
- reg_t hstatus;
+ csr_t_p hstatus;
reg_t hideleg;
reg_t hedeleg;
uint32_t hcounteren;