From 0ac8c77d40480a91c35c9f70b2a7ea5bd6339344 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 5 Sep 2024 13:43:25 -0700 Subject: [PATCH] Only implement one solution for native triggers. When S-mode is present, use option 1 (disable triggers in M-mode unless MIE is set) from the Debug Spec. When S-mode is not present, use option 2 (implement mte and mpte bits in tcontrol). See discussion in #1777. --- riscv/csr_init.cc | 4 +++- riscv/triggers.cc | 39 ++++++++++++++++++++++++++------------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/riscv/csr_init.cc b/riscv/csr_init.cc index 297771b76..e124130fb 100644 --- a/riscv/csr_init.cc +++ b/riscv/csr_init.cc @@ -212,7 +212,9 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) add_csr(CSR_TDATA2, tdata2 = std::make_shared(proc, CSR_TDATA2)); add_csr(CSR_TDATA3, std::make_shared(proc, CSR_TDATA3)); add_csr(CSR_TINFO, std::make_shared(proc, CSR_TINFO)); - add_csr(CSR_TCONTROL, tcontrol = std::make_shared(proc, CSR_TCONTROL, CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE, 0)); + if (!proc->extension_enabled_const('S')) { + add_csr(CSR_TCONTROL, tcontrol = std::make_shared(proc, CSR_TCONTROL, CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE, 0)); + } } else { add_csr(CSR_TDATA1, std::make_shared(proc, CSR_TDATA1, 0)); add_csr(CSR_TDATA2, tdata2 = std::make_shared(proc, CSR_TDATA2, 0)); diff --git a/riscv/triggers.cc b/riscv/triggers.cc index b3b8699c4..9ae430603 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -74,19 +74,32 @@ bool trigger_t::common_match(processor_t * const proc, bool use_prev_prv) const return false; if (get_action() == ACTION_DEBUG_EXCEPTION) { - const bool mstatus_mie = state->mstatus->read() & MSTATUS_MIE; - if (prv == PRV_M && !mstatus_mie) - return false; - - const bool sstatus_sie = state->sstatus->read() & MSTATUS_SIE; - const bool medeleg_breakpoint = (state->medeleg->read() >> CAUSE_BREAKPOINT) & 1; - if (prv == PRV_S && !v && medeleg_breakpoint && !sstatus_sie) - return false; - - const bool vsstatus_sie = state->vsstatus->read() & MSTATUS_SIE; - const bool hedeleg_breakpoint = (state->hedeleg->read() >> CAUSE_BREAKPOINT) & 1; - if (prv == PRV_S && v && medeleg_breakpoint && hedeleg_breakpoint && !vsstatus_sie) - return false; + if (proc->extension_enabled('S')) { + // The hardware prevents triggers with action=0 from matching or firing + // while in M-mode and while MIE in mstatus is 0. If medeleg [3]=1 then it + // prevents triggers with action=0 from matching or firing while in S-mode + // and while SIE in sstatus is 0. If medeleg [3]=1 and hedeleg [3]=1 then + // it prevents triggers with action=0 from matching or firing while in + // VS-mode and while SIE in vstatus is 0. + + const bool mstatus_mie = state->mstatus->read() & MSTATUS_MIE; + if (prv == PRV_M && !mstatus_mie) + return false; + + const bool sstatus_sie = state->sstatus->read() & MSTATUS_SIE; + const bool medeleg_breakpoint = (state->medeleg->read() >> CAUSE_BREAKPOINT) & 1; + if (prv == PRV_S && !v && medeleg_breakpoint && !sstatus_sie) + return false; + + const bool vsstatus_sie = state->vsstatus->read() & MSTATUS_SIE; + const bool hedeleg_breakpoint = (state->hedeleg->read() >> CAUSE_BREAKPOINT) & 1; + if (prv == PRV_S && v && medeleg_breakpoint && hedeleg_breakpoint && !vsstatus_sie) + return false; + } else { + // mte and mpte in tcontrol is implemented. medeleg [3] is hard-wired to 0. + if (prv == PRV_M && !(tcontrol_value(state) & CSR_TCONTROL_MTE)) + return false; + } } return true;