aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/target/riscv/riscv-013.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 5e54347..4172ff6 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -4304,9 +4304,32 @@ static int riscv013_halt_go(struct target *target)
target_list_t *entry;
list_for_each_entry(entry, &dm->target_list, list) {
struct target *t = entry->target;
- t->state = TARGET_HALTED;
- if (t->debug_reason == DBG_REASON_NOTHALTED)
- t->debug_reason = DBG_REASON_DBGRQ;
+ uint32_t t_dmstatus;
+ if (get_field(dmstatus, DM_DMSTATUS_ALLHALTED) ||
+ get_field(dmstatus, DM_DMSTATUS_ALLUNAVAIL)) {
+ /* All harts are either halted or unavailable. No
+ * need to read dmstatus for each hart. */
+ t_dmstatus = dmstatus;
+ } else {
+ /* Only some harts were halted/unavailable. Read
+ * dmstatus for this one to see what its status
+ * is. */
+ riscv013_info_t *info = get_info(t);
+ dmcontrol = set_dmcontrol_hartsel(dmcontrol, info->index);
+ if (dmi_write(target, DM_DMCONTROL, dmcontrol) != ERROR_OK)
+ return ERROR_FAIL;
+ dm->current_hartid = info->index;
+ if (dmi_read(target, &t_dmstatus, DM_DMSTATUS) != ERROR_OK)
+ return ERROR_FAIL;
+ }
+ /* Set state for the current target based on its dmstatus. */
+ if (get_field(t_dmstatus, DM_DMSTATUS_ALLHALTED)) {
+ t->state = TARGET_HALTED;
+ if (t->debug_reason == DBG_REASON_NOTHALTED)
+ t->debug_reason = DBG_REASON_DBGRQ;
+ } else if (get_field(t_dmstatus, DM_DMSTATUS_ALLUNAVAIL)) {
+ t->state = TARGET_UNAVAILABLE;
+ }
}
}
/* The "else" case is handled in halt_go(). */