[Top][All Lists]
[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
- [Qemu-devel] [RFC 0/9] QOM: qomify -netdev, zwu . kernel, 2012/03/26
- [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model,
zwu . kernel <=
- Re: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model, Zhi Yong Wu, 2012/03/26
- Re: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model, Paolo Bonzini, 2012/03/27
- Re: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model, Zhi Yong Wu, 2012/03/27
- Re: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model, Paolo Bonzini, 2012/03/27
- Re: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model, Zhi Yong Wu, 2012/03/27
- Re: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model, Paolo Bonzini, 2012/03/27
- Re: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model, Zhi Yong Wu, 2012/03/27
- Re: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model, Paolo Bonzini, 2012/03/27
- Re: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model, Zhi Yong Wu, 2012/03/27
- Re: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model, Paolo Bonzini, 2012/03/28