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
next prev parent 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).