Merge remote-tracking branch 'qmp/queue/qmp' into staging

This commit is contained in:
Anthony Liguori 2011-10-10 08:21:46 -05:00
commit ebffe2afce
34 changed files with 963 additions and 456 deletions

View File

@ -7,6 +7,7 @@ GENERATED_HEADERS = config-host.h trace.h qemu-options.def
ifeq ($(TRACE_BACKEND),dtrace)
GENERATED_HEADERS += trace-dtrace.h
endif
GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
ifneq ($(wildcard config-host.mak),)
# Put the all: rule here so that config-host.mak can contain dependencies.
@ -188,9 +189,20 @@ $(qapi-dir)/qga-qapi-types.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scr
$(qapi-dir)/qga-qapi-visit.c: $(qapi-dir)/qga-qapi-visit.h
$(qapi-dir)/qga-qapi-visit.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-visit.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@")
$(qapi-dir)/qga-qmp-commands.h: $(qapi-dir)/qga-qmp-marshal.c
$(qapi-dir)/qga-qmp-marshal.c: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-commands.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@")
qapi-types.c: qapi-types.h
qapi-types.h: $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py -o "." < $<, " GEN $@")
qapi-visit.c: qapi-visit.h
qapi-visit.h: $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "." < $<, " GEN $@")
qmp-commands.h: qmp-marshal.c
qmp-marshal.c: $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -m -o "." < $<, " GEN $@")
test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
test-visitor: test-visitor.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o

View File

@ -405,6 +405,9 @@ qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-
qapi-nested-y += qmp-registry.o qmp-dispatch.o
qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o $(qapi-obj-y)
common-obj-y += qmp.o hmp.o
######################################################################
# guest agent

View File

@ -376,7 +376,7 @@ obj-xtensa-y += xtensa-semi.o
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
monitor.o: hmp-commands.h qmp-commands.h
monitor.o: hmp-commands.h qmp-commands-old.h
$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
@ -408,13 +408,13 @@ gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
hmp-commands.h: $(SRC_PATH)/hmp-commands.hx
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
qmp-commands.h: $(SRC_PATH)/qmp-commands.hx
qmp-commands-old.h: $(SRC_PATH)/qmp-commands.hx
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
clean:
rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
rm -f *.d */*.d tcg/*.o ide/*.o 9pfs/*.o
rm -f hmp-commands.h qmp-commands.h gdbstub-xml.c
rm -f hmp-commands.h qmp-commands-old.h gdbstub-xml.c
ifdef CONFIG_TRACE_SYSTEMTAP
rm -f *.stp
endif

View File

@ -97,6 +97,10 @@ bool error_is_type(Error *err, const char *fmt)
char *ptr;
char *end;
if (!err) {
return false;
}
ptr = strstr(fmt, "'class': '");
assert(ptr != NULL);
ptr += strlen("'class': '");

View File

@ -2385,7 +2385,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
return;
}
switch (state) {
case RSTATE_DEBUG:
case RUN_STATE_DEBUG:
if (env->watchpoint_hit) {
switch (env->watchpoint_hit->flags & BP_MEM_ACCESS) {
case BP_MEM_READ:
@ -2408,25 +2408,25 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
tb_flush(env);
ret = GDB_SIGNAL_TRAP;
break;
case RSTATE_PAUSED:
case RUN_STATE_PAUSED:
ret = GDB_SIGNAL_INT;
break;
case RSTATE_SHUTDOWN:
case RUN_STATE_SHUTDOWN:
ret = GDB_SIGNAL_QUIT;
break;
case RSTATE_IO_ERROR:
case RUN_STATE_IO_ERROR:
ret = GDB_SIGNAL_IO;
break;
case RSTATE_WATCHDOG:
case RUN_STATE_WATCHDOG:
ret = GDB_SIGNAL_ALRM;
break;
case RSTATE_PANICKED:
case RUN_STATE_INTERNAL_ERROR:
ret = GDB_SIGNAL_ABRT;
break;
case RSTATE_SAVEVM:
case RSTATE_RESTORE:
case RUN_STATE_SAVE_VM:
case RUN_STATE_RESTORE_VM:
return;
case RSTATE_PRE_MIGRATE:
case RUN_STATE_FINISH_MIGRATE:
ret = GDB_SIGNAL_XCPU;
break;
default:
@ -2463,7 +2463,7 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
gdb_current_syscall_cb = cb;
s->state = RS_SYSCALL;
#ifndef CONFIG_USER_ONLY
vm_stop(RSTATE_DEBUG);
vm_stop(RUN_STATE_DEBUG);
#endif
s->state = RS_IDLE;
va_start(va, fmt);
@ -2537,7 +2537,7 @@ static void gdb_read_byte(GDBState *s, int ch)
if (runstate_is_running()) {
/* when the CPU is running, we cannot do anything except stop
it when receiving a char */
vm_stop(RSTATE_PAUSED);
vm_stop(RUN_STATE_PAUSED);
} else
#endif
{
@ -2799,7 +2799,7 @@ static void gdb_chr_event(void *opaque, int event)
{
switch (event) {
case CHR_EVENT_OPENED:
vm_stop(RSTATE_PAUSED);
vm_stop(RUN_STATE_PAUSED);
gdb_has_xml = 0;
break;
default:
@ -2840,7 +2840,7 @@ static int gdb_monitor_write(CharDriverState *chr, const uint8_t *buf, int len)
static void gdb_sigterm_handler(int signal)
{
if (runstate_is_running()) {
vm_stop(RSTATE_PAUSED);
vm_stop(RUN_STATE_PAUSED);
}
}
#endif

View File

@ -43,7 +43,7 @@ ETEXI
.params = "",
.help = "quit the emulator",
.user_print = monitor_user_noop,
.mhandler.cmd_new = do_quit,
.mhandler.cmd = hmp_quit,
},
STEXI
@ -290,8 +290,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "stop emulation",
.user_print = monitor_user_noop,
.mhandler.cmd_new = do_stop,
.mhandler.cmd = hmp_stop,
},
STEXI
@ -478,8 +477,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "reset the system",
.user_print = monitor_user_noop,
.mhandler.cmd_new = do_system_reset,
.mhandler.cmd = hmp_system_reset,
},
STEXI
@ -494,8 +492,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "send system power down event",
.user_print = monitor_user_noop,
.mhandler.cmd_new = do_system_powerdown,
.mhandler.cmd = hmp_system_powerdown,
},
STEXI

116
hmp.c Normal file
View File

@ -0,0 +1,116 @@
/*
* Human Monitor Interface
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
*/
#include "hmp.h"
#include "qmp-commands.h"
void hmp_info_name(Monitor *mon)
{
NameInfo *info;
info = qmp_query_name(NULL);
if (info->has_name) {
monitor_printf(mon, "%s\n", info->name);
}
qapi_free_NameInfo(info);
}
void hmp_info_version(Monitor *mon)
{
VersionInfo *info;
info = qmp_query_version(NULL);
monitor_printf(mon, "%" PRId64 ".%" PRId64 ".%" PRId64 "%s\n",
info->qemu.major, info->qemu.minor, info->qemu.micro,
info->package);
qapi_free_VersionInfo(info);
}
void hmp_info_kvm(Monitor *mon)
{
KvmInfo *info;
info = qmp_query_kvm(NULL);
monitor_printf(mon, "kvm support: ");
if (info->present) {
monitor_printf(mon, "%s\n", info->enabled ? "enabled" : "disabled");
} else {
monitor_printf(mon, "not compiled\n");
}
qapi_free_KvmInfo(info);
}
void hmp_info_status(Monitor *mon)
{
StatusInfo *info;
info = qmp_query_status(NULL);
monitor_printf(mon, "VM status: %s%s",
info->running ? "running" : "paused",
info->singlestep ? " (single step mode)" : "");
if (!info->running && info->status != RUN_STATE_PAUSED) {
monitor_printf(mon, " (%s)", RunState_lookup[info->status]);
}
monitor_printf(mon, "\n");
qapi_free_StatusInfo(info);
}
void hmp_info_uuid(Monitor *mon)
{
UuidInfo *info;
info = qmp_query_uuid(NULL);
monitor_printf(mon, "%s\n", info->UUID);
qapi_free_UuidInfo(info);
}
void hmp_info_chardev(Monitor *mon)
{
ChardevInfoList *char_info, *info;
char_info = qmp_query_chardev(NULL);
for (info = char_info; info; info = info->next) {
monitor_printf(mon, "%s: filename=%s\n", info->value->label,
info->value->filename);
}
qapi_free_ChardevInfoList(char_info);
}
void hmp_quit(Monitor *mon, const QDict *qdict)
{
monitor_suspend(mon);
qmp_quit(NULL);
}
void hmp_stop(Monitor *mon, const QDict *qdict)
{
qmp_stop(NULL);
}
void hmp_system_reset(Monitor *mon, const QDict *qdict)
{
qmp_system_reset(NULL);
}
void hmp_system_powerdown(Monitor *mon, const QDict *qdict)
{
qmp_system_powerdown(NULL);
}

31
hmp.h Normal file
View File

@ -0,0 +1,31 @@
/*
* Human Monitor Interface
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
*/
#ifndef HMP_H
#define HMP_H
#include "qemu-common.h"
#include "qapi-types.h"
void hmp_info_name(Monitor *mon);
void hmp_info_version(Monitor *mon);
void hmp_info_kvm(Monitor *mon);
void hmp_info_status(Monitor *mon);
void hmp_info_uuid(Monitor *mon);
void hmp_info_chardev(Monitor *mon);
void hmp_quit(Monitor *mon, const QDict *qdict);
void hmp_stop(Monitor *mon, const QDict *qdict);
void hmp_system_reset(Monitor *mon, const QDict *qdict);
void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
#endif

View File

@ -527,7 +527,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op)
s->bus->dma->ops->set_unit(s->bus->dma, s->unit);
s->bus->error_status = op;
bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
vm_stop(RSTATE_IO_ERROR);
vm_stop(RUN_STATE_IO_ERROR);
} else {
if (op & BM_STATUS_DMA_RETRY) {
dma_buf_commit(s, 0);

View File

@ -227,7 +227,7 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
r->status |= SCSI_REQ_STATUS_RETRY | type;
bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
vm_stop(RSTATE_IO_ERROR);
vm_stop(RUN_STATE_IO_ERROR);
} else {
switch (error) {
case ENOMEM:

View File

@ -77,7 +77,7 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
req->next = s->rq;
s->rq = req;
bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
vm_stop(RSTATE_IO_ERROR);
vm_stop(RUN_STATE_IO_ERROR);
} else {
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
bdrv_acct_done(s->bs, &req->acct);

View File

@ -132,7 +132,7 @@ void watchdog_perform_action(void)
case WDT_PAUSE: /* same as 'stop' command in monitor */
watchdog_mon_event("pause");
vm_stop(RSTATE_WATCHDOG);
vm_stop(RUN_STATE_WATCHDOG);
break;
case WDT_DEBUG:

View File

@ -1014,7 +1014,7 @@ int kvm_cpu_exec(CPUState *env)
if (ret < 0) {
cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
vm_stop(RSTATE_PANICKED);
vm_stop(RUN_STATE_INTERNAL_ERROR);
}
env->exit_request = 0;

View File

@ -73,7 +73,7 @@ void process_incoming_migration(QEMUFile *f)
if (autostart) {
vm_start();
} else {
runstate_set(RSTATE_PRE_LAUNCH);
runstate_set(RUN_STATE_PRELAUNCH);
}
}
@ -375,7 +375,7 @@ void migrate_fd_put_ready(void *opaque)
int old_vm_running = runstate_is_running();
DPRINTF("done iterating\n");
vm_stop(RSTATE_PRE_MIGRATE);
vm_stop(RUN_STATE_FINISH_MIGRATE);
if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
if (old_vm_running) {
@ -392,7 +392,7 @@ void migrate_fd_put_ready(void *opaque)
state = MIG_STATE_ERROR;
}
if (state == MIG_STATE_COMPLETED) {
runstate_set(RSTATE_POST_MIGRATE);
runstate_set(RUN_STATE_POSTMIGRATE);
}
s->state = state;
notifier_list_notify(&migration_state_notifiers, NULL);

281
monitor.c
View File

@ -64,6 +64,8 @@
#endif
#include "ui/qemu-spice.h"
#include "memory.h"
#include "qmp-commands.h"
#include "hmp.h"
//#define DEBUG
//#define DEBUG_COMPLETION
@ -122,6 +124,7 @@ typedef struct mon_cmd_t {
int (*cmd_async)(Monitor *mon, const QDict *params,
MonitorCompletion *cb, void *opaque);
} mhandler;
bool qapi;
int flags;
} mon_cmd_t;
@ -730,105 +733,37 @@ help:
help_cmd(mon, "info");
}
static void do_info_version_print(Monitor *mon, const QObject *data)
static CommandInfoList *alloc_cmd_entry(const char *cmd_name)
{
QDict *qdict;
QDict *qemu;
CommandInfoList *info;
qdict = qobject_to_qdict(data);
qemu = qdict_get_qdict(qdict, "qemu");
info = g_malloc0(sizeof(*info));
info->value = g_malloc0(sizeof(*info->value));
info->value->name = g_strdup(cmd_name);
monitor_printf(mon, "%" PRId64 ".%" PRId64 ".%" PRId64 "%s\n",
qdict_get_int(qemu, "major"),
qdict_get_int(qemu, "minor"),
qdict_get_int(qemu, "micro"),
qdict_get_str(qdict, "package"));
return info;
}
static void do_info_version(Monitor *mon, QObject **ret_data)
CommandInfoList *qmp_query_commands(Error **errp)
{
const char *version = QEMU_VERSION;
int major = 0, minor = 0, micro = 0;
char *tmp;
major = strtol(version, &tmp, 10);
tmp++;
minor = strtol(tmp, &tmp, 10);
tmp++;
micro = strtol(tmp, &tmp, 10);
*ret_data = qobject_from_jsonf("{ 'qemu': { 'major': %d, 'minor': %d, \
'micro': %d }, 'package': %s }", major, minor, micro, QEMU_PKGVERSION);
}
static void do_info_name_print(Monitor *mon, const QObject *data)
{
QDict *qdict;
qdict = qobject_to_qdict(data);
if (qdict_size(qdict) == 0) {
return;
}
monitor_printf(mon, "%s\n", qdict_get_str(qdict, "name"));
}
static void do_info_name(Monitor *mon, QObject **ret_data)
{
*ret_data = qemu_name ? qobject_from_jsonf("{'name': %s }", qemu_name) :
qobject_from_jsonf("{}");
}
static QObject *get_cmd_dict(const char *name)
{
const char *p;
/* Remove '|' from some commands */
p = strchr(name, '|');
if (p) {
p++;
} else {
p = name;
}
return qobject_from_jsonf("{ 'name': %s }", p);
}
static void do_info_commands(Monitor *mon, QObject **ret_data)
{
QList *cmd_list;
CommandInfoList *info, *cmd_list = NULL;
const mon_cmd_t *cmd;
cmd_list = qlist_new();
for (cmd = qmp_cmds; cmd->name != NULL; cmd++) {
qlist_append_obj(cmd_list, get_cmd_dict(cmd->name));
info = alloc_cmd_entry(cmd->name);
info->next = cmd_list;
cmd_list = info;
}
for (cmd = qmp_query_cmds; cmd->name != NULL; cmd++) {
char buf[128];
snprintf(buf, sizeof(buf), "query-%s", cmd->name);
qlist_append_obj(cmd_list, get_cmd_dict(buf));
info = alloc_cmd_entry(buf);
info->next = cmd_list;
cmd_list = info;
}
*ret_data = QOBJECT(cmd_list);
}
static void do_info_uuid_print(Monitor *mon, const QObject *data)
{
monitor_printf(mon, "%s\n", qdict_get_str(qobject_to_qdict(data), "UUID"));
}
static void do_info_uuid(Monitor *mon, QObject **ret_data)
{
char uuid[64];
snprintf(uuid, sizeof(uuid), UUID_FMT, qemu_uuid[0], qemu_uuid[1],
qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], qemu_uuid[5],
qemu_uuid[6], qemu_uuid[7], qemu_uuid[8], qemu_uuid[9],
qemu_uuid[10], qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
qemu_uuid[14], qemu_uuid[15]);
*ret_data = qobject_from_jsonf("{ 'UUID': %s }", uuid);
return cmd_list;
}
/* get the current CPU defined by the user */
@ -1013,18 +948,6 @@ static void do_trace_print_events(Monitor *mon)
trace_print_events((FILE *)mon, &monitor_fprintf);
}
/**
* do_quit(): Quit QEMU execution
*/
static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
monitor_suspend(mon);
no_shutdown = 0;
qemu_system_shutdown_request();
return 0;
}
#ifdef CONFIG_VNC
static int change_vnc_password(const char *password)
{
@ -1291,15 +1214,6 @@ static void do_singlestep(Monitor *mon, const QDict *qdict)
}
}
/**
* do_stop(): Stop VM execution
*/
static int do_stop(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
vm_stop(RSTATE_PAUSED);
return 0;
}
static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs);
struct bdrv_iterate_context {
@ -1314,11 +1228,11 @@ static int do_cont(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
struct bdrv_iterate_context context = { mon, 0 };
if (runstate_check(RSTATE_IN_MIGRATE)) {
if (runstate_check(RUN_STATE_INMIGRATE)) {
qerror_report(QERR_MIGRATION_EXPECTED);
return -1;
} else if (runstate_check(RSTATE_PANICKED) ||
runstate_check(RSTATE_SHUTDOWN)) {
} else if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
runstate_check(RUN_STATE_SHUTDOWN)) {
qerror_report(QERR_RESET_REQUIRED);
return -1;
}
@ -2017,16 +1931,6 @@ static void do_boot_set(Monitor *mon, const QDict *qdict)
}
}
/**
* do_system_reset(): Issue a machine reset
*/
static int do_system_reset(Monitor *mon, const QDict *qdict,
QObject **ret_data)
{
qemu_system_reset_request();
return 0;
}
/**
* do_system_powerdown(): Issue a machine powerdown
*/
@ -2478,31 +2382,6 @@ static void do_info_mtree(Monitor *mon)
mtree_info((fprintf_function)monitor_printf, mon);
}
static void do_info_kvm_print(Monitor *mon, const QObject *data)
{
QDict *qdict;
qdict = qobject_to_qdict(data);
monitor_printf(mon, "kvm support: ");
if (qdict_get_bool(qdict, "present")) {
monitor_printf(mon, "%s\n", qdict_get_bool(qdict, "enabled") ?
"enabled" : "disabled");
} else {
monitor_printf(mon, "not compiled\n");
}
}
static void do_info_kvm(Monitor *mon, QObject **ret_data)
{
#ifdef CONFIG_KVM
*ret_data = qobject_from_jsonf("{ 'enabled': %i, 'present': true }",
kvm_enabled());
#else
*ret_data = qobject_from_jsonf("{ 'enabled': false, 'present': false }");
#endif
}
static void do_info_numa(Monitor *mon)
{
int i;
@ -2623,36 +2502,6 @@ static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data)
}
#endif
static void do_info_status_print(Monitor *mon, const QObject *data)
{
QDict *qdict;
const char *status;
qdict = qobject_to_qdict(data);
monitor_printf(mon, "VM status: ");
if (qdict_get_bool(qdict, "running")) {
monitor_printf(mon, "running");
if (qdict_get_bool(qdict, "singlestep")) {
monitor_printf(mon, " (single step mode)");
}
} else {
monitor_printf(mon, "paused");
}
status = qdict_get_str(qdict, "status");
if (strcmp(status, "paused") && strcmp(status, "running")) {
monitor_printf(mon, " (%s)", status);
}
monitor_printf(mon, "\n");
}
static void do_info_status(Monitor *mon, QObject **ret_data)
{
*ret_data = qobject_from_jsonf("{ 'running': %i, 'singlestep': %i, 'status': %s }", runstate_is_running(), singlestep, runstate_as_string());
}
static qemu_acl *find_acl(Monitor *mon, const char *name)
{
qemu_acl *acl = qemu_acl_find(name);
@ -2846,7 +2695,7 @@ static void do_loadvm(Monitor *mon, const QDict *qdict)
int saved_vm_running = runstate_is_running();
const char *name = qdict_get_str(qdict, "name");
vm_stop(RSTATE_RESTORE);
vm_stop(RUN_STATE_RESTORE_VM);
if (load_vmstate(name) == 0 && saved_vm_running) {
vm_start();
@ -2889,8 +2738,7 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show the version of QEMU",
.user_print = do_info_version_print,
.mhandler.info_new = do_info_version,
.mhandler.info = hmp_info_version,
},
{
.name = "network",
@ -2904,8 +2752,7 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show the character devices",
.user_print = qemu_chr_info_print,
.mhandler.info_new = qemu_chr_info,
.mhandler.info = hmp_info_chardev,
},
{
.name = "block",
@ -3005,8 +2852,7 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show KVM information",
.user_print = do_info_kvm_print,
.mhandler.info_new = do_info_kvm,
.mhandler.info = hmp_info_kvm,
},
{
.name = "numa",
@ -3055,8 +2901,7 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show the current VM status (running|paused)",
.user_print = do_info_status_print,
.mhandler.info_new = do_info_status,
.mhandler.info = hmp_info_status,
},
{
.name = "pcmcia",
@ -3096,16 +2941,14 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show the current VM name",
.user_print = do_info_name_print,
.mhandler.info_new = do_info_name,
.mhandler.info = hmp_info_name,
},
{
.name = "uuid",
.args_type = "",
.params = "",
.help = "show the current VM UUID",
.user_print = do_info_uuid_print,
.mhandler.info_new = do_info_uuid,
.mhandler.info = hmp_info_uuid,
},
#if defined(TARGET_PPC)
{
@ -3185,35 +3028,11 @@ static const mon_cmd_t info_cmds[] = {
};
static const mon_cmd_t qmp_cmds[] = {
#include "qmp-commands.h"
#include "qmp-commands-old.h"
{ /* NULL */ },
};
static const mon_cmd_t qmp_query_cmds[] = {
{
.name = "version",
.args_type = "",
.params = "",
.help = "show the version of QEMU",
.user_print = do_info_version_print,
.mhandler.info_new = do_info_version,
},
{
.name = "commands",
.args_type = "",
.params = "",
.help = "list QMP available commands",
.user_print = monitor_user_noop,
.mhandler.info_new = do_info_commands,
},
{
.name = "chardev",
.args_type = "",
.params = "",
.help = "show the character devices",
.user_print = qemu_chr_info_print,
.mhandler.info_new = qemu_chr_info,
},
{
.name = "block",
.args_type = "",
@ -3246,22 +3065,6 @@ static const mon_cmd_t qmp_query_cmds[] = {
.user_print = do_pci_info_print,
.mhandler.info_new = do_pci_info,
},
{
.name = "kvm",
.args_type = "",
.params = "",
.help = "show KVM information",
.user_print = do_info_kvm_print,
.mhandler.info_new = do_info_kvm,
},
{
.name = "status",
.args_type = "",
.params = "",
.help = "show the current VM status (running|paused)",
.user_print = do_info_status_print,
.mhandler.info_new = do_info_status,
},
{
.name = "mice",
.args_type = "",
@ -3288,22 +3091,6 @@ static const mon_cmd_t qmp_query_cmds[] = {
.mhandler.info_new = do_info_spice,
},
#endif
{
.name = "name",
.args_type = "",
.params = "",
.help = "show the current VM name",
.user_print = do_info_name_print,
.mhandler.info_new = do_info_name,
},
{
.name = "uuid",
.args_type = "",
.params = "",
.help = "show the current VM UUID",
.user_print = do_info_uuid_print,
.mhandler.info_new = do_info_uuid,
},
{
.name = "migrate",
.args_type = "",
@ -5111,12 +4898,10 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
goto err_out;
}
if (strstart(cmd_name, "query-", &query_cmd)) {
cmd = qmp_find_cmd(cmd_name);
if (!cmd && strstart(cmd_name, "query-", &query_cmd)) {
cmd = qmp_find_query_cmd(query_cmd);
} else {
cmd = qmp_find_cmd(cmd_name);
}
if (!cmd) {
qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
goto err_out;
@ -5215,9 +5000,9 @@ void monitor_resume(Monitor *mon)
static QObject *get_qmp_greeting(void)
{
QObject *ver;
QObject *ver = NULL;
do_info_version(NULL, &ver);
qmp_marshal_input_query_version(NULL, NULL, &ver);
return qobject_from_jsonf("{'QMP':{'version': %p,'capabilities': []}}",ver);
}

273
qapi-schema.json Normal file
View File

@ -0,0 +1,273 @@
# -*- Mode: Python -*-
#
# QAPI Schema
##
# @NameInfo:
#
# Guest name information.
#
# @name: #optional The name of the guest
#
# Since 0.14.0
##
{ 'type': 'NameInfo', 'data': {'*name': 'str'} }
##
# @query-name:
#
# Return the name information of a guest.
#
# Returns: @NameInfo of the guest
#
# Since 0.14.0
##
{ 'command': 'query-name', 'returns': 'NameInfo' }
##
# @VersionInfo:
#
# A description of QEMU's version.
#
# @qemu.major: The major version of QEMU
#
# @qemu.minor: The minor version of QEMU
#
# @qemu.micro: The micro version of QEMU. By current convention, a micro
# version of 50 signifies a development branch. A micro version
# greater than or equal to 90 signifies a release candidate for
# the next minor version. A micro version of less than 50
# signifies a stable release.
#
# @package: QEMU will always set this field to an empty string. Downstream
# versions of QEMU should set this to a non-empty string. The
# exact format depends on the downstream however it highly
# recommended that a unique name is used.
#
# Since: 0.14.0
##
{ 'type': 'VersionInfo',
'data': {'qemu': {'major': 'int', 'minor': 'int', 'micro': 'int'},
'package': 'str'} }
##
# @query-version:
#
# Returns the current version of QEMU.
#
# Returns: A @VersionInfo object describing the current version of QEMU.
#
# Since: 0.14.0
##
{ 'command': 'query-version', 'returns': 'VersionInfo' }
##
# @KvmInfo:
#
# Information about support for KVM acceleration
#
# @enabled: true if KVM acceleration is active
#
# @present: true if KVM acceleration is built into this executable
#
# Since: 0.14.0
##
{ 'type': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
##
# @query-kvm:
#
# Returns information about KVM acceleration
#
# Returns: @KvmInfo
#
# Since: 0.14.0
##
{ 'command': 'query-kvm', 'returns': 'KvmInfo' }
##
# @RunState
#
# An enumation of VM run states.
#
# @debug: QEMU is running on a debugger
#
# @inmigrate: guest is paused waiting for an incoming migration
#
# @internal-error: An internal error that prevents further guest execution
# has occurred
#
# @io-error: the last IOP has failed and the device is configured to pause
# on I/O errors
#
# @paused: guest has been paused via the 'stop' command
#
# @postmigrate: guest is paused following a successful 'migrate'
#
# @prelaunch: QEMU was started with -S and guest has not started
#
# @finish-migrate: guest is paused to finish the migration process
#
# @restore-vm: guest is paused to restore VM state
#
# @running: guest is actively running
#
# @save-vm: guest is paused to save the VM state
#
# @shutdown: guest is shut down (and -no-shutdown is in use)
#
# @watchdog: the watchdog action is configured to pause and has been triggered
##
{ 'enum': 'RunState',
'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused',
'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',
'running', 'save-vm', 'shutdown', 'watchdog' ] }
##
# @StatusInfo:
#
# Information about VCPU run state
#
# @running: true if all VCPUs are runnable, false if not runnable
#
# @singlestep: true if VCPUs are in single-step mode
#
# @status: the virtual machine @RunState
#
# Since: 0.14.0
#
# Notes: @singlestep is enabled through the GDB stub
##
{ 'type': 'StatusInfo',
'data': {'running': 'bool', 'singlestep': 'bool', 'status': 'RunState'} }
##
# @query-status:
#
# Query the run status of all VCPUs
#
# Returns: @StatusInfo reflecting all VCPUs
#
# Since: 0.14.0
##
{ 'command': 'query-status', 'returns': 'StatusInfo' }
##
# @UuidInfo:
#
# Guest UUID information.
#
# @UUID: the UUID of the guest
#
# Since: 0.14.0
#
# Notes: If no UUID was specified for the guest, a null UUID is returned.
##
{ 'type': 'UuidInfo', 'data': {'UUID': 'str'} }
##
# @query-uuid:
#
# Query the guest UUID information.
#
# Returns: The @UuidInfo for the guest
#
# Since 0.14.0
##
{ 'command': 'query-uuid', 'returns': 'UuidInfo' }
##
# @ChardevInfo:
#
# Information about a character device.
#
# @label: the label of the character device
#
# @filename: the filename of the character device
#
# Notes: @filename is encoded using the QEMU command line character device
# encoding. See the QEMU man page for details.
#
# Since: 0.14.0
##
{ 'type': 'ChardevInfo', 'data': {'label': 'str', 'filename': 'str'} }
##
# @query-chardev:
#
# Returns information about current character devices.
#
# Returns: a list of @ChardevInfo
#
# Since: 0.14.0
##
{ 'command': 'query-chardev', 'returns': ['ChardevInfo'] }
##
# @CommandInfo:
#
# Information about a QMP command
#
# @name: The command name
#
# Since: 0.14.0
##
{ 'type': 'CommandInfo', 'data': {'name': 'str'} }
##
# @query-commands:
#
# Return a list of supported QMP commands by this server
#
# Returns: A list of @CommandInfo for all supported commands
#
# Since: 0.14.0
##
{ 'command': 'query-commands', 'returns': ['CommandInfo'] }
##
# @quit:
#
# This command will cause the QEMU process to exit gracefully. While every
# attempt is made to send the QMP response before terminating, this is not
# guaranteed. When using this interface, a premature EOF would not be
# unexpected.
#
# Since: 0.14.0
##
{ 'command': 'quit' }
##
# @stop:
#
# Stop all guest VCPU execution.
#
# Since: 0.14.0
#
# Notes: This function will succeed even if the guest is already in the stopped
# state
##
{ 'command': 'stop' }
##
# @system_reset:
#
# Performs a hard reset of a guest.
#
# Since: 0.14.0
##
{ 'command': 'system_reset' }
##
# @system_powerdown:
#
# Requests that a guest perform a powerdown operation.
#
# Since: 0.14.0
#
# Notes: A guest may or may not respond to this command. This command
# returning does not indicate that a guest has accepted the request or
# that it has shut down. Many guests will respond to this command by
# prompting the user in some way.
##
{ 'command': 'system_powerdown' }

View File

@ -19,6 +19,7 @@
typedef struct StackEntry
{
void *value;
bool is_list_head;
QTAILQ_ENTRY(StackEntry) node;
} StackEntry;
@ -26,6 +27,7 @@ struct QapiDeallocVisitor
{
Visitor visitor;
QTAILQ_HEAD(, StackEntry) stack;
bool is_list_head;
};
static QapiDeallocVisitor *to_qov(Visitor *v)
@ -38,6 +40,11 @@ static void qapi_dealloc_push(QapiDeallocVisitor *qov, void *value)
StackEntry *e = g_malloc0(sizeof(*e));
e->value = value;
/* see if we're just pushing a list head tracker */
if (value == NULL) {
e->is_list_head = true;
}
QTAILQ_INSERT_HEAD(&qov->stack, e, node);
}
@ -70,19 +77,36 @@ static void qapi_dealloc_end_struct(Visitor *v, Error **errp)
static void qapi_dealloc_start_list(Visitor *v, const char *name, Error **errp)
{
QapiDeallocVisitor *qov = to_qov(v);
qapi_dealloc_push(qov, NULL);
}
static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **list,
static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **listp,
Error **errp)
{
GenericList *retval = *list;
g_free(retval->value);
*list = retval->next;
return retval;
GenericList *list = *listp;
QapiDeallocVisitor *qov = to_qov(v);
StackEntry *e = QTAILQ_FIRST(&qov->stack);
if (e && e->is_list_head) {
e->is_list_head = false;
return list;
}
if (list) {
list = list->next;
g_free(*listp);
return list;
}
return NULL;
}
static void qapi_dealloc_end_list(Visitor *v, Error **errp)
{
QapiDeallocVisitor *qov = to_qov(v);
void *obj = qapi_dealloc_pop(qov);
assert(obj == NULL); /* should've been list head tracker with no payload */
}
static void qapi_dealloc_type_str(Visitor *v, char **obj, const char *name,

View File

@ -17,4 +17,7 @@
#include "qemu-common.h"
#include "error.h"
/* FIXME this is temporary until we remove middle mode */
#include "monitor.h"
#endif

View File

@ -144,8 +144,6 @@ static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
}
(*list)->next = entry;
}
*list = entry;
return entry;
}
@ -240,9 +238,11 @@ static void qmp_input_type_enum(Visitor *v, int *obj, const char *strings[],
if (strings[value] == NULL) {
error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
g_free(enum_str);
return;
}
g_free(enum_str);
*obj = value;
}

View File

@ -20,6 +20,7 @@
typedef struct QStackEntry
{
QObject *value;
bool is_list_head;
QTAILQ_ENTRY(QStackEntry) node;
} QStackEntry;
@ -45,6 +46,9 @@ static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value)
QStackEntry *e = g_malloc0(sizeof(*e));
e->value = value;
if (qobject_type(e->value) == QTYPE_QLIST) {
e->is_list_head = true;
}
QTAILQ_INSERT_HEAD(&qov->stack, e, node);
}
@ -122,12 +126,20 @@ static void qmp_output_start_list(Visitor *v, const char *name, Error **errp)
qmp_output_push(qov, list);
}
static GenericList *qmp_output_next_list(Visitor *v, GenericList **list,
static GenericList *qmp_output_next_list(Visitor *v, GenericList **listp,
Error **errp)
{
GenericList *retval = *list;
*list = retval->next;
return retval;
GenericList *list = *listp;
QmpOutputVisitor *qov = to_qov(v);
QStackEntry *e = QTAILQ_FIRST(&qov->stack);
assert(e);
if (e->is_list_head) {
e->is_list_head = false;
return list;
}
return list ? list->next : NULL;
}
static void qmp_output_end_list(Visitor *v, Error **errp)

View File

@ -31,7 +31,7 @@
#include "hw/usb.h"
#include "hw/baum.h"
#include "hw/msmouse.h"
#include "qemu-objects.h"
#include "qmp-commands.h"
#include <unistd.h>
#include <fcntl.h>
@ -2650,35 +2650,22 @@ void qemu_chr_delete(CharDriverState *chr)
g_free(chr);
}
static void qemu_chr_qlist_iter(QObject *obj, void *opaque)
ChardevInfoList *qmp_query_chardev(Error **errp)
{
QDict *chr_dict;
Monitor *mon = opaque;
chr_dict = qobject_to_qdict(obj);
monitor_printf(mon, "%s: filename=%s\n", qdict_get_str(chr_dict, "label"),
qdict_get_str(chr_dict, "filename"));
}
void qemu_chr_info_print(Monitor *mon, const QObject *ret_data)
{
qlist_iter(qobject_to_qlist(ret_data), qemu_chr_qlist_iter, mon);
}
void qemu_chr_info(Monitor *mon, QObject **ret_data)
{
QList *chr_list;
ChardevInfoList *chr_list = NULL;
CharDriverState *chr;
chr_list = qlist_new();
QTAILQ_FOREACH(chr, &chardevs, next) {
QObject *obj = qobject_from_jsonf("{ 'label': %s, 'filename': %s }",
chr->label, chr->filename);
qlist_append_obj(chr_list, obj);
ChardevInfoList *info = g_malloc0(sizeof(*info));
info->value = g_malloc0(sizeof(*info->value));
info->value->label = g_strdup(chr->label);
info->value->filename = g_strdup(chr->filename);
info->next = chr_list;
chr_list = info;
}
*ret_data = QOBJECT(chr_list);
return chr_list;
}
CharDriverState *qemu_chr_find(const char *name)

View File

@ -482,6 +482,39 @@ void qerror_report_internal(const char *file, int linenr, const char *func,
}
}
/* Evil... */
struct Error
{
QDict *obj;
const char *fmt;
char *msg;
};
void qerror_report_err(Error *err)
{
QError *qerr;
int i;
qerr = qerror_new();
loc_save(&qerr->loc);
QINCREF(err->obj);
qerr->error = err->obj;
for (i = 0; qerror_table[i].error_fmt; i++) {
if (strcmp(qerror_table[i].error_fmt, err->fmt) == 0) {
qerr->entry = &qerror_table[i];
break;
}
}
if (monitor_cur_is_qmp()) {
monitor_set_error(cur_mon, qerr);
} else {
qerror_print(qerr);
QDECREF(qerr);
}
}
/**
* qobject_to_qerror(): Convert a QObject into a QError
*/

View File

@ -15,6 +15,7 @@
#include "qdict.h"
#include "qstring.h"
#include "qemu-error.h"
#include "error.h"
#include <stdarg.h>
typedef struct QErrorStringTable {
@ -39,6 +40,7 @@ QString *qerror_human(const QError *qerror);
void qerror_print(QError *qerror);
void qerror_report_internal(const char *file, int linenr, const char *func,
const char *fmt, ...) GCC_FMT_ATTR(4, 5);
void qerror_report_err(Error *err);
QString *qerror_format(const char *fmt, QDict *error);
#define qerror_report(fmt, ...) \
qerror_report_internal(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__)

View File

@ -63,10 +63,7 @@ EQMP
{
.name = "quit",
.args_type = "",
.params = "",
.help = "quit the emulator",
.user_print = monitor_user_noop,
.mhandler.cmd_new = do_quit,
.mhandler.cmd_new = qmp_marshal_input_quit,
},
SQMP
@ -181,10 +178,7 @@ EQMP
{
.name = "stop",
.args_type = "",
.params = "",
.help = "stop emulation",
.user_print = monitor_user_noop,
.mhandler.cmd_new = do_stop,
.mhandler.cmd_new = qmp_marshal_input_stop,
},
SQMP
@ -229,10 +223,7 @@ EQMP
{
.name = "system_reset",
.args_type = "",
.params = "",
.help = "reset the system",
.user_print = monitor_user_noop,
.mhandler.cmd_new = do_system_reset,
.mhandler.cmd_new = qmp_marshal_input_system_reset,
},
SQMP
@ -1053,6 +1044,12 @@ Example:
EQMP
{
.name = "query-version",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_input_query_version,
},
SQMP
query-commands
--------------
@ -1084,6 +1081,12 @@ Note: This example has been shortened as the real response is too long.
EQMP
{
.name = "query-commands",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_input_query_commands,
},
SQMP
query-chardev
-------------
@ -1114,6 +1117,12 @@ Example:
EQMP
{
.name = "query-chardev",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_input_query_chardev,
},
SQMP
query-block
-----------
@ -1564,6 +1573,12 @@ Example:
EQMP
{
.name = "query-kvm",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_input_query_kvm,
},
SQMP
query-status
------------
@ -1597,6 +1612,12 @@ Example:
<- { "return": { "running": true, "singlestep": false, "status": "running" } }
EQMP
{
.name = "query-status",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_input_query_status,
},
SQMP
query-mice
@ -1780,6 +1801,12 @@ Example:
EQMP
{
.name = "query-name",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_input_query_name,
},
SQMP
query-uuid
----------
@ -1797,6 +1824,12 @@ Example:
EQMP
{
.name = "query-uuid",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_input_query_uuid,
},
SQMP
query-migrate
-------------

92
qmp.c Normal file
View File

@ -0,0 +1,92 @@
/*
* QEMU Management Protocol
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
*/
#include "qemu-common.h"
#include "sysemu.h"
#include "qmp-commands.h"
#include "kvm.h"
#include "arch_init.h"
NameInfo *qmp_query_name(Error **errp)
{
NameInfo *info = g_malloc0(sizeof(*info));
if (qemu_name) {
info->has_name = true;
info->name = g_strdup(qemu_name);
}
return info;
}
VersionInfo *qmp_query_version(Error **err)
{
VersionInfo *info = g_malloc0(sizeof(*info));
const char *version = QEMU_VERSION;
char *tmp;
info->qemu.major = strtol(version, &tmp, 10);
tmp++;
info->qemu.minor = strtol(tmp, &tmp, 10);
tmp++;
info->qemu.micro = strtol(tmp, &tmp, 10);
info->package = g_strdup(QEMU_PKGVERSION);
return info;
}
KvmInfo *qmp_query_kvm(Error **errp)
{
KvmInfo *info = g_malloc0(sizeof(*info));
info->enabled = kvm_enabled();
info->present = kvm_available();
return info;
}
UuidInfo *qmp_query_uuid(Error **errp)
{
UuidInfo *info = g_malloc0(sizeof(*info));
char uuid[64];
snprintf(uuid, sizeof(uuid), UUID_FMT, qemu_uuid[0], qemu_uuid[1],
qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], qemu_uuid[5],
qemu_uuid[6], qemu_uuid[7], qemu_uuid[8], qemu_uuid[9],
qemu_uuid[10], qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
qemu_uuid[14], qemu_uuid[15]);
info->UUID = g_strdup(uuid);
return info;
}
void qmp_quit(Error **err)
{
no_shutdown = 0;
qemu_system_shutdown_request();
}
void qmp_stop(Error **errp)
{
vm_stop(RUN_STATE_PAUSED);
}
void qmp_system_reset(Error **errp)
{
qemu_system_reset_request();
}
void qmp_system_powerdown(Error **erp)
{
qemu_system_powerdown_request();
}

View File

@ -1603,7 +1603,7 @@ static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
int ret;
saved_vm_running = runstate_is_running();
vm_stop(RSTATE_SAVEVM);
vm_stop(RUN_STATE_SAVE_VM);
if (qemu_savevm_state_blocked(mon)) {
ret = -EINVAL;
@ -1932,7 +1932,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
}
saved_vm_running = runstate_is_running();
vm_stop(RSTATE_SAVEVM);
vm_stop(RUN_STATE_SAVE_VM);
memset(sn, 0, sizeof(*sn));

View File

@ -17,12 +17,18 @@
import getopt
import errno
def type_visitor(name):
if type(name) == list:
return 'visit_type_%sList' % name[0]
else:
return 'visit_type_%s' % name
def generate_decl_enum(name, members, genlist=True):
return mcgen('''
void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp);
void %(visitor)s(Visitor *m, %(name)s * obj, const char *name, Error **errp);
''',
name=name)
visitor=type_visitor(name))
def generate_command_decl(name, args, ret_type):
arglist=""
@ -146,9 +152,10 @@ def gen_visitor_input_block(args, obj, dealloc=False):
c_name=c_var(argname), name=argname)
push_indent()
ret += mcgen('''
visit_type_%(argtype)s(v, &%(c_name)s, "%(name)s", errp);
%(visitor)s(v, &%(c_name)s, "%(name)s", errp);
''',
c_name=c_var(argname), name=argname, argtype=argtype)
c_name=c_var(argname), name=argname, argtype=argtype,
visitor=type_visitor(argtype))
if optional:
pop_indent()
ret += mcgen('''
@ -167,9 +174,10 @@ def gen_visitor_input_block(args, obj, dealloc=False):
pop_indent()
return ret.rstrip()
def gen_marshal_output(name, args, ret_type):
def gen_marshal_output(name, args, ret_type, middle_mode):
if not ret_type:
return ""
ret = mcgen('''
static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp)
{
@ -178,26 +186,44 @@ def gen_marshal_output(name, args, ret_type):
Visitor *v;
v = qmp_output_get_visitor(mo);
visit_type_%(ret_type)s(v, &ret_in, "unused", errp);
%(visitor)s(v, &ret_in, "unused", errp);
if (!error_is_set(errp)) {
*ret_out = qmp_output_get_qobject(mo);
}
qmp_output_visitor_cleanup(mo);
v = qapi_dealloc_get_visitor(md);
visit_type_%(ret_type)s(v, &ret_in, "unused", errp);
%(visitor)s(v, &ret_in, "unused", errp);
qapi_dealloc_visitor_cleanup(md);
}
''',
c_ret_type=c_type(ret_type), c_name=c_var(name), ret_type=ret_type)
c_ret_type=c_type(ret_type), c_name=c_var(name),
visitor=type_visitor(ret_type))
return ret
def gen_marshal_input(name, args, ret_type):
def gen_marshal_input_decl(name, args, ret_type, middle_mode):
if middle_mode:
return 'int qmp_marshal_input_%s(Monitor *mon, const QDict *qdict, QObject **ret)' % c_var(name)
else:
return 'static void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_var(name)
def gen_marshal_input(name, args, ret_type, middle_mode):
hdr = gen_marshal_input_decl(name, args, ret_type, middle_mode)
ret = mcgen('''
static void qmp_marshal_input_%(c_name)s(QDict *args, QObject **ret, Error **errp)
%(header)s
{
''',
c_name=c_var(name))
header=hdr)
if middle_mode:
ret += mcgen('''
Error *local_err = NULL;
Error **errp = &local_err;
QDict *args = (QDict *)qdict;
''')
if ret_type:
if c_type(ret_type).endswith("*"):
@ -220,6 +246,10 @@ def gen_marshal_input(name, args, ret_type):
visitor_input_containers_decl=gen_visitor_input_containers_decl(args),
visitor_input_vars_decl=gen_visitor_input_vars_decl(args),
visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)"))
else:
ret += mcgen('''
(void)args;
''')
ret += mcgen('''
if (error_is_set(errp)) {
@ -234,10 +264,29 @@ def gen_marshal_input(name, args, ret_type):
''')
ret += mcgen('''
%(visitor_input_block_cleanup)s
return;
}
''',
visitor_input_block_cleanup=gen_visitor_input_block(args, None, dealloc=True))
visitor_input_block_cleanup=gen_visitor_input_block(args, None,
dealloc=True))
if middle_mode:
ret += mcgen('''
if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return -1;
}
return 0;
''')
else:
ret += mcgen('''
return;
''')
ret += mcgen('''
}
''')
return ret
def gen_registry(commands):
@ -284,7 +333,7 @@ def gen_command_decl_prologue(header, guard, prefix=""):
#include "error.h"
''',
header=basename(h_file), guard=guardname(h_file), prefix=prefix)
header=basename(header), guard=guardname(header), prefix=prefix)
return ret
def gen_command_def_prologue(prefix="", proxy=False):
@ -317,11 +366,11 @@ def gen_command_def_prologue(prefix="", proxy=False):
prefix=prefix)
if not proxy:
ret += '#include "%sqmp-commands.h"' % prefix
return ret + "\n"
return ret + "\n\n"
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", "output-dir=", "type="])
opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:m", ["prefix=", "output-dir=", "type=", "middle"])
except getopt.GetoptError, err:
print str(err)
sys.exit(1)
@ -331,6 +380,7 @@ def gen_command_def_prologue(prefix="", proxy=False):
dispatch_type = "sync"
c_file = 'qmp-marshal.c'
h_file = 'qmp-commands.h'
middle_mode = False
for o, a in opts:
if o in ("-p", "--prefix"):
@ -339,6 +389,8 @@ def gen_command_def_prologue(prefix="", proxy=False):
output_dir = a + "/"
elif o in ("-t", "--type"):
dispatch_type = a
elif o in ("-m", "--middle"):
middle_mode = True
c_file = output_dir + prefix + c_file
h_file = output_dir + prefix + h_file
@ -370,14 +422,20 @@ def gen_command_def_prologue(prefix="", proxy=False):
ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
fdecl.write(ret)
if ret_type:
ret = gen_marshal_output(cmd['command'], arglist, ret_type) + "\n"
ret = gen_marshal_output(cmd['command'], arglist, ret_type, middle_mode) + "\n"
fdef.write(ret)
ret = gen_marshal_input(cmd['command'], arglist, ret_type) + "\n"
if middle_mode:
fdecl.write('%s;\n' % gen_marshal_input_decl(cmd['command'], arglist, ret_type, middle_mode))
ret = gen_marshal_input(cmd['command'], arglist, ret_type, middle_mode) + "\n"
fdef.write(ret)
fdecl.write("\n#endif\n");
ret = gen_registry(commands)
fdef.write(ret)
if not middle_mode:
ret = gen_registry(commands)
fdef.write(ret)
fdef.flush()
fdef.close()

View File

@ -70,7 +70,7 @@ def generate_enum_lookup(name, values):
ret += mcgen('''
"%(value)s",
''',
value=c_var(value).lower())
value=value.lower())
ret += mcgen('''
NULL,
@ -91,8 +91,11 @@ def generate_enum(name, values):
''',
name=name)
# append automatically generated _MAX value
enum_values = values + [ 'MAX' ]
i = 0
for value in values:
for value in enum_values:
enum_decl += mcgen('''
%(abbrev)s_%(value)s = %(i)d,
''',
@ -254,6 +257,8 @@ def generate_type_cleanup(name):
ret = "\n"
if expr.has_key('type'):
ret += generate_struct(expr['type'], "", expr['data']) + "\n"
ret += generate_type_cleanup_decl(expr['type'] + "List")
fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n")
ret += generate_type_cleanup_decl(expr['type'])
fdef.write(generate_type_cleanup(expr['type']) + "\n")
elif expr.has_key('union'):
@ -268,3 +273,6 @@ def generate_type_cleanup(name):
fdecl.flush()
fdecl.close()
fdef.flush()
fdef.close()

View File

@ -79,11 +79,11 @@ def generate_visit_list(name, members):
void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp)
{
GenericList *i;
GenericList *i, **head = (GenericList **)obj;
visit_start_list(m, name, errp);
for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) {
for (*head = i = visit_next_list(m, head, errp); i; i = visit_next_list(m, &i, errp)) {
%(name)sList *native_i = (%(name)sList *)i;
visit_type_%(name)s(m, &native_i->value, NULL, errp);
}

View File

@ -200,4 +200,6 @@ def basename(filename):
return filename.split("/")[-1]
def guardname(filename):
return filename.replace("/", "_").replace("-", "_").split(".")[0].upper()
if filename.startswith('./'):
filename = filename[2:]
return filename.replace("/", "_").replace("-", "_").split(".")[0].upper() + '_H'

View File

@ -6,28 +6,11 @@
#include "qemu-option.h"
#include "qemu-queue.h"
#include "qemu-timer.h"
#include "qapi-types.h"
#include "notify.h"
/* vl.c */
typedef enum {
RSTATE_NO_STATE,
RSTATE_DEBUG, /* qemu is running under gdb */
RSTATE_IN_MIGRATE, /* paused waiting for an incoming migration */
RSTATE_PANICKED, /* paused due to an internal error */
RSTATE_IO_ERROR, /* paused due to an I/O error */
RSTATE_PAUSED, /* paused by the user (ie. the 'stop' command) */
RSTATE_POST_MIGRATE, /* paused following a successful migration */
RSTATE_PRE_LAUNCH, /* qemu was started with -S and haven't started */
RSTATE_PRE_MIGRATE, /* paused preparing to finish migrate */
RSTATE_RESTORE, /* paused restoring the VM state */
RSTATE_RUNNING, /* qemu is running */
RSTATE_SAVEVM, /* paused saving VM state */
RSTATE_SHUTDOWN, /* guest shut down and -no-shutdown is in use */
RSTATE_WATCHDOG, /* watchdog fired and qemu is configured to pause */
RSTATE_MAX
} RunState;
extern const char *bios_name;
extern const char *qemu_name;
@ -39,7 +22,6 @@ void runstate_init(void);
bool runstate_check(RunState state);
void runstate_set(RunState new_state);
int runstate_is_running(void);
const char *runstate_as_string(void);
typedef struct vm_change_state_entry VMChangeStateEntry;
typedef void VMChangeStateHandler(void *opaque, int running, RunState state);

View File

@ -98,6 +98,34 @@ static void test_dispatch_cmd_io(void)
QDECREF(req);
}
/* test generated dealloc functions for generated types */
static void test_dealloc_types(void)
{
UserDefOne *ud1test, *ud1a, *ud1b;
UserDefOneList *ud1list;
ud1test = g_malloc0(sizeof(UserDefOne));
ud1test->integer = 42;
ud1test->string = g_strdup("hi there 42");
qapi_free_UserDefOne(ud1test);
ud1a = g_malloc0(sizeof(UserDefOne));
ud1a->integer = 43;
ud1a->string = g_strdup("hi there 43");
ud1b = g_malloc0(sizeof(UserDefOne));
ud1b->integer = 44;
ud1b->string = g_strdup("hi there 44");
ud1list = g_malloc0(sizeof(UserDefOneList));
ud1list->value = ud1a;
ud1list->next = g_malloc0(sizeof(UserDefOneList));
ud1list->next->value = ud1b;
qapi_free_UserDefOneList(ud1list);
}
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
@ -105,6 +133,7 @@ int main(int argc, char **argv)
g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd);
g_test_add_func("/0.15/dispatch_cmd_error", test_dispatch_cmd_error);
g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io);
g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
module_call_init(MODULE_INIT_QAPI);
g_test_run();

View File

@ -27,11 +27,11 @@ static void visit_type_TestStruct(Visitor *v, TestStruct **obj, const char *name
static void visit_type_TestStructList(Visitor *m, TestStructList ** obj, const char *name, Error **errp)
{
GenericList *i;
GenericList *i, **head = (GenericList **)obj;
visit_start_list(m, name, errp);
for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) {
for (*head = i = visit_next_list(m, head, errp); i; i = visit_next_list(m, &i, errp)) {
TestStructList *native_i = (TestStructList *)i;
visit_type_TestStruct(m, &native_i->value, NULL, errp);
}
@ -50,6 +50,8 @@ static void test_visitor_core(void)
TestStructList *lts = NULL;
Error *err = NULL;
QObject *obj;
QList *qlist;
QDict *qdict;
QString *str;
int64_t value = 0;
@ -96,7 +98,9 @@ static void test_visitor_core(void)
g_assert(pts->y == 84);
qobject_decref(obj);
g_free(pts);
/* test list input visitor */
obj = qobject_from_json("[{'x': 42, 'y': 84}, {'x': 12, 'y': 24}]");
mi = qmp_input_visitor_new(obj);
v = qmp_input_get_visitor(mi);
@ -110,14 +114,41 @@ static void test_visitor_core(void)
g_assert(lts->value->x == 42);
g_assert(lts->value->y == 84);
lts = lts->next;
g_assert(lts != NULL);
g_assert(lts->value->x == 12);
g_assert(lts->value->y == 24);
g_assert(lts->next == NULL);
g_assert(lts->next != NULL);
g_assert(lts->next->value->x == 12);
g_assert(lts->next->value->y == 24);
g_assert(lts->next->next == NULL);
qobject_decref(obj);
/* test list output visitor */
mo = qmp_output_visitor_new();
v = qmp_output_get_visitor(mo);
visit_type_TestStructList(v, &lts, NULL, &err);
if (err) {
g_error("%s", error_get_pretty(err));
}
obj = qmp_output_get_qobject(mo);
g_print("obj: %s\n", qstring_get_str(qobject_to_json(obj)));
qlist = qobject_to_qlist(obj);
assert(qlist);
obj = qlist_pop(qlist);
qdict = qobject_to_qdict(obj);
assert(qdict);
assert(qdict_get_int(qdict, "x") == 42);
assert(qdict_get_int(qdict, "y") == 84);
qobject_decref(obj);
obj = qlist_pop(qlist);
qdict = qobject_to_qdict(obj);
assert(qdict);
assert(qdict_get_int(qdict, "x") == 12);
assert(qdict_get_int(qdict, "y") == 24);
qobject_decref(obj);
qmp_output_visitor_cleanup(mo);
QDECREF(qlist);
}
/* test deep nesting with refs to other user-defined types */
@ -286,7 +317,8 @@ static void test_nested_enums(void)
g_assert(nested_enums_cpy->has_enum2 == false);
g_assert(nested_enums_cpy->has_enum4 == true);
qobject_decref(obj);
qmp_output_visitor_cleanup(mo);
qmp_input_visitor_cleanup(mi);
qapi_free_NestedEnumsOne(nested_enums);
qapi_free_NestedEnumsOne(nested_enums_cpy);
}

137
vl.c
View File

@ -147,6 +147,7 @@ int main(int argc, char **argv)
#include "qemu-config.h"
#include "qemu-objects.h"
#include "qemu-options.h"
#include "qmp-commands.h"
#ifdef CONFIG_VIRTFS
#include "fsdev/qemu-fsdev.h"
#endif
@ -323,7 +324,7 @@ static int default_driver_check(QemuOpts *opts, void *opaque)
/***********************************************************/
/* QEMU state */
static RunState current_run_state = RSTATE_NO_STATE;
static RunState current_run_state = RUN_STATE_PRELAUNCH;
typedef struct {
RunState from;
@ -332,67 +333,48 @@ typedef struct {
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 },
{ RUN_STATE_DEBUG, RUN_STATE_RUNNING },
{ RSTATE_DEBUG, RSTATE_RUNNING },
{ RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
{ RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH },
{ RSTATE_IN_MIGRATE, RSTATE_RUNNING },
{ RSTATE_IN_MIGRATE, RSTATE_PRE_LAUNCH },
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
{ RSTATE_PANICKED, RSTATE_PAUSED },
{ RUN_STATE_IO_ERROR, RUN_STATE_RUNNING },
{ RSTATE_IO_ERROR, RSTATE_RUNNING },
{ RUN_STATE_PAUSED, RUN_STATE_RUNNING },
{ RSTATE_PAUSED, RSTATE_RUNNING },
{ RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
{ RSTATE_POST_MIGRATE, RSTATE_RUNNING },
{ RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING },
{ RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
{ RUN_STATE_PRELAUNCH, RUN_STATE_POSTMIGRATE },
{ RSTATE_PRE_LAUNCH, RSTATE_RUNNING },
{ RSTATE_PRE_LAUNCH, RSTATE_POST_MIGRATE },
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
{ RSTATE_PRE_MIGRATE, RSTATE_RUNNING },
{ RSTATE_PRE_MIGRATE, RSTATE_POST_MIGRATE },
{ RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
{ RSTATE_RESTORE, RSTATE_RUNNING },
{ RUN_STATE_RUNNING, RUN_STATE_DEBUG },
{ RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR },
{ RUN_STATE_RUNNING, RUN_STATE_IO_ERROR },
{ RUN_STATE_RUNNING, RUN_STATE_PAUSED },
{ RUN_STATE_RUNNING, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_RUNNING, RUN_STATE_RESTORE_VM },
{ RUN_STATE_RUNNING, RUN_STATE_SAVE_VM },
{ RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN },
{ RUN_STATE_RUNNING, RUN_STATE_WATCHDOG },
{ 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 },
{ RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
{ RSTATE_SAVEVM, RSTATE_RUNNING },
{ RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
{ RSTATE_SHUTDOWN, RSTATE_PAUSED },
{ RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
{ RSTATE_WATCHDOG, RSTATE_RUNNING },
{ RSTATE_MAX, RSTATE_MAX },
{ RUN_STATE_MAX, RUN_STATE_MAX },
};
static bool runstate_valid_transitions[RSTATE_MAX][RSTATE_MAX];
static const char *const runstate_name_tbl[RSTATE_MAX] = {
[RSTATE_DEBUG] = "debug",
[RSTATE_IN_MIGRATE] = "incoming-migration",
[RSTATE_PANICKED] = "internal-error",
[RSTATE_IO_ERROR] = "io-error",
[RSTATE_PAUSED] = "paused",
[RSTATE_POST_MIGRATE] = "post-migrate",
[RSTATE_PRE_LAUNCH] = "prelaunch",
[RSTATE_PRE_MIGRATE] = "finish-migrate",
[RSTATE_RESTORE] = "restore-vm",
[RSTATE_RUNNING] = "running",
[RSTATE_SAVEVM] = "save-vm",
[RSTATE_SHUTDOWN] = "shutdown",
[RSTATE_WATCHDOG] = "watchdog",
};
static bool runstate_valid_transitions[RUN_STATE_MAX][RUN_STATE_MAX];
bool runstate_check(RunState state)
{
@ -405,7 +387,7 @@ void runstate_init(void)
memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
for (p = &runstate_transitions_def[0]; p->from != RSTATE_MAX; p++) {
for (p = &runstate_transitions_def[0]; p->from != RUN_STATE_MAX; p++) {
runstate_valid_transitions[p->from][p->to] = true;
}
}
@ -413,7 +395,7 @@ void runstate_init(void)
/* This function will abort() on invalid state transitions */
void runstate_set(RunState new_state)
{
if (new_state >= RSTATE_MAX ||
if (new_state >= RUN_STATE_MAX ||
!runstate_valid_transitions[current_run_state][new_state]) {
fprintf(stderr, "invalid runstate transition\n");
abort();
@ -422,16 +404,20 @@ void runstate_set(RunState new_state)
current_run_state = new_state;
}
const char *runstate_as_string(void)
{
assert(current_run_state > RSTATE_NO_STATE &&
current_run_state < RSTATE_MAX);
return runstate_name_tbl[current_run_state];
}
int runstate_is_running(void)
{
return runstate_check(RSTATE_RUNNING);
return runstate_check(RUN_STATE_RUNNING);
}
StatusInfo *qmp_query_status(Error **errp)
{
StatusInfo *info = g_malloc0(sizeof(*info));
info->running = runstate_is_running();
info->singlestep = singlestep;
info->status = current_run_state;
return info;
}
/***********************************************************/
@ -1272,8 +1258,8 @@ void vm_start(void)
{
if (!runstate_is_running()) {
cpu_enable_ticks();
runstate_set(RSTATE_RUNNING);
vm_state_notify(1, RSTATE_RUNNING);
runstate_set(RUN_STATE_RUNNING);
vm_state_notify(1, RUN_STATE_RUNNING);
resume_all_vcpus();
monitor_protocol_event(QEVENT_RESUME, NULL);
}
@ -1294,7 +1280,7 @@ static int shutdown_requested, shutdown_signal = -1;
static pid_t shutdown_pid;
static int powerdown_requested;
static int debug_requested;
static RunState vmstop_requested = RSTATE_NO_STATE;
static RunState vmstop_requested = RUN_STATE_MAX;
int qemu_shutdown_requested_get(void)
{
@ -1350,11 +1336,16 @@ static int qemu_debug_requested(void)
return r;
}
static RunState qemu_vmstop_requested(void)
/* We use RUN_STATE_MAX but any invalid value will do */
static bool qemu_vmstop_requested(RunState *r)
{
RunState s = vmstop_requested;
vmstop_requested = RSTATE_NO_STATE;
return s;
if (vmstop_requested < RUN_STATE_MAX) {
*r = vmstop_requested;
vmstop_requested = RUN_STATE_MAX;
return true;
}
return false;
}
void qemu_register_reset(QEMUResetHandler *func, void *opaque)
@ -1567,7 +1558,7 @@ static void main_loop(void)
#ifdef CONFIG_PROFILER
int64_t ti;
#endif
int r;
RunState r;
qemu_main_loop_start();
@ -1582,13 +1573,13 @@ static void main_loop(void)
#endif
if (qemu_debug_requested()) {
vm_stop(RSTATE_DEBUG);
vm_stop(RUN_STATE_DEBUG);
}
if (qemu_shutdown_requested()) {
qemu_kill_report();
monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
if (no_shutdown) {
vm_stop(RSTATE_SHUTDOWN);
vm_stop(RUN_STATE_SHUTDOWN);
} else
break;
}
@ -1597,16 +1588,16 @@ static void main_loop(void)
cpu_synchronize_all_states();
qemu_system_reset(VMRESET_REPORT);
resume_all_vcpus();
if (runstate_check(RSTATE_PANICKED) ||
runstate_check(RSTATE_SHUTDOWN)) {
runstate_set(RSTATE_PAUSED);
if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
runstate_check(RUN_STATE_SHUTDOWN)) {
runstate_set(RUN_STATE_PAUSED);
}
}
if (qemu_powerdown_requested()) {
monitor_protocol_event(QEVENT_POWERDOWN, NULL);
qemu_irq_raise(qemu_system_powerdown);
}
if ((r = qemu_vmstop_requested())) {
if (qemu_vmstop_requested(&r)) {
vm_stop(r);
}
}
@ -3556,7 +3547,7 @@ int main(int argc, char **argv, char **envp)
}
if (incoming) {
runstate_set(RSTATE_IN_MIGRATE);
runstate_set(RUN_STATE_INMIGRATE);
int ret = qemu_start_incoming_migration(incoming);
if (ret < 0) {
fprintf(stderr, "Migration failed. Exit code %s(%d), exiting.\n",
@ -3565,8 +3556,6 @@ int main(int argc, char **argv, char **envp)
}
} else if (autostart) {
vm_start();
} else {
runstate_set(RSTATE_PRE_LAUNCH);
}
os_setup_post();