From 8a34e1a5b3bc68b915127af15ea9254f7d812727 Mon Sep 17 00:00:00 2001 From: Ryan Buchner Date: Tue, 11 Apr 2023 10:42:58 -0700 Subject: Add structure (mem_access_info_t) for holding memory access information Add complementary function for generating access information. Update mmu_t::translate() to accept a mem_access_info_t. --- riscv/mmu.cc | 28 ++++++++++------------------ riscv/mmu.h | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 6a5fdee..e2341fb 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -52,25 +52,16 @@ void throw_access_exception(bool virt, reg_t addr, access_type type) } } -reg_t mmu_t::translate(reg_t addr, reg_t len, access_type type, xlate_flags_t xlate_flags) +reg_t mmu_t::translate(mem_access_info_t access_info, reg_t len) { + reg_t addr = access_info.vaddr; + access_type type = access_info.type; if (!proc) return addr; - bool virt = proc->state.v; - bool hlvx = xlate_flags.hlvx; - reg_t mode = proc->state.prv; - if (type != FETCH) { - if (in_mprv()) { - mode = get_field(proc->state.mstatus->read(), MSTATUS_MPP); - if (get_field(proc->state.mstatus->read(), MSTATUS_MPV) && mode != PRV_M) - virt = true; - } - if (xlate_flags.forced_virt) { - virt = true; - mode = get_field(proc->state.hstatus->read(), HSTATUS_SPVP); - } - } + bool virt = access_info.effective_virt; + bool hlvx = access_info.flags.hlvx; + reg_t mode = (reg_t) access_info.effective_priv; reg_t paddr = walk(addr, type, mode, virt, hlvx) | (addr & (PGSIZE-1)); if (!pmp_ok(paddr, len, type, mode)) @@ -80,12 +71,13 @@ reg_t mmu_t::translate(reg_t addr, reg_t len, access_type type, xlate_flags_t xl tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr) { + auto access_info = generate_access_info(vaddr, FETCH, {false, false, false}); check_triggers(triggers::OPERATION_EXECUTE, vaddr); 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, {false, false, false}); + reg_t paddr = translate(access_info, sizeof(fetch_temp)); if (auto host_addr = sim->addr_to_mem(paddr)) { result = refill_tlb(vaddr, paddr, host_addr, FETCH); } else { @@ -207,7 +199,7 @@ void mmu_t::load_slow_path_intrapage(reg_t addr, reg_t len, uint8_t* bytes, xlat return; } - reg_t paddr = translate(addr, len, LOAD, xlate_flags); + reg_t paddr = translate(generate_access_info(addr, LOAD, xlate_flags), len); if (xlate_flags.lr && !sim->reservable(paddr)) { throw trap_load_access_fault((proc) ? proc->state.v : false, addr, 0, 0); @@ -263,7 +255,7 @@ void mmu_t::store_slow_path_intrapage(reg_t addr, reg_t len, const uint8_t* byte return; } - reg_t paddr = translate(addr, len, STORE, xlate_flags); + reg_t paddr = translate(generate_access_info(addr, STORE, xlate_flags), len); if (actually_store) { if (auto host_addr = sim->addr_to_mem(paddr)) { diff --git a/riscv/mmu.h b/riscv/mmu.h index 6e79539..1039de1 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -48,6 +48,14 @@ struct xlate_flags_t { } }; +struct mem_access_info_t { + const reg_t vaddr; + const reg_t effective_priv; + const bool effective_virt; + const xlate_flags_t flags; + const access_type type; +}; + void throw_access_exception(bool virt, reg_t addr, access_type type); // this class implements a processor's port into the virtual memory system. @@ -57,6 +65,26 @@ class mmu_t private: std::map alloc_cache; std::vector> addr_tbl; + + mem_access_info_t generate_access_info(reg_t addr, access_type type, xlate_flags_t xlate_flags) { + if (!proc) + return {addr, 0, false, {false, false, false}, type}; + bool virt = proc->state.v; + reg_t mode = proc->state.prv; + if (type != FETCH) { + if (in_mprv()) { + mode = get_field(proc->state.mstatus->read(), MSTATUS_MPP); + if (get_field(proc->state.mstatus->read(), MSTATUS_MPV) && mode != PRV_M) + virt = true; + } + if (xlate_flags.forced_virt) { + virt = true; + mode = get_field(proc->state.hstatus->read(), HSTATUS_SPVP); + } + } + return {addr, mode, virt, xlate_flags, type}; + } + public: mmu_t(simif_t* sim, endianness_t endianness, processor_t* proc); ~mmu_t(); @@ -182,7 +210,7 @@ public: void clean_inval(reg_t addr, bool clean, bool inval) { convert_load_traps_to_store_traps({ - const reg_t paddr = translate(addr, blocksz, LOAD, {false, false, false}) & ~(blocksz - 1); + const reg_t paddr = translate(generate_access_info(addr, LOAD, {false, false, false}), blocksz) & ~(blocksz - 1); if (sim->reservable(paddr)) { if (tracer.interested_in_range(paddr, paddr + PGSIZE, LOAD)) tracer.clean_invalidate(paddr, blocksz, clean, inval); @@ -204,7 +232,7 @@ public: store_slow_path(vaddr, size, nullptr, {false, false, false}, false, true); } - reg_t paddr = translate(vaddr, 1, STORE, {false, false, false}); + reg_t paddr = translate(generate_access_info(vaddr, STORE, {false, false, false}), 1); if (sim->reservable(paddr)) return load_reservation_address == paddr; else @@ -360,7 +388,7 @@ private: bool mmio(reg_t paddr, size_t len, uint8_t* bytes, access_type type); bool mmio_ok(reg_t paddr, access_type type); void check_triggers(triggers::operation_t operation, reg_t address, std::optional data = std::nullopt); - reg_t translate(reg_t addr, reg_t len, access_type type, xlate_flags_t xlate_flags); + 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) { if (ptesize == 4) -- cgit v1.1