mirror of https://github.com/xemu-project/xemu.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)
|
ifeq ($(TRACE_BACKEND),dtrace)
|
||||||
GENERATED_HEADERS += trace-dtrace.h
|
GENERATED_HEADERS += trace-dtrace.h
|
||||||
endif
|
endif
|
||||||
|
GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
|
||||||
|
|
||||||
ifneq ($(wildcard config-host.mak),)
|
ifneq ($(wildcard config-host.mak),)
|
||||||
# Put the all: rule here so that config-host.mak can contain dependencies.
|
# 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.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
|
$(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 $@")
|
$(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
|
$(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 $@")
|
$(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.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
|
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-nested-y += qmp-registry.o qmp-dispatch.o
|
||||||
qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
|
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
|
# guest agent
|
||||||
|
|
||||||
|
|
|
@ -376,7 +376,7 @@ obj-xtensa-y += xtensa-semi.o
|
||||||
|
|
||||||
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
|
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)
|
$(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
|
hmp-commands.h: $(SRC_PATH)/hmp-commands.hx
|
||||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
|
$(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)$@")
|
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
|
rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
|
||||||
rm -f *.d */*.d tcg/*.o ide/*.o 9pfs/*.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
|
ifdef CONFIG_TRACE_SYSTEMTAP
|
||||||
rm -f *.stp
|
rm -f *.stp
|
||||||
endif
|
endif
|
||||||
|
|
4
error.c
4
error.c
|
@ -97,6 +97,10 @@ bool error_is_type(Error *err, const char *fmt)
|
||||||
char *ptr;
|
char *ptr;
|
||||||
char *end;
|
char *end;
|
||||||
|
|
||||||
|
if (!err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ptr = strstr(fmt, "'class': '");
|
ptr = strstr(fmt, "'class': '");
|
||||||
assert(ptr != NULL);
|
assert(ptr != NULL);
|
||||||
ptr += strlen("'class': '");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case RSTATE_DEBUG:
|
case RUN_STATE_DEBUG:
|
||||||
if (env->watchpoint_hit) {
|
if (env->watchpoint_hit) {
|
||||||
switch (env->watchpoint_hit->flags & BP_MEM_ACCESS) {
|
switch (env->watchpoint_hit->flags & BP_MEM_ACCESS) {
|
||||||
case BP_MEM_READ:
|
case BP_MEM_READ:
|
||||||
|
@ -2408,25 +2408,25 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
|
||||||
tb_flush(env);
|
tb_flush(env);
|
||||||
ret = GDB_SIGNAL_TRAP;
|
ret = GDB_SIGNAL_TRAP;
|
||||||
break;
|
break;
|
||||||
case RSTATE_PAUSED:
|
case RUN_STATE_PAUSED:
|
||||||
ret = GDB_SIGNAL_INT;
|
ret = GDB_SIGNAL_INT;
|
||||||
break;
|
break;
|
||||||
case RSTATE_SHUTDOWN:
|
case RUN_STATE_SHUTDOWN:
|
||||||
ret = GDB_SIGNAL_QUIT;
|
ret = GDB_SIGNAL_QUIT;
|
||||||
break;
|
break;
|
||||||
case RSTATE_IO_ERROR:
|
case RUN_STATE_IO_ERROR:
|
||||||
ret = GDB_SIGNAL_IO;
|
ret = GDB_SIGNAL_IO;
|
||||||
break;
|
break;
|
||||||
case RSTATE_WATCHDOG:
|
case RUN_STATE_WATCHDOG:
|
||||||
ret = GDB_SIGNAL_ALRM;
|
ret = GDB_SIGNAL_ALRM;
|
||||||
break;
|
break;
|
||||||
case RSTATE_PANICKED:
|
case RUN_STATE_INTERNAL_ERROR:
|
||||||
ret = GDB_SIGNAL_ABRT;
|
ret = GDB_SIGNAL_ABRT;
|
||||||
break;
|
break;
|
||||||
case RSTATE_SAVEVM:
|
case RUN_STATE_SAVE_VM:
|
||||||
case RSTATE_RESTORE:
|
case RUN_STATE_RESTORE_VM:
|
||||||
return;
|
return;
|
||||||
case RSTATE_PRE_MIGRATE:
|
case RUN_STATE_FINISH_MIGRATE:
|
||||||
ret = GDB_SIGNAL_XCPU;
|
ret = GDB_SIGNAL_XCPU;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -2463,7 +2463,7 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
|
||||||
gdb_current_syscall_cb = cb;
|
gdb_current_syscall_cb = cb;
|
||||||
s->state = RS_SYSCALL;
|
s->state = RS_SYSCALL;
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
vm_stop(RSTATE_DEBUG);
|
vm_stop(RUN_STATE_DEBUG);
|
||||||
#endif
|
#endif
|
||||||
s->state = RS_IDLE;
|
s->state = RS_IDLE;
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
|
@ -2537,7 +2537,7 @@ static void gdb_read_byte(GDBState *s, int ch)
|
||||||
if (runstate_is_running()) {
|
if (runstate_is_running()) {
|
||||||
/* when the CPU is running, we cannot do anything except stop
|
/* when the CPU is running, we cannot do anything except stop
|
||||||
it when receiving a char */
|
it when receiving a char */
|
||||||
vm_stop(RSTATE_PAUSED);
|
vm_stop(RUN_STATE_PAUSED);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
@ -2799,7 +2799,7 @@ static void gdb_chr_event(void *opaque, int event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case CHR_EVENT_OPENED:
|
case CHR_EVENT_OPENED:
|
||||||
vm_stop(RSTATE_PAUSED);
|
vm_stop(RUN_STATE_PAUSED);
|
||||||
gdb_has_xml = 0;
|
gdb_has_xml = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
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)
|
static void gdb_sigterm_handler(int signal)
|
||||||
{
|
{
|
||||||
if (runstate_is_running()) {
|
if (runstate_is_running()) {
|
||||||
vm_stop(RSTATE_PAUSED);
|
vm_stop(RUN_STATE_PAUSED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,7 +43,7 @@ ETEXI
|
||||||
.params = "",
|
.params = "",
|
||||||
.help = "quit the emulator",
|
.help = "quit the emulator",
|
||||||
.user_print = monitor_user_noop,
|
.user_print = monitor_user_noop,
|
||||||
.mhandler.cmd_new = do_quit,
|
.mhandler.cmd = hmp_quit,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
|
@ -290,8 +290,7 @@ ETEXI
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
.params = "",
|
.params = "",
|
||||||
.help = "stop emulation",
|
.help = "stop emulation",
|
||||||
.user_print = monitor_user_noop,
|
.mhandler.cmd = hmp_stop,
|
||||||
.mhandler.cmd_new = do_stop,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
|
@ -478,8 +477,7 @@ ETEXI
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
.params = "",
|
.params = "",
|
||||||
.help = "reset the system",
|
.help = "reset the system",
|
||||||
.user_print = monitor_user_noop,
|
.mhandler.cmd = hmp_system_reset,
|
||||||
.mhandler.cmd_new = do_system_reset,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
|
@ -494,8 +492,7 @@ ETEXI
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
.params = "",
|
.params = "",
|
||||||
.help = "send system power down event",
|
.help = "send system power down event",
|
||||||
.user_print = monitor_user_noop,
|
.mhandler.cmd = hmp_system_powerdown,
|
||||||
.mhandler.cmd_new = do_system_powerdown,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
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->dma->ops->set_unit(s->bus->dma, s->unit);
|
||||||
s->bus->error_status = op;
|
s->bus->error_status = op;
|
||||||
bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
|
bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
|
||||||
vm_stop(RSTATE_IO_ERROR);
|
vm_stop(RUN_STATE_IO_ERROR);
|
||||||
} else {
|
} else {
|
||||||
if (op & BM_STATUS_DMA_RETRY) {
|
if (op & BM_STATUS_DMA_RETRY) {
|
||||||
dma_buf_commit(s, 0);
|
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;
|
r->status |= SCSI_REQ_STATUS_RETRY | type;
|
||||||
|
|
||||||
bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
|
bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
|
||||||
vm_stop(RSTATE_IO_ERROR);
|
vm_stop(RUN_STATE_IO_ERROR);
|
||||||
} else {
|
} else {
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case ENOMEM:
|
case ENOMEM:
|
||||||
|
|
|
@ -77,7 +77,7 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
|
||||||
req->next = s->rq;
|
req->next = s->rq;
|
||||||
s->rq = req;
|
s->rq = req;
|
||||||
bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
|
bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
|
||||||
vm_stop(RSTATE_IO_ERROR);
|
vm_stop(RUN_STATE_IO_ERROR);
|
||||||
} else {
|
} else {
|
||||||
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
|
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
|
||||||
bdrv_acct_done(s->bs, &req->acct);
|
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 */
|
case WDT_PAUSE: /* same as 'stop' command in monitor */
|
||||||
watchdog_mon_event("pause");
|
watchdog_mon_event("pause");
|
||||||
vm_stop(RSTATE_WATCHDOG);
|
vm_stop(RUN_STATE_WATCHDOG);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WDT_DEBUG:
|
case WDT_DEBUG:
|
||||||
|
|
|
@ -1014,7 +1014,7 @@ int kvm_cpu_exec(CPUState *env)
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
|
cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
|
||||||
vm_stop(RSTATE_PANICKED);
|
vm_stop(RUN_STATE_INTERNAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
env->exit_request = 0;
|
env->exit_request = 0;
|
||||||
|
|
|
@ -73,7 +73,7 @@ void process_incoming_migration(QEMUFile *f)
|
||||||
if (autostart) {
|
if (autostart) {
|
||||||
vm_start();
|
vm_start();
|
||||||
} else {
|
} 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();
|
int old_vm_running = runstate_is_running();
|
||||||
|
|
||||||
DPRINTF("done iterating\n");
|
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 ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
|
||||||
if (old_vm_running) {
|
if (old_vm_running) {
|
||||||
|
@ -392,7 +392,7 @@ void migrate_fd_put_ready(void *opaque)
|
||||||
state = MIG_STATE_ERROR;
|
state = MIG_STATE_ERROR;
|
||||||
}
|
}
|
||||||
if (state == MIG_STATE_COMPLETED) {
|
if (state == MIG_STATE_COMPLETED) {
|
||||||
runstate_set(RSTATE_POST_MIGRATE);
|
runstate_set(RUN_STATE_POSTMIGRATE);
|
||||||
}
|
}
|
||||||
s->state = state;
|
s->state = state;
|
||||||
notifier_list_notify(&migration_state_notifiers, NULL);
|
notifier_list_notify(&migration_state_notifiers, NULL);
|
||||||
|
|
281
monitor.c
281
monitor.c
|
@ -64,6 +64,8 @@
|
||||||
#endif
|
#endif
|
||||||
#include "ui/qemu-spice.h"
|
#include "ui/qemu-spice.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "qmp-commands.h"
|
||||||
|
#include "hmp.h"
|
||||||
|
|
||||||
//#define DEBUG
|
//#define DEBUG
|
||||||
//#define DEBUG_COMPLETION
|
//#define DEBUG_COMPLETION
|
||||||
|
@ -122,6 +124,7 @@ typedef struct mon_cmd_t {
|
||||||
int (*cmd_async)(Monitor *mon, const QDict *params,
|
int (*cmd_async)(Monitor *mon, const QDict *params,
|
||||||
MonitorCompletion *cb, void *opaque);
|
MonitorCompletion *cb, void *opaque);
|
||||||
} mhandler;
|
} mhandler;
|
||||||
|
bool qapi;
|
||||||
int flags;
|
int flags;
|
||||||
} mon_cmd_t;
|
} mon_cmd_t;
|
||||||
|
|
||||||
|
@ -730,105 +733,37 @@ help:
|
||||||
help_cmd(mon, "info");
|
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;
|
CommandInfoList *info;
|
||||||
QDict *qemu;
|
|
||||||
|
|
||||||
qdict = qobject_to_qdict(data);
|
info = g_malloc0(sizeof(*info));
|
||||||
qemu = qdict_get_qdict(qdict, "qemu");
|
info->value = g_malloc0(sizeof(*info->value));
|
||||||
|
info->value->name = g_strdup(cmd_name);
|
||||||
|
|
||||||
monitor_printf(mon, "%" PRId64 ".%" PRId64 ".%" PRId64 "%s\n",
|
return info;
|
||||||
qdict_get_int(qemu, "major"),
|
|
||||||
qdict_get_int(qemu, "minor"),
|
|
||||||
qdict_get_int(qemu, "micro"),
|
|
||||||
qdict_get_str(qdict, "package"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_info_version(Monitor *mon, QObject **ret_data)
|
CommandInfoList *qmp_query_commands(Error **errp)
|
||||||
{
|
{
|
||||||
const char *version = QEMU_VERSION;
|
CommandInfoList *info, *cmd_list = NULL;
|
||||||
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;
|
|
||||||
const mon_cmd_t *cmd;
|
const mon_cmd_t *cmd;
|
||||||
|
|
||||||
cmd_list = qlist_new();
|
|
||||||
|
|
||||||
for (cmd = qmp_cmds; cmd->name != NULL; cmd++) {
|
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++) {
|
for (cmd = qmp_query_cmds; cmd->name != NULL; cmd++) {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
snprintf(buf, sizeof(buf), "query-%s", cmd->name);
|
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);
|
return 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the current CPU defined by the user */
|
/* 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);
|
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
|
#ifdef CONFIG_VNC
|
||||||
static int change_vnc_password(const char *password)
|
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);
|
static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs);
|
||||||
|
|
||||||
struct bdrv_iterate_context {
|
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 };
|
struct bdrv_iterate_context context = { mon, 0 };
|
||||||
|
|
||||||
if (runstate_check(RSTATE_IN_MIGRATE)) {
|
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
||||||
qerror_report(QERR_MIGRATION_EXPECTED);
|
qerror_report(QERR_MIGRATION_EXPECTED);
|
||||||
return -1;
|
return -1;
|
||||||
} else if (runstate_check(RSTATE_PANICKED) ||
|
} else if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
|
||||||
runstate_check(RSTATE_SHUTDOWN)) {
|
runstate_check(RUN_STATE_SHUTDOWN)) {
|
||||||
qerror_report(QERR_RESET_REQUIRED);
|
qerror_report(QERR_RESET_REQUIRED);
|
||||||
return -1;
|
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
|
* 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);
|
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)
|
static void do_info_numa(Monitor *mon)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -2623,36 +2502,6 @@ static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
static qemu_acl *find_acl(Monitor *mon, const char *name)
|
||||||
{
|
{
|
||||||
qemu_acl *acl = qemu_acl_find(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();
|
int saved_vm_running = runstate_is_running();
|
||||||
const char *name = qdict_get_str(qdict, "name");
|
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) {
|
if (load_vmstate(name) == 0 && saved_vm_running) {
|
||||||
vm_start();
|
vm_start();
|
||||||
|
@ -2889,8 +2738,7 @@ static const mon_cmd_t info_cmds[] = {
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
.params = "",
|
.params = "",
|
||||||
.help = "show the version of QEMU",
|
.help = "show the version of QEMU",
|
||||||
.user_print = do_info_version_print,
|
.mhandler.info = hmp_info_version,
|
||||||
.mhandler.info_new = do_info_version,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "network",
|
.name = "network",
|
||||||
|
@ -2904,8 +2752,7 @@ static const mon_cmd_t info_cmds[] = {
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
.params = "",
|
.params = "",
|
||||||
.help = "show the character devices",
|
.help = "show the character devices",
|
||||||
.user_print = qemu_chr_info_print,
|
.mhandler.info = hmp_info_chardev,
|
||||||
.mhandler.info_new = qemu_chr_info,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "block",
|
.name = "block",
|
||||||
|
@ -3005,8 +2852,7 @@ static const mon_cmd_t info_cmds[] = {
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
.params = "",
|
.params = "",
|
||||||
.help = "show KVM information",
|
.help = "show KVM information",
|
||||||
.user_print = do_info_kvm_print,
|
.mhandler.info = hmp_info_kvm,
|
||||||
.mhandler.info_new = do_info_kvm,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "numa",
|
.name = "numa",
|
||||||
|
@ -3055,8 +2901,7 @@ static const mon_cmd_t info_cmds[] = {
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
.params = "",
|
.params = "",
|
||||||
.help = "show the current VM status (running|paused)",
|
.help = "show the current VM status (running|paused)",
|
||||||
.user_print = do_info_status_print,
|
.mhandler.info = hmp_info_status,
|
||||||
.mhandler.info_new = do_info_status,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "pcmcia",
|
.name = "pcmcia",
|
||||||
|
@ -3096,16 +2941,14 @@ static const mon_cmd_t info_cmds[] = {
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
.params = "",
|
.params = "",
|
||||||
.help = "show the current VM name",
|
.help = "show the current VM name",
|
||||||
.user_print = do_info_name_print,
|
.mhandler.info = hmp_info_name,
|
||||||
.mhandler.info_new = do_info_name,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "uuid",
|
.name = "uuid",
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
.params = "",
|
.params = "",
|
||||||
.help = "show the current VM UUID",
|
.help = "show the current VM UUID",
|
||||||
.user_print = do_info_uuid_print,
|
.mhandler.info = hmp_info_uuid,
|
||||||
.mhandler.info_new = do_info_uuid,
|
|
||||||
},
|
},
|
||||||
#if defined(TARGET_PPC)
|
#if defined(TARGET_PPC)
|
||||||
{
|
{
|
||||||
|
@ -3185,35 +3028,11 @@ static const mon_cmd_t info_cmds[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const mon_cmd_t qmp_cmds[] = {
|
static const mon_cmd_t qmp_cmds[] = {
|
||||||
#include "qmp-commands.h"
|
#include "qmp-commands-old.h"
|
||||||
{ /* NULL */ },
|
{ /* NULL */ },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const mon_cmd_t qmp_query_cmds[] = {
|
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",
|
.name = "block",
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
|
@ -3246,22 +3065,6 @@ static const mon_cmd_t qmp_query_cmds[] = {
|
||||||
.user_print = do_pci_info_print,
|
.user_print = do_pci_info_print,
|
||||||
.mhandler.info_new = do_pci_info,
|
.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",
|
.name = "mice",
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
|
@ -3288,22 +3091,6 @@ static const mon_cmd_t qmp_query_cmds[] = {
|
||||||
.mhandler.info_new = do_info_spice,
|
.mhandler.info_new = do_info_spice,
|
||||||
},
|
},
|
||||||
#endif
|
#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",
|
.name = "migrate",
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
|
@ -5111,12 +4898,10 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strstart(cmd_name, "query-", &query_cmd)) {
|
|
||||||
cmd = qmp_find_query_cmd(query_cmd);
|
|
||||||
} else {
|
|
||||||
cmd = qmp_find_cmd(cmd_name);
|
cmd = qmp_find_cmd(cmd_name);
|
||||||
|
if (!cmd && strstart(cmd_name, "query-", &query_cmd)) {
|
||||||
|
cmd = qmp_find_query_cmd(query_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cmd) {
|
if (!cmd) {
|
||||||
qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
|
qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
@ -5215,9 +5000,9 @@ void monitor_resume(Monitor *mon)
|
||||||
|
|
||||||
static QObject *get_qmp_greeting(void)
|
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);
|
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
|
typedef struct StackEntry
|
||||||
{
|
{
|
||||||
void *value;
|
void *value;
|
||||||
|
bool is_list_head;
|
||||||
QTAILQ_ENTRY(StackEntry) node;
|
QTAILQ_ENTRY(StackEntry) node;
|
||||||
} StackEntry;
|
} StackEntry;
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ struct QapiDeallocVisitor
|
||||||
{
|
{
|
||||||
Visitor visitor;
|
Visitor visitor;
|
||||||
QTAILQ_HEAD(, StackEntry) stack;
|
QTAILQ_HEAD(, StackEntry) stack;
|
||||||
|
bool is_list_head;
|
||||||
};
|
};
|
||||||
|
|
||||||
static QapiDeallocVisitor *to_qov(Visitor *v)
|
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));
|
StackEntry *e = g_malloc0(sizeof(*e));
|
||||||
|
|
||||||
e->value = value;
|
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);
|
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)
|
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)
|
Error **errp)
|
||||||
{
|
{
|
||||||
GenericList *retval = *list;
|
GenericList *list = *listp;
|
||||||
g_free(retval->value);
|
QapiDeallocVisitor *qov = to_qov(v);
|
||||||
*list = retval->next;
|
StackEntry *e = QTAILQ_FIRST(&qov->stack);
|
||||||
return retval;
|
|
||||||
|
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)
|
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,
|
static void qapi_dealloc_type_str(Visitor *v, char **obj, const char *name,
|
||||||
|
|
|
@ -17,4 +17,7 @@
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
|
/* FIXME this is temporary until we remove middle mode */
|
||||||
|
#include "monitor.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -144,8 +144,6 @@ static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
|
||||||
}
|
}
|
||||||
(*list)->next = entry;
|
(*list)->next = entry;
|
||||||
}
|
}
|
||||||
*list = entry;
|
|
||||||
|
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
@ -240,9 +238,11 @@ static void qmp_input_type_enum(Visitor *v, int *obj, const char *strings[],
|
||||||
|
|
||||||
if (strings[value] == NULL) {
|
if (strings[value] == NULL) {
|
||||||
error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
|
error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
|
||||||
|
g_free(enum_str);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_free(enum_str);
|
||||||
*obj = value;
|
*obj = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
typedef struct QStackEntry
|
typedef struct QStackEntry
|
||||||
{
|
{
|
||||||
QObject *value;
|
QObject *value;
|
||||||
|
bool is_list_head;
|
||||||
QTAILQ_ENTRY(QStackEntry) node;
|
QTAILQ_ENTRY(QStackEntry) node;
|
||||||
} QStackEntry;
|
} QStackEntry;
|
||||||
|
|
||||||
|
@ -45,6 +46,9 @@ static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value)
|
||||||
QStackEntry *e = g_malloc0(sizeof(*e));
|
QStackEntry *e = g_malloc0(sizeof(*e));
|
||||||
|
|
||||||
e->value = value;
|
e->value = value;
|
||||||
|
if (qobject_type(e->value) == QTYPE_QLIST) {
|
||||||
|
e->is_list_head = true;
|
||||||
|
}
|
||||||
QTAILQ_INSERT_HEAD(&qov->stack, e, node);
|
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);
|
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)
|
Error **errp)
|
||||||
{
|
{
|
||||||
GenericList *retval = *list;
|
GenericList *list = *listp;
|
||||||
*list = retval->next;
|
QmpOutputVisitor *qov = to_qov(v);
|
||||||
return retval;
|
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)
|
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/usb.h"
|
||||||
#include "hw/baum.h"
|
#include "hw/baum.h"
|
||||||
#include "hw/msmouse.h"
|
#include "hw/msmouse.h"
|
||||||
#include "qemu-objects.h"
|
#include "qmp-commands.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -2650,35 +2650,22 @@ void qemu_chr_delete(CharDriverState *chr)
|
||||||
g_free(chr);
|
g_free(chr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qemu_chr_qlist_iter(QObject *obj, void *opaque)
|
ChardevInfoList *qmp_query_chardev(Error **errp)
|
||||||
{
|
{
|
||||||
QDict *chr_dict;
|
ChardevInfoList *chr_list = NULL;
|
||||||
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;
|
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
|
|
||||||
chr_list = qlist_new();
|
|
||||||
|
|
||||||
QTAILQ_FOREACH(chr, &chardevs, next) {
|
QTAILQ_FOREACH(chr, &chardevs, next) {
|
||||||
QObject *obj = qobject_from_jsonf("{ 'label': %s, 'filename': %s }",
|
ChardevInfoList *info = g_malloc0(sizeof(*info));
|
||||||
chr->label, chr->filename);
|
info->value = g_malloc0(sizeof(*info->value));
|
||||||
qlist_append_obj(chr_list, obj);
|
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)
|
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
|
* qobject_to_qerror(): Convert a QObject into a QError
|
||||||
*/
|
*/
|
||||||
|
|
2
qerror.h
2
qerror.h
|
@ -15,6 +15,7 @@
|
||||||
#include "qdict.h"
|
#include "qdict.h"
|
||||||
#include "qstring.h"
|
#include "qstring.h"
|
||||||
#include "qemu-error.h"
|
#include "qemu-error.h"
|
||||||
|
#include "error.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
typedef struct QErrorStringTable {
|
typedef struct QErrorStringTable {
|
||||||
|
@ -39,6 +40,7 @@ QString *qerror_human(const QError *qerror);
|
||||||
void qerror_print(QError *qerror);
|
void qerror_print(QError *qerror);
|
||||||
void qerror_report_internal(const char *file, int linenr, const char *func,
|
void qerror_report_internal(const char *file, int linenr, const char *func,
|
||||||
const char *fmt, ...) GCC_FMT_ATTR(4, 5);
|
const char *fmt, ...) GCC_FMT_ATTR(4, 5);
|
||||||
|
void qerror_report_err(Error *err);
|
||||||
QString *qerror_format(const char *fmt, QDict *error);
|
QString *qerror_format(const char *fmt, QDict *error);
|
||||||
#define qerror_report(fmt, ...) \
|
#define qerror_report(fmt, ...) \
|
||||||
qerror_report_internal(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__)
|
qerror_report_internal(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__)
|
||||||
|
|
|
@ -63,10 +63,7 @@ EQMP
|
||||||
{
|
{
|
||||||
.name = "quit",
|
.name = "quit",
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
.params = "",
|
.mhandler.cmd_new = qmp_marshal_input_quit,
|
||||||
.help = "quit the emulator",
|
|
||||||
.user_print = monitor_user_noop,
|
|
||||||
.mhandler.cmd_new = do_quit,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
|
@ -181,10 +178,7 @@ EQMP
|
||||||
{
|
{
|
||||||
.name = "stop",
|
.name = "stop",
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
.params = "",
|
.mhandler.cmd_new = qmp_marshal_input_stop,
|
||||||
.help = "stop emulation",
|
|
||||||
.user_print = monitor_user_noop,
|
|
||||||
.mhandler.cmd_new = do_stop,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
|
@ -229,10 +223,7 @@ EQMP
|
||||||
{
|
{
|
||||||
.name = "system_reset",
|
.name = "system_reset",
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
.params = "",
|
.mhandler.cmd_new = qmp_marshal_input_system_reset,
|
||||||
.help = "reset the system",
|
|
||||||
.user_print = monitor_user_noop,
|
|
||||||
.mhandler.cmd_new = do_system_reset,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
|
@ -1053,6 +1044,12 @@ Example:
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "query-version",
|
||||||
|
.args_type = "",
|
||||||
|
.mhandler.cmd_new = qmp_marshal_input_query_version,
|
||||||
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
query-commands
|
query-commands
|
||||||
--------------
|
--------------
|
||||||
|
@ -1084,6 +1081,12 @@ Note: This example has been shortened as the real response is too long.
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "query-commands",
|
||||||
|
.args_type = "",
|
||||||
|
.mhandler.cmd_new = qmp_marshal_input_query_commands,
|
||||||
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
query-chardev
|
query-chardev
|
||||||
-------------
|
-------------
|
||||||
|
@ -1114,6 +1117,12 @@ Example:
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "query-chardev",
|
||||||
|
.args_type = "",
|
||||||
|
.mhandler.cmd_new = qmp_marshal_input_query_chardev,
|
||||||
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
query-block
|
query-block
|
||||||
-----------
|
-----------
|
||||||
|
@ -1564,6 +1573,12 @@ Example:
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "query-kvm",
|
||||||
|
.args_type = "",
|
||||||
|
.mhandler.cmd_new = qmp_marshal_input_query_kvm,
|
||||||
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
query-status
|
query-status
|
||||||
------------
|
------------
|
||||||
|
@ -1598,6 +1613,12 @@ Example:
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "query-status",
|
||||||
|
.args_type = "",
|
||||||
|
.mhandler.cmd_new = qmp_marshal_input_query_status,
|
||||||
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
query-mice
|
query-mice
|
||||||
----------
|
----------
|
||||||
|
@ -1780,6 +1801,12 @@ Example:
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "query-name",
|
||||||
|
.args_type = "",
|
||||||
|
.mhandler.cmd_new = qmp_marshal_input_query_name,
|
||||||
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
query-uuid
|
query-uuid
|
||||||
----------
|
----------
|
||||||
|
@ -1797,6 +1824,12 @@ Example:
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "query-uuid",
|
||||||
|
.args_type = "",
|
||||||
|
.mhandler.cmd_new = qmp_marshal_input_query_uuid,
|
||||||
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
query-migrate
|
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;
|
int ret;
|
||||||
|
|
||||||
saved_vm_running = runstate_is_running();
|
saved_vm_running = runstate_is_running();
|
||||||
vm_stop(RSTATE_SAVEVM);
|
vm_stop(RUN_STATE_SAVE_VM);
|
||||||
|
|
||||||
if (qemu_savevm_state_blocked(mon)) {
|
if (qemu_savevm_state_blocked(mon)) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@ -1932,7 +1932,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
|
||||||
}
|
}
|
||||||
|
|
||||||
saved_vm_running = runstate_is_running();
|
saved_vm_running = runstate_is_running();
|
||||||
vm_stop(RSTATE_SAVEVM);
|
vm_stop(RUN_STATE_SAVE_VM);
|
||||||
|
|
||||||
memset(sn, 0, sizeof(*sn));
|
memset(sn, 0, sizeof(*sn));
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,18 @@ import os
|
||||||
import getopt
|
import getopt
|
||||||
import errno
|
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):
|
def generate_decl_enum(name, members, genlist=True):
|
||||||
return mcgen('''
|
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):
|
def generate_command_decl(name, args, ret_type):
|
||||||
arglist=""
|
arglist=""
|
||||||
|
@ -146,9 +152,10 @@ if (has_%(c_name)s) {
|
||||||
c_name=c_var(argname), name=argname)
|
c_name=c_var(argname), name=argname)
|
||||||
push_indent()
|
push_indent()
|
||||||
ret += mcgen('''
|
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:
|
if optional:
|
||||||
pop_indent()
|
pop_indent()
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
@ -167,9 +174,10 @@ qmp_input_visitor_cleanup(mi);
|
||||||
pop_indent()
|
pop_indent()
|
||||||
return ret.rstrip()
|
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:
|
if not ret_type:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp)
|
static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp)
|
||||||
{
|
{
|
||||||
|
@ -178,26 +186,44 @@ static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_o
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
|
|
||||||
v = qmp_output_get_visitor(mo);
|
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)) {
|
if (!error_is_set(errp)) {
|
||||||
*ret_out = qmp_output_get_qobject(mo);
|
*ret_out = qmp_output_get_qobject(mo);
|
||||||
}
|
}
|
||||||
qmp_output_visitor_cleanup(mo);
|
qmp_output_visitor_cleanup(mo);
|
||||||
v = qapi_dealloc_get_visitor(md);
|
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);
|
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
|
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('''
|
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 ret_type:
|
||||||
if c_type(ret_type).endswith("*"):
|
if c_type(ret_type).endswith("*"):
|
||||||
|
@ -220,6 +246,10 @@ static void qmp_marshal_input_%(c_name)s(QDict *args, QObject **ret, Error **err
|
||||||
visitor_input_containers_decl=gen_visitor_input_containers_decl(args),
|
visitor_input_containers_decl=gen_visitor_input_containers_decl(args),
|
||||||
visitor_input_vars_decl=gen_visitor_input_vars_decl(args),
|
visitor_input_vars_decl=gen_visitor_input_vars_decl(args),
|
||||||
visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)"))
|
visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)"))
|
||||||
|
else:
|
||||||
|
ret += mcgen('''
|
||||||
|
(void)args;
|
||||||
|
''')
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
if (error_is_set(errp)) {
|
if (error_is_set(errp)) {
|
||||||
|
@ -234,10 +264,29 @@ out:
|
||||||
''')
|
''')
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
%(visitor_input_block_cleanup)s
|
%(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
|
return ret
|
||||||
|
|
||||||
def gen_registry(commands):
|
def gen_registry(commands):
|
||||||
|
@ -284,7 +333,7 @@ def gen_command_decl_prologue(header, guard, prefix=""):
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
''',
|
''',
|
||||||
header=basename(h_file), guard=guardname(h_file), prefix=prefix)
|
header=basename(header), guard=guardname(header), prefix=prefix)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def gen_command_def_prologue(prefix="", proxy=False):
|
def gen_command_def_prologue(prefix="", proxy=False):
|
||||||
|
@ -317,11 +366,11 @@ def gen_command_def_prologue(prefix="", proxy=False):
|
||||||
prefix=prefix)
|
prefix=prefix)
|
||||||
if not proxy:
|
if not proxy:
|
||||||
ret += '#include "%sqmp-commands.h"' % prefix
|
ret += '#include "%sqmp-commands.h"' % prefix
|
||||||
return ret + "\n"
|
return ret + "\n\n"
|
||||||
|
|
||||||
|
|
||||||
try:
|
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:
|
except getopt.GetoptError, err:
|
||||||
print str(err)
|
print str(err)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -331,6 +380,7 @@ prefix = ""
|
||||||
dispatch_type = "sync"
|
dispatch_type = "sync"
|
||||||
c_file = 'qmp-marshal.c'
|
c_file = 'qmp-marshal.c'
|
||||||
h_file = 'qmp-commands.h'
|
h_file = 'qmp-commands.h'
|
||||||
|
middle_mode = False
|
||||||
|
|
||||||
for o, a in opts:
|
for o, a in opts:
|
||||||
if o in ("-p", "--prefix"):
|
if o in ("-p", "--prefix"):
|
||||||
|
@ -339,6 +389,8 @@ for o, a in opts:
|
||||||
output_dir = a + "/"
|
output_dir = a + "/"
|
||||||
elif o in ("-t", "--type"):
|
elif o in ("-t", "--type"):
|
||||||
dispatch_type = a
|
dispatch_type = a
|
||||||
|
elif o in ("-m", "--middle"):
|
||||||
|
middle_mode = True
|
||||||
|
|
||||||
c_file = output_dir + prefix + c_file
|
c_file = output_dir + prefix + c_file
|
||||||
h_file = output_dir + prefix + h_file
|
h_file = output_dir + prefix + h_file
|
||||||
|
@ -370,12 +422,18 @@ if dispatch_type == "sync":
|
||||||
ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
|
ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
|
||||||
fdecl.write(ret)
|
fdecl.write(ret)
|
||||||
if ret_type:
|
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)
|
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)
|
fdef.write(ret)
|
||||||
|
|
||||||
fdecl.write("\n#endif\n");
|
fdecl.write("\n#endif\n");
|
||||||
|
|
||||||
|
if not middle_mode:
|
||||||
ret = gen_registry(commands)
|
ret = gen_registry(commands)
|
||||||
fdef.write(ret)
|
fdef.write(ret)
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ const char *%(name)s_lookup[] = {
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
"%(value)s",
|
"%(value)s",
|
||||||
''',
|
''',
|
||||||
value=c_var(value).lower())
|
value=value.lower())
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -91,8 +91,11 @@ typedef enum %(name)s
|
||||||
''',
|
''',
|
||||||
name=name)
|
name=name)
|
||||||
|
|
||||||
|
# append automatically generated _MAX value
|
||||||
|
enum_values = values + [ 'MAX' ]
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
for value in values:
|
for value in enum_values:
|
||||||
enum_decl += mcgen('''
|
enum_decl += mcgen('''
|
||||||
%(abbrev)s_%(value)s = %(i)d,
|
%(abbrev)s_%(value)s = %(i)d,
|
||||||
''',
|
''',
|
||||||
|
@ -254,6 +257,8 @@ for expr in exprs:
|
||||||
ret = "\n"
|
ret = "\n"
|
||||||
if expr.has_key('type'):
|
if expr.has_key('type'):
|
||||||
ret += generate_struct(expr['type'], "", expr['data']) + "\n"
|
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'])
|
ret += generate_type_cleanup_decl(expr['type'])
|
||||||
fdef.write(generate_type_cleanup(expr['type']) + "\n")
|
fdef.write(generate_type_cleanup(expr['type']) + "\n")
|
||||||
elif expr.has_key('union'):
|
elif expr.has_key('union'):
|
||||||
|
@ -268,3 +273,6 @@ fdecl.write('''
|
||||||
|
|
||||||
fdecl.flush()
|
fdecl.flush()
|
||||||
fdecl.close()
|
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)
|
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);
|
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;
|
%(name)sList *native_i = (%(name)sList *)i;
|
||||||
visit_type_%(name)s(m, &native_i->value, NULL, errp);
|
visit_type_%(name)s(m, &native_i->value, NULL, errp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,4 +200,6 @@ def basename(filename):
|
||||||
return filename.split("/")[-1]
|
return filename.split("/")[-1]
|
||||||
|
|
||||||
def guardname(filename):
|
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-option.h"
|
||||||
#include "qemu-queue.h"
|
#include "qemu-queue.h"
|
||||||
#include "qemu-timer.h"
|
#include "qemu-timer.h"
|
||||||
|
#include "qapi-types.h"
|
||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
|
|
||||||
/* vl.c */
|
/* 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 *bios_name;
|
||||||
|
|
||||||
extern const char *qemu_name;
|
extern const char *qemu_name;
|
||||||
|
@ -39,7 +22,6 @@ void runstate_init(void);
|
||||||
bool runstate_check(RunState state);
|
bool runstate_check(RunState state);
|
||||||
void runstate_set(RunState new_state);
|
void runstate_set(RunState new_state);
|
||||||
int runstate_is_running(void);
|
int runstate_is_running(void);
|
||||||
const char *runstate_as_string(void);
|
|
||||||
typedef struct vm_change_state_entry VMChangeStateEntry;
|
typedef struct vm_change_state_entry VMChangeStateEntry;
|
||||||
typedef void VMChangeStateHandler(void *opaque, int running, RunState state);
|
typedef void VMChangeStateHandler(void *opaque, int running, RunState state);
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,34 @@ static void test_dispatch_cmd_io(void)
|
||||||
QDECREF(req);
|
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)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
g_test_init(&argc, &argv, NULL);
|
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", test_dispatch_cmd);
|
||||||
g_test_add_func("/0.15/dispatch_cmd_error", test_dispatch_cmd_error);
|
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/dispatch_cmd_io", test_dispatch_cmd_io);
|
||||||
|
g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
|
||||||
|
|
||||||
module_call_init(MODULE_INIT_QAPI);
|
module_call_init(MODULE_INIT_QAPI);
|
||||||
g_test_run();
|
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)
|
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);
|
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;
|
TestStructList *native_i = (TestStructList *)i;
|
||||||
visit_type_TestStruct(m, &native_i->value, NULL, errp);
|
visit_type_TestStruct(m, &native_i->value, NULL, errp);
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,8 @@ static void test_visitor_core(void)
|
||||||
TestStructList *lts = NULL;
|
TestStructList *lts = NULL;
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
QObject *obj;
|
QObject *obj;
|
||||||
|
QList *qlist;
|
||||||
|
QDict *qdict;
|
||||||
QString *str;
|
QString *str;
|
||||||
int64_t value = 0;
|
int64_t value = 0;
|
||||||
|
|
||||||
|
@ -96,7 +98,9 @@ static void test_visitor_core(void)
|
||||||
g_assert(pts->y == 84);
|
g_assert(pts->y == 84);
|
||||||
|
|
||||||
qobject_decref(obj);
|
qobject_decref(obj);
|
||||||
|
g_free(pts);
|
||||||
|
|
||||||
|
/* test list input visitor */
|
||||||
obj = qobject_from_json("[{'x': 42, 'y': 84}, {'x': 12, 'y': 24}]");
|
obj = qobject_from_json("[{'x': 42, 'y': 84}, {'x': 12, 'y': 24}]");
|
||||||
mi = qmp_input_visitor_new(obj);
|
mi = qmp_input_visitor_new(obj);
|
||||||
v = qmp_input_get_visitor(mi);
|
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->x == 42);
|
||||||
g_assert(lts->value->y == 84);
|
g_assert(lts->value->y == 84);
|
||||||
|
|
||||||
lts = lts->next;
|
g_assert(lts->next != NULL);
|
||||||
g_assert(lts != NULL);
|
g_assert(lts->next->value->x == 12);
|
||||||
g_assert(lts->value->x == 12);
|
g_assert(lts->next->value->y == 24);
|
||||||
g_assert(lts->value->y == 24);
|
g_assert(lts->next->next == NULL);
|
||||||
|
|
||||||
g_assert(lts->next == NULL);
|
|
||||||
|
|
||||||
qobject_decref(obj);
|
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 */
|
/* 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_enum2 == false);
|
||||||
g_assert(nested_enums_cpy->has_enum4 == true);
|
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);
|
||||||
qapi_free_NestedEnumsOne(nested_enums_cpy);
|
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-config.h"
|
||||||
#include "qemu-objects.h"
|
#include "qemu-objects.h"
|
||||||
#include "qemu-options.h"
|
#include "qemu-options.h"
|
||||||
|
#include "qmp-commands.h"
|
||||||
#ifdef CONFIG_VIRTFS
|
#ifdef CONFIG_VIRTFS
|
||||||
#include "fsdev/qemu-fsdev.h"
|
#include "fsdev/qemu-fsdev.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -323,7 +324,7 @@ static int default_driver_check(QemuOpts *opts, void *opaque)
|
||||||
/***********************************************************/
|
/***********************************************************/
|
||||||
/* QEMU state */
|
/* QEMU state */
|
||||||
|
|
||||||
static RunState current_run_state = RSTATE_NO_STATE;
|
static RunState current_run_state = RUN_STATE_PRELAUNCH;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
RunState from;
|
RunState from;
|
||||||
|
@ -332,67 +333,48 @@ typedef struct {
|
||||||
|
|
||||||
static const RunStateTransition runstate_transitions_def[] = {
|
static const RunStateTransition runstate_transitions_def[] = {
|
||||||
/* from -> to */
|
/* from -> to */
|
||||||
{ RSTATE_NO_STATE, RSTATE_RUNNING },
|
{ RUN_STATE_DEBUG, RUN_STATE_RUNNING },
|
||||||
{ RSTATE_NO_STATE, RSTATE_IN_MIGRATE },
|
|
||||||
{ RSTATE_NO_STATE, RSTATE_PRE_LAUNCH },
|
|
||||||
|
|
||||||
{ RSTATE_DEBUG, RSTATE_RUNNING },
|
{ RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
|
||||||
|
{ RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH },
|
||||||
|
|
||||||
{ RSTATE_IN_MIGRATE, RSTATE_RUNNING },
|
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
|
||||||
{ RSTATE_IN_MIGRATE, RSTATE_PRE_LAUNCH },
|
|
||||||
|
|
||||||
{ 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 },
|
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
|
||||||
{ RSTATE_PRE_LAUNCH, RSTATE_POST_MIGRATE },
|
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
|
||||||
|
|
||||||
{ RSTATE_PRE_MIGRATE, RSTATE_RUNNING },
|
{ RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
|
||||||
{ RSTATE_PRE_MIGRATE, RSTATE_POST_MIGRATE },
|
|
||||||
|
|
||||||
{ 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 },
|
{ RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
|
||||||
{ RSTATE_RUNNING, RSTATE_PANICKED },
|
|
||||||
{ RSTATE_RUNNING, RSTATE_IO_ERROR },
|
|
||||||
{ RSTATE_RUNNING, RSTATE_PAUSED },
|
|
||||||
{ RSTATE_RUNNING, RSTATE_PRE_MIGRATE },
|
|
||||||
{ RSTATE_RUNNING, RSTATE_RESTORE },
|
|
||||||
{ RSTATE_RUNNING, RSTATE_SAVEVM },
|
|
||||||
{ RSTATE_RUNNING, RSTATE_SHUTDOWN },
|
|
||||||
{ RSTATE_RUNNING, RSTATE_WATCHDOG },
|
|
||||||
|
|
||||||
{ RSTATE_SAVEVM, RSTATE_RUNNING },
|
{ RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
|
||||||
|
|
||||||
{ RSTATE_SHUTDOWN, RSTATE_PAUSED },
|
{ RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
|
||||||
|
|
||||||
{ RSTATE_WATCHDOG, RSTATE_RUNNING },
|
{ RUN_STATE_MAX, RUN_STATE_MAX },
|
||||||
|
|
||||||
{ RSTATE_MAX, RSTATE_MAX },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool runstate_valid_transitions[RSTATE_MAX][RSTATE_MAX];
|
static bool runstate_valid_transitions[RUN_STATE_MAX][RUN_STATE_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",
|
|
||||||
};
|
|
||||||
|
|
||||||
bool runstate_check(RunState state)
|
bool runstate_check(RunState state)
|
||||||
{
|
{
|
||||||
|
@ -405,7 +387,7 @@ void runstate_init(void)
|
||||||
|
|
||||||
memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
|
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;
|
runstate_valid_transitions[p->from][p->to] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,7 +395,7 @@ void runstate_init(void)
|
||||||
/* This function will abort() on invalid state transitions */
|
/* This function will abort() on invalid state transitions */
|
||||||
void runstate_set(RunState new_state)
|
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]) {
|
!runstate_valid_transitions[current_run_state][new_state]) {
|
||||||
fprintf(stderr, "invalid runstate transition\n");
|
fprintf(stderr, "invalid runstate transition\n");
|
||||||
abort();
|
abort();
|
||||||
|
@ -422,16 +404,20 @@ void runstate_set(RunState new_state)
|
||||||
current_run_state = 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)
|
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()) {
|
if (!runstate_is_running()) {
|
||||||
cpu_enable_ticks();
|
cpu_enable_ticks();
|
||||||
runstate_set(RSTATE_RUNNING);
|
runstate_set(RUN_STATE_RUNNING);
|
||||||
vm_state_notify(1, RSTATE_RUNNING);
|
vm_state_notify(1, RUN_STATE_RUNNING);
|
||||||
resume_all_vcpus();
|
resume_all_vcpus();
|
||||||
monitor_protocol_event(QEVENT_RESUME, NULL);
|
monitor_protocol_event(QEVENT_RESUME, NULL);
|
||||||
}
|
}
|
||||||
|
@ -1294,7 +1280,7 @@ static int shutdown_requested, shutdown_signal = -1;
|
||||||
static pid_t shutdown_pid;
|
static pid_t shutdown_pid;
|
||||||
static int powerdown_requested;
|
static int powerdown_requested;
|
||||||
static int debug_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)
|
int qemu_shutdown_requested_get(void)
|
||||||
{
|
{
|
||||||
|
@ -1350,11 +1336,16 @@ static int qemu_debug_requested(void)
|
||||||
return r;
|
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;
|
if (vmstop_requested < RUN_STATE_MAX) {
|
||||||
vmstop_requested = RSTATE_NO_STATE;
|
*r = vmstop_requested;
|
||||||
return s;
|
vmstop_requested = RUN_STATE_MAX;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_register_reset(QEMUResetHandler *func, void *opaque)
|
void qemu_register_reset(QEMUResetHandler *func, void *opaque)
|
||||||
|
@ -1567,7 +1558,7 @@ static void main_loop(void)
|
||||||
#ifdef CONFIG_PROFILER
|
#ifdef CONFIG_PROFILER
|
||||||
int64_t ti;
|
int64_t ti;
|
||||||
#endif
|
#endif
|
||||||
int r;
|
RunState r;
|
||||||
|
|
||||||
qemu_main_loop_start();
|
qemu_main_loop_start();
|
||||||
|
|
||||||
|
@ -1582,13 +1573,13 @@ static void main_loop(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (qemu_debug_requested()) {
|
if (qemu_debug_requested()) {
|
||||||
vm_stop(RSTATE_DEBUG);
|
vm_stop(RUN_STATE_DEBUG);
|
||||||
}
|
}
|
||||||
if (qemu_shutdown_requested()) {
|
if (qemu_shutdown_requested()) {
|
||||||
qemu_kill_report();
|
qemu_kill_report();
|
||||||
monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
|
monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
|
||||||
if (no_shutdown) {
|
if (no_shutdown) {
|
||||||
vm_stop(RSTATE_SHUTDOWN);
|
vm_stop(RUN_STATE_SHUTDOWN);
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1597,16 +1588,16 @@ static void main_loop(void)
|
||||||
cpu_synchronize_all_states();
|
cpu_synchronize_all_states();
|
||||||
qemu_system_reset(VMRESET_REPORT);
|
qemu_system_reset(VMRESET_REPORT);
|
||||||
resume_all_vcpus();
|
resume_all_vcpus();
|
||||||
if (runstate_check(RSTATE_PANICKED) ||
|
if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
|
||||||
runstate_check(RSTATE_SHUTDOWN)) {
|
runstate_check(RUN_STATE_SHUTDOWN)) {
|
||||||
runstate_set(RSTATE_PAUSED);
|
runstate_set(RUN_STATE_PAUSED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (qemu_powerdown_requested()) {
|
if (qemu_powerdown_requested()) {
|
||||||
monitor_protocol_event(QEVENT_POWERDOWN, NULL);
|
monitor_protocol_event(QEVENT_POWERDOWN, NULL);
|
||||||
qemu_irq_raise(qemu_system_powerdown);
|
qemu_irq_raise(qemu_system_powerdown);
|
||||||
}
|
}
|
||||||
if ((r = qemu_vmstop_requested())) {
|
if (qemu_vmstop_requested(&r)) {
|
||||||
vm_stop(r);
|
vm_stop(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3556,7 +3547,7 @@ int main(int argc, char **argv, char **envp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (incoming) {
|
if (incoming) {
|
||||||
runstate_set(RSTATE_IN_MIGRATE);
|
runstate_set(RUN_STATE_INMIGRATE);
|
||||||
int ret = qemu_start_incoming_migration(incoming);
|
int ret = qemu_start_incoming_migration(incoming);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Migration failed. Exit code %s(%d), exiting.\n",
|
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) {
|
} else if (autostart) {
|
||||||
vm_start();
|
vm_start();
|
||||||
} else {
|
|
||||||
runstate_set(RSTATE_PRE_LAUNCH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
os_setup_post();
|
os_setup_post();
|
||||||
|
|
Loading…
Reference in New Issue