|
|
|
@ -20,6 +20,21 @@ |
|
|
|
const reg_t PGSIZE = 1 << PGSHIFT; |
|
|
|
#define MAX_PADDR_BITS 64 |
|
|
|
|
|
|
|
// observability hooks for load, store and fetch
|
|
|
|
// intentionally empty not to cause runtime overhead
|
|
|
|
// can be redefined if needed
|
|
|
|
#ifndef MMU_OBSERVE_FETCH |
|
|
|
#define MMU_OBSERVE_FETCH(addr, insn, length) |
|
|
|
#endif |
|
|
|
|
|
|
|
#ifndef MMU_OBSERVE_LOAD |
|
|
|
#define MMU_OBSERVE_LOAD(addr, data, length) |
|
|
|
#endif |
|
|
|
|
|
|
|
#ifndef MMU_OBSERVE_STORE |
|
|
|
#define MMU_OBSERVE_STORE(addr, data, length) |
|
|
|
#endif |
|
|
|
|
|
|
|
struct insn_fetch_t |
|
|
|
{ |
|
|
|
insn_func_t func; |
|
|
|
@ -89,6 +104,8 @@ public: |
|
|
|
load_slow_path(addr, sizeof(T), (uint8_t*)&res, xlate_flags); |
|
|
|
} |
|
|
|
|
|
|
|
MMU_OBSERVE_LOAD(addr,from_target(res),sizeof(T)); |
|
|
|
|
|
|
|
return from_target(res); |
|
|
|
} |
|
|
|
|
|
|
|
@ -117,6 +134,7 @@ public: |
|
|
|
|
|
|
|
template<typename T> |
|
|
|
void ALWAYS_INLINE store(reg_t addr, T val, xlate_flags_t xlate_flags = {}) { |
|
|
|
MMU_OBSERVE_STORE(addr, val, sizeof(T)); |
|
|
|
bool aligned = (addr & (sizeof(T) - 1)) == 0; |
|
|
|
auto [tlb_hit, host_addr, _] = access_tlb(tlb_store, addr); |
|
|
|
|
|
|
|
@ -323,15 +341,17 @@ public: |
|
|
|
tracer.trace(paddr, paddr + length, FETCH); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
MMU_OBSERVE_FETCH(addr, insn, length); |
|
|
|
return entry; |
|
|
|
} |
|
|
|
|
|
|
|
inline icache_entry_t* access_icache(reg_t addr) |
|
|
|
{ |
|
|
|
icache_entry_t* entry = &icache[icache_index(addr)]; |
|
|
|
if (likely(entry->tag == addr)) |
|
|
|
if (likely(entry->tag == addr)){ |
|
|
|
MMU_OBSERVE_FETCH(addr, entry->data.insn, insn_length(entry->data.insn.bits())); |
|
|
|
return entry; |
|
|
|
} |
|
|
|
return refill_icache(addr, entry); |
|
|
|
} |
|
|
|
|
|
|
|
|