diff options
author | YenHaoChen <howard25336284@gmail.com> | 2022-09-30 12:05:40 +0800 |
---|---|---|
committer | YenHaoChen <howard25336284@gmail.com> | 2022-09-30 12:18:39 +0800 |
commit | d52858f3a80d3f87bfedffbff1fec34245a63082 (patch) | |
tree | 75f6e973bef46896f8eefd8fb0414ae9659f61bc | |
parent | 99cb603973b3f9575b411b80934035f3ee7fbcf3 (diff) | |
download | spike-d52858f3a80d3f87bfedffbff1fec34245a63082.zip spike-d52858f3a80d3f87bfedffbff1fec34245a63082.tar.gz spike-d52858f3a80d3f87bfedffbff1fec34245a63082.tar.bz2 |
Fix priority of mcontrol trigger store address/data before
The spec defines that the mcontrol store address/data has a higher
priority over page fault and address misalignment (Debug spec, Table
5.2). Thus, the trigger checking should be before the translation and
alignment checking.
The previous implementation checks the trigger after the translation and
alignment, resulting in incorrect priority. For instance, when page fault
and trigger occur on the same instruction, the previous implementation
will choose to raise the page fault, which contradicts the priority
requirement.
This commit moves the trigger checking before the misaligned checking and
translation. The trigger will fire on the instruction instead of the page
fault in the above case.
-rw-r--r-- | riscv/mmu.cc | 4 | ||||
-rw-r--r-- | riscv/mmu.h | 7 |
2 files changed, 9 insertions, 2 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 3048bde..ede5722 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -170,8 +170,6 @@ 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, bool actually_store) { - reg_t paddr = translate(addr, len, STORE, xlate_flags); - if (!matched_trigger) { reg_t data = reg_from_bytes(len, bytes); matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, true, data); @@ -179,6 +177,8 @@ void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, uint32_ throw *matched_trigger; } + reg_t paddr = translate(addr, len, STORE, xlate_flags); + if (actually_store) { if (auto host_addr = sim->addr_to_mem(paddr)) { memcpy(host_addr, bytes, len); diff --git a/riscv/mmu.h b/riscv/mmu.h index 3a06c1e..40a435f 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -169,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); \ } \ |