From 1bf835816a6871a4b638d0795054bb726eec5d6c Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 4 Dec 2025 15:29:06 -0800 Subject: [PATCH] Clean up VA size handling Representing the VA size as a feature set rather than an integer allows for internal inconsistency and is inelegant. --- riscv/csrs.cc | 22 +++++++++---------- riscv/decode_macros.h | 1 - riscv/insns/sfence_inval_ir.h | 2 +- riscv/insns/sfence_vma.h | 2 +- riscv/isa_parser.h | 6 ----- riscv/processor.cc | 41 ++++++++++++++--------------------- riscv/processor.h | 4 ++++ riscv/sim.cc | 12 +++++----- 8 files changed, 38 insertions(+), 52 deletions(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index ce64ee65..70468d0f 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -431,7 +431,7 @@ reg_t cause_csr_t::read() const noexcept { // 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), - has_page(proc->extension_enabled_const('S') && proc->supports_impl(IMPL_MMU)), + has_page(proc->extension_enabled_const('S') && proc->has_mmu()), sstatus_write_mask(compute_sstatus_write_mask()), sstatus_read_mask(sstatus_write_mask | SSTATUS_UBE | SSTATUS_UXL | (proc->get_const_xlen() == 32 ? SSTATUS32_SD : SSTATUS64_SD)) { @@ -1005,7 +1005,7 @@ bool medeleg_csr_t::unlogged_write(const reg_t val) noexcept { | (1 << CAUSE_STORE_ACCESS) | (1 << CAUSE_USER_ECALL) | (1 << CAUSE_SUPERVISOR_ECALL) - | (proc->supports_impl(IMPL_MMU) ? mmu_exceptions : 0) + | (proc->has_mmu() ? mmu_exceptions : 0) | (proc->extension_enabled('H') ? hypervisor_exceptions : 0) | (1 << CAUSE_SOFTWARE_CHECK_FAULT) | (1 << CAUSE_HARDWARE_ERROR_FAULT) @@ -1088,7 +1088,7 @@ base_atp_csr_t::base_atp_csr_t(processor_t* const proc, const reg_t addr): } 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; + const reg_t newval = proc->has_mmu() ? compute_new_satp(val) : 0; if (newval != read()) proc->get_mmu()->flush_tlb(); return basic_csr_t::unlogged_write(newval); @@ -1097,16 +1097,16 @@ bool base_atp_csr_t::unlogged_write(const reg_t val) noexcept { bool base_atp_csr_t::satp_valid(reg_t val) const noexcept { if (proc->get_xlen() == 32) { switch (get_field(val, SATP32_MODE)) { - case SATP_MODE_SV32: return proc->supports_impl(IMPL_MMU_SV32); case SATP_MODE_OFF: return true; + case SATP_MODE_SV32: return proc->get_max_vaddr_bits() >= 32; default: return false; } } else { switch (get_field(val, SATP64_MODE)) { - case SATP_MODE_SV39: return proc->supports_impl(IMPL_MMU_SV39); - case SATP_MODE_SV48: return proc->supports_impl(IMPL_MMU_SV48); - case SATP_MODE_SV57: return proc->supports_impl(IMPL_MMU_SV57); case SATP_MODE_OFF: return true; + case SATP_MODE_SV39: return proc->get_max_vaddr_bits() >= 39; + case SATP_MODE_SV48: return proc->get_max_vaddr_bits() >= 48; + case SATP_MODE_SV57: return proc->get_max_vaddr_bits() >= 57; default: return false; } } @@ -1345,9 +1345,9 @@ bool hgatp_csr_t::unlogged_write(const reg_t val) noexcept { (proc->supports_impl(IMPL_MMU_VMID) ? HGATP64_VMID : 0); if (get_field(val, HGATP64_MODE) == HGATP_MODE_OFF || - (proc->supports_impl(IMPL_MMU_SV39) && get_field(val, HGATP64_MODE) == HGATP_MODE_SV39X4) || - (proc->supports_impl(IMPL_MMU_SV48) && get_field(val, HGATP64_MODE) == HGATP_MODE_SV48X4) || - (proc->supports_impl(IMPL_MMU_SV57) && get_field(val, HGATP64_MODE) == HGATP_MODE_SV57X4)) + (proc->get_max_vaddr_bits() >= 39 && get_field(val, HGATP64_MODE) == HGATP_MODE_SV39X4) || + (proc->get_max_vaddr_bits() >= 48 && get_field(val, HGATP64_MODE) == HGATP_MODE_SV48X4) || + (proc->get_max_vaddr_bits() >= 57 && get_field(val, HGATP64_MODE) == HGATP_MODE_SV57X4)) mask |= HGATP64_MODE; } mask &= ~(reg_t)3; @@ -2037,7 +2037,7 @@ hstatus_csr_t::hstatus_csr_t(processor_t* const proc, const reg_t addr): bool hstatus_csr_t::unlogged_write(const reg_t val) noexcept { const reg_t mask = (proc->extension_enabled(EXT_SVUKTE) ? HSTATUS_HUKTE : 0) | HSTATUS_VTSR | HSTATUS_VTW - | (proc->supports_impl(IMPL_MMU) ? HSTATUS_VTVM : 0) + | (proc->has_mmu() ? HSTATUS_VTVM : 0) | (proc->extension_enabled(EXT_SSNPM) ? HSTATUS_HUPMM : 0) | HSTATUS_HU | HSTATUS_SPVP | HSTATUS_SPV | HSTATUS_GVA; diff --git a/riscv/decode_macros.h b/riscv/decode_macros.h index 136c9eda..6f24799f 100644 --- a/riscv/decode_macros.h +++ b/riscv/decode_macros.h @@ -163,7 +163,6 @@ static inline bool is_aligned(const unsigned val, const unsigned pos) #define require_rv32 require(xlen == 32) #define require_extension(s) require(p->extension_enabled(s)) #define require_either_extension(A,B) require(p->extension_enabled(A) || p->extension_enabled(B)); -#define require_impl(s) require(p->supports_impl(s)) #define require_fp STATE.fflags->verify_permissions(insn, false) #define require_accelerator require(STATE.sstatus->enabled(SSTATUS_XS)) #define require_vector_vs require(p->any_vector_extensions() && STATE.sstatus->enabled(SSTATUS_VS)) diff --git a/riscv/insns/sfence_inval_ir.h b/riscv/insns/sfence_inval_ir.h index 6f76a3ff..42fb177d 100644 --- a/riscv/insns/sfence_inval_ir.h +++ b/riscv/insns/sfence_inval_ir.h @@ -1,4 +1,4 @@ require_extension('S'); require_extension(EXT_SVINVAL); -require_impl(IMPL_MMU); +require(p->has_mmu()); require_privilege_hs_qualified(PRV_S); diff --git a/riscv/insns/sfence_vma.h b/riscv/insns/sfence_vma.h index 7d6c01a8..156331d1 100644 --- a/riscv/insns/sfence_vma.h +++ b/riscv/insns/sfence_vma.h @@ -1,5 +1,5 @@ require_extension('S'); -require_impl(IMPL_MMU); +require(p->has_mmu()); if (STATE.v) { if (STATE.prv == PRV_U || get_field(STATE.hstatus->read(), HSTATUS_VTVM)) require_novirt(); diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 8815ec2d..ff2867a6 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -114,12 +114,6 @@ typedef enum { } isa_extension_t; typedef enum { - IMPL_MMU_SV32, - IMPL_MMU_SV39, - IMPL_MMU_SV48, - IMPL_MMU_SV57, - IMPL_MMU_SBARE, - IMPL_MMU, IMPL_MMU_VMID, IMPL_MMU_ASID, } impl_extension_t; diff --git a/riscv/processor.cc b/riscv/processor.cc index 8962d6c1..80a47d93 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -67,11 +67,7 @@ processor_t::processor_t(const char* isa_str, const char* priv_str, set_pmp_granularity(cfg->pmpgranularity); set_pmp_num(cfg->pmpregions); - if (isa.get_max_xlen() == 32) - set_mmu_capability(IMPL_MMU_SV32); - else if (isa.get_max_xlen() == 64) - set_mmu_capability(IMPL_MMU_SV57); - + set_max_vaddr_bits(0); set_impl(IMPL_MMU_ASID, true); set_impl(IMPL_MMU_VMID, true); @@ -217,31 +213,26 @@ void processor_t::set_pmp_granularity(reg_t gran) lg_pmp_granularity = ctz(gran); } -void processor_t::set_mmu_capability(int cap) +void processor_t::set_max_vaddr_bits(unsigned n) { - switch (cap) { - case IMPL_MMU_SV32: - set_impl(IMPL_MMU_SV32, true); - set_impl(IMPL_MMU, true); + switch (n) { + case 0: break; - case IMPL_MMU_SV57: - set_impl(IMPL_MMU_SV57, true); - [[fallthrough]]; - case IMPL_MMU_SV48: - set_impl(IMPL_MMU_SV48, true); - [[fallthrough]]; - case IMPL_MMU_SV39: - set_impl(IMPL_MMU_SV39, true); - set_impl(IMPL_MMU, true); + case 32: + if (isa.get_max_xlen() != 32) + abort(); break; - default: - set_impl(IMPL_MMU_SV32, false); - set_impl(IMPL_MMU_SV39, false); - set_impl(IMPL_MMU_SV48, false); - set_impl(IMPL_MMU_SV57, false); - set_impl(IMPL_MMU, false); + case 39: + case 48: + case 57: + if (isa.get_max_xlen() != 64) + abort(); break; + default: + abort(); } + + max_vaddr_bits = n; } reg_t processor_t::select_an_interrupt_with_default_priority(reg_t enabled_interrupts) const diff --git a/riscv/processor.h b/riscv/processor.h index d0c5b3f9..18ac08f0 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -290,6 +290,9 @@ public: extension_enable_table[ext] = enable && isa.extension_enabled(ext); } void set_impl(uint8_t impl, bool val) { impl_table[impl] = val; } + bool has_mmu() const { return max_vaddr_bits != 0; } + unsigned get_max_vaddr_bits() const { return max_vaddr_bits; } + void set_max_vaddr_bits(unsigned); bool supports_impl(uint8_t impl) const { return impl_table[impl]; } @@ -358,6 +361,7 @@ private: state_t state; uint32_t id; unsigned xlen; + unsigned max_vaddr_bits; bool histogram_enabled; bool log_commits_enabled; FILE *log_file; diff --git a/riscv/sim.cc b/riscv/sim.cc index e11bebab..4eb5ed0a 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -214,16 +214,16 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, // handle mmu-type const char *mmu_type; rc = fdt_parse_mmu_type(fdt, cpu_offset, &mmu_type); + procs[cpu_idx]->set_max_vaddr_bits(0); if (rc == 0) { - procs[cpu_idx]->set_mmu_capability(IMPL_MMU_SBARE); if (strncmp(mmu_type, "riscv,sv32", strlen("riscv,sv32")) == 0) { - procs[cpu_idx]->set_mmu_capability(IMPL_MMU_SV32); + procs[cpu_idx]->set_max_vaddr_bits(32); } else if (strncmp(mmu_type, "riscv,sv39", strlen("riscv,sv39")) == 0) { - procs[cpu_idx]->set_mmu_capability(IMPL_MMU_SV39); + procs[cpu_idx]->set_max_vaddr_bits(39); } else if (strncmp(mmu_type, "riscv,sv48", strlen("riscv,sv48")) == 0) { - procs[cpu_idx]->set_mmu_capability(IMPL_MMU_SV48); + procs[cpu_idx]->set_max_vaddr_bits(48); } else if (strncmp(mmu_type, "riscv,sv57", strlen("riscv,sv57")) == 0) { - procs[cpu_idx]->set_mmu_capability(IMPL_MMU_SV57); + procs[cpu_idx]->set_max_vaddr_bits(57); } else if (strncmp(mmu_type, "riscv,sbare", strlen("riscv,sbare")) == 0) { // has been set in the beginning } else { @@ -233,8 +233,6 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, << mmu_type << ").\n"; exit(1); } - } else { - procs[cpu_idx]->set_mmu_capability(IMPL_MMU_SBARE); } procs[cpu_idx]->reset();