Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 21 additions & 14 deletions riscv/mmu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}

Expand Down
3 changes: 2 additions & 1 deletion riscv/mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,8 @@ class mmu_t
check_triggers(operation, address, virt, address, data);
}
void check_triggers(triggers::operation_t operation, reg_t address, bool virt, reg_t tval, std::optional<reg_t> 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) {
Expand Down
Loading