diff options
-rw-r--r-- | src/target/riscv/riscv-013.c | 29 |
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(). */ |