All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user
@ 2012-10-16 19:08 Eduardo Habkost
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 01/12] qdev: split up header so it can be used in cpu.h Eduardo Habkost
                   ` (11 more replies)
  0 siblings, 12 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

v2:
  This version removes the CONFIG_USER_ONLY ifdefs, and use weak symbols to move
  the vmstate and qemu_register_reset() handling to qdev-system.c
v3 (submitted by Igor):
  - rebased on top of 8b4a3df (today's master)
  - slight code reshuffling in (see commit's changelog)
     "qdev: separate core from the code used only by qemu-system-*"
     "move qemu_irq typedef out of cpu-common.h"
  - commit messages cleanup
v4:
  - Add GCC_WEAK_DECL to functions that have GCC_WEAK versions
  - Updated the qdev_init_gpio_in() code on qdev-system.c to current version
  - Patch description updates (moved changelog below "---" and/or move info
    about changes made by different authors between SoB lines)

git tree for testing:
  https://github.com/ehabkost/qemu-hacks/tree/cpu_qdev.v4

References to previous versions:
  v3: http://article.gmane.org/gmane.comp.emulators.qemu/175980
  v2: http://article.gmane.org/gmane.comp.emulators.qemu/173909
  v1: http://article.gmane.org/gmane.comp.emulators.qemu/166630

Anthony Liguori (1):
  qdev: split up header so it can be used in cpu.h

Eduardo Habkost (8):
  qdev: separate core from the code used only by qemu-system-*
  qdev: rename qdev.c to qdev-core.c
  qdev-core: isolate vmstate handling into separate functions
  qdev: move vmstate handling to qdev-system.c
  qdev-core: isolate reset register/unregister code
  qdev: move reset register/unregister code to qdev-system.c
  qdev: use full qdev.h include path on qdev*.c
  include core qdev code into *-user, too

Igor Mammedov (3):
  qapi-types.h doesn't really need to include qemu-common.h
  move qemu_irq typedef out of cpu-common.h
  qom: make CPU a child of DeviceState

 Makefile.objs               |    3 +
 hw/Makefile.objs            |    3 +-
 hw/arm-misc.h               |    1 +
 hw/bt.h                     |    2 +
 hw/devices.h                |    2 +
 hw/irq.h                    |    2 +
 hw/mc146818rtc.c            |    1 +
 hw/omap.h                   |    1 +
 hw/qdev-addr.c              |    1 +
 hw/qdev-core.h              |  243 ++++++++
 hw/qdev-monitor.h           |   16 +
 hw/qdev-properties-system.c |  340 ++++++++++++
 hw/qdev-properties.c        | 1280 -------------------------------------------
 hw/qdev-properties.h        |  131 +++++
 hw/qdev-system.c            |  105 ++++
 hw/qdev.c                   |  795 ---------------------------
 hw/qdev.h                   |  370 +------------
 hw/soc_dma.h                |    1 +
 hw/xen.h                    |    1 +
 include/qemu/cpu.h          |    6 +-
 qemu-common.h               |    1 -
 qom/Makefile.objs           |    2 +-
 qom/cpu.c                   |    3 +-
 qom/qdev-core.c             |  727 ++++++++++++++++++++++++
 qom/qdev-properties.c       |  963 ++++++++++++++++++++++++++++++++
 scripts/qapi-types.py       |    3 +-
 26 files changed, 2554 insertions(+), 2449 deletions(-)
 create mode 100644 hw/qdev-core.h
 create mode 100644 hw/qdev-monitor.h
 create mode 100644 hw/qdev-properties-system.c
 delete mode 100644 hw/qdev-properties.c
 create mode 100644 hw/qdev-properties.h
 create mode 100644 hw/qdev-system.c
 delete mode 100644 hw/qdev.c
 create mode 100644 qom/qdev-core.c
 create mode 100644 qom/qdev-properties.c

-- 
1.7.11.7

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 01/12] qdev: split up header so it can be used in cpu.h
  2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 02/12] qapi-types.h doesn't really need to include qemu-common.h Eduardo Habkost
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

From: Anthony Liguori <aliguori@us.ibm.com>

Header file dependency is a frickin' nightmare right now.  cpu.h tends to get
included in our 'include everything' header files but qdev also needs to include
those headers mainly for qdev-properties since it knows about CharDriverState
and friends.

We can solve this for now by splitting out qdev.h along the same lines that we
previously split the C file.  Then cpu.h just needs to include qdev-core.h

hw/qdev.h is split into following new headers:
    hw/qdev-core.h
    hw/qdev-properties.h
    hw/qdev-monitor.h

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

[ehabkost: re-add DEFINE_PROP_PCI_HOST_DEVADDR, that was removed on the
 original patch (by mistake, I guess)]
[ehabkost: kill qdev_prop_set_vlan() declaration]
[ehabkost: moved get_fw_dev_path() comment to the original location
 (I don't know why it was moved)]
[ehabkost: removed qdev_exists() declaration]
[ehabkost: keep using 'QemuOpts' instead of 'struct QemuOpts', as
 qdev-core.h includes qemu-option.h]

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Yes, there is "changelog" data before the "---" mark, but I believe that
in this case they are important to indicate authorship and the scope of
the Signed-off-by lines (so they need to get into the git commit
message)

Detailed changelog:

Changes v1 (from Anthony) -> v2 (from Eduardo):
 - re-add DEFINE_PROP_PCI_HOST_DEVADDR, that was removed on the original
   patch (by mistake, I guess)
 - kill qdev_prop_set_vlan() declaration

Changes v2 -> v3 (from Eduardo):
 - moved get_fw_dev_path() comment to the original location (I don't
   know why it was moved)
 - removed qdev_exists() declaration
 - keep using 'QemuOpts' instead of 'struct QemuOpts', as qdev-core.h
   includes qemu-option.h

Changes v3 -> v4 (from Eduardo):
 - Edited commit message to include additional information
---
 hw/irq.h             |   2 +
 hw/mc146818rtc.c     |   1 +
 hw/qdev-addr.c       |   1 +
 hw/qdev-core.h       | 238 +++++++++++++++++++++++++++++++++
 hw/qdev-monitor.h    |  16 +++
 hw/qdev-properties.c |   1 +
 hw/qdev-properties.h | 130 ++++++++++++++++++
 hw/qdev.c            |   1 +
 hw/qdev.h            | 370 +--------------------------------------------------
 9 files changed, 394 insertions(+), 366 deletions(-)
 create mode 100644 hw/qdev-core.h
 create mode 100644 hw/qdev-monitor.h
 create mode 100644 hw/qdev-properties.h

diff --git a/hw/irq.h b/hw/irq.h
index e640c10..610e6b7 100644
--- a/hw/irq.h
+++ b/hw/irq.h
@@ -3,6 +3,8 @@
 
 /* Generic IRQ/GPIO pin infrastructure.  */
 
+typedef struct IRQState *qemu_irq;
+
 typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
 
 void qemu_set_irq(qemu_irq irq, int level);
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 332a77d..4bf8808 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -25,6 +25,7 @@
 #include "qemu-timer.h"
 #include "sysemu.h"
 #include "mc146818rtc.h"
+#include "qapi/qapi-visit-core.h"
 
 #ifdef TARGET_I386
 #include "apic.h"
diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c
index b711b6b..5b5d38f 100644
--- a/hw/qdev-addr.c
+++ b/hw/qdev-addr.c
@@ -1,6 +1,7 @@
 #include "qdev.h"
 #include "qdev-addr.h"
 #include "targphys.h"
+#include "qapi/qapi-visit-core.h"
 
 /* --- target physical address --- */
 
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
new file mode 100644
index 0000000..fce9e22
--- /dev/null
+++ b/hw/qdev-core.h
@@ -0,0 +1,238 @@
+#ifndef QDEV_CORE_H
+#define QDEV_CORE_H
+
+#include "qemu-queue.h"
+#include "qemu-option.h"
+#include "qemu/object.h"
+#include "hw/irq.h"
+#include "error.h"
+
+typedef struct Property Property;
+
+typedef struct PropertyInfo PropertyInfo;
+
+typedef struct CompatProperty CompatProperty;
+
+typedef struct BusState BusState;
+
+typedef struct BusClass BusClass;
+
+enum DevState {
+    DEV_STATE_CREATED = 1,
+    DEV_STATE_INITIALIZED,
+};
+
+enum {
+    DEV_NVECTORS_UNSPECIFIED = -1,
+};
+
+#define TYPE_DEVICE "device"
+#define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE)
+#define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE)
+#define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE)
+
+typedef int (*qdev_initfn)(DeviceState *dev);
+typedef int (*qdev_event)(DeviceState *dev);
+typedef void (*qdev_resetfn)(DeviceState *dev);
+
+struct VMStateDescription;
+
+typedef struct DeviceClass {
+    ObjectClass parent_class;
+
+    const char *fw_name;
+    const char *desc;
+    Property *props;
+    int no_user;
+
+    /* callbacks */
+    void (*reset)(DeviceState *dev);
+
+    /* device state */
+    const struct VMStateDescription *vmsd;
+
+    /* Private to qdev / bus.  */
+    qdev_initfn init;
+    qdev_event unplug;
+    qdev_event exit;
+    const char *bus_type;
+} DeviceClass;
+
+/* This structure should not be accessed directly.  We declare it here
+   so that it can be embedded in individual device state structures.  */
+struct DeviceState {
+    Object parent_obj;
+
+    const char *id;
+    enum DevState state;
+    QemuOpts *opts;
+    int hotplugged;
+    BusState *parent_bus;
+    int num_gpio_out;
+    qemu_irq *gpio_out;
+    int num_gpio_in;
+    qemu_irq *gpio_in;
+    QLIST_HEAD(, BusState) child_bus;
+    int num_child_bus;
+    int instance_id_alias;
+    int alias_required_for_version;
+};
+
+#define TYPE_BUS "bus"
+#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS)
+#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS)
+#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS)
+
+struct BusClass {
+    ObjectClass parent_class;
+
+    /* FIXME first arg should be BusState */
+    void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
+    char *(*get_dev_path)(DeviceState *dev);
+    /*
+     * This callback is used to create Open Firmware device path in accordance
+     * with OF spec http://forthworks.com/standards/of1275.pdf. Individual bus
+     * bindings can be found at http://playground.sun.com/1275/bindings/.
+     */
+    char *(*get_fw_dev_path)(DeviceState *dev);
+    int (*reset)(BusState *bus);
+};
+
+typedef struct BusChild {
+    DeviceState *child;
+    int index;
+    QTAILQ_ENTRY(BusChild) sibling;
+} BusChild;
+
+/**
+ * BusState:
+ * @qom_allocated: Indicates whether the object was allocated by QOM.
+ * @glib_allocated: Indicates whether the object was initialized in-place
+ * yet is expected to be freed with g_free().
+ */
+struct BusState {
+    Object obj;
+    DeviceState *parent;
+    const char *name;
+    int allow_hotplug;
+    bool qom_allocated;
+    bool glib_allocated;
+    int max_index;
+    QTAILQ_HEAD(ChildrenHead, BusChild) children;
+    QLIST_ENTRY(BusState) sibling;
+};
+
+struct Property {
+    const char   *name;
+    PropertyInfo *info;
+    int          offset;
+    uint8_t      bitnr;
+    uint8_t      qtype;
+    int64_t      defval;
+};
+
+struct PropertyInfo {
+    const char *name;
+    const char *legacy_name;
+    const char **enum_table;
+    int (*parse)(DeviceState *dev, Property *prop, const char *str);
+    int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
+    ObjectPropertyAccessor *get;
+    ObjectPropertyAccessor *set;
+    ObjectPropertyRelease *release;
+};
+
+typedef struct GlobalProperty {
+    const char *driver;
+    const char *property;
+    const char *value;
+    QTAILQ_ENTRY(GlobalProperty) next;
+} GlobalProperty;
+
+/*** Board API.  This should go away once we have a machine config file.  ***/
+
+DeviceState *qdev_create(BusState *bus, const char *name);
+DeviceState *qdev_try_create(BusState *bus, const char *name);
+int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
+void qdev_init_nofail(DeviceState *dev);
+void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
+                                 int required_for_version);
+void qdev_unplug(DeviceState *dev, Error **errp);
+void qdev_free(DeviceState *dev);
+int qdev_simple_unplug_cb(DeviceState *dev);
+void qdev_machine_creation_done(void);
+bool qdev_machine_modified(void);
+
+qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
+void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
+
+BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
+
+/*** Device API.  ***/
+
+/* Register device properties.  */
+/* GPIO inputs also double as IRQ sinks.  */
+void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
+void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
+
+BusState *qdev_get_parent_bus(DeviceState *dev);
+
+/*** BUS API. ***/
+
+DeviceState *qdev_find_recursive(BusState *bus, const char *id);
+
+/* Returns 0 to walk children, > 0 to skip walk, < 0 to terminate walk. */
+typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
+typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
+
+void qbus_create_inplace(BusState *bus, const char *typename,
+                         DeviceState *parent, const char *name);
+BusState *qbus_create(const char *typename, DeviceState *parent, const char *name);
+/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
+ *         < 0 if either devfn or busfn terminate walk somewhere in cursion,
+ *           0 otherwise. */
+int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
+                       qbus_walkerfn *busfn, void *opaque);
+int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
+                       qbus_walkerfn *busfn, void *opaque);
+void qdev_reset_all(DeviceState *dev);
+void qbus_reset_all_fn(void *opaque);
+
+void qbus_free(BusState *bus);
+
+#define FROM_QBUS(type, dev) DO_UPCAST(type, qbus, dev)
+
+/* This should go away once we get rid of the NULL bus hack */
+BusState *sysbus_get_default(void);
+
+char *qdev_get_fw_dev_path(DeviceState *dev);
+
+/**
+ * @qdev_machine_init
+ *
+ * Initialize platform devices before machine init.  This is a hack until full
+ * support for composition is added.
+ */
+void qdev_machine_init(void);
+
+/**
+ * @device_reset
+ *
+ * Reset a single device (by calling the reset method).
+ */
+void device_reset(DeviceState *dev);
+
+const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);
+
+const char *qdev_fw_name(DeviceState *dev);
+
+Object *qdev_get_machine(void);
+
+/* FIXME: make this a link<> */
+void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
+
+extern int qdev_hotplug;
+
+char *qdev_get_dev_path(DeviceState *dev);
+
+#endif
diff --git a/hw/qdev-monitor.h b/hw/qdev-monitor.h
new file mode 100644
index 0000000..220ceba
--- /dev/null
+++ b/hw/qdev-monitor.h
@@ -0,0 +1,16 @@
+#ifndef QEMU_QDEV_MONITOR_H
+#define QEMU_QDEV_MONITOR_H
+
+#include "qdev-core.h"
+#include "monitor.h"
+
+/*** monitor commands ***/
+
+void do_info_qtree(Monitor *mon);
+void do_info_qdm(Monitor *mon);
+int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int qdev_device_help(QemuOpts *opts);
+DeviceState *qdev_device_add(QemuOpts *opts);
+
+#endif
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 8aca0d4..81d901c 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -4,6 +4,7 @@
 #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)
 {
diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h
new file mode 100644
index 0000000..5b046ab
--- /dev/null
+++ b/hw/qdev-properties.h
@@ -0,0 +1,130 @@
+#ifndef QEMU_QDEV_PROPERTIES_H
+#define QEMU_QDEV_PROPERTIES_H
+
+#include "qdev-core.h"
+
+/*** qdev-properties.c ***/
+
+extern PropertyInfo qdev_prop_bit;
+extern PropertyInfo qdev_prop_uint8;
+extern PropertyInfo qdev_prop_uint16;
+extern PropertyInfo qdev_prop_uint32;
+extern PropertyInfo qdev_prop_int32;
+extern PropertyInfo qdev_prop_uint64;
+extern PropertyInfo qdev_prop_hex8;
+extern PropertyInfo qdev_prop_hex32;
+extern PropertyInfo qdev_prop_hex64;
+extern PropertyInfo qdev_prop_string;
+extern PropertyInfo qdev_prop_chr;
+extern PropertyInfo qdev_prop_ptr;
+extern PropertyInfo qdev_prop_macaddr;
+extern PropertyInfo qdev_prop_losttickpolicy;
+extern PropertyInfo qdev_prop_bios_chs_trans;
+extern PropertyInfo qdev_prop_drive;
+extern PropertyInfo qdev_prop_netdev;
+extern PropertyInfo qdev_prop_vlan;
+extern PropertyInfo qdev_prop_pci_devfn;
+extern PropertyInfo qdev_prop_blocksize;
+extern PropertyInfo qdev_prop_pci_host_devaddr;
+
+#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
+        .name      = (_name),                                    \
+        .info      = &(_prop),                                   \
+        .offset    = offsetof(_state, _field)                    \
+            + type_check(_type,typeof_field(_state, _field)),    \
+        }
+#define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \
+        .name      = (_name),                                           \
+        .info      = &(_prop),                                          \
+        .offset    = offsetof(_state, _field)                           \
+            + type_check(_type,typeof_field(_state, _field)),           \
+        .qtype     = QTYPE_QINT,                                        \
+        .defval    = (_type)_defval,                                    \
+        }
+#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {  \
+        .name      = (_name),                                    \
+        .info      = &(qdev_prop_bit),                           \
+        .bitnr    = (_bit),                                      \
+        .offset    = offsetof(_state, _field)                    \
+            + type_check(uint32_t,typeof_field(_state, _field)), \
+        .qtype     = QTYPE_QBOOL,                                \
+        .defval    = (bool)_defval,                              \
+        }
+
+#define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
+#define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
+#define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
+#define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t)
+#define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
+#define DEFINE_PROP_HEX8(_n, _s, _f, _d)                       \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex8, uint8_t)
+#define DEFINE_PROP_HEX32(_n, _s, _f, _d)                       \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t)
+#define DEFINE_PROP_HEX64(_n, _s, _f, _d)                       \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t)
+#define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d)                   \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
+
+#define DEFINE_PROP_PTR(_n, _s, _f)             \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*)
+#define DEFINE_PROP_CHR(_n, _s, _f)             \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharDriverState*)
+#define DEFINE_PROP_STRING(_n, _s, _f)             \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
+#define DEFINE_PROP_NETDEV(_n, _s, _f)             \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NetClientState*)
+#define DEFINE_PROP_VLAN(_n, _s, _f)             \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NetClientState*)
+#define DEFINE_PROP_DRIVE(_n, _s, _f) \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *)
+#define DEFINE_PROP_MACADDR(_n, _s, _f)         \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
+#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
+                        LostTickPolicy)
+#define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
+#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t)
+#define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
+
+#define DEFINE_PROP_END_OF_LIST()               \
+    {}
+
+/* Set properties between creation and init.  */
+void *qdev_get_prop_ptr(DeviceState *dev, Property *prop);
+int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
+void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value);
+void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value);
+void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
+void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
+void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
+void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
+void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value);
+void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
+void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value);
+int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) QEMU_WARN_UNUSED_RESULT;
+void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value);
+void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
+void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
+/* FIXME: Remove opaque pointer properties.  */
+void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
+
+void qdev_prop_register_global_list(GlobalProperty *props);
+void qdev_prop_set_globals(DeviceState *dev);
+void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
+                                    Property *prop, const char *value);
+
+/**
+ * @qdev_property_add_static - add a @Property to a device referencing a
+ * field in a struct.
+ */
+void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
+
+#endif
diff --git a/hw/qdev.c b/hw/qdev.c
index 9b9aba3..7ddcd24 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -29,6 +29,7 @@
 #include "qdev.h"
 #include "sysemu.h"
 #include "error.h"
+#include "qapi/qapi-visit-core.h"
 
 int qdev_hotplug = 0;
 static bool qdev_hot_added = false;
diff --git a/hw/qdev.h b/hw/qdev.h
index c6ac636..365b8d6 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -1,371 +1,9 @@
 #ifndef QDEV_H
 #define QDEV_H
 
-#include "hw.h"
-#include "qemu-queue.h"
-#include "qemu-char.h"
-#include "qemu-option.h"
-#include "qapi/qapi-visit-core.h"
-#include "qemu/object.h"
-#include "error.h"
-
-typedef struct Property Property;
-
-typedef struct PropertyInfo PropertyInfo;
-
-typedef struct CompatProperty CompatProperty;
-
-typedef struct BusState BusState;
-
-typedef struct BusClass BusClass;
-
-enum DevState {
-    DEV_STATE_CREATED = 1,
-    DEV_STATE_INITIALIZED,
-};
-
-enum {
-    DEV_NVECTORS_UNSPECIFIED = -1,
-};
-
-#define TYPE_DEVICE "device"
-#define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE)
-#define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE)
-#define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE)
-
-typedef int (*qdev_initfn)(DeviceState *dev);
-typedef int (*qdev_event)(DeviceState *dev);
-typedef void (*qdev_resetfn)(DeviceState *dev);
-
-typedef struct DeviceClass {
-    ObjectClass parent_class;
-
-    const char *fw_name;
-    const char *desc;
-    Property *props;
-    int no_user;
-
-    /* callbacks */
-    void (*reset)(DeviceState *dev);
-
-    /* device state */
-    const VMStateDescription *vmsd;
-
-    /* Private to qdev / bus.  */
-    qdev_initfn init;
-    qdev_event unplug;
-    qdev_event exit;
-    const char *bus_type;
-} DeviceClass;
-
-/* This structure should not be accessed directly.  We declare it here
-   so that it can be embedded in individual device state structures.  */
-struct DeviceState {
-    Object parent_obj;
-
-    const char *id;
-    enum DevState state;
-    QemuOpts *opts;
-    int hotplugged;
-    BusState *parent_bus;
-    int num_gpio_out;
-    qemu_irq *gpio_out;
-    int num_gpio_in;
-    qemu_irq *gpio_in;
-    QLIST_HEAD(, BusState) child_bus;
-    int num_child_bus;
-    int instance_id_alias;
-    int alias_required_for_version;
-};
-
-#define TYPE_BUS "bus"
-#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS)
-#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS)
-#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS)
-
-struct BusClass {
-    ObjectClass parent_class;
-
-    /* FIXME first arg should be BusState */
-    void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
-    char *(*get_dev_path)(DeviceState *dev);
-    /*
-     * This callback is used to create Open Firmware device path in accordance
-     * with OF spec http://forthworks.com/standards/of1275.pdf. Individual bus
-     * bindings can be found at http://playground.sun.com/1275/bindings/.
-     */
-    char *(*get_fw_dev_path)(DeviceState *dev);
-    int (*reset)(BusState *bus);
-};
-
-typedef struct BusChild {
-    DeviceState *child;
-    int index;
-    QTAILQ_ENTRY(BusChild) sibling;
-} BusChild;
-
-/**
- * BusState:
- * @qom_allocated: Indicates whether the object was allocated by QOM.
- * @glib_allocated: Indicates whether the object was initialized in-place
- * yet is expected to be freed with g_free().
- */
-struct BusState {
-    Object obj;
-    DeviceState *parent;
-    const char *name;
-    int allow_hotplug;
-    bool qom_allocated;
-    bool glib_allocated;
-    int max_index;
-    QTAILQ_HEAD(ChildrenHead, BusChild) children;
-    QLIST_ENTRY(BusState) sibling;
-};
-
-struct Property {
-    const char   *name;
-    PropertyInfo *info;
-    int          offset;
-    uint8_t      bitnr;
-    uint8_t      qtype;
-    int64_t      defval;
-};
-
-struct PropertyInfo {
-    const char *name;
-    const char *legacy_name;
-    const char **enum_table;
-    int (*parse)(DeviceState *dev, Property *prop, const char *str);
-    int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
-    ObjectPropertyAccessor *get;
-    ObjectPropertyAccessor *set;
-    ObjectPropertyRelease *release;
-};
-
-typedef struct GlobalProperty {
-    const char *driver;
-    const char *property;
-    const char *value;
-    QTAILQ_ENTRY(GlobalProperty) next;
-} GlobalProperty;
-
-/*** Board API.  This should go away once we have a machine config file.  ***/
-
-DeviceState *qdev_create(BusState *bus, const char *name);
-DeviceState *qdev_try_create(BusState *bus, const char *name);
-int qdev_device_help(QemuOpts *opts);
-DeviceState *qdev_device_add(QemuOpts *opts);
-int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
-void qdev_init_nofail(DeviceState *dev);
-void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
-                                 int required_for_version);
-void qdev_unplug(DeviceState *dev, Error **errp);
-void qdev_free(DeviceState *dev);
-int qdev_simple_unplug_cb(DeviceState *dev);
-void qdev_machine_creation_done(void);
-bool qdev_machine_modified(void);
-
-qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
-void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
-
-BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
-
-/*** Device API.  ***/
-
-/* Register device properties.  */
-/* GPIO inputs also double as IRQ sinks.  */
-void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
-void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
-
-BusState *qdev_get_parent_bus(DeviceState *dev);
-
-/*** BUS API. ***/
-
-DeviceState *qdev_find_recursive(BusState *bus, const char *id);
-
-/* Returns 0 to walk children, > 0 to skip walk, < 0 to terminate walk. */
-typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
-typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
-
-void qbus_create_inplace(BusState *bus, const char *typename,
-                         DeviceState *parent, const char *name);
-BusState *qbus_create(const char *typename, DeviceState *parent, const char *name);
-/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
- *         < 0 if either devfn or busfn terminate walk somewhere in cursion,
- *           0 otherwise. */
-int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
-                       qbus_walkerfn *busfn, void *opaque);
-int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
-                       qbus_walkerfn *busfn, void *opaque);
-void qdev_reset_all(DeviceState *dev);
-void qbus_reset_all_fn(void *opaque);
-
-void qbus_free(BusState *bus);
-
-#define FROM_QBUS(type, dev) DO_UPCAST(type, qbus, dev)
-
-/* This should go away once we get rid of the NULL bus hack */
-BusState *sysbus_get_default(void);
-
-/*** monitor commands ***/
-
-void do_info_qtree(Monitor *mon);
-void do_info_qdm(Monitor *mon);
-int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
-/*** qdev-properties.c ***/
-
-extern PropertyInfo qdev_prop_bit;
-extern PropertyInfo qdev_prop_uint8;
-extern PropertyInfo qdev_prop_uint16;
-extern PropertyInfo qdev_prop_uint32;
-extern PropertyInfo qdev_prop_int32;
-extern PropertyInfo qdev_prop_uint64;
-extern PropertyInfo qdev_prop_hex8;
-extern PropertyInfo qdev_prop_hex32;
-extern PropertyInfo qdev_prop_hex64;
-extern PropertyInfo qdev_prop_string;
-extern PropertyInfo qdev_prop_chr;
-extern PropertyInfo qdev_prop_ptr;
-extern PropertyInfo qdev_prop_macaddr;
-extern PropertyInfo qdev_prop_losttickpolicy;
-extern PropertyInfo qdev_prop_bios_chs_trans;
-extern PropertyInfo qdev_prop_drive;
-extern PropertyInfo qdev_prop_netdev;
-extern PropertyInfo qdev_prop_vlan;
-extern PropertyInfo qdev_prop_pci_devfn;
-extern PropertyInfo qdev_prop_blocksize;
-extern PropertyInfo qdev_prop_pci_host_devaddr;
-
-#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
-        .name      = (_name),                                    \
-        .info      = &(_prop),                                   \
-        .offset    = offsetof(_state, _field)                    \
-            + type_check(_type,typeof_field(_state, _field)),    \
-        }
-#define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \
-        .name      = (_name),                                           \
-        .info      = &(_prop),                                          \
-        .offset    = offsetof(_state, _field)                           \
-            + type_check(_type,typeof_field(_state, _field)),           \
-        .qtype     = QTYPE_QINT,                                        \
-        .defval    = (_type)_defval,                                    \
-        }
-#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {  \
-        .name      = (_name),                                    \
-        .info      = &(qdev_prop_bit),                           \
-        .bitnr    = (_bit),                                      \
-        .offset    = offsetof(_state, _field)                    \
-            + type_check(uint32_t,typeof_field(_state, _field)), \
-        .qtype     = QTYPE_QBOOL,                                \
-        .defval    = (bool)_defval,                              \
-        }
-
-#define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
-#define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
-#define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
-#define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t)
-#define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
-#define DEFINE_PROP_HEX8(_n, _s, _f, _d)                       \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex8, uint8_t)
-#define DEFINE_PROP_HEX32(_n, _s, _f, _d)                       \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t)
-#define DEFINE_PROP_HEX64(_n, _s, _f, _d)                       \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t)
-#define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d)                   \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
-
-#define DEFINE_PROP_PTR(_n, _s, _f)             \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*)
-#define DEFINE_PROP_CHR(_n, _s, _f)             \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharDriverState*)
-#define DEFINE_PROP_STRING(_n, _s, _f)             \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
-#define DEFINE_PROP_NETDEV(_n, _s, _f)             \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NetClientState*)
-#define DEFINE_PROP_VLAN(_n, _s, _f)             \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NetClientState*)
-#define DEFINE_PROP_DRIVE(_n, _s, _f) \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *)
-#define DEFINE_PROP_MACADDR(_n, _s, _f)         \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
-#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
-                        LostTickPolicy)
-#define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
-#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t)
-#define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
-
-#define DEFINE_PROP_END_OF_LIST()               \
-    {}
-
-/* Set properties between creation and init.  */
-void *qdev_get_prop_ptr(DeviceState *dev, Property *prop);
-int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
-void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value);
-void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value);
-void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
-void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
-void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
-void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
-void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value);
-void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
-void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value);
-int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) QEMU_WARN_UNUSED_RESULT;
-void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value);
-void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
-void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
-/* FIXME: Remove opaque pointer properties.  */
-void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
-
-void qdev_prop_register_global_list(GlobalProperty *props);
-void qdev_prop_set_globals(DeviceState *dev);
-void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
-                                    Property *prop, const char *value);
-
-char *qdev_get_fw_dev_path(DeviceState *dev);
-
-/**
- * @qdev_property_add_static - add a @Property to a device referencing a
- * field in a struct.
- */
-void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
-
-/**
- * @qdev_machine_init
- *
- * Initialize platform devices before machine init.  This is a hack until full
- * support for composition is added.
- */
-void qdev_machine_init(void);
-
-/**
- * @device_reset
- *
- * Reset a single device (by calling the reset method).
- */
-void device_reset(DeviceState *dev);
-
-const VMStateDescription *qdev_get_vmsd(DeviceState *dev);
-
-const char *qdev_fw_name(DeviceState *dev);
-
-Object *qdev_get_machine(void);
-
-/* FIXME: make this a link<> */
-void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
-
-extern int qdev_hotplug;
-
-char *qdev_get_dev_path(DeviceState *dev);
+#include "hw/hw.h"
+#include "qdev-core.h"
+#include "qdev-properties.h"
+#include "qdev-monitor.h"
 
 #endif
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 02/12] qapi-types.h doesn't really need to include qemu-common.h
  2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 01/12] qdev: split up header so it can be used in cpu.h Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 03/12] qdev: separate core from the code used only by qemu-system-* Eduardo Habkost
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

From: Igor Mammedov <imammedo@redhat.com>

needed to prevent build breakage when CPU becomes a child of DeviceState

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
[ehabkost: include <stdbool.h> too]
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Yes, there is "changelog" data before the "---" mark, but I believe that
in this case they are important to indicate authorship and the scope of
the Signed-off-by lines (so they need to get into the git commit
message).
---
 scripts/qapi-types.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 1b84834..6bc2391 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -273,7 +273,8 @@ fdecl.write(mcgen('''
 #ifndef %(guard)s
 #define %(guard)s
 
-#include "qemu-common.h"
+#include <stdbool.h>
+#include <stdint.h>
 
 ''',
                   guard=guardname(h_file)))
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 03/12] qdev: separate core from the code used only by qemu-system-*
  2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 01/12] qdev: split up header so it can be used in cpu.h Eduardo Habkost
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 02/12] qapi-types.h doesn't really need to include qemu-common.h Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 04/12] qdev: rename qdev.c to qdev-core.c Eduardo Habkost
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

This change should help on two things:
 - Allowing DeviceState to be used by *-user;
 - Writing qdev unit tests without pulling too many dependencies.

Note that there are two parts that depend on code compiled only on
qemu-system-*, but are still inside qdev.c:
 - vmstate handling
 - reset function registration.

Those two parts will be handled later, by moving that code to
qdev-system.c but keeping weak symbols for *-user.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
[imammedo: keep qdev_get_child_bus() in hw/qdev.c]
[imammedo: put qdev_set_nic_properties() in hw/qdev-properties-system.c]
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
[ehabkost: updated the qdev_init_gpio_in() code on qdev-system.c to current
 version]
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Yes, there is "changelog" data before the "---" mark, but I believe that
in this case they are important to indicate authorship and the scope of
the Signed-off-by lines (so they need to get into the git commit
message).
---
 hw/Makefile.objs            |   1 +
 hw/qdev-properties-system.c | 340 ++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev-properties.c        | 320 +----------------------------------------
 hw/qdev-properties.h        |   1 +
 hw/qdev-system.c            |  68 +++++++++
 hw/qdev.c                   |  80 -----------
 6 files changed, 411 insertions(+), 399 deletions(-)
 create mode 100644 hw/qdev-properties-system.c
 create mode 100644 hw/qdev-system.c

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 854faa9..16f23c0 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -181,6 +181,7 @@ 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.o qdev-properties.o qdev-monitor.o
+common-obj-y += qdev-system.o qdev-properties-system.o
 common-obj-$(CONFIG_BRLAPI) += baum.o
 
 # xen backend driver support
diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c
new file mode 100644
index 0000000..e3a21db
--- /dev/null
+++ b/hw/qdev-properties-system.c
@@ -0,0 +1,340 @@
+#include "net.h"
+#include "qdev.h"
+#include "qerror.h"
+#include "blockdev.h"
+#include "hw/block-common.h"
+#include "net/hub.h"
+#include "qapi/qapi-visit-core.h"
+
+static void get_pointer(Object *obj, Visitor *v, Property *prop,
+                        const char *(*print)(void *ptr),
+                        const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    void **ptr = qdev_get_prop_ptr(dev, prop);
+    char *p;
+
+    p = (char *) (*ptr ? print(*ptr) : "");
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_pointer(Object *obj, Visitor *v, Property *prop,
+                        int (*parse)(DeviceState *dev, const char *str,
+                                     void **ptr),
+                        const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Error *local_err = NULL;
+    void **ptr = qdev_get_prop_ptr(dev, prop);
+    char *str;
+    int ret;
+
+    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 (!*str) {
+        g_free(str);
+        *ptr = NULL;
+        return;
+    }
+    ret = parse(dev, str, ptr);
+    error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
+    g_free(str);
+}
+
+/* --- drive --- */
+
+static int parse_drive(DeviceState *dev, const char *str, void **ptr)
+{
+    BlockDriverState *bs;
+
+    bs = bdrv_find(str);
+    if (bs == NULL)
+        return -ENOENT;
+    if (bdrv_attach_dev(bs, dev) < 0)
+        return -EEXIST;
+    *ptr = bs;
+    return 0;
+}
+
+static void release_drive(Object *obj, const char *name, void *opaque)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
+
+    if (*ptr) {
+        bdrv_detach_dev(*ptr, dev);
+        blockdev_auto_del(*ptr);
+    }
+}
+
+static const char *print_drive(void *ptr)
+{
+    return bdrv_get_device_name(ptr);
+}
+
+static void get_drive(Object *obj, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    get_pointer(obj, v, opaque, print_drive, name, errp);
+}
+
+static void set_drive(Object *obj, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    set_pointer(obj, v, opaque, parse_drive, name, errp);
+}
+
+PropertyInfo qdev_prop_drive = {
+    .name  = "drive",
+    .get   = get_drive,
+    .set   = set_drive,
+    .release = release_drive,
+};
+
+/* --- character device --- */
+
+static int parse_chr(DeviceState *dev, const char *str, void **ptr)
+{
+    CharDriverState *chr = qemu_chr_find(str);
+    if (chr == NULL) {
+        return -ENOENT;
+    }
+    if (chr->avail_connections < 1) {
+        return -EEXIST;
+    }
+    *ptr = chr;
+    --chr->avail_connections;
+    return 0;
+}
+
+static void release_chr(Object *obj, const char *name, void *opaque)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
+
+    if (*ptr) {
+        qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
+    }
+}
+
+
+static const char *print_chr(void *ptr)
+{
+    CharDriverState *chr = ptr;
+
+    return chr->label ? chr->label : "";
+}
+
+static void get_chr(Object *obj, Visitor *v, void *opaque,
+                    const char *name, Error **errp)
+{
+    get_pointer(obj, v, opaque, print_chr, name, errp);
+}
+
+static void set_chr(Object *obj, Visitor *v, void *opaque,
+                    const char *name, Error **errp)
+{
+    set_pointer(obj, v, opaque, parse_chr, name, errp);
+}
+
+PropertyInfo qdev_prop_chr = {
+    .name  = "chr",
+    .get   = get_chr,
+    .set   = set_chr,
+    .release = release_chr,
+};
+
+/* --- netdev device --- */
+
+static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
+{
+    NetClientState *netdev = qemu_find_netdev(str);
+
+    if (netdev == NULL) {
+        return -ENOENT;
+    }
+    if (netdev->peer) {
+        return -EEXIST;
+    }
+    *ptr = netdev;
+    return 0;
+}
+
+static const char *print_netdev(void *ptr)
+{
+    NetClientState *netdev = ptr;
+
+    return netdev->name ? netdev->name : "";
+}
+
+static void get_netdev(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    get_pointer(obj, v, opaque, print_netdev, name, errp);
+}
+
+static void set_netdev(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    set_pointer(obj, v, opaque, parse_netdev, name, errp);
+}
+
+PropertyInfo qdev_prop_netdev = {
+    .name  = "netdev",
+    .get   = get_netdev,
+    .set   = set_netdev,
+};
+
+void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
+{
+    qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
+    if (nd->netdev)
+        qdev_prop_set_netdev(dev, "netdev", nd->netdev);
+    if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
+        object_property_find(OBJECT(dev), "vectors", NULL)) {
+        qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
+    }
+    nd->instantiated = 1;
+}
+
+/* --- vlan --- */
+
+static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+    NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
+
+    if (*ptr) {
+        int id;
+        if (!net_hub_id_for_client(*ptr, &id)) {
+            return snprintf(dest, len, "%d", id);
+        }
+    }
+
+    return snprintf(dest, len, "<null>");
+}
+
+static void get_vlan(Object *obj, Visitor *v, void *opaque,
+                     const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
+    int32_t id = -1;
+
+    if (*ptr) {
+        int hub_id;
+        if (!net_hub_id_for_client(*ptr, &hub_id)) {
+            id = hub_id;
+        }
+    }
+
+    visit_type_int32(v, &id, name, errp);
+}
+
+static void set_vlan(Object *obj, Visitor *v, void *opaque,
+                     const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    int32_t id;
+    NetClientState *hubport;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_int32(v, &id, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if (id == -1) {
+        *ptr = NULL;
+        return;
+    }
+
+    hubport = net_hub_port_find(id);
+    if (!hubport) {
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
+                  name, prop->info->name);
+        return;
+    }
+    *ptr = hubport;
+}
+
+PropertyInfo qdev_prop_vlan = {
+    .name  = "vlan",
+    .print = print_vlan,
+    .get   = get_vlan,
+    .set   = set_vlan,
+};
+
+
+int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
+{
+    Error *errp = NULL;
+    const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
+    object_property_set_str(OBJECT(dev), bdrv_name,
+                            name, &errp);
+    if (errp) {
+        qerror_report_err(errp);
+        error_free(errp);
+        return -1;
+    }
+    return 0;
+}
+
+void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
+{
+    if (qdev_prop_set_drive(dev, name, value) < 0) {
+        exit(1);
+    }
+}
+
+void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
+{
+    Error *errp = NULL;
+    assert(!value || value->label);
+    object_property_set_str(OBJECT(dev),
+                            value ? value->label : "", name, &errp);
+    assert_no_error(errp);
+}
+
+void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value)
+{
+    Error *errp = NULL;
+    assert(!value || value->name);
+    object_property_set_str(OBJECT(dev),
+                            value ? value->name : "", name, &errp);
+    assert_no_error(errp);
+}
+
+static int qdev_add_one_global(QemuOpts *opts, void *opaque)
+{
+    GlobalProperty *g;
+
+    g = g_malloc0(sizeof(*g));
+    g->driver   = qemu_opt_get(opts, "driver");
+    g->property = qemu_opt_get(opts, "property");
+    g->value    = qemu_opt_get(opts, "value");
+    qdev_prop_register_global(g);
+    return 0;
+}
+
+void qemu_add_globals(void)
+{
+    qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
+}
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 81d901c..917d986 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -13,49 +13,6 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
     return ptr;
 }
 
-static void get_pointer(Object *obj, Visitor *v, Property *prop,
-                        const char *(*print)(void *ptr),
-                        const char *name, Error **errp)
-{
-    DeviceState *dev = DEVICE(obj);
-    void **ptr = qdev_get_prop_ptr(dev, prop);
-    char *p;
-
-    p = (char *) (*ptr ? print(*ptr) : "");
-    visit_type_str(v, &p, name, errp);
-}
-
-static void set_pointer(Object *obj, Visitor *v, Property *prop,
-                        int (*parse)(DeviceState *dev, const char *str,
-                                     void **ptr),
-                        const char *name, Error **errp)
-{
-    DeviceState *dev = DEVICE(obj);
-    Error *local_err = NULL;
-    void **ptr = qdev_get_prop_ptr(dev, prop);
-    char *str;
-    int ret;
-
-    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 (!*str) {
-        g_free(str);
-        *ptr = NULL;
-        return;
-    }
-    ret = parse(dev, str, ptr);
-    error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
-    g_free(str);
-}
-
 static void get_enum(Object *obj, Visitor *v, void *opaque,
                      const char *name, Error **errp)
 {
@@ -476,227 +433,6 @@ PropertyInfo qdev_prop_string = {
     .set   = set_string,
 };
 
-/* --- drive --- */
-
-static int parse_drive(DeviceState *dev, const char *str, void **ptr)
-{
-    BlockDriverState *bs;
-
-    bs = bdrv_find(str);
-    if (bs == NULL)
-        return -ENOENT;
-    if (bdrv_attach_dev(bs, dev) < 0)
-        return -EEXIST;
-    *ptr = bs;
-    return 0;
-}
-
-static void release_drive(Object *obj, const char *name, void *opaque)
-{
-    DeviceState *dev = DEVICE(obj);
-    Property *prop = opaque;
-    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
-
-    if (*ptr) {
-        bdrv_detach_dev(*ptr, dev);
-        blockdev_auto_del(*ptr);
-    }
-}
-
-static const char *print_drive(void *ptr)
-{
-    return bdrv_get_device_name(ptr);
-}
-
-static void get_drive(Object *obj, Visitor *v, void *opaque,
-                      const char *name, Error **errp)
-{
-    get_pointer(obj, v, opaque, print_drive, name, errp);
-}
-
-static void set_drive(Object *obj, Visitor *v, void *opaque,
-                      const char *name, Error **errp)
-{
-    set_pointer(obj, v, opaque, parse_drive, name, errp);
-}
-
-PropertyInfo qdev_prop_drive = {
-    .name  = "drive",
-    .get   = get_drive,
-    .set   = set_drive,
-    .release = release_drive,
-};
-
-/* --- character device --- */
-
-static int parse_chr(DeviceState *dev, const char *str, void **ptr)
-{
-    CharDriverState *chr = qemu_chr_find(str);
-    if (chr == NULL) {
-        return -ENOENT;
-    }
-    if (chr->avail_connections < 1) {
-        return -EEXIST;
-    }
-    *ptr = chr;
-    --chr->avail_connections;
-    return 0;
-}
-
-static void release_chr(Object *obj, const char *name, void *opaque)
-{
-    DeviceState *dev = DEVICE(obj);
-    Property *prop = opaque;
-    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
-
-    if (*ptr) {
-        qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
-    }
-}
-
-
-static const char *print_chr(void *ptr)
-{
-    CharDriverState *chr = ptr;
-
-    return chr->label ? chr->label : "";
-}
-
-static void get_chr(Object *obj, Visitor *v, void *opaque,
-                    const char *name, Error **errp)
-{
-    get_pointer(obj, v, opaque, print_chr, name, errp);
-}
-
-static void set_chr(Object *obj, Visitor *v, void *opaque,
-                    const char *name, Error **errp)
-{
-    set_pointer(obj, v, opaque, parse_chr, name, errp);
-}
-
-PropertyInfo qdev_prop_chr = {
-    .name  = "chr",
-    .get   = get_chr,
-    .set   = set_chr,
-    .release = release_chr,
-};
-
-/* --- netdev device --- */
-
-static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
-{
-    NetClientState *netdev = qemu_find_netdev(str);
-
-    if (netdev == NULL) {
-        return -ENOENT;
-    }
-    if (netdev->peer) {
-        return -EEXIST;
-    }
-    *ptr = netdev;
-    return 0;
-}
-
-static const char *print_netdev(void *ptr)
-{
-    NetClientState *netdev = ptr;
-
-    return netdev->name ? netdev->name : "";
-}
-
-static void get_netdev(Object *obj, Visitor *v, void *opaque,
-                       const char *name, Error **errp)
-{
-    get_pointer(obj, v, opaque, print_netdev, name, errp);
-}
-
-static void set_netdev(Object *obj, Visitor *v, void *opaque,
-                       const char *name, Error **errp)
-{
-    set_pointer(obj, v, opaque, parse_netdev, name, errp);
-}
-
-PropertyInfo qdev_prop_netdev = {
-    .name  = "netdev",
-    .get   = get_netdev,
-    .set   = set_netdev,
-};
-
-/* --- vlan --- */
-
-static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
-{
-    NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
-
-    if (*ptr) {
-        int id;
-        if (!net_hub_id_for_client(*ptr, &id)) {
-            return snprintf(dest, len, "%d", id);
-        }
-    }
-
-    return snprintf(dest, len, "<null>");
-}
-
-static void get_vlan(Object *obj, Visitor *v, void *opaque,
-                     const char *name, Error **errp)
-{
-    DeviceState *dev = DEVICE(obj);
-    Property *prop = opaque;
-    NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
-    int32_t id = -1;
-
-    if (*ptr) {
-        int hub_id;
-        if (!net_hub_id_for_client(*ptr, &hub_id)) {
-            id = hub_id;
-        }
-    }
-
-    visit_type_int32(v, &id, name, errp);
-}
-
-static void set_vlan(Object *obj, Visitor *v, void *opaque,
-                     const char *name, Error **errp)
-{
-    DeviceState *dev = DEVICE(obj);
-    Property *prop = opaque;
-    NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
-    Error *local_err = NULL;
-    int32_t id;
-    NetClientState *hubport;
-
-    if (dev->state != DEV_STATE_CREATED) {
-        error_set(errp, QERR_PERMISSION_DENIED);
-        return;
-    }
-
-    visit_type_int32(v, &id, name, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-    if (id == -1) {
-        *ptr = NULL;
-        return;
-    }
-
-    hubport = net_hub_port_find(id);
-    if (!hubport) {
-        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
-                  name, prop->info->name);
-        return;
-    }
-    *ptr = hubport;
-}
-
-PropertyInfo qdev_prop_vlan = {
-    .name  = "vlan",
-    .print = print_vlan,
-    .get   = get_vlan,
-    .set   = set_vlan,
-};
-
 /* --- pointer --- */
 
 /* Not a proper property, just for dirty hacks.  TODO Remove it!  */
@@ -1158,44 +894,6 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
     assert_no_error(errp);
 }
 
-int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
-{
-    Error *errp = NULL;
-    const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
-    object_property_set_str(OBJECT(dev), bdrv_name,
-                            name, &errp);
-    if (errp) {
-        qerror_report_err(errp);
-        error_free(errp);
-        return -1;
-    }
-    return 0;
-}
-
-void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
-{
-    if (qdev_prop_set_drive(dev, name, value) < 0) {
-        exit(1);
-    }
-}
-void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
-{
-    Error *errp = NULL;
-    assert(!value || value->label);
-    object_property_set_str(OBJECT(dev),
-                            value ? value->label : "", name, &errp);
-    assert_no_error(errp);
-}
-
-void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value)
-{
-    Error *errp = NULL;
-    assert(!value || value->name);
-    object_property_set_str(OBJECT(dev),
-                            value ? value->name : "", name, &errp);
-    assert_no_error(errp);
-}
-
 void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
 {
     Error *errp = NULL;
@@ -1231,7 +929,7 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
 
 static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
 
-static void qdev_prop_register_global(GlobalProperty *prop)
+void qdev_prop_register_global(GlobalProperty *prop)
 {
     QTAILQ_INSERT_TAIL(&global_props, prop, next);
 }
@@ -1263,19 +961,3 @@ void qdev_prop_set_globals(DeviceState *dev)
     } while (class);
 }
 
-static int qdev_add_one_global(QemuOpts *opts, void *opaque)
-{
-    GlobalProperty *g;
-
-    g = g_malloc0(sizeof(*g));
-    g->driver   = qemu_opt_get(opts, "driver");
-    g->property = qemu_opt_get(opts, "property");
-    g->value    = qemu_opt_get(opts, "value");
-    qdev_prop_register_global(g);
-    return 0;
-}
-
-void qemu_add_globals(void)
-{
-    qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
-}
diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h
index 5b046ab..ddcf774 100644
--- a/hw/qdev-properties.h
+++ b/hw/qdev-properties.h
@@ -116,6 +116,7 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
 /* FIXME: Remove opaque pointer properties.  */
 void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
 
+void qdev_prop_register_global(GlobalProperty *prop);
 void qdev_prop_register_global_list(GlobalProperty *props);
 void qdev_prop_set_globals(DeviceState *dev);
 void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
diff --git a/hw/qdev-system.c b/hw/qdev-system.c
new file mode 100644
index 0000000..93feaee
--- /dev/null
+++ b/hw/qdev-system.c
@@ -0,0 +1,68 @@
+#include "qdev.h"
+
+void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
+{
+    dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler,
+                                        dev, n);
+    dev->num_gpio_in += n;
+}
+
+void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
+{
+    assert(dev->num_gpio_out == 0);
+    dev->num_gpio_out = n;
+    dev->gpio_out = pins;
+}
+
+qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
+{
+    assert(n >= 0 && n < dev->num_gpio_in);
+    return dev->gpio_in[n];
+}
+
+void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
+{
+    assert(n >= 0 && n < dev->num_gpio_out);
+    dev->gpio_out[n] = pin;
+}
+
+/* Create a new device.  This only initializes the device state structure
+   and allows properties to be set.  qdev_init should be called to
+   initialize the actual device emulation.  */
+DeviceState *qdev_create(BusState *bus, const char *name)
+{
+    DeviceState *dev;
+
+    dev = qdev_try_create(bus, name);
+    if (!dev) {
+        if (bus) {
+            hw_error("Unknown device '%s' for bus '%s'\n", name,
+                     object_get_typename(OBJECT(bus)));
+        } else {
+            hw_error("Unknown device '%s' for default sysbus\n", name);
+        }
+    }
+
+    return dev;
+}
+
+DeviceState *qdev_try_create(BusState *bus, const char *type)
+{
+    DeviceState *dev;
+
+    if (object_class_by_name(type) == NULL) {
+        return NULL;
+    }
+    dev = DEVICE(object_new(type));
+    if (!dev) {
+        return NULL;
+    }
+
+    if (!bus) {
+        bus = sysbus_get_default();
+    }
+
+    qdev_set_parent_bus(dev, bus);
+
+    return dev;
+}
diff --git a/hw/qdev.c b/hw/qdev.c
index 7ddcd24..ee19dd5 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -25,7 +25,6 @@
    inherit from a particular bus (e.g. PCI or I2C) rather than
    this API directly.  */
 
-#include "net.h"
 #include "qdev.h"
 #include "sysemu.h"
 #include "error.h"
@@ -99,47 +98,6 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
     bus_add_child(bus, dev);
 }
 
-/* Create a new device.  This only initializes the device state structure
-   and allows properties to be set.  qdev_init should be called to
-   initialize the actual device emulation.  */
-DeviceState *qdev_create(BusState *bus, const char *name)
-{
-    DeviceState *dev;
-
-    dev = qdev_try_create(bus, name);
-    if (!dev) {
-        if (bus) {
-            hw_error("Unknown device '%s' for bus '%s'\n", name,
-                     object_get_typename(OBJECT(bus)));
-        } else {
-            hw_error("Unknown device '%s' for default sysbus\n", name);
-        }
-    }
-
-    return dev;
-}
-
-DeviceState *qdev_try_create(BusState *bus, const char *type)
-{
-    DeviceState *dev;
-
-    if (object_class_by_name(type) == NULL) {
-        return NULL;
-    }
-    dev = DEVICE(object_new(type));
-    if (!dev) {
-        return NULL;
-    }
-
-    if (!bus) {
-        bus = sysbus_get_default();
-    }
-
-    qdev_set_parent_bus(dev, bus);
-
-    return 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.
@@ -284,44 +242,6 @@ BusState *qdev_get_parent_bus(DeviceState *dev)
     return dev->parent_bus;
 }
 
-void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
-{
-    dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler,
-                                        dev, n);
-    dev->num_gpio_in += n;
-}
-
-void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
-{
-    assert(dev->num_gpio_out == 0);
-    dev->num_gpio_out = n;
-    dev->gpio_out = pins;
-}
-
-qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
-{
-    assert(n >= 0 && n < dev->num_gpio_in);
-    return dev->gpio_in[n];
-}
-
-void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
-{
-    assert(n >= 0 && n < dev->num_gpio_out);
-    dev->gpio_out[n] = pin;
-}
-
-void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
-{
-    qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
-    if (nd->netdev)
-        qdev_prop_set_netdev(dev, "netdev", nd->netdev);
-    if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
-        object_property_find(OBJECT(dev), "vectors", NULL)) {
-        qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
-    }
-    nd->instantiated = 1;
-}
-
 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
 {
     BusState *bus;
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 04/12] qdev: rename qdev.c to qdev-core.c
  2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
                   ` (2 preceding siblings ...)
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 03/12] qdev: separate core from the code used only by qemu-system-* Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions Eduardo Habkost
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

Just to make clear that it's the qdev core code, corresponding to
qdev-core.h.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 hw/Makefile.objs |   2 +-
 hw/qdev-core.c   | 716 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.c        | 716 -------------------------------------------------------
 3 files changed, 717 insertions(+), 717 deletions(-)
 create mode 100644 hw/qdev-core.c
 delete mode 100644 hw/qdev.c

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 16f23c0..70f2014 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.o qdev-properties.o qdev-monitor.o
+common-obj-y += qdev-core.o qdev-properties.o 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
new file mode 100644
index 0000000..ee19dd5
--- /dev/null
+++ b/hw/qdev-core.c
@@ -0,0 +1,716 @@
+/*
+ *  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 "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;
+
+const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
+{
+    DeviceClass *dc = DEVICE_GET_CLASS(dev);
+    return dc->vmsd;
+}
+
+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);
+    }
+
+    if (qdev_get_vmsd(dev)) {
+        vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
+                                       dev->instance_id_alias,
+                                       dev->alias_required_for_version);
+    }
+    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 if (bus != sysbus_get_default()) {
+        /* TODO: once all bus devices are qdevified,
+           only reset handler for main_system_bus should be registered here. */
+        qemu_register_reset(qbus_reset_all_fn, 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);
+        }
+        if (qdev_get_vmsd(dev)) {
+            vmstate_unregister(dev, qdev_get_vmsd(dev), 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 {
+        assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
+        qemu_unregister_reset(qbus_reset_all_fn, 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.c b/hw/qdev.c
deleted file mode 100644
index ee19dd5..0000000
--- a/hw/qdev.c
+++ /dev/null
@@ -1,716 +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 "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;
-
-const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
-{
-    DeviceClass *dc = DEVICE_GET_CLASS(dev);
-    return dc->vmsd;
-}
-
-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);
-    }
-
-    if (qdev_get_vmsd(dev)) {
-        vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
-                                       dev->instance_id_alias,
-                                       dev->alias_required_for_version);
-    }
-    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 if (bus != sysbus_get_default()) {
-        /* TODO: once all bus devices are qdevified,
-           only reset handler for main_system_bus should be registered here. */
-        qemu_register_reset(qbus_reset_all_fn, 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);
-        }
-        if (qdev_get_vmsd(dev)) {
-            vmstate_unregister(dev, qdev_get_vmsd(dev), 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 {
-        assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
-        qemu_unregister_reset(qbus_reset_all_fn, 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)
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions
  2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
                   ` (3 preceding siblings ...)
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 04/12] qdev: rename qdev.c to qdev-core.c Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
  2012-10-17 18:06   ` Anthony Liguori
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 06/12] qdev: move vmstate handling to qdev-system.c Eduardo Habkost
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

Those functions will eventually be moved somewhere else, and won't get
included on *-user.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 hw/qdev-core.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/hw/qdev-core.c b/hw/qdev-core.c
index ee19dd5..92c3021 100644
--- a/hw/qdev-core.c
+++ b/hw/qdev-core.c
@@ -40,6 +40,22 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
     return dc->vmsd;
 }
 
+static void qdev_init_vmstate(DeviceState *dev)
+{
+    if (qdev_get_vmsd(dev)) {
+        vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
+                                       dev->instance_id_alias,
+                                       dev->alias_required_for_version);
+    }
+}
+
+static void qdev_finalize_vmstate(DeviceState *dev)
+{
+    if (qdev_get_vmsd(dev)) {
+        vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
+    }
+}
+
 const char *qdev_fw_name(DeviceState *dev)
 {
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
@@ -126,11 +142,7 @@ int qdev_init(DeviceState *dev)
         g_free(name);
     }
 
-    if (qdev_get_vmsd(dev)) {
-        vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
-                                       dev->instance_id_alias,
-                                       dev->alias_required_for_version);
-    }
+    qdev_init_vmstate(dev);
     dev->state = DEV_STATE_INITIALIZED;
     if (dev->hotplugged) {
         device_reset(dev);
@@ -615,9 +627,7 @@ static void device_finalize(Object *obj)
             bus = QLIST_FIRST(&dev->child_bus);
             qbus_free(bus);
         }
-        if (qdev_get_vmsd(dev)) {
-            vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
-        }
+        qdev_finalize_vmstate(dev);
         if (dc->exit) {
             dc->exit(dev);
         }
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 06/12] qdev: move vmstate handling to qdev-system.c
  2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
                   ` (4 preceding siblings ...)
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code Eduardo Habkost
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

Add GCC_WEAK symbols to qdev-core.c, so that qdev-core.o can be used
without qdev-system.o (i.e. by *-user).

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes v1 -> v2:
 - Add GCC_WEAK_DECL to function declarations
---
 hw/qdev-core.c   | 23 +++++++----------------
 hw/qdev-core.h   |  2 ++
 hw/qdev-system.c | 22 ++++++++++++++++++++++
 3 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/hw/qdev-core.c b/hw/qdev-core.c
index 92c3021..af0af52 100644
--- a/hw/qdev-core.c
+++ b/hw/qdev-core.c
@@ -34,26 +34,17 @@ int qdev_hotplug = 0;
 static bool qdev_hot_added = false;
 static bool qdev_hot_removed = false;
 
-const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
-{
-    DeviceClass *dc = DEVICE_GET_CLASS(dev);
-    return dc->vmsd;
-}
-
-static void qdev_init_vmstate(DeviceState *dev)
+/* 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)
 {
-    if (qdev_get_vmsd(dev)) {
-        vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
-                                       dev->instance_id_alias,
-                                       dev->alias_required_for_version);
-    }
 }
 
-static void qdev_finalize_vmstate(DeviceState *dev)
+void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
 {
-    if (qdev_get_vmsd(dev)) {
-        vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
-    }
 }
 
 const char *qdev_fw_name(DeviceState *dev)
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index fce9e22..89c54d5 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -223,6 +223,8 @@ void qdev_machine_init(void);
 void device_reset(DeviceState *dev);
 
 const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);
+void GCC_WEAK_DECL qdev_init_vmstate(DeviceState *dev);
+void GCC_WEAK_DECL qdev_finalize_vmstate(DeviceState *dev);
 
 const char *qdev_fw_name(DeviceState *dev);
 
diff --git a/hw/qdev-system.c b/hw/qdev-system.c
index 93feaee..0c00ab3 100644
--- a/hw/qdev-system.c
+++ b/hw/qdev-system.c
@@ -66,3 +66,25 @@ DeviceState *qdev_try_create(BusState *bus, const char *type)
 
     return dev;
 }
+
+const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
+{
+    DeviceClass *dc = DEVICE_GET_CLASS(dev);
+    return dc->vmsd;
+}
+
+void qdev_init_vmstate(DeviceState *dev)
+{
+    if (qdev_get_vmsd(dev)) {
+        vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
+                                       dev->instance_id_alias,
+                                       dev->alias_required_for_version);
+    }
+}
+
+void qdev_finalize_vmstate(DeviceState *dev)
+{
+    if (qdev_get_vmsd(dev)) {
+        vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
+    }
+}
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code
  2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
                   ` (5 preceding siblings ...)
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 06/12] qdev: move vmstate handling to qdev-system.c Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
  2012-10-17 18:08   ` Anthony Liguori
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 08/12] qdev: move reset register/unregister code to qdev-system.c Eduardo Habkost
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

The reset register/unregister code is specific to qemu-system-*, so
isolate it so it can be moved to qdev-system.c.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 hw/qdev-core.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/hw/qdev-core.c b/hw/qdev-core.c
index af0af52..a105679 100644
--- a/hw/qdev-core.c
+++ b/hw/qdev-core.c
@@ -47,6 +47,21 @@ void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
 {
 }
 
+static void qbus_register_reset(BusState *bus)
+{
+    if (bus != sysbus_get_default()) {
+        /* TODO: once all bus devices are qdevified,
+           only reset handler for main_system_bus should be registered here. */
+        qemu_register_reset(qbus_reset_all_fn, bus);
+    }
+}
+
+static void qbus_unregister_reset(BusState *bus)
+{
+    assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
+    qemu_unregister_reset(qbus_reset_all_fn, bus);
+}
+
 const char *qdev_fw_name(DeviceState *dev)
 {
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
@@ -355,10 +370,8 @@ static void qbus_realize(BusState *bus)
         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 if (bus != sysbus_get_default()) {
-        /* TODO: once all bus devices are qdevified,
-           only reset handler for main_system_bus should be registered here. */
-        qemu_register_reset(qbus_reset_all_fn, bus);
+    } else {
+        qbus_register_reset(bus);
     }
 }
 
@@ -692,8 +705,7 @@ static void qbus_finalize(Object *obj)
         QLIST_REMOVE(bus, sibling);
         bus->parent->num_child_bus--;
     } else {
-        assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
-        qemu_unregister_reset(qbus_reset_all_fn, bus);
+        qbus_unregister_reset(bus);
     }
     g_free((char *)bus->name);
 }
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 08/12] qdev: move reset register/unregister code to qdev-system.c
  2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
                   ` (6 preceding siblings ...)
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 09/12] move qemu_irq typedef out of cpu-common.h Eduardo Habkost
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

Also, add weak symbols that will be used if qdev-system.o is not
compiled in (i.e. on *-user).

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes v1 -> v2:
 - Add GCC_WEAK_DECL to function declarations
---
 hw/qdev-core.c   | 16 +++++++---------
 hw/qdev-core.h   |  3 +++
 hw/qdev-system.c | 15 +++++++++++++++
 3 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/hw/qdev-core.c b/hw/qdev-core.c
index a105679..a756e07 100644
--- a/hw/qdev-core.c
+++ b/hw/qdev-core.c
@@ -47,19 +47,17 @@ void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
 {
 }
 
-static void qbus_register_reset(BusState *bus)
+/* 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)
 {
-    if (bus != sysbus_get_default()) {
-        /* TODO: once all bus devices are qdevified,
-           only reset handler for main_system_bus should be registered here. */
-        qemu_register_reset(qbus_reset_all_fn, bus);
-    }
 }
 
-static void qbus_unregister_reset(BusState *bus)
+void GCC_WEAK qbus_unregister_reset(BusState *bus)
 {
-    assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
-    qemu_unregister_reset(qbus_reset_all_fn, bus);
 }
 
 const char *qdev_fw_name(DeviceState *dev)
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index 89c54d5..e030fff 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -226,6 +226,9 @@ const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);
 void GCC_WEAK_DECL qdev_init_vmstate(DeviceState *dev);
 void GCC_WEAK_DECL qdev_finalize_vmstate(DeviceState *dev);
 
+void GCC_WEAK_DECL qbus_register_reset(BusState *bus);
+void GCC_WEAK_DECL qbus_unregister_reset(BusState *bus);
+
 const char *qdev_fw_name(DeviceState *dev);
 
 Object *qdev_get_machine(void);
diff --git a/hw/qdev-system.c b/hw/qdev-system.c
index 0c00ab3..21074a0 100644
--- a/hw/qdev-system.c
+++ b/hw/qdev-system.c
@@ -88,3 +88,18 @@ void qdev_finalize_vmstate(DeviceState *dev)
         vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
     }
 }
+
+void qbus_register_reset(BusState *bus)
+{
+    if (bus != sysbus_get_default()) {
+        /* TODO: once all bus devices are qdevified,
+           only reset handler for main_system_bus should be registered here. */
+        qemu_register_reset(qbus_reset_all_fn, bus);
+    }
+}
+
+void qbus_unregister_reset(BusState *bus)
+{
+    assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
+    qemu_unregister_reset(qbus_reset_all_fn, bus);
+}
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 09/12] move qemu_irq typedef out of cpu-common.h
  2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
                   ` (7 preceding siblings ...)
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 08/12] qdev: move reset register/unregister code to qdev-system.c Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
  2012-10-17 18:08   ` Anthony Liguori
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 10/12] qdev: use full qdev.h include path on qdev*.c Eduardo Habkost
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

From: Igor Mammedov <imammedo@redhat.com>

it's necessary for making CPU child of DEVICE without
causing circular header deps.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
Changes v2 -> v3:
  imammedo: sysemu.h doesn't need irq.h since 013c2f150
---
 hw/arm-misc.h | 1 +
 hw/bt.h       | 2 ++
 hw/devices.h  | 2 ++
 hw/omap.h     | 1 +
 hw/soc_dma.h  | 1 +
 hw/xen.h      | 1 +
 qemu-common.h | 1 -
 7 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index bdd8fec..b13aa59 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -12,6 +12,7 @@
 #define ARM_MISC_H 1
 
 #include "memory.h"
+#include "hw/irq.h"
 
 /* The CPU is also modeled as an interrupt controller.  */
 #define ARM_PIC_CPU_IRQ 0
diff --git a/hw/bt.h b/hw/bt.h
index a48b8d4..ebf6a37 100644
--- a/hw/bt.h
+++ b/hw/bt.h
@@ -23,6 +23,8 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "hw/irq.h"
+
 /* BD Address */
 typedef struct {
     uint8_t b[6];
diff --git a/hw/devices.h b/hw/devices.h
index 1a55c1e..c60bcab 100644
--- a/hw/devices.h
+++ b/hw/devices.h
@@ -1,6 +1,8 @@
 #ifndef QEMU_DEVICES_H
 #define QEMU_DEVICES_H
 
+#include "hw/irq.h"
+
 /* ??? Not all users of this file can include cpu-common.h.  */
 struct MemoryRegion;
 
diff --git a/hw/omap.h b/hw/omap.h
index 413851b..8b08462 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -19,6 +19,7 @@
 #ifndef hw_omap_h
 #include "memory.h"
 # define hw_omap_h		"omap.h"
+#include "hw/irq.h"
 
 # define OMAP_EMIFS_BASE	0x00000000
 # define OMAP2_Q0_BASE		0x00000000
diff --git a/hw/soc_dma.h b/hw/soc_dma.h
index 904b26c..e386ace 100644
--- a/hw/soc_dma.h
+++ b/hw/soc_dma.h
@@ -19,6 +19,7 @@
  */
 
 #include "memory.h"
+#include "hw/irq.h"
 
 struct soc_dma_s;
 struct soc_dma_ch_s;
diff --git a/hw/xen.h b/hw/xen.h
index d14e92d..e3cca7f 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -8,6 +8,7 @@
  */
 #include <inttypes.h>
 
+#include "hw/irq.h"
 #include "qemu-common.h"
 
 /* xen-machine.c */
diff --git a/qemu-common.h b/qemu-common.h
index b54612b..95585b8 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -286,7 +286,6 @@ typedef struct PCIEPort PCIEPort;
 typedef struct PCIESlot PCIESlot;
 typedef struct MSIMessage MSIMessage;
 typedef struct SerialState SerialState;
-typedef struct IRQState *qemu_irq;
 typedef struct PCMCIACardState PCMCIACardState;
 typedef struct MouseTransformInfo MouseTransformInfo;
 typedef struct uWireSlave uWireSlave;
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 10/12] qdev: use full qdev.h include path on qdev*.c
  2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
                   ` (8 preceding siblings ...)
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 09/12] move qemu_irq typedef out of cpu-common.h Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too Eduardo Habkost
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 12/12] qom: make CPU a child of DeviceState Eduardo Habkost
  11 siblings, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

This way, the files can be moved to the qom/ directory as-is.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 hw/qdev-core.c       | 2 +-
 hw/qdev-properties.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/qdev-core.c b/hw/qdev-core.c
index a756e07..fbb7cb5 100644
--- a/hw/qdev-core.c
+++ b/hw/qdev-core.c
@@ -25,7 +25,7 @@
    inherit from a particular bus (e.g. PCI or I2C) rather than
    this API directly.  */
 
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "sysemu.h"
 #include "error.h"
 #include "qapi/qapi-visit-core.h"
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 917d986..2e82cb9 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -1,5 +1,5 @@
 #include "net.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "qerror.h"
 #include "blockdev.h"
 #include "hw/block-common.h"
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
  2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
                   ` (9 preceding siblings ...)
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 10/12] qdev: use full qdev.h include path on qdev*.c Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
  2012-10-17 18:11   ` Anthony Liguori
  2012-10-22 12:36   ` Igor Mammedov
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 12/12] qom: make CPU a child of DeviceState Eduardo Habkost
  11 siblings, 2 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

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 <ehabkost@redhat.com>
---
 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

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

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [Qemu-devel] [PATCH 12/12] qom: make CPU a child of DeviceState
  2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
                   ` (10 preceding siblings ...)
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too Eduardo Habkost
@ 2012-10-16 19:08 ` Eduardo Habkost
  11 siblings, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-16 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, riku.voipio, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

From: Igor Mammedov <imammedo@redhat.com>

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
[ehabkost: change CPU type declaration to hae TYPE_DEVICE as parent]
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Yes, there is "changelog" data before the "---" mark, but I believe that
in this case they are important to indicate authorship and the scope of
the Signed-off-by lines (so they need to get into the git commit
message).
---
 include/qemu/cpu.h | 6 +++---
 qom/cpu.c          | 3 ++-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h
index ad706a6..ac44057 100644
--- a/include/qemu/cpu.h
+++ b/include/qemu/cpu.h
@@ -20,7 +20,7 @@
 #ifndef QEMU_CPU_H
 #define QEMU_CPU_H
 
-#include "qemu/object.h"
+#include "hw/qdev-core.h"
 #include "qemu-thread.h"
 
 /**
@@ -46,7 +46,7 @@ typedef struct CPUState CPUState;
  */
 typedef struct CPUClass {
     /*< private >*/
-    ObjectClass parent_class;
+    DeviceClass parent_class;
     /*< public >*/
 
     void (*reset)(CPUState *cpu);
@@ -59,7 +59,7 @@ typedef struct CPUClass {
  */
 struct CPUState {
     /*< private >*/
-    Object parent_obj;
+    DeviceState parent_obj;
     /*< public >*/
 
     struct QemuThread *thread;
diff --git a/qom/cpu.c b/qom/cpu.c
index 5b36046..f59db7d 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -20,6 +20,7 @@
 
 #include "qemu/cpu.h"
 #include "qemu-common.h"
+#include "hw/qdev-core.h"
 
 void cpu_reset(CPUState *cpu)
 {
@@ -43,7 +44,7 @@ static void cpu_class_init(ObjectClass *klass, void *data)
 
 static TypeInfo cpu_type_info = {
     .name = TYPE_CPU,
-    .parent = TYPE_OBJECT,
+    .parent = TYPE_DEVICE,
     .instance_size = sizeof(CPUState),
     .abstract = true,
     .class_size = sizeof(CPUClass),
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions Eduardo Habkost
@ 2012-10-17 18:06   ` Anthony Liguori
  0 siblings, 0 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-10-17 18:06 UTC (permalink / raw)
  To: Eduardo Habkost, qemu-devel
  Cc: blauwirbel, Igor Mammedov, riku.voipio, Andreas Färber,
	peter.maydell

Eduardo Habkost <ehabkost@redhat.com> writes:

> Those functions will eventually be moved somewhere else, and won't get
> included on *-user.
>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
>  hw/qdev-core.c | 26 ++++++++++++++++++--------
>  1 file changed, 18 insertions(+), 8 deletions(-)
>
> diff --git a/hw/qdev-core.c b/hw/qdev-core.c
> index ee19dd5..92c3021 100644
> --- a/hw/qdev-core.c
> +++ b/hw/qdev-core.c
> @@ -40,6 +40,22 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
>      return dc->vmsd;
>  }
>  
> +static void qdev_init_vmstate(DeviceState *dev)
> +{
> +    if (qdev_get_vmsd(dev)) {
> +        vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
> +                                       dev->instance_id_alias,
> +                                       dev->alias_required_for_version);
> +    }
> +}
> +
> +static void qdev_finalize_vmstate(DeviceState *dev)
> +{
> +    if (qdev_get_vmsd(dev)) {
> +        vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
> +    }
> +}
> +

You're stubbing at the wrong level.  The place to implement stubs ought
to be vmstate_register/vmstate_unregister.

Regards,

Anthony Liguori

>  const char *qdev_fw_name(DeviceState *dev)
>  {
>      DeviceClass *dc = DEVICE_GET_CLASS(dev);
> @@ -126,11 +142,7 @@ int qdev_init(DeviceState *dev)
>          g_free(name);
>      }
>  
> -    if (qdev_get_vmsd(dev)) {
> -        vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
> -                                       dev->instance_id_alias,
> -                                       dev->alias_required_for_version);
> -    }
> +    qdev_init_vmstate(dev);
>      dev->state = DEV_STATE_INITIALIZED;
>      if (dev->hotplugged) {
>          device_reset(dev);
> @@ -615,9 +627,7 @@ static void device_finalize(Object *obj)
>              bus = QLIST_FIRST(&dev->child_bus);
>              qbus_free(bus);
>          }
> -        if (qdev_get_vmsd(dev)) {
> -            vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
> -        }
> +        qdev_finalize_vmstate(dev);
>          if (dc->exit) {
>              dc->exit(dev);
>          }
> -- 
> 1.7.11.7

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code Eduardo Habkost
@ 2012-10-17 18:08   ` Anthony Liguori
  2012-10-17 18:32     ` Eduardo Habkost
  2012-10-23 14:56     ` Eduardo Habkost
  0 siblings, 2 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-10-17 18:08 UTC (permalink / raw)
  To: Eduardo Habkost, qemu-devel
  Cc: blauwirbel, Igor Mammedov, riku.voipio, Andreas Färber,
	peter.maydell

Eduardo Habkost <ehabkost@redhat.com> writes:

> The reset register/unregister code is specific to qemu-system-*, so
> isolate it so it can be moved to qdev-system.c.
>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
>  hw/qdev-core.c | 24 ++++++++++++++++++------
>  1 file changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/hw/qdev-core.c b/hw/qdev-core.c
> index af0af52..a105679 100644
> --- a/hw/qdev-core.c
> +++ b/hw/qdev-core.c
> @@ -47,6 +47,21 @@ void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
>  {
>  }
>  
> +static void qbus_register_reset(BusState *bus)
> +{
> +    if (bus != sysbus_get_default()) {
> +        /* TODO: once all bus devices are qdevified,
> +           only reset handler for main_system_bus should be registered here. */
> +        qemu_register_reset(qbus_reset_all_fn, bus);
> +    }
> +}
> +
> +static void qbus_unregister_reset(BusState *bus)
> +{
> +    assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> +    qemu_unregister_reset(qbus_reset_all_fn, bus);
> +}
> +

Again, I'd suggest stubbing out qemu_[un]register_reset instead of
trying to cope with it's users.

Regards,

Anthony Liguori

>  const char *qdev_fw_name(DeviceState *dev)
>  {
>      DeviceClass *dc = DEVICE_GET_CLASS(dev);
> @@ -355,10 +370,8 @@ static void qbus_realize(BusState *bus)
>          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 if (bus != sysbus_get_default()) {
> -        /* TODO: once all bus devices are qdevified,
> -           only reset handler for main_system_bus should be registered here. */
> -        qemu_register_reset(qbus_reset_all_fn, bus);
> +    } else {
> +        qbus_register_reset(bus);
>      }
>  }
>  
> @@ -692,8 +705,7 @@ static void qbus_finalize(Object *obj)
>          QLIST_REMOVE(bus, sibling);
>          bus->parent->num_child_bus--;
>      } else {
> -        assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> -        qemu_unregister_reset(qbus_reset_all_fn, bus);
> +        qbus_unregister_reset(bus);
>      }
>      g_free((char *)bus->name);
>  }
> -- 
> 1.7.11.7

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 09/12] move qemu_irq typedef out of cpu-common.h
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 09/12] move qemu_irq typedef out of cpu-common.h Eduardo Habkost
@ 2012-10-17 18:08   ` Anthony Liguori
  0 siblings, 0 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-10-17 18:08 UTC (permalink / raw)
  To: Eduardo Habkost, qemu-devel
  Cc: blauwirbel, Igor Mammedov, riku.voipio, Andreas Färber,
	peter.maydell

Eduardo Habkost <ehabkost@redhat.com> writes:

> From: Igor Mammedov <imammedo@redhat.com>
>
> it's necessary for making CPU child of DEVICE without
> causing circular header deps.
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
> Changes v2 -> v3:
>   imammedo: sysemu.h doesn't need irq.h since 013c2f150
> ---
>  hw/arm-misc.h | 1 +
>  hw/bt.h       | 2 ++
>  hw/devices.h  | 2 ++
>  hw/omap.h     | 1 +
>  hw/soc_dma.h  | 1 +
>  hw/xen.h      | 1 +
>  qemu-common.h | 1 -
>  7 files changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/hw/arm-misc.h b/hw/arm-misc.h
> index bdd8fec..b13aa59 100644
> --- a/hw/arm-misc.h
> +++ b/hw/arm-misc.h
> @@ -12,6 +12,7 @@
>  #define ARM_MISC_H 1
>  
>  #include "memory.h"
> +#include "hw/irq.h"
>  
>  /* The CPU is also modeled as an interrupt controller.  */
>  #define ARM_PIC_CPU_IRQ 0
> diff --git a/hw/bt.h b/hw/bt.h
> index a48b8d4..ebf6a37 100644
> --- a/hw/bt.h
> +++ b/hw/bt.h
> @@ -23,6 +23,8 @@
>   * along with this program; if not, see <http://www.gnu.org/licenses/>.
>   */
>  
> +#include "hw/irq.h"
> +
>  /* BD Address */
>  typedef struct {
>      uint8_t b[6];
> diff --git a/hw/devices.h b/hw/devices.h
> index 1a55c1e..c60bcab 100644
> --- a/hw/devices.h
> +++ b/hw/devices.h
> @@ -1,6 +1,8 @@
>  #ifndef QEMU_DEVICES_H
>  #define QEMU_DEVICES_H
>  
> +#include "hw/irq.h"
> +
>  /* ??? Not all users of this file can include cpu-common.h.  */
>  struct MemoryRegion;
>  
> diff --git a/hw/omap.h b/hw/omap.h
> index 413851b..8b08462 100644
> --- a/hw/omap.h
> +++ b/hw/omap.h
> @@ -19,6 +19,7 @@
>  #ifndef hw_omap_h
>  #include "memory.h"
>  # define hw_omap_h		"omap.h"
> +#include "hw/irq.h"
>  
>  # define OMAP_EMIFS_BASE	0x00000000
>  # define OMAP2_Q0_BASE		0x00000000
> diff --git a/hw/soc_dma.h b/hw/soc_dma.h
> index 904b26c..e386ace 100644
> --- a/hw/soc_dma.h
> +++ b/hw/soc_dma.h
> @@ -19,6 +19,7 @@
>   */
>  
>  #include "memory.h"
> +#include "hw/irq.h"
>  
>  struct soc_dma_s;
>  struct soc_dma_ch_s;
> diff --git a/hw/xen.h b/hw/xen.h
> index d14e92d..e3cca7f 100644
> --- a/hw/xen.h
> +++ b/hw/xen.h
> @@ -8,6 +8,7 @@
>   */
>  #include <inttypes.h>
>  
> +#include "hw/irq.h"
>  #include "qemu-common.h"
>  
>  /* xen-machine.c */
> diff --git a/qemu-common.h b/qemu-common.h
> index b54612b..95585b8 100644
> --- a/qemu-common.h
> +++ b/qemu-common.h
> @@ -286,7 +286,6 @@ typedef struct PCIEPort PCIEPort;
>  typedef struct PCIESlot PCIESlot;
>  typedef struct MSIMessage MSIMessage;
>  typedef struct SerialState SerialState;
> -typedef struct IRQState *qemu_irq;
>  typedef struct PCMCIACardState PCMCIACardState;
>  typedef struct MouseTransformInfo MouseTransformInfo;
>  typedef struct uWireSlave uWireSlave;
> -- 
> 1.7.11.7

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too Eduardo Habkost
@ 2012-10-17 18:11   ` Anthony Liguori
  2012-10-17 18:18     ` Eduardo Habkost
  2012-10-17 19:21     ` Peter Maydell
  2012-10-22 12:36   ` Igor Mammedov
  1 sibling, 2 replies; 26+ messages in thread
From: Anthony Liguori @ 2012-10-17 18:11 UTC (permalink / raw)
  To: Eduardo Habkost, qemu-devel
  Cc: blauwirbel, Igor Mammedov, riku.voipio, Andreas Färber,
	peter.maydell

Eduardo Habkost <ehabkost@redhat.com> 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 <ehabkost@redhat.com>
> ---
>  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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
  2012-10-17 18:11   ` Anthony Liguori
@ 2012-10-17 18:18     ` Eduardo Habkost
  2012-10-17 19:21     ` Peter Maydell
  1 sibling, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-17 18:18 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
	Igor Mammedov, Andreas Färber

On Wed, Oct 17, 2012 at 01:11:41PM -0500, Anthony Liguori wrote:
> Eduardo Habkost <ehabkost@redhat.com> 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 <ehabkost@redhat.com>
> > ---
> >  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

Done.

> 
> 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/.

I don't mind keeping it on hw/, either. I was unsure wheter to move it,
or if it would be OK for *-user to start including files from the hw/
directory.

If nobody complains, I will change the patches to keep the files on
"hw/" on the next version of the series.


> 
> 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

-- 
Eduardo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code
  2012-10-17 18:08   ` Anthony Liguori
@ 2012-10-17 18:32     ` Eduardo Habkost
  2012-10-18 14:51       ` Andreas Färber
  2012-10-23 14:56     ` Eduardo Habkost
  1 sibling, 1 reply; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-17 18:32 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
	Igor Mammedov, Andreas Färber

On Wed, Oct 17, 2012 at 01:08:23PM -0500, Anthony Liguori wrote:
> Eduardo Habkost <ehabkost@redhat.com> writes:
> 
> > The reset register/unregister code is specific to qemu-system-*, so
> > isolate it so it can be moved to qdev-system.c.
> >
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > ---
> >  hw/qdev-core.c | 24 ++++++++++++++++++------
> >  1 file changed, 18 insertions(+), 6 deletions(-)
> >
> > diff --git a/hw/qdev-core.c b/hw/qdev-core.c
> > index af0af52..a105679 100644
> > --- a/hw/qdev-core.c
> > +++ b/hw/qdev-core.c
> > @@ -47,6 +47,21 @@ void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
> >  {
> >  }
> >  
> > +static void qbus_register_reset(BusState *bus)
> > +{
> > +    if (bus != sysbus_get_default()) {
> > +        /* TODO: once all bus devices are qdevified,
> > +           only reset handler for main_system_bus should be registered here. */
> > +        qemu_register_reset(qbus_reset_all_fn, bus);
> > +    }
> > +}
> > +
> > +static void qbus_unregister_reset(BusState *bus)
> > +{
> > +    assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> > +    qemu_unregister_reset(qbus_reset_all_fn, bus);
> > +}
> > +
> 
> Again, I'd suggest stubbing out qemu_[un]register_reset instead of
> trying to cope with it's users.

I agree on the vmstate case (the other patch), but on this case this
would require implementing a sysbus_get_default() stub as well. Skipping
the whole check for sysbus_get_default() on *-user looks like the right
thing to do, to me.

Anyway, I am actually wondering if we really need to include the qbus
code on *-user. Do you think *-user will eventually use BusState objects
too, or it will use only DeviceState objects in the foreseeable future?


> 
> Regards,
> 
> Anthony Liguori
> 
> >  const char *qdev_fw_name(DeviceState *dev)
> >  {
> >      DeviceClass *dc = DEVICE_GET_CLASS(dev);
> > @@ -355,10 +370,8 @@ static void qbus_realize(BusState *bus)
> >          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 if (bus != sysbus_get_default()) {
> > -        /* TODO: once all bus devices are qdevified,
> > -           only reset handler for main_system_bus should be registered here. */
> > -        qemu_register_reset(qbus_reset_all_fn, bus);
> > +    } else {
> > +        qbus_register_reset(bus);
> >      }
> >  }
> >  
> > @@ -692,8 +705,7 @@ static void qbus_finalize(Object *obj)
> >          QLIST_REMOVE(bus, sibling);
> >          bus->parent->num_child_bus--;
> >      } else {
> > -        assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> > -        qemu_unregister_reset(qbus_reset_all_fn, bus);
> > +        qbus_unregister_reset(bus);
> >      }
> >      g_free((char *)bus->name);
> >  }
> > -- 
> > 1.7.11.7

-- 
Eduardo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
  2012-10-17 18:11   ` Anthony Liguori
  2012-10-17 18:18     ` Eduardo Habkost
@ 2012-10-17 19:21     ` Peter Maydell
  2012-10-19 16:59       ` Eduardo Habkost
  1 sibling, 1 reply; 26+ messages in thread
From: Peter Maydell @ 2012-10-17 19:21 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: Eduardo Habkost, riku.voipio, qemu-devel, blauwirbel,
	Igor Mammedov, Andreas Färber

On 17 October 2012 19:11, Anthony Liguori <anthony@codemonkey.ws> wrote:
> 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/.

"-user emulators don't get anything from hw/" is one of those semi
arbitrary but easily definable lines that I'd prefer it if we didn't
break. (Although IIRC there was a directory-renaming proposal recently
which maybe defines some different lines instead.)

-- PMM

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code
  2012-10-17 18:32     ` Eduardo Habkost
@ 2012-10-18 14:51       ` Andreas Färber
  0 siblings, 0 replies; 26+ messages in thread
From: Andreas Färber @ 2012-10-18 14:51 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
	Anthony Liguori, Igor Mammedov

Am 17.10.2012 20:32, schrieb Eduardo Habkost:
> Anyway, I am actually wondering if we really need to include the qbus
> code on *-user. Do you think *-user will eventually use BusState objects
> too, or it will use only DeviceState objects in the foreseeable future?

My understanding is that we want DeviceState as a consistent parent and
its static properties mechanisms. Most of it, including BusState, is
going to be unused. At runtime *-user only needs the TCG fields in
CPUArchState plus the name -> object mapping mechanisms of the day for
initialization.

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
  2012-10-17 19:21     ` Peter Maydell
@ 2012-10-19 16:59       ` Eduardo Habkost
  0 siblings, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-19 16:59 UTC (permalink / raw)
  To: Peter Maydell
  Cc: riku.voipio, qemu-devel, blauwirbel, Anthony Liguori,
	Igor Mammedov, Andreas Färber

On Wed, Oct 17, 2012 at 08:21:17PM +0100, Peter Maydell wrote:
> On 17 October 2012 19:11, Anthony Liguori <anthony@codemonkey.ws> wrote:
> > 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/.
> 
> "-user emulators don't get anything from hw/" is one of those semi
> arbitrary but easily definable lines that I'd prefer it if we didn't
> break. (Although IIRC there was a directory-renaming proposal recently
> which maybe defines some different lines instead.)

I just rememberd another reason for moving qdev-core to qom: the CPU
class itself (that's going to be a child of DeviceState) is already
inside qom. Keeping qdev-core it on hw/ would mean having a qom->hw->qom
dependency chain (qom/cpu.c -> hw/qdev.c -> qom/object.c).

So, by now I am keeping the proposed patch as-is (moving qdev-core to
qom/).

-- 
Eduardo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
  2012-10-16 19:08 ` [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too Eduardo Habkost
  2012-10-17 18:11   ` Anthony Liguori
@ 2012-10-22 12:36   ` Igor Mammedov
  2012-10-22 12:43     ` Eduardo Habkost
  1 sibling, 1 reply; 26+ messages in thread
From: Igor Mammedov @ 2012-10-22 12:36 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
	Anthony Liguori, Andreas Färber

On Tue, 16 Oct 2012 16:08:42 -0300
Eduardo Habkost <ehabkost@redhat.com> wrote:
[...]
> 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
[...]
> +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);
> +}
> +
^^^ git complains "whitespace line at EOF" 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too
  2012-10-22 12:36   ` Igor Mammedov
@ 2012-10-22 12:43     ` Eduardo Habkost
  0 siblings, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-22 12:43 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
	Anthony Liguori, Andreas Färber

On Mon, Oct 22, 2012 at 02:36:01PM +0200, Igor Mammedov wrote:
> On Tue, 16 Oct 2012 16:08:42 -0300
> Eduardo Habkost <ehabkost@redhat.com> wrote:
> [...]
> > 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
> [...]
> > +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);
> > +}
> > +
> ^^^ git complains "whitespace line at EOF" 

I will fix it on the next version. Thanks.

-- 
Eduardo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code
  2012-10-17 18:08   ` Anthony Liguori
  2012-10-17 18:32     ` Eduardo Habkost
@ 2012-10-23 14:56     ` Eduardo Habkost
  2012-10-24  2:43       ` Eduardo Habkost
  1 sibling, 1 reply; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-23 14:56 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
	Igor Mammedov, Andreas Färber

On Wed, Oct 17, 2012 at 01:08:23PM -0500, Anthony Liguori wrote:
> Eduardo Habkost <ehabkost@redhat.com> writes:
> 
> > The reset register/unregister code is specific to qemu-system-*, so
> > isolate it so it can be moved to qdev-system.c.
> >
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > ---
> >  hw/qdev-core.c | 24 ++++++++++++++++++------
> >  1 file changed, 18 insertions(+), 6 deletions(-)
> >
> > diff --git a/hw/qdev-core.c b/hw/qdev-core.c
> > index af0af52..a105679 100644
> > --- a/hw/qdev-core.c
> > +++ b/hw/qdev-core.c
> > @@ -47,6 +47,21 @@ void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
> >  {
> >  }
> >  
> > +static void qbus_register_reset(BusState *bus)
> > +{
> > +    if (bus != sysbus_get_default()) {
> > +        /* TODO: once all bus devices are qdevified,
> > +           only reset handler for main_system_bus should be registered here. */
> > +        qemu_register_reset(qbus_reset_all_fn, bus);
> > +    }
> > +}
> > +
> > +static void qbus_unregister_reset(BusState *bus)
> > +{
> > +    assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> > +    qemu_unregister_reset(qbus_reset_all_fn, bus);
> > +}
> > +
> 
> Again, I'd suggest stubbing out qemu_[un]register_reset instead of
> trying to cope with it's users.

I was going to implement it the way you suggested. But then I noticed
that I _ *-user will need to request the devices to be reset once, too
(even if the only devices available are the CPU objects).

On the next version, I will move the reset-function list from vl.c to
qdev-core.c. Code that uses qdev will need to take care of calling
qemu_devices_reset() eventually (qemu-system does that on vl.c *-user
will need to that somewhere else).

> 
> Regards,
> 
> Anthony Liguori
> 
> >  const char *qdev_fw_name(DeviceState *dev)
> >  {
> >      DeviceClass *dc = DEVICE_GET_CLASS(dev);
> > @@ -355,10 +370,8 @@ static void qbus_realize(BusState *bus)
> >          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 if (bus != sysbus_get_default()) {
> > -        /* TODO: once all bus devices are qdevified,
> > -           only reset handler for main_system_bus should be registered here. */
> > -        qemu_register_reset(qbus_reset_all_fn, bus);
> > +    } else {
> > +        qbus_register_reset(bus);
> >      }
> >  }
> >  
> > @@ -692,8 +705,7 @@ static void qbus_finalize(Object *obj)
> >          QLIST_REMOVE(bus, sibling);
> >          bus->parent->num_child_bus--;
> >      } else {
> > -        assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> > -        qemu_unregister_reset(qbus_reset_all_fn, bus);
> > +        qbus_unregister_reset(bus);
> >      }
> >      g_free((char *)bus->name);
> >  }
> > -- 
> > 1.7.11.7
> 

-- 
Eduardo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code
  2012-10-23 14:56     ` Eduardo Habkost
@ 2012-10-24  2:43       ` Eduardo Habkost
  0 siblings, 0 replies; 26+ messages in thread
From: Eduardo Habkost @ 2012-10-24  2:43 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: peter.maydell, riku.voipio, qemu-devel, blauwirbel,
	Igor Mammedov, Andreas Färber

On Tue, Oct 23, 2012 at 12:56:18PM -0200, Eduardo Habkost wrote:
> On Wed, Oct 17, 2012 at 01:08:23PM -0500, Anthony Liguori wrote:
> > Eduardo Habkost <ehabkost@redhat.com> writes:
> > 
> > > The reset register/unregister code is specific to qemu-system-*, so
> > > isolate it so it can be moved to qdev-system.c.
> > >
> > > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > > ---
> > >  hw/qdev-core.c | 24 ++++++++++++++++++------
> > >  1 file changed, 18 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/hw/qdev-core.c b/hw/qdev-core.c
> > > index af0af52..a105679 100644
> > > --- a/hw/qdev-core.c
> > > +++ b/hw/qdev-core.c
> > > @@ -47,6 +47,21 @@ void GCC_WEAK qdev_finalize_vmstate(DeviceState *dev)
> > >  {
> > >  }
> > >  
> > > +static void qbus_register_reset(BusState *bus)
> > > +{
> > > +    if (bus != sysbus_get_default()) {
> > > +        /* TODO: once all bus devices are qdevified,
> > > +           only reset handler for main_system_bus should be registered here. */
> > > +        qemu_register_reset(qbus_reset_all_fn, bus);
> > > +    }
> > > +}
> > > +
> > > +static void qbus_unregister_reset(BusState *bus)
> > > +{
> > > +    assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> > > +    qemu_unregister_reset(qbus_reset_all_fn, bus);
> > > +}
> > > +
> > 
> > Again, I'd suggest stubbing out qemu_[un]register_reset instead of
> > trying to cope with it's users.
> 
> I was going to implement it the way you suggested. But then I noticed
> that I _ *-user will need to request the devices to be reset once, too
> (even if the only devices available are the CPU objects).
> 
> On the next version, I will move the reset-function list from vl.c to
> qdev-core.c. Code that uses qdev will need to take care of calling
> qemu_devices_reset() eventually (qemu-system does that on vl.c *-user
> will need to that somewhere else).

I don't usually reply to myself to correct typos, but the message above
was almost impossible to parse. So, rewriting it:

  I was going to implement it the way you suggested. But then I noticed
  that *-user will need to request the devices to be reset once, too
  (even if the only devices available are the CPU objects).

  On the next version, I will move the reset-function list from vl.c to
  qdev-core.c. Code that uses qdev will need to take care of calling
  qemu_devices_reset() eventually (qemu-system does that on vl.c, and
  *-user will need to that somewhere else).


> 
> > 
> > Regards,
> > 
> > Anthony Liguori
> > 
> > >  const char *qdev_fw_name(DeviceState *dev)
> > >  {
> > >      DeviceClass *dc = DEVICE_GET_CLASS(dev);
> > > @@ -355,10 +370,8 @@ static void qbus_realize(BusState *bus)
> > >          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 if (bus != sysbus_get_default()) {
> > > -        /* TODO: once all bus devices are qdevified,
> > > -           only reset handler for main_system_bus should be registered here. */
> > > -        qemu_register_reset(qbus_reset_all_fn, bus);
> > > +    } else {
> > > +        qbus_register_reset(bus);
> > >      }
> > >  }
> > >  
> > > @@ -692,8 +705,7 @@ static void qbus_finalize(Object *obj)
> > >          QLIST_REMOVE(bus, sibling);
> > >          bus->parent->num_child_bus--;
> > >      } else {
> > > -        assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
> > > -        qemu_unregister_reset(qbus_reset_all_fn, bus);
> > > +        qbus_unregister_reset(bus);
> > >      }
> > >      g_free((char *)bus->name);
> > >  }
> > > -- 
> > > 1.7.11.7
> > 
> 
> -- 
> Eduardo
> 

-- 
Eduardo

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2012-10-24  2:43 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-16 19:08 [Qemu-devel] [PATCH 00/12] make CPU child of DeviceState and include qdev core in *-user Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 01/12] qdev: split up header so it can be used in cpu.h Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 02/12] qapi-types.h doesn't really need to include qemu-common.h Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 03/12] qdev: separate core from the code used only by qemu-system-* Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 04/12] qdev: rename qdev.c to qdev-core.c Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 05/12] qdev-core: isolate vmstate handling into separate functions Eduardo Habkost
2012-10-17 18:06   ` Anthony Liguori
2012-10-16 19:08 ` [Qemu-devel] [PATCH 06/12] qdev: move vmstate handling to qdev-system.c Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 07/12] qdev-core: isolate reset register/unregister code Eduardo Habkost
2012-10-17 18:08   ` Anthony Liguori
2012-10-17 18:32     ` Eduardo Habkost
2012-10-18 14:51       ` Andreas Färber
2012-10-23 14:56     ` Eduardo Habkost
2012-10-24  2:43       ` Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 08/12] qdev: move reset register/unregister code to qdev-system.c Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 09/12] move qemu_irq typedef out of cpu-common.h Eduardo Habkost
2012-10-17 18:08   ` Anthony Liguori
2012-10-16 19:08 ` [Qemu-devel] [PATCH 10/12] qdev: use full qdev.h include path on qdev*.c Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 11/12] include core qdev code into *-user, too Eduardo Habkost
2012-10-17 18:11   ` Anthony Liguori
2012-10-17 18:18     ` Eduardo Habkost
2012-10-17 19:21     ` Peter Maydell
2012-10-19 16:59       ` Eduardo Habkost
2012-10-22 12:36   ` Igor Mammedov
2012-10-22 12:43     ` Eduardo Habkost
2012-10-16 19:08 ` [Qemu-devel] [PATCH 12/12] qom: make CPU a child of DeviceState Eduardo Habkost

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.