Browse Source

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
pull/2171/head
Andrew Waterman 5 months ago
parent
commit
62d64ef6bd
  1. 35
      riscv/mmu.cc
  2. 3
      riscv/mmu.h

35
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(); state_t* state = proc->get_state();
if (mode != PRV_U) if (access_info.effective_priv != PRV_U)
return true; return false;
if (proc->extension_enabled('S') && get_field(state->senvcfg->read(), SENVCFG_UKTE)) { bool ukte = get_field(state->senvcfg->read(), SENVCFG_UKTE);
if (forced_virt && state->prv == PRV_U) { if (access_info.flags.forced_virt && state->prv == PRV_U)
bool hstatus_hukte = proc->extension_enabled('H') && (get_field(state->hstatus->read(), HSTATUS_HUKTE) == 1); ukte = get_field(state->hstatus->read(), HSTATUS_HUKTE);
return !hstatus_hukte;
}
assert(proc->get_xlen() == 64); if (!ukte)
if ((addr >> 63) & 1) { return false;
return (state->v || forced_virt) && ((state->vsatp->read() & SATP64_MODE) == 0);
} 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; 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) reg_t mmu_t::walk(mem_access_info_t access_info)
{ {
access_type type = access_info.type; 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) 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 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); throw_page_fault_exception(virt, addr, type);
} }

3
riscv/mmu.h

@ -453,7 +453,8 @@ private:
check_triggers(operation, address, virt, address, data); 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); 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 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) { reg_t pte_load(reg_t pte_paddr, reg_t addr, bool virt, access_type trap_type, size_t ptesize) {

Loading…
Cancel
Save