]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Merge remote-tracking branch 'qmp/queue/qmp' into staging
authorAnthony Liguori <aliguori@us.ibm.com>
Mon, 10 Oct 2011 13:21:46 +0000 (08:21 -0500)
committerAnthony Liguori <aliguori@us.ibm.com>
Mon, 10 Oct 2011 13:21:46 +0000 (08:21 -0500)
34 files changed:
Makefile
Makefile.objs
Makefile.target
error.c
gdbstub.c
hmp-commands.hx
hmp.c [new file with mode: 0644]
hmp.h [new file with mode: 0644]
hw/ide/core.c
hw/scsi-disk.c
hw/virtio-blk.c
hw/watchdog.c
kvm-all.c
migration.c
monitor.c
qapi-schema.json [new file with mode: 0644]
qapi/qapi-dealloc-visitor.c
qapi/qapi-types-core.h
qapi/qmp-input-visitor.c
qapi/qmp-output-visitor.c
qemu-char.c
qerror.c
qerror.h
qmp-commands.hx
qmp.c [new file with mode: 0644]
savevm.c
scripts/qapi-commands.py
scripts/qapi-types.py
scripts/qapi-visit.py
scripts/qapi.py
sysemu.h
test-qmp-commands.c
test-visitor.c
vl.c

index bcb4cd09e8e323641ffd600884400f683cdd71a7..f63fc02ca3e3ddd7c447619e5d355936f2c81087 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,7 @@ GENERATED_HEADERS = config-host.h trace.h qemu-options.def
 ifeq ($(TRACE_BACKEND),dtrace)
 GENERATED_HEADERS += trace-dtrace.h
 endif
+GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
 
 ifneq ($(wildcard config-host.mak),)
 # Put the all: rule here so that config-host.mak can contain dependencies.
@@ -188,9 +189,20 @@ $(qapi-dir)/qga-qapi-types.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scr
 $(qapi-dir)/qga-qapi-visit.c: $(qapi-dir)/qga-qapi-visit.h
 $(qapi-dir)/qga-qapi-visit.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-visit.py
        $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "qga-" < $<, "  GEN   $@")
+$(qapi-dir)/qga-qmp-commands.h: $(qapi-dir)/qga-qmp-marshal.c
 $(qapi-dir)/qga-qmp-marshal.c: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-commands.py
        $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "qga-" < $<, "  GEN   $@")
 
+qapi-types.c: qapi-types.h
+qapi-types.h: $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py
+       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py -o "." < $<, "  GEN   $@")
+qapi-visit.c: qapi-visit.h
+qapi-visit.h: $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py
+       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "."  < $<, "  GEN   $@")
+qmp-commands.h: qmp-marshal.c
+qmp-marshal.c: $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
+       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -m -o "." < $<, "  GEN   $@")
+
 test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
 test-visitor: test-visitor.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
 
index c849e51122f1a683e26ffd317db14c1afe153879..7b0739c524e27cdb475b50feb2a7d3e9b24dad43 100644 (file)
@@ -405,6 +405,9 @@ qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-
 qapi-nested-y += qmp-registry.o qmp-dispatch.o
 qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
 
+common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o $(qapi-obj-y)
+common-obj-y += qmp.o hmp.o
+
 ######################################################################
 # guest agent
 
index 1aa6fce69087368d25f7061727a6254fbdc8c379..42adfecc35452f9c9b61a203becdd07e503809e4 100644 (file)
@@ -376,7 +376,7 @@ obj-xtensa-y += xtensa-semi.o
 
 main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
-monitor.o: hmp-commands.h qmp-commands.h
+monitor.o: hmp-commands.h qmp-commands-old.h
 
 $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
 
@@ -408,13 +408,13 @@ gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
 hmp-commands.h: $(SRC_PATH)/hmp-commands.hx
        $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $(TARGET_DIR)$@")
 
-qmp-commands.h: $(SRC_PATH)/qmp-commands.hx
+qmp-commands-old.h: $(SRC_PATH)/qmp-commands.hx
        $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $(TARGET_DIR)$@")
 
 clean:
        rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
        rm -f *.d */*.d tcg/*.o ide/*.o 9pfs/*.o
-       rm -f hmp-commands.h qmp-commands.h gdbstub-xml.c
+       rm -f hmp-commands.h qmp-commands-old.h gdbstub-xml.c
 ifdef CONFIG_TRACE_SYSTEMTAP
        rm -f *.stp
 endif
diff --git a/error.c b/error.c
index b80275261c476c27b88ffb767e48ecc412160f96..68c0039dbaa399e3a00aa34fe7c11c4f43427236 100644 (file)
--- a/error.c
+++ b/error.c
@@ -97,6 +97,10 @@ bool error_is_type(Error *err, const char *fmt)
     char *ptr;
     char *end;
 
+    if (!err) {
+        return false;
+    }
+
     ptr = strstr(fmt, "'class': '");
     assert(ptr != NULL);
     ptr += strlen("'class': '");
index 1d99e19258ba84f3cd1a8ca748c9f9bcf2078420..4009058788347ad06d9843d32355b85c44cec594 100644 (file)
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2385,7 +2385,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
         return;
     }
     switch (state) {
-    case RSTATE_DEBUG:
+    case RUN_STATE_DEBUG:
         if (env->watchpoint_hit) {
             switch (env->watchpoint_hit->flags & BP_MEM_ACCESS) {
             case BP_MEM_READ:
@@ -2408,25 +2408,25 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
         tb_flush(env);
         ret = GDB_SIGNAL_TRAP;
         break;
-    case RSTATE_PAUSED:
+    case RUN_STATE_PAUSED:
         ret = GDB_SIGNAL_INT;
         break;
-    case RSTATE_SHUTDOWN:
+    case RUN_STATE_SHUTDOWN:
         ret = GDB_SIGNAL_QUIT;
         break;
-    case RSTATE_IO_ERROR:
+    case RUN_STATE_IO_ERROR:
         ret = GDB_SIGNAL_IO;
         break;
-    case RSTATE_WATCHDOG:
+    case RUN_STATE_WATCHDOG:
         ret = GDB_SIGNAL_ALRM;
         break;
-    case RSTATE_PANICKED:
+    case RUN_STATE_INTERNAL_ERROR:
         ret = GDB_SIGNAL_ABRT;
         break;
-    case RSTATE_SAVEVM:
-    case RSTATE_RESTORE:
+    case RUN_STATE_SAVE_VM:
+    case RUN_STATE_RESTORE_VM:
         return;
-    case RSTATE_PRE_MIGRATE:
+    case RUN_STATE_FINISH_MIGRATE:
         ret = GDB_SIGNAL_XCPU;
         break;
     default:
@@ -2463,7 +2463,7 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
     gdb_current_syscall_cb = cb;
     s->state = RS_SYSCALL;
 #ifndef CONFIG_USER_ONLY
-    vm_stop(RSTATE_DEBUG);
+    vm_stop(RUN_STATE_DEBUG);
 #endif
     s->state = RS_IDLE;
     va_start(va, fmt);
@@ -2537,7 +2537,7 @@ static void gdb_read_byte(GDBState *s, int ch)
     if (runstate_is_running()) {
         /* when the CPU is running, we cannot do anything except stop
            it when receiving a char */
-        vm_stop(RSTATE_PAUSED);
+        vm_stop(RUN_STATE_PAUSED);
     } else
 #endif
     {
@@ -2799,7 +2799,7 @@ static void gdb_chr_event(void *opaque, int event)
 {
     switch (event) {
     case CHR_EVENT_OPENED:
-        vm_stop(RSTATE_PAUSED);
+        vm_stop(RUN_STATE_PAUSED);
         gdb_has_xml = 0;
         break;
     default:
@@ -2840,7 +2840,7 @@ static int gdb_monitor_write(CharDriverState *chr, const uint8_t *buf, int len)
 static void gdb_sigterm_handler(int signal)
 {
     if (runstate_is_running()) {
-        vm_stop(RSTATE_PAUSED);
+        vm_stop(RUN_STATE_PAUSED);
     }
 }
 #endif
index a8ece43de752ca44e0b784419e63511df0cf958e..ab08d583df1a5871e6129c2cd54f085915e34539 100644 (file)
@@ -43,7 +43,7 @@ ETEXI
         .params     = "",
         .help       = "quit the emulator",
         .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_quit,
+        .mhandler.cmd = hmp_quit,
     },
 
 STEXI
@@ -290,8 +290,7 @@ ETEXI
         .args_type  = "",
         .params     = "",
         .help       = "stop emulation",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_stop,
+        .mhandler.cmd = hmp_stop,
     },
 
 STEXI
@@ -478,8 +477,7 @@ ETEXI
         .args_type  = "",
         .params     = "",
         .help       = "reset the system",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_system_reset,
+        .mhandler.cmd = hmp_system_reset,
     },
 
 STEXI
@@ -494,8 +492,7 @@ ETEXI
         .args_type  = "",
         .params     = "",
         .help       = "send system power down event",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_system_powerdown,
+        .mhandler.cmd = hmp_system_powerdown,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
new file mode 100644 (file)
index 0000000..34416fc
--- /dev/null
+++ b/hmp.c
@@ -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);
+}
diff --git a/hmp.h b/hmp.h
new file mode 100644 (file)
index 0000000..92433cf
--- /dev/null
+++ b/hmp.h
@@ -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
index 4e76fc78d3e687a230da3f5b45401efef6c8b225..b71a356f39a3bfcb6813432842fa693c1e3301c3 100644 (file)
@@ -527,7 +527,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op)
         s->bus->dma->ops->set_unit(s->bus->dma, s->unit);
         s->bus->error_status = op;
         bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
-        vm_stop(RSTATE_IO_ERROR);
+        vm_stop(RUN_STATE_IO_ERROR);
     } else {
         if (op & BM_STATUS_DMA_RETRY) {
             dma_buf_commit(s, 0);
index e843f712c2144e5bb53deb242ac721ff88fab389..4f681ef09293dc138253982ba15970c2af41e112 100644 (file)
@@ -227,7 +227,7 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
         r->status |= SCSI_REQ_STATUS_RETRY | type;
 
         bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
-        vm_stop(RSTATE_IO_ERROR);
+        vm_stop(RUN_STATE_IO_ERROR);
     } else {
         switch (error) {
         case ENOMEM:
index daa8e42be7f7b78eebc6e4b697d25d3a09690642..03878bfc5eee857720c8b6b03bf71f249e2b440b 100644 (file)
@@ -77,7 +77,7 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
         req->next = s->rq;
         s->rq = req;
         bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
-        vm_stop(RSTATE_IO_ERROR);
+        vm_stop(RUN_STATE_IO_ERROR);
     } else {
         virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
         bdrv_acct_done(s->bs, &req->acct);
index 71c6c7df63c23b29dbc6701464e032401833590e..4c189656540c4b9ad1348495fbd47458538304d9 100644 (file)
@@ -132,7 +132,7 @@ void watchdog_perform_action(void)
 
     case WDT_PAUSE:             /* same as 'stop' command in monitor */
         watchdog_mon_event("pause");
-        vm_stop(RSTATE_WATCHDOG);
+        vm_stop(RUN_STATE_WATCHDOG);
         break;
 
     case WDT_DEBUG:
index 228655b388370add3481a4d7196c49a1dd1fc914..e7faf5cba9ab4c1eef0394f1dcf8b4196756c246 100644 (file)
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1014,7 +1014,7 @@ int kvm_cpu_exec(CPUState *env)
 
     if (ret < 0) {
         cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
-        vm_stop(RSTATE_PANICKED);
+        vm_stop(RUN_STATE_INTERNAL_ERROR);
     }
 
     env->exit_request = 0;
index 7dd8f4eee9286242a17d1bba52672e012147ac6b..77a51adc5bb6691b9f9079e717ca158998b3b6f7 100644 (file)
@@ -73,7 +73,7 @@ void process_incoming_migration(QEMUFile *f)
     if (autostart) {
         vm_start();
     } else {
-        runstate_set(RSTATE_PRE_LAUNCH);
+        runstate_set(RUN_STATE_PRELAUNCH);
     }
 }
 
@@ -375,7 +375,7 @@ void migrate_fd_put_ready(void *opaque)
         int old_vm_running = runstate_is_running();
 
         DPRINTF("done iterating\n");
-        vm_stop(RSTATE_PRE_MIGRATE);
+        vm_stop(RUN_STATE_FINISH_MIGRATE);
 
         if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
             if (old_vm_running) {
@@ -392,7 +392,7 @@ void migrate_fd_put_ready(void *opaque)
             state = MIG_STATE_ERROR;
         }
         if (state == MIG_STATE_COMPLETED) {
-            runstate_set(RSTATE_POST_MIGRATE);
+            runstate_set(RUN_STATE_POSTMIGRATE);
         }
         s->state = state;
         notifier_list_notify(&migration_state_notifiers, NULL);
index da1347160c4b961aba0f62bcdfa95ebed97c7fb7..31b212aa6b75917f948adeb0ec35ea611e5e92a9 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -64,6 +64,8 @@
 #endif
 #include "ui/qemu-spice.h"
 #include "memory.h"
+#include "qmp-commands.h"
+#include "hmp.h"
 
 //#define DEBUG
 //#define DEBUG_COMPLETION
@@ -122,6 +124,7 @@ typedef struct mon_cmd_t {
         int  (*cmd_async)(Monitor *mon, const QDict *params,
                           MonitorCompletion *cb, void *opaque);
     } mhandler;
+    bool qapi;
     int flags;
 } mon_cmd_t;
 
@@ -730,105 +733,37 @@ help:
     help_cmd(mon, "info");
 }
 
-static void do_info_version_print(Monitor *mon, const QObject *data)
-{
-    QDict *qdict;
-    QDict *qemu;
-
-    qdict = qobject_to_qdict(data);
-    qemu = qdict_get_qdict(qdict, "qemu");
-
-    monitor_printf(mon, "%" PRId64 ".%" PRId64 ".%" PRId64 "%s\n",
-                  qdict_get_int(qemu, "major"),
-                  qdict_get_int(qemu, "minor"),
-                  qdict_get_int(qemu, "micro"),
-                  qdict_get_str(qdict, "package"));
-}
-
-static void do_info_version(Monitor *mon, QObject **ret_data)
-{
-    const char *version = QEMU_VERSION;
-    int major = 0, minor = 0, micro = 0;
-    char *tmp;
-
-    major = strtol(version, &tmp, 10);
-    tmp++;
-    minor = strtol(tmp, &tmp, 10);
-    tmp++;
-    micro = strtol(tmp, &tmp, 10);
-
-    *ret_data = qobject_from_jsonf("{ 'qemu': { 'major': %d, 'minor': %d, \
-        'micro': %d }, 'package': %s }", major, minor, micro, QEMU_PKGVERSION);
-}
-
-static void do_info_name_print(Monitor *mon, const QObject *data)
-{
-    QDict *qdict;
-
-    qdict = qobject_to_qdict(data);
-    if (qdict_size(qdict) == 0) {
-        return;
-    }
-
-    monitor_printf(mon, "%s\n", qdict_get_str(qdict, "name"));
-}
-
-static void do_info_name(Monitor *mon, QObject **ret_data)
+static CommandInfoList *alloc_cmd_entry(const char *cmd_name)
 {
-    *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;
+    CommandInfoList *info;
 
-    /* Remove '|' from some commands */
-    p = strchr(name, '|');
-    if (p) {
-        p++;
-    } else {
-        p = name;
-    }
+    info = g_malloc0(sizeof(*info));
+    info->value = g_malloc0(sizeof(*info->value));
+    info->value->name = g_strdup(cmd_name);
 
-    return qobject_from_jsonf("{ 'name': %s }", p);
+    return info;
 }
 
-static void do_info_commands(Monitor *mon, QObject **ret_data)
+CommandInfoList *qmp_query_commands(Error **errp)
 {
-    QList *cmd_list;
+    CommandInfoList *info, *cmd_list = NULL;
     const mon_cmd_t *cmd;
 
-    cmd_list = qlist_new();
-
     for (cmd = qmp_cmds; cmd->name != NULL; cmd++) {
-        qlist_append_obj(cmd_list, get_cmd_dict(cmd->name));
+        info = alloc_cmd_entry(cmd->name);
+        info->next = cmd_list;
+        cmd_list = info;
     }
 
     for (cmd = qmp_query_cmds; cmd->name != NULL; cmd++) {
         char buf[128];
         snprintf(buf, sizeof(buf), "query-%s", cmd->name);
-        qlist_append_obj(cmd_list, get_cmd_dict(buf));
+        info = alloc_cmd_entry(buf);
+        info->next = cmd_list;
+        cmd_list = info;
     }
 
-    *ret_data = QOBJECT(cmd_list);
-}
-
-static void do_info_uuid_print(Monitor *mon, const QObject *data)
-{
-    monitor_printf(mon, "%s\n", qdict_get_str(qobject_to_qdict(data), "UUID"));
-}
-
-static void do_info_uuid(Monitor *mon, QObject **ret_data)
-{
-    char uuid[64];
-
-    snprintf(uuid, sizeof(uuid), UUID_FMT, qemu_uuid[0], qemu_uuid[1],
-                   qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], qemu_uuid[5],
-                   qemu_uuid[6], qemu_uuid[7], qemu_uuid[8], qemu_uuid[9],
-                   qemu_uuid[10], qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
-                   qemu_uuid[14], qemu_uuid[15]);
-    *ret_data = qobject_from_jsonf("{ 'UUID': %s }", uuid);
+    return cmd_list;
 }
 
 /* get the current CPU defined by the user */
@@ -1013,18 +948,6 @@ static void do_trace_print_events(Monitor *mon)
     trace_print_events((FILE *)mon, &monitor_fprintf);
 }
 
-/**
- * do_quit(): Quit QEMU execution
- */
-static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    monitor_suspend(mon);
-    no_shutdown = 0;
-    qemu_system_shutdown_request();
-
-    return 0;
-}
-
 #ifdef CONFIG_VNC
 static int change_vnc_password(const char *password)
 {
@@ -1291,15 +1214,6 @@ static void do_singlestep(Monitor *mon, const QDict *qdict)
     }
 }
 
-/**
- * do_stop(): Stop VM execution
- */
-static int do_stop(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    vm_stop(RSTATE_PAUSED);
-    return 0;
-}
-
 static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs);
 
 struct bdrv_iterate_context {
@@ -1314,11 +1228,11 @@ static int do_cont(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     struct bdrv_iterate_context context = { mon, 0 };
 
-    if (runstate_check(RSTATE_IN_MIGRATE)) {
+    if (runstate_check(RUN_STATE_INMIGRATE)) {
         qerror_report(QERR_MIGRATION_EXPECTED);
         return -1;
-    } else if (runstate_check(RSTATE_PANICKED) ||
-               runstate_check(RSTATE_SHUTDOWN)) {
+    } else if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
+               runstate_check(RUN_STATE_SHUTDOWN)) {
         qerror_report(QERR_RESET_REQUIRED);
         return -1;
     }
@@ -2017,16 +1931,6 @@ static void do_boot_set(Monitor *mon, const QDict *qdict)
     }
 }
 
-/**
- * do_system_reset(): Issue a machine reset
- */
-static int do_system_reset(Monitor *mon, const QDict *qdict,
-                           QObject **ret_data)
-{
-    qemu_system_reset_request();
-    return 0;
-}
-
 /**
  * do_system_powerdown(): Issue a machine powerdown
  */
@@ -2478,31 +2382,6 @@ static void do_info_mtree(Monitor *mon)
     mtree_info((fprintf_function)monitor_printf, mon);
 }
 
-static void do_info_kvm_print(Monitor *mon, const QObject *data)
-{
-    QDict *qdict;
-
-    qdict = qobject_to_qdict(data);
-
-    monitor_printf(mon, "kvm support: ");
-    if (qdict_get_bool(qdict, "present")) {
-        monitor_printf(mon, "%s\n", qdict_get_bool(qdict, "enabled") ?
-                                    "enabled" : "disabled");
-    } else {
-        monitor_printf(mon, "not compiled\n");
-    }
-}
-
-static void do_info_kvm(Monitor *mon, QObject **ret_data)
-{
-#ifdef CONFIG_KVM
-    *ret_data = qobject_from_jsonf("{ 'enabled': %i, 'present': true }",
-                                   kvm_enabled());
-#else
-    *ret_data = qobject_from_jsonf("{ 'enabled': false, 'present': false }");
-#endif
-}
-
 static void do_info_numa(Monitor *mon)
 {
     int i;
@@ -2623,36 +2502,6 @@ static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data)
 }
 #endif
 
-static void do_info_status_print(Monitor *mon, const QObject *data)
-{
-    QDict *qdict;
-    const char *status;
-
-    qdict = qobject_to_qdict(data);
-
-    monitor_printf(mon, "VM status: ");
-    if (qdict_get_bool(qdict, "running")) {
-        monitor_printf(mon, "running");
-        if (qdict_get_bool(qdict, "singlestep")) {
-            monitor_printf(mon, " (single step mode)");
-        }
-    } else {
-        monitor_printf(mon, "paused");
-    }
-
-    status = qdict_get_str(qdict, "status");
-    if (strcmp(status, "paused") && strcmp(status, "running")) {
-        monitor_printf(mon, " (%s)", status);
-    }
-
-    monitor_printf(mon, "\n");
-}
-
-static void do_info_status(Monitor *mon, QObject **ret_data)
-{
-    *ret_data = qobject_from_jsonf("{ 'running': %i, 'singlestep': %i, 'status': %s }", runstate_is_running(), singlestep, runstate_as_string());
-}
-
 static qemu_acl *find_acl(Monitor *mon, const char *name)
 {
     qemu_acl *acl = qemu_acl_find(name);
@@ -2846,7 +2695,7 @@ static void do_loadvm(Monitor *mon, const QDict *qdict)
     int saved_vm_running  = runstate_is_running();
     const char *name = qdict_get_str(qdict, "name");
 
-    vm_stop(RSTATE_RESTORE);
+    vm_stop(RUN_STATE_RESTORE_VM);
 
     if (load_vmstate(name) == 0 && saved_vm_running) {
         vm_start();
@@ -2889,8 +2738,7 @@ static const mon_cmd_t info_cmds[] = {
         .args_type  = "",
         .params     = "",
         .help       = "show the version of QEMU",
-        .user_print = do_info_version_print,
-        .mhandler.info_new = do_info_version,
+        .mhandler.info = hmp_info_version,
     },
     {
         .name       = "network",
@@ -2904,8 +2752,7 @@ static const mon_cmd_t info_cmds[] = {
         .args_type  = "",
         .params     = "",
         .help       = "show the character devices",
-        .user_print = qemu_chr_info_print,
-        .mhandler.info_new = qemu_chr_info,
+        .mhandler.info = hmp_info_chardev,
     },
     {
         .name       = "block",
@@ -3005,8 +2852,7 @@ static const mon_cmd_t info_cmds[] = {
         .args_type  = "",
         .params     = "",
         .help       = "show KVM information",
-        .user_print = do_info_kvm_print,
-        .mhandler.info_new = do_info_kvm,
+        .mhandler.info = hmp_info_kvm,
     },
     {
         .name       = "numa",
@@ -3055,8 +2901,7 @@ static const mon_cmd_t info_cmds[] = {
         .args_type  = "",
         .params     = "",
         .help       = "show the current VM status (running|paused)",
-        .user_print = do_info_status_print,
-        .mhandler.info_new = do_info_status,
+        .mhandler.info = hmp_info_status,
     },
     {
         .name       = "pcmcia",
@@ -3096,16 +2941,14 @@ static const mon_cmd_t info_cmds[] = {
         .args_type  = "",
         .params     = "",
         .help       = "show the current VM name",
-        .user_print = do_info_name_print,
-        .mhandler.info_new = do_info_name,
+        .mhandler.info = hmp_info_name,
     },
     {
         .name       = "uuid",
         .args_type  = "",
         .params     = "",
         .help       = "show the current VM UUID",
-        .user_print = do_info_uuid_print,
-        .mhandler.info_new = do_info_uuid,
+        .mhandler.info = hmp_info_uuid,
     },
 #if defined(TARGET_PPC)
     {
@@ -3185,35 +3028,11 @@ static const mon_cmd_t info_cmds[] = {
 };
 
 static const mon_cmd_t qmp_cmds[] = {
-#include "qmp-commands.h"
+#include "qmp-commands-old.h"
     { /* NULL */ },
 };
 
 static const mon_cmd_t qmp_query_cmds[] = {
-    {
-        .name       = "version",
-        .args_type  = "",
-        .params     = "",
-        .help       = "show the version of QEMU",
-        .user_print = do_info_version_print,
-        .mhandler.info_new = do_info_version,
-    },
-    {
-        .name       = "commands",
-        .args_type  = "",
-        .params     = "",
-        .help       = "list QMP available commands",
-        .user_print = monitor_user_noop,
-        .mhandler.info_new = do_info_commands,
-    },
-    {
-        .name       = "chardev",
-        .args_type  = "",
-        .params     = "",
-        .help       = "show the character devices",
-        .user_print = qemu_chr_info_print,
-        .mhandler.info_new = qemu_chr_info,
-    },
     {
         .name       = "block",
         .args_type  = "",
@@ -3246,22 +3065,6 @@ static const mon_cmd_t qmp_query_cmds[] = {
         .user_print = do_pci_info_print,
         .mhandler.info_new = do_pci_info,
     },
-    {
-        .name       = "kvm",
-        .args_type  = "",
-        .params     = "",
-        .help       = "show KVM information",
-        .user_print = do_info_kvm_print,
-        .mhandler.info_new = do_info_kvm,
-    },
-    {
-        .name       = "status",
-        .args_type  = "",
-        .params     = "",
-        .help       = "show the current VM status (running|paused)",
-        .user_print = do_info_status_print,
-        .mhandler.info_new = do_info_status,
-    },
     {
         .name       = "mice",
         .args_type  = "",
@@ -3288,22 +3091,6 @@ static const mon_cmd_t qmp_query_cmds[] = {
         .mhandler.info_new = do_info_spice,
     },
 #endif
-    {
-        .name       = "name",
-        .args_type  = "",
-        .params     = "",
-        .help       = "show the current VM name",
-        .user_print = do_info_name_print,
-        .mhandler.info_new = do_info_name,
-    },
-    {
-        .name       = "uuid",
-        .args_type  = "",
-        .params     = "",
-        .help       = "show the current VM UUID",
-        .user_print = do_info_uuid_print,
-        .mhandler.info_new = do_info_uuid,
-    },
     {
         .name       = "migrate",
         .args_type  = "",
@@ -5111,12 +4898,10 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
         goto err_out;
     }
 
-    if (strstart(cmd_name, "query-", &query_cmd)) {
+    cmd = qmp_find_cmd(cmd_name);
+    if (!cmd && strstart(cmd_name, "query-", &query_cmd)) {
         cmd = qmp_find_query_cmd(query_cmd);
-    } else {
-        cmd = qmp_find_cmd(cmd_name);
     }
-
     if (!cmd) {
         qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
         goto err_out;
@@ -5215,9 +5000,9 @@ void monitor_resume(Monitor *mon)
 
 static QObject *get_qmp_greeting(void)
 {
-    QObject *ver;
+    QObject *ver = NULL;
 
-    do_info_version(NULL, &ver);
+    qmp_marshal_input_query_version(NULL, NULL, &ver);
     return qobject_from_jsonf("{'QMP':{'version': %p,'capabilities': []}}",ver);
 }
 
diff --git a/qapi-schema.json b/qapi-schema.json
new file mode 100644 (file)
index 0000000..5922c4a
--- /dev/null
@@ -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' }
index f6290611feae485ada5743ab0c06e9261e175b23..a154523731b23a941fe0adaea0577da197f83bd8 100644 (file)
@@ -19,6 +19,7 @@
 typedef struct StackEntry
 {
     void *value;
+    bool is_list_head;
     QTAILQ_ENTRY(StackEntry) node;
 } StackEntry;
 
@@ -26,6 +27,7 @@ struct QapiDeallocVisitor
 {
     Visitor visitor;
     QTAILQ_HEAD(, StackEntry) stack;
+    bool is_list_head;
 };
 
 static QapiDeallocVisitor *to_qov(Visitor *v)
@@ -38,6 +40,11 @@ static void qapi_dealloc_push(QapiDeallocVisitor *qov, void *value)
     StackEntry *e = g_malloc0(sizeof(*e));
 
     e->value = value;
+
+    /* see if we're just pushing a list head tracker */
+    if (value == NULL) {
+        e->is_list_head = true;
+    }
     QTAILQ_INSERT_HEAD(&qov->stack, e, node);
 }
 
@@ -70,19 +77,36 @@ static void qapi_dealloc_end_struct(Visitor *v, Error **errp)
 
 static void qapi_dealloc_start_list(Visitor *v, const char *name, Error **errp)
 {
+    QapiDeallocVisitor *qov = to_qov(v);
+    qapi_dealloc_push(qov, NULL);
 }
 
-static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **list,
+static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **listp,
                                            Error **errp)
 {
-    GenericList *retval = *list;
-    g_free(retval->value);
-    *list = retval->next;
-    return retval;
+    GenericList *list = *listp;
+    QapiDeallocVisitor *qov = to_qov(v);
+    StackEntry *e = QTAILQ_FIRST(&qov->stack);
+
+    if (e && e->is_list_head) {
+        e->is_list_head = false;
+        return list;
+    }
+
+    if (list) {
+        list = list->next;
+        g_free(*listp);
+        return list;
+    }
+
+    return NULL;
 }
 
 static void qapi_dealloc_end_list(Visitor *v, Error **errp)
 {
+    QapiDeallocVisitor *qov = to_qov(v);
+    void *obj = qapi_dealloc_pop(qov);
+    assert(obj == NULL); /* should've been list head tracker with no payload */
 }
 
 static void qapi_dealloc_type_str(Visitor *v, char **obj, const char *name,
index a79bc2b3c3126f17d03f65478d3959c57bb206ee..27e6be0a878ce4018eb594b0e6c048f9d02cd299 100644 (file)
@@ -17,4 +17,7 @@
 #include "qemu-common.h"
 #include "error.h"
 
+/* FIXME this is temporary until we remove middle mode */
+#include "monitor.h"
+
 #endif
index fcf8bf920b1ada0aa0e8111dc22ba1ff63aec28d..8cbc0abcfd4c432fc65554807be22a12babac336 100644 (file)
@@ -144,8 +144,6 @@ static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
         }
         (*list)->next = entry;
     }
-    *list = entry;
-
 
     return entry;
 }
@@ -240,9 +238,11 @@ static void qmp_input_type_enum(Visitor *v, int *obj, const char *strings[],
 
     if (strings[value] == NULL) {
         error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
+        g_free(enum_str);
         return;
     }
 
+    g_free(enum_str);
     *obj = value;
 }
 
index 4419a31644689f2a80851578af7156a0e844c987..d67724ea4bde46e3255a73674e6c314a1d40e81f 100644 (file)
@@ -20,6 +20,7 @@
 typedef struct QStackEntry
 {
     QObject *value;
+    bool is_list_head;
     QTAILQ_ENTRY(QStackEntry) node;
 } QStackEntry;
 
@@ -45,6 +46,9 @@ static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value)
     QStackEntry *e = g_malloc0(sizeof(*e));
 
     e->value = value;
+    if (qobject_type(e->value) == QTYPE_QLIST) {
+        e->is_list_head = true;
+    }
     QTAILQ_INSERT_HEAD(&qov->stack, e, node);
 }
 
@@ -122,12 +126,20 @@ static void qmp_output_start_list(Visitor *v, const char *name, Error **errp)
     qmp_output_push(qov, list);
 }
 
-static GenericList *qmp_output_next_list(Visitor *v, GenericList **list,
+static GenericList *qmp_output_next_list(Visitor *v, GenericList **listp,
                                          Error **errp)
 {
-    GenericList *retval = *list;
-    *list = retval->next;
-    return retval;
+    GenericList *list = *listp;
+    QmpOutputVisitor *qov = to_qov(v);
+    QStackEntry *e = QTAILQ_FIRST(&qov->stack);
+
+    assert(e);
+    if (e->is_list_head) {
+        e->is_list_head = false;
+        return list;
+    }
+
+    return list ? list->next : NULL;
 }
 
 static void qmp_output_end_list(Visitor *v, Error **errp)
index 09d2309eb6b2b29d683b7097a781ecf6f976ceca..8bdbcfdad20b004d2324a3ded9c454db2dad25db 100644 (file)
@@ -31,7 +31,7 @@
 #include "hw/usb.h"
 #include "hw/baum.h"
 #include "hw/msmouse.h"
-#include "qemu-objects.h"
+#include "qmp-commands.h"
 
 #include <unistd.h>
 #include <fcntl.h>
@@ -2650,35 +2650,22 @@ void qemu_chr_delete(CharDriverState *chr)
     g_free(chr);
 }
 
-static void qemu_chr_qlist_iter(QObject *obj, void *opaque)
+ChardevInfoList *qmp_query_chardev(Error **errp)
 {
-    QDict *chr_dict;
-    Monitor *mon = opaque;
-
-    chr_dict = qobject_to_qdict(obj);
-    monitor_printf(mon, "%s: filename=%s\n", qdict_get_str(chr_dict, "label"),
-                                         qdict_get_str(chr_dict, "filename"));
-}
-
-void qemu_chr_info_print(Monitor *mon, const QObject *ret_data)
-{
-    qlist_iter(qobject_to_qlist(ret_data), qemu_chr_qlist_iter, mon);
-}
-
-void qemu_chr_info(Monitor *mon, QObject **ret_data)
-{
-    QList *chr_list;
+    ChardevInfoList *chr_list = NULL;
     CharDriverState *chr;
 
-    chr_list = qlist_new();
-
     QTAILQ_FOREACH(chr, &chardevs, next) {
-        QObject *obj = qobject_from_jsonf("{ 'label': %s, 'filename': %s }",
-                                          chr->label, chr->filename);
-        qlist_append_obj(chr_list, obj);
+        ChardevInfoList *info = g_malloc0(sizeof(*info));
+        info->value = g_malloc0(sizeof(*info->value));
+        info->value->label = g_strdup(chr->label);
+        info->value->filename = g_strdup(chr->filename);
+
+        info->next = chr_list;
+        chr_list = info;
     }
 
-    *ret_data = QOBJECT(chr_list);
+    return chr_list;
 }
 
 CharDriverState *qemu_chr_find(const char *name)
index c591a5443cedb4d3d85dae95218edbd44d5aeb6e..68998d4bab9b4b1c7a5063f79b0869805616e954 100644 (file)
--- a/qerror.c
+++ b/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
  */
index d4070015f726d80e3a88a6f5990df1da853b4e15..d4bfcfd16713e50ac474ed8fec50719c9deec960 100644 (file)
--- a/qerror.h
+++ b/qerror.h
@@ -15,6 +15,7 @@
 #include "qdict.h"
 #include "qstring.h"
 #include "qemu-error.h"
+#include "error.h"
 #include <stdarg.h>
 
 typedef struct QErrorStringTable {
@@ -39,6 +40,7 @@ QString *qerror_human(const QError *qerror);
 void qerror_print(QError *qerror);
 void qerror_report_internal(const char *file, int linenr, const char *func,
                             const char *fmt, ...) GCC_FMT_ATTR(4, 5);
+void qerror_report_err(Error *err);
 QString *qerror_format(const char *fmt, QDict *error);
 #define qerror_report(fmt, ...) \
     qerror_report_internal(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__)
index d83bce5662871ba9a0956c73790730a4c03e6895..ea96191c12830deb5f72de3a2cb6cf674c9a2ba2 100644 (file)
@@ -63,10 +63,7 @@ EQMP
     {
         .name       = "quit",
         .args_type  = "",
-        .params     = "",
-        .help       = "quit the emulator",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_quit,
+        .mhandler.cmd_new = qmp_marshal_input_quit,
     },
 
 SQMP
@@ -181,10 +178,7 @@ EQMP
     {
         .name       = "stop",
         .args_type  = "",
-        .params     = "",
-        .help       = "stop emulation",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_stop,
+        .mhandler.cmd_new = qmp_marshal_input_stop,
     },
 
 SQMP
@@ -229,10 +223,7 @@ EQMP
     {
         .name       = "system_reset",
         .args_type  = "",
-        .params     = "",
-        .help       = "reset the system",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_system_reset,
+        .mhandler.cmd_new = qmp_marshal_input_system_reset,
     },
 
 SQMP
@@ -1053,6 +1044,12 @@ Example:
 
 EQMP
 
+    {
+        .name       = "query-version",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_version,
+    },
+
 SQMP
 query-commands
 --------------
@@ -1084,6 +1081,12 @@ Note: This example has been shortened as the real response is too long.
 
 EQMP
 
+    {
+        .name       = "query-commands",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_commands,
+    },
+
 SQMP
 query-chardev
 -------------
@@ -1114,6 +1117,12 @@ Example:
 
 EQMP
 
+    {
+        .name       = "query-chardev",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_chardev,
+    },
+
 SQMP
 query-block
 -----------
@@ -1564,6 +1573,12 @@ Example:
 
 EQMP
 
+    {
+        .name       = "query-kvm",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_kvm,
+    },
+
 SQMP
 query-status
 ------------
@@ -1597,6 +1612,12 @@ Example:
 <- { "return": { "running": true, "singlestep": false, "status": "running" } }
 
 EQMP
+    
+    {
+        .name       = "query-status",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_status,
+    },
 
 SQMP
 query-mice
@@ -1780,6 +1801,12 @@ Example:
 
 EQMP
 
+    {
+        .name       = "query-name",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_name,
+    },
+
 SQMP
 query-uuid
 ----------
@@ -1797,6 +1824,12 @@ Example:
 
 EQMP
 
+    {
+        .name       = "query-uuid",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_uuid,
+    },
+
 SQMP
 query-migrate
 -------------
diff --git a/qmp.c b/qmp.c
new file mode 100644 (file)
index 0000000..bf58b05
--- /dev/null
+++ b/qmp.c
@@ -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();
+}
index 46f2447dc07cfdd4adb8db270ba7d684f5cc529d..bf4d0e76c315c3a5d0715b2fa109c9e0c60e2e36 100644 (file)
--- a/savevm.c
+++ b/savevm.c
@@ -1603,7 +1603,7 @@ static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
     int ret;
 
     saved_vm_running = runstate_is_running();
-    vm_stop(RSTATE_SAVEVM);
+    vm_stop(RUN_STATE_SAVE_VM);
 
     if (qemu_savevm_state_blocked(mon)) {
         ret = -EINVAL;
@@ -1932,7 +1932,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
     }
 
     saved_vm_running = runstate_is_running();
-    vm_stop(RSTATE_SAVEVM);
+    vm_stop(RUN_STATE_SAVE_VM);
 
     memset(sn, 0, sizeof(*sn));
 
index bf617401ad2651b0ed1079100558eb1691b94973..c947ba4208c20986c6edad27e59b1d86874df90a 100644 (file)
@@ -17,12 +17,18 @@ import os
 import getopt
 import errno
 
+def type_visitor(name):
+    if type(name) == list:
+        return 'visit_type_%sList' % name[0]
+    else:
+        return 'visit_type_%s' % name
+
 def generate_decl_enum(name, members, genlist=True):
     return mcgen('''
 
-void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp);
+void %(visitor)s(Visitor *m, %(name)s * obj, const char *name, Error **errp);
 ''',
-                name=name)
+                 visitor=type_visitor(name))
 
 def generate_command_decl(name, args, ret_type):
     arglist=""
@@ -146,9 +152,10 @@ if (has_%(c_name)s) {
                          c_name=c_var(argname), name=argname)
             push_indent()
         ret += mcgen('''
-visit_type_%(argtype)s(v, &%(c_name)s, "%(name)s", errp);
+%(visitor)s(v, &%(c_name)s, "%(name)s", errp);
 ''',
-                      c_name=c_var(argname), name=argname, argtype=argtype)
+                     c_name=c_var(argname), name=argname, argtype=argtype,
+                     visitor=type_visitor(argtype))
         if optional:
             pop_indent()
             ret += mcgen('''
@@ -167,9 +174,10 @@ qmp_input_visitor_cleanup(mi);
     pop_indent()
     return ret.rstrip()
 
-def gen_marshal_output(name, args, ret_type):
+def gen_marshal_output(name, args, ret_type, middle_mode):
     if not ret_type:
         return ""
+
     ret = mcgen('''
 static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp)
 {
@@ -178,26 +186,44 @@ static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_o
     Visitor *v;
 
     v = qmp_output_get_visitor(mo);
-    visit_type_%(ret_type)s(v, &ret_in, "unused", errp);
+    %(visitor)s(v, &ret_in, "unused", errp);
     if (!error_is_set(errp)) {
         *ret_out = qmp_output_get_qobject(mo);
     }
     qmp_output_visitor_cleanup(mo);
     v = qapi_dealloc_get_visitor(md);
-    visit_type_%(ret_type)s(v, &ret_in, "unused", errp);
+    %(visitor)s(v, &ret_in, "unused", errp);
     qapi_dealloc_visitor_cleanup(md);
 }
 ''',
-            c_ret_type=c_type(ret_type), c_name=c_var(name), ret_type=ret_type)
+                c_ret_type=c_type(ret_type), c_name=c_var(name),
+                visitor=type_visitor(ret_type))
 
     return ret
 
-def gen_marshal_input(name, args, ret_type):
+def gen_marshal_input_decl(name, args, ret_type, middle_mode):
+    if middle_mode:
+        return 'int qmp_marshal_input_%s(Monitor *mon, const QDict *qdict, QObject **ret)' % c_var(name)
+    else:
+        return 'static void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_var(name)
+
+
+
+def gen_marshal_input(name, args, ret_type, middle_mode):
+    hdr = gen_marshal_input_decl(name, args, ret_type, middle_mode)
+
     ret = mcgen('''
-static void qmp_marshal_input_%(c_name)s(QDict *args, QObject **ret, Error **errp)
+%(header)s
 {
 ''',
-                c_name=c_var(name))
+                header=hdr)
+
+    if middle_mode:
+        ret += mcgen('''
+    Error *local_err = NULL;
+    Error **errp = &local_err;
+    QDict *args = (QDict *)qdict;
+''')
 
     if ret_type:
         if c_type(ret_type).endswith("*"):
@@ -220,6 +246,10 @@ 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_vars_decl=gen_visitor_input_vars_decl(args),
                      visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)"))
+    else:
+        ret += mcgen('''
+    (void)args;
+''')
 
     ret += mcgen('''
     if (error_is_set(errp)) {
@@ -234,10 +264,29 @@ out:
 ''')
     ret += mcgen('''
 %(visitor_input_block_cleanup)s
+''',
+                 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('''
 }
-''',
-                 visitor_input_block_cleanup=gen_visitor_input_block(args, None, dealloc=True))
+''')
+
     return ret
 
 def gen_registry(commands):
@@ -284,7 +333,7 @@ def gen_command_decl_prologue(header, guard, prefix=""):
 #include "error.h"
 
 ''',
-                 header=basename(h_file), guard=guardname(h_file), prefix=prefix)
+                 header=basename(header), guard=guardname(header), prefix=prefix)
     return ret
 
 def gen_command_def_prologue(prefix="", proxy=False):
@@ -317,11 +366,11 @@ def gen_command_def_prologue(prefix="", proxy=False):
                 prefix=prefix)
     if not proxy:
         ret += '#include "%sqmp-commands.h"' % prefix
-    return ret + "\n"
+    return ret + "\n\n"
 
 
 try:
-    opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", "output-dir=", "type="])
+    opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:m", ["prefix=", "output-dir=", "type=", "middle"])
 except getopt.GetoptError, err:
     print str(err)
     sys.exit(1)
@@ -331,6 +380,7 @@ prefix = ""
 dispatch_type = "sync"
 c_file = 'qmp-marshal.c'
 h_file = 'qmp-commands.h'
+middle_mode = False
 
 for o, a in opts:
     if o in ("-p", "--prefix"):
@@ -339,6 +389,8 @@ for o, a in opts:
         output_dir = a + "/"
     elif o in ("-t", "--type"):
         dispatch_type = a
+    elif o in ("-m", "--middle"):
+        middle_mode = True
 
 c_file = output_dir + prefix + c_file
 h_file = output_dir + prefix + h_file
@@ -370,14 +422,20 @@ if dispatch_type == "sync":
         ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
         fdecl.write(ret)
         if ret_type:
-            ret = gen_marshal_output(cmd['command'], arglist, ret_type) + "\n"
+            ret = gen_marshal_output(cmd['command'], arglist, ret_type, middle_mode) + "\n"
             fdef.write(ret)
-        ret = gen_marshal_input(cmd['command'], arglist, ret_type) + "\n"
+
+        if middle_mode:
+            fdecl.write('%s;\n' % gen_marshal_input_decl(cmd['command'], arglist, ret_type, middle_mode))
+
+        ret = gen_marshal_input(cmd['command'], arglist, ret_type, middle_mode) + "\n"
         fdef.write(ret)
 
     fdecl.write("\n#endif\n");
-    ret = gen_registry(commands)
-    fdef.write(ret)
+
+    if not middle_mode:
+        ret = gen_registry(commands)
+        fdef.write(ret)
 
     fdef.flush()
     fdef.close()
index cece32546a65f3690df44c2f1899cc7c86a35dee..f64d84c39ea7ae7b6f5f60ef997e0a7ae9b9cc5f 100644 (file)
@@ -70,7 +70,7 @@ const char *%(name)s_lookup[] = {
         ret += mcgen('''
     "%(value)s",
 ''',
-                     value=c_var(value).lower())
+                     value=value.lower())
 
     ret += mcgen('''
     NULL,
@@ -91,8 +91,11 @@ typedef enum %(name)s
 ''',
                 name=name)
 
+    # append automatically generated _MAX value
+    enum_values = values + [ 'MAX' ]
+
     i = 0
-    for value in values:
+    for value in enum_values:
         enum_decl += mcgen('''
     %(abbrev)s_%(value)s = %(i)d,
 ''',
@@ -254,6 +257,8 @@ for expr in exprs:
     ret = "\n"
     if expr.has_key('type'):
         ret += generate_struct(expr['type'], "", expr['data']) + "\n"
+        ret += generate_type_cleanup_decl(expr['type'] + "List")
+        fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n")
         ret += generate_type_cleanup_decl(expr['type'])
         fdef.write(generate_type_cleanup(expr['type']) + "\n")
     elif expr.has_key('union'):
@@ -268,3 +273,6 @@ fdecl.write('''
 
 fdecl.flush()
 fdecl.close()
+
+fdef.flush()
+fdef.close()
index 252230ef25f256c8babccc0e579c6a39c70678a9..62de83d0f085b4a1dc59d8a390c3b6f29d98a94d 100644 (file)
@@ -79,11 +79,11 @@ def generate_visit_list(name, members):
 
 void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp)
 {
-    GenericList *i;
+    GenericList *i, **head = (GenericList **)obj;
 
     visit_start_list(m, name, errp);
 
-    for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) {
+    for (*head = i = visit_next_list(m, head, errp); i; i = visit_next_list(m, &i, errp)) {
         %(name)sList *native_i = (%(name)sList *)i;
         visit_type_%(name)s(m, &native_i->value, NULL, errp);
     }
index 56af2329bb4a4db772a3930e9c6a33d7a1e75211..52999763eef4faad1c53d61a24b9f10cd5be2646 100644 (file)
@@ -200,4 +200,6 @@ def basename(filename):
     return filename.split("/")[-1]
 
 def guardname(filename):
-    return filename.replace("/", "_").replace("-", "_").split(".")[0].upper()
+    if filename.startswith('./'):
+        filename = filename[2:]
+    return filename.replace("/", "_").replace("-", "_").split(".")[0].upper() + '_H'
index 43ff546f9b08c4501383a87416abd6a7af39ffba..a889d90957970cd01b48f707b700ab8f350852bd 100644 (file)
--- a/sysemu.h
+++ b/sysemu.h
@@ -6,28 +6,11 @@
 #include "qemu-option.h"
 #include "qemu-queue.h"
 #include "qemu-timer.h"
+#include "qapi-types.h"
 #include "notify.h"
 
 /* vl.c */
 
-typedef enum {
-    RSTATE_NO_STATE,
-    RSTATE_DEBUG,          /* qemu is running under gdb */
-    RSTATE_IN_MIGRATE,     /* paused waiting for an incoming migration */
-    RSTATE_PANICKED,       /* paused due to an internal error */
-    RSTATE_IO_ERROR,       /* paused due to an I/O error */
-    RSTATE_PAUSED,         /* paused by the user (ie. the 'stop' command) */
-    RSTATE_POST_MIGRATE,   /* paused following a successful migration */
-    RSTATE_PRE_LAUNCH,     /* qemu was started with -S and haven't started */
-    RSTATE_PRE_MIGRATE,    /* paused preparing to finish migrate */
-    RSTATE_RESTORE,        /* paused restoring the VM state */
-    RSTATE_RUNNING,        /* qemu is running */
-    RSTATE_SAVEVM,         /* paused saving VM state */
-    RSTATE_SHUTDOWN,       /* guest shut down and -no-shutdown is in use */
-    RSTATE_WATCHDOG,       /* watchdog fired and qemu is configured to pause */
-    RSTATE_MAX
-} RunState;
-
 extern const char *bios_name;
 
 extern const char *qemu_name;
@@ -39,7 +22,6 @@ void runstate_init(void);
 bool runstate_check(RunState state);
 void runstate_set(RunState new_state);
 int runstate_is_running(void);
-const char *runstate_as_string(void);
 typedef struct vm_change_state_entry VMChangeStateEntry;
 typedef void VMChangeStateHandler(void *opaque, int running, RunState state);
 
index f142cc616d7de4cbb0114b1765e5f061be90eea9..fa5a7bd8dc72354d1d536e793e7f75e90ef1ae88 100644 (file)
@@ -98,6 +98,34 @@ static void test_dispatch_cmd_io(void)
     QDECREF(req);
 }
 
+/* test generated dealloc functions for generated types */
+static void test_dealloc_types(void)
+{
+    UserDefOne *ud1test, *ud1a, *ud1b;
+    UserDefOneList *ud1list;
+
+    ud1test = g_malloc0(sizeof(UserDefOne));
+    ud1test->integer = 42;
+    ud1test->string = g_strdup("hi there 42");
+
+    qapi_free_UserDefOne(ud1test);
+
+    ud1a = g_malloc0(sizeof(UserDefOne));
+    ud1a->integer = 43;
+    ud1a->string = g_strdup("hi there 43");
+
+    ud1b = g_malloc0(sizeof(UserDefOne));
+    ud1b->integer = 44;
+    ud1b->string = g_strdup("hi there 44");
+
+    ud1list = g_malloc0(sizeof(UserDefOneList));
+    ud1list->value = ud1a;
+    ud1list->next = g_malloc0(sizeof(UserDefOneList));
+    ud1list->next->value = ud1b;
+
+    qapi_free_UserDefOneList(ud1list);
+}
+
 int main(int argc, char **argv)
 {
     g_test_init(&argc, &argv, NULL);
@@ -105,6 +133,7 @@ int main(int argc, char **argv)
     g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd);
     g_test_add_func("/0.15/dispatch_cmd_error", test_dispatch_cmd_error);
     g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io);
+    g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
 
     module_call_init(MODULE_INIT_QAPI);
     g_test_run();
index b7717deb6d38e81f4d7be617d4d65399b09b0d0d..847ce14ea1328f4551c170c609cb3150e440b8ff 100644 (file)
@@ -27,11 +27,11 @@ static void visit_type_TestStruct(Visitor *v, TestStruct **obj, const char *name
 
 static void visit_type_TestStructList(Visitor *m, TestStructList ** obj, const char *name, Error **errp)
 {
-    GenericList *i;
+    GenericList *i, **head = (GenericList **)obj;
 
     visit_start_list(m, name, errp);
 
-    for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) {
+    for (*head = i = visit_next_list(m, head, errp); i; i = visit_next_list(m, &i, errp)) {
         TestStructList *native_i = (TestStructList *)i;
         visit_type_TestStruct(m, &native_i->value, NULL, errp);
     }
@@ -50,6 +50,8 @@ static void test_visitor_core(void)
     TestStructList *lts = NULL;
     Error *err = NULL;
     QObject *obj;
+    QList *qlist;
+    QDict *qdict;
     QString *str;
     int64_t value = 0;
 
@@ -96,7 +98,9 @@ static void test_visitor_core(void)
     g_assert(pts->y == 84);
 
     qobject_decref(obj);
+    g_free(pts);
 
+    /* test list input visitor */
     obj = qobject_from_json("[{'x': 42, 'y': 84}, {'x': 12, 'y': 24}]");
     mi = qmp_input_visitor_new(obj);
     v = qmp_input_get_visitor(mi);
@@ -110,14 +114,41 @@ static void test_visitor_core(void)
     g_assert(lts->value->x == 42);
     g_assert(lts->value->y == 84);
 
-    lts = lts->next;
-    g_assert(lts != NULL);
-    g_assert(lts->value->x == 12);
-    g_assert(lts->value->y == 24);
+    g_assert(lts->next != NULL);
+    g_assert(lts->next->value->x == 12);
+    g_assert(lts->next->value->y == 24);
+    g_assert(lts->next->next == NULL);
 
-    g_assert(lts->next == NULL);
+    qobject_decref(obj);
 
+    /* test list output visitor */
+    mo = qmp_output_visitor_new();
+    v = qmp_output_get_visitor(mo);
+    visit_type_TestStructList(v, &lts, NULL, &err);
+    if (err) {
+        g_error("%s", error_get_pretty(err));
+    }
+    obj = qmp_output_get_qobject(mo);
+    g_print("obj: %s\n", qstring_get_str(qobject_to_json(obj)));
+
+    qlist = qobject_to_qlist(obj);
+    assert(qlist);
+    obj = qlist_pop(qlist);
+    qdict = qobject_to_qdict(obj);
+    assert(qdict);
+    assert(qdict_get_int(qdict, "x") == 42);
+    assert(qdict_get_int(qdict, "y") == 84);
+    qobject_decref(obj);
+
+    obj = qlist_pop(qlist);
+    qdict = qobject_to_qdict(obj);
+    assert(qdict);
+    assert(qdict_get_int(qdict, "x") == 12);
+    assert(qdict_get_int(qdict, "y") == 24);
     qobject_decref(obj);
+
+    qmp_output_visitor_cleanup(mo);
+    QDECREF(qlist);
 }
 
 /* test deep nesting with refs to other user-defined types */
@@ -286,7 +317,8 @@ static void test_nested_enums(void)
     g_assert(nested_enums_cpy->has_enum2 == false);
     g_assert(nested_enums_cpy->has_enum4 == true);
 
-    qobject_decref(obj);
+    qmp_output_visitor_cleanup(mo);
+    qmp_input_visitor_cleanup(mi);
     qapi_free_NestedEnumsOne(nested_enums);
     qapi_free_NestedEnumsOne(nested_enums_cpy);
 }
diff --git a/vl.c b/vl.c
index bd4a5ce8a2fdeec593e916eb5351be08087b5bd3..dbf77781a7378f77c3702a82968af356fa04609b 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -147,6 +147,7 @@ int main(int argc, char **argv)
 #include "qemu-config.h"
 #include "qemu-objects.h"
 #include "qemu-options.h"
+#include "qmp-commands.h"
 #ifdef CONFIG_VIRTFS
 #include "fsdev/qemu-fsdev.h"
 #endif
@@ -323,7 +324,7 @@ static int default_driver_check(QemuOpts *opts, void *opaque)
 /***********************************************************/
 /* QEMU state */
 
-static RunState current_run_state = RSTATE_NO_STATE;
+static RunState current_run_state = RUN_STATE_PRELAUNCH;
 
 typedef struct {
     RunState from;
@@ -332,67 +333,48 @@ typedef struct {
 
 static const RunStateTransition runstate_transitions_def[] = {
     /*     from      ->     to      */
-    { RSTATE_NO_STATE, RSTATE_RUNNING },
-    { RSTATE_NO_STATE, RSTATE_IN_MIGRATE },
-    { RSTATE_NO_STATE, RSTATE_PRE_LAUNCH },
+    { RUN_STATE_DEBUG, RUN_STATE_RUNNING },
 
-    { RSTATE_DEBUG, RSTATE_RUNNING },
+    { RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
+    { RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH },
 
-    { RSTATE_IN_MIGRATE, RSTATE_RUNNING },
-    { RSTATE_IN_MIGRATE, RSTATE_PRE_LAUNCH },
+    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
 
-    { RSTATE_PANICKED, RSTATE_PAUSED },
+    { RUN_STATE_IO_ERROR, RUN_STATE_RUNNING },
 
-    { RSTATE_IO_ERROR, RSTATE_RUNNING },
+    { RUN_STATE_PAUSED, RUN_STATE_RUNNING },
 
-    { RSTATE_PAUSED, RSTATE_RUNNING },
+    { RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
 
-    { RSTATE_POST_MIGRATE, RSTATE_RUNNING },
+    { RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING },
+    { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
+    { RUN_STATE_PRELAUNCH, RUN_STATE_POSTMIGRATE },
 
-    { RSTATE_PRE_LAUNCH, RSTATE_RUNNING },
-    { RSTATE_PRE_LAUNCH, RSTATE_POST_MIGRATE },
+    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
+    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
 
-    { RSTATE_PRE_MIGRATE, RSTATE_RUNNING },
-    { RSTATE_PRE_MIGRATE, RSTATE_POST_MIGRATE },
+    { RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
 
-    { RSTATE_RESTORE, RSTATE_RUNNING },
+    { RUN_STATE_RUNNING, RUN_STATE_DEBUG },
+    { RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR },
+    { RUN_STATE_RUNNING, RUN_STATE_IO_ERROR },
+    { RUN_STATE_RUNNING, RUN_STATE_PAUSED },
+    { RUN_STATE_RUNNING, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_RUNNING, RUN_STATE_RESTORE_VM },
+    { RUN_STATE_RUNNING, RUN_STATE_SAVE_VM },
+    { RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN },
+    { RUN_STATE_RUNNING, RUN_STATE_WATCHDOG },
 
-    { RSTATE_RUNNING, RSTATE_DEBUG },
-    { RSTATE_RUNNING, RSTATE_PANICKED },
-    { RSTATE_RUNNING, RSTATE_IO_ERROR },
-    { RSTATE_RUNNING, RSTATE_PAUSED },
-    { RSTATE_RUNNING, RSTATE_PRE_MIGRATE },
-    { RSTATE_RUNNING, RSTATE_RESTORE },
-    { RSTATE_RUNNING, RSTATE_SAVEVM },
-    { RSTATE_RUNNING, RSTATE_SHUTDOWN },
-    { RSTATE_RUNNING, RSTATE_WATCHDOG },
+    { RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
 
-    { RSTATE_SAVEVM, RSTATE_RUNNING },
+    { RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
 
-    { RSTATE_SHUTDOWN, RSTATE_PAUSED },
+    { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
 
-    { RSTATE_WATCHDOG, RSTATE_RUNNING },
-
-    { RSTATE_MAX, RSTATE_MAX },
+    { RUN_STATE_MAX, RUN_STATE_MAX },
 };
 
-static bool runstate_valid_transitions[RSTATE_MAX][RSTATE_MAX];
-
-static const char *const runstate_name_tbl[RSTATE_MAX] = {
-    [RSTATE_DEBUG] = "debug",
-    [RSTATE_IN_MIGRATE] = "incoming-migration",
-    [RSTATE_PANICKED] = "internal-error",
-    [RSTATE_IO_ERROR] = "io-error",
-    [RSTATE_PAUSED] = "paused",
-    [RSTATE_POST_MIGRATE] = "post-migrate",
-    [RSTATE_PRE_LAUNCH] = "prelaunch",
-    [RSTATE_PRE_MIGRATE] = "finish-migrate",
-    [RSTATE_RESTORE] = "restore-vm",
-    [RSTATE_RUNNING] = "running",
-    [RSTATE_SAVEVM] = "save-vm",
-    [RSTATE_SHUTDOWN] = "shutdown",
-    [RSTATE_WATCHDOG] = "watchdog",
-};
+static bool runstate_valid_transitions[RUN_STATE_MAX][RUN_STATE_MAX];
 
 bool runstate_check(RunState state)
 {
@@ -405,7 +387,7 @@ void runstate_init(void)
 
     memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
 
-    for (p = &runstate_transitions_def[0]; p->from != RSTATE_MAX; p++) {
+    for (p = &runstate_transitions_def[0]; p->from != RUN_STATE_MAX; p++) {
         runstate_valid_transitions[p->from][p->to] = true;
     }
 }
@@ -413,7 +395,7 @@ void runstate_init(void)
 /* This function will abort() on invalid state transitions */
 void runstate_set(RunState new_state)
 {
-    if (new_state >= RSTATE_MAX ||
+    if (new_state >= RUN_STATE_MAX ||
         !runstate_valid_transitions[current_run_state][new_state]) {
         fprintf(stderr, "invalid runstate transition\n");
         abort();
@@ -422,16 +404,20 @@ void runstate_set(RunState new_state)
     current_run_state = new_state;
 }
 
-const char *runstate_as_string(void)
+int runstate_is_running(void)
 {
-    assert(current_run_state > RSTATE_NO_STATE &&
-           current_run_state < RSTATE_MAX);
-    return runstate_name_tbl[current_run_state];
+    return runstate_check(RUN_STATE_RUNNING);
 }
 
-int runstate_is_running(void)
+StatusInfo *qmp_query_status(Error **errp)
 {
-    return runstate_check(RSTATE_RUNNING);
+    StatusInfo *info = g_malloc0(sizeof(*info));
+
+    info->running = runstate_is_running();
+    info->singlestep = singlestep;
+    info->status = current_run_state;
+
+    return info;
 }
 
 /***********************************************************/
@@ -1272,8 +1258,8 @@ void vm_start(void)
 {
     if (!runstate_is_running()) {
         cpu_enable_ticks();
-        runstate_set(RSTATE_RUNNING);
-        vm_state_notify(1, RSTATE_RUNNING);
+        runstate_set(RUN_STATE_RUNNING);
+        vm_state_notify(1, RUN_STATE_RUNNING);
         resume_all_vcpus();
         monitor_protocol_event(QEVENT_RESUME, NULL);
     }
@@ -1294,7 +1280,7 @@ static int shutdown_requested, shutdown_signal = -1;
 static pid_t shutdown_pid;
 static int powerdown_requested;
 static int debug_requested;
-static RunState vmstop_requested = RSTATE_NO_STATE;
+static RunState vmstop_requested = RUN_STATE_MAX;
 
 int qemu_shutdown_requested_get(void)
 {
@@ -1350,11 +1336,16 @@ static int qemu_debug_requested(void)
     return r;
 }
 
-static RunState qemu_vmstop_requested(void)
+/* We use RUN_STATE_MAX but any invalid value will do */
+static bool qemu_vmstop_requested(RunState *r)
 {
-    RunState s = vmstop_requested;
-    vmstop_requested = RSTATE_NO_STATE;
-    return s;
+    if (vmstop_requested < RUN_STATE_MAX) {
+        *r = vmstop_requested;
+        vmstop_requested = RUN_STATE_MAX;
+        return true;
+    }
+
+    return false;
 }
 
 void qemu_register_reset(QEMUResetHandler *func, void *opaque)
@@ -1567,7 +1558,7 @@ static void main_loop(void)
 #ifdef CONFIG_PROFILER
     int64_t ti;
 #endif
-    int r;
+    RunState r;
 
     qemu_main_loop_start();
 
@@ -1582,13 +1573,13 @@ static void main_loop(void)
 #endif
 
         if (qemu_debug_requested()) {
-            vm_stop(RSTATE_DEBUG);
+            vm_stop(RUN_STATE_DEBUG);
         }
         if (qemu_shutdown_requested()) {
             qemu_kill_report();
             monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
             if (no_shutdown) {
-                vm_stop(RSTATE_SHUTDOWN);
+                vm_stop(RUN_STATE_SHUTDOWN);
             } else
                 break;
         }
@@ -1597,16 +1588,16 @@ static void main_loop(void)
             cpu_synchronize_all_states();
             qemu_system_reset(VMRESET_REPORT);
             resume_all_vcpus();
-            if (runstate_check(RSTATE_PANICKED) ||
-                runstate_check(RSTATE_SHUTDOWN)) {
-                runstate_set(RSTATE_PAUSED);
+            if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
+                runstate_check(RUN_STATE_SHUTDOWN)) {
+                runstate_set(RUN_STATE_PAUSED);
             }
         }
         if (qemu_powerdown_requested()) {
             monitor_protocol_event(QEVENT_POWERDOWN, NULL);
             qemu_irq_raise(qemu_system_powerdown);
         }
-        if ((r = qemu_vmstop_requested())) {
+        if (qemu_vmstop_requested(&r)) {
             vm_stop(r);
         }
     }
@@ -3556,7 +3547,7 @@ int main(int argc, char **argv, char **envp)
     }
 
     if (incoming) {
-        runstate_set(RSTATE_IN_MIGRATE);
+        runstate_set(RUN_STATE_INMIGRATE);
         int ret = qemu_start_incoming_migration(incoming);
         if (ret < 0) {
             fprintf(stderr, "Migration failed. Exit code %s(%d), exiting.\n",
@@ -3565,8 +3556,6 @@ int main(int argc, char **argv, char **envp)
         }
     } else if (autostart) {
         vm_start();
-    } else {
-        runstate_set(RSTATE_PRE_LAUNCH);
     }
 
     os_setup_post();