From 84a98f6f718cd482710238042eac3d2b855c6768 Mon Sep 17 00:00:00 2001 From: "soberl@nvidia.com" Date: Tue, 3 May 2022 19:38:07 -0700 Subject: Implement the new csr mseccfg for ePMP as dummy --- riscv/csrs.cc | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 98edacf..c887c4e 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1,5 +1,8 @@ // See LICENSE for license details. +// For std::any_of +#include + #include "csrs.h" // For processor_t: #include "processor.h" @@ -227,6 +230,46 @@ bool pmpcfg_csr_t::unlogged_write(const reg_t val) noexcept { return write_success; } +// implement class mseccfg_csr_t +mseccfg_csr_t::mseccfg_csr_t(processor_t* const proc, const reg_t addr): + basic_csr_t(proc, addr, 0) { +} + +bool mseccfg_csr_t::get_mml() const noexcept { + return (read() & MSECCFG_MML); +} + +bool mseccfg_csr_t::get_mmwp() const noexcept { + return (read() & MSECCFG_MMWP); +} + +bool mseccfg_csr_t::get_rlb() const noexcept { + return (read() & MSECCFG_RLB); +} + +bool mseccfg_csr_t::unlogged_write(const reg_t val) noexcept { + if (proc->n_pmp == 0) + return false; + + // pmpcfg.L is 1 in any rule or entry (including disabled entries) + const bool pmplock_recorded = std::any_of(state->pmpaddr, state->pmpaddr + proc->n_pmp, + [](const pmpaddr_csr_t_p & c) { return c->is_locked(); } ); + reg_t new_val = read(); + + // When RLB is 0 and pmplock_recorded, RLB is locked to 0. + // Otherwise set the RLB bit according val + if (!(pmplock_recorded && (read() & MSECCFG_RLB) == 0)) { + new_val &= ~MSECCFG_RLB; + new_val |= (val & MSECCFG_RLB); + } + + new_val |= (val & MSECCFG_MMWP); //MMWP is sticky + new_val |= (val & MSECCFG_MML); //MML is sticky + + proc->get_mmu()->flush_tlb(); + + return basic_csr_t::unlogged_write(new_val); +} // implement class virtualized_csr_t virtualized_csr_t::virtualized_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt): -- cgit v1.1 From af500657c3ecde57fb88ed027dbdaa5da72a1c4b Mon Sep 17 00:00:00 2001 From: "soberl@nvidia.com" Date: Tue, 3 May 2022 19:49:21 -0700 Subject: Update csr access rules for ePMP on pmpaddr and pmpcfg --- riscv/csrs.cc | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index c887c4e..1e9b544 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -120,7 +120,9 @@ bool pmpaddr_csr_t::unlogged_write(const reg_t val) noexcept { if (proc->n_pmp == 0) return false; - bool locked = cfg & PMP_L; + const bool lock_bypass = state->mseccfg->get_rlb(); + const bool locked = !lock_bypass && (cfg & PMP_L); + if (pmpidx < proc->n_pmp && !locked && !next_locked_and_tor()) { this->val = val & ((reg_t(1) << (MAX_PADDR_BITS - PMP_SHIFT)) - 1); } @@ -132,8 +134,9 @@ bool pmpaddr_csr_t::unlogged_write(const reg_t val) noexcept { bool pmpaddr_csr_t::next_locked_and_tor() const noexcept { if (pmpidx+1 >= state->max_pmp) return false; // this is the last entry - bool next_locked = state->pmpaddr[pmpidx+1]->cfg & PMP_L; - bool next_tor = (state->pmpaddr[pmpidx+1]->cfg & PMP_A) == PMP_TOR; + const bool lock_bypass = state->mseccfg->get_rlb(); + const bool next_locked = !lock_bypass && (state->pmpaddr[pmpidx+1]->cfg & PMP_L); + const bool next_tor = (state->pmpaddr[pmpidx+1]->cfg & PMP_A) == PMP_TOR; return next_locked && next_tor; } @@ -214,14 +217,35 @@ bool pmpcfg_csr_t::unlogged_write(const reg_t val) noexcept { return false; bool write_success = false; + const bool rlb = state->mseccfg->get_rlb(); + const bool mml = state->mseccfg->get_mml(); for (size_t i0 = (address - CSR_PMPCFG0) * 4, i = i0; i < i0 + proc->get_xlen() / 8; i++) { if (i < proc->n_pmp) { - if (!(state->pmpaddr[i]->cfg & PMP_L)) { + const bool locked = (state->pmpaddr[i]->cfg & PMP_L); + if (rlb || (!locked && !state->pmpaddr[i]->next_locked_and_tor())) { uint8_t cfg = (val >> (8 * (i - i0))) & (PMP_R | PMP_W | PMP_X | PMP_A | PMP_L); - cfg &= ~PMP_W | ((cfg & PMP_R) ? PMP_W : 0); // Disallow R=0 W=1 + // Drop R=0 W=1 when MML = 0 + // Remove the restriction when MML = 1 + if (!mml) { + cfg &= ~PMP_W | ((cfg & PMP_R) ? PMP_W : 0); + } + // Disallow A=NA4 when granularity > 4 if (proc->lg_pmp_granularity != PMP_SHIFT && (cfg & PMP_A) == PMP_NA4) - cfg |= PMP_NAPOT; // Disallow A=NA4 when granularity > 4 - state->pmpaddr[i]->cfg = cfg; + cfg |= PMP_NAPOT; + /* + * Adding a rule with executable privileges that either is M-mode-only or a locked Shared-Region + * is not possible and such pmpcfg writes are ignored, leaving pmpcfg unchanged. + * This restriction can be temporarily lifted e.g. during the boot process, by setting mseccfg.RLB. + */ + const bool cfgx = cfg & PMP_X; + const bool cfgw = cfg & PMP_W; + const bool cfgr = cfg & PMP_R; + if (rlb || !(mml && ((cfg & PMP_L) // M-mode-only or a locked Shared-Region + && !(cfgx && cfgw && cfgr) // RWX = 111 is allowed + && (cfgx || (cfgw && !cfgr)) // X=1 or RW=01 is not allowed + ))) { + state->pmpaddr[i]->cfg = cfg; + } } write_success = true; } -- cgit v1.1 From b0fdd88d26ef4b20023e1d2a79cfcb1e9df047de Mon Sep 17 00:00:00 2001 From: "soberl@nvidia.com" Date: Tue, 3 May 2022 19:56:01 -0700 Subject: Update pmpaddr_csr_t::access_ok() for ePMP on matching regions --- riscv/csrs.cc | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 1e9b544..8366d8a 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -192,11 +192,37 @@ bool pmpaddr_csr_t::subset_match(reg_t addr, reg_t len) const noexcept { bool pmpaddr_csr_t::access_ok(access_type type, reg_t mode) const noexcept { - return - (mode == PRV_M && !(cfg & PMP_L)) || - (type == LOAD && (cfg & PMP_R)) || - (type == STORE && (cfg & PMP_W)) || - (type == FETCH && (cfg & PMP_X)); + const bool cfgx = cfg & PMP_X; + const bool cfgw = cfg & PMP_W; + const bool cfgr = cfg & PMP_R; + const bool cfgl = cfg & PMP_L; + + const bool prvm = mode == PRV_M; + + const bool typer = type == LOAD; + const bool typex = type == FETCH; + const bool typew = type == STORE; + const bool normal_rwx = (typer && cfgr) || (typew && cfgw) || (typex && cfgx); + const bool mseccfg_mml = state->mseccfg->get_mml(); + + if (mseccfg_mml) { + if (cfgx && cfgw && cfgr && cfgl) { + // Locked Shared data region: Read only on both M and S/U mode. + return typer; + } else { + const bool mml_shared_region = !cfgr && cfgw; + const bool mml_chk_normal = (prvm == cfgl) && normal_rwx; + const bool mml_chk_shared = + (!cfgl && cfgx && (typer || typew)) || + (!cfgl && !cfgx && (typer || (typew && prvm))) || + (cfgl && typex) || + (cfgl && typer && cfgx && prvm); + return mml_shared_region ? mml_chk_shared : mml_chk_normal; + } + } else { + const bool m_bypass = (prvm && !cfgl); + return m_bypass || normal_rwx; + } } -- cgit v1.1 From fc35f34fd0f5307354cc25ae8018cda62f834e25 Mon Sep 17 00:00:00 2001 From: Ryan Buchner Date: Tue, 10 May 2022 15:22:11 -0700 Subject: Change henvcfg csr to a henvcfg_csr_t To do so implemented henvcfg_csr_t. henvcfg.PBMTE will be read only 0 if menvcfg.PBMTE = 0. --- riscv/csrs.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 8366d8a..3d6cf91 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -840,6 +840,13 @@ bool masked_csr_t::unlogged_write(const reg_t val) noexcept { } +// implement class henvcfg_csr_t +henvcfg_csr_t::henvcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init, csr_t_p menvcfg): + masked_csr_t(proc, addr, mask, init), + menvcfg(menvcfg) { +} + + // implement class base_atp_csr_t and family base_atp_csr_t::base_atp_csr_t(processor_t* const proc, const reg_t addr): basic_csr_t(proc, addr, 0) { -- cgit v1.1 From 68b3eb9bf1c04c19a66631f717163dd9ba2c923c Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 26 May 2022 14:21:07 -0700 Subject: Fix RV32 hgatp write mask computation (#1014) clang with `-Wall` happened to catch this. --- riscv/csrs.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 3d6cf91..6bca99c 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1075,7 +1075,7 @@ bool hgatp_csr_t::unlogged_write(const reg_t val) noexcept { if (proc->get_const_xlen() == 32) { mask = HGATP32_PPN | HGATP32_MODE | - proc->supports_impl(IMPL_MMU_VMID) ? HGATP32_VMID : 0; + (proc->supports_impl(IMPL_MMU_VMID) ? HGATP32_VMID : 0); } else { mask = (HGATP64_PPN & ((reg_t(1) << (MAX_PADDR_BITS - PGSHIFT)) - 1)) | (proc->supports_impl(IMPL_MMU_VMID) ? HGATP64_VMID : 0); -- cgit v1.1 From 2aedbdd01911a42565cd6d154f82fa00a66410cd Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Fri, 1 Jul 2022 16:09:02 +0800 Subject: remove multi blank lines --- riscv/csrs.cc | 63 ----------------------------------------------------------- 1 file changed, 63 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 6bca99c..7d1be10 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -18,7 +18,6 @@ #undef STATE #define STATE (*state) - // implement class csr_t csr_t::csr_t(processor_t* const proc, const reg_t addr): proc(proc), @@ -47,7 +46,6 @@ void csr_t::verify_permissions(insn_t insn, bool write) const { } } - csr_t::~csr_t() { } @@ -83,7 +81,6 @@ bool basic_csr_t::unlogged_write(const reg_t val) noexcept { return true; } - // implement class pmpaddr_csr_t pmpaddr_csr_t::pmpaddr_csr_t(processor_t* const proc, const reg_t addr): csr_t(proc, addr), @@ -92,7 +89,6 @@ pmpaddr_csr_t::pmpaddr_csr_t(processor_t* const proc, const reg_t addr): pmpidx(address - CSR_PMPADDR0) { } - void pmpaddr_csr_t::verify_permissions(insn_t insn, bool write) const { csr_t::verify_permissions(insn, write); // If n_pmp is zero, that means pmp is not implemented hence raise @@ -103,14 +99,12 @@ void pmpaddr_csr_t::verify_permissions(insn_t insn, bool write) const { throw trap_illegal_instruction(insn.bits()); } - reg_t pmpaddr_csr_t::read() const noexcept { if ((cfg & PMP_A) >= PMP_NAPOT) return val | (~proc->pmp_tor_mask() >> 1); return val & proc->pmp_tor_mask(); } - bool pmpaddr_csr_t::unlogged_write(const reg_t val) noexcept { // If no PMPs are configured, disallow access to all. Otherwise, // allow access to all, but unimplemented ones are hardwired to @@ -140,25 +134,21 @@ bool pmpaddr_csr_t::next_locked_and_tor() const noexcept { return next_locked && next_tor; } - reg_t pmpaddr_csr_t::tor_paddr() const noexcept { return (val & proc->pmp_tor_mask()) << PMP_SHIFT; } - reg_t pmpaddr_csr_t::tor_base_paddr() const noexcept { if (pmpidx == 0) return 0; // entry 0 always uses 0 as base return state->pmpaddr[pmpidx-1]->tor_paddr(); } - reg_t pmpaddr_csr_t::napot_mask() const noexcept { bool is_na4 = (cfg & PMP_A) == PMP_NA4; reg_t mask = (val << 1) | (!is_na4) | ~proc->pmp_tor_mask(); return ~(mask & ~(mask + 1)) << PMP_SHIFT; } - bool pmpaddr_csr_t::match4(reg_t addr) const noexcept { if ((cfg & PMP_A) == 0) return false; bool is_tor = (cfg & PMP_A) == PMP_TOR; @@ -167,7 +157,6 @@ bool pmpaddr_csr_t::match4(reg_t addr) const noexcept { return ((addr ^ tor_paddr()) & napot_mask()) == 0; } - bool pmpaddr_csr_t::subset_match(reg_t addr, reg_t len) const noexcept { if ((addr | len) & (len - 1)) abort(); @@ -190,7 +179,6 @@ bool pmpaddr_csr_t::subset_match(reg_t addr, reg_t len) const noexcept { return !(is_tor ? tor_homogeneous : napot_homogeneous); } - bool pmpaddr_csr_t::access_ok(access_type type, reg_t mode) const noexcept { const bool cfgx = cfg & PMP_X; const bool cfgw = cfg & PMP_W; @@ -225,7 +213,6 @@ bool pmpaddr_csr_t::access_ok(access_type type, reg_t mode) const noexcept { } } - // implement class pmpcfg_csr_t pmpcfg_csr_t::pmpcfg_csr_t(processor_t* const proc, const reg_t addr): csr_t(proc, addr) { @@ -328,7 +315,6 @@ virtualized_csr_t::virtualized_csr_t(processor_t* const proc, csr_t_p orig, csr_ virt_csr(virt) { } - reg_t virtualized_csr_t::read() const noexcept { return readvirt(state->v); } @@ -345,49 +331,41 @@ bool virtualized_csr_t::unlogged_write(const reg_t val) noexcept { return false; // virt_csr or orig_csr has already logged } - // implement class epc_csr_t epc_csr_t::epc_csr_t(processor_t* const proc, const reg_t addr): csr_t(proc, addr), val(0) { } - reg_t epc_csr_t::read() const noexcept { return val & proc->pc_alignment_mask(); } - bool epc_csr_t::unlogged_write(const reg_t val) noexcept { this->val = val & ~(reg_t)1; return true; } - // implement class tvec_csr_t tvec_csr_t::tvec_csr_t(processor_t* const proc, const reg_t addr): csr_t(proc, addr), val(0) { } - reg_t tvec_csr_t::read() const noexcept { return val; } - bool tvec_csr_t::unlogged_write(const reg_t val) noexcept { this->val = val & ~(reg_t)2; return true; } - // implement class cause_csr_t cause_csr_t::cause_csr_t(processor_t* const proc, const reg_t addr): basic_csr_t(proc, addr, 0) { } - reg_t cause_csr_t::read() const noexcept { reg_t val = basic_csr_t::read(); // When reading, the interrupt bit needs to adjust to xlen. Spike does @@ -398,7 +376,6 @@ reg_t cause_csr_t::read() const noexcept { return val; } - // implement class base_status_csr_t base_status_csr_t::base_status_csr_t(processor_t* const proc, const reg_t addr): csr_t(proc, addr), @@ -408,7 +385,6 @@ base_status_csr_t::base_status_csr_t(processor_t* const proc, const reg_t addr): | (proc->get_const_xlen() == 32 ? SSTATUS32_SD : SSTATUS64_SD)) { } - reg_t base_status_csr_t::compute_sstatus_write_mask() const noexcept { // If a configuration has FS bits, they will always be accessible no // matter the state of misa. @@ -424,7 +400,6 @@ reg_t base_status_csr_t::compute_sstatus_write_mask() const noexcept { ; } - reg_t base_status_csr_t::adjust_sd(const reg_t val) const noexcept { // This uses get_const_xlen() instead of get_xlen() not only because // the variable is static, so it's only called once, but also @@ -440,7 +415,6 @@ reg_t base_status_csr_t::adjust_sd(const reg_t val) const noexcept { return val & ~sd_bit; } - void base_status_csr_t::maybe_flush_tlb(const reg_t newval) noexcept { if ((newval ^ read()) & (MSTATUS_MPP | MSTATUS_MPRV @@ -449,7 +423,6 @@ void base_status_csr_t::maybe_flush_tlb(const reg_t newval) noexcept { proc->get_mmu()->flush_tlb(); } - namespace { int xlen_to_uxl(int xlen) { if (xlen == 32) @@ -460,7 +433,6 @@ namespace { } } - // implement class vsstatus_csr_t vsstatus_csr_t::vsstatus_csr_t(processor_t* const proc, const reg_t addr): base_status_csr_t(proc, addr), @@ -474,7 +446,6 @@ bool vsstatus_csr_t::unlogged_write(const reg_t val) noexcept { return true; } - // implement class sstatus_proxy_csr_t sstatus_proxy_csr_t::sstatus_proxy_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus): base_status_csr_t(proc, addr), @@ -488,7 +459,6 @@ bool sstatus_proxy_csr_t::unlogged_write(const reg_t val) noexcept { return false; // avoid double logging: already logged by mstatus->write() } - // implement class mstatus_csr_t mstatus_csr_t::mstatus_csr_t(processor_t* const proc, const reg_t addr): base_status_csr_t(proc, addr), @@ -503,7 +473,6 @@ mstatus_csr_t::mstatus_csr_t(processor_t* const proc, const reg_t addr): ) { } - bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept { const bool has_mpv = proc->extension_enabled('S') && proc->extension_enabled('H'); const bool has_gva = has_mpv; @@ -576,7 +545,6 @@ bool sstatus_csr_t::enabled(const reg_t which) { return false; } - // implement class misa_csr_t misa_csr_t::misa_csr_t(processor_t* const proc, const reg_t addr, const reg_t max_isa): basic_csr_t(proc, addr, max_isa), @@ -637,7 +605,6 @@ bool misa_csr_t::extension_enabled_const(unsigned char ext) const noexcept { return extension_enabled(ext); } - // implement class mip_or_mie_csr_t mip_or_mie_csr_t::mip_or_mie_csr_t(processor_t* const proc, const reg_t addr): csr_t(proc, addr), @@ -658,7 +625,6 @@ bool mip_or_mie_csr_t::unlogged_write(const reg_t val) noexcept { return false; // avoid double logging: already logged by write_with_mask() } - mip_csr_t::mip_csr_t(processor_t* const proc, const reg_t addr): mip_or_mie_csr_t(proc, addr) { } @@ -680,12 +646,10 @@ reg_t mip_csr_t::write_mask() const noexcept { (MIP_SEIP | MIP_SSIP | MIP_STIP | vssip_int); } - mie_csr_t::mie_csr_t(processor_t* const proc, const reg_t addr): mip_or_mie_csr_t(proc, addr) { } - reg_t mie_csr_t::write_mask() const noexcept { const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | MIP_STIP | MIP_SEIP : 0; const reg_t hypervisor_ints = proc->extension_enabled('H') ? MIP_HS_MASK : 0; @@ -695,7 +659,6 @@ reg_t mie_csr_t::write_mask() const noexcept { return all_ints; } - // implement class generic_int_accessor_t generic_int_accessor_t::generic_int_accessor_t(state_t* const state, const reg_t read_mask, @@ -736,7 +699,6 @@ reg_t generic_int_accessor_t::deleg_mask() const { return hideleg_mask & mideleg_mask; } - // implement class mip_proxy_csr_t mip_proxy_csr_t::mip_proxy_csr_t(processor_t* const proc, const reg_t addr, generic_int_accessor_t_p accr): csr_t(proc, addr), @@ -767,7 +729,6 @@ bool mie_proxy_csr_t::unlogged_write(const reg_t val) noexcept { return false; // accr has already logged } - // implement class mideleg_csr_t mideleg_csr_t::mideleg_csr_t(processor_t* const proc, const reg_t addr): basic_csr_t(proc, addr, 0) { @@ -795,7 +756,6 @@ bool mideleg_csr_t::unlogged_write(const reg_t val) noexcept { return basic_csr_t::unlogged_write(val & delegable_ints); } - // implement class medeleg_csr_t medeleg_csr_t::medeleg_csr_t(processor_t* const proc, const reg_t addr): basic_csr_t(proc, addr, 0), @@ -828,7 +788,6 @@ bool medeleg_csr_t::unlogged_write(const reg_t val) noexcept { return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask)); } - // implement class masked_csr_t masked_csr_t::masked_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init): basic_csr_t(proc, addr, init), @@ -839,20 +798,17 @@ bool masked_csr_t::unlogged_write(const reg_t val) noexcept { return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask)); } - // implement class henvcfg_csr_t henvcfg_csr_t::henvcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init, csr_t_p menvcfg): masked_csr_t(proc, addr, mask, init), menvcfg(menvcfg) { } - // implement class base_atp_csr_t and family base_atp_csr_t::base_atp_csr_t(processor_t* const proc, const reg_t addr): basic_csr_t(proc, addr, 0) { } - bool base_atp_csr_t::unlogged_write(const reg_t val) noexcept { const reg_t newval = proc->supports_impl(IMPL_MMU) ? compute_new_satp(val) : 0; if (newval != read()) @@ -926,7 +882,6 @@ bool virtualized_satp_csr_t::unlogged_write(const reg_t val) noexcept { return virtualized_csr_t::unlogged_write(newval); } - // implement class wide_counter_csr_t wide_counter_csr_t::wide_counter_csr_t(processor_t* const proc, const reg_t addr): csr_t(proc, addr), @@ -966,7 +921,6 @@ void wide_counter_csr_t::write_upper_half(const reg_t val) noexcept { log_special_write(address + (CSR_MINSTRETH - CSR_MINSTRET), written_value() >> 32); } - counter_top_csr_t::counter_top_csr_t(processor_t* const proc, const reg_t addr, wide_counter_csr_t_p parent): csr_t(proc, addr), parent(parent) { @@ -981,7 +935,6 @@ bool counter_top_csr_t::unlogged_write(const reg_t val) noexcept { return true; } - proxy_csr_t::proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate): csr_t(proc, addr), delegate(delegate) { @@ -996,7 +949,6 @@ bool proxy_csr_t::unlogged_write(const reg_t val) noexcept { return false; } - const_csr_t::const_csr_t(processor_t* const proc, const reg_t addr, reg_t val): csr_t(proc, addr), val(val) { @@ -1010,7 +962,6 @@ bool const_csr_t::unlogged_write(const reg_t val) noexcept { return false; } - counter_proxy_csr_t::counter_proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate): proxy_csr_t(proc, addr, delegate) { } @@ -1036,7 +987,6 @@ void counter_proxy_csr_t::verify_permissions(insn_t insn, bool write) const { } } - hypervisor_csr_t::hypervisor_csr_t(processor_t* const proc, const reg_t addr): basic_csr_t(proc, addr, 0) { } @@ -1047,7 +997,6 @@ void hypervisor_csr_t::verify_permissions(insn_t insn, bool write) const { throw trap_illegal_instruction(insn.bits()); } - hideleg_csr_t::hideleg_csr_t(processor_t* const proc, const reg_t addr, csr_t_p mideleg): masked_csr_t(proc, addr, MIP_VS_MASK, 0), mideleg(mideleg) { @@ -1057,7 +1006,6 @@ reg_t hideleg_csr_t::read() const noexcept { return masked_csr_t::read() & mideleg->read(); }; - hgatp_csr_t::hgatp_csr_t(processor_t* const proc, const reg_t addr): basic_csr_t(proc, addr, 0) { } @@ -1090,7 +1038,6 @@ bool hgatp_csr_t::unlogged_write(const reg_t val) noexcept { return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask)); } - tselect_csr_t::tselect_csr_t(processor_t* const proc, const reg_t addr): basic_csr_t(proc, addr, 0) { } @@ -1099,7 +1046,6 @@ bool tselect_csr_t::unlogged_write(const reg_t val) noexcept { return basic_csr_t::unlogged_write((val < proc->TM.count()) ? val : read()); } - tdata1_csr_t::tdata1_csr_t(processor_t* const proc, const reg_t addr): csr_t(proc, addr) { } @@ -1112,7 +1058,6 @@ bool tdata1_csr_t::unlogged_write(const reg_t val) noexcept { return proc->TM.tdata1_write(proc, state->tselect->read(), val); } - tdata2_csr_t::tdata2_csr_t(processor_t* const proc, const reg_t addr): csr_t(proc, addr) { } @@ -1125,7 +1070,6 @@ bool tdata2_csr_t::unlogged_write(const reg_t val) noexcept { return proc->TM.tdata2_write(proc, state->tselect->read(), val); } - debug_mode_csr_t::debug_mode_csr_t(processor_t* const proc, const reg_t addr): basic_csr_t(proc, addr, 0) { } @@ -1146,7 +1090,6 @@ void dpc_csr_t::verify_permissions(insn_t insn, bool write) const { throw trap_illegal_instruction(insn.bits()); } - dcsr_csr_t::dcsr_csr_t(processor_t* const proc, const reg_t addr): csr_t(proc, addr), prv(0), @@ -1198,7 +1141,6 @@ void dcsr_csr_t::write_cause_and_prv(uint8_t cause, reg_t prv) noexcept { log_write(); } - float_csr_t::float_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) { } @@ -1215,7 +1157,6 @@ bool float_csr_t::unlogged_write(const reg_t val) noexcept { return masked_csr_t::unlogged_write(val); } - composite_csr_t::composite_csr_t(processor_t* const proc, const reg_t addr, csr_t_p upper_csr, csr_t_p lower_csr, const unsigned upper_lsb): csr_t(proc, addr), upper_csr(upper_csr), @@ -1239,7 +1180,6 @@ bool composite_csr_t::unlogged_write(const reg_t val) noexcept { return false; // logging is done only by the underlying CSRs } - seed_csr_t::seed_csr_t(processor_t* const proc, const reg_t addr): csr_t(proc, addr) { } @@ -1261,8 +1201,6 @@ bool seed_csr_t::unlogged_write(const reg_t val) noexcept { return true; } - - vector_csr_t::vector_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init): basic_csr_t(proc, addr, init), mask(mask) { @@ -1287,7 +1225,6 @@ bool vector_csr_t::unlogged_write(const reg_t val) noexcept { return basic_csr_t::unlogged_write(val & mask); } - vxsat_csr_t::vxsat_csr_t(processor_t* const proc, const reg_t addr): masked_csr_t(proc, addr, /*mask*/ 1, /*init*/ 0) { } -- cgit v1.1 From 9b66f89b8102f032f721fe332819325508aa3b95 Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Wed, 6 Jul 2022 10:43:57 +0800 Subject: modify mstatush_csr_t to general rv32_high_csr_t --- riscv/csrs.cc | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 7d1be10..b8fa920 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -493,19 +493,23 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept { return true; } -// implement class mstatush_csr_t -mstatush_csr_t::mstatush_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus): +// implement class rv32_high_csr_t +rv32_high_csr_t::rv32_high_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, csr_t_p orig): csr_t(proc, addr), - mstatus(mstatus), - mask(MSTATUSH_MPV | MSTATUSH_GVA | MSTATUSH_SBE | MSTATUSH_MBE) { + orig(orig), + mask(mask) { +} + +reg_t rv32_high_csr_t::read() const noexcept { + return (orig->read() >> 32) & mask; } -reg_t mstatush_csr_t::read() const noexcept { - return (mstatus->read() >> 32) & mask; +void rv32_high_csr_t::verify_permissions(insn_t insn, bool write) const { + orig->verify_permissions(insn, write); } -bool mstatush_csr_t::unlogged_write(const reg_t val) noexcept { - return mstatus->unlogged_write((mstatus->written_value() & ~(mask << 32)) | ((val & mask) << 32)); +bool rv32_high_csr_t::unlogged_write(const reg_t val) noexcept { + return orig->unlogged_write((orig->written_value() & ~(mask << 32)) | ((val & mask) << 32)); } // implement class sstatus_csr_t -- cgit v1.1 From 2bf74857f0f7f3a63e029d7c7ecaf3d4523a846e Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Wed, 6 Jul 2022 10:45:04 +0800 Subject: add support for csrs of smstateen extensions --- riscv/csrs.cc | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index b8fa920..c2bdf0a 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1244,3 +1244,64 @@ bool vxsat_csr_t::unlogged_write(const reg_t val) noexcept { dirty_vs_state; return masked_csr_t::unlogged_write(val); } + +// implement class hstateen_csr_t +hstateen_csr_t::hstateen_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, + const reg_t init, uint8_t index): + masked_csr_t(proc, addr, mask, init), + index(index) { +} + +reg_t hstateen_csr_t::read() const noexcept { + // For every bit in an mstateen CSR that is zero (whether read-only zero or set to zero), + // the same bit appears as read-only zero in the matching hstateen and sstateen CSRs + return masked_csr_t::read() & state->mstateen[index]->read(); +} + +bool hstateen_csr_t::unlogged_write(const reg_t val) noexcept { + // For every bit in an mstateen CSR that is zero (whether read-only zero or set to zero), + // the same bit appears as read-only zero in the matching hstateen and sstateen CSRs + return masked_csr_t::unlogged_write(val & state->mstateen[index]->read()); +} + +void hstateen_csr_t::verify_permissions(insn_t insn, bool write) const { + masked_csr_t::verify_permissions(insn, write); + + if ((state->prv < PRV_M) && !(state->mstateen[index]->read() & MSTATEEN_HSTATEEN)) + throw trap_illegal_instruction(insn.bits()); +} + +// implement class sstateen_csr_t +sstateen_csr_t::sstateen_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, + const reg_t init, uint8_t index): + hstateen_csr_t(proc, addr, mask, init, index) { +} + +reg_t sstateen_csr_t::read() const noexcept { + // For every bit in an mstateen CSR that is zero (whether read-only zero or set to zero), + // the same bit appears as read-only zero in the matching hstateen and sstateen CSRs + // For every bit in an hstateen CSR that is zero (whether read-only zero or set to zero), + // the same bit appears as read-only zero in sstateen when accessed in VS-mode + if (state->v) + return hstateen_csr_t::read() & state->hstateen[index]->read(); + else + return hstateen_csr_t::read(); +} + +bool sstateen_csr_t::unlogged_write(const reg_t val) noexcept { + // For every bit in an mstateen CSR that is zero (whether read-only zero or set to zero), + // the same bit appears as read-only zero in the matching hstateen and sstateen CSRs + // For every bit in an hstateen CSR that is zero (whether read-only zero or set to zero), + // the same bit appears as read-only zero in sstateen when accessed in VS-mode + if (state->v) + return hstateen_csr_t::unlogged_write(val & state->hstateen[index]->read()); + else + return hstateen_csr_t::unlogged_write(val); +} + +void sstateen_csr_t::verify_permissions(insn_t insn, bool write) const { + hstateen_csr_t::verify_permissions(insn, write); + + if (state->v && !(state->hstateen[index]->read() & HSTATEEN_SSTATEEN)) + throw trap_virtual_instruction(insn.bits()); +} -- cgit v1.1 From 11dacaedc4b55ac1d79f1152a549ab9bfb170d2d Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Wed, 6 Jul 2022 10:51:36 +0800 Subject: add standalone class for fcsr and senvcfg csr --- riscv/csrs.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index c2bdf0a..1a23ff9 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1305,3 +1305,14 @@ void sstateen_csr_t::verify_permissions(insn_t insn, bool write) const { if (state->v && !(state->hstateen[index]->read() & HSTATEEN_SSTATEEN)) throw trap_virtual_instruction(insn.bits()); } + +// implement class fcsr_csr_t +fcsr_csr_t::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): + composite_csr_t(proc, addr, upper_csr, lower_csr, upper_lsb) { +} + +// 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) { +} -- cgit v1.1 From 10fefa1542756a7f7caf45670a64d965a995153a Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Wed, 6 Jul 2022 10:52:15 +0800 Subject: add smstateen check for fcsr, senvcfg, henvcfg --- riscv/csrs.cc | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 1a23ff9..45b9c4a 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()); + } +} -- cgit v1.1 From d920cdeeb47056e6976198384cd31f6e2e7b97da Mon Sep 17 00:00:00 2001 From: YenHaoChen <39526191+YenHaoChen@users.noreply.github.com> Date: Tue, 12 Jul 2022 06:13:10 +0800 Subject: Allow writes to pmp(i-1)cfg on locked pmp(i)cfg (#1039) The privileged spec allows writes to pmp(i-1)cfg with locked pmp(i)cfg (According to a recent discussion: https://github.com/riscv/riscv-isa-manual/issues/866) --- riscv/csrs.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 6bca99c..c5e65c8 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -248,7 +248,7 @@ bool pmpcfg_csr_t::unlogged_write(const reg_t val) noexcept { for (size_t i0 = (address - CSR_PMPCFG0) * 4, i = i0; i < i0 + proc->get_xlen() / 8; i++) { if (i < proc->n_pmp) { const bool locked = (state->pmpaddr[i]->cfg & PMP_L); - if (rlb || (!locked && !state->pmpaddr[i]->next_locked_and_tor())) { + if (rlb || !locked) { uint8_t cfg = (val >> (8 * (i - i0))) & (PMP_R | PMP_W | PMP_X | PMP_A | PMP_L); // Drop R=0 W=1 when MML = 0 // Remove the restriction when MML = 1 -- cgit v1.1 From e050da4c27635a22d6dbdab920371012b2ea8b4f Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Wed, 13 Jul 2022 09:23:18 +0800 Subject: Add verify_permissions() for mseccfg_csr_t The mseccfg only exists when enabling the Smepmp extension. If not enabling the Smepmp extension, CSR instructions to the mseccfg raise illegal instruction faults, and the PMP behaviors as hardwiring mseccfg 0 (the reset value of mseccfg). --- riscv/csrs.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index ab6b4bb..4e18ac0 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -272,6 +272,12 @@ mseccfg_csr_t::mseccfg_csr_t(processor_t* const proc, const reg_t addr): basic_csr_t(proc, addr, 0) { } +void mseccfg_csr_t::verify_permissions(insn_t insn, bool write) const { + basic_csr_t::verify_permissions(insn, write); + if (!proc->extension_enabled(EXT_SMEPMP)) + throw trap_illegal_instruction(insn.bits()); +} + bool mseccfg_csr_t::get_mml() const noexcept { return (read() & MSECCFG_MML); } -- cgit v1.1 From 5eada616d48e1e0f1f9f5add53dfca76dc29de68 Mon Sep 17 00:00:00 2001 From: liweiwei90 <34847211+liweiwei90@users.noreply.github.com> Date: Thu, 14 Jul 2022 09:39:30 +0800 Subject: add check for H extension requires S mode (#1042) --- riscv/csrs.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index ab6b4bb..83906cc 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -474,7 +474,7 @@ mstatus_csr_t::mstatus_csr_t(processor_t* const proc, const reg_t addr): } bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept { - const bool has_mpv = proc->extension_enabled('S') && proc->extension_enabled('H'); + const bool has_mpv = proc->extension_enabled('H'); const bool has_gva = has_mpv; const reg_t mask = sstatus_write_mask -- cgit v1.1 From 00c38fdb95dff4e18ed75361da03436075a03b3a Mon Sep 17 00:00:00 2001 From: Scott Johnson Date: Wed, 13 Jul 2022 09:01:15 -0700 Subject: Remove unnecessary mask from rv32_high_csr_t constructor --- riscv/csrs.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 83906cc..18956ff 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -494,10 +494,9 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept { } // implement class rv32_high_csr_t -rv32_high_csr_t::rv32_high_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, csr_t_p orig): +rv32_high_csr_t::rv32_high_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig): csr_t(proc, addr), - orig(orig), - mask(mask) { + orig(orig) { } reg_t rv32_high_csr_t::read() const noexcept { -- cgit v1.1 From 8f36f1a5f8a47282743706e7777a277b9f17ba6f Mon Sep 17 00:00:00 2001 From: Scott Johnson Date: Wed, 13 Jul 2022 09:14:05 -0700 Subject: Remove no-longer-needed mask from rv32_high_csr_t --- riscv/csrs.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 18956ff..3a929ff 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -500,7 +500,7 @@ rv32_high_csr_t::rv32_high_csr_t(processor_t* const proc, const reg_t addr, csr_ } reg_t rv32_high_csr_t::read() const noexcept { - return (orig->read() >> 32) & mask; + return (orig->read() >> 32) & 0xffffffffU; } void rv32_high_csr_t::verify_permissions(insn_t insn, bool write) const { @@ -508,7 +508,7 @@ void rv32_high_csr_t::verify_permissions(insn_t insn, bool write) const { } bool rv32_high_csr_t::unlogged_write(const reg_t val) noexcept { - return orig->unlogged_write((orig->written_value() & ~(mask << 32)) | ((val & mask) << 32)); + return orig->unlogged_write((orig->written_value() << 32 >> 32) | ((val & 0xffffffffU) << 32)); } // implement class sstatus_csr_t -- cgit v1.1 From 85ab2228ddb802c33a967349d69b2d948846bd01 Mon Sep 17 00:00:00 2001 From: Scott Johnson Date: Wed, 13 Jul 2022 09:33:36 -0700 Subject: Add proxy for accessing the low 32 bits of a 64-bit CSR Use this for mstatus on RV32 so that `csrw mstatus` does not modify the bits in `mstatush`. Fixes #1044. --- riscv/csrs.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 3a929ff..dac3eef 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -493,6 +493,24 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept { return true; } +// implement class rv32_low_csr_t +rv32_low_csr_t::rv32_low_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig): + csr_t(proc, addr), + orig(orig) { +} + +reg_t rv32_low_csr_t::read() const noexcept { + return orig->read() & 0xffffffffU; +} + +void rv32_low_csr_t::verify_permissions(insn_t insn, bool write) const { + orig->verify_permissions(insn, write); +} + +bool rv32_low_csr_t::unlogged_write(const reg_t val) noexcept { + return orig->unlogged_write((orig->written_value() >> 32 << 32) | (val & 0xffffffffU)); +} + // implement class rv32_high_csr_t rv32_high_csr_t::rv32_high_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig): csr_t(proc, addr), -- cgit v1.1 From b21a28bce174f2d1ac3e8a424bc9b9b1f01251a6 Mon Sep 17 00:00:00 2001 From: Scott Johnson Date: Wed, 13 Jul 2022 10:21:43 -0700 Subject: Add assertion to ensure proper logging of mstatus changes on RV32 --- riscv/csrs.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index dac3eef..7a52353 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -455,6 +455,10 @@ sstatus_proxy_csr_t::sstatus_proxy_csr_t(processor_t* const proc, const reg_t ad bool sstatus_proxy_csr_t::unlogged_write(const reg_t val) noexcept { const reg_t new_mstatus = (mstatus->read() & ~sstatus_write_mask) | (val & sstatus_write_mask); + // On RV32 this will only log the low 32 bits, so make sure we're + // not modifying anything in the upper 32 bits. + assert((sstatus_write_mask & 0xffffffffU) == sstatus_write_mask); + mstatus->write(new_mstatus); return false; // avoid double logging: already logged by mstatus->write() } -- cgit v1.1 From 3688fd8302d1b7b8eea1dd8f6206ceab1bedfb2c Mon Sep 17 00:00:00 2001 From: Scott Johnson Date: Wed, 13 Jul 2022 10:45:41 -0700 Subject: Properly log mstatush side effect updates These have never been logged properly. --- riscv/csrs.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 7a52353..6f8f260 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -616,7 +616,9 @@ bool misa_csr_t::unlogged_write(const reg_t val) noexcept { | (1 << CAUSE_STORE_GUEST_PAGE_FAULT) ; state->medeleg->write(state->medeleg->read() & ~hypervisor_exceptions); - state->mstatus->write(state->mstatus->read() & ~(MSTATUS_GVA | MSTATUS_MPV)); + const reg_t new_mstatus = state->mstatus->read() & ~(MSTATUS_GVA | MSTATUS_MPV); + state->mstatus->write(new_mstatus); + if (state->mstatush) state->mstatush->write(new_mstatus >> 32); // log mstatush change 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 state->hstatus->write(0); -- cgit v1.1 From 61a2c0ee6306562e084b25e4734d6ae725c475b4 Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Sun, 17 Jul 2022 09:13:06 +0800 Subject: extract the progress of computing the inital value of mstatus into separate function compute_mstatus_initial_value() --- riscv/csrs.cc | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 6f8f260..be23a2e 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -466,15 +466,7 @@ bool sstatus_proxy_csr_t::unlogged_write(const reg_t val) noexcept { // implement class mstatus_csr_t mstatus_csr_t::mstatus_csr_t(processor_t* const proc, const reg_t addr): base_status_csr_t(proc, addr), - val(0 - | (proc->extension_enabled_const('U') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0) - | (proc->extension_enabled_const('S') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 0) - -#ifdef RISCV_ENABLE_DUAL_ENDIAN - | (proc->get_mmu()->is_target_big_endian() ? MSTATUS_UBE | MSTATUS_SBE | MSTATUS_MBE : 0) -#endif - | 0 // initial value for mstatus - ) { + val(compute_mstatus_initial_value()) { } bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept { @@ -497,6 +489,16 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept { return true; } +reg_t mstatus_csr_t::compute_mstatus_initial_value() const noexcept { + return 0 + | (proc->extension_enabled_const('U') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0) + | (proc->extension_enabled_const('S') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 0) +#ifdef RISCV_ENABLE_DUAL_ENDIAN + | (proc->get_mmu()->is_target_big_endian() ? MSTATUS_UBE | MSTATUS_SBE | MSTATUS_MBE : 0) +#endif + | 0; // initial value for mstatus +} + // implement class rv32_low_csr_t rv32_low_csr_t::rv32_low_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig): csr_t(proc, addr), -- cgit v1.1 From f82e54124345f348abaa80ec82d67528a9a8f774 Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Sun, 17 Jul 2022 09:46:09 +0800 Subject: remove unnecessary ifdef for RISCV_ENABLE_DUAL_ENDIAN the default target endian is always little endian: - mmu::is_target_big_endian() return false - sim_t::get_target_endianness() return memif_endianness_little when RISCV_ENABLE_DUAL_ENDIAN macro is undefined --- riscv/csrs.cc | 2 -- 1 file changed, 2 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index be23a2e..c27410c 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -493,9 +493,7 @@ reg_t mstatus_csr_t::compute_mstatus_initial_value() const noexcept { return 0 | (proc->extension_enabled_const('U') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0) | (proc->extension_enabled_const('S') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 0) -#ifdef RISCV_ENABLE_DUAL_ENDIAN | (proc->get_mmu()->is_target_big_endian() ? MSTATUS_UBE | MSTATUS_SBE | MSTATUS_MBE : 0) -#endif | 0; // initial value for mstatus } -- cgit v1.1 From 89a79b673208a61f7ff16be628955109a742c1ac Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Sun, 17 Jul 2022 10:00:23 +0800 Subject: Fix the initial value and write mask for mstatus - MPRV is read-only 0 if U-mode is not supported - If U-mode is not supported, UBE is read-only 0 - If S-mode is not supported, SBE is read-only 0 --- riscv/csrs.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index c27410c..57778c3 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -474,7 +474,8 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept { const bool has_gva = has_mpv; const reg_t mask = sstatus_write_mask - | MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPRV + | MSTATUS_MIE | MSTATUS_MPIE + | (proc->extension_enabled('U') ? MSTATUS_MPRV : 0) | MSTATUS_MPP | MSTATUS_TW | (proc->extension_enabled('S') ? MSTATUS_TSR : 0) | (has_page ? MSTATUS_TVM : 0) @@ -490,10 +491,13 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept { } reg_t mstatus_csr_t::compute_mstatus_initial_value() const noexcept { + const reg_t big_endian_bits = (proc->extension_enabled_const('U') ? MSTATUS_UBE : 0) + | (proc->extension_enabled_const('S') ? MSTATUS_SBE : 0) + | MSTATUS_MBE; return 0 | (proc->extension_enabled_const('U') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0) | (proc->extension_enabled_const('S') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 0) - | (proc->get_mmu()->is_target_big_endian() ? MSTATUS_UBE | MSTATUS_SBE | MSTATUS_MBE : 0) + | (proc->get_mmu()->is_target_big_endian() ? big_endian_bits : 0) | 0; // initial value for mstatus } -- cgit v1.1 From c0b3fdcbaba99576393c57607985a0009bb2ebb1 Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Tue, 12 Jul 2022 23:21:34 +0800 Subject: modify the check for "state->prv >= PRV_M" to "state->prv == PRV_M" prv can never be larger than PRV_M --- riscv/csrs.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 57778c3..c43812b 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -885,7 +885,7 @@ satp_csr_t::satp_csr_t(processor_t* const proc, const reg_t addr): void satp_csr_t::verify_permissions(insn_t insn, bool write) const { base_atp_csr_t::verify_permissions(insn, write); if (get_field(state->mstatus->read(), MSTATUS_TVM)) - require(state->prv >= PRV_M); + require(state->prv == PRV_M); } virtualized_satp_csr_t::virtualized_satp_csr_t(processor_t* const proc, satp_csr_t_p orig, csr_t_p virt): -- cgit v1.1 From 28ee0c4d6a1ed221f1a05ba48f54023ac7d455cc Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Fri, 8 Jul 2022 18:34:13 +0800 Subject: modify minstret/mcycle/minstreth/mcycleh to reuse rv32_low/high_csr_t --- riscv/csrs.cc | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 6f8f260..9721f87 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -515,6 +515,10 @@ bool rv32_low_csr_t::unlogged_write(const reg_t val) noexcept { return orig->unlogged_write((orig->written_value() >> 32 << 32) | (val & 0xffffffffU)); } +reg_t rv32_low_csr_t::written_value() const noexcept { + return orig->written_value() & 0xffffffffU; +} + // implement class rv32_high_csr_t rv32_high_csr_t::rv32_high_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig): csr_t(proc, addr), @@ -533,6 +537,10 @@ bool rv32_high_csr_t::unlogged_write(const reg_t val) noexcept { return orig->unlogged_write((orig->written_value() << 32 >> 32) | ((val & 0xffffffffU) << 32)); } +reg_t rv32_high_csr_t::written_value() const noexcept { + return (orig->written_value() >> 32) & 0xffffffffU; +} + // implement class sstatus_csr_t sstatus_csr_t::sstatus_csr_t(processor_t* const proc, sstatus_proxy_csr_t_p orig, vsstatus_csr_t_p virt): virtualized_csr_t(proc, orig, virt), @@ -924,10 +932,7 @@ void wide_counter_csr_t::bump(const reg_t howmuch) noexcept { } bool wide_counter_csr_t::unlogged_write(const reg_t val) noexcept { - if (proc->get_xlen() == 32) - this->val = (this->val >> 32 << 32) | (val & 0xffffffffU); - else - this->val = val; + this->val = val; // The ISA mandates that if an instruction writes instret, the write // takes precedence over the increment to instret. However, Spike // unconditionally increments instret after executing an instruction. @@ -941,27 +946,6 @@ reg_t wide_counter_csr_t::written_value() const noexcept { return this->val + 1; } -void wide_counter_csr_t::write_upper_half(const reg_t val) noexcept { - this->val = (val << 32) | (this->val << 32 >> 32); - this->val--; // See comment above. - // Log upper half only. - log_special_write(address + (CSR_MINSTRETH - CSR_MINSTRET), written_value() >> 32); -} - -counter_top_csr_t::counter_top_csr_t(processor_t* const proc, const reg_t addr, wide_counter_csr_t_p parent): - csr_t(proc, addr), - parent(parent) { -} - -reg_t counter_top_csr_t::read() const noexcept { - return parent->read() >> 32; -} - -bool counter_top_csr_t::unlogged_write(const reg_t val) noexcept { - parent->write_upper_half(val); - return true; -} - proxy_csr_t::proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate): csr_t(proc, addr), delegate(delegate) { -- cgit v1.1 From 3ff1b5f1c6c6e13777be1c677abc2340f3dabd1a Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Fri, 8 Jul 2022 20:30:02 +0800 Subject: add support for time/timeh/htimedelta/htimedeltah csrs --- riscv/csrs.cc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 9721f87..8cb9953 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -946,6 +946,25 @@ reg_t wide_counter_csr_t::written_value() const noexcept { return this->val + 1; } +// implement class time_counter_csr_t +time_counter_csr_t::time_counter_csr_t(processor_t* const proc, const reg_t addr): + csr_t(proc, addr), + shadow_val(0) { +} + +reg_t time_counter_csr_t::read() const noexcept { + // reading the time CSR in VS or VU mode returns the sum of the contents of + // htimedelta and the actual value of time. + if (state->v) + return shadow_val + state->htimedelta->read(); + else + return shadow_val; +} + +void time_counter_csr_t::sync(const reg_t val) noexcept { + shadow_val = val; +} + proxy_csr_t::proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate): csr_t(proc, addr), delegate(delegate) { -- cgit v1.1 From eff4011f24390017e4582cb8556ebc6e5ce41d61 Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Fri, 8 Jul 2022 10:00:00 +0800 Subject: add base verify_permission in counter_proxy_csr_t::verify_permissions Normally, csrs will reuse the checks in verify_permissions of its base csr type This modification will not cause any functional change, just reuse the check in csr_t class to check whether it writes to read-only csr instead of checking writes to counter_proxy_csr_t by itself. --- riscv/csrs.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 8cb9953..27bef5e 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1001,11 +1001,13 @@ bool counter_proxy_csr_t::myenable(csr_t_p counteren) const noexcept { } void counter_proxy_csr_t::verify_permissions(insn_t insn, bool write) const { + proxy_csr_t::verify_permissions(insn, write); + const bool mctr_ok = (state->prv < PRV_M) ? myenable(state->mcounteren) : true; const bool hctr_ok = state->v ? myenable(state->hcounteren) : true; const bool sctr_ok = (proc->extension_enabled('S') && state->prv < PRV_S) ? myenable(state->scounteren) : true; - if (write || !mctr_ok) + if (!mctr_ok) throw trap_illegal_instruction(insn.bits()); if (!hctr_ok) throw trap_virtual_instruction(insn.bits()); -- cgit v1.1 From 8d016bffdbc8d7cbeb253cc4f2ee9e5d4bf0a626 Mon Sep 17 00:00:00 2001 From: Brendan Sweeney Date: Tue, 26 Jul 2022 14:36:01 -0500 Subject: Add additional bits to medeleg (#1050) Pursuant to https://github.com/riscv-software-src/riscv-isa-sim/issues/668 and https://github.com/riscv-software-src/riscv-isa-sim/issues/194, allowing for additional exceptions to be delegated from M-mode. It is implementation-defined whether these bits are defined or are read-only-zero. QEMU implements the added bits (Fetch/Load/StoreAMO access, Load/StoreAMO misalignment, and illegal instruction). (https://github.com/qemu/qemu/blob/f6cce6bcb2ef959cdd4da0e368f7c72045f21d6d/target/riscv/csr.c#L813) ECALL_FROM_M is not implemented here because it would have no effect, although QEMU does implement it. This allows Spike to emulate QEMU and other systems which allow for the delegation of such exceptions. Signed-off-by: Brendan Sweeney --- riscv/csrs.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 3cb6af2..d02212b 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -822,7 +822,13 @@ void medeleg_csr_t::verify_permissions(insn_t insn, bool write) const { bool medeleg_csr_t::unlogged_write(const reg_t val) noexcept { const reg_t mask = 0 | (1 << CAUSE_MISALIGNED_FETCH) + | (1 << CAUSE_FETCH_ACCESS) + | (1 << CAUSE_ILLEGAL_INSTRUCTION) | (1 << CAUSE_BREAKPOINT) + | (1 << CAUSE_MISALIGNED_LOAD) + | (1 << CAUSE_LOAD_ACCESS) + | (1 << CAUSE_MISALIGNED_STORE) + | (1 << CAUSE_STORE_ACCESS) | (1 << CAUSE_USER_ECALL) | (1 << CAUSE_SUPERVISOR_ECALL) | (1 << CAUSE_FETCH_PAGE_FAULT) -- cgit v1.1 From eb2cce0c99075f89e77b0c1db92108f9c49ccab0 Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Wed, 3 Aug 2022 10:32:51 +0800 Subject: add stateen related check to frm/fflags and then apply to fcsr implicitly --- riscv/csrs.cc | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index d02212b..4ec404b 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1198,6 +1198,21 @@ void float_csr_t::verify_permissions(insn_t insn, bool write) const { require_fp; if (!proc->extension_enabled('F')) throw trap_illegal_instruction(insn.bits()); + + 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()); + } + } } bool float_csr_t::unlogged_write(const reg_t val) noexcept { @@ -1350,30 +1365,6 @@ void sstateen_csr_t::verify_permissions(insn_t insn, bool write) const { throw trap_virtual_instruction(insn.bits()); } -// implement class fcsr_csr_t -fcsr_csr_t::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): - 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): -- cgit v1.1 From a7de776de66a1c1caea8d896e6ff51503b0a46bf Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Wed, 3 Aug 2022 22:10:17 +0800 Subject: Fix exception type for accessing senvcfg/henvcfg/hstateen Illegal instruciton trap should be raised when accessing senvcfg/ henvcfg/hstateen if related bit of mstateen is zero in VU mode --- riscv/csrs.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 4ec404b..875461a 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1324,10 +1324,9 @@ bool hstateen_csr_t::unlogged_write(const reg_t val) noexcept { } void hstateen_csr_t::verify_permissions(insn_t insn, bool write) const { - masked_csr_t::verify_permissions(insn, write); - if ((state->prv < PRV_M) && !(state->mstateen[index]->read() & MSTATEEN_HSTATEEN)) throw trap_illegal_instruction(insn.bits()); + masked_csr_t::verify_permissions(insn, write); } // implement class sstateen_csr_t @@ -1372,8 +1371,6 @@ senvcfg_csr_t::senvcfg_csr_t(processor_t* const proc, const reg_t addr, const re } 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()); @@ -1381,13 +1378,15 @@ void senvcfg_csr_t::verify_permissions(insn_t insn, bool write) const { 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); +} +void henvcfg_csr_t::verify_permissions(insn_t insn, bool write) const { if (proc->extension_enabled(EXT_SMSTATEEN)) { if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_HENVCFG)) throw trap_illegal_instruction(insn.bits()); } + + masked_csr_t::verify_permissions(insn, write); } -- cgit v1.1 From 5672c4a41ad7a9af011d385962c175a5a6012fd9 Mon Sep 17 00:00:00 2001 From: i2h2 <110197402+i2h2@users.noreply.github.com> Date: Wed, 3 Aug 2022 16:01:57 -0600 Subject: Add Sstc support. (#1057) --- riscv/csrs.cc | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index d02212b..50cbfb3 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -679,7 +679,8 @@ void mip_csr_t::backdoor_write_with_mask(const reg_t mask, const reg_t val) noex } reg_t mip_csr_t::write_mask() const noexcept { - const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | MIP_STIP | MIP_SEIP : 0; + // MIP_STIP is writable unless SSTC exists and STCE is set in MENVCFG + const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | ((state->menvcfg->read() & MENVCFG_STCE) ? 0 : MIP_STIP) | MIP_SEIP : 0; const reg_t vssip_int = proc->extension_enabled('H') ? MIP_VSSIP : 0; const reg_t hypervisor_ints = proc->extension_enabled('H') ? MIP_HS_MASK : 0; // We must mask off sgeip, vstip, and vseip. All three of these @@ -979,6 +980,11 @@ reg_t time_counter_csr_t::read() const noexcept { void time_counter_csr_t::sync(const reg_t val) noexcept { shadow_val = val; + if (proc->extension_enabled(EXT_SSTC)) { + const reg_t mip_val = (shadow_val >= state->stimecmp->read() ? MIP_STIP : 0) | + (shadow_val + state->htimedelta->read() >= state->vstimecmp->read() ? MIP_VSTIP : 0); + state->mip->backdoor_write_with_mask(MIP_STIP | MIP_VSTIP, mip_val); + } } proxy_csr_t::proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate): @@ -1400,3 +1406,32 @@ void henvcfg_csr_t::verify_permissions(insn_t insn, bool write) const { throw trap_illegal_instruction(insn.bits()); } } + +stimecmp_csr_t::stimecmp_csr_t(processor_t* const proc, const reg_t addr, const reg_t imask): + basic_csr_t(proc, addr, 0), intr_mask(imask) { +} + +bool stimecmp_csr_t::unlogged_write(const reg_t val) noexcept { + state->mip->backdoor_write_with_mask(intr_mask, state->time->read() >= val ? intr_mask : 0); + return basic_csr_t::unlogged_write(val); +} + +virtualized_stimecmp_csr_t::virtualized_stimecmp_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt): + virtualized_csr_t(proc, orig, virt) { +} + +void virtualized_stimecmp_csr_t::verify_permissions(insn_t insn, bool write) const { + virtualized_csr_t::verify_permissions(insn, write); + + // check for read permission to time as enabled by xcounteren + state->time_proxy->verify_permissions(insn, false); + + if (!(state->menvcfg->read() & MENVCFG_STCE)) { + // access to (v)stimecmp with MENVCFG.STCE = 0 + if (state->prv < PRV_M) + throw trap_illegal_instruction(insn.bits()); + } else if (state->v && !(state->henvcfg->read() & HENVCFG_STCE)) { + // access to vstimecmp with MENVCFG.STCE = 1 and HENVCFG.STCE = 0 when V = 1 + throw trap_virtual_instruction(insn.bits()); + } +} -- cgit v1.1 From 7812b01154c6a2f19e0d4bc9f00e5d5fcb9aec22 Mon Sep 17 00:00:00 2001 From: liweiwei Date: Thu, 14 Oct 2021 09:44:54 +0800 Subject: Add flags for Zfinx/Zdinx/Zhinx{min} Hardwire mstatus_fs to zero when enable ZFinx --- riscv/csrs.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 50cbfb3..fc5dce1 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -394,8 +394,8 @@ base_status_csr_t::base_status_csr_t(processor_t* const proc, const reg_t addr): reg_t base_status_csr_t::compute_sstatus_write_mask() const noexcept { // If a configuration has FS bits, they will always be accessible no // matter the state of misa. - const bool has_fs = proc->extension_enabled('S') || proc->extension_enabled('F') - || proc->extension_enabled('V'); + const bool has_fs = (proc->extension_enabled('S') || proc->extension_enabled('F') + || proc->extension_enabled('V')) && !proc->extension_enabled(EXT_ZFINX); const bool has_vs = proc->extension_enabled('V'); return 0 | (proc->extension_enabled('S') ? (SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP) : 0) @@ -1202,7 +1202,7 @@ float_csr_t::float_csr_t(processor_t* const proc, const reg_t addr, const reg_t void float_csr_t::verify_permissions(insn_t insn, bool write) const { masked_csr_t::verify_permissions(insn, write); require_fp; - if (!proc->extension_enabled('F')) + if (!proc->extension_enabled('F') && !proc->extension_enabled(EXT_ZFINX)) throw trap_illegal_instruction(insn.bits()); } -- cgit v1.1 From caee7f3fa508b0bf84eb3f8d60d6c9e43b0ccf61 Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Thu, 4 Aug 2022 10:18:19 +0800 Subject: Add stateen related check for float point instructions --- riscv/csrs.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index fc5dce1..7592c2d 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1201,7 +1201,7 @@ float_csr_t::float_csr_t(processor_t* const proc, const reg_t addr, const reg_t void float_csr_t::verify_permissions(insn_t insn, bool write) const { masked_csr_t::verify_permissions(insn, write); - require_fp; + require_fs; if (!proc->extension_enabled('F') && !proc->extension_enabled(EXT_ZFINX)) throw trap_illegal_instruction(insn.bits()); } -- cgit v1.1 From ba10686fd18f3fbb036ca04b906deb57e7d1fe54 Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Mon, 4 Jul 2022 21:31:09 +0800 Subject: add support for sscofpmf extension v0.5.2 since spike doesn't truly support counting of hardware performance events, only csr related read/write functions is supported currently --- riscv/csrs.cc | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 50cbfb3..f50ac6e 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -681,6 +681,7 @@ void mip_csr_t::backdoor_write_with_mask(const reg_t mask, const reg_t val) noex reg_t mip_csr_t::write_mask() const noexcept { // MIP_STIP is writable unless SSTC exists and STCE is set in MENVCFG const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | ((state->menvcfg->read() & MENVCFG_STCE) ? 0 : MIP_STIP) | MIP_SEIP : 0; + const reg_t lscof_int = proc->extension_enabled(EXT_SSCOFPMF) ? MIP_LCOFIP : 0; const reg_t vssip_int = proc->extension_enabled('H') ? MIP_VSSIP : 0; const reg_t hypervisor_ints = proc->extension_enabled('H') ? MIP_HS_MASK : 0; // We must mask off sgeip, vstip, and vseip. All three of these @@ -688,8 +689,8 @@ reg_t mip_csr_t::write_mask() const noexcept { // * sgeip is read-only -- write hgeip instead // * vseip is read-only -- write hvip instead // * vstip is read-only -- write hvip instead - return (supervisor_ints | hypervisor_ints) & - (MIP_SEIP | MIP_SSIP | MIP_STIP | vssip_int); + return (supervisor_ints | hypervisor_ints | lscof_int) & + (MIP_SEIP | MIP_SSIP | MIP_STIP | MIP_LCOFIP | vssip_int); } mie_csr_t::mie_csr_t(processor_t* const proc, const reg_t addr): @@ -698,9 +699,10 @@ mie_csr_t::mie_csr_t(processor_t* const proc, const reg_t addr): reg_t mie_csr_t::write_mask() const noexcept { const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | MIP_STIP | MIP_SEIP : 0; + const reg_t lscof_int = proc->extension_enabled(EXT_SSCOFPMF) ? MIP_LCOFIP : 0; const reg_t hypervisor_ints = proc->extension_enabled('H') ? MIP_HS_MASK : 0; const reg_t coprocessor_ints = (reg_t)proc->any_custom_extensions() << IRQ_COP; - const reg_t delegable_ints = supervisor_ints | coprocessor_ints; + const reg_t delegable_ints = supervisor_ints | coprocessor_ints | lscof_int; const reg_t all_ints = delegable_ints | hypervisor_ints | MIP_MSIP | MIP_MTIP | MIP_MEIP; return all_ints; } @@ -796,8 +798,9 @@ void mideleg_csr_t::verify_permissions(insn_t insn, bool write) const { bool mideleg_csr_t::unlogged_write(const reg_t val) noexcept { const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | MIP_STIP | MIP_SEIP : 0; + const reg_t lscof_int = proc->extension_enabled(EXT_SSCOFPMF) ? MIP_LCOFIP : 0; const reg_t coprocessor_ints = (reg_t)proc->any_custom_extensions() << IRQ_COP; - const reg_t delegable_ints = supervisor_ints | coprocessor_ints; + const reg_t delegable_ints = supervisor_ints | coprocessor_ints | lscof_int; return basic_csr_t::unlogged_write(val & delegable_ints); } @@ -1435,3 +1438,34 @@ void virtualized_stimecmp_csr_t::verify_permissions(insn_t insn, bool write) con throw trap_virtual_instruction(insn.bits()); } } + +scountovf_csr_t::scountovf_csr_t(processor_t* const proc, const reg_t addr): + csr_t(proc, addr) { +} + +void scountovf_csr_t::verify_permissions(insn_t insn, bool write) const { + if (!proc->extension_enabled(EXT_SSCOFPMF)) + throw trap_illegal_instruction(insn.bits()); + csr_t::verify_permissions(insn, write); +} + +reg_t scountovf_csr_t::read() const noexcept { + reg_t val = 0; + for (reg_t i = 3; i <= 31; ++i) { + bool of = state->mevent[i - 3]->read() & MHPMEVENT_OF; + val |= of << i; + } + + /* In M and S modes, scountovf bit X is readable when mcounteren bit X is set, */ + /* and otherwise reads as zero. Similarly, in VS mode, scountovf bit X is readable */ + /* when mcounteren bit X and hcounteren bit X are both set, and otherwise reads as zero. */ + val &= state->mcounteren->read(); + if (state->v) + val &= state->hcounteren->read(); + return val; +} + +bool scountovf_csr_t::unlogged_write(const reg_t val) noexcept { + /* this function is unused */ + return false; +} -- cgit v1.1 From 7383118078a98112ca4036919e6654d8171d2274 Mon Sep 17 00:00:00 2001 From: liweiwei90 <34847211+liweiwei90@users.noreply.github.com> Date: Wed, 10 Aug 2022 05:50:53 +0800 Subject: Fix exception type for accessing (v)stimecmp (#1061) Illegal instruciton trap should be raised when accessing if related bit of mcounteren.TM or menvcfg.STCE is zero in VS/VU mode --- riscv/csrs.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 7de49a7..bc5db50 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1411,17 +1411,18 @@ virtualized_stimecmp_csr_t::virtualized_stimecmp_csr_t(processor_t* const proc, } void virtualized_stimecmp_csr_t::verify_permissions(insn_t insn, bool write) const { - virtualized_csr_t::verify_permissions(insn, write); - - // check for read permission to time as enabled by xcounteren - state->time_proxy->verify_permissions(insn, false); - if (!(state->menvcfg->read() & MENVCFG_STCE)) { // access to (v)stimecmp with MENVCFG.STCE = 0 if (state->prv < PRV_M) throw trap_illegal_instruction(insn.bits()); - } else if (state->v && !(state->henvcfg->read() & HENVCFG_STCE)) { + } + + state->time_proxy->verify_permissions(insn, false); + + if (state->v && !(state->henvcfg->read() & HENVCFG_STCE)) { // access to vstimecmp with MENVCFG.STCE = 1 and HENVCFG.STCE = 0 when V = 1 throw trap_virtual_instruction(insn.bits()); } + + virtualized_csr_t::verify_permissions(insn, write); } -- cgit v1.1 From ac117cc35aa2bc5296f7a7bfd817a539e269919f Mon Sep 17 00:00:00 2001 From: Greg Chadwick Date: Thu, 11 Aug 2022 21:09:57 +0100 Subject: Unify PMPCFGx behaviour with PMPADDRx where PMP is disabled (#1068) Previously any access to the PMPADDRx CSRs when no PMP regions were configured would result in an illegal instruction trap, whilst PMPCFGx registers would act as WARL, ignoring writes and reading as 0. This unifies the behaviour so both PMPADDRx and PMPCFGx CSRs produce an illegal instruction trap when accessed when no PMP regions are configured. --- riscv/csrs.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index bc5db50..e516e4a 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -218,6 +218,16 @@ pmpcfg_csr_t::pmpcfg_csr_t(processor_t* const proc, const reg_t addr): csr_t(proc, addr) { } +void pmpcfg_csr_t::verify_permissions(insn_t insn, bool write) const { + csr_t::verify_permissions(insn, write); + // If n_pmp is zero, that means pmp is not implemented hence raise + // trap if it tries to access the csr. I would prefer to implement + // this by not instantiating any pmpcfg_csr_t for these regs, but + // n_pmp can change after reset() is run. + if (proc->n_pmp == 0) + throw trap_illegal_instruction(insn.bits()); +} + reg_t pmpcfg_csr_t::read() const noexcept { reg_t cfg_res = 0; for (size_t i0 = (address - CSR_PMPCFG0) * 4, i = i0; i < i0 + proc->get_xlen() / 8 && i < state->max_pmp; i++) -- cgit v1.1 From 8f511653940cb2b9edd9a18ec30a51422b34a573 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 22 Sep 2022 14:57:42 -0700 Subject: Fix remaining ignored-qualifiers warning --- riscv/csrs.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 858f12d..c8f8c8a 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -615,7 +615,7 @@ misa_csr_t::misa_csr_t(processor_t* const proc, const reg_t addr, const reg_t ma ) { } -const reg_t misa_csr_t::dependency(const reg_t val, const char feature, const char depends_on) const noexcept { +reg_t misa_csr_t::dependency(const reg_t val, const char feature, const char depends_on) const noexcept { return (val & (1L << (depends_on - 'A'))) ? val : (val & ~(1L << (feature - 'A'))); } -- cgit v1.1 From ce69fb5db97ecf240336b7826dd9dddeb32e5dca Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 22 Sep 2022 17:34:33 -0700 Subject: Suppress most unused variable warnings --- riscv/csrs.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'riscv/csrs.cc') diff --git a/riscv/csrs.cc b/riscv/csrs.cc index c8f8c8a..93b0bae 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -60,7 +60,7 @@ void csr_t::log_write() const noexcept { log_special_write(address, written_value()); } -void csr_t::log_special_write(const reg_t address, const reg_t val) const noexcept { +void csr_t::log_special_write(const reg_t UNUSED address, const reg_t UNUSED val) const noexcept { #if defined(RISCV_ENABLE_COMMITLOG) proc->get_state()->log_reg_write[((address) << 4) | 4] = {val, 0}; #endif @@ -1023,7 +1023,7 @@ reg_t const_csr_t::read() const noexcept { return val; } -bool const_csr_t::unlogged_write(const reg_t val) noexcept { +bool const_csr_t::unlogged_write(const reg_t UNUSED val) noexcept { return false; } @@ -1466,7 +1466,7 @@ reg_t scountovf_csr_t::read() const noexcept { return val; } -bool scountovf_csr_t::unlogged_write(const reg_t val) noexcept { +bool scountovf_csr_t::unlogged_write(const reg_t UNUSED val) noexcept { /* this function is unused */ return false; } -- cgit v1.1