|
|
|
@ -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; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|