Skip to content
Open
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
2 changes: 2 additions & 0 deletions disasm/isa_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_SVPBMT] = true;
} else if (ext_str == "svinval") {
extension_table[EXT_SVINVAL] = true;
} else if (ext_str == "svukte") {
extension_table[EXT_SVUKTE] = true;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have a check that XLEN is 64 and issue an error if not.

} else if (ext_str == "zfa") {
extension_table[EXT_ZFA] = true;
} else if (ext_str == "zicbom") {
Expand Down
1 change: 1 addition & 0 deletions riscv/csr_init.cc
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
}
const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) |
(proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0) |
(proc->extension_enabled(EXT_SVUKTE) ? SENVCFG_UKTE : 0) |
(proc->extension_enabled(EXT_SSNPM) ? SENVCFG_PMM : 0) |
(proc->extension_enabled(EXT_ZICFILP) ? SENVCFG_LPE : 0) |
(proc->extension_enabled(EXT_ZICFISS) ? SENVCFG_SSE : 0);
Expand Down
3 changes: 2 additions & 1 deletion riscv/csrs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2020,7 +2020,8 @@ 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 = HSTATUS_VTSR | HSTATUS_VTW
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->extension_enabled(EXT_SSNPM) ? HSTATUS_HUPMM : 0)
| HSTATUS_HU | HSTATUS_SPVP | HSTATUS_SPV | HSTATUS_GVA;
Expand Down
1 change: 1 addition & 0 deletions riscv/isa_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ typedef enum {
EXT_SVNAPOT,
EXT_SVPBMT,
EXT_SVINVAL,
EXT_SVUKTE,
EXT_ZDINX,
EXT_ZFA,
EXT_ZFBFMIN,
Expand Down
44 changes: 38 additions & 6 deletions riscv/mmu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ void throw_access_exception(bool virt, reg_t addr, access_type type)
}
}

[[noreturn]] void throw_page_access_exception(bool virt, reg_t addr, access_type type)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename this function to throw_page_fault_exception.

{
switch (type) {
case FETCH: throw trap_instruction_page_fault(virt, addr, 0, 0);
case LOAD: throw trap_load_page_fault(virt, addr, 0, 0);
case STORE: throw trap_store_page_fault(virt, addr, 0, 0);
default: abort();
}
}

reg_t mmu_t::translate(mem_access_info_t access_info, reg_t len)
{
reg_t addr = access_info.transformed_vaddr;
Expand Down Expand Up @@ -560,6 +570,29 @@ 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)
{
state_t* state = proc->get_state();

if (mode != PRV_U)
return true;

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;
}

if (((addr >> SYS_MEM_HEADING_BIT) & 0x1)) {
Copy link
Collaborator

@aswaterman aswaterman Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should have assert(proc->get_xlen() == 64) here. Then we can simply write if ((addr >> 63) & 1).

return ((state->v || forced_virt) &&
((proc->get_xlen() == 64) ? ((state->vsatp->read() & SATP64_MODE) == 0) :
((state->vsatp->read() & SATP32_MODE) == 0)));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And then we can get rid of the XLEN=32 stuff here.

}
}

return true;
}

reg_t mmu_t::walk(mem_access_info_t access_info)
{
access_type type = access_info.type;
Expand All @@ -582,6 +615,10 @@ 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)) {
throw_page_access_exception(virt, addr, type);
}

bool s_mode = mode == PRV_S;
bool sum = proc->state.sstatus->readvirt(virt) & MSTATUS_SUM;
bool mxr = (proc->state.sstatus->readvirt(false) | proc->state.sstatus->readvirt(virt)) & MSTATUS_MXR;
Expand Down Expand Up @@ -672,12 +709,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
}
}

switch (type) {
case FETCH: throw trap_instruction_page_fault(virt, addr, 0, 0);
case LOAD: throw trap_load_page_fault(virt, addr, 0, 0);
case STORE: throw trap_store_page_fault(virt, addr, 0, 0);
default: abort();
}
throw_page_access_exception(virt, addr, type);
}

void mmu_t::register_memtracer(memtracer_t* t)
Expand Down
5 changes: 5 additions & 0 deletions riscv/mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ const reg_t PGSIZE = 1 << PGSHIFT;
#define MMU_OBSERVE_STORE(addr, data, length)
#endif

// Svukte extension
#define SYS_MEM_HEADING_BIT 63
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And we can get rid of this, too.


struct insn_fetch_t
{
insn_func_t func;
Expand Down Expand Up @@ -78,6 +81,7 @@ struct mem_access_info_t {
};

void throw_access_exception(bool virt, reg_t addr, access_type type);
[[noreturn]] void throw_page_access_exception(bool virt, reg_t addr, access_type type);

// this class implements a processor's port into the virtual memory system.
// an MMU and instruction cache are maintained for simulator performance.
Expand Down Expand Up @@ -447,6 +451,7 @@ 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);
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