All of lore.kernel.org
 help / color / mirror / Atom feed
From: zwu.kernel@gmail.com
To: qemu-devel@nongnu.org
Cc: zwu.kernel@gmail.com, pbonzini@redhat.com,
	Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>,
	stefanha@linux.vnet.ibm.com
Subject: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model
Date: Mon, 26 Mar 2012 13:40:13 +0800	[thread overview]
Message-ID: <1332740423-8426-2-git-send-email-zwu.kernel@gmail.com> (raw)
In-Reply-To: <1332740423-8426-1-git-send-email-zwu.kernel@gmail.com>

From: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>

Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
---
 include/qemu/hostdev.h |  128 ++++++++++++++++++
 qom/Makefile           |    2 +-
 qom/hostdev.c          |  333 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 462 insertions(+), 1 deletions(-)
 create mode 100644 include/qemu/hostdev.h
 create mode 100644 qom/hostdev.c

diff --git a/include/qemu/hostdev.h b/include/qemu/hostdev.h
new file mode 100644
index 0000000..a291761
--- /dev/null
+++ b/include/qemu/hostdev.h
@@ -0,0 +1,128 @@
+/*
+ * QEMU host device model
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Zhi Yong Wu   <wuzhy@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_HOSTDEV_H
+#define QEMU_HOSTDEV_H
+
+#include "qemu-queue.h"
+#include "qemu-char.h"
+#include "qemu-option.h"
+#include "qapi/qapi-visit-core.h"
+#include "qemu/object.h"
+
+typedef struct hostdevProperty hostdevProperty;
+typedef struct hostdevPropertyInfo hostdevPropertyInfo;
+
+/**
+ * SECTION: hostdev
+ * @section_id: QEMU-hostdev
+ * @title: hostdev Class
+ * @short_description: Base class for all host devices
+ */
+
+typedef struct HOSTDevice HOSTDevice;
+
+#define TYPE_HOSTDEV "host-dev"
+#define HOST_DEVICE(obj) \
+     OBJECT_CHECK(HOSTDevice, (obj), TYPE_HOSTDEV)
+#define HOSTDEV_CLASS(klass) \
+     OBJECT_CLASS_CHECK(HOSTDeviceClass, (klass), TYPE_HOSTDEV)
+#define HOSTDEV_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(HOSTDeviceClass, (obj), TYPE_HOSTDEV)
+
+/**
+ * HOSTDeviceClass:
+ *
+ * Represents a host device model.
+ */
+typedef struct HOSTDeviceClass {
+    ObjectClass parent_class;
+    hostdevProperty *props;
+
+    int (*init)(HOSTDevice *host_dv);
+} HOSTDeviceClass;
+
+/**
+ * HOSTDevice:
+ *
+ * State of one host device.
+ */
+struct HOSTDevice {
+    /*< private >*/
+    Object parent_obj;
+
+    /*< public >*/
+};
+
+struct hostdevProperty {
+    const char   *name;
+    hostdevPropertyInfo *info;
+    int          offset;
+    uint8_t      bitnr;
+    uint8_t      qtype;
+    int64_t      defval;
+};
+
+struct hostdevPropertyInfo {
+    const char *name;
+    const char *legacy_name;
+    const char **enum_table;
+    int64_t min;
+    int64_t max;
+    int (*parse)(HOSTDevice *dev,
+                 hostdevProperty *prop,
+                 const char *str);
+    int (*print)(HOSTDevice *dev,
+                 hostdevProperty *prop,
+                 char *dest,
+                 size_t len);
+    ObjectPropertyAccessor *get;
+    ObjectPropertyAccessor *set;
+    ObjectPropertyRelease *release;
+};
+
+extern hostdevPropertyInfo hostdev_prop_int32;
+extern hostdevPropertyInfo hostdev_prop_string;
+extern hostdevPropertyInfo hostdev_prop_netdev;
+
+#define DEFINE_HOSTDEV_PROP(_name, _state, _field, _prop, _type) { \
+        .name      = (_name),                                    \
+        .info      = &(_prop),                                   \
+        .offset    = offsetof(_state, _field)                    \
+            + type_check(_type,typeof_field(_state, _field)),    \
+        }
+#define DEFINE_HOSTDEV_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \
+        .name      = (_name),                                           \
+        .info      = &(_prop),                                          \
+        .offset    = offsetof(_state, _field)                           \
+            + type_check(_type,typeof_field(_state, _field)),           \
+        .qtype     = QTYPE_QINT,                                        \
+        .defval    = (_type)_defval,                                    \
+        }
+#define DEFINE_HOSTDEV_PROP_END_OF_LIST()               \
+    {}
+#define DEFINE_HOSTDEV_PROP_INT32(_n, _s, _f, _d)              \
+    DEFINE_HOSTDEV_PROP_DEFAULT(_n, _s, _f, _d, hostdev_prop_int32, int32_t)
+#define DEFINE_HOSTDEV_PROP_PEER(_n, _s, _f)             \
+    DEFINE_HOSTDEV_PROP(_n, _s, _f, hostdev_prop_netdev, NetClientState*)
+#define DEFINE_HOSTDEV_PROP_STRING(_n, _s, _f)             \
+    DEFINE_HOSTDEV_PROP(_n, _s, _f, hostdev_prop_string, char*)
+
+HOSTDevice *hostdev_device_create(const char *type);
+int hostdev_device_init(HOSTDevice *dev, const char *type, const char *id);
+void hostdev_prop_set_string(HOSTDevice *dev,
+                             const char *name, char *value);
+void hostdev_prop_set_peer(HOSTDevice *dev,
+                           const char *name, NetClientState *value);
+
+#endif
diff --git a/qom/Makefile b/qom/Makefile
index 34c6de5..4731fb9 100644
--- a/qom/Makefile
+++ b/qom/Makefile
@@ -1,2 +1,2 @@
 qom-y = object.o container.o qom-qobject.o
-qom-twice-y = cpu.o
+qom-twice-y = cpu.o hostdev.o
diff --git a/qom/hostdev.c b/qom/hostdev.c
new file mode 100644
index 0000000..867e869
--- /dev/null
+++ b/qom/hostdev.c
@@ -0,0 +1,333 @@
+/*
+ * QEMU host device model
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Zhi Yong Wu   <wuzhy@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/hostdev.h"
+#include "qemu-common.h"
+#include "net.h"
+
+void hostdev_prop_set_string(HOSTDevice *dev,
+                             const char *name, char *value)
+{
+    Error *errp = NULL;
+    object_property_set_str(OBJECT(dev), value, name, &errp);
+    assert_no_error(errp);
+}
+
+void hostdev_prop_set_peer(HOSTDevice *dev,
+                           const char *name, NetClientState *value)
+{
+    Error *errp = NULL;
+    assert(!value || value->name);
+    object_property_set_str(OBJECT(dev),
+                            value ? value->name : "", name, &errp);
+    assert_no_error(errp);
+}
+
+static Object *hostdev_get_hostdev(void)
+{
+    static Object *dev;
+
+    if (dev == NULL) {
+        dev = object_new("container");
+        object_property_add_child(object_get_root(), "hostdev",
+                                  OBJECT(dev), NULL);
+    }
+
+    return dev;
+}
+
+HOSTDevice *hostdev_device_create(const char *type)
+{
+    HOSTDevice *hostdev;
+
+    hostdev = HOST_DEVICE(object_new(type));
+    if (!hostdev) {
+        return NULL;
+    }
+
+    return hostdev;
+}
+
+int hostdev_device_init(HOSTDevice *dev, const char *type, const char *id)
+{
+    HOSTDeviceClass *dc = HOSTDEV_GET_CLASS(dev);
+    gchar *dev_id;
+    int rc;
+
+    rc = dc->init(dev);
+    if (rc < 0) {
+        object_delete(OBJECT(dev));
+        return rc;
+    }
+
+    if (id) {
+        dev_id = g_strdup(id);
+    } else {
+        static int anon_count;
+        dev_id = g_strdup_printf("%s[%d]", (char *)type, anon_count++);
+    }
+
+    object_property_add_child(hostdev_get_hostdev(), dev_id,
+                              OBJECT(dev), NULL);
+    g_free(dev_id);
+
+    return 0;
+}
+
+static void *hostdev_get_prop_ptr(HOSTDevice *dev, hostdevProperty *prop)
+{
+    void *ptr = dev;
+    ptr += prop->offset;
+    return ptr;
+}
+
+static void error_set_from_hostdev_prop_error(Error **errp, int ret,
+                                              HOSTDevice *dev, hostdevProperty *prop,
+                                              const char *value)
+{
+    switch (ret) {
+    case -EEXIST:
+        error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
+                  object_get_typename(OBJECT(dev)), prop->name, value);
+        break;
+    default:
+    case -EINVAL:
+        error_set(errp, QERR_PROPERTY_VALUE_BAD,
+                  object_get_typename(OBJECT(dev)), prop->name, value);
+        break;
+    case -ENOENT:
+        error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
+                  object_get_typename(OBJECT(dev)), prop->name, value);
+        break;
+    case 0:
+        break;
+    }
+}
+
+/* --- netdev device --- */
+static void get_pointer(Object *obj, Visitor *v, hostdevProperty *prop,
+                        const char *(*print)(void *ptr),
+                        const char *name, Error **errp)
+{
+    HOSTDevice *dev = HOST_DEVICE(obj);
+    void **ptr = hostdev_get_prop_ptr(dev, prop);
+    char *p;
+
+    p = (char *) (*ptr ? print(*ptr) : "");
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_pointer(Object *obj, Visitor *v, hostdevProperty *prop,
+                        int (*parse)(HOSTDevice *dev, const char *str, void **ptr),
+                        const char *name, Error **errp)
+{
+    HOSTDevice *dev = HOST_DEVICE(obj);
+    Error *local_err = NULL;
+    void **ptr = hostdev_get_prop_ptr(dev, prop);
+    char *str;
+    int ret;
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if (!*str) {
+        g_free(str);
+        *ptr = NULL;
+        return;
+    }
+    ret = parse(dev, str, ptr);
+    error_set_from_hostdev_prop_error(errp, ret, dev, prop, str);
+    g_free(str);
+}
+
+/* --- 32bit integer --- */
+static void get_int32(Object *obj, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    HOSTDevice *dev = HOST_DEVICE(obj);
+    hostdevProperty *prop = opaque;
+    int32_t *ptr = hostdev_get_prop_ptr(dev, prop);
+    int64_t value;
+
+    value = *ptr;
+    visit_type_int(v, &value, name, errp);
+}
+
+static void set_int32(Object *obj, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    HOSTDevice *dev = HOST_DEVICE(obj);
+    hostdevProperty *prop = opaque;
+    int32_t *ptr = hostdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    int64_t value;
+
+    visit_type_int(v, &value, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if (value >= prop->info->min && value <= prop->info->max) {
+        *ptr = value;
+    } else {
+        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
+                  "", name, value, prop->info->min,
+                  prop->info->max);
+    }
+}
+
+hostdevPropertyInfo hostdev_prop_int32 = {
+    .name  = "int32",
+    .get   = get_int32,
+    .set   = set_int32,
+    .min   = -0x80000000LL,
+    .max   = 0x7FFFFFFFLL,
+};
+
+/* --- netdev --- */
+static int parse_netdev(HOSTDevice *dev, const char *str, void **ptr)
+{
+    NetClientState *netdev = qemu_find_netdev(str);
+
+    if (netdev == NULL) {
+        return -ENOENT;
+    }
+    if (netdev->peer) {
+        return -EEXIST;
+    }
+    *ptr = netdev;
+    return 0;
+}
+
+static const char *print_netdev(void *ptr)
+{
+    NetClientState *netdev = ptr;
+
+    return netdev->name ? netdev->name : "";
+}
+
+static void get_netdev(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    get_pointer(obj, v, opaque, print_netdev, name, errp);
+}
+
+static void set_netdev(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    set_pointer(obj, v, opaque, parse_netdev, name, errp);
+}
+
+hostdevPropertyInfo hostdev_prop_netdev = {
+    .name  = "peer",
+    .get   = get_netdev,
+    .set   = set_netdev,
+};
+
+/* --- string --- */
+static void release_string(Object *obj, const char *name, void *opaque)
+{
+    hostdevProperty *prop = opaque;
+    g_free(*(char **)hostdev_get_prop_ptr(HOST_DEVICE(obj), prop));
+}
+
+static void get_string(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    HOSTDevice *dev = HOST_DEVICE(obj);
+    hostdevProperty *prop = opaque;
+    char **ptr = hostdev_get_prop_ptr(dev, prop);
+
+    if (!*ptr) {
+        char *str = (char *)"";
+        visit_type_str(v, &str, name, errp);
+    } else {
+        visit_type_str(v, ptr, name, errp);
+    }
+}
+
+static void set_string(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    HOSTDevice *dev = HOST_DEVICE(obj);
+    hostdevProperty *prop = opaque;
+    char **ptr = hostdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if (*ptr) {
+        g_free(*ptr);
+    }
+    *ptr = str;
+}
+
+hostdevPropertyInfo hostdev_prop_string = {
+    .name  = "string",
+    .release = release_string,
+    .get   = get_string,
+    .set   = set_string,
+};
+/*
+static char *hostdev_get_type(Object *obj, Error **errp)
+{
+    return g_strdup(object_get_typename(obj));
+}
+*/
+static void hostdev_property_add_static(HOSTDevice *dev, hostdevProperty *prop,
+                                        Error **errp)
+{
+    if (!prop->info->get && !prop->info->set) {
+        return;
+    }
+
+    object_property_add(OBJECT(dev), prop->name, prop->info->name,
+                        prop->info->get, prop->info->set,
+                        prop->info->release,
+                        prop, errp);
+}
+
+static void hostdev_init(Object *obj)
+{
+    HOSTDevice *s = HOST_DEVICE(obj);
+    HOSTDeviceClass *dc = HOSTDEV_GET_CLASS(obj);
+    hostdevProperty *prop;
+
+    for (prop = dc->props; prop && prop->name; prop++) {
+        hostdev_property_add_static(s, prop, NULL);
+    }
+
+    //object_property_add_str(OBJECT(s), "type", hostdev_get_type, NULL, NULL);
+}
+
+static TypeInfo hostdev_type_info = {
+    .name          = TYPE_HOSTDEV,
+    .parent        = TYPE_OBJECT,
+    .instance_size = sizeof(HOSTDevice),
+    .instance_init = hostdev_init,
+    .abstract      = true,
+    .class_size    = sizeof(HOSTDeviceClass),
+};
+
+static void hostdev_register_types(void)
+{
+    type_register_static(&hostdev_type_info);
+}
+
+type_init(hostdev_register_types)
-- 
1.7.6

  reply	other threads:[~2012-03-26  5:40 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-26  5:40 [Qemu-devel] [RFC 0/9] QOM: qomify -netdev zwu.kernel
2012-03-26  5:40 ` zwu.kernel [this message]
2012-03-26  5:54   ` [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model Zhi Yong Wu
2012-03-27  8:23   ` Paolo Bonzini
2012-03-27  9:06     ` Zhi Yong Wu
2012-03-27 10:15       ` Paolo Bonzini
2012-03-27 11:59         ` Zhi Yong Wu
2012-03-27 13:58           ` Paolo Bonzini
2012-03-27 14:18             ` Zhi Yong Wu
2012-03-27 14:50               ` Paolo Bonzini
2012-03-27 21:21                 ` Zhi Yong Wu
2012-03-28  6:41                   ` Paolo Bonzini
2012-03-28  7:50                     ` Zhi Yong Wu
2012-03-28  7:53                     ` Zhi Yong Wu
2012-03-28  8:02                       ` Paolo Bonzini
2012-03-28  8:05                         ` 陳韋任
2012-03-28  8:25                           ` Zhi Yong Wu
2012-03-28  8:29                             ` 陳韋任
2012-03-26  5:40 ` [Qemu-devel] [PATCH] net: qomify -netdev zwu.kernel
2012-03-26  5:40 ` zwu.kernel
2012-03-26  5:44   ` Zhi Yong Wu
2012-03-26  5:40 ` [Qemu-devel] [RFC 2/9] net: introduce one net host device class zwu.kernel
2012-03-27  8:30   ` Paolo Bonzini
2012-03-27  9:13     ` Zhi Yong Wu
2012-03-26  5:40 ` [Qemu-devel] [RFC 3/9] net: adjust net common part for qomify -netdev zwu.kernel
2012-03-26  5:40 ` [Qemu-devel] [RFC 4/9] net: adjust nic init API zwu.kernel
2012-03-26  5:40 ` [Qemu-devel] [RFC 5/9] net: adjust dump " zwu.kernel
2012-03-26  5:40 ` [Qemu-devel] [RFC 6/9] net: qomify -netdev user zwu.kernel
2012-03-26  5:40 ` [Qemu-devel] [RFC 7/9] net: qomify -netdev socket zwu.kernel
2012-03-26  5:40 ` [Qemu-devel] [RFC 8/9] net: qomify -netdev vde zwu.kernel
2012-03-26  5:40 ` [Qemu-devel] [RFC 9/9] net: qomify -netdev tap & -netdev bridge zwu.kernel
2012-03-26 11:54 ` [Qemu-devel] [RFC 0/9] QOM: qomify -netdev Stefan Hajnoczi
2012-03-26 14:20   ` Zhi Yong Wu
2012-03-27  8:19     ` Paolo Bonzini
2012-03-27  9:03       ` Zhi Yong Wu
2012-03-26 14:39   ` Andreas Färber
2012-03-26 14:57     ` Stefan Hajnoczi
2012-03-26 15:01     ` Zhi Yong Wu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1332740423-8426-2-git-send-email-zwu.kernel@gmail.com \
    --to=zwu.kernel@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@linux.vnet.ibm.com \
    --cc=wuzhy@linux.vnet.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.