-
Notifications
You must be signed in to change notification settings - Fork 993
Add Svukte extension support #2121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,6 +47,7 @@ typedef enum { | |
| EXT_SVNAPOT, | ||
| EXT_SVPBMT, | ||
| EXT_SVINVAL, | ||
| EXT_SVUKTE, | ||
| EXT_ZDINX, | ||
| EXT_ZFA, | ||
| EXT_ZFBFMIN, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rename this function to |
||
| { | ||
| 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; | ||
|
|
@@ -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)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should have |
||
| return ((state->v || forced_virt) && | ||
| ((proc->get_xlen() == 64) ? ((state->vsatp->read() & SATP64_MODE) == 0) : | ||
| ((state->vsatp->read() & SATP32_MODE) == 0))); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
|
|
@@ -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; | ||
|
|
@@ -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) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
|
|
@@ -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. | ||
|
|
@@ -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) { | ||
|
|
||
There was a problem hiding this comment.
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.