Browse Source

Merge pull request #976 from rbuchner-aril/amo-attr-fix

Fix for #873 AMO exception priorities
pull/977/head
Andrew Waterman 4 years ago
committed by GitHub
parent
commit
b7d258075b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      riscv/mmu.cc
  2. 29
      riscv/mmu.h

20
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); 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; throw *matched_trigger;
} }
if (auto host_addr = sim->addr_to_mem(paddr)) { if (actually_store) {
memcpy(host_addr, bytes, len); if (auto host_addr = sim->addr_to_mem(paddr)) {
if (tracer.interested_in_range(paddr, paddr + PGSIZE, STORE)) memcpy(host_addr, bytes, len);
tracer.trace(paddr, len, STORE); if (tracer.interested_in_range(paddr, paddr + PGSIZE, STORE))
else if (xlate_flags == 0) tracer.trace(paddr, len, STORE);
refill_tlb(addr, paddr, host_addr, STORE); else if (xlate_flags == 0)
} else if (!mmio_store(paddr, len, bytes)) { refill_tlb(addr, paddr, host_addr, STORE);
throw trap_store_access_fault((proc) ? proc->state.v : false, addr, 0, 0); } else if (!mmio_store(paddr, len, bytes)) {
throw trap_store_access_fault((proc) ? proc->state.v : false, addr, 0, 0);
}
} }
} }

29
riscv/mmu.h

@ -147,28 +147,32 @@ public:
// template for functions that store an aligned value to memory // template for functions that store an aligned value to memory
#define store_func(type, prefix, xlate_flags) \ #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))) \ if (unlikely(addr & (sizeof(type##_t)-1))) \
return misaligned_store(addr, val, sizeof(type##_t), xlate_flags); \ return misaligned_store(addr, val, sizeof(type##_t), xlate_flags); \
reg_t vpn = addr >> PGSHIFT; \ reg_t vpn = addr >> PGSHIFT; \
size_t size = sizeof(type##_t); \ size_t size = sizeof(type##_t); \
if ((xlate_flags) == 0 && likely(tlb_store_tag[vpn % TLB_ENTRIES] == vpn)) { \ if ((xlate_flags) == 0 && likely(tlb_store_tag[vpn % TLB_ENTRIES] == vpn)) { \
if (proc) WRITE_MEM(addr, val, size); \ if (actually_store) { \
*(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 if ((xlate_flags) == 0 && unlikely(tlb_store_tag[vpn % TLB_ENTRIES] == (vpn | TLB_CHECK_TRIGGERS))) { \ else if ((xlate_flags) == 0 && unlikely(tlb_store_tag[vpn % TLB_ENTRIES] == (vpn | TLB_CHECK_TRIGGERS))) { \
if (!matched_trigger) { \ if (actually_store) { \
matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, val); \ if (!matched_trigger) { \
if (matched_trigger) \ matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, val); \
throw *matched_trigger; \ 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 { \ else { \
target_endian<type##_t> target_val = to_target(val); \ target_endian<type##_t> target_val = to_target(val); \
store_slow_path(addr, sizeof(type##_t), (const uint8_t*)&target_val, (xlate_flags)); \ 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<typename op> \ template<typename op> \
type##_t amo_##type(reg_t addr, op f) { \ type##_t amo_##type(reg_t addr, op f) { \
convert_load_traps_to_store_traps({ \ convert_load_traps_to_store_traps({ \
store_##type(addr, 0, false); \
auto lhs = load_##type(addr, true); \ auto lhs = load_##type(addr, true); \
store_##type(addr, f(lhs)); \ store_##type(addr, f(lhs)); \
return lhs; \ return lhs; \
@ -438,7 +443,7 @@ private:
// handle uncommon cases: TLB misses, page faults, MMIO // handle uncommon cases: TLB misses, page faults, MMIO
tlb_entry_t fetch_slow_path(reg_t addr); 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 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_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_store(reg_t addr, size_t len, const uint8_t* bytes);
bool mmio_ok(reg_t addr, access_type type); bool mmio_ok(reg_t addr, access_type type);

Loading…
Cancel
Save