aboutsummaryrefslogtreecommitdiff
path: root/riscv/mmu.h
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2022-10-05 17:17:40 -0700
committerGitHub <noreply@github.com>2022-10-05 17:17:40 -0700
commitcb7e6b840be13ebc46fdcdb23df6db61ff306fde (patch)
tree549393ded86f05531e63f2bc00caf4f5511f504d /riscv/mmu.h
parent9b074198357b77189df989f0e274b23353f7f528 (diff)
parentab104011ba66fb3c88ce8405236908dc8700c679 (diff)
downloadspike-cb7e6b840be13ebc46fdcdb23df6db61ff306fde.zip
spike-cb7e6b840be13ebc46fdcdb23df6db61ff306fde.tar.gz
spike-cb7e6b840be13ebc46fdcdb23df6db61ff306fde.tar.bz2
Merge pull request #1105 from YenHaoChen/pr-trigger-priority
Fix trigger priority
Diffstat (limited to 'riscv/mmu.h')
-rw-r--r--riscv/mmu.h28
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) {