summary refs log tree commit diff stats
path: root/qapi
diff options
context:
space:
mode:
Diffstat (limited to 'qapi')
-rw-r--r--qapi/qapi-dealloc-visitor.c147
-rw-r--r--qapi/qapi-dealloc-visitor.h26
-rw-r--r--qapi/qapi-types-core.h20
-rw-r--r--qapi/qapi-visit-core.c118
-rw-r--r--qapi/qapi-visit-core.h76
-rw-r--r--qapi/qmp-core.h41
-rw-r--r--qapi/qmp-dispatch.c124
-rw-r--r--qapi/qmp-input-visitor.c301
-rw-r--r--qapi/qmp-input-visitor.h27
-rw-r--r--qapi/qmp-output-visitor.c239
-rw-r--r--qapi/qmp-output-visitor.h28
-rw-r--r--qapi/qmp-registry.c40
12 files changed, 1187 insertions, 0 deletions
diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
new file mode 100644
index 0000000000..8cde4dd0d4
--- /dev/null
+++ b/qapi/qapi-dealloc-visitor.c
@@ -0,0 +1,147 @@
+/*
+ * Dealloc Visitor
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Michael Roth   <mdroth@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qapi-dealloc-visitor.h"
+#include "qemu-queue.h"
+#include "qemu-common.h"
+#include "qemu-objects.h"
+
+typedef struct StackEntry
+{
+    void *value;
+    QTAILQ_ENTRY(StackEntry) node;
+} StackEntry;
+
+struct QapiDeallocVisitor
+{
+    Visitor visitor;
+    QTAILQ_HEAD(, StackEntry) stack;
+};
+
+static QapiDeallocVisitor *to_qov(Visitor *v)
+{
+    return container_of(v, QapiDeallocVisitor, visitor);
+}
+
+static void qapi_dealloc_push(QapiDeallocVisitor *qov, void *value)
+{
+    StackEntry *e = qemu_mallocz(sizeof(*e));
+
+    e->value = value;
+    QTAILQ_INSERT_HEAD(&qov->stack, e, node);
+}
+
+static void *qapi_dealloc_pop(QapiDeallocVisitor *qov)
+{
+    StackEntry *e = QTAILQ_FIRST(&qov->stack);
+    QObject *value;
+    QTAILQ_REMOVE(&qov->stack, e, node);
+    value = e->value;
+    qemu_free(e);
+    return value;
+}
+
+static void qapi_dealloc_start_struct(Visitor *v, void **obj, const char *kind,
+                                      const char *name, size_t unused,
+                                      Error **errp)
+{
+    QapiDeallocVisitor *qov = to_qov(v);
+    qapi_dealloc_push(qov, obj);
+}
+
+static void qapi_dealloc_end_struct(Visitor *v, Error **errp)
+{
+    QapiDeallocVisitor *qov = to_qov(v);
+    void **obj = qapi_dealloc_pop(qov);
+    if (obj) {
+        qemu_free(*obj);
+    }
+}
+
+static void qapi_dealloc_start_list(Visitor *v, const char *name, Error **errp)
+{
+}
+
+static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **list,
+                                           Error **errp)
+{
+    GenericList *retval = *list;
+    qemu_free(retval->value);
+    *list = retval->next;
+    return retval;
+}
+
+static void qapi_dealloc_end_list(Visitor *v, Error **errp)
+{
+}
+
+static void qapi_dealloc_type_str(Visitor *v, char **obj, const char *name,
+                                  Error **errp)
+{
+    if (obj) {
+        qemu_free(*obj);
+    }
+}
+
+static void qapi_dealloc_type_int(Visitor *v, int64_t *obj, const char *name,
+                                  Error **errp)
+{
+}
+
+static void qapi_dealloc_type_bool(Visitor *v, bool *obj, const char *name,
+                                   Error **errp)
+{
+}
+
+static void qapi_dealloc_type_number(Visitor *v, double *obj, const char *name,
+                                     Error **errp)
+{
+}
+
+static void qapi_dealloc_type_enum(Visitor *v, int *obj, const char *strings[],
+                                   const char *kind, const char *name,
+                                   Error **errp)
+{
+}
+
+Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v)
+{
+    return &v->visitor;
+}
+
+void qapi_dealloc_visitor_cleanup(QapiDeallocVisitor *v)
+{
+    qemu_free(v);
+}
+
+QapiDeallocVisitor *qapi_dealloc_visitor_new(void)
+{
+    QapiDeallocVisitor *v;
+
+    v = qemu_mallocz(sizeof(*v));
+
+    v->visitor.start_struct = qapi_dealloc_start_struct;
+    v->visitor.end_struct = qapi_dealloc_end_struct;
+    v->visitor.start_list = qapi_dealloc_start_list;
+    v->visitor.next_list = qapi_dealloc_next_list;
+    v->visitor.end_list = qapi_dealloc_end_list;
+    v->visitor.type_enum = qapi_dealloc_type_enum;
+    v->visitor.type_int = qapi_dealloc_type_int;
+    v->visitor.type_bool = qapi_dealloc_type_bool;
+    v->visitor.type_str = qapi_dealloc_type_str;
+    v->visitor.type_number = qapi_dealloc_type_number;
+
+    QTAILQ_INIT(&v->stack);
+
+    return v;
+}
diff --git a/qapi/qapi-dealloc-visitor.h b/qapi/qapi-dealloc-visitor.h
new file mode 100644
index 0000000000..5842bc79bd
--- /dev/null
+++ b/qapi/qapi-dealloc-visitor.h
@@ -0,0 +1,26 @@
+/*
+ * Dealloc Visitor
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Michael Roth   <mdroth@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QAPI_DEALLOC_VISITOR_H
+#define QAPI_DEALLOC_VISITOR_H
+
+#include "qapi-visit-core.h"
+
+typedef struct QapiDeallocVisitor QapiDeallocVisitor;
+
+QapiDeallocVisitor *qapi_dealloc_visitor_new(void);
+void qapi_dealloc_visitor_cleanup(QapiDeallocVisitor *d);
+
+Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v);
+
+#endif
diff --git a/qapi/qapi-types-core.h b/qapi/qapi-types-core.h
new file mode 100644
index 0000000000..a79bc2b3c3
--- /dev/null
+++ b/qapi/qapi-types-core.h
@@ -0,0 +1,20 @@
+/*
+ * Core Definitions for QAPI-generated Types
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QAPI_TYPES_CORE_H
+#define QAPI_TYPES_CORE_H
+
+#include "qemu-common.h"
+#include "error.h"
+
+#endif
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
new file mode 100644
index 0000000000..ddef3eda12
--- /dev/null
+++ b/qapi/qapi-visit-core.c
@@ -0,0 +1,118 @@
+/*
+ * Core Definitions for QAPI Visitor Classes
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qapi/qapi-visit-core.h"
+
+void visit_start_handle(Visitor *v, void **obj, const char *kind,
+                        const char *name, Error **errp)
+{
+    if (!error_is_set(errp) && v->start_handle) {
+        v->start_handle(v, obj, kind, name, errp);
+    }
+}
+
+void visit_end_handle(Visitor *v, Error **errp)
+{
+    if (!error_is_set(errp) && v->end_handle) {
+        v->end_handle(v, errp);
+    }
+}
+
+void visit_start_struct(Visitor *v, void **obj, const char *kind,
+                        const char *name, size_t size, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->start_struct(v, obj, kind, name, size, errp);
+    }
+}
+
+void visit_end_struct(Visitor *v, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->end_struct(v, errp);
+    }
+}
+
+void visit_start_list(Visitor *v, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->start_list(v, name, errp);
+    }
+}
+
+GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        return v->next_list(v, list, errp);
+    }
+
+    return 0;
+}
+
+void visit_end_list(Visitor *v, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->end_list(v, errp);
+    }
+}
+
+void visit_start_optional(Visitor *v, bool *present, const char *name,
+                          Error **errp)
+{
+    if (!error_is_set(errp) && v->start_optional) {
+        v->start_optional(v, present, name, errp);
+    }
+}
+
+void visit_end_optional(Visitor *v, Error **errp)
+{
+    if (!error_is_set(errp) && v->end_optional) {
+        v->end_optional(v, errp);
+    }
+}
+
+void visit_type_enum(Visitor *v, int *obj, const char *strings[],
+                     const char *kind, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->type_enum(v, obj, strings, kind, name, errp);
+    }
+}
+
+void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->type_int(v, obj, name, errp);
+    }
+}
+
+void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->type_bool(v, obj, name, errp);
+    }
+}
+
+void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->type_str(v, obj, name, errp);
+    }
+}
+
+void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        v->type_number(v, obj, name, errp);
+    }
+}
diff --git a/qapi/qapi-visit-core.h b/qapi/qapi-visit-core.h
new file mode 100644
index 0000000000..e850746b75
--- /dev/null
+++ b/qapi/qapi-visit-core.h
@@ -0,0 +1,76 @@
+/*
+ * Core Definitions for QAPI Visitor Classes
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+#ifndef QAPI_VISITOR_CORE_H
+#define QAPI_VISITOR_CORE_H
+
+#include "qapi/qapi-types-core.h"
+#include <stdlib.h>
+
+typedef struct GenericList
+{
+    void *value;
+    struct GenericList *next;
+} GenericList;
+
+typedef struct Visitor Visitor;
+
+struct Visitor
+{
+    /* Must be set */
+    void (*start_struct)(Visitor *v, void **obj, const char *kind,
+                         const char *name, size_t size, Error **errp);
+    void (*end_struct)(Visitor *v, Error **errp);
+
+    void (*start_list)(Visitor *v, const char *name, Error **errp);
+    GenericList *(*next_list)(Visitor *v, GenericList **list, Error **errp);
+    void (*end_list)(Visitor *v, Error **errp);
+
+    void (*type_enum)(Visitor *v, int *obj, const char *strings[],
+                      const char *kind, const char *name, Error **errp);
+
+    void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp);
+    void (*type_bool)(Visitor *v, bool *obj, const char *name, Error **errp);
+    void (*type_str)(Visitor *v, char **obj, const char *name, Error **errp);
+    void (*type_number)(Visitor *v, double *obj, const char *name,
+                        Error **errp);
+
+    /* May be NULL */
+    void (*start_optional)(Visitor *v, bool *present, const char *name,
+                           Error **errp);
+    void (*end_optional)(Visitor *v, Error **errp);
+
+    void (*start_handle)(Visitor *v, void **obj, const char *kind,
+                         const char *name, Error **errp);
+    void (*end_handle)(Visitor *v, Error **errp);
+};
+
+void visit_start_handle(Visitor *v, void **obj, const char *kind,
+                        const char *name, Error **errp);
+void visit_end_handle(Visitor *v, Error **errp);
+void visit_start_struct(Visitor *v, void **obj, const char *kind,
+                        const char *name, size_t size, Error **errp);
+void visit_end_struct(Visitor *v, Error **errp);
+void visit_start_list(Visitor *v, const char *name, Error **errp);
+GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp);
+void visit_end_list(Visitor *v, Error **errp);
+void visit_start_optional(Visitor *v, bool *present, const char *name,
+                          Error **errp);
+void visit_end_optional(Visitor *v, Error **errp);
+void visit_type_enum(Visitor *v, int *obj, const char *strings[],
+                     const char *kind, const char *name, Error **errp);
+void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp);
+void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
+void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
+void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
+
+#endif
diff --git a/qapi/qmp-core.h b/qapi/qmp-core.h
new file mode 100644
index 0000000000..f1c26e4b2e
--- /dev/null
+++ b/qapi/qmp-core.h
@@ -0,0 +1,41 @@
+/*
+ * Core Definitions for QAPI/QMP Dispatch
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QMP_CORE_H
+#define QMP_CORE_H
+
+#include "qobject.h"
+#include "qdict.h"
+#include "error.h"
+
+typedef void (QmpCommandFunc)(QDict *, QObject **, Error **);
+
+typedef enum QmpCommandType
+{
+    QCT_NORMAL,
+} QmpCommandType;
+
+typedef struct QmpCommand
+{
+    const char *name;
+    QmpCommandType type;
+    QmpCommandFunc *fn;
+    QTAILQ_ENTRY(QmpCommand) node;
+} QmpCommand;
+
+void qmp_register_command(const char *name, QmpCommandFunc *fn);
+QmpCommand *qmp_find_command(const char *name);
+QObject *qmp_dispatch(QObject *request);
+
+#endif
+
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
new file mode 100644
index 0000000000..558469325c
--- /dev/null
+++ b/qapi/qmp-dispatch.c
@@ -0,0 +1,124 @@
+/*
+ * Core Definitions for QAPI/QMP Dispatch
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu-objects.h"
+#include "qapi/qmp-core.h"
+#include "json-parser.h"
+#include "error.h"
+#include "error_int.h"
+#include "qerror.h"
+
+static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp)
+{
+    const QDictEntry *ent;
+    const char *arg_name;
+    const QObject *arg_obj;
+    bool has_exec_key = false;
+    QDict *dict = NULL;
+
+    if (qobject_type(request) != QTYPE_QDICT) {
+        error_set(errp, QERR_QMP_BAD_INPUT_OBJECT,
+                  "request is not a dictionary");
+        return NULL;
+    }
+
+    dict = qobject_to_qdict(request);
+
+    for (ent = qdict_first(dict); ent;
+         ent = qdict_next(dict, ent)) {
+        arg_name = qdict_entry_key(ent);
+        arg_obj = qdict_entry_value(ent);
+
+        if (!strcmp(arg_name, "execute")) {
+            if (qobject_type(arg_obj) != QTYPE_QSTRING) {
+                error_set(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute",
+                          "string");
+                return NULL;
+            }
+            has_exec_key = true;
+        } else if (strcmp(arg_name, "arguments")) {
+            error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
+            return NULL;
+        }
+    }
+
+    if (!has_exec_key) {
+        error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute");
+        return NULL;
+    }
+
+    return dict;
+}
+
+static QObject *do_qmp_dispatch(QObject *request, Error **errp)
+{
+    const char *command;
+    QDict *args, *dict;
+    QmpCommand *cmd;
+    QObject *ret = NULL;
+
+
+    dict = qmp_dispatch_check_obj(request, errp);
+    if (!dict || error_is_set(errp)) {
+        return NULL;
+    }
+
+    command = qdict_get_str(dict, "execute");
+    cmd = qmp_find_command(command);
+    if (cmd == NULL) {
+        error_set(errp, QERR_COMMAND_NOT_FOUND, command);
+        return NULL;
+    }
+
+    if (!qdict_haskey(dict, "arguments")) {
+        args = qdict_new();
+    } else {
+        args = qdict_get_qdict(dict, "arguments");
+        QINCREF(args);
+    }
+
+    switch (cmd->type) {
+    case QCT_NORMAL:
+        cmd->fn(args, &ret, errp);
+        if (!error_is_set(errp) && ret == NULL) {
+            ret = QOBJECT(qdict_new());
+        }
+        break;
+    }
+
+    QDECREF(args);
+
+    return ret;
+}
+
+QObject *qmp_dispatch(QObject *request)
+{
+    Error *err = NULL;
+    QObject *ret;
+    QDict *rsp;
+
+    ret = do_qmp_dispatch(request, &err);
+
+    rsp = qdict_new();
+    if (err) {
+        qdict_put_obj(rsp, "error", error_get_qobject(err));
+        error_free(err);
+    } else if (ret) {
+        qdict_put_obj(rsp, "return", ret);
+    } else {
+        QDECREF(rsp);
+        return NULL;
+    }
+
+    return QOBJECT(rsp);
+}
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
new file mode 100644
index 0000000000..6a1adc9fce
--- /dev/null
+++ b/qapi/qmp-input-visitor.c
@@ -0,0 +1,301 @@
+/*
+ * Input Visitor
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qmp-input-visitor.h"
+#include "qemu-queue.h"
+#include "qemu-common.h"
+#include "qemu-objects.h"
+#include "qerror.h"
+
+#define QIV_STACK_SIZE 1024
+
+typedef struct StackObject
+{
+    const QObject *obj;
+    const  QListEntry *entry;
+} StackObject;
+
+struct QmpInputVisitor
+{
+    Visitor visitor;
+    QObject *obj;
+    StackObject stack[QIV_STACK_SIZE];
+    int nb_stack;
+};
+
+static QmpInputVisitor *to_qiv(Visitor *v)
+{
+    return container_of(v, QmpInputVisitor, visitor);
+}
+
+static const QObject *qmp_input_get_object(QmpInputVisitor *qiv,
+                                           const char *name)
+{
+    const QObject *qobj;
+
+    if (qiv->nb_stack == 0) {
+        qobj = qiv->obj;
+    } else {
+        qobj = qiv->stack[qiv->nb_stack - 1].obj;
+    }
+
+    if (name && qobject_type(qobj) == QTYPE_QDICT) {
+        return qdict_get(qobject_to_qdict(qobj), name);
+    } else if (qiv->nb_stack > 0 && qobject_type(qobj) == QTYPE_QLIST) {
+        return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry);
+    }
+
+    return qobj;
+}
+
+static void qmp_input_push(QmpInputVisitor *qiv, const QObject *obj, Error **errp)
+{
+    qiv->stack[qiv->nb_stack].obj = obj;
+    if (qobject_type(obj) == QTYPE_QLIST) {
+        qiv->stack[qiv->nb_stack].entry = qlist_first(qobject_to_qlist(obj));
+    }
+    qiv->nb_stack++;
+
+    if (qiv->nb_stack >= QIV_STACK_SIZE) {
+        error_set(errp, QERR_BUFFER_OVERRUN);
+        return;
+    }
+}
+
+static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
+{
+    qiv->nb_stack--;
+    if (qiv->nb_stack < 0) {
+        error_set(errp, QERR_BUFFER_OVERRUN);
+        return;
+    }
+}
+
+static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind,
+                                   const char *name, size_t size, Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj || qobject_type(qobj) != QTYPE_QDICT) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                  "QDict");
+        return;
+    }
+
+    qmp_input_push(qiv, qobj, errp);
+    if (error_is_set(errp)) {
+        return;
+    }
+
+    if (obj) {
+        *obj = qemu_mallocz(size);
+    }
+}
+
+static void qmp_input_end_struct(Visitor *v, Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+
+    qmp_input_pop(qiv, errp);
+}
+
+static void qmp_input_start_list(Visitor *v, const char *name, Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj || qobject_type(qobj) != QTYPE_QLIST) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                  "list");
+        return;
+    }
+
+    qmp_input_push(qiv, qobj, errp);
+}
+
+static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
+                                        Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    GenericList *entry;
+    StackObject *so = &qiv->stack[qiv->nb_stack - 1];
+
+    if (so->entry == NULL) {
+        return NULL;
+    }
+
+    entry = qemu_mallocz(sizeof(*entry));
+    if (*list) {
+        so->entry = qlist_next(so->entry);
+        if (so->entry == NULL) {
+            qemu_free(entry);
+            return NULL;
+        }
+        (*list)->next = entry;
+    }
+    *list = entry;
+
+
+    return entry;
+}
+
+static void qmp_input_end_list(Visitor *v, Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+
+    qmp_input_pop(qiv, errp);
+}
+
+static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name,
+                               Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj || qobject_type(qobj) != QTYPE_QINT) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                  "integer");
+        return;
+    }
+
+    *obj = qint_get_int(qobject_to_qint(qobj));
+}
+
+static void qmp_input_type_bool(Visitor *v, bool *obj, const char *name,
+                                Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                  "boolean");
+        return;
+    }
+
+    *obj = qbool_get_int(qobject_to_qbool(qobj));
+}
+
+static void qmp_input_type_str(Visitor *v, char **obj, const char *name,
+                               Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                  "string");
+        return;
+    }
+
+    *obj = qemu_strdup(qstring_get_str(qobject_to_qstring(qobj)));
+}
+
+static void qmp_input_type_number(Visitor *v, double *obj, const char *name,
+                                  Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj || qobject_type(qobj) != QTYPE_QFLOAT) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                  "double");
+        return;
+    }
+
+    *obj = qfloat_get_double(qobject_to_qfloat(qobj));
+}
+
+static void qmp_input_type_enum(Visitor *v, int *obj, const char *strings[],
+                                const char *kind, const char *name,
+                                Error **errp)
+{
+    int64_t value = 0;
+    char *enum_str;
+
+    assert(strings);
+
+    qmp_input_type_str(v, &enum_str, name, errp);
+    if (error_is_set(errp)) {
+        return;
+    }
+
+    while (strings[value] != NULL) {
+        if (strcmp(strings[value], enum_str) == 0) {
+            break;
+        }
+        value++;
+    }
+
+    if (strings[value] == NULL) {
+        error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
+        return;
+    }
+
+    *obj = value;
+}
+
+static void qmp_input_start_optional(Visitor *v, bool *present,
+                                     const char *name, Error **errp)
+{
+    QmpInputVisitor *qiv = to_qiv(v);
+    const QObject *qobj = qmp_input_get_object(qiv, name);
+
+    if (!qobj) {
+        *present = false;
+        return;
+    }
+
+    *present = true;
+}
+
+static void qmp_input_end_optional(Visitor *v, Error **errp)
+{
+}
+
+Visitor *qmp_input_get_visitor(QmpInputVisitor *v)
+{
+    return &v->visitor;
+}
+
+void qmp_input_visitor_cleanup(QmpInputVisitor *v)
+{
+    qobject_decref(v->obj);
+    qemu_free(v);
+}
+
+QmpInputVisitor *qmp_input_visitor_new(QObject *obj)
+{
+    QmpInputVisitor *v;
+
+    v = qemu_mallocz(sizeof(*v));
+
+    v->visitor.start_struct = qmp_input_start_struct;
+    v->visitor.end_struct = qmp_input_end_struct;
+    v->visitor.start_list = qmp_input_start_list;
+    v->visitor.next_list = qmp_input_next_list;
+    v->visitor.end_list = qmp_input_end_list;
+    v->visitor.type_enum = qmp_input_type_enum;
+    v->visitor.type_int = qmp_input_type_int;
+    v->visitor.type_bool = qmp_input_type_bool;
+    v->visitor.type_str = qmp_input_type_str;
+    v->visitor.type_number = qmp_input_type_number;
+    v->visitor.start_optional = qmp_input_start_optional;
+    v->visitor.end_optional = qmp_input_end_optional;
+
+    v->obj = obj;
+    qobject_incref(v->obj);
+
+    return v;
+}
diff --git a/qapi/qmp-input-visitor.h b/qapi/qmp-input-visitor.h
new file mode 100644
index 0000000000..3f798f0335
--- /dev/null
+++ b/qapi/qmp-input-visitor.h
@@ -0,0 +1,27 @@
+/*
+ * Input Visitor
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QMP_INPUT_VISITOR_H
+#define QMP_INPUT_VISITOR_H
+
+#include "qapi-visit-core.h"
+#include "qobject.h"
+
+typedef struct QmpInputVisitor QmpInputVisitor;
+
+QmpInputVisitor *qmp_input_visitor_new(QObject *obj);
+void qmp_input_visitor_cleanup(QmpInputVisitor *v);
+
+Visitor *qmp_input_get_visitor(QmpInputVisitor *v);
+
+#endif
diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c
new file mode 100644
index 0000000000..c398cac4f0
--- /dev/null
+++ b/qapi/qmp-output-visitor.c
@@ -0,0 +1,239 @@
+/*
+ * Core Definitions for QAPI/QMP Command Registry
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qmp-output-visitor.h"
+#include "qemu-queue.h"
+#include "qemu-common.h"
+#include "qemu-objects.h"
+#include "qerror.h"
+
+typedef struct QStackEntry
+{
+    QObject *value;
+    QTAILQ_ENTRY(QStackEntry) node;
+} QStackEntry;
+
+typedef QTAILQ_HEAD(QStack, QStackEntry) QStack;
+
+struct QmpOutputVisitor
+{
+    Visitor visitor;
+    QStack stack;
+};
+
+#define qmp_output_add(qov, name, value) \
+    qmp_output_add_obj(qov, name, QOBJECT(value))
+#define qmp_output_push(qov, value) qmp_output_push_obj(qov, QOBJECT(value))
+
+static QmpOutputVisitor *to_qov(Visitor *v)
+{
+    return container_of(v, QmpOutputVisitor, visitor);
+}
+
+static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value)
+{
+    QStackEntry *e = qemu_mallocz(sizeof(*e));
+
+    e->value = value;
+    QTAILQ_INSERT_HEAD(&qov->stack, e, node);
+}
+
+static QObject *qmp_output_pop(QmpOutputVisitor *qov)
+{
+    QStackEntry *e = QTAILQ_FIRST(&qov->stack);
+    QObject *value;
+    QTAILQ_REMOVE(&qov->stack, e, node);
+    value = e->value;
+    qemu_free(e);
+    return value;
+}
+
+static QObject *qmp_output_first(QmpOutputVisitor *qov)
+{
+    QStackEntry *e = QTAILQ_LAST(&qov->stack, QStack);
+    return e->value;
+}
+
+static QObject *qmp_output_last(QmpOutputVisitor *qov)
+{
+    QStackEntry *e = QTAILQ_FIRST(&qov->stack);
+    return e->value;
+}
+
+static void qmp_output_add_obj(QmpOutputVisitor *qov, const char *name,
+                               QObject *value)
+{
+    QObject *cur;
+
+    if (QTAILQ_EMPTY(&qov->stack)) {
+        qmp_output_push_obj(qov, value);
+        return;
+    }
+
+    cur = qmp_output_last(qov);
+
+    switch (qobject_type(cur)) {
+    case QTYPE_QDICT:
+        qdict_put_obj(qobject_to_qdict(cur), name, value);
+        break;
+    case QTYPE_QLIST:
+        qlist_append_obj(qobject_to_qlist(cur), value);
+        break;
+    default:
+        qobject_decref(qmp_output_pop(qov));
+        qmp_output_push_obj(qov, value);
+        break;
+    }
+}
+
+static void qmp_output_start_struct(Visitor *v, void **obj, const char *kind,
+                                    const char *name, size_t unused,
+                                    Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    QDict *dict = qdict_new();
+
+    qmp_output_add(qov, name, dict);
+    qmp_output_push(qov, dict);
+}
+
+static void qmp_output_end_struct(Visitor *v, Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    qmp_output_pop(qov);
+}
+
+static void qmp_output_start_list(Visitor *v, const char *name, Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    QList *list = qlist_new();
+
+    qmp_output_add(qov, name, list);
+    qmp_output_push(qov, list);
+}
+
+static GenericList *qmp_output_next_list(Visitor *v, GenericList **list,
+                                         Error **errp)
+{
+    GenericList *retval = *list;
+    *list = retval->next;
+    return retval;
+}
+
+static void qmp_output_end_list(Visitor *v, Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    qmp_output_pop(qov);
+}
+
+static void qmp_output_type_int(Visitor *v, int64_t *obj, const char *name,
+                                Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    qmp_output_add(qov, name, qint_from_int(*obj));
+}
+
+static void qmp_output_type_bool(Visitor *v, bool *obj, const char *name,
+                                 Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    qmp_output_add(qov, name, qbool_from_int(*obj));
+}
+
+static void qmp_output_type_str(Visitor *v, char **obj, const char *name,
+                                Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    if (*obj) {
+        qmp_output_add(qov, name, qstring_from_str(*obj));
+    } else {
+        qmp_output_add(qov, name, qstring_from_str(""));
+    }
+}
+
+static void qmp_output_type_number(Visitor *v, double *obj, const char *name,
+                                   Error **errp)
+{
+    QmpOutputVisitor *qov = to_qov(v);
+    qmp_output_add(qov, name, qfloat_from_double(*obj));
+}
+
+static void qmp_output_type_enum(Visitor *v, int *obj, const char *strings[],
+                                 const char *kind, const char *name,
+                                 Error **errp)
+{
+    int i = 0;
+    int value = *obj;
+    char *enum_str;
+
+    assert(strings);
+    while (strings[i++] != NULL);
+    if (value >= i - 1) {
+        error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
+        return;
+    }
+
+    enum_str = (char *)strings[value];
+    qmp_output_type_str(v, &enum_str, name, errp);
+}
+
+QObject *qmp_output_get_qobject(QmpOutputVisitor *qov)
+{
+    QObject *obj = qmp_output_first(qov);
+    if (obj) {
+        qobject_incref(obj);
+    }
+    return obj;
+}
+
+Visitor *qmp_output_get_visitor(QmpOutputVisitor *v)
+{
+    return &v->visitor;
+}
+
+void qmp_output_visitor_cleanup(QmpOutputVisitor *v)
+{
+    QStackEntry *e, *tmp;
+
+    QTAILQ_FOREACH_SAFE(e, &v->stack, node, tmp) {
+        QTAILQ_REMOVE(&v->stack, e, node);
+        if (e->value) {
+            qobject_decref(e->value);
+        }
+        qemu_free(e);
+    }
+
+    qemu_free(v);
+}
+
+QmpOutputVisitor *qmp_output_visitor_new(void)
+{
+    QmpOutputVisitor *v;
+
+    v = qemu_mallocz(sizeof(*v));
+
+    v->visitor.start_struct = qmp_output_start_struct;
+    v->visitor.end_struct = qmp_output_end_struct;
+    v->visitor.start_list = qmp_output_start_list;
+    v->visitor.next_list = qmp_output_next_list;
+    v->visitor.end_list = qmp_output_end_list;
+    v->visitor.type_enum = qmp_output_type_enum;
+    v->visitor.type_int = qmp_output_type_int;
+    v->visitor.type_bool = qmp_output_type_bool;
+    v->visitor.type_str = qmp_output_type_str;
+    v->visitor.type_number = qmp_output_type_number;
+
+    QTAILQ_INIT(&v->stack);
+
+    return v;
+}
diff --git a/qapi/qmp-output-visitor.h b/qapi/qmp-output-visitor.h
new file mode 100644
index 0000000000..4a649c2504
--- /dev/null
+++ b/qapi/qmp-output-visitor.h
@@ -0,0 +1,28 @@
+/*
+ * Output Visitor
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QMP_OUTPUT_VISITOR_H
+#define QMP_OUTPUT_VISITOR_H
+
+#include "qapi-visit-core.h"
+#include "qobject.h"
+
+typedef struct QmpOutputVisitor QmpOutputVisitor;
+
+QmpOutputVisitor *qmp_output_visitor_new(void);
+void qmp_output_visitor_cleanup(QmpOutputVisitor *v);
+
+QObject *qmp_output_get_qobject(QmpOutputVisitor *v);
+Visitor *qmp_output_get_visitor(QmpOutputVisitor *v);
+
+#endif
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
new file mode 100644
index 0000000000..3fe8866d44
--- /dev/null
+++ b/qapi/qmp-registry.c
@@ -0,0 +1,40 @@
+/*
+ * Core Definitions for QAPI/QMP Dispatch
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *  Michael Roth      <mdroth@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qapi/qmp-core.h"
+
+static QTAILQ_HEAD(, QmpCommand) qmp_commands =
+    QTAILQ_HEAD_INITIALIZER(qmp_commands);
+
+void qmp_register_command(const char *name, QmpCommandFunc *fn)
+{
+    QmpCommand *cmd = qemu_mallocz(sizeof(*cmd));
+
+    cmd->name = name;
+    cmd->type = QCT_NORMAL;
+    cmd->fn = fn;
+    QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node);
+}
+
+QmpCommand *qmp_find_command(const char *name)
+{
+    QmpCommand *i;
+
+    QTAILQ_FOREACH(i, &qmp_commands, node) {
+        if (strcmp(i->name, name) == 0) {
+            return i;
+        }
+    }
+    return NULL;
+}