aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@casualhacker.net>2024-09-05 13:43:25 -0700
committerTim Newsome <tim@casualhacker.net>2024-09-09 13:04:06 -0700
commit0703b44b77efba863d73e719f2482123dc1c236f (patch)
tree5223de03ae280a97f02037ec963349e236b24b20
parent451a7dcdd72c2278e3dd3dc311273c40946e366a (diff)
downloadriscv-isa-sim-0703b44b77efba863d73e719f2482123dc1c236f.zip
riscv-isa-sim-0703b44b77efba863d73e719f2482123dc1c236f.tar.gz
riscv-isa-sim-0703b44b77efba863d73e719f2482123dc1c236f.tar.bz2
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.
-rw-r--r--riscv/csr_init.cc5
-rw-r--r--riscv/triggers.cc39
2 files changed, 29 insertions, 15 deletions
diff --git a/riscv/csr_init.cc b/riscv/csr_init.cc
index d72c925..2c2760f 100644
--- a/riscv/csr_init.cc
+++ b/riscv/csr_init.cc
@@ -205,13 +205,14 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
add_csr(CSR_TDATA2, tdata2 = std::make_shared<tdata2_csr_t>(proc, CSR_TDATA2));
add_csr(CSR_TDATA3, std::make_shared<tdata3_csr_t>(proc, CSR_TDATA3));
add_csr(CSR_TINFO, std::make_shared<tinfo_csr_t>(proc, CSR_TINFO));
- add_csr(CSR_TCONTROL, tcontrol = std::make_shared<masked_csr_t>(proc, CSR_TCONTROL, CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE, 0));
+ if (!proc->extension_enabled_const('S')) {
+ add_csr(CSR_TCONTROL, tcontrol = std::make_shared<masked_csr_t>(proc, CSR_TCONTROL, CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE, 0));
+ }
} else {
add_csr(CSR_TDATA1, std::make_shared<const_csr_t>(proc, CSR_TDATA1, 0));
add_csr(CSR_TDATA2, tdata2 = std::make_shared<const_csr_t>(proc, CSR_TDATA2, 0));
add_csr(CSR_TDATA3, std::make_shared<const_csr_t>(proc, CSR_TDATA3, 0));
add_csr(CSR_TINFO, std::make_shared<const_csr_t>(proc, CSR_TINFO, 0));
- add_csr(CSR_TCONTROL, tcontrol = std::make_shared<const_csr_t>(proc, CSR_TCONTROL, 0));
}
unsigned scontext_length = (xlen == 32 ? 16 : 32); // debug spec suggests 16-bit for RV32 and 32-bit for RV64
add_supervisor_csr(CSR_SCONTEXT, scontext = std::make_shared<masked_csr_t>(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0));
diff --git a/riscv/triggers.cc b/riscv/triggers.cc
index a0a84c0..e130a87 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;