qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for hos


From: Zhi Yong Wu
Subject: Re: [Qemu-devel] [RFC 1/9] hostdev: introduce the infrastructure for host device model
Date: Mon, 26 Mar 2012 13:54:47 +0800

A lot of property get/set functions in qdev-properties.c are related
to DeviceState. So i have to copy and modify some of them here to
apply our host device model. In the future, we should make those
functions more generic.

On Mon, Mar 26, 2012 at 1:40 PM,  <address@hidden> wrote:
> 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
>



-- 
Regards,

Zhi Yong Wu



reply via email to

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