diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 9d0635ae..44fd9598 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -418,8 +418,9 @@ bool sstatus_proxy_csr_t::unlogged_write(const reg_t val) noexcept { 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') ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0) - | (proc->extension_enabled_const('S') ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 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 @@ -926,8 +927,6 @@ 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; @@ -942,6 +941,9 @@ void counter_proxy_csr_t::verify_permissions(insn_t insn, bool write) const { else throw trap_illegal_instruction(insn.bits()); } + + if (write) + throw trap_illegal_instruction(insn.bits()); } diff --git a/riscv/insns/mret.h b/riscv/insns/mret.h index be9f2473..77847dd3 100644 --- a/riscv/insns/mret.h +++ b/riscv/insns/mret.h @@ -7,7 +7,7 @@ if (prev_prv != PRV_M) s = set_field(s, MSTATUS_MPRV, 0); s = set_field(s, MSTATUS_MIE, get_field(s, MSTATUS_MPIE)); s = set_field(s, MSTATUS_MPIE, 1); -s = set_field(s, MSTATUS_MPP, PRV_U); +s = set_field(s, MSTATUS_MPP, p->extension_enabled('U') ? PRV_U : PRV_M); s = set_field(s, MSTATUS_MPV, 0); p->set_csr(CSR_MSTATUS, s); p->set_privilege(prev_prv); diff --git a/riscv/processor.cc b/riscv/processor.cc index a0513b8b..947eab5a 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -207,6 +207,10 @@ isa_parser_t::isa_parser_t(const char* str) const char* all_subsets = "mafdqchpv"; max_isa = reg_t(2) << 62; + // enable zicntr and zihpm unconditionally for backward compatibility + extension_table[EXT_ZICNTR] = true; + extension_table[EXT_ZIHPM] = true; + if (isa_string.compare(0, 4, "rv32") == 0) max_xlen = 32, max_isa = reg_t(1) << 30; else if (isa_string.compare(0, 4, "rv64") == 0) @@ -341,8 +345,10 @@ isa_parser_t::isa_parser_t(const char* str) } else if (ext_str == "zicbom") { extension_table[EXT_ZICBOM] = true; } else if (ext_str == "zicboz") { - extension_table[EXT_ZICBOZ] = true; + extension_table[EXT_ZICBOZ] = true; } else if (ext_str == "zicbop") { + } else if (ext_str == "zicntr") { + } else if (ext_str == "zihpm") { } else if (ext_str[0] == 'x') { max_isa |= 1L << ('x' - 'a'); extension_table[toupper('x')] = true; @@ -424,14 +430,18 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) csrmap[CSR_MCAUSE] = mcause = std::make_shared(proc, CSR_MCAUSE); csrmap[CSR_MINSTRET] = minstret = std::make_shared(proc, CSR_MINSTRET); csrmap[CSR_MCYCLE] = mcycle = std::make_shared(proc, CSR_MCYCLE); - csrmap[CSR_INSTRET] = std::make_shared(proc, CSR_INSTRET, minstret); - csrmap[CSR_CYCLE] = std::make_shared(proc, CSR_CYCLE, mcycle); + if (proc->extension_enabled_const(EXT_ZICNTR)) { + csrmap[CSR_INSTRET] = std::make_shared(proc, CSR_INSTRET, minstret); + csrmap[CSR_CYCLE] = std::make_shared(proc, CSR_CYCLE, mcycle); + } if (xlen == 32) { counter_top_csr_t_p minstreth, mcycleh; csrmap[CSR_MINSTRETH] = minstreth = std::make_shared(proc, CSR_MINSTRETH, minstret); csrmap[CSR_MCYCLEH] = mcycleh = std::make_shared(proc, CSR_MCYCLEH, mcycle); - csrmap[CSR_INSTRETH] = std::make_shared(proc, CSR_INSTRETH, minstreth); - csrmap[CSR_CYCLEH] = std::make_shared(proc, CSR_CYCLEH, mcycleh); + if (proc->extension_enabled_const(EXT_ZICNTR)) { + csrmap[CSR_INSTRETH] = std::make_shared(proc, CSR_INSTRETH, minstreth); + csrmap[CSR_CYCLEH] = std::make_shared(proc, CSR_CYCLEH, mcycleh); + } } for (reg_t i=3; i<=31; ++i) { const reg_t which_mevent = CSR_MHPMEVENT3 + i - 3; @@ -441,15 +451,20 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) const reg_t which_counterh = CSR_HPMCOUNTER3H + i - 3; auto mevent = std::make_shared(proc, which_mevent, 0); auto mcounter = std::make_shared(proc, which_mcounter, 0); - auto counter = std::make_shared(proc, which_counter, mcounter); csrmap[which_mevent] = mevent; csrmap[which_mcounter] = mcounter; - csrmap[which_counter] = counter; + + if (proc->extension_enabled_const(EXT_ZICNTR) && proc->extension_enabled_const(EXT_ZIHPM)) { + auto counter = std::make_shared(proc, which_counter, mcounter); + csrmap[which_counter] = counter; + } if (xlen == 32) { auto mcounterh = std::make_shared(proc, which_mcounterh, 0); - auto counterh = std::make_shared(proc, which_counterh, mcounterh); csrmap[which_mcounterh] = mcounterh; - csrmap[which_counterh] = counterh; + if (proc->extension_enabled_const(EXT_ZICNTR) && proc->extension_enabled_const(EXT_ZIHPM)) { + auto counterh = std::make_shared(proc, which_counterh, mcounterh); + csrmap[which_counterh] = counterh; + } } } csrmap[CSR_MCOUNTINHIBIT] = std::make_shared(proc, CSR_MCOUNTINHIBIT, 0); diff --git a/riscv/processor.h b/riscv/processor.h index f58ec4bb..9ee3e6c8 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -280,6 +280,8 @@ typedef enum { EXT_ZHINXMIN, EXT_ZICBOM, EXT_ZICBOZ, + EXT_ZICNTR, + EXT_ZIHPM, EXT_XZBP, EXT_XZBS, EXT_XZBE, diff --git a/riscv/sim.cc b/riscv/sim.cc index ad7e45b0..8648d5a2 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -128,7 +128,17 @@ sim_t::sim_t(const char* isa, const char* priv, const char* varch, //handle pmp reg_t pmp_num = 0, pmp_granularity = 0; if (fdt_parse_pmp_num(fdt, cpu_offset, &pmp_num) == 0) { - procs[cpu_idx]->set_pmp_num(pmp_num); + if (pmp_num <= 64) { + procs[cpu_idx]->set_pmp_num(pmp_num); + } else { + std::cerr << "core (" + << hartids.size() + << ") doesn't have valid 'riscv,pmpregions'" + << pmp_num << ").\n"; + exit(1); + } + } else { + procs[cpu_idx]->set_pmp_num(0); } if (fdt_parse_pmp_alignment(fdt, cpu_offset, &pmp_granularity) == 0) { @@ -155,6 +165,8 @@ sim_t::sim_t(const char* isa, const char* priv, const char* varch, << mmu_type << ").\n"; exit(1); } + } else { + procs[cpu_idx]->set_mmu_capability(IMPL_MMU_SBARE); } cpu_idx++;