diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 8927ac136..a5b7dcf75 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -2752,6 +2752,10 @@ static int riscv_poll_hart(struct target *target, enum riscv_next_action *next_a } } + if (r->handle_became_halted && + r->handle_became_halted(target, previous_riscv_state) != ERROR_OK) + return ERROR_FAIL; + /* We shouldn't do the callbacks yet. What if * there are multiple harts that halted at the * same time? We need to set debug reason on each @@ -2769,12 +2773,18 @@ static int riscv_poll_hart(struct target *target, enum riscv_next_action *next_a LOG_TARGET_DEBUG(target, " triggered running"); target->state = TARGET_RUNNING; target->debug_reason = DBG_REASON_NOTHALTED; + if (r->handle_became_running && + r->handle_became_running(target, previous_riscv_state) != ERROR_OK) + return ERROR_FAIL; break; case RISCV_STATE_UNAVAILABLE: LOG_TARGET_DEBUG(target, " became unavailable"); LOG_TARGET_INFO(target, "became unavailable."); target->state = TARGET_UNAVAILABLE; + if (r->handle_became_unavailable && + r->handle_became_unavailable(target, previous_riscv_state) != ERROR_OK) + return ERROR_FAIL; break; case RISCV_STATE_NON_EXISTENT: diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index a695cc349..03159cfa2 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -193,6 +193,17 @@ struct riscv_info { * was resumed. */ int (*resume_go)(struct target *target); int (*step_current_hart)(struct target *target); + + /* These get called from riscv_poll_hart(), which is a house of cards + * together with openocd_poll(), so be careful not to upset things too + * much. */ + int (*handle_became_halted)(struct target *target, + enum riscv_hart_state previous_riscv_state); + int (*handle_became_running)(struct target *target, + enum riscv_hart_state previous_riscv_state); + int (*handle_became_unavailable)(struct target *target, + enum riscv_hart_state previous_riscv_state); + /* Get this target as ready as possible to resume, without actually * resuming. */ int (*resume_prep)(struct target *target);