diff options
-rw-r--r-- | riscv/csrs.cc | 15 | ||||
-rw-r--r-- | riscv/csrs.h | 8 | ||||
-rw-r--r-- | riscv/insns/hlv_b.h | 2 | ||||
-rw-r--r-- | riscv/insns/hlv_bu.h | 2 | ||||
-rw-r--r-- | riscv/insns/hlv_d.h | 2 | ||||
-rw-r--r-- | riscv/insns/hlv_h.h | 2 | ||||
-rw-r--r-- | riscv/insns/hlv_hu.h | 2 | ||||
-rw-r--r-- | riscv/insns/hlv_w.h | 2 | ||||
-rw-r--r-- | riscv/insns/hlv_wu.h | 2 | ||||
-rw-r--r-- | riscv/insns/hlvx_hu.h | 2 | ||||
-rw-r--r-- | riscv/insns/hlvx_wu.h | 2 | ||||
-rw-r--r-- | riscv/insns/hsv_b.h | 2 | ||||
-rw-r--r-- | riscv/insns/hsv_d.h | 2 | ||||
-rw-r--r-- | riscv/insns/hsv_h.h | 2 | ||||
-rw-r--r-- | riscv/insns/hsv_w.h | 2 | ||||
-rw-r--r-- | riscv/insns/sfence_vma.h | 2 | ||||
-rw-r--r-- | riscv/insns/sret.h | 4 | ||||
-rw-r--r-- | riscv/insns/wfi.h | 2 | ||||
-rw-r--r-- | riscv/mmu.cc | 2 | ||||
-rw-r--r-- | riscv/processor.cc | 18 | ||||
-rw-r--r-- | riscv/processor.h | 2 |
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; |