qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host de


From: zwu . kernel
Subject: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model
Date: Mon, 26 Mar 2012 13:40:13 +0800

From: Zhi Yong Wu <address@hidden>

Signed-off-by: Zhi Yong Wu <address@hidden>
---
 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   <address@hidden>
+ *
+ * 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   <address@hidden>
+ *
+ * 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 via email to

[Prev in Thread] Current Thread [Next in Thread]