mirror of https://gitee.com/openkylin/qemu.git
Merge remote-tracking branch 'qmp/queue/qmp' into staging
This commit is contained in:
commit
ebffe2afce
12
Makefile
12
Makefile
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
4
error.c
4
error.c
|
@ -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': '");
|
||||
|
|
26
gdbstub.c
26
gdbstub.c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
281
monitor.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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' }
|
|
@ -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,
|
||||
|
|
|
@ -17,4 +17,7 @@
|
|||
#include "qemu-common.h"
|
||||
#include "error.h"
|
||||
|
||||
/* FIXME this is temporary until we remove middle mode */
|
||||
#include "monitor.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
35
qemu-char.c
35
qemu-char.c
|
@ -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)
|
||||
|
|
33
qerror.c
33
qerror.c
|
@ -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
|
||||
*/
|
||||
|
|
2
qerror.h
2
qerror.h
|
@ -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__)
|
||||
|
|
|
@ -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
|
||||
-------------
|
||||
|
|
|
@ -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();
|
||||
}
|
4
savevm.c
4
savevm.c
|
@ -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));
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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'
|
||||
|
|
20
sysemu.h
20
sysemu.h
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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, <s, 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
137
vl.c
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue