From 62d64ef6bd915b66d3b7d588c2f679278a85457a Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 1 Dec 2025 17:38:11 -0800 Subject: [PATCH] Fix Svukte implementation - Change polarity of svukte_qualified to match ISA spec - Avoid address dependence of svukte_qualified, per ISA spec - Move address check to separate routine --- riscv/mmu.cc | 35 +++++++++++++++++++++-------------- riscv/mmu.h | 3 ++- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 4dbe3476..6b4a571d 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -630,28 +630,35 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty } } -bool mmu_t::check_svukte_qualified(reg_t addr, reg_t mode, bool forced_virt) +bool mmu_t::svukte_qualified(mem_access_info_t access_info) { state_t* state = proc->get_state(); - if (mode != PRV_U) - return true; + if (access_info.effective_priv != PRV_U) + return false; - if (proc->extension_enabled('S') && get_field(state->senvcfg->read(), SENVCFG_UKTE)) { - if (forced_virt && state->prv == PRV_U) { - bool hstatus_hukte = proc->extension_enabled('H') && (get_field(state->hstatus->read(), HSTATUS_HUKTE) == 1); - return !hstatus_hukte; - } + bool ukte = get_field(state->senvcfg->read(), SENVCFG_UKTE); + if (access_info.flags.forced_virt && state->prv == PRV_U) + ukte = get_field(state->hstatus->read(), HSTATUS_HUKTE); - assert(proc->get_xlen() == 64); - if ((addr >> 63) & 1) { - return (state->v || forced_virt) && ((state->vsatp->read() & SATP64_MODE) == 0); - } - } + if (!ukte) + return false; + + reg_t mode_mask = proc->get_xlen() == 32 ? SATP32_MODE : SATP64_MODE; + if (get_field(proc->get_state()->satp->readvirt(access_info.effective_virt), mode_mask) == 0) + return false; return true; } +bool mmu_t::svukte_fault(reg_t addr, mem_access_info_t access_info) +{ + if (!svukte_qualified(access_info)) + return false; + + return addr >> (proc->get_xlen() - 1); +} + reg_t mmu_t::walk(mem_access_info_t access_info) { access_type type = access_info.type; @@ -674,7 +681,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info) if (vm.levels == 0) return s2xlate(addr, addr & ((reg_t(2) << (proc->xlen-1))-1), type, type, virt, hlvx, false) & ~page_mask; // zero-extend from xlen - if (proc->extension_enabled(EXT_SVUKTE) && !check_svukte_qualified(addr, mode, access_info.flags.forced_virt)) { + if (svukte_fault(addr, access_info)) { throw_page_fault_exception(virt, addr, type); } diff --git a/riscv/mmu.h b/riscv/mmu.h index b1c9306a..9112eed6 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -453,7 +453,8 @@ private: check_triggers(operation, address, virt, address, data); } void check_triggers(triggers::operation_t operation, reg_t address, bool virt, reg_t tval, std::optional data); - bool check_svukte_qualified(reg_t addr, reg_t mode, bool forced_virt); + bool svukte_qualified(mem_access_info_t access_info); + bool svukte_fault(reg_t addr, mem_access_info_t access_info); reg_t translate(mem_access_info_t access_info, reg_t len); reg_t pte_load(reg_t pte_paddr, reg_t addr, bool virt, access_type trap_type, size_t ptesize) {