From 147ed1bc807360c4c90784f975c24693cdd291d4 Mon Sep 17 00:00:00 2001 From: Ryan Buchner Date: Tue, 12 Apr 2022 13:06:10 -0700 Subject: Skip storing in store_func if actually_store is false, add a fake store at start of AMO. This includes skipping store in store_slow_path. Is okay to skip the mmio_store part too, since the access_fault for mmio_failure will be caught on the actual store. The ordering for the mmio_access fault is irrelevant since it will occur after the TW faults, and load faults are converted to store faults. Will catch any faults from the access but won't perform a store. Since store permissions can only be granted if read permissions exist, any store faults will occur before or at the same time as a load fault. Thus this store permissions check is sufficient for properly catching the faults in an Amo access TW. --- riscv/mmu.cc | 2 ++ riscv/mmu.h | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 6c7af21..40dccf0 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -172,6 +172,7 @@ void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, uint32_ throw *matched_trigger; } + if (actually_store) { if (auto host_addr = sim->addr_to_mem(paddr)) { memcpy(host_addr, bytes, len); if (tracer.interested_in_range(paddr, paddr + PGSIZE, STORE)) @@ -181,6 +182,7 @@ void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, uint32_ } else if (!mmio_store(paddr, len, bytes)) { throw trap_store_access_fault((proc) ? proc->state.v : false, addr, 0, 0); } + } } tlb_entry_t mmu_t::refill_tlb(reg_t vaddr, reg_t paddr, char* host_addr, access_type type) diff --git a/riscv/mmu.h b/riscv/mmu.h index deacbc4..fc6f950 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -153,10 +153,13 @@ public: reg_t vpn = addr >> PGSHIFT; \ size_t size = sizeof(type##_t); \ if ((xlate_flags) == 0 && likely(tlb_store_tag[vpn % TLB_ENTRIES] == vpn)) { \ + if (actually_store) { \ if (proc) WRITE_MEM(addr, val, size); \ *(target_endian*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr) = to_target(val); \ + } \ } \ else if ((xlate_flags) == 0 && unlikely(tlb_store_tag[vpn % TLB_ENTRIES] == (vpn | TLB_CHECK_TRIGGERS))) { \ + if (actually_store) { \ if (!matched_trigger) { \ matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, val); \ if (matched_trigger) \ @@ -164,11 +167,12 @@ public: } \ if (proc) WRITE_MEM(addr, val, size); \ *(target_endian*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr) = to_target(val); \ + } \ } \ else { \ target_endian target_val = to_target(val); \ store_slow_path(addr, sizeof(type##_t), (const uint8_t*)&target_val, (xlate_flags), actually_store); \ - if (proc) WRITE_MEM(addr, val, size); \ + if (actually_store && proc) WRITE_MEM(addr, val, size); \ } \ } @@ -192,6 +196,7 @@ public: template \ type##_t amo_##type(reg_t addr, op f) { \ convert_load_traps_to_store_traps({ \ + store_##type(addr, 0, false); \ auto lhs = load_##type(addr, true); \ store_##type(addr, f(lhs)); \ return lhs; \ -- cgit v1.1