From 25f9028475b3b774be617a197fe76435827258b1 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Tue, 27 Dec 2022 15:38:41 -0800 Subject: Pull pte load/store into methods of mmu_t --- riscv/mmu.cc | 23 +++++------------------ riscv/mmu.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index ddf277b..0ac0d65 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -42,7 +42,7 @@ void mmu_t::flush_tlb() flush_icache(); } -static void throw_access_exception(bool virt, reg_t addr, access_type type) +void throw_access_exception(bool virt, reg_t addr, access_type type) { switch (type) { case FETCH: throw trap_instruction_access_fault(virt, addr, 0, 0); @@ -382,12 +382,7 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty // check that physical address of PTE is legal auto pte_paddr = base + idx * vm.ptesize; - auto ppte = sim->addr_to_mem(pte_paddr); - if (!ppte || !pmp_ok(pte_paddr, vm.ptesize, LOAD, PRV_S)) { - throw_access_exception(virt, gva, trap_type); - } - - reg_t pte = vm.ptesize == 4 ? from_target(*(target_endian*)ppte) : from_target(*(target_endian*)ppte); + reg_t pte = pte_load(pte_paddr, gva, virt, trap_type, vm.ptesize); reg_t ppn = (pte & ~reg_t(PTE_ATTR)) >> PTE_PPN_SHIFT; bool pbmte = proc->get_state()->menvcfg->read() & MENVCFG_PBMTE; @@ -418,9 +413,7 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty #ifdef RISCV_ENABLE_DIRTY // set accessed and possibly dirty bits. if ((pte & ad) != ad) { - if (!pmp_ok(pte_paddr, vm.ptesize, STORE, PRV_S)) - throw_access_exception(virt, gva, trap_type); - *(target_endian*)ppte |= to_target((uint32_t)ad); + pte_store(pte_paddr, pte | ad, gva, virt, type, vm.ptesize); } #else // take exception if access or possibly dirty bit is not set. @@ -476,11 +469,7 @@ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode, bool virt, bool hlvx // check that physical address of PTE is legal auto pte_paddr = s2xlate(addr, base + idx * vm.ptesize, LOAD, type, virt, false); - auto ppte = sim->addr_to_mem(pte_paddr); - if (!ppte || !pmp_ok(pte_paddr, vm.ptesize, LOAD, PRV_S)) - throw_access_exception(virt, addr, type); - - reg_t pte = vm.ptesize == 4 ? from_target(*(target_endian*)ppte) : from_target(*(target_endian*)ppte); + reg_t pte = pte_load(pte_paddr, addr, virt, type, vm.ptesize); reg_t ppn = (pte & ~reg_t(PTE_ATTR)) >> PTE_PPN_SHIFT; bool pbmte = virt ? (proc->get_state()->henvcfg->read() & HENVCFG_PBMTE) : (proc->get_state()->menvcfg->read() & MENVCFG_PBMTE); @@ -511,9 +500,7 @@ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode, bool virt, bool hlvx #ifdef RISCV_ENABLE_DIRTY // set accessed and possibly dirty bits. if ((pte & ad) != ad) { - if (!pmp_ok(pte_paddr, vm.ptesize, STORE, PRV_S)) - throw_access_exception(virt, addr, type); - *(target_endian*)ppte |= to_target((uint32_t)ad); + pte_store(pte_paddr, pte | ad, addr, virt, type, vm.ptesize); } #else // take exception if access or possibly dirty bit is not set. diff --git a/riscv/mmu.h b/riscv/mmu.h index cc00010..6f532c1 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -38,6 +38,8 @@ struct tlb_entry_t { reg_t target_offset; }; +void throw_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. class mmu_t @@ -354,6 +356,53 @@ private: 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, uint32_t xlate_flags); + reg_t pte_load(reg_t pte_paddr, reg_t addr, bool virt, access_type trap_type, size_t ptesize) { + if (ptesize == 4) + return pte_load(pte_paddr, addr, virt, trap_type); + else + return pte_load(pte_paddr, addr, virt, trap_type); + } + + void pte_store(reg_t pte_paddr, reg_t new_pte, reg_t addr, bool virt, access_type trap_type, size_t ptesize) { + if (ptesize == 4) + return pte_store(pte_paddr, new_pte, addr, virt, trap_type); + else + return pte_store(pte_paddr, new_pte, addr, virt, trap_type); + } + + template inline reg_t pte_load(reg_t pte_paddr, reg_t addr, bool virt, access_type trap_type) + { + const size_t ptesize = sizeof(T); + + if (!pmp_ok(pte_paddr, ptesize, LOAD, PRV_S)) + throw_access_exception(virt, addr, trap_type); + + void* host_pte_paddr = sim->addr_to_mem(pte_paddr); + target_endian target_pte; + if (host_pte_paddr) { + memcpy(&target_pte, host_pte_paddr, ptesize); + } else { + throw_access_exception(virt, addr, trap_type); + } + return from_target(target_pte); + } + + template inline void pte_store(reg_t pte_paddr, reg_t new_pte, reg_t addr, bool virt, access_type trap_type) + { + const size_t ptesize = sizeof(T); + + if (!pmp_ok(pte_paddr, ptesize, STORE, PRV_S)) + throw_access_exception(virt, addr, trap_type); + + void* host_pte_paddr = sim->addr_to_mem(pte_paddr); + target_endian target_pte = to_target((T)new_pte); + if (host_pte_paddr) { + memcpy(host_pte_paddr, &target_pte, ptesize); + } else { + throw_access_exception(virt, addr, trap_type); + } + } + // ITLB lookup inline tlb_entry_t translate_insn_addr(reg_t addr) { reg_t vpn = addr >> PGSHIFT; -- cgit v1.1 From 43474ddc63ff52ef6a92e32889312609a770941c Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 28 Dec 2022 19:59:30 -0800 Subject: Support pte load/store from mmio regions --- riscv/mmu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/riscv/mmu.h b/riscv/mmu.h index 6f532c1..061c5f8 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -381,7 +381,7 @@ private: target_endian target_pte; if (host_pte_paddr) { memcpy(&target_pte, host_pte_paddr, ptesize); - } else { + } else if (!mmio_load(pte_paddr, ptesize, (uint8_t*)&target_pte)) { throw_access_exception(virt, addr, trap_type); } return from_target(target_pte); @@ -398,7 +398,7 @@ private: target_endian target_pte = to_target((T)new_pte); if (host_pte_paddr) { memcpy(host_pte_paddr, &target_pte, ptesize); - } else { + } else if (!mmio_store(pte_paddr, ptesize, (uint8_t*)&target_pte)) { throw_access_exception(virt, addr, trap_type); } } -- cgit v1.1