mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'qmp/queue/qmp' into staging
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
+3
-3
@@ -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
|
||||
|
||||
@@ -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': '");
|
||||
|
||||
@@ -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
|
||||
|
||||
+4
-7
@@ -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
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+1
-1
@@ -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:
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+3
-3
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user