diff options
Diffstat (limited to 'riscv/mmu.cc')
-rw-r--r-- | riscv/mmu.cc | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 1473e89..165be53 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -387,7 +387,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 hlvx) +reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_type, bool virt, bool hlvx, bool is_for_vs_pt_addr) { if (!virt) return gpa; @@ -400,6 +400,14 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty reg_t maxgpa = (1ULL << maxgpabits) - 1; bool mxr = proc->state.sstatus->readvirt(false) & MSTATUS_MXR; + // tinst is set to 0x3000/0x3020 - for RV64 read/write respectively for + // VS-stage address translation (for spike HSXLEN == VSXLEN always) else + // tinst is set to 0x2000/0x2020 - for RV32 read/write respectively for + // VS-stage address translation else set to 0 + int tinst = 0; + tinst |= (is_for_vs_pt_addr == true) ? 0x2000 : 0; + tinst |= ((proc->get_const_xlen() == 64) && (is_for_vs_pt_addr == true)) ? 0x1000 : 0; + tinst |= ((type == STORE) && (is_for_vs_pt_addr == true)) ? 0x0020 : 0; reg_t base = vm.ptbase; if ((gpa & ~maxgpa) == 0) { @@ -466,9 +474,9 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty } switch (trap_type) { - case FETCH: throw trap_instruction_guest_page_fault(gva, gpa >> 2, 0); - case LOAD: throw trap_load_guest_page_fault(gva, gpa >> 2, 0); - case STORE: throw trap_store_guest_page_fault(gva, gpa >> 2, 0); + case FETCH: throw trap_instruction_guest_page_fault(gva, gpa >> 2, tinst); + case LOAD: throw trap_load_guest_page_fault(gva, gpa >> 2, tinst); + case STORE: throw trap_store_guest_page_fault(gva, gpa >> 2, tinst); default: abort(); } } @@ -484,7 +492,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info) reg_t satp = proc->get_state()->satp->readvirt(virt); vm_info vm = decode_vm_info(proc->get_const_xlen(), false, mode, satp); if (vm.levels == 0) - return s2xlate(addr, addr & ((reg_t(2) << (proc->xlen-1))-1), type, type, virt, hlvx) & ~page_mask; // zero-extend from xlen + return s2xlate(addr, addr & ((reg_t(2) << (proc->xlen-1))-1), type, type, virt, hlvx, false) & ~page_mask; // zero-extend from xlen bool s_mode = mode == PRV_S; bool sum = proc->state.sstatus->readvirt(virt) & MSTATUS_SUM; @@ -503,7 +511,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info) 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, true); 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); @@ -538,7 +546,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info) if (hade) { // Check for write permission to the first-stage PT in second-stage // PTE and set the D bit in the second-stage PTE if needed - s2xlate(addr, base + idx * vm.ptesize, STORE, type, virt, false); + s2xlate(addr, base + idx * vm.ptesize, STORE, type, virt, false, true); // set accessed and possibly dirty bits. pte_store(pte_paddr, pte | ad, addr, virt, type, vm.ptesize); } else { @@ -558,7 +566,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info) | (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, hlvx) & ~page_mask; + return s2xlate(addr, phys, type, type, virt, hlvx, false) & ~page_mask; } } |