aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riscv/debug_module.cc45
-rw-r--r--riscv/debug_module.h6
2 files changed, 43 insertions, 8 deletions
diff --git a/riscv/debug_module.cc b/riscv/debug_module.cc
index f7163ef..4a7a802 100644
--- a/riscv/debug_module.cc
+++ b/riscv/debug_module.cc
@@ -73,6 +73,9 @@ debug_module_t::debug_module_t(simif_t *sim, const debug_module_config_t &config
jal(ZERO, debug_abstract_start - DEBUG_ROM_WHERETO));
memset(debug_abstract, 0, sizeof(debug_abstract));
+ for (unsigned i = 0; i < sizeof(hart_available_state) / sizeof(*hart_available_state); i++) {
+ hart_available_state[i] = true;
+ }
reset();
}
@@ -202,7 +205,8 @@ bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
if (hart_state[id].haltgroup) {
for (const auto& [hart_id, hart] : sim->get_harts()) {
if (!hart_state[hart_id].halted &&
- hart_state[hart_id].haltgroup == hart_state[id].haltgroup) {
+ hart_state[hart_id].haltgroup == hart_state[id].haltgroup &&
+ hart_available(hart_id)) {
hart->halt_request = hart->HR_GROUP;
// TODO: What if the debugger comes and writes dmcontrol before the
// halt occurs?
@@ -337,6 +341,13 @@ void debug_module_t::sb_write()
}
}
+bool debug_module_t::hart_available(unsigned hart_id) const
+{
+ if (hart_id < sizeof(hart_available_state) / sizeof(*hart_available_state))
+ return hart_available_state[hart_id];
+ return true;
+}
+
bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
{
uint32_t result = 0;
@@ -391,6 +402,8 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
dmstatus.allnonexistant = true;
dmstatus.allresumeack = true;
dmstatus.anyresumeack = false;
+ dmstatus.allunavail = true;
+ dmstatus.anyunavail = false;
for (const auto& [hart_id, hart] : sim->get_harts()) {
if (hart_selected(hart_id)) {
dmstatus.allnonexistant = false;
@@ -399,12 +412,19 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
} else {
dmstatus.allresumeack = false;
}
+ auto hart = sim->get_harts().at(hart_id);
if (hart_state[hart_id].halted) {
dmstatus.allrunning = false;
dmstatus.anyhalted = true;
+ dmstatus.allunavail = false;
+ } else if (!hart_available(hart_id)) {
+ dmstatus.allrunning = false;
+ dmstatus.allhalted = false;
+ dmstatus.anyunavail = true;
} else {
dmstatus.allhalted = false;
dmstatus.anyrunning = true;
+ dmstatus.allunavail = false;
}
}
}
@@ -414,9 +434,6 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
// non-existant hartsel.
dmstatus.anynonexistant = dmcontrol.hartsel >= sim->get_cfg().nprocs();
- dmstatus.allunavail = false;
- dmstatus.anyunavail = false;
-
result = set_field(result, DM_DMSTATUS_IMPEBREAK,
dmstatus.impebreak);
result = set_field(result, DM_DMSTATUS_ALLHAVERESET, selected_hart_state().havereset);
@@ -522,6 +539,11 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
case DM_DMCS2:
result = set_field(result, DM_DMCS2_GROUP, selected_hart_state().haltgroup);
break;
+ case DM_CUSTOM:
+ for (unsigned i = 0; i < sizeof(hart_available_state) / sizeof(*hart_available_state); i++) {
+ result |= hart_available_state[i] << i;
+ }
+ break;
default:
result = 0;
D(fprintf(stderr, "Unexpected. Returning Error."));
@@ -790,16 +812,18 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
if (get_field(value, DM_DMCONTROL_ACKHAVERESET)) {
hart_state[hart_id].havereset = false;
}
- hart->halt_request = dmcontrol.haltreq ? hart->HR_REGULAR : hart->HR_NONE;
- if (dmcontrol.haltreq) {
+ if (dmcontrol.haltreq && hart_available(hart_id)) {
+ hart->halt_request = hart->HR_REGULAR;
D(fprintf(stderr, "halt hart %d\n", hart_id));
+ } else {
+ hart->halt_request = hart->HR_NONE;
}
- if (dmcontrol.resumereq) {
+ if (dmcontrol.resumereq && hart_available(hart_id)) {
D(fprintf(stderr, "resume hart %d\n", hart_id));
debug_rom_flags[hart_id] |= (1 << DEBUG_ROM_FLAG_RESUME);
hart_state[hart_id].resumeack = false;
}
- if (dmcontrol.hartreset) {
+ if (dmcontrol.hartreset && hart_available(hart_id)) {
hart->reset();
}
}
@@ -903,6 +927,11 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
selected_hart_state().haltgroup = get_field(value, DM_DMCS2_GROUP);
}
return true;
+ case DM_CUSTOM:
+ for (unsigned i = 0; i < sizeof(hart_available_state) / sizeof(*hart_available_state); i++) {
+ hart_available_state[i] = get_field(value, 1<<i);
+ }
+ return true;
}
}
return false;
diff --git a/riscv/debug_module.h b/riscv/debug_module.h
index 518f119..73bb7fa 100644
--- a/riscv/debug_module.h
+++ b/riscv/debug_module.h
@@ -185,6 +185,12 @@ class debug_module_t : public abstract_device_t
size_t selected_hart_id() const;
hart_debug_state_t& selected_hart_state();
+
+ /* Whether the first 2 harts are available is controllable through DMCUSTOM,
+ * where bit 0 corresponds to hart 0, etc. When a bit is one the hart
+ * available. Otherwise it is unavailable. */
+ bool hart_available_state[2];
+ bool hart_available(unsigned hart_id) const;
};
#endif