From 0578364d13a0094ca62c5b36ffd2b750883fcbbb Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Thu, 14 Sep 2023 08:50:19 +0800 Subject: [PATCH 1/4] triggers: fix data mcontrol/mcontrol6 on fetching instruction data The fetching instruction data are in refill_icache() instead of fetch_slow_path(). This commit moves the mcontrol/mcontrol6 checking from fetch_slow_path() to refill_icache() for the correct data value. For example, consider an instruction 0xe9830313 (addi t1, t1, -360). The previous implementation fires mcontrol data triggers with tdata2=0xe983 and tdata2=0x0313 but does not fire one with tdata2=0xe9830313, which is incorrect. This commit fixes the issue. --- riscv/mmu.cc | 2 -- riscv/mmu.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 285ef6d364..fcaa6eed82 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -88,8 +88,6 @@ tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr) result = tlb_data[vpn % TLB_ENTRIES]; } - check_triggers(triggers::OPERATION_EXECUTE, vaddr, access_info.effective_virt, from_le(*(const uint16_t*)(result.host_offset + vaddr))); - return result; } diff --git a/riscv/mmu.h b/riscv/mmu.h index ce505275df..de929d5526 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -290,6 +290,7 @@ class mmu_t if (matched_trigger) throw *matched_trigger; + auto access_info = generate_access_info(addr, FETCH, {false, false, false}); auto tlb_entry = translate_insn_addr(addr); insn_bits_t insn = from_le(*(uint16_t*)(tlb_entry.host_offset + addr)); int length = insn_length(insn); @@ -307,6 +308,7 @@ class mmu_t insn |= (insn_bits_t)from_le(*(const uint16_t*)translate_insn_addr_to_host(addr + 4)) << 32; insn |= (insn_bits_t)from_le(*(const uint16_t*)translate_insn_addr_to_host(addr + 6)) << 48; } + check_triggers(triggers::OPERATION_EXECUTE, addr, access_info.effective_virt, insn); insn_fetch_t fetch = {proc->decode_insn(insn), insn}; entry->tag = addr; From 146e41e27fa50434d8c08d9dac2268a0349599e2 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Thu, 14 Sep 2023 08:45:15 +0800 Subject: [PATCH 2/4] triggers: fix address mcontrol/mcontrol6 on fetching PC The fetching PC is in refill_icache() instead of fetch_slow_path(). This commit moves the address mcontrol/mcontrol6 checking from fetch_slow_path() to refill_icache() for the correct fetching PC. For example, consider a 4-byte instruction at PC=0x4000. The Debug specification recommends to compare PC={0x4000,0x4001,0x4002,0x4003}; otherwise, the Debug specification requires to compare PC=0x4000. The previous implementation compares PC={0x4000,0x4002}, which is undesired. --- riscv/mmu.cc | 1 - riscv/mmu.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index fcaa6eed82..dbe0fc1adc 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -71,7 +71,6 @@ reg_t mmu_t::translate(mem_access_info_t access_info, reg_t len) tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr) { auto access_info = generate_access_info(vaddr, FETCH, {false, false, false}); - check_triggers(triggers::OPERATION_EXECUTE, vaddr, access_info.effective_virt); tlb_entry_t result; reg_t vpn = vaddr >> PGSHIFT; diff --git a/riscv/mmu.h b/riscv/mmu.h index de929d5526..ecfe9bc0f1 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -291,6 +291,7 @@ class mmu_t throw *matched_trigger; auto access_info = generate_access_info(addr, FETCH, {false, false, false}); + check_triggers(triggers::OPERATION_EXECUTE, addr, access_info.effective_virt); auto tlb_entry = translate_insn_addr(addr); insn_bits_t insn = from_le(*(uint16_t*)(tlb_entry.host_offset + addr)); int length = insn_length(insn); From 0d8067b563b2afdbc082530df8d738c29c406585 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Wed, 13 Sep 2023 10:09:23 +0800 Subject: [PATCH 3/4] triggers: refactor: move access_info to where it is used in mmu_t::translate() --- riscv/mmu.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index dbe0fc1adc..6928e9b276 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -70,11 +70,10 @@ reg_t mmu_t::translate(mem_access_info_t access_info, reg_t len) tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr) { - auto access_info = generate_access_info(vaddr, FETCH, {false, false, false}); - tlb_entry_t result; reg_t vpn = vaddr >> PGSHIFT; if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] != (vpn | TLB_CHECK_TRIGGERS))) { + auto access_info = generate_access_info(vaddr, FETCH, {false, false, false}); reg_t paddr = translate(access_info, sizeof(fetch_temp)); if (auto host_addr = sim->addr_to_mem(paddr)) { result = refill_tlb(vaddr, paddr, host_addr, FETCH); From 661c6a2a0c3a699d486d353652c5adeb7dba4843 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Wed, 13 Sep 2023 10:37:10 +0800 Subject: [PATCH 4/4] triggers: performance improvement on execute mcontrol/mcontrol6 --- riscv/mmu.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/riscv/mmu.h b/riscv/mmu.h index ecfe9bc0f1..e22c579a15 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -290,8 +290,10 @@ class mmu_t if (matched_trigger) throw *matched_trigger; + reg_t vpn = addr >> PGSHIFT; auto access_info = generate_access_info(addr, FETCH, {false, false, false}); - check_triggers(triggers::OPERATION_EXECUTE, addr, access_info.effective_virt); + if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] != vpn)) + check_triggers(triggers::OPERATION_EXECUTE, addr, access_info.effective_virt); auto tlb_entry = translate_insn_addr(addr); insn_bits_t insn = from_le(*(uint16_t*)(tlb_entry.host_offset + addr)); int length = insn_length(insn); @@ -309,7 +311,8 @@ class mmu_t insn |= (insn_bits_t)from_le(*(const uint16_t*)translate_insn_addr_to_host(addr + 4)) << 32; insn |= (insn_bits_t)from_le(*(const uint16_t*)translate_insn_addr_to_host(addr + 6)) << 48; } - check_triggers(triggers::OPERATION_EXECUTE, addr, access_info.effective_virt, insn); + if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] != vpn)) + check_triggers(triggers::OPERATION_EXECUTE, addr, access_info.effective_virt, insn); insn_fetch_t fetch = {proc->decode_insn(insn), insn}; entry->tag = addr;