diff options
Diffstat (limited to 'riscv/mmu.h')
-rw-r--r-- | riscv/mmu.h | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/riscv/mmu.h b/riscv/mmu.h index 4d52618..8b9ff9b 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -101,6 +101,11 @@ public: #define load_func(type, prefix, xlate_flags) \ type##_t ALWAYS_INLINE prefix##_##type(reg_t addr, bool require_alignment = false) { \ if (unlikely(addr & (sizeof(type##_t)-1))) { \ + if (!matched_trigger) { \ + matched_trigger = trigger_exception(triggers::OPERATION_LOAD, addr, false); \ + if (matched_trigger) \ + throw *matched_trigger; \ + } \ if (require_alignment) load_reserved_address_misaligned(addr); \ else return misaligned_load(addr, sizeof(type##_t), xlate_flags); \ } \ @@ -113,7 +118,7 @@ public: if ((xlate_flags) == 0 && unlikely(tlb_load_tag[vpn % TLB_ENTRIES] == (vpn | TLB_CHECK_TRIGGERS))) { \ type##_t data = from_target(*(target_endian<type##_t>*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr)); \ if (!matched_trigger) { \ - matched_trigger = trigger_exception(triggers::OPERATION_LOAD, addr, data); \ + matched_trigger = trigger_exception(triggers::OPERATION_LOAD, addr, true, data); \ if (matched_trigger) \ throw *matched_trigger; \ } \ @@ -164,6 +169,13 @@ public: #define store_func(type, prefix, xlate_flags) \ void ALWAYS_INLINE prefix##_##type(reg_t addr, type##_t val, bool actually_store=true, bool require_alignment=false) { \ if (unlikely(addr & (sizeof(type##_t)-1))) { \ + if (actually_store) { \ + if (!matched_trigger) { \ + matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, true, val); \ + if (matched_trigger) \ + throw *matched_trigger; \ + } \ + } \ if (require_alignment) store_conditional_address_misaligned(addr); \ else return misaligned_store(addr, val, sizeof(type##_t), xlate_flags, actually_store); \ } \ @@ -178,7 +190,7 @@ public: 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); \ + matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, true, val); \ if (matched_trigger) \ throw *matched_trigger; \ } \ @@ -471,6 +483,11 @@ private: reg_t vpn = addr >> PGSHIFT; if (likely(tlb_insn_tag[vpn % TLB_ENTRIES] == vpn)) return tlb_data[vpn % TLB_ENTRIES]; + triggers::action_t action; + auto match = proc->TM.memory_access_match(&action, triggers::OPERATION_EXECUTE, addr, false); + if (match != triggers::MATCH_NONE) { + throw triggers::matched_t(triggers::OPERATION_EXECUTE, addr, 0, action); + } tlb_entry_t result; if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] != (vpn | TLB_CHECK_TRIGGERS))) { result = fetch_slow_path(addr); @@ -478,8 +495,7 @@ private: result = tlb_data[vpn % TLB_ENTRIES]; } target_endian<uint16_t>* ptr = (target_endian<uint16_t>*)(result.host_offset + addr); - triggers::action_t action; - auto match = proc->TM.memory_access_match(&action, triggers::OPERATION_EXECUTE, addr, from_target(*ptr)); + match = proc->TM.memory_access_match(&action, triggers::OPERATION_EXECUTE, addr, true, from_target(*ptr)); if (match != triggers::MATCH_NONE) { throw triggers::matched_t(triggers::OPERATION_EXECUTE, addr, from_target(*ptr), action); } @@ -491,13 +507,13 @@ private: } inline triggers::matched_t *trigger_exception(triggers::operation_t operation, - reg_t address, reg_t data) + reg_t address, bool has_data, reg_t data=0) { if (!proc) { return NULL; } triggers::action_t action; - auto match = proc->TM.memory_access_match(&action, operation, address, data); + auto match = proc->TM.memory_access_match(&action, operation, address, has_data, data); if (match == triggers::MATCH_NONE) return NULL; if (match == triggers::MATCH_FIRE_BEFORE) { |