Nicholas Piggin <npig...@gmail.com> writes: > 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: Pavel Dovgalyuk <pavel.dovgal...@ispras.ru> > Signed-off-by: Nicholas Piggin <npig...@gmail.com> > --- > include/sysemu/runstate.h | 1 + > replay/replay.c | 2 ++ > system/runstate.c | 19 +++++++++++++++++++ > 3 files changed, 22 insertions(+) > > diff --git a/include/sysemu/runstate.h b/include/sysemu/runstate.h > index 0117d243c4..fe25eed3c0 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 3fd241a4fc..2951eed3bd 100644 > --- a/replay/replay.c > +++ b/replay/replay.c > @@ -383,6 +383,8 @@ static void replay_enable(const char *fname, int mode) > /* go to the beginning */ > fseek(replay_file, HEADER_SIZE, SEEK_SET); > replay_fetch_data_kind(); > + > + runstate_replay_enable(); > } > > replay_init_events(); > diff --git a/system/runstate.c b/system/runstate.c > index d6ab860eca..bd0fed8657 100644 > --- a/system/runstate.c > +++ b/system/runstate.c > @@ -182,6 +182,12 @@ static const RunStateTransition > runstate_transitions_def[] = { > { RUN_STATE__MAX, RUN_STATE__MAX }, > }; > > +static const RunStateTransition replay_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) > @@ -189,6 +195,19 @@ bool runstate_check(RunState state) > return current_run_state == state; > } > > +void runstate_replay_enable(void) > +{ > + const RunStateTransition *p; > + > + assert(replay_mode == REPLAY_MODE_PLAY); > +
As the bellow is common to runstate_init it could be re-factored into a helper taking the runstate_transitions_def pointer. > + for (p = &replay_runstate_transitions_def[0]; p->from != RUN_STATE__MAX; > + p++) { > + runstate_valid_transitions[p->from][p->to] = true; > + } > + > +} > + > static void runstate_init(void) > { > const RunStateTransition *p; -- Alex Bennée Virtualisation Tech Lead @ Linaro