diff options
author | Nicholas Piggin <npiggin@gmail.com> | 2024-08-13 21:23:20 +0100 |
---|---|---|
committer | Alex Bennée <alex.bennee@linaro.org> | 2024-08-16 14:04:19 +0100 |
commit | 9dbab31d9eb710b433f93e9e35962fbfd29f4c3f (patch) | |
tree | 6e67a45ed855a8c8a256dbcaeffeda1ff77d5005 | |
parent | 4926b6e6444ffcfcea6f60b855debca88bf9db2e (diff) |
replay: allow runstate shutdown->running when replaying trace
When replaying a trace, it is possible to go from shutdown to running
with a reverse-debugging step. This can be useful if the problem being
debugged triggers a reset or shutdown.
This can be tested by making a recording of a machine that shuts down,
then using -action shutdown=pause when replaying it. Continuing to the
end of the trace then reverse-stepping in gdb crashes due to invalid
runstate transition.
Just permitting the transition seems to be all that's necessary for
reverse-debugging to work well in such a state.
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Message-Id: <20240813050638.446172-5-npiggin@gmail.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20240813202329.1237572-13-alex.bennee@linaro.org>
-rw-r--r-- | include/sysemu/runstate.h | 1 | ||||
-rw-r--r-- | replay/replay.c | 2 | ||||
-rw-r--r-- | system/runstate.c | 31 |
3 files changed, 31 insertions, 3 deletions
diff --git a/include/sysemu/runstate.h b/include/sysemu/runstate.h index e210a37abf..11c7ff3ffb 100644 --- a/include/sysemu/runstate.h +++ b/include/sysemu/runstate.h @@ -9,6 +9,7 @@ void runstate_set(RunState new_state); RunState runstate_get(void); bool runstate_is_running(void); bool runstate_needs_reset(void); +void runstate_replay_enable(void); typedef void VMChangeStateHandler(void *opaque, bool running, RunState state); diff --git a/replay/replay.c b/replay/replay.c index a2c576c16e..b8564a4813 100644 --- a/replay/replay.c +++ b/replay/replay.c @@ -385,6 +385,8 @@ static void replay_enable(const char *fname, int mode) replay_fetch_data_kind(); } + runstate_replay_enable(); + replay_init_events(); } diff --git a/system/runstate.c b/system/runstate.c index c833316f6d..a0e2a5fd22 100644 --- a/system/runstate.c +++ b/system/runstate.c @@ -181,6 +181,12 @@ static const RunStateTransition runstate_transitions_def[] = { { RUN_STATE__MAX, RUN_STATE__MAX }, }; +static const RunStateTransition replay_play_runstate_transitions_def[] = { + { RUN_STATE_SHUTDOWN, RUN_STATE_RUNNING}, + + { RUN_STATE__MAX, RUN_STATE__MAX }, +}; + static bool runstate_valid_transitions[RUN_STATE__MAX][RUN_STATE__MAX]; bool runstate_check(RunState state) @@ -188,14 +194,33 @@ bool runstate_check(RunState state) return current_run_state == state; } -static void runstate_init(void) +static void transitions_set_valid(const RunStateTransition *rst) { const RunStateTransition *p; - memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions)); - for (p = &runstate_transitions_def[0]; p->from != RUN_STATE__MAX; p++) { + for (p = rst; p->from != RUN_STATE__MAX; p++) { runstate_valid_transitions[p->from][p->to] = true; } +} + +void runstate_replay_enable(void) +{ + assert(replay_mode != REPLAY_MODE_NONE); + + if (replay_mode == REPLAY_MODE_PLAY) { + /* + * When reverse-debugging, it is possible to move state from + * shutdown to running. + */ + transitions_set_valid(&replay_play_runstate_transitions_def[0]); + } +} + +static void runstate_init(void) +{ + memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions)); + + transitions_set_valid(&runstate_transitions_def[0]); qemu_mutex_init(&vmstop_lock); } |