diff options
Diffstat (limited to 'riscv/mmu.cc')
-rw-r--r-- | riscv/mmu.cc | 28 |
1 files changed, 13 insertions, 15 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 3c62295..2d8e283 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -55,6 +55,7 @@ reg_t mmu_t::translate(reg_t addr, reg_t len, access_type type, uint32_t xlate_f bool mxr = get_field(proc->state.mstatus, MSTATUS_MXR); bool virt = (proc) ? proc->state.v : false; + bool hlvx = xlate_flags & RISCV_XLATE_VIRT_HLVX; reg_t mode = proc->state.prv; if (type != FETCH) { if (!proc->state.debug_mode && get_field(proc->state.mstatus, MSTATUS_MPRV)) { @@ -65,13 +66,10 @@ reg_t mmu_t::translate(reg_t addr, reg_t len, access_type type, uint32_t xlate_f if (xlate_flags & RISCV_XLATE_VIRT) { virt = true; mode = get_field(proc->state.hstatus, HSTATUS_SPVP); - if (type == LOAD && (xlate_flags & RISCV_XLATE_VIRT_MXR)) { - mxr = true; - } } } - reg_t paddr = walk(addr, type, mode, virt, mxr) | (addr & (PGSIZE-1)); + reg_t paddr = walk(addr, type, mode, virt, mxr, hlvx) | (addr & (PGSIZE-1)); if (!pmp_ok(paddr, len, type, mode)) throw_access_exception(virt, addr, type); return paddr; @@ -305,7 +303,7 @@ reg_t mmu_t::pmp_homogeneous(reg_t addr, reg_t len) return true; } -reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_type, bool virt, bool mxr) +reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_type, bool virt, bool mxr, bool hlvx) { if (!virt) return gpa; @@ -338,9 +336,9 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty break; } else if (!(pte & PTE_U)) { break; - } else if (type == FETCH ? !(pte & PTE_X) : - type == LOAD ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) : - !((pte & PTE_R) && (pte & PTE_W))) { + } else if (type == FETCH || hlvx ? !(pte & PTE_X) : + type == LOAD ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) : + !((pte & PTE_R) && (pte & PTE_W))) { break; } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) { break; @@ -380,13 +378,13 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty } } -reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode, bool virt, bool mxr) +reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode, bool virt, bool mxr, bool hlvx) { reg_t page_mask = (reg_t(1) << PGSHIFT) - 1; reg_t satp = (virt) ? proc->get_state()->vsatp : proc->get_state()->satp; vm_info vm = decode_vm_info(proc->max_xlen, false, mode, satp); if (vm.levels == 0) - return s2xlate(addr, addr & ((reg_t(2) << (proc->xlen-1))-1), type, type, virt, mxr) & ~page_mask; // zero-extend from xlen + return s2xlate(addr, addr & ((reg_t(2) << (proc->xlen-1))-1), type, type, virt, mxr, hlvx) & ~page_mask; // zero-extend from xlen bool s_mode = mode == PRV_S; bool sum = get_field(proc->state.mstatus, MSTATUS_SUM); @@ -404,7 +402,7 @@ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode, bool virt, bool mxr) reg_t idx = (addr >> (PGSHIFT + ptshift)) & ((1 << vm.idxbits) - 1); // check that physical address of PTE is legal - auto pte_paddr = s2xlate(addr, base + idx * vm.ptesize, LOAD, type, virt, false); + auto pte_paddr = s2xlate(addr, base + idx * vm.ptesize, LOAD, type, virt, false, 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); @@ -420,9 +418,9 @@ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode, bool virt, bool mxr) break; } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) { break; - } else if (type == FETCH ? !(pte & PTE_X) : - type == LOAD ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) : - !((pte & PTE_R) && (pte & PTE_W))) { + } else if (type == FETCH || hlvx ? !(pte & PTE_X) : + type == LOAD ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) : + !((pte & PTE_R) && (pte & PTE_W))) { break; } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) { break; @@ -451,7 +449,7 @@ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode, bool virt, bool mxr) | (vpn & ((reg_t(1) << napot_bits) - 1)) | (vpn & ((reg_t(1) << ptshift) - 1))) << PGSHIFT; reg_t phys = page_base | (addr & page_mask); - return s2xlate(addr, phys, type, type, virt, mxr) & ~page_mask; + return s2xlate(addr, phys, type, type, virt, mxr, hlvx) & ~page_mask; } } |