summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sysemu.h1
-rw-r--r--vl.c74
2 files changed, 74 insertions, 1 deletions
diff --git a/sysemu.h b/sysemu.h
index 19088aa2dd..a01ddac564 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -36,6 +36,7 @@ extern uint8_t qemu_uuid[];
int qemu_uuid_parse(const char *str, uint8_t *uuid);
#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
+void runstate_init(void);
bool runstate_check(RunState state);
void runstate_set(RunState new_state);
typedef struct vm_change_state_entry VMChangeStateEntry;
diff --git a/vl.c b/vl.c
index 059e727cb2..cc68fb327d 100644
--- a/vl.c
+++ b/vl.c
@@ -327,14 +327,84 @@ static int default_driver_check(QemuOpts *opts, void *opaque)
static RunState current_run_state = RSTATE_NO_STATE;
+typedef struct {
+ RunState from;
+ RunState to;
+} RunStateTransition;
+
+static const RunStateTransition runstate_transitions_def[] = {
+ /* from -> to */
+ { RSTATE_NO_STATE, RSTATE_RUNNING },
+ { RSTATE_NO_STATE, RSTATE_IN_MIGRATE },
+ { RSTATE_NO_STATE, RSTATE_PRE_LAUNCH },
+
+ { RSTATE_DEBUG, RSTATE_RUNNING },
+
+ { RSTATE_IN_MIGRATE, RSTATE_RUNNING },
+ { RSTATE_IN_MIGRATE, RSTATE_PRE_LAUNCH },
+
+ { RSTATE_PANICKED, RSTATE_PAUSED },
+
+ { RSTATE_IO_ERROR, RSTATE_RUNNING },
+
+ { RSTATE_PAUSED, RSTATE_RUNNING },
+
+ { RSTATE_POST_MIGRATE, RSTATE_RUNNING },
+
+ { RSTATE_PRE_LAUNCH, RSTATE_RUNNING },
+ { RSTATE_PRE_LAUNCH, RSTATE_POST_MIGRATE },
+
+ { RSTATE_PRE_MIGRATE, RSTATE_RUNNING },
+ { RSTATE_PRE_MIGRATE, RSTATE_POST_MIGRATE },
+
+ { RSTATE_RESTORE, RSTATE_RUNNING },
+
+ { RSTATE_RUNNING, RSTATE_DEBUG },
+ { RSTATE_RUNNING, RSTATE_PANICKED },
+ { RSTATE_RUNNING, RSTATE_IO_ERROR },
+ { RSTATE_RUNNING, RSTATE_PAUSED },
+ { RSTATE_RUNNING, RSTATE_PRE_MIGRATE },
+ { RSTATE_RUNNING, RSTATE_RESTORE },
+ { RSTATE_RUNNING, RSTATE_SAVEVM },
+ { RSTATE_RUNNING, RSTATE_SHUTDOWN },
+ { RSTATE_RUNNING, RSTATE_WATCHDOG },
+
+ { RSTATE_SAVEVM, RSTATE_RUNNING },
+
+ { RSTATE_SHUTDOWN, RSTATE_PAUSED },
+
+ { RSTATE_WATCHDOG, RSTATE_RUNNING },
+
+ { RSTATE_MAX, RSTATE_MAX },
+};
+
+static bool runstate_valid_transitions[RSTATE_MAX][RSTATE_MAX];
+
bool runstate_check(RunState state)
{
return current_run_state == state;
}
+void runstate_init(void)
+{
+ const RunStateTransition *p;
+
+ memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
+
+ for (p = &runstate_transitions_def[0]; p->from != RSTATE_MAX; p++) {
+ runstate_valid_transitions[p->from][p->to] = true;
+ }
+}
+
+/* This function will abort() on invalid state transitions */
void runstate_set(RunState new_state)
{
- assert(new_state < RSTATE_MAX);
+ if (new_state >= RSTATE_MAX ||
+ !runstate_valid_transitions[current_run_state][new_state]) {
+ fprintf(stderr, "invalid runstate transition\n");
+ abort();
+ }
+
current_run_state = new_state;
}
@@ -2219,6 +2289,8 @@ int main(int argc, char **argv, char **envp)
g_mem_set_vtable(&mem_trace);
g_thread_init(NULL);
+ runstate_init();
+
init_clocks();
qemu_cache_utils_init(envp);