aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riscv/mmu.cc20
-rw-r--r--riscv/mmu.h29
2 files changed, 28 insertions, 21 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index fd8a320..1ef81cf 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -161,7 +161,7 @@ void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, uint32_t xlate
}
}
-void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, uint32_t xlate_flags)
+void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, uint32_t xlate_flags, bool actually_store)
{
reg_t paddr = translate(addr, len, STORE, xlate_flags);
@@ -172,14 +172,16 @@ void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, uint32_
throw *matched_trigger;
}
- if (auto host_addr = sim->addr_to_mem(paddr)) {
- memcpy(host_addr, bytes, len);
- if (tracer.interested_in_range(paddr, paddr + PGSIZE, STORE))
- tracer.trace(paddr, len, STORE);
- else if (xlate_flags == 0)
- refill_tlb(addr, paddr, host_addr, STORE);
- } else if (!mmio_store(paddr, len, bytes)) {
- throw trap_store_access_fault((proc) ? proc->state.v : false, addr, 0, 0);
+ 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))
+ tracer.trace(paddr, len, STORE);
+ else if (xlate_flags == 0)
+ refill_tlb(addr, paddr, host_addr, STORE);
+ } else if (!mmio_store(paddr, len, bytes)) {
+ throw trap_store_access_fault((proc) ? proc->state.v : false, addr, 0, 0);
+ }
}
}
diff --git a/riscv/mmu.h b/riscv/mmu.h
index 3782ffa..dcf338f 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -147,28 +147,32 @@ public:
// template for functions that store an aligned value to memory
#define store_func(type, prefix, xlate_flags) \
- void prefix##_##type(reg_t addr, type##_t val) { \
+ void prefix##_##type(reg_t addr, type##_t val, bool actually_store=true) { \
if (unlikely(addr & (sizeof(type##_t)-1))) \
return misaligned_store(addr, val, sizeof(type##_t), xlate_flags); \
reg_t vpn = addr >> PGSHIFT; \
size_t size = sizeof(type##_t); \
if ((xlate_flags) == 0 && likely(tlb_store_tag[vpn % TLB_ENTRIES] == vpn)) { \
- if (proc) WRITE_MEM(addr, val, size); \
- *(target_endian<type##_t>*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr) = to_target(val); \
+ if (actually_store) { \
+ if (proc) WRITE_MEM(addr, val, size); \
+ *(target_endian<type##_t>*)(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 (!matched_trigger) { \
- matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, val); \
- if (matched_trigger) \
- throw *matched_trigger; \
+ if (actually_store) { \
+ if (!matched_trigger) { \
+ matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, val); \
+ if (matched_trigger) \
+ throw *matched_trigger; \
+ } \
+ if (proc) WRITE_MEM(addr, val, size); \
+ *(target_endian<type##_t>*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr) = to_target(val); \
} \
- if (proc) WRITE_MEM(addr, val, size); \
- *(target_endian<type##_t>*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr) = to_target(val); \
} \
else { \
target_endian<type##_t> target_val = to_target(val); \
- store_slow_path(addr, sizeof(type##_t), (const uint8_t*)&target_val, (xlate_flags)); \
- if (proc) WRITE_MEM(addr, val, size); \
+ store_slow_path(addr, sizeof(type##_t), (const uint8_t*)&target_val, (xlate_flags), actually_store); \
+ if (actually_store && proc) WRITE_MEM(addr, val, size); \
} \
}
@@ -192,6 +196,7 @@ public:
template<typename op> \
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; \
@@ -438,7 +443,7 @@ private:
// handle uncommon cases: TLB misses, page faults, MMIO
tlb_entry_t fetch_slow_path(reg_t addr);
void load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, uint32_t xlate_flags);
- void store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, uint32_t xlate_flags);
+ void store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, uint32_t xlate_flags, bool actually_store);
bool mmio_load(reg_t addr, size_t len, uint8_t* bytes);
bool mmio_store(reg_t addr, size_t len, const uint8_t* bytes);
bool mmio_ok(reg_t addr, access_type type);