diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 8e32dfe7..23f132e0 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -38,12 +38,12 @@ void mmu_t::flush_tlb() flush_icache(); } -static void throw_access_exception(reg_t addr, access_type type) +static void throw_access_exception(bool virt, reg_t addr, access_type type) { switch (type) { - case FETCH: throw trap_instruction_access_fault(addr, 0, 0); - case LOAD: throw trap_load_access_fault(addr, 0, 0); - case STORE: throw trap_store_access_fault(addr, 0, 0); + case FETCH: throw trap_instruction_access_fault(virt, addr, 0, 0); + case LOAD: throw trap_load_access_fault(virt, addr, 0, 0); + case STORE: throw trap_store_access_fault(virt, addr, 0, 0); default: abort(); } } @@ -73,7 +73,7 @@ reg_t mmu_t::translate(reg_t addr, reg_t len, access_type type, uint32_t xlate_f reg_t paddr = walk(addr, type, mode, virt, mxr) | (addr & (PGSIZE-1)); if (!pmp_ok(paddr, len, type, mode)) - throw_access_exception(addr, type); + throw_access_exception(virt, addr, type); return paddr; } @@ -85,7 +85,7 @@ tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr) return refill_tlb(vaddr, paddr, host_addr, FETCH); } else { if (!mmio_load(paddr, sizeof fetch_temp, (uint8_t*)&fetch_temp)) - throw trap_instruction_access_fault(vaddr, 0, 0); + throw trap_instruction_access_fault(proc->state.v, vaddr, 0, 0); tlb_entry_t entry = {(char*)&fetch_temp - vaddr, paddr - vaddr}; return entry; } @@ -153,7 +153,7 @@ void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, uint32_t xlate else refill_tlb(addr, paddr, host_addr, LOAD); } else if (!mmio_load(paddr, len, bytes)) { - throw trap_load_access_fault(addr, 0, 0); + throw trap_load_access_fault(proc->state.v, addr, 0, 0); } if (!matched_trigger) { @@ -182,7 +182,7 @@ void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, uint32_ else refill_tlb(addr, paddr, host_addr, STORE); } else if (!mmio_store(paddr, len, bytes)) { - throw trap_store_access_fault(addr, 0, 0); + throw trap_store_access_fault(proc->state.v, addr, 0, 0); } } @@ -320,7 +320,7 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty 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(gva, trap_type); + throw_access_exception(virt, gva, trap_type); } reg_t pte = vm.ptesize == 4 ? from_target(*(target_endian*)ppte) : from_target(*(target_endian*)ppte); @@ -344,7 +344,7 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty // set accessed and possibly dirty bits. if ((pte & ad) != ad) { if (!pmp_ok(pte_paddr, vm.ptesize, STORE, PRV_S)) - throw_access_exception(gva, trap_type); + throw_access_exception(virt, gva, trap_type); *(target_endian*)ppte |= to_target((uint32_t)ad); } #else @@ -401,7 +401,7 @@ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode, bool virt, bool mxr) 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(addr, type); + throw_access_exception(virt, addr, type); reg_t pte = vm.ptesize == 4 ? from_target(*(target_endian*)ppte) : from_target(*(target_endian*)ppte); reg_t ppn = (pte & ~reg_t(PTE_N)) >> PTE_PPN_SHIFT; @@ -424,7 +424,7 @@ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode, bool virt, bool mxr) // set accessed and possibly dirty bits. if ((pte & ad) != ad) { if (!pmp_ok(pte_paddr, vm.ptesize, STORE, PRV_S)) - throw_access_exception(addr, type); + throw_access_exception(virt, addr, type); *(target_endian*)ppte |= to_target((uint32_t)ad); } #else @@ -448,9 +448,9 @@ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode, bool virt, bool mxr) } switch (type) { - case FETCH: throw trap_instruction_page_fault(addr, 0, 0); - case LOAD: throw trap_load_page_fault(addr, 0, 0); - case STORE: throw trap_store_page_fault(addr, 0, 0); + case FETCH: throw trap_instruction_page_fault(virt, addr, 0, 0); + case LOAD: throw trap_load_page_fault(virt, addr, 0, 0); + case STORE: throw trap_store_page_fault(virt, addr, 0, 0); default: abort(); } } diff --git a/riscv/mmu.h b/riscv/mmu.h index 4bba5b08..ada20fbd 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -200,10 +200,10 @@ public: throw trap_store_address_misaligned(t.get_tval(), t.get_tval2(), t.get_tinst()); \ } catch (trap_load_page_fault& t) { \ /* AMO faults should be reported as store faults */ \ - throw trap_store_page_fault(t.get_tval(), t.get_tval2(), t.get_tinst()); \ + throw trap_store_page_fault(t.has_gva(), t.get_tval(), t.get_tval2(), t.get_tinst()); \ } catch (trap_load_access_fault& t) { \ /* AMO faults should be reported as store faults */ \ - throw trap_store_access_fault(t.get_tval(), t.get_tval2(), t.get_tinst()); \ + throw trap_store_access_fault(t.has_gva(), t.get_tval(), t.get_tval2(), t.get_tinst()); \ } \ } @@ -253,7 +253,7 @@ public: if (auto host_addr = sim->addr_to_mem(paddr)) load_reservation_address = refill_tlb(vaddr, paddr, host_addr, LOAD).target_offset + vaddr; else - throw trap_load_access_fault(vaddr, 0, 0); // disallow LR to I/O space + throw trap_load_access_fault(proc->state.v, vaddr, 0, 0); // disallow LR to I/O space } inline bool check_load_reservation(reg_t vaddr, size_t size) @@ -265,7 +265,7 @@ public: if (auto host_addr = sim->addr_to_mem(paddr)) return load_reservation_address == refill_tlb(vaddr, paddr, host_addr, STORE).target_offset + vaddr; else - throw trap_store_access_fault(vaddr, 0, 0); // disallow SC to I/O space + throw trap_store_access_fault(proc->state.v, vaddr, 0, 0); // disallow SC to I/O space } static const reg_t ICACHE_ENTRIES = 1024; diff --git a/riscv/trap.h b/riscv/trap.h index 4431d8a9..46114ec6 100644 --- a/riscv/trap.h +++ b/riscv/trap.h @@ -67,17 +67,29 @@ class mem_trap_t : public trap_t }; #define DECLARE_MEM_TRAP(n, x) class trap_##x : public mem_trap_t { \ + public: \ + trap_##x(bool gva, reg_t tval, reg_t tval2, reg_t tinst) : mem_trap_t(n, gva, tval, tval2, tinst) {} \ + const char* name() { return "trap_"#x; } \ +}; + +#define DECLARE_MEM_NOGVA_TRAP(n, x) class trap_##x : public mem_trap_t { \ + public: \ + trap_##x(reg_t tval, reg_t tval2, reg_t tinst) : mem_trap_t(n, false, tval, tval2, tinst) {} \ + const char* name() { return "trap_"#x; } \ +}; + +#define DECLARE_MEM_GVA_TRAP(n, x) class trap_##x : public mem_trap_t { \ public: \ trap_##x(reg_t tval, reg_t tval2, reg_t tinst) : mem_trap_t(n, true, tval, tval2, tinst) {} \ const char* name() { return "trap_"#x; } \ }; -DECLARE_MEM_TRAP(CAUSE_MISALIGNED_FETCH, instruction_address_misaligned) +DECLARE_MEM_NOGVA_TRAP(CAUSE_MISALIGNED_FETCH, instruction_address_misaligned) DECLARE_MEM_TRAP(CAUSE_FETCH_ACCESS, instruction_access_fault) DECLARE_INST_TRAP(CAUSE_ILLEGAL_INSTRUCTION, illegal_instruction) DECLARE_INST_TRAP(CAUSE_BREAKPOINT, breakpoint) -DECLARE_MEM_TRAP(CAUSE_MISALIGNED_LOAD, load_address_misaligned) -DECLARE_MEM_TRAP(CAUSE_MISALIGNED_STORE, store_address_misaligned) +DECLARE_MEM_NOGVA_TRAP(CAUSE_MISALIGNED_LOAD, load_address_misaligned) +DECLARE_MEM_NOGVA_TRAP(CAUSE_MISALIGNED_STORE, store_address_misaligned) DECLARE_MEM_TRAP(CAUSE_LOAD_ACCESS, load_access_fault) DECLARE_MEM_TRAP(CAUSE_STORE_ACCESS, store_access_fault) DECLARE_TRAP(CAUSE_USER_ECALL, user_ecall) @@ -87,9 +99,9 @@ DECLARE_TRAP(CAUSE_MACHINE_ECALL, machine_ecall) DECLARE_MEM_TRAP(CAUSE_FETCH_PAGE_FAULT, instruction_page_fault) DECLARE_MEM_TRAP(CAUSE_LOAD_PAGE_FAULT, load_page_fault) DECLARE_MEM_TRAP(CAUSE_STORE_PAGE_FAULT, store_page_fault) -DECLARE_MEM_TRAP(CAUSE_FETCH_GUEST_PAGE_FAULT, instruction_guest_page_fault) -DECLARE_MEM_TRAP(CAUSE_LOAD_GUEST_PAGE_FAULT, load_guest_page_fault) +DECLARE_MEM_GVA_TRAP(CAUSE_FETCH_GUEST_PAGE_FAULT, instruction_guest_page_fault) +DECLARE_MEM_GVA_TRAP(CAUSE_LOAD_GUEST_PAGE_FAULT, load_guest_page_fault) DECLARE_INST_TRAP(CAUSE_VIRTUAL_INSTRUCTION, virtual_instruction) -DECLARE_MEM_TRAP(CAUSE_STORE_GUEST_PAGE_FAULT, store_guest_page_fault) +DECLARE_MEM_GVA_TRAP(CAUSE_STORE_GUEST_PAGE_FAULT, store_guest_page_fault) #endif