X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=riscv%2Fmmu.cc;h=3a0bd39b89471470cef1155f201a646b673cbfab;hb=d6fcfdebf6a893bf37670fd67203d18653df4a0e;hp=76a6ab1d4f685cf142a83d03a87f68847529e266;hpb=b3caeee9858b3417d4110b921305c441d3c87653;p=riscv-isa-sim.git diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 76a6ab1..3a0bd39 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -1,10 +1,10 @@ // See LICENSE for license details. #include "mmu.h" -#include "sim.h" +#include "simif.h" #include "processor.h" -mmu_t::mmu_t(sim_t* sim, processor_t* proc) +mmu_t::mmu_t(simif_t* sim, processor_t* proc) : sim(sim), proc(proc), check_triggers_fetch(false), check_triggers_load(false), @@ -159,11 +159,11 @@ tlb_entry_t mmu_t::refill_tlb(reg_t vaddr, reg_t paddr, char* host_addr, access_ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode) { - vm_info vm = decode_vm_info(proc->max_xlen, mode, proc->get_state()->sptbr); + vm_info vm = decode_vm_info(proc->max_xlen, mode, proc->get_state()->satp); if (vm.levels == 0) return addr & ((reg_t(2) << (proc->xlen-1))-1); // zero-extend from xlen - bool supervisor = mode == PRV_S; + bool s_mode = mode == PRV_S; bool sum = get_field(proc->state.mstatus, MSTATUS_SUM); bool mxr = get_field(proc->state.mstatus, MSTATUS_MXR); @@ -182,14 +182,14 @@ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode) // check that physical address of PTE is legal auto ppte = sim->addr_to_mem(base + idx * vm.ptesize); if (!ppte) - throw trap_load_access_fault(addr); + goto fail_access; reg_t pte = vm.ptesize == 4 ? *(uint32_t*)ppte : *(uint64_t*)ppte; reg_t ppn = pte >> PTE_PPN_SHIFT; if (PTE_TABLE(pte)) { // next level of page table base = ppn << PGSHIFT; - } else if ((pte & PTE_U) ? supervisor && !sum : !supervisor) { + } else if ((pte & PTE_U) ? s_mode && (type == FETCH || !sum) : !s_mode) { break; } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) { break; @@ -223,6 +223,14 @@ fail: case STORE: throw trap_store_page_fault(addr); default: abort(); } + +fail_access: + switch (type) { + case FETCH: throw trap_instruction_access_fault(addr); + case LOAD: throw trap_load_access_fault(addr); + case STORE: throw trap_store_access_fault(addr); + default: abort(); + } } void mmu_t::register_memtracer(memtracer_t* t)