qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too


From: Anthony Liguori
Subject: Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
Date: Wed, 17 Oct 2012 13:11:41 -0500
User-agent: Notmuch/0.13.2+93~ged93d79 (http://notmuchmail.org) Emacs/23.3.1 (x86_64-pc-linux-gnu)

Eduardo Habkost <address@hidden> writes:

> The code depends on some functions from qemu-option.o, so add
> qemu-option.o to universal-obj-y to make sure it's included.
>
> Signed-off-by: Eduardo Habkost <address@hidden>
> ---
>  Makefile.objs         |   3 +
>  hw/Makefile.objs      |   2 +-
>  hw/qdev-core.c        | 727 -------------------------------------
>  hw/qdev-properties.c  | 963 
> --------------------------------------------------
>  qom/Makefile.objs     |   2 +-
>  qom/qdev-core.c       | 727 +++++++++++++++++++++++++++++++++++++
>  qom/qdev-properties.c | 963 
> ++++++++++++++++++++++++++++++++++++++++++++++++++
>  7 files changed, 1695 insertions(+), 1692 deletions(-)
>  delete mode 100644 hw/qdev-core.c
>  delete mode 100644 hw/qdev-properties.c
>  create mode 100644 qom/qdev-core.c
>  create mode 100644 qom/qdev-properties.c

Stick the following in your .git/config:

[diff]
        renames = true

It's dangerously close to bike-shedding, but i don't think qdev belongs
in qom/.  It's not core infrastructure.  It's the device base class and
belongs IMHO in hw/.

Regards,

Anthony Liguori

>
> diff --git a/Makefile.objs b/Makefile.objs
> index 74b3542..fcd1336 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -16,6 +16,9 @@ universal-obj-y += $(qobject-obj-y)
>  qom-obj-y = qom/
>  
>  universal-obj-y += $(qom-obj-y)
> +# QOM qdev-core.o requires qemu-option.o:
> +universal-obj-y += qemu-option.o
> +
>  
>  #######################################################################
>  # oslib-obj-y is code depending on the OS (win32 vs posix)
> diff --git a/hw/Makefile.objs b/hw/Makefile.objs
> index 70f2014..3ce38d2 100644
> --- a/hw/Makefile.objs
> +++ b/hw/Makefile.objs
> @@ -180,7 +180,7 @@ common-obj-$(CONFIG_SD) += sd.o
>  common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
>  common-obj-y += bt-hci-csr.o
>  common-obj-y += msmouse.o ps2.o
> -common-obj-y += qdev-core.o qdev-properties.o qdev-monitor.o
> +common-obj-y += qdev-monitor.o
>  common-obj-y += qdev-system.o qdev-properties-system.o
>  common-obj-$(CONFIG_BRLAPI) += baum.o
>  
> diff --git a/hw/qdev-core.c b/hw/qdev-core.c
> deleted file mode 100644
> index fbb7cb5..0000000
> --- a/hw/qdev-core.c
> +++ /dev/null
> @@ -1,727 +0,0 @@
> -/*
> - *  Dynamic device configuration and creation.
> - *
> - *  Copyright (c) 2009 CodeSourcery
> - *
> - * This library is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU Lesser General Public
> - * License as published by the Free Software Foundation; either
> - * version 2 of the License, or (at your option) any later version.
> - *
> - * This library is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> - * Lesser General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public
> - * License along with this library; if not, see 
> <http://www.gnu.org/licenses/>.
> - */
> -
> -/* The theory here is that it should be possible to create a machine without
> -   knowledge of specific devices.  Historically board init routines have
> -   passed a bunch of arguments to each device, requiring the board know
> -   exactly which device it is dealing with.  This file provides an abstract
> -   API for device configuration and initialization.  Devices will generally
> -   inherit from a particular bus (e.g. PCI or I2C) rather than
> -   this API directly.  */
> -
> -#include "hw/qdev.h"
> -#include "sysemu.h"
> -#include "error.h"
> -#include "qapi/qapi-visit-core.h"
> -
> -int qdev_hotplug = 0;
> -static bool qdev_hot_added = false;
> -static bool qdev_hot_removed = false;
> -
> -/* vmstate handling:
> - *
> - * The real implementations are on qdev-system.c. Those are weak symbols
> - * used by *-user.
> - */
> -void GCC_WEAK qdev_init_vmstate(DeviceState *dev)
> -{
> -}
> -
> -void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
> -{
> -}
> -
> -/* reset handler register/unregister:
> - *
> - * The real implementations are on qdev-system.c. Those are weak symbols
> - * used by *-user.
> - */
> -void GCC_WEAK qbus_register_reset(BusState *bus)
> -{
> -}
> -
> -void GCC_WEAK qbus_unregister_reset(BusState *bus)
> -{
> -}
> -
> -const char *qdev_fw_name(DeviceState *dev)
> -{
> -    DeviceClass *dc = DEVICE_GET_CLASS(dev);
> -
> -    if (dc->fw_name) {
> -        return dc->fw_name;
> -    }
> -
> -    return object_get_typename(OBJECT(dev));
> -}
> -
> -static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
> -                                     Error **errp);
> -
> -static void bus_remove_child(BusState *bus, DeviceState *child)
> -{
> -    BusChild *kid;
> -
> -    QTAILQ_FOREACH(kid, &bus->children, sibling) {
> -        if (kid->child == child) {
> -            char name[32];
> -
> -            snprintf(name, sizeof(name), "child[%d]", kid->index);
> -            QTAILQ_REMOVE(&bus->children, kid, sibling);
> -            object_property_del(OBJECT(bus), name, NULL);
> -            g_free(kid);
> -            return;
> -        }
> -    }
> -}
> -
> -static void bus_add_child(BusState *bus, DeviceState *child)
> -{
> -    char name[32];
> -    BusChild *kid = g_malloc0(sizeof(*kid));
> -
> -    if (qdev_hotplug) {
> -        assert(bus->allow_hotplug);
> -    }
> -
> -    kid->index = bus->max_index++;
> -    kid->child = child;
> -
> -    QTAILQ_INSERT_HEAD(&bus->children, kid, sibling);
> -
> -    snprintf(name, sizeof(name), "child[%d]", kid->index);
> -    object_property_add_link(OBJECT(bus), name,
> -                             object_get_typename(OBJECT(child)),
> -                             (Object **)&kid->child,
> -                             NULL);
> -}
> -
> -void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
> -{
> -    dev->parent_bus = bus;
> -    bus_add_child(bus, dev);
> -}
> -
> -/* Initialize a device.  Device properties should be set before calling
> -   this function.  IRQs and MMIO regions should be connected/mapped after
> -   calling this function.
> -   On failure, destroy the device and return negative value.
> -   Return 0 on success.  */
> -int qdev_init(DeviceState *dev)
> -{
> -    DeviceClass *dc = DEVICE_GET_CLASS(dev);
> -    int rc;
> -
> -    assert(dev->state == DEV_STATE_CREATED);
> -
> -    rc = dc->init(dev);
> -    if (rc < 0) {
> -        qdev_free(dev);
> -        return rc;
> -    }
> -
> -    if (!OBJECT(dev)->parent) {
> -        static int unattached_count = 0;
> -        gchar *name = g_strdup_printf("device[%d]", unattached_count++);
> -
> -        object_property_add_child(container_get(qdev_get_machine(),
> -                                                "/unattached"),
> -                                  name, OBJECT(dev), NULL);
> -        g_free(name);
> -    }
> -
> -    qdev_init_vmstate(dev);
> -    dev->state = DEV_STATE_INITIALIZED;
> -    if (dev->hotplugged) {
> -        device_reset(dev);
> -    }
> -    return 0;
> -}
> -
> -void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
> -                                 int required_for_version)
> -{
> -    assert(dev->state == DEV_STATE_CREATED);
> -    dev->instance_id_alias = alias_id;
> -    dev->alias_required_for_version = required_for_version;
> -}
> -
> -void qdev_unplug(DeviceState *dev, Error **errp)
> -{
> -    DeviceClass *dc = DEVICE_GET_CLASS(dev);
> -
> -    if (!dev->parent_bus->allow_hotplug) {
> -        error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
> -        return;
> -    }
> -    assert(dc->unplug != NULL);
> -
> -    qdev_hot_removed = true;
> -
> -    if (dc->unplug(dev) < 0) {
> -        error_set(errp, QERR_UNDEFINED_ERROR);
> -        return;
> -    }
> -}
> -
> -static int qdev_reset_one(DeviceState *dev, void *opaque)
> -{
> -    device_reset(dev);
> -
> -    return 0;
> -}
> -
> -static int qbus_reset_one(BusState *bus, void *opaque)
> -{
> -    BusClass *bc = BUS_GET_CLASS(bus);
> -    if (bc->reset) {
> -        return bc->reset(bus);
> -    }
> -    return 0;
> -}
> -
> -void qdev_reset_all(DeviceState *dev)
> -{
> -    qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
> -}
> -
> -void qbus_reset_all_fn(void *opaque)
> -{
> -    BusState *bus = opaque;
> -    qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
> -}
> -
> -/* can be used as ->unplug() callback for the simple cases */
> -int qdev_simple_unplug_cb(DeviceState *dev)
> -{
> -    /* just zap it */
> -    qdev_free(dev);
> -    return 0;
> -}
> -
> -
> -/* Like qdev_init(), but terminate program via error_report() instead of
> -   returning an error value.  This is okay during machine creation.
> -   Don't use for hotplug, because there callers need to recover from
> -   failure.  Exception: if you know the device's init() callback can't
> -   fail, then qdev_init_nofail() can't fail either, and is therefore
> -   usable even then.  But relying on the device implementation that
> -   way is somewhat unclean, and best avoided.  */
> -void qdev_init_nofail(DeviceState *dev)
> -{
> -    const char *typename = object_get_typename(OBJECT(dev));
> -
> -    if (qdev_init(dev) < 0) {
> -        error_report("Initialization of device %s failed", typename);
> -        exit(1);
> -    }
> -}
> -
> -/* Unlink device from bus and free the structure.  */
> -void qdev_free(DeviceState *dev)
> -{
> -    object_delete(OBJECT(dev));
> -}
> -
> -void qdev_machine_creation_done(void)
> -{
> -    /*
> -     * ok, initial machine setup is done, starting from now we can
> -     * only create hotpluggable devices
> -     */
> -    qdev_hotplug = 1;
> -}
> -
> -bool qdev_machine_modified(void)
> -{
> -    return qdev_hot_added || qdev_hot_removed;
> -}
> -
> -BusState *qdev_get_parent_bus(DeviceState *dev)
> -{
> -    return dev->parent_bus;
> -}
> -
> -BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
> -{
> -    BusState *bus;
> -
> -    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> -        if (strcmp(name, bus->name) == 0) {
> -            return bus;
> -        }
> -    }
> -    return NULL;
> -}
> -
> -int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
> -                       qbus_walkerfn *busfn, void *opaque)
> -{
> -    BusChild *kid;
> -    int err;
> -
> -    if (busfn) {
> -        err = busfn(bus, opaque);
> -        if (err) {
> -            return err;
> -        }
> -    }
> -
> -    QTAILQ_FOREACH(kid, &bus->children, sibling) {
> -        err = qdev_walk_children(kid->child, devfn, busfn, opaque);
> -        if (err < 0) {
> -            return err;
> -        }
> -    }
> -
> -    return 0;
> -}
> -
> -int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
> -                       qbus_walkerfn *busfn, void *opaque)
> -{
> -    BusState *bus;
> -    int err;
> -
> -    if (devfn) {
> -        err = devfn(dev, opaque);
> -        if (err) {
> -            return err;
> -        }
> -    }
> -
> -    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> -        err = qbus_walk_children(bus, devfn, busfn, opaque);
> -        if (err < 0) {
> -            return err;
> -        }
> -    }
> -
> -    return 0;
> -}
> -
> -DeviceState *qdev_find_recursive(BusState *bus, const char *id)
> -{
> -    BusChild *kid;
> -    DeviceState *ret;
> -    BusState *child;
> -
> -    QTAILQ_FOREACH(kid, &bus->children, sibling) {
> -        DeviceState *dev = kid->child;
> -
> -        if (dev->id && strcmp(dev->id, id) == 0) {
> -            return dev;
> -        }
> -
> -        QLIST_FOREACH(child, &dev->child_bus, sibling) {
> -            ret = qdev_find_recursive(child, id);
> -            if (ret) {
> -                return ret;
> -            }
> -        }
> -    }
> -    return NULL;
> -}
> -
> -static void qbus_realize(BusState *bus)
> -{
> -    const char *typename = object_get_typename(OBJECT(bus));
> -    char *buf;
> -    int i,len;
> -
> -    if (bus->name) {
> -        /* use supplied name */
> -    } else if (bus->parent && bus->parent->id) {
> -        /* parent device has id -> use it for bus name */
> -        len = strlen(bus->parent->id) + 16;
> -        buf = g_malloc(len);
> -        snprintf(buf, len, "%s.%d", bus->parent->id, 
> bus->parent->num_child_bus);
> -        bus->name = buf;
> -    } else {
> -        /* no id -> use lowercase bus type for bus name */
> -        len = strlen(typename) + 16;
> -        buf = g_malloc(len);
> -        len = snprintf(buf, len, "%s.%d", typename,
> -                       bus->parent ? bus->parent->num_child_bus : 0);
> -        for (i = 0; i < len; i++)
> -            buf[i] = qemu_tolower(buf[i]);
> -        bus->name = buf;
> -    }
> -
> -    if (bus->parent) {
> -        QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
> -        bus->parent->num_child_bus++;
> -        object_property_add_child(OBJECT(bus->parent), bus->name, 
> OBJECT(bus), NULL);
> -    } else {
> -        qbus_register_reset(bus);
> -    }
> -}
> -
> -void qbus_create_inplace(BusState *bus, const char *typename,
> -                         DeviceState *parent, const char *name)
> -{
> -    object_initialize(bus, typename);
> -
> -    bus->parent = parent;
> -    bus->name = name ? g_strdup(name) : NULL;
> -    qbus_realize(bus);
> -}
> -
> -BusState *qbus_create(const char *typename, DeviceState *parent, const char 
> *name)
> -{
> -    BusState *bus;
> -
> -    bus = BUS(object_new(typename));
> -    bus->qom_allocated = true;
> -
> -    bus->parent = parent;
> -    bus->name = name ? g_strdup(name) : NULL;
> -    qbus_realize(bus);
> -
> -    return bus;
> -}
> -
> -void qbus_free(BusState *bus)
> -{
> -    if (bus->qom_allocated) {
> -        object_delete(OBJECT(bus));
> -    } else {
> -        object_finalize(OBJECT(bus));
> -        if (bus->glib_allocated) {
> -            g_free(bus);
> -        }
> -    }
> -}
> -
> -static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
> -{
> -    BusClass *bc = BUS_GET_CLASS(bus);
> -
> -    if (bc->get_fw_dev_path) {
> -        return bc->get_fw_dev_path(dev);
> -    }
> -
> -    return NULL;
> -}
> -
> -static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
> -{
> -    int l = 0;
> -
> -    if (dev && dev->parent_bus) {
> -        char *d;
> -        l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
> -        d = bus_get_fw_dev_path(dev->parent_bus, dev);
> -        if (d) {
> -            l += snprintf(p + l, size - l, "%s", d);
> -            g_free(d);
> -        } else {
> -            l += snprintf(p + l, size - l, "%s", 
> object_get_typename(OBJECT(dev)));
> -        }
> -    }
> -    l += snprintf(p + l , size - l, "/");
> -
> -    return l;
> -}
> -
> -char* qdev_get_fw_dev_path(DeviceState *dev)
> -{
> -    char path[128];
> -    int l;
> -
> -    l = qdev_get_fw_dev_path_helper(dev, path, 128);
> -
> -    path[l-1] = '\0';
> -
> -    return g_strdup(path);
> -}
> -
> -char *qdev_get_dev_path(DeviceState *dev)
> -{
> -    BusClass *bc;
> -
> -    if (!dev || !dev->parent_bus) {
> -        return NULL;
> -    }
> -
> -    bc = BUS_GET_CLASS(dev->parent_bus);
> -    if (bc->get_dev_path) {
> -        return bc->get_dev_path(dev);
> -    }
> -
> -    return NULL;
> -}
> -
> -/**
> - * Legacy property handling
> - */
> -
> -static void qdev_get_legacy_property(Object *obj, Visitor *v, void *opaque,
> -                                     const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -
> -    char buffer[1024];
> -    char *ptr = buffer;
> -
> -    prop->info->print(dev, prop, buffer, sizeof(buffer));
> -    visit_type_str(v, &ptr, name, errp);
> -}
> -
> -static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
> -                                     const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    Error *local_err = NULL;
> -    char *ptr = NULL;
> -    int ret;
> -
> -    if (dev->state != DEV_STATE_CREATED) {
> -        error_set(errp, QERR_PERMISSION_DENIED);
> -        return;
> -    }
> -
> -    visit_type_str(v, &ptr, name, &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -
> -    ret = prop->info->parse(dev, prop, ptr);
> -    error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
> -    g_free(ptr);
> -}
> -
> -/**
> - * @qdev_add_legacy_property - adds a legacy property
> - *
> - * Do not use this is new code!  Properties added through this interface will
> - * be given names and types in the "legacy" namespace.
> - *
> - * Legacy properties are string versions of other OOM properties.  The format
> - * of the string depends on the property type.
> - */
> -void qdev_property_add_legacy(DeviceState *dev, Property *prop,
> -                              Error **errp)
> -{
> -    gchar *name, *type;
> -
> -    /* Register pointer properties as legacy properties */
> -    if (!prop->info->print && !prop->info->parse &&
> -        (prop->info->set || prop->info->get)) {
> -        return;
> -    }
> -
> -    name = g_strdup_printf("legacy-%s", prop->name);
> -    type = g_strdup_printf("legacy<%s>",
> -                           prop->info->legacy_name ?: prop->info->name);
> -
> -    object_property_add(OBJECT(dev), name, type,
> -                        prop->info->print ? qdev_get_legacy_property : 
> prop->info->get,
> -                        prop->info->parse ? qdev_set_legacy_property : 
> prop->info->set,
> -                        NULL,
> -                        prop, errp);
> -
> -    g_free(type);
> -    g_free(name);
> -}
> -
> -/**
> - * @qdev_property_add_static - add a @Property to a device.
> - *
> - * Static properties access data in a struct.  The actual type of the
> - * property and the field depends on the property type.
> - */
> -void qdev_property_add_static(DeviceState *dev, Property *prop,
> -                              Error **errp)
> -{
> -    Error *local_err = NULL;
> -    Object *obj = OBJECT(dev);
> -
> -    /*
> -     * TODO qdev_prop_ptr does not have getters or setters.  It must
> -     * go now that it can be replaced with links.  The test should be
> -     * removed along with it: all static properties are read/write.
> -     */
> -    if (!prop->info->get && !prop->info->set) {
> -        return;
> -    }
> -
> -    object_property_add(obj, prop->name, prop->info->name,
> -                        prop->info->get, prop->info->set,
> -                        prop->info->release,
> -                        prop, &local_err);
> -
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -    if (prop->qtype == QTYPE_NONE) {
> -        return;
> -    }
> -
> -    if (prop->qtype == QTYPE_QBOOL) {
> -        object_property_set_bool(obj, prop->defval, prop->name, &local_err);
> -    } else if (prop->info->enum_table) {
> -        object_property_set_str(obj, prop->info->enum_table[prop->defval],
> -                                prop->name, &local_err);
> -    } else if (prop->qtype == QTYPE_QINT) {
> -        object_property_set_int(obj, prop->defval, prop->name, &local_err);
> -    }
> -    assert_no_error(local_err);
> -}
> -
> -static void device_initfn(Object *obj)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    ObjectClass *class;
> -    Property *prop;
> -
> -    if (qdev_hotplug) {
> -        dev->hotplugged = 1;
> -        qdev_hot_added = true;
> -    }
> -
> -    dev->instance_id_alias = -1;
> -    dev->state = DEV_STATE_CREATED;
> -
> -    class = object_get_class(OBJECT(dev));
> -    do {
> -        for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
> -            qdev_property_add_legacy(dev, prop, NULL);
> -            qdev_property_add_static(dev, prop, NULL);
> -        }
> -        class = object_class_get_parent(class);
> -    } while (class != object_class_by_name(TYPE_DEVICE));
> -    qdev_prop_set_globals(dev);
> -
> -    object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
> -                             (Object **)&dev->parent_bus, NULL);
> -}
> -
> -/* Unlink device from bus and free the structure.  */
> -static void device_finalize(Object *obj)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    BusState *bus;
> -    DeviceClass *dc = DEVICE_GET_CLASS(dev);
> -
> -    if (dev->state == DEV_STATE_INITIALIZED) {
> -        while (dev->num_child_bus) {
> -            bus = QLIST_FIRST(&dev->child_bus);
> -            qbus_free(bus);
> -        }
> -        qdev_finalize_vmstate(dev);
> -        if (dc->exit) {
> -            dc->exit(dev);
> -        }
> -        if (dev->opts) {
> -            qemu_opts_del(dev->opts);
> -        }
> -    }
> -    if (dev->parent_bus) {
> -        bus_remove_child(dev->parent_bus, dev);
> -    }
> -}
> -
> -static void device_class_base_init(ObjectClass *class, void *data)
> -{
> -    DeviceClass *klass = DEVICE_CLASS(class);
> -
> -    /* We explicitly look up properties in the superclasses,
> -     * so do not propagate them to the subclasses.
> -     */
> -    klass->props = NULL;
> -}
> -
> -void device_reset(DeviceState *dev)
> -{
> -    DeviceClass *klass = DEVICE_GET_CLASS(dev);
> -
> -    if (klass->reset) {
> -        klass->reset(dev);
> -    }
> -}
> -
> -Object *qdev_get_machine(void)
> -{
> -    static Object *dev;
> -
> -    if (dev == NULL) {
> -        dev = container_get(object_get_root(), "/machine");
> -    }
> -
> -    return dev;
> -}
> -
> -static TypeInfo device_type_info = {
> -    .name = TYPE_DEVICE,
> -    .parent = TYPE_OBJECT,
> -    .instance_size = sizeof(DeviceState),
> -    .instance_init = device_initfn,
> -    .instance_finalize = device_finalize,
> -    .class_base_init = device_class_base_init,
> -    .abstract = true,
> -    .class_size = sizeof(DeviceClass),
> -};
> -
> -static void qbus_initfn(Object *obj)
> -{
> -    BusState *bus = BUS(obj);
> -
> -    QTAILQ_INIT(&bus->children);
> -}
> -
> -static void qbus_finalize(Object *obj)
> -{
> -    BusState *bus = BUS(obj);
> -    BusChild *kid;
> -
> -    while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
> -        DeviceState *dev = kid->child;
> -        qdev_free(dev);
> -    }
> -    if (bus->parent) {
> -        QLIST_REMOVE(bus, sibling);
> -        bus->parent->num_child_bus--;
> -    } else {
> -        qbus_unregister_reset(bus);
> -    }
> -    g_free((char *)bus->name);
> -}
> -
> -static const TypeInfo bus_info = {
> -    .name = TYPE_BUS,
> -    .parent = TYPE_OBJECT,
> -    .instance_size = sizeof(BusState),
> -    .abstract = true,
> -    .class_size = sizeof(BusClass),
> -    .instance_init = qbus_initfn,
> -    .instance_finalize = qbus_finalize,
> -};
> -
> -static void qdev_register_types(void)
> -{
> -    type_register_static(&bus_info);
> -    type_register_static(&device_type_info);
> -}
> -
> -type_init(qdev_register_types)
> diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
> deleted file mode 100644
> index 2e82cb9..0000000
> --- a/hw/qdev-properties.c
> +++ /dev/null
> @@ -1,963 +0,0 @@
> -#include "net.h"
> -#include "hw/qdev.h"
> -#include "qerror.h"
> -#include "blockdev.h"
> -#include "hw/block-common.h"
> -#include "net/hub.h"
> -#include "qapi/qapi-visit-core.h"
> -
> -void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
> -{
> -    void *ptr = dev;
> -    ptr += prop->offset;
> -    return ptr;
> -}
> -
> -static void get_enum(Object *obj, Visitor *v, void *opaque,
> -                     const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    int *ptr = qdev_get_prop_ptr(dev, prop);
> -
> -    visit_type_enum(v, ptr, prop->info->enum_table,
> -                    prop->info->name, prop->name, errp);
> -}
> -
> -static void set_enum(Object *obj, Visitor *v, void *opaque,
> -                     const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    int *ptr = qdev_get_prop_ptr(dev, prop);
> -
> -    if (dev->state != DEV_STATE_CREATED) {
> -        error_set(errp, QERR_PERMISSION_DENIED);
> -        return;
> -    }
> -
> -    visit_type_enum(v, ptr, prop->info->enum_table,
> -                    prop->info->name, prop->name, errp);
> -}
> -
> -/* Bit */
> -
> -static uint32_t qdev_get_prop_mask(Property *prop)
> -{
> -    assert(prop->info == &qdev_prop_bit);
> -    return 0x1 << prop->bitnr;
> -}
> -
> -static void bit_prop_set(DeviceState *dev, Property *props, bool val)
> -{
> -    uint32_t *p = qdev_get_prop_ptr(dev, props);
> -    uint32_t mask = qdev_get_prop_mask(props);
> -    if (val)
> -        *p |= mask;
> -    else
> -        *p &= ~mask;
> -}
> -
> -static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t 
> len)
> -{
> -    uint32_t *p = qdev_get_prop_ptr(dev, prop);
> -    return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : 
> "off");
> -}
> -
> -static void get_bit(Object *obj, Visitor *v, void *opaque,
> -                    const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    uint32_t *p = qdev_get_prop_ptr(dev, prop);
> -    bool value = (*p & qdev_get_prop_mask(prop)) != 0;
> -
> -    visit_type_bool(v, &value, name, errp);
> -}
> -
> -static void set_bit(Object *obj, Visitor *v, void *opaque,
> -                    const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    Error *local_err = NULL;
> -    bool value;
> -
> -    if (dev->state != DEV_STATE_CREATED) {
> -        error_set(errp, QERR_PERMISSION_DENIED);
> -        return;
> -    }
> -
> -    visit_type_bool(v, &value, name, &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -    bit_prop_set(dev, prop, value);
> -}
> -
> -PropertyInfo qdev_prop_bit = {
> -    .name  = "boolean",
> -    .legacy_name  = "on/off",
> -    .print = print_bit,
> -    .get   = get_bit,
> -    .set   = set_bit,
> -};
> -
> -/* --- 8bit integer --- */
> -
> -static void get_uint8(Object *obj, Visitor *v, void *opaque,
> -                      const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> -    visit_type_uint8(v, ptr, name, errp);
> -}
> -
> -static void set_uint8(Object *obj, Visitor *v, void *opaque,
> -                      const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> -    if (dev->state != DEV_STATE_CREATED) {
> -        error_set(errp, QERR_PERMISSION_DENIED);
> -        return;
> -    }
> -
> -    visit_type_uint8(v, ptr, name, errp);
> -}
> -
> -PropertyInfo qdev_prop_uint8 = {
> -    .name  = "uint8",
> -    .get   = get_uint8,
> -    .set   = set_uint8,
> -};
> -
> -/* --- 8bit hex value --- */
> -
> -static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
> -{
> -    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> -    char *end;
> -
> -    if (str[0] != '0' || str[1] != 'x') {
> -        return -EINVAL;
> -    }
> -
> -    *ptr = strtoul(str, &end, 16);
> -    if ((*end != '\0') || (end == str)) {
> -        return -EINVAL;
> -    }
> -
> -    return 0;
> -}
> -
> -static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t 
> len)
> -{
> -    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> -    return snprintf(dest, len, "0x%" PRIx8, *ptr);
> -}
> -
> -PropertyInfo qdev_prop_hex8 = {
> -    .name  = "uint8",
> -    .legacy_name  = "hex8",
> -    .parse = parse_hex8,
> -    .print = print_hex8,
> -    .get   = get_uint8,
> -    .set   = set_uint8,
> -};
> -
> -/* --- 16bit integer --- */
> -
> -static void get_uint16(Object *obj, Visitor *v, void *opaque,
> -                       const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> -    visit_type_uint16(v, ptr, name, errp);
> -}
> -
> -static void set_uint16(Object *obj, Visitor *v, void *opaque,
> -                       const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> -    if (dev->state != DEV_STATE_CREATED) {
> -        error_set(errp, QERR_PERMISSION_DENIED);
> -        return;
> -    }
> -
> -    visit_type_uint16(v, ptr, name, errp);
> -}
> -
> -PropertyInfo qdev_prop_uint16 = {
> -    .name  = "uint16",
> -    .get   = get_uint16,
> -    .set   = set_uint16,
> -};
> -
> -/* --- 32bit integer --- */
> -
> -static void get_uint32(Object *obj, Visitor *v, void *opaque,
> -                       const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> -    visit_type_uint32(v, ptr, name, errp);
> -}
> -
> -static void set_uint32(Object *obj, Visitor *v, void *opaque,
> -                       const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> -    if (dev->state != DEV_STATE_CREATED) {
> -        error_set(errp, QERR_PERMISSION_DENIED);
> -        return;
> -    }
> -
> -    visit_type_uint32(v, ptr, name, errp);
> -}
> -
> -static void get_int32(Object *obj, Visitor *v, void *opaque,
> -                      const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> -    visit_type_int32(v, ptr, name, errp);
> -}
> -
> -static void set_int32(Object *obj, Visitor *v, void *opaque,
> -                      const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> -    if (dev->state != DEV_STATE_CREATED) {
> -        error_set(errp, QERR_PERMISSION_DENIED);
> -        return;
> -    }
> -
> -    visit_type_int32(v, ptr, name, errp);
> -}
> -
> -PropertyInfo qdev_prop_uint32 = {
> -    .name  = "uint32",
> -    .get   = get_uint32,
> -    .set   = set_uint32,
> -};
> -
> -PropertyInfo qdev_prop_int32 = {
> -    .name  = "int32",
> -    .get   = get_int32,
> -    .set   = set_int32,
> -};
> -
> -/* --- 32bit hex value --- */
> -
> -static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
> -{
> -    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -    char *end;
> -
> -    if (str[0] != '0' || str[1] != 'x') {
> -        return -EINVAL;
> -    }
> -
> -    *ptr = strtoul(str, &end, 16);
> -    if ((*end != '\0') || (end == str)) {
> -        return -EINVAL;
> -    }
> -
> -    return 0;
> -}
> -
> -static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t 
> len)
> -{
> -    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -    return snprintf(dest, len, "0x%" PRIx32, *ptr);
> -}
> -
> -PropertyInfo qdev_prop_hex32 = {
> -    .name  = "uint32",
> -    .legacy_name  = "hex32",
> -    .parse = parse_hex32,
> -    .print = print_hex32,
> -    .get   = get_uint32,
> -    .set   = set_uint32,
> -};
> -
> -/* --- 64bit integer --- */
> -
> -static void get_uint64(Object *obj, Visitor *v, void *opaque,
> -                       const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> -    visit_type_uint64(v, ptr, name, errp);
> -}
> -
> -static void set_uint64(Object *obj, Visitor *v, void *opaque,
> -                       const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> -    if (dev->state != DEV_STATE_CREATED) {
> -        error_set(errp, QERR_PERMISSION_DENIED);
> -        return;
> -    }
> -
> -    visit_type_uint64(v, ptr, name, errp);
> -}
> -
> -PropertyInfo qdev_prop_uint64 = {
> -    .name  = "uint64",
> -    .get   = get_uint64,
> -    .set   = set_uint64,
> -};
> -
> -/* --- 64bit hex value --- */
> -
> -static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
> -{
> -    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> -    char *end;
> -
> -    if (str[0] != '0' || str[1] != 'x') {
> -        return -EINVAL;
> -    }
> -
> -    *ptr = strtoull(str, &end, 16);
> -    if ((*end != '\0') || (end == str)) {
> -        return -EINVAL;
> -    }
> -
> -    return 0;
> -}
> -
> -static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t 
> len)
> -{
> -    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> -    return snprintf(dest, len, "0x%" PRIx64, *ptr);
> -}
> -
> -PropertyInfo qdev_prop_hex64 = {
> -    .name  = "uint64",
> -    .legacy_name  = "hex64",
> -    .parse = parse_hex64,
> -    .print = print_hex64,
> -    .get   = get_uint64,
> -    .set   = set_uint64,
> -};
> -
> -/* --- string --- */
> -
> -static void release_string(Object *obj, const char *name, void *opaque)
> -{
> -    Property *prop = opaque;
> -    g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
> -}
> -
> -static int print_string(DeviceState *dev, Property *prop, char *dest, size_t 
> len)
> -{
> -    char **ptr = qdev_get_prop_ptr(dev, prop);
> -    if (!*ptr)
> -        return snprintf(dest, len, "<null>");
> -    return snprintf(dest, len, "\"%s\"", *ptr);
> -}
> -
> -static void get_string(Object *obj, Visitor *v, void *opaque,
> -                       const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    char **ptr = qdev_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)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    char **ptr = qdev_get_prop_ptr(dev, prop);
> -    Error *local_err = NULL;
> -    char *str;
> -
> -    if (dev->state != DEV_STATE_CREATED) {
> -        error_set(errp, QERR_PERMISSION_DENIED);
> -        return;
> -    }
> -
> -    visit_type_str(v, &str, name, &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -    if (*ptr) {
> -        g_free(*ptr);
> -    }
> -    *ptr = str;
> -}
> -
> -PropertyInfo qdev_prop_string = {
> -    .name  = "string",
> -    .print = print_string,
> -    .release = release_string,
> -    .get   = get_string,
> -    .set   = set_string,
> -};
> -
> -/* --- pointer --- */
> -
> -/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
> -PropertyInfo qdev_prop_ptr = {
> -    .name  = "ptr",
> -};
> -
> -/* --- mac address --- */
> -
> -/*
> - * accepted syntax versions:
> - *   01:02:03:04:05:06
> - *   01-02-03-04-05-06
> - */
> -static void get_mac(Object *obj, Visitor *v, void *opaque,
> -                    const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
> -    char buffer[2 * 6 + 5 + 1];
> -    char *p = buffer;
> -
> -    snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
> -             mac->a[0], mac->a[1], mac->a[2],
> -             mac->a[3], mac->a[4], mac->a[5]);
> -
> -    visit_type_str(v, &p, name, errp);
> -}
> -
> -static void set_mac(Object *obj, Visitor *v, void *opaque,
> -                    const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
> -    Error *local_err = NULL;
> -    int i, pos;
> -    char *str, *p;
> -
> -    if (dev->state != DEV_STATE_CREATED) {
> -        error_set(errp, QERR_PERMISSION_DENIED);
> -        return;
> -    }
> -
> -    visit_type_str(v, &str, name, &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -
> -    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
> -        if (!qemu_isxdigit(str[pos]))
> -            goto inval;
> -        if (!qemu_isxdigit(str[pos+1]))
> -            goto inval;
> -        if (i == 5) {
> -            if (str[pos+2] != '\0')
> -                goto inval;
> -        } else {
> -            if (str[pos+2] != ':' && str[pos+2] != '-')
> -                goto inval;
> -        }
> -        mac->a[i] = strtol(str+pos, &p, 16);
> -    }
> -    g_free(str);
> -    return;
> -
> -inval:
> -    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> -    g_free(str);
> -}
> -
> -PropertyInfo qdev_prop_macaddr = {
> -    .name  = "macaddr",
> -    .get   = get_mac,
> -    .set   = set_mac,
> -};
> -
> -/* --- lost tick policy --- */
> -
> -static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
> -    [LOST_TICK_DISCARD] = "discard",
> -    [LOST_TICK_DELAY] = "delay",
> -    [LOST_TICK_MERGE] = "merge",
> -    [LOST_TICK_SLEW] = "slew",
> -    [LOST_TICK_MAX] = NULL,
> -};
> -
> -QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
> -
> -PropertyInfo qdev_prop_losttickpolicy = {
> -    .name  = "LostTickPolicy",
> -    .enum_table  = lost_tick_policy_table,
> -    .get   = get_enum,
> -    .set   = set_enum,
> -};
> -
> -/* --- BIOS CHS translation */
> -
> -static const char *bios_chs_trans_table[] = {
> -    [BIOS_ATA_TRANSLATION_AUTO] = "auto",
> -    [BIOS_ATA_TRANSLATION_NONE] = "none",
> -    [BIOS_ATA_TRANSLATION_LBA]  = "lba",
> -};
> -
> -PropertyInfo qdev_prop_bios_chs_trans = {
> -    .name = "bios-chs-trans",
> -    .enum_table = bios_chs_trans_table,
> -    .get = get_enum,
> -    .set = set_enum,
> -};
> -
> -/* --- pci address --- */
> -
> -/*
> - * bus-local address, i.e. "$slot" or "$slot.$fn"
> - */
> -static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
> -                          const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
> -    unsigned int slot, fn, n;
> -    Error *local_err = NULL;
> -    char *str;
> -
> -    if (dev->state != DEV_STATE_CREATED) {
> -        error_set(errp, QERR_PERMISSION_DENIED);
> -        return;
> -    }
> -
> -    visit_type_str(v, &str, name, &local_err);
> -    if (local_err) {
> -        error_free(local_err);
> -        local_err = NULL;
> -        visit_type_int32(v, &value, name, &local_err);
> -        if (local_err) {
> -            error_propagate(errp, local_err);
> -        } else if (value < -1 || value > 255) {
> -            error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : 
> "null",
> -                      "pci_devfn");
> -        } else {
> -            *ptr = value;
> -        }
> -        return;
> -    }
> -
> -    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
> -        fn = 0;
> -        if (sscanf(str, "%x%n", &slot, &n) != 1) {
> -            goto invalid;
> -        }
> -    }
> -    if (str[n] != '\0' || fn > 7 || slot > 31) {
> -        goto invalid;
> -    }
> -    *ptr = slot << 3 | fn;
> -    g_free(str);
> -    return;
> -
> -invalid:
> -    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> -    g_free(str);
> -}
> -
> -static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, 
> size_t len)
> -{
> -    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> -
> -    if (*ptr == -1) {
> -        return snprintf(dest, len, "<unset>");
> -    } else {
> -        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
> -    }
> -}
> -
> -PropertyInfo qdev_prop_pci_devfn = {
> -    .name  = "int32",
> -    .legacy_name  = "pci-devfn",
> -    .print = print_pci_devfn,
> -    .get   = get_int32,
> -    .set   = set_pci_devfn,
> -};
> -
> -/* --- blocksize --- */
> -
> -static void set_blocksize(Object *obj, Visitor *v, void *opaque,
> -                          const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
> -    Error *local_err = NULL;
> -    const int64_t min = 512;
> -    const int64_t max = 32768;
> -
> -    if (dev->state != DEV_STATE_CREATED) {
> -        error_set(errp, QERR_PERMISSION_DENIED);
> -        return;
> -    }
> -
> -    visit_type_uint16(v, &value, name, &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -    if (value < min || value > max) {
> -        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
> -                  dev->id?:"", name, (int64_t)value, min, max);
> -        return;
> -    }
> -
> -    /* We rely on power-of-2 blocksizes for bitmasks */
> -    if ((value & (value - 1)) != 0) {
> -        error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
> -                  dev->id?:"", name, (int64_t)value);
> -        return;
> -    }
> -
> -    *ptr = value;
> -}
> -
> -PropertyInfo qdev_prop_blocksize = {
> -    .name  = "blocksize",
> -    .get   = get_uint16,
> -    .set   = set_blocksize,
> -};
> -
> -/* --- pci host address --- */
> -
> -static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
> -                                 const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
> -    char buffer[] = "xxxx:xx:xx.x";
> -    char *p = buffer;
> -    int rc = 0;
> -
> -    rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
> -                  addr->domain, addr->bus, addr->slot, addr->function);
> -    assert(rc == sizeof(buffer) - 1);
> -
> -    visit_type_str(v, &p, name, errp);
> -}
> -
> -/*
> - * Parse [<domain>:]<bus>:<slot>.<func>
> - *   if <domain> is not supplied, it's assumed to be 0.
> - */
> -static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
> -                                 const char *name, Error **errp)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -    Property *prop = opaque;
> -    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
> -    Error *local_err = NULL;
> -    char *str, *p;
> -    char *e;
> -    unsigned long val;
> -    unsigned long dom = 0, bus = 0;
> -    unsigned int slot = 0, func = 0;
> -
> -    if (dev->state != DEV_STATE_CREATED) {
> -        error_set(errp, QERR_PERMISSION_DENIED);
> -        return;
> -    }
> -
> -    visit_type_str(v, &str, name, &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -
> -    p = str;
> -    val = strtoul(p, &e, 16);
> -    if (e == p || *e != ':') {
> -        goto inval;
> -    }
> -    bus = val;
> -
> -    p = e + 1;
> -    val = strtoul(p, &e, 16);
> -    if (e == p) {
> -        goto inval;
> -    }
> -    if (*e == ':') {
> -        dom = bus;
> -        bus = val;
> -        p = e + 1;
> -        val = strtoul(p, &e, 16);
> -        if (e == p) {
> -            goto inval;
> -        }
> -    }
> -    slot = val;
> -
> -    if (*e != '.') {
> -        goto inval;
> -    }
> -    p = e + 1;
> -    val = strtoul(p, &e, 10);
> -    if (e == p) {
> -        goto inval;
> -    }
> -    func = val;
> -
> -    if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
> -        goto inval;
> -    }
> -
> -    if (*e) {
> -        goto inval;
> -    }
> -
> -    addr->domain = dom;
> -    addr->bus = bus;
> -    addr->slot = slot;
> -    addr->function = func;
> -
> -    g_free(str);
> -    return;
> -
> -inval:
> -    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> -    g_free(str);
> -}
> -
> -PropertyInfo qdev_prop_pci_host_devaddr = {
> -    .name = "pci-host-devaddr",
> -    .get = get_pci_host_devaddr,
> -    .set = set_pci_host_devaddr,
> -};
> -
> -/* --- public helpers --- */
> -
> -static Property *qdev_prop_walk(Property *props, const char *name)
> -{
> -    if (!props)
> -        return NULL;
> -    while (props->name) {
> -        if (strcmp(props->name, name) == 0)
> -            return props;
> -        props++;
> -    }
> -    return NULL;
> -}
> -
> -static Property *qdev_prop_find(DeviceState *dev, const char *name)
> -{
> -    ObjectClass *class;
> -    Property *prop;
> -
> -    /* device properties */
> -    class = object_get_class(OBJECT(dev));
> -    do {
> -        prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
> -        if (prop) {
> -            return prop;
> -        }
> -        class = object_class_get_parent(class);
> -    } while (class != object_class_by_name(TYPE_DEVICE));
> -
> -    return NULL;
> -}
> -
> -void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
> -                                    Property *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;
> -    }
> -}
> -
> -int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
> -{
> -    char *legacy_name;
> -    Error *err = NULL;
> -
> -    legacy_name = g_strdup_printf("legacy-%s", name);
> -    if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
> -        object_property_parse(OBJECT(dev), value, legacy_name, &err);
> -    } else {
> -        object_property_parse(OBJECT(dev), value, name, &err);
> -    }
> -    g_free(legacy_name);
> -
> -    if (err) {
> -        qerror_report_err(err);
> -        error_free(err);
> -        return -1;
> -    }
> -    return 0;
> -}
> -
> -void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
> -{
> -    Error *errp = NULL;
> -    object_property_set_bool(OBJECT(dev), value, name, &errp);
> -    assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
> -{
> -    Error *errp = NULL;
> -    object_property_set_int(OBJECT(dev), value, name, &errp);
> -    assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
> -{
> -    Error *errp = NULL;
> -    object_property_set_int(OBJECT(dev), value, name, &errp);
> -    assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
> -{
> -    Error *errp = NULL;
> -    object_property_set_int(OBJECT(dev), value, name, &errp);
> -    assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
> -{
> -    Error *errp = NULL;
> -    object_property_set_int(OBJECT(dev), value, name, &errp);
> -    assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
> -{
> -    Error *errp = NULL;
> -    object_property_set_int(OBJECT(dev), value, name, &errp);
> -    assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_string(DeviceState *dev, const char *name, const char 
> *value)
> -{
> -    Error *errp = NULL;
> -    object_property_set_str(OBJECT(dev), value, name, &errp);
> -    assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t 
> *value)
> -{
> -    Error *errp = NULL;
> -    char str[2 * 6 + 5 + 1];
> -    snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
> -             value[0], value[1], value[2], value[3], value[4], value[5]);
> -
> -    object_property_set_str(OBJECT(dev), str, name, &errp);
> -    assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
> -{
> -    Property *prop;
> -    Error *errp = NULL;
> -
> -    prop = qdev_prop_find(dev, name);
> -    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
> -                            name, &errp);
> -    assert_no_error(errp);
> -}
> -
> -void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
> -{
> -    Property *prop;
> -    void **ptr;
> -
> -    prop = qdev_prop_find(dev, name);
> -    assert(prop && prop->info == &qdev_prop_ptr);
> -    ptr = qdev_get_prop_ptr(dev, prop);
> -    *ptr = value;
> -}
> -
> -static QTAILQ_HEAD(, GlobalProperty) global_props = 
> QTAILQ_HEAD_INITIALIZER(global_props);
> -
> -void qdev_prop_register_global(GlobalProperty *prop)
> -{
> -    QTAILQ_INSERT_TAIL(&global_props, prop, next);
> -}
> -
> -void qdev_prop_register_global_list(GlobalProperty *props)
> -{
> -    int i;
> -
> -    for (i = 0; props[i].driver != NULL; i++) {
> -        qdev_prop_register_global(props+i);
> -    }
> -}
> -
> -void qdev_prop_set_globals(DeviceState *dev)
> -{
> -    ObjectClass *class = object_get_class(OBJECT(dev));
> -
> -    do {
> -        GlobalProperty *prop;
> -        QTAILQ_FOREACH(prop, &global_props, next) {
> -            if (strcmp(object_class_get_name(class), prop->driver) != 0) {
> -                continue;
> -            }
> -            if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
> -                exit(1);
> -            }
> -        }
> -        class = object_class_get_parent(class);
> -    } while (class);
> -}
> -
> diff --git a/qom/Makefile.objs b/qom/Makefile.objs
> index 5ef060a..09ef871 100644
> --- a/qom/Makefile.objs
> +++ b/qom/Makefile.objs
> @@ -1,4 +1,4 @@
>  qom-obj-y = object.o container.o qom-qobject.o
> -qom-obj-twice-y = cpu.o
> +qom-obj-twice-y = cpu.o qdev-core.o qdev-properties.o
>  common-obj-y = $(qom-obj-twice-y)
>  user-obj-y = $(qom-obj-twice-y)
> diff --git a/qom/qdev-core.c b/qom/qdev-core.c
> new file mode 100644
> index 0000000..fbb7cb5
> --- /dev/null
> +++ b/qom/qdev-core.c
> @@ -0,0 +1,727 @@
> +/*
> + *  Dynamic device configuration and creation.
> + *
> + *  Copyright (c) 2009 CodeSourcery
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see 
> <http://www.gnu.org/licenses/>.
> + */
> +
> +/* The theory here is that it should be possible to create a machine without
> +   knowledge of specific devices.  Historically board init routines have
> +   passed a bunch of arguments to each device, requiring the board know
> +   exactly which device it is dealing with.  This file provides an abstract
> +   API for device configuration and initialization.  Devices will generally
> +   inherit from a particular bus (e.g. PCI or I2C) rather than
> +   this API directly.  */
> +
> +#include "hw/qdev.h"
> +#include "sysemu.h"
> +#include "error.h"
> +#include "qapi/qapi-visit-core.h"
> +
> +int qdev_hotplug = 0;
> +static bool qdev_hot_added = false;
> +static bool qdev_hot_removed = false;
> +
> +/* vmstate handling:
> + *
> + * The real implementations are on qdev-system.c. Those are weak symbols
> + * used by *-user.
> + */
> +void GCC_WEAK qdev_init_vmstate(DeviceState *dev)
> +{
> +}
> +
> +void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
> +{
> +}
> +
> +/* reset handler register/unregister:
> + *
> + * The real implementations are on qdev-system.c. Those are weak symbols
> + * used by *-user.
> + */
> +void GCC_WEAK qbus_register_reset(BusState *bus)
> +{
> +}
> +
> +void GCC_WEAK qbus_unregister_reset(BusState *bus)
> +{
> +}
> +
> +const char *qdev_fw_name(DeviceState *dev)
> +{
> +    DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +
> +    if (dc->fw_name) {
> +        return dc->fw_name;
> +    }
> +
> +    return object_get_typename(OBJECT(dev));
> +}
> +
> +static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
> +                                     Error **errp);
> +
> +static void bus_remove_child(BusState *bus, DeviceState *child)
> +{
> +    BusChild *kid;
> +
> +    QTAILQ_FOREACH(kid, &bus->children, sibling) {
> +        if (kid->child == child) {
> +            char name[32];
> +
> +            snprintf(name, sizeof(name), "child[%d]", kid->index);
> +            QTAILQ_REMOVE(&bus->children, kid, sibling);
> +            object_property_del(OBJECT(bus), name, NULL);
> +            g_free(kid);
> +            return;
> +        }
> +    }
> +}
> +
> +static void bus_add_child(BusState *bus, DeviceState *child)
> +{
> +    char name[32];
> +    BusChild *kid = g_malloc0(sizeof(*kid));
> +
> +    if (qdev_hotplug) {
> +        assert(bus->allow_hotplug);
> +    }
> +
> +    kid->index = bus->max_index++;
> +    kid->child = child;
> +
> +    QTAILQ_INSERT_HEAD(&bus->children, kid, sibling);
> +
> +    snprintf(name, sizeof(name), "child[%d]", kid->index);
> +    object_property_add_link(OBJECT(bus), name,
> +                             object_get_typename(OBJECT(child)),
> +                             (Object **)&kid->child,
> +                             NULL);
> +}
> +
> +void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
> +{
> +    dev->parent_bus = bus;
> +    bus_add_child(bus, dev);
> +}
> +
> +/* Initialize a device.  Device properties should be set before calling
> +   this function.  IRQs and MMIO regions should be connected/mapped after
> +   calling this function.
> +   On failure, destroy the device and return negative value.
> +   Return 0 on success.  */
> +int qdev_init(DeviceState *dev)
> +{
> +    DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +    int rc;
> +
> +    assert(dev->state == DEV_STATE_CREATED);
> +
> +    rc = dc->init(dev);
> +    if (rc < 0) {
> +        qdev_free(dev);
> +        return rc;
> +    }
> +
> +    if (!OBJECT(dev)->parent) {
> +        static int unattached_count = 0;
> +        gchar *name = g_strdup_printf("device[%d]", unattached_count++);
> +
> +        object_property_add_child(container_get(qdev_get_machine(),
> +                                                "/unattached"),
> +                                  name, OBJECT(dev), NULL);
> +        g_free(name);
> +    }
> +
> +    qdev_init_vmstate(dev);
> +    dev->state = DEV_STATE_INITIALIZED;
> +    if (dev->hotplugged) {
> +        device_reset(dev);
> +    }
> +    return 0;
> +}
> +
> +void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
> +                                 int required_for_version)
> +{
> +    assert(dev->state == DEV_STATE_CREATED);
> +    dev->instance_id_alias = alias_id;
> +    dev->alias_required_for_version = required_for_version;
> +}
> +
> +void qdev_unplug(DeviceState *dev, Error **errp)
> +{
> +    DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +
> +    if (!dev->parent_bus->allow_hotplug) {
> +        error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
> +        return;
> +    }
> +    assert(dc->unplug != NULL);
> +
> +    qdev_hot_removed = true;
> +
> +    if (dc->unplug(dev) < 0) {
> +        error_set(errp, QERR_UNDEFINED_ERROR);
> +        return;
> +    }
> +}
> +
> +static int qdev_reset_one(DeviceState *dev, void *opaque)
> +{
> +    device_reset(dev);
> +
> +    return 0;
> +}
> +
> +static int qbus_reset_one(BusState *bus, void *opaque)
> +{
> +    BusClass *bc = BUS_GET_CLASS(bus);
> +    if (bc->reset) {
> +        return bc->reset(bus);
> +    }
> +    return 0;
> +}
> +
> +void qdev_reset_all(DeviceState *dev)
> +{
> +    qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
> +}
> +
> +void qbus_reset_all_fn(void *opaque)
> +{
> +    BusState *bus = opaque;
> +    qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
> +}
> +
> +/* can be used as ->unplug() callback for the simple cases */
> +int qdev_simple_unplug_cb(DeviceState *dev)
> +{
> +    /* just zap it */
> +    qdev_free(dev);
> +    return 0;
> +}
> +
> +
> +/* Like qdev_init(), but terminate program via error_report() instead of
> +   returning an error value.  This is okay during machine creation.
> +   Don't use for hotplug, because there callers need to recover from
> +   failure.  Exception: if you know the device's init() callback can't
> +   fail, then qdev_init_nofail() can't fail either, and is therefore
> +   usable even then.  But relying on the device implementation that
> +   way is somewhat unclean, and best avoided.  */
> +void qdev_init_nofail(DeviceState *dev)
> +{
> +    const char *typename = object_get_typename(OBJECT(dev));
> +
> +    if (qdev_init(dev) < 0) {
> +        error_report("Initialization of device %s failed", typename);
> +        exit(1);
> +    }
> +}
> +
> +/* Unlink device from bus and free the structure.  */
> +void qdev_free(DeviceState *dev)
> +{
> +    object_delete(OBJECT(dev));
> +}
> +
> +void qdev_machine_creation_done(void)
> +{
> +    /*
> +     * ok, initial machine setup is done, starting from now we can
> +     * only create hotpluggable devices
> +     */
> +    qdev_hotplug = 1;
> +}
> +
> +bool qdev_machine_modified(void)
> +{
> +    return qdev_hot_added || qdev_hot_removed;
> +}
> +
> +BusState *qdev_get_parent_bus(DeviceState *dev)
> +{
> +    return dev->parent_bus;
> +}
> +
> +BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
> +{
> +    BusState *bus;
> +
> +    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> +        if (strcmp(name, bus->name) == 0) {
> +            return bus;
> +        }
> +    }
> +    return NULL;
> +}
> +
> +int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
> +                       qbus_walkerfn *busfn, void *opaque)
> +{
> +    BusChild *kid;
> +    int err;
> +
> +    if (busfn) {
> +        err = busfn(bus, opaque);
> +        if (err) {
> +            return err;
> +        }
> +    }
> +
> +    QTAILQ_FOREACH(kid, &bus->children, sibling) {
> +        err = qdev_walk_children(kid->child, devfn, busfn, opaque);
> +        if (err < 0) {
> +            return err;
> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
> +                       qbus_walkerfn *busfn, void *opaque)
> +{
> +    BusState *bus;
> +    int err;
> +
> +    if (devfn) {
> +        err = devfn(dev, opaque);
> +        if (err) {
> +            return err;
> +        }
> +    }
> +
> +    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> +        err = qbus_walk_children(bus, devfn, busfn, opaque);
> +        if (err < 0) {
> +            return err;
> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +DeviceState *qdev_find_recursive(BusState *bus, const char *id)
> +{
> +    BusChild *kid;
> +    DeviceState *ret;
> +    BusState *child;
> +
> +    QTAILQ_FOREACH(kid, &bus->children, sibling) {
> +        DeviceState *dev = kid->child;
> +
> +        if (dev->id && strcmp(dev->id, id) == 0) {
> +            return dev;
> +        }
> +
> +        QLIST_FOREACH(child, &dev->child_bus, sibling) {
> +            ret = qdev_find_recursive(child, id);
> +            if (ret) {
> +                return ret;
> +            }
> +        }
> +    }
> +    return NULL;
> +}
> +
> +static void qbus_realize(BusState *bus)
> +{
> +    const char *typename = object_get_typename(OBJECT(bus));
> +    char *buf;
> +    int i,len;
> +
> +    if (bus->name) {
> +        /* use supplied name */
> +    } else if (bus->parent && bus->parent->id) {
> +        /* parent device has id -> use it for bus name */
> +        len = strlen(bus->parent->id) + 16;
> +        buf = g_malloc(len);
> +        snprintf(buf, len, "%s.%d", bus->parent->id, 
> bus->parent->num_child_bus);
> +        bus->name = buf;
> +    } else {
> +        /* no id -> use lowercase bus type for bus name */
> +        len = strlen(typename) + 16;
> +        buf = g_malloc(len);
> +        len = snprintf(buf, len, "%s.%d", typename,
> +                       bus->parent ? bus->parent->num_child_bus : 0);
> +        for (i = 0; i < len; i++)
> +            buf[i] = qemu_tolower(buf[i]);
> +        bus->name = buf;
> +    }
> +
> +    if (bus->parent) {
> +        QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
> +        bus->parent->num_child_bus++;
> +        object_property_add_child(OBJECT(bus->parent), bus->name, 
> OBJECT(bus), NULL);
> +    } else {
> +        qbus_register_reset(bus);
> +    }
> +}
> +
> +void qbus_create_inplace(BusState *bus, const char *typename,
> +                         DeviceState *parent, const char *name)
> +{
> +    object_initialize(bus, typename);
> +
> +    bus->parent = parent;
> +    bus->name = name ? g_strdup(name) : NULL;
> +    qbus_realize(bus);
> +}
> +
> +BusState *qbus_create(const char *typename, DeviceState *parent, const char 
> *name)
> +{
> +    BusState *bus;
> +
> +    bus = BUS(object_new(typename));
> +    bus->qom_allocated = true;
> +
> +    bus->parent = parent;
> +    bus->name = name ? g_strdup(name) : NULL;
> +    qbus_realize(bus);
> +
> +    return bus;
> +}
> +
> +void qbus_free(BusState *bus)
> +{
> +    if (bus->qom_allocated) {
> +        object_delete(OBJECT(bus));
> +    } else {
> +        object_finalize(OBJECT(bus));
> +        if (bus->glib_allocated) {
> +            g_free(bus);
> +        }
> +    }
> +}
> +
> +static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
> +{
> +    BusClass *bc = BUS_GET_CLASS(bus);
> +
> +    if (bc->get_fw_dev_path) {
> +        return bc->get_fw_dev_path(dev);
> +    }
> +
> +    return NULL;
> +}
> +
> +static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
> +{
> +    int l = 0;
> +
> +    if (dev && dev->parent_bus) {
> +        char *d;
> +        l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
> +        d = bus_get_fw_dev_path(dev->parent_bus, dev);
> +        if (d) {
> +            l += snprintf(p + l, size - l, "%s", d);
> +            g_free(d);
> +        } else {
> +            l += snprintf(p + l, size - l, "%s", 
> object_get_typename(OBJECT(dev)));
> +        }
> +    }
> +    l += snprintf(p + l , size - l, "/");
> +
> +    return l;
> +}
> +
> +char* qdev_get_fw_dev_path(DeviceState *dev)
> +{
> +    char path[128];
> +    int l;
> +
> +    l = qdev_get_fw_dev_path_helper(dev, path, 128);
> +
> +    path[l-1] = '\0';
> +
> +    return g_strdup(path);
> +}
> +
> +char *qdev_get_dev_path(DeviceState *dev)
> +{
> +    BusClass *bc;
> +
> +    if (!dev || !dev->parent_bus) {
> +        return NULL;
> +    }
> +
> +    bc = BUS_GET_CLASS(dev->parent_bus);
> +    if (bc->get_dev_path) {
> +        return bc->get_dev_path(dev);
> +    }
> +
> +    return NULL;
> +}
> +
> +/**
> + * Legacy property handling
> + */
> +
> +static void qdev_get_legacy_property(Object *obj, Visitor *v, void *opaque,
> +                                     const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +
> +    char buffer[1024];
> +    char *ptr = buffer;
> +
> +    prop->info->print(dev, prop, buffer, sizeof(buffer));
> +    visit_type_str(v, &ptr, name, errp);
> +}
> +
> +static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
> +                                     const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    Error *local_err = NULL;
> +    char *ptr = NULL;
> +    int ret;
> +
> +    if (dev->state != DEV_STATE_CREATED) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    visit_type_str(v, &ptr, name, &local_err);
> +    if (local_err) {
> +        error_propagate(errp, local_err);
> +        return;
> +    }
> +
> +    ret = prop->info->parse(dev, prop, ptr);
> +    error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
> +    g_free(ptr);
> +}
> +
> +/**
> + * @qdev_add_legacy_property - adds a legacy property
> + *
> + * Do not use this is new code!  Properties added through this interface will
> + * be given names and types in the "legacy" namespace.
> + *
> + * Legacy properties are string versions of other OOM properties.  The format
> + * of the string depends on the property type.
> + */
> +void qdev_property_add_legacy(DeviceState *dev, Property *prop,
> +                              Error **errp)
> +{
> +    gchar *name, *type;
> +
> +    /* Register pointer properties as legacy properties */
> +    if (!prop->info->print && !prop->info->parse &&
> +        (prop->info->set || prop->info->get)) {
> +        return;
> +    }
> +
> +    name = g_strdup_printf("legacy-%s", prop->name);
> +    type = g_strdup_printf("legacy<%s>",
> +                           prop->info->legacy_name ?: prop->info->name);
> +
> +    object_property_add(OBJECT(dev), name, type,
> +                        prop->info->print ? qdev_get_legacy_property : 
> prop->info->get,
> +                        prop->info->parse ? qdev_set_legacy_property : 
> prop->info->set,
> +                        NULL,
> +                        prop, errp);
> +
> +    g_free(type);
> +    g_free(name);
> +}
> +
> +/**
> + * @qdev_property_add_static - add a @Property to a device.
> + *
> + * Static properties access data in a struct.  The actual type of the
> + * property and the field depends on the property type.
> + */
> +void qdev_property_add_static(DeviceState *dev, Property *prop,
> +                              Error **errp)
> +{
> +    Error *local_err = NULL;
> +    Object *obj = OBJECT(dev);
> +
> +    /*
> +     * TODO qdev_prop_ptr does not have getters or setters.  It must
> +     * go now that it can be replaced with links.  The test should be
> +     * removed along with it: all static properties are read/write.
> +     */
> +    if (!prop->info->get && !prop->info->set) {
> +        return;
> +    }
> +
> +    object_property_add(obj, prop->name, prop->info->name,
> +                        prop->info->get, prop->info->set,
> +                        prop->info->release,
> +                        prop, &local_err);
> +
> +    if (local_err) {
> +        error_propagate(errp, local_err);
> +        return;
> +    }
> +    if (prop->qtype == QTYPE_NONE) {
> +        return;
> +    }
> +
> +    if (prop->qtype == QTYPE_QBOOL) {
> +        object_property_set_bool(obj, prop->defval, prop->name, &local_err);
> +    } else if (prop->info->enum_table) {
> +        object_property_set_str(obj, prop->info->enum_table[prop->defval],
> +                                prop->name, &local_err);
> +    } else if (prop->qtype == QTYPE_QINT) {
> +        object_property_set_int(obj, prop->defval, prop->name, &local_err);
> +    }
> +    assert_no_error(local_err);
> +}
> +
> +static void device_initfn(Object *obj)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    ObjectClass *class;
> +    Property *prop;
> +
> +    if (qdev_hotplug) {
> +        dev->hotplugged = 1;
> +        qdev_hot_added = true;
> +    }
> +
> +    dev->instance_id_alias = -1;
> +    dev->state = DEV_STATE_CREATED;
> +
> +    class = object_get_class(OBJECT(dev));
> +    do {
> +        for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
> +            qdev_property_add_legacy(dev, prop, NULL);
> +            qdev_property_add_static(dev, prop, NULL);
> +        }
> +        class = object_class_get_parent(class);
> +    } while (class != object_class_by_name(TYPE_DEVICE));
> +    qdev_prop_set_globals(dev);
> +
> +    object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
> +                             (Object **)&dev->parent_bus, NULL);
> +}
> +
> +/* Unlink device from bus and free the structure.  */
> +static void device_finalize(Object *obj)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    BusState *bus;
> +    DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +
> +    if (dev->state == DEV_STATE_INITIALIZED) {
> +        while (dev->num_child_bus) {
> +            bus = QLIST_FIRST(&dev->child_bus);
> +            qbus_free(bus);
> +        }
> +        qdev_finalize_vmstate(dev);
> +        if (dc->exit) {
> +            dc->exit(dev);
> +        }
> +        if (dev->opts) {
> +            qemu_opts_del(dev->opts);
> +        }
> +    }
> +    if (dev->parent_bus) {
> +        bus_remove_child(dev->parent_bus, dev);
> +    }
> +}
> +
> +static void device_class_base_init(ObjectClass *class, void *data)
> +{
> +    DeviceClass *klass = DEVICE_CLASS(class);
> +
> +    /* We explicitly look up properties in the superclasses,
> +     * so do not propagate them to the subclasses.
> +     */
> +    klass->props = NULL;
> +}
> +
> +void device_reset(DeviceState *dev)
> +{
> +    DeviceClass *klass = DEVICE_GET_CLASS(dev);
> +
> +    if (klass->reset) {
> +        klass->reset(dev);
> +    }
> +}
> +
> +Object *qdev_get_machine(void)
> +{
> +    static Object *dev;
> +
> +    if (dev == NULL) {
> +        dev = container_get(object_get_root(), "/machine");
> +    }
> +
> +    return dev;
> +}
> +
> +static TypeInfo device_type_info = {
> +    .name = TYPE_DEVICE,
> +    .parent = TYPE_OBJECT,
> +    .instance_size = sizeof(DeviceState),
> +    .instance_init = device_initfn,
> +    .instance_finalize = device_finalize,
> +    .class_base_init = device_class_base_init,
> +    .abstract = true,
> +    .class_size = sizeof(DeviceClass),
> +};
> +
> +static void qbus_initfn(Object *obj)
> +{
> +    BusState *bus = BUS(obj);
> +
> +    QTAILQ_INIT(&bus->children);
> +}
> +
> +static void qbus_finalize(Object *obj)
> +{
> +    BusState *bus = BUS(obj);
> +    BusChild *kid;
> +
> +    while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
> +        DeviceState *dev = kid->child;
> +        qdev_free(dev);
> +    }
> +    if (bus->parent) {
> +        QLIST_REMOVE(bus, sibling);
> +        bus->parent->num_child_bus--;
> +    } else {
> +        qbus_unregister_reset(bus);
> +    }
> +    g_free((char *)bus->name);
> +}
> +
> +static const TypeInfo bus_info = {
> +    .name = TYPE_BUS,
> +    .parent = TYPE_OBJECT,
> +    .instance_size = sizeof(BusState),
> +    .abstract = true,
> +    .class_size = sizeof(BusClass),
> +    .instance_init = qbus_initfn,
> +    .instance_finalize = qbus_finalize,
> +};
> +
> +static void qdev_register_types(void)
> +{
> +    type_register_static(&bus_info);
> +    type_register_static(&device_type_info);
> +}
> +
> +type_init(qdev_register_types)
> diff --git a/qom/qdev-properties.c b/qom/qdev-properties.c
> new file mode 100644
> index 0000000..2e82cb9
> --- /dev/null
> +++ b/qom/qdev-properties.c
> @@ -0,0 +1,963 @@
> +#include "net.h"
> +#include "hw/qdev.h"
> +#include "qerror.h"
> +#include "blockdev.h"
> +#include "hw/block-common.h"
> +#include "net/hub.h"
> +#include "qapi/qapi-visit-core.h"
> +
> +void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
> +{
> +    void *ptr = dev;
> +    ptr += prop->offset;
> +    return ptr;
> +}
> +
> +static void get_enum(Object *obj, Visitor *v, void *opaque,
> +                     const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    int *ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    visit_type_enum(v, ptr, prop->info->enum_table,
> +                    prop->info->name, prop->name, errp);
> +}
> +
> +static void set_enum(Object *obj, Visitor *v, void *opaque,
> +                     const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    int *ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    if (dev->state != DEV_STATE_CREATED) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    visit_type_enum(v, ptr, prop->info->enum_table,
> +                    prop->info->name, prop->name, errp);
> +}
> +
> +/* Bit */
> +
> +static uint32_t qdev_get_prop_mask(Property *prop)
> +{
> +    assert(prop->info == &qdev_prop_bit);
> +    return 0x1 << prop->bitnr;
> +}
> +
> +static void bit_prop_set(DeviceState *dev, Property *props, bool val)
> +{
> +    uint32_t *p = qdev_get_prop_ptr(dev, props);
> +    uint32_t mask = qdev_get_prop_mask(props);
> +    if (val)
> +        *p |= mask;
> +    else
> +        *p &= ~mask;
> +}
> +
> +static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t 
> len)
> +{
> +    uint32_t *p = qdev_get_prop_ptr(dev, prop);
> +    return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : 
> "off");
> +}
> +
> +static void get_bit(Object *obj, Visitor *v, void *opaque,
> +                    const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    uint32_t *p = qdev_get_prop_ptr(dev, prop);
> +    bool value = (*p & qdev_get_prop_mask(prop)) != 0;
> +
> +    visit_type_bool(v, &value, name, errp);
> +}
> +
> +static void set_bit(Object *obj, Visitor *v, void *opaque,
> +                    const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    Error *local_err = NULL;
> +    bool value;
> +
> +    if (dev->state != DEV_STATE_CREATED) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    visit_type_bool(v, &value, name, &local_err);
> +    if (local_err) {
> +        error_propagate(errp, local_err);
> +        return;
> +    }
> +    bit_prop_set(dev, prop, value);
> +}
> +
> +PropertyInfo qdev_prop_bit = {
> +    .name  = "boolean",
> +    .legacy_name  = "on/off",
> +    .print = print_bit,
> +    .get   = get_bit,
> +    .set   = set_bit,
> +};
> +
> +/* --- 8bit integer --- */
> +
> +static void get_uint8(Object *obj, Visitor *v, void *opaque,
> +                      const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    visit_type_uint8(v, ptr, name, errp);
> +}
> +
> +static void set_uint8(Object *obj, Visitor *v, void *opaque,
> +                      const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    if (dev->state != DEV_STATE_CREATED) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    visit_type_uint8(v, ptr, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_uint8 = {
> +    .name  = "uint8",
> +    .get   = get_uint8,
> +    .set   = set_uint8,
> +};
> +
> +/* --- 8bit hex value --- */
> +
> +static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
> +{
> +    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> +    char *end;
> +
> +    if (str[0] != '0' || str[1] != 'x') {
> +        return -EINVAL;
> +    }
> +
> +    *ptr = strtoul(str, &end, 16);
> +    if ((*end != '\0') || (end == str)) {
> +        return -EINVAL;
> +    }
> +
> +    return 0;
> +}
> +
> +static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t 
> len)
> +{
> +    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
> +    return snprintf(dest, len, "0x%" PRIx8, *ptr);
> +}
> +
> +PropertyInfo qdev_prop_hex8 = {
> +    .name  = "uint8",
> +    .legacy_name  = "hex8",
> +    .parse = parse_hex8,
> +    .print = print_hex8,
> +    .get   = get_uint8,
> +    .set   = set_uint8,
> +};
> +
> +/* --- 16bit integer --- */
> +
> +static void get_uint16(Object *obj, Visitor *v, void *opaque,
> +                       const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    visit_type_uint16(v, ptr, name, errp);
> +}
> +
> +static void set_uint16(Object *obj, Visitor *v, void *opaque,
> +                       const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    if (dev->state != DEV_STATE_CREATED) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    visit_type_uint16(v, ptr, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_uint16 = {
> +    .name  = "uint16",
> +    .get   = get_uint16,
> +    .set   = set_uint16,
> +};
> +
> +/* --- 32bit integer --- */
> +
> +static void get_uint32(Object *obj, Visitor *v, void *opaque,
> +                       const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    visit_type_uint32(v, ptr, name, errp);
> +}
> +
> +static void set_uint32(Object *obj, Visitor *v, void *opaque,
> +                       const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    if (dev->state != DEV_STATE_CREATED) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    visit_type_uint32(v, ptr, name, errp);
> +}
> +
> +static void get_int32(Object *obj, Visitor *v, void *opaque,
> +                      const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    visit_type_int32(v, ptr, name, errp);
> +}
> +
> +static void set_int32(Object *obj, Visitor *v, void *opaque,
> +                      const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    if (dev->state != DEV_STATE_CREATED) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    visit_type_int32(v, ptr, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_uint32 = {
> +    .name  = "uint32",
> +    .get   = get_uint32,
> +    .set   = set_uint32,
> +};
> +
> +PropertyInfo qdev_prop_int32 = {
> +    .name  = "int32",
> +    .get   = get_int32,
> +    .set   = set_int32,
> +};
> +
> +/* --- 32bit hex value --- */
> +
> +static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
> +{
> +    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +    char *end;
> +
> +    if (str[0] != '0' || str[1] != 'x') {
> +        return -EINVAL;
> +    }
> +
> +    *ptr = strtoul(str, &end, 16);
> +    if ((*end != '\0') || (end == str)) {
> +        return -EINVAL;
> +    }
> +
> +    return 0;
> +}
> +
> +static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t 
> len)
> +{
> +    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +    return snprintf(dest, len, "0x%" PRIx32, *ptr);
> +}
> +
> +PropertyInfo qdev_prop_hex32 = {
> +    .name  = "uint32",
> +    .legacy_name  = "hex32",
> +    .parse = parse_hex32,
> +    .print = print_hex32,
> +    .get   = get_uint32,
> +    .set   = set_uint32,
> +};
> +
> +/* --- 64bit integer --- */
> +
> +static void get_uint64(Object *obj, Visitor *v, void *opaque,
> +                       const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    visit_type_uint64(v, ptr, name, errp);
> +}
> +
> +static void set_uint64(Object *obj, Visitor *v, void *opaque,
> +                       const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    if (dev->state != DEV_STATE_CREATED) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    visit_type_uint64(v, ptr, name, errp);
> +}
> +
> +PropertyInfo qdev_prop_uint64 = {
> +    .name  = "uint64",
> +    .get   = get_uint64,
> +    .set   = set_uint64,
> +};
> +
> +/* --- 64bit hex value --- */
> +
> +static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
> +{
> +    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> +    char *end;
> +
> +    if (str[0] != '0' || str[1] != 'x') {
> +        return -EINVAL;
> +    }
> +
> +    *ptr = strtoull(str, &end, 16);
> +    if ((*end != '\0') || (end == str)) {
> +        return -EINVAL;
> +    }
> +
> +    return 0;
> +}
> +
> +static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t 
> len)
> +{
> +    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
> +    return snprintf(dest, len, "0x%" PRIx64, *ptr);
> +}
> +
> +PropertyInfo qdev_prop_hex64 = {
> +    .name  = "uint64",
> +    .legacy_name  = "hex64",
> +    .parse = parse_hex64,
> +    .print = print_hex64,
> +    .get   = get_uint64,
> +    .set   = set_uint64,
> +};
> +
> +/* --- string --- */
> +
> +static void release_string(Object *obj, const char *name, void *opaque)
> +{
> +    Property *prop = opaque;
> +    g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
> +}
> +
> +static int print_string(DeviceState *dev, Property *prop, char *dest, size_t 
> len)
> +{
> +    char **ptr = qdev_get_prop_ptr(dev, prop);
> +    if (!*ptr)
> +        return snprintf(dest, len, "<null>");
> +    return snprintf(dest, len, "\"%s\"", *ptr);
> +}
> +
> +static void get_string(Object *obj, Visitor *v, void *opaque,
> +                       const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    char **ptr = qdev_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)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    char **ptr = qdev_get_prop_ptr(dev, prop);
> +    Error *local_err = NULL;
> +    char *str;
> +
> +    if (dev->state != DEV_STATE_CREATED) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    visit_type_str(v, &str, name, &local_err);
> +    if (local_err) {
> +        error_propagate(errp, local_err);
> +        return;
> +    }
> +    if (*ptr) {
> +        g_free(*ptr);
> +    }
> +    *ptr = str;
> +}
> +
> +PropertyInfo qdev_prop_string = {
> +    .name  = "string",
> +    .print = print_string,
> +    .release = release_string,
> +    .get   = get_string,
> +    .set   = set_string,
> +};
> +
> +/* --- pointer --- */
> +
> +/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
> +PropertyInfo qdev_prop_ptr = {
> +    .name  = "ptr",
> +};
> +
> +/* --- mac address --- */
> +
> +/*
> + * accepted syntax versions:
> + *   01:02:03:04:05:06
> + *   01-02-03-04-05-06
> + */
> +static void get_mac(Object *obj, Visitor *v, void *opaque,
> +                    const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
> +    char buffer[2 * 6 + 5 + 1];
> +    char *p = buffer;
> +
> +    snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
> +             mac->a[0], mac->a[1], mac->a[2],
> +             mac->a[3], mac->a[4], mac->a[5]);
> +
> +    visit_type_str(v, &p, name, errp);
> +}
> +
> +static void set_mac(Object *obj, Visitor *v, void *opaque,
> +                    const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
> +    Error *local_err = NULL;
> +    int i, pos;
> +    char *str, *p;
> +
> +    if (dev->state != DEV_STATE_CREATED) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    visit_type_str(v, &str, name, &local_err);
> +    if (local_err) {
> +        error_propagate(errp, local_err);
> +        return;
> +    }
> +
> +    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
> +        if (!qemu_isxdigit(str[pos]))
> +            goto inval;
> +        if (!qemu_isxdigit(str[pos+1]))
> +            goto inval;
> +        if (i == 5) {
> +            if (str[pos+2] != '\0')
> +                goto inval;
> +        } else {
> +            if (str[pos+2] != ':' && str[pos+2] != '-')
> +                goto inval;
> +        }
> +        mac->a[i] = strtol(str+pos, &p, 16);
> +    }
> +    g_free(str);
> +    return;
> +
> +inval:
> +    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> +    g_free(str);
> +}
> +
> +PropertyInfo qdev_prop_macaddr = {
> +    .name  = "macaddr",
> +    .get   = get_mac,
> +    .set   = set_mac,
> +};
> +
> +/* --- lost tick policy --- */
> +
> +static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
> +    [LOST_TICK_DISCARD] = "discard",
> +    [LOST_TICK_DELAY] = "delay",
> +    [LOST_TICK_MERGE] = "merge",
> +    [LOST_TICK_SLEW] = "slew",
> +    [LOST_TICK_MAX] = NULL,
> +};
> +
> +QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
> +
> +PropertyInfo qdev_prop_losttickpolicy = {
> +    .name  = "LostTickPolicy",
> +    .enum_table  = lost_tick_policy_table,
> +    .get   = get_enum,
> +    .set   = set_enum,
> +};
> +
> +/* --- BIOS CHS translation */
> +
> +static const char *bios_chs_trans_table[] = {
> +    [BIOS_ATA_TRANSLATION_AUTO] = "auto",
> +    [BIOS_ATA_TRANSLATION_NONE] = "none",
> +    [BIOS_ATA_TRANSLATION_LBA]  = "lba",
> +};
> +
> +PropertyInfo qdev_prop_bios_chs_trans = {
> +    .name = "bios-chs-trans",
> +    .enum_table = bios_chs_trans_table,
> +    .get = get_enum,
> +    .set = set_enum,
> +};
> +
> +/* --- pci address --- */
> +
> +/*
> + * bus-local address, i.e. "$slot" or "$slot.$fn"
> + */
> +static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
> +                          const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
> +    unsigned int slot, fn, n;
> +    Error *local_err = NULL;
> +    char *str;
> +
> +    if (dev->state != DEV_STATE_CREATED) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    visit_type_str(v, &str, name, &local_err);
> +    if (local_err) {
> +        error_free(local_err);
> +        local_err = NULL;
> +        visit_type_int32(v, &value, name, &local_err);
> +        if (local_err) {
> +            error_propagate(errp, local_err);
> +        } else if (value < -1 || value > 255) {
> +            error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : 
> "null",
> +                      "pci_devfn");
> +        } else {
> +            *ptr = value;
> +        }
> +        return;
> +    }
> +
> +    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
> +        fn = 0;
> +        if (sscanf(str, "%x%n", &slot, &n) != 1) {
> +            goto invalid;
> +        }
> +    }
> +    if (str[n] != '\0' || fn > 7 || slot > 31) {
> +        goto invalid;
> +    }
> +    *ptr = slot << 3 | fn;
> +    g_free(str);
> +    return;
> +
> +invalid:
> +    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> +    g_free(str);
> +}
> +
> +static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, 
> size_t len)
> +{
> +    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    if (*ptr == -1) {
> +        return snprintf(dest, len, "<unset>");
> +    } else {
> +        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
> +    }
> +}
> +
> +PropertyInfo qdev_prop_pci_devfn = {
> +    .name  = "int32",
> +    .legacy_name  = "pci-devfn",
> +    .print = print_pci_devfn,
> +    .get   = get_int32,
> +    .set   = set_pci_devfn,
> +};
> +
> +/* --- blocksize --- */
> +
> +static void set_blocksize(Object *obj, Visitor *v, void *opaque,
> +                          const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
> +    Error *local_err = NULL;
> +    const int64_t min = 512;
> +    const int64_t max = 32768;
> +
> +    if (dev->state != DEV_STATE_CREATED) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    visit_type_uint16(v, &value, name, &local_err);
> +    if (local_err) {
> +        error_propagate(errp, local_err);
> +        return;
> +    }
> +    if (value < min || value > max) {
> +        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
> +                  dev->id?:"", name, (int64_t)value, min, max);
> +        return;
> +    }
> +
> +    /* We rely on power-of-2 blocksizes for bitmasks */
> +    if ((value & (value - 1)) != 0) {
> +        error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
> +                  dev->id?:"", name, (int64_t)value);
> +        return;
> +    }
> +
> +    *ptr = value;
> +}
> +
> +PropertyInfo qdev_prop_blocksize = {
> +    .name  = "blocksize",
> +    .get   = get_uint16,
> +    .set   = set_blocksize,
> +};
> +
> +/* --- pci host address --- */
> +
> +static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
> +                                 const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
> +    char buffer[] = "xxxx:xx:xx.x";
> +    char *p = buffer;
> +    int rc = 0;
> +
> +    rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
> +                  addr->domain, addr->bus, addr->slot, addr->function);
> +    assert(rc == sizeof(buffer) - 1);
> +
> +    visit_type_str(v, &p, name, errp);
> +}
> +
> +/*
> + * Parse [<domain>:]<bus>:<slot>.<func>
> + *   if <domain> is not supplied, it's assumed to be 0.
> + */
> +static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
> +                                 const char *name, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    Property *prop = opaque;
> +    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
> +    Error *local_err = NULL;
> +    char *str, *p;
> +    char *e;
> +    unsigned long val;
> +    unsigned long dom = 0, bus = 0;
> +    unsigned int slot = 0, func = 0;
> +
> +    if (dev->state != DEV_STATE_CREATED) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    visit_type_str(v, &str, name, &local_err);
> +    if (local_err) {
> +        error_propagate(errp, local_err);
> +        return;
> +    }
> +
> +    p = str;
> +    val = strtoul(p, &e, 16);
> +    if (e == p || *e != ':') {
> +        goto inval;
> +    }
> +    bus = val;
> +
> +    p = e + 1;
> +    val = strtoul(p, &e, 16);
> +    if (e == p) {
> +        goto inval;
> +    }
> +    if (*e == ':') {
> +        dom = bus;
> +        bus = val;
> +        p = e + 1;
> +        val = strtoul(p, &e, 16);
> +        if (e == p) {
> +            goto inval;
> +        }
> +    }
> +    slot = val;
> +
> +    if (*e != '.') {
> +        goto inval;
> +    }
> +    p = e + 1;
> +    val = strtoul(p, &e, 10);
> +    if (e == p) {
> +        goto inval;
> +    }
> +    func = val;
> +
> +    if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
> +        goto inval;
> +    }
> +
> +    if (*e) {
> +        goto inval;
> +    }
> +
> +    addr->domain = dom;
> +    addr->bus = bus;
> +    addr->slot = slot;
> +    addr->function = func;
> +
> +    g_free(str);
> +    return;
> +
> +inval:
> +    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
> +    g_free(str);
> +}
> +
> +PropertyInfo qdev_prop_pci_host_devaddr = {
> +    .name = "pci-host-devaddr",
> +    .get = get_pci_host_devaddr,
> +    .set = set_pci_host_devaddr,
> +};
> +
> +/* --- public helpers --- */
> +
> +static Property *qdev_prop_walk(Property *props, const char *name)
> +{
> +    if (!props)
> +        return NULL;
> +    while (props->name) {
> +        if (strcmp(props->name, name) == 0)
> +            return props;
> +        props++;
> +    }
> +    return NULL;
> +}
> +
> +static Property *qdev_prop_find(DeviceState *dev, const char *name)
> +{
> +    ObjectClass *class;
> +    Property *prop;
> +
> +    /* device properties */
> +    class = object_get_class(OBJECT(dev));
> +    do {
> +        prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
> +        if (prop) {
> +            return prop;
> +        }
> +        class = object_class_get_parent(class);
> +    } while (class != object_class_by_name(TYPE_DEVICE));
> +
> +    return NULL;
> +}
> +
> +void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
> +                                    Property *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;
> +    }
> +}
> +
> +int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
> +{
> +    char *legacy_name;
> +    Error *err = NULL;
> +
> +    legacy_name = g_strdup_printf("legacy-%s", name);
> +    if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
> +        object_property_parse(OBJECT(dev), value, legacy_name, &err);
> +    } else {
> +        object_property_parse(OBJECT(dev), value, name, &err);
> +    }
> +    g_free(legacy_name);
> +
> +    if (err) {
> +        qerror_report_err(err);
> +        error_free(err);
> +        return -1;
> +    }
> +    return 0;
> +}
> +
> +void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
> +{
> +    Error *errp = NULL;
> +    object_property_set_bool(OBJECT(dev), value, name, &errp);
> +    assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
> +{
> +    Error *errp = NULL;
> +    object_property_set_int(OBJECT(dev), value, name, &errp);
> +    assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
> +{
> +    Error *errp = NULL;
> +    object_property_set_int(OBJECT(dev), value, name, &errp);
> +    assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
> +{
> +    Error *errp = NULL;
> +    object_property_set_int(OBJECT(dev), value, name, &errp);
> +    assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
> +{
> +    Error *errp = NULL;
> +    object_property_set_int(OBJECT(dev), value, name, &errp);
> +    assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
> +{
> +    Error *errp = NULL;
> +    object_property_set_int(OBJECT(dev), value, name, &errp);
> +    assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_string(DeviceState *dev, const char *name, const char 
> *value)
> +{
> +    Error *errp = NULL;
> +    object_property_set_str(OBJECT(dev), value, name, &errp);
> +    assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t 
> *value)
> +{
> +    Error *errp = NULL;
> +    char str[2 * 6 + 5 + 1];
> +    snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
> +             value[0], value[1], value[2], value[3], value[4], value[5]);
> +
> +    object_property_set_str(OBJECT(dev), str, name, &errp);
> +    assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
> +{
> +    Property *prop;
> +    Error *errp = NULL;
> +
> +    prop = qdev_prop_find(dev, name);
> +    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
> +                            name, &errp);
> +    assert_no_error(errp);
> +}
> +
> +void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
> +{
> +    Property *prop;
> +    void **ptr;
> +
> +    prop = qdev_prop_find(dev, name);
> +    assert(prop && prop->info == &qdev_prop_ptr);
> +    ptr = qdev_get_prop_ptr(dev, prop);
> +    *ptr = value;
> +}
> +
> +static QTAILQ_HEAD(, GlobalProperty) global_props = 
> QTAILQ_HEAD_INITIALIZER(global_props);
> +
> +void qdev_prop_register_global(GlobalProperty *prop)
> +{
> +    QTAILQ_INSERT_TAIL(&global_props, prop, next);
> +}
> +
> +void qdev_prop_register_global_list(GlobalProperty *props)
> +{
> +    int i;
> +
> +    for (i = 0; props[i].driver != NULL; i++) {
> +        qdev_prop_register_global(props+i);
> +    }
> +}
> +
> +void qdev_prop_set_globals(DeviceState *dev)
> +{
> +    ObjectClass *class = object_get_class(OBJECT(dev));
> +
> +    do {
> +        GlobalProperty *prop;
> +        QTAILQ_FOREACH(prop, &global_props, next) {
> +            if (strcmp(object_class_get_name(class), prop->driver) != 0) {
> +                continue;
> +            }
> +            if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
> +                exit(1);
> +            }
> +        }
> +        class = object_class_get_parent(class);
> +    } while (class);
> +}
> +
> -- 
> 1.7.11.7



reply via email to

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