From ba9339a50d5ac5591fb96ac233d264a25e38a323 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 21 Sep 2021 16:52:40 +0200 Subject: [PATCH] fix MPP reset value, PMP inactive in U-mode handling and MRET in U-mode --- incl/iss/arch/riscv_hart_msu_vp.h | 8 ++-- incl/iss/arch/riscv_hart_mu_p.h | 68 +++++++++++++++++-------------- 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/incl/iss/arch/riscv_hart_msu_vp.h b/incl/iss/arch/riscv_hart_msu_vp.h index ff1ed78..2dbfef2 100644 --- a/incl/iss/arch/riscv_hart_msu_vp.h +++ b/incl/iss/arch/riscv_hart_msu_vp.h @@ -145,7 +145,7 @@ public: mstatus_t mstatus; - static const reg_t mstatus_reset_val = 0; + static const reg_t mstatus_reset_val = 0x1800; void write_mstatus(T val, unsigned priv_lvl) { auto mask = get_mask(priv_lvl); @@ -398,7 +398,7 @@ private: iss::status read_ip(unsigned addr, reg_t &val); iss::status write_ip(unsigned addr, reg_t val); iss::status read_hartid(unsigned addr, reg_t &val); - iss::status write_mepc(unsigned addr, reg_t val); + iss::status write_epc(unsigned addr, reg_t val); iss::status read_satp(unsigned addr, reg_t &val); iss::status write_satp(unsigned addr, reg_t val); iss::status read_fcsr(unsigned addr, reg_t &val); @@ -954,8 +954,8 @@ template iss::status riscv_hart_msu_vp::write_ip(unsigned return iss::Ok; } -template iss::status riscv_hart_m_p::write_epc(unsigned addr, reg_t val) { - csr[addr] = val & get_pc_mask(); +template iss::status riscv_hart_msu_vp::write_epc(unsigned addr, reg_t val) { + csr[addr] = val & get_pc_mask(); return iss::Ok; } diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/incl/iss/arch/riscv_hart_mu_p.h index 8d01c3f..b931fb2 100644 --- a/incl/iss/arch/riscv_hart_mu_p.h +++ b/incl/iss/arch/riscv_hart_mu_p.h @@ -146,7 +146,7 @@ public: mstatus_t mstatus; - static const reg_t mstatus_reset_val = 0; + static const reg_t mstatus_reset_val = 0x1800; // MPP set to 1 void write_mstatus(T val, unsigned priv_lvl) { auto mask = get_mask(priv_lvl); @@ -543,25 +543,27 @@ template bool riscv_hart_mu_p::pmp_ constexpr auto PMP_NA4 =0x2U; constexpr auto PMP_NAPOT =0x3U; reg_t base = 0; + auto any_active = false; for (size_t i = 0; i < 16; i++) { reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT; uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); if (cfg & PMP_A) { + any_active=true; auto pmp_a = (cfg & PMP_A) >> 3; - bool is_tor = pmp_a == PMP_TOR; - bool is_na4 = pmp_a == PMP_NA4; + auto is_tor = pmp_a == PMP_TOR; + auto is_na4 = pmp_a == PMP_NA4; reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4); mask = ~(mask & ~(mask + 1)) << PMP_SHIFT; // Check each 4-byte sector of the access - bool any_match = false; - bool all_match = true; + auto any_match = false; + auto all_match = true; for (reg_t offset = 0; offset < len; offset += 1 << PMP_SHIFT) { reg_t cur_addr = addr + offset; - bool napot_match = ((cur_addr ^ tor) & mask) == 0; - bool tor_match = base <= cur_addr && cur_addr < tor; - bool match = is_tor ? tor_match : napot_match; + auto napot_match = ((cur_addr ^ tor) & mask) == 0; + auto tor_match = base <= cur_addr && cur_addr < tor; + auto match = is_tor ? tor_match : napot_match; any_match |= match; all_match &= match; } @@ -577,7 +579,7 @@ template bool riscv_hart_mu_p::pmp_ } base = tor; } - return this->reg.PRIV == PRIV_M; + return !any_active || this->reg.PRIV == PRIV_M; } @@ -926,8 +928,6 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::write_ie(unsigned addr, reg_t val) { auto mask = get_irq_wrmask((addr >> 8) & 0x3); - if(this->reg.PRIV==0) - mask&= ~(0xff<<4); // STIE and UTIE are read only in user and supervisor mode csr[mie] = (csr[mie] & ~mask) | (val & mask); check_interrupt(); return iss::Ok; @@ -1256,27 +1256,33 @@ template uint64_t riscv_hart_mu_p:: template uint64_t riscv_hart_mu_p::leave_trap(uint64_t flags) { auto cur_priv = this->reg.PRIV; auto inst_priv = (flags & 0x3)? 3:0; - auto status = state.mstatus; - // pop the relevant lower-privilege interrupt enable and privilege mode stack - // clear respective yIE - switch (inst_priv) { - case PRIV_M: - this->reg.PRIV = state.mstatus.MPP; - state.mstatus.MPP = 0; // clear mpp to U mode - state.mstatus.MIE = state.mstatus.MPIE; - state.mstatus.MPIE = 1; - break; - case PRIV_U: - this->reg.PRIV = 0; - state.mstatus.UIE = state.mstatus.UPIE; - state.mstatus.UPIE = 1; - break; + if(inst_priv>cur_priv){ + auto trap_val = 0x80ULL << 24 | (2 << 16); // illegal instruction + this->reg.trap_state = trap_val; + this->reg.NEXT_PC = std::numeric_limits::max(); + } else { + auto status = state.mstatus; + // pop the relevant lower-privilege interrupt enable and privilege mode stack + // clear respective yIE + switch (inst_priv) { + case PRIV_M: + this->reg.PRIV = state.mstatus.MPP; + state.mstatus.MPP = 0; // clear mpp to U mode + state.mstatus.MIE = state.mstatus.MPIE; + state.mstatus.MPIE = 1; + break; + case PRIV_U: + this->reg.PRIV = 0; + state.mstatus.UIE = state.mstatus.UPIE; + state.mstatus.UPIE = 1; + break; + } + // sets the pc to the value stored in the x epc register. + this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; + CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " + << lvl[this->reg.PRIV]; + check_interrupt(); } - // sets the pc to the value stored in the x epc register. - this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; - CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " - << lvl[this->reg.PRIV]; - check_interrupt(); return this->reg.NEXT_PC; }