diff options
author | Andrew Waterman <andrew@sifive.com> | 2022-10-06 14:31:07 -0700 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2022-10-06 19:30:40 -0700 |
commit | 14410156b2d796dad0e439b9535057f1e4c5a13c (patch) | |
tree | 7b5c3ec0cde00a43b26f876848393b90414d3233 /riscv | |
parent | 6311f7513aa150797f69ecac906978bb9e9fecbd (diff) | |
download | spike-14410156b2d796dad0e439b9535057f1e4c5a13c.zip spike-14410156b2d796dad0e439b9535057f1e4c5a13c.tar.gz spike-14410156b2d796dad0e439b9535057f1e4c5a13c.tar.bz2 |
Move uncommon-case fetch functionality into fetch_slow_path
Diffstat (limited to 'riscv')
-rw-r--r-- | riscv/mmu.cc | 32 | ||||
-rw-r--r-- | riscv/mmu.h | 18 |
2 files changed, 25 insertions, 25 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 9c9a6c5..5a5f5c0 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -76,16 +76,32 @@ reg_t mmu_t::translate(reg_t addr, reg_t len, access_type type, uint32_t xlate_f tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr) { - reg_t paddr = translate(vaddr, sizeof(fetch_temp), FETCH, 0); - - if (auto host_addr = sim->addr_to_mem(paddr)) { - return refill_tlb(vaddr, paddr, host_addr, FETCH); + triggers::action_t action; + auto match = proc->TM.memory_access_match(&action, triggers::OPERATION_EXECUTE, vaddr, false); + if (match != triggers::MATCH_NONE) + throw triggers::matched_t(triggers::OPERATION_EXECUTE, vaddr, 0, action); + + tlb_entry_t result; + reg_t vpn = vaddr >> PGSHIFT; + if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] != (vpn | TLB_CHECK_TRIGGERS))) { + reg_t paddr = translate(vaddr, sizeof(fetch_temp), FETCH, 0); + if (auto host_addr = sim->addr_to_mem(paddr)) { + result = refill_tlb(vaddr, paddr, host_addr, FETCH); + } else { + if (!mmio_load(paddr, sizeof fetch_temp, (uint8_t*)&fetch_temp)) + throw trap_instruction_access_fault(proc->state.v, vaddr, 0, 0); + result = {(char*)&fetch_temp - vaddr, paddr - vaddr}; + } } else { - if (!mmio_load(paddr, sizeof fetch_temp, (uint8_t*)&fetch_temp)) - throw trap_instruction_access_fault(proc->state.v, vaddr, 0, 0); - tlb_entry_t entry = {(char*)&fetch_temp - vaddr, paddr - vaddr}; - return entry; + result = tlb_data[vpn % TLB_ENTRIES]; } + + target_endian<uint16_t>* ptr = (target_endian<uint16_t>*)(result.host_offset + vaddr); + match = proc->TM.memory_access_match(&action, triggers::OPERATION_EXECUTE, vaddr, true, from_target(*ptr)); + if (match != triggers::MATCH_NONE) + throw triggers::matched_t(triggers::OPERATION_EXECUTE, vaddr, from_target(*ptr), action); + + return result; } reg_t reg_from_bytes(size_t len, const uint8_t* bytes) diff --git a/riscv/mmu.h b/riscv/mmu.h index 137b306..74c9a71 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -391,23 +391,7 @@ private: reg_t vpn = addr >> PGSHIFT; if (likely(tlb_insn_tag[vpn % TLB_ENTRIES] == vpn)) return tlb_data[vpn % TLB_ENTRIES]; - triggers::action_t action; - auto match = proc->TM.memory_access_match(&action, triggers::OPERATION_EXECUTE, addr, false); - if (match != triggers::MATCH_NONE) { - throw triggers::matched_t(triggers::OPERATION_EXECUTE, addr, 0, action); - } - tlb_entry_t result; - if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] != (vpn | TLB_CHECK_TRIGGERS))) { - result = fetch_slow_path(addr); - } else { - result = tlb_data[vpn % TLB_ENTRIES]; - } - target_endian<uint16_t>* ptr = (target_endian<uint16_t>*)(result.host_offset + addr); - match = proc->TM.memory_access_match(&action, triggers::OPERATION_EXECUTE, addr, true, from_target(*ptr)); - if (match != triggers::MATCH_NONE) { - throw triggers::matched_t(triggers::OPERATION_EXECUTE, addr, from_target(*ptr), action); - } - return result; + return fetch_slow_path(addr); } inline const uint16_t* translate_insn_addr_to_host(reg_t addr) { |