Skip to content

Commit a4b5a48

Browse files
youngarbinno
authored andcommitted
Add Svukte extension support
This adds support for the Svukte extension, which adds support for address-independent latency of user-mode faults to supervisor addresses.
1 parent 217cbc5 commit a4b5a48

File tree

6 files changed

+49
-7
lines changed

6 files changed

+49
-7
lines changed

disasm/isa_parser.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
265265
extension_table[EXT_SVPBMT] = true;
266266
} else if (ext_str == "svinval") {
267267
extension_table[EXT_SVINVAL] = true;
268+
} else if (ext_str == "svukte") {
269+
extension_table[EXT_SVUKTE] = true;
268270
} else if (ext_str == "zfa") {
269271
extension_table[EXT_ZFA] = true;
270272
} else if (ext_str == "zicbom") {

riscv/csr_init.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
329329
}
330330
const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) |
331331
(proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0) |
332+
(proc->extension_enabled(EXT_SVUKTE) ? SENVCFG_UKTE : 0) |
332333
(proc->extension_enabled(EXT_SSNPM) ? SENVCFG_PMM : 0) |
333334
(proc->extension_enabled(EXT_ZICFILP) ? SENVCFG_LPE : 0) |
334335
(proc->extension_enabled(EXT_ZICFISS) ? SENVCFG_SSE : 0);

riscv/csrs.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2020,7 +2020,8 @@ hstatus_csr_t::hstatus_csr_t(processor_t* const proc, const reg_t addr):
20202020
}
20212021

20222022
bool hstatus_csr_t::unlogged_write(const reg_t val) noexcept {
2023-
const reg_t mask = HSTATUS_VTSR | HSTATUS_VTW
2023+
const reg_t mask = (proc->extension_enabled(EXT_SVUKTE) ? HSTATUS_HUKTE : 0)
2024+
| HSTATUS_VTSR | HSTATUS_VTW
20242025
| (proc->supports_impl(IMPL_MMU) ? HSTATUS_VTVM : 0)
20252026
| (proc->extension_enabled(EXT_SSNPM) ? HSTATUS_HUPMM : 0)
20262027
| HSTATUS_HU | HSTATUS_SPVP | HSTATUS_SPV | HSTATUS_GVA;

riscv/isa_parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ typedef enum {
4747
EXT_SVNAPOT,
4848
EXT_SVPBMT,
4949
EXT_SVINVAL,
50+
EXT_SVUKTE,
5051
EXT_ZDINX,
5152
EXT_ZFA,
5253
EXT_ZFBFMIN,

riscv/mmu.cc

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ void throw_access_exception(bool virt, reg_t addr, access_type type)
5353
}
5454
}
5555

56+
[[noreturn]] void throw_page_access_exception(bool virt, reg_t addr, access_type type)
57+
{
58+
switch (type) {
59+
case FETCH: throw trap_instruction_page_fault(virt, addr, 0, 0);
60+
case LOAD: throw trap_load_page_fault(virt, addr, 0, 0);
61+
case STORE: throw trap_store_page_fault(virt, addr, 0, 0);
62+
default: abort();
63+
}
64+
}
65+
5666
reg_t mmu_t::translate(mem_access_info_t access_info, reg_t len)
5767
{
5868
reg_t addr = access_info.transformed_vaddr;
@@ -560,6 +570,29 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty
560570
}
561571
}
562572

573+
bool mmu_t::check_svukte_qualified(reg_t addr, reg_t mode, bool forced_virt)
574+
{
575+
state_t* state = proc->get_state();
576+
577+
if (mode != PRV_U)
578+
return true;
579+
580+
if (proc->extension_enabled('S') && get_field(state->senvcfg->read(), SENVCFG_UKTE)) {
581+
if (forced_virt && state->prv == PRV_U) {
582+
bool hstatus_hukte = proc->extension_enabled('H') && (get_field(state->hstatus->read(), HSTATUS_HUKTE) == 1);
583+
return !hstatus_hukte;
584+
}
585+
586+
if (((addr >> SYS_MEM_HEADING_BIT) & 0x1)) {
587+
return ((state->v || forced_virt) &&
588+
((proc->get_xlen() == 64) ? ((state->vsatp->read() & SATP64_MODE) == 0) :
589+
((state->vsatp->read() & SATP32_MODE) == 0)));
590+
}
591+
}
592+
593+
return true;
594+
}
595+
563596
reg_t mmu_t::walk(mem_access_info_t access_info)
564597
{
565598
access_type type = access_info.type;
@@ -582,6 +615,10 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
582615
if (vm.levels == 0)
583616
return s2xlate(addr, addr & ((reg_t(2) << (proc->xlen-1))-1), type, type, virt, hlvx, false) & ~page_mask; // zero-extend from xlen
584617

618+
if (proc->extension_enabled(EXT_SVUKTE) && !check_svukte_qualified(addr, mode, access_info.flags.forced_virt)) {
619+
throw_page_access_exception(virt, addr, type);
620+
}
621+
585622
bool s_mode = mode == PRV_S;
586623
bool sum = proc->state.sstatus->readvirt(virt) & MSTATUS_SUM;
587624
bool mxr = (proc->state.sstatus->readvirt(false) | proc->state.sstatus->readvirt(virt)) & MSTATUS_MXR;
@@ -672,12 +709,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
672709
}
673710
}
674711

675-
switch (type) {
676-
case FETCH: throw trap_instruction_page_fault(virt, addr, 0, 0);
677-
case LOAD: throw trap_load_page_fault(virt, addr, 0, 0);
678-
case STORE: throw trap_store_page_fault(virt, addr, 0, 0);
679-
default: abort();
680-
}
712+
throw_page_access_exception(virt, addr, type);
681713
}
682714

683715
void mmu_t::register_memtracer(memtracer_t* t)

riscv/mmu.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ const reg_t PGSIZE = 1 << PGSHIFT;
3434
#define MMU_OBSERVE_STORE(addr, data, length)
3535
#endif
3636

37+
// Svukte extension
38+
#define SYS_MEM_HEADING_BIT 63
39+
3740
struct insn_fetch_t
3841
{
3942
insn_func_t func;
@@ -78,6 +81,7 @@ struct mem_access_info_t {
7881
};
7982

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

8286
// this class implements a processor's port into the virtual memory system.
8387
// an MMU and instruction cache are maintained for simulator performance.
@@ -447,6 +451,7 @@ class mmu_t
447451
check_triggers(operation, address, virt, address, data);
448452
}
449453
void check_triggers(triggers::operation_t operation, reg_t address, bool virt, reg_t tval, std::optional<reg_t> data);
454+
bool check_svukte_qualified(reg_t addr, reg_t mode, bool forced_virt);
450455
reg_t translate(mem_access_info_t access_info, reg_t len);
451456

452457
reg_t pte_load(reg_t pte_paddr, reg_t addr, bool virt, access_type trap_type, size_t ptesize) {

0 commit comments

Comments
 (0)