* [Qemu-devel] [PATCH 1/6] qdev: split up header so it can be used in cpu.h
2012-10-03 17:48 [Qemu-devel] [PATCH 0/6] qdev: handle global properties after all instance_init calls Eduardo Habkost
@ 2012-10-03 17:48 ` Eduardo Habkost
2012-10-03 17:48 ` [Qemu-devel] [PATCH 2/6] qapi-types.h doesn't really need to include qemu-common.h Eduardo Habkost
` (5 subsequent siblings)
6 siblings, 0 replies; 17+ messages in thread
From: Eduardo Habkost @ 2012-10-03 17:48 UTC (permalink / raw)
To: qemu-devel; +Cc: Paolo Bonzini, Anthony Liguori, Igor Mammedov
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
[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]
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
hw/irq.h | 2 +
hw/mc146818rtc.c | 1 +
hw/qdev-addr.c | 1 +
hw/qdev-core.h | 240 +++++++++++++++++++++++++++++++++
hw/qdev-monitor.h | 16 +++
hw/qdev-properties.c | 1 +
hw/qdev-properties.h | 130 ++++++++++++++++++
hw/qdev.c | 1 +
hw/qdev.h | 371 +--------------------------------------------------
9 files changed, 396 insertions(+), 367 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 56c55f0..1339a3a 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 d63554f..1718a57 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..ca205fc
--- /dev/null
+++ b/hw/qdev-core.h
@@ -0,0 +1,240 @@
+#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;
+ struct 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;
+};
+
+/*
+ * This callback is used to create Open Firmware device path in accordance with
+ * OF spec http://forthworks.com/standards/of1275.pdf. Indicidual bus bindings
+ * can be found here http://playground.sun.com/1275/bindings/.
+ */
+
+#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);
+ 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);
+bool qdev_exists(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 b5a52ac..d0775f6 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 d699194..365b8d6 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -1,372 +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);
-bool qdev_exists(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.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 2/6] qapi-types.h doesn't really need to include qemu-common.h
2012-10-03 17:48 [Qemu-devel] [PATCH 0/6] qdev: handle global properties after all instance_init calls Eduardo Habkost
2012-10-03 17:48 ` [Qemu-devel] [PATCH 1/6] qdev: split up header so it can be used in cpu.h Eduardo Habkost
@ 2012-10-03 17:48 ` Eduardo Habkost
2012-10-03 17:48 ` [Qemu-devel] [PATCH 3/6] qdev: separate core from the code used only by qemu-system-* Eduardo Habkost
` (4 subsequent siblings)
6 siblings, 0 replies; 17+ messages in thread
From: Eduardo Habkost @ 2012-10-03 17:48 UTC (permalink / raw)
To: qemu-devel; +Cc: Paolo Bonzini, Anthony Liguori, Igor Mammedov
From: Igor Mammedov <imammedo@redhat.com>
needed to prevent build breakage when CPU becomes a child of DeviceState
[ehabkost: include <stdbool.h> too]
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
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 49ef569..6e0e6ba 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.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 3/6] qdev: separate core from the code used only by qemu-system-*
2012-10-03 17:48 [Qemu-devel] [PATCH 0/6] qdev: handle global properties after all instance_init calls Eduardo Habkost
2012-10-03 17:48 ` [Qemu-devel] [PATCH 1/6] qdev: split up header so it can be used in cpu.h Eduardo Habkost
2012-10-03 17:48 ` [Qemu-devel] [PATCH 2/6] qapi-types.h doesn't really need to include qemu-common.h Eduardo Habkost
@ 2012-10-03 17:48 ` Eduardo Habkost
2012-10-03 17:48 ` [Qemu-devel] [PATCH 4/6] tests: unit tests for qdev global-properties handling Eduardo Habkost
` (3 subsequent siblings)
6 siblings, 0 replies; 17+ messages in thread
From: Eduardo Habkost @ 2012-10-03 17:48 UTC (permalink / raw)
To: qemu-devel; +Cc: Paolo Bonzini, Anthony Liguori, Igor Mammedov
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 need to be handled somehow (by being moved outside
of qdev-core, or compiled out, or by adding equivalent implementations
to *-user), to allow the qdev core to be used by *-user.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
hw/Makefile.objs | 1 +
hw/qdev-properties-system.c | 329 ++++++++++++++++++++++++++++++++++++++++++++
hw/qdev-properties.c | 320 +-----------------------------------------
hw/qdev-properties.h | 1 +
hw/qdev-system.c | 93 +++++++++++++
hw/qdev.c | 92 -------------
6 files changed, 425 insertions(+), 411 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 ecdbe44..030cb2d 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -179,6 +179,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..c42e656
--- /dev/null
+++ b/hw/qdev-properties-system.c
@@ -0,0 +1,329 @@
+#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,
+};
+
+/* --- 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..4891d2f
--- /dev/null
+++ b/hw/qdev-system.c
@@ -0,0 +1,93 @@
+#include "net.h"
+#include "qdev.h"
+
+void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
+{
+ assert(dev->num_gpio_in == 0);
+ dev->num_gpio_in = n;
+ dev->gpio_in = qemu_allocate_irqs(handler, dev, 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;
+
+ QLIST_FOREACH(bus, &dev->child_bus, sibling) {
+ if (strcmp(name, bus->name) == 0) {
+ return bus;
+ }
+ }
+ return NULL;
+}
+
+/* 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 d0775f6..9e73655 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"
@@ -105,47 +104,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.
@@ -290,56 +248,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)
-{
- assert(dev->num_gpio_in == 0);
- dev->num_gpio_in = n;
- dev->gpio_in = qemu_allocate_irqs(handler, dev, 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;
-
- 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)
{
--
1.7.11.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 4/6] tests: unit tests for qdev global-properties handling
2012-10-03 17:48 [Qemu-devel] [PATCH 0/6] qdev: handle global properties after all instance_init calls Eduardo Habkost
` (2 preceding siblings ...)
2012-10-03 17:48 ` [Qemu-devel] [PATCH 3/6] qdev: separate core from the code used only by qemu-system-* Eduardo Habkost
@ 2012-10-03 17:48 ` Eduardo Habkost
2012-10-03 17:48 ` [Qemu-devel] [PATCH 5/6] qom: introduce post_init() function Eduardo Habkost
` (2 subsequent siblings)
6 siblings, 0 replies; 17+ messages in thread
From: Eduardo Habkost @ 2012-10-03 17:48 UTC (permalink / raw)
To: qemu-devel; +Cc: Paolo Bonzini, Anthony Liguori, Igor Mammedov
This tests the qdev global-properties handling code.
A fake-qdev.c module was added with some stub functions, to keep
dependencies under control.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
tests/Makefile | 6 +++
tests/fake-qdev.c | 52 ++++++++++++++++++++
tests/test-qdev-global-prop.c | 109 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 167 insertions(+)
create mode 100644 tests/fake-qdev.c
create mode 100644 tests/test-qdev-global-prop.c
diff --git a/tests/Makefile b/tests/Makefile
index 26a67ce..2433be7 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -15,6 +15,7 @@ check-unit-y += tests/test-string-output-visitor$(EXESUF)
check-unit-y += tests/test-coroutine$(EXESUF)
check-unit-y += tests/test-visitor-serialization$(EXESUF)
check-unit-y += tests/test-iov$(EXESUF)
+check-unit-y += tests/test-qdev-global-prop$(EXESUF)
check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
@@ -50,6 +51,11 @@ tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o $(tools-obj-y)
tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) $(tools-obj-y)
tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y)
tests/test-iov$(EXESUF): tests/test-iov.o iov.o
+tests/test-qdev-global-prop$(EXESUF): tests/test-qdev-global-prop.o \
+ hw/qdev.o hw/qdev-properties.o \
+ $(test-qapi-obj-y) $(qom-obj-y) \
+ qemu-option.o \
+ tests/fake-qdev.o
tests/test-qapi-types.c tests/test-qapi-types.h :\
$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
diff --git a/tests/fake-qdev.c b/tests/fake-qdev.c
new file mode 100644
index 0000000..bdbbc6e
--- /dev/null
+++ b/tests/fake-qdev.c
@@ -0,0 +1,52 @@
+/* Fake implementations of functions that are not essential for qdev testing,
+ * but are required by the qdev core code.
+ *
+ * Copyright (c) 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/qdev-core.h"
+#include "hw/hw.h"
+
+BusState *sysbus_get_default(void)
+{
+ return NULL;
+}
+
+void qemu_register_reset(QEMUResetHandler *func, void *opaque)
+{
+}
+
+void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
+{
+}
+
+int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
+ const VMStateDescription *vmsd,
+ void *base, int alias_id,
+ int required_for_version)
+{
+ return 0;
+}
+
+void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
+ void *opaque)
+{
+}
diff --git a/tests/test-qdev-global-prop.c b/tests/test-qdev-global-prop.c
new file mode 100644
index 0000000..4c50156
--- /dev/null
+++ b/tests/test-qdev-global-prop.c
@@ -0,0 +1,109 @@
+/*
+ * Test code for qdev global-properties handling
+ *
+ * Copyright (c) 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <glib.h>
+#include <stdint.h>
+
+#include "hw/qdev.h"
+
+
+#define TYPE_STATIC_PROPS "static_prop_type"
+#define STATIC_TYPE(obj) \
+ OBJECT_CHECK(MyType, (obj), TYPE_STATIC_PROPS)
+
+#define PROP_DEFAULT 100
+
+typedef struct MyType {
+ DeviceState parent_obj;
+
+ uint32_t prop1, prop2, prop3;
+} MyType;
+
+static Property static_props[] = {
+ DEFINE_PROP_UINT32("prop1", MyType, prop1, PROP_DEFAULT),
+ DEFINE_PROP_UINT32("prop2", MyType, prop2, PROP_DEFAULT),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static int mytype_init(DeviceState *dev)
+{
+ return 0;
+}
+
+static void static_prop_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->props = static_props;
+ dc->init = mytype_init;
+}
+
+static TypeInfo static_prop_type = {
+ .name = TYPE_STATIC_PROPS,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(MyType),
+ .class_init = static_prop_class_init,
+};
+
+/* Test simple static property setting to default value */
+static void test_static_prop(void)
+{
+ MyType *mt;
+
+ mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS));
+ qdev_init_nofail(DEVICE(mt));
+
+ g_assert_cmpuint(mt->prop1, ==, PROP_DEFAULT);
+}
+
+/* Test setting of static property using global properties */
+static void test_static_globalprop(void)
+{
+ MyType *mt;
+ GlobalProperty props[] = {
+ {TYPE_STATIC_PROPS, "prop1", "200"},
+ {}
+ };
+ qdev_prop_register_global_list(props);
+
+ mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS));
+ qdev_init_nofail(DEVICE(mt));
+
+ g_assert_cmpuint(mt->prop1, ==, 200);
+ g_assert_cmpuint(mt->prop2, ==, PROP_DEFAULT);
+}
+
+int main(int argc, char **argv)
+{
+ module_call_init(MODULE_INIT_QOM);
+ type_register_static(&static_prop_type);
+
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/qdev/properties/static/default", test_static_prop);
+ g_test_add_func("/qdev/properties/static/global", test_static_globalprop);
+
+ g_test_run();
+
+ return 0;
+}
--
1.7.11.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 5/6] qom: introduce post_init() function
2012-10-03 17:48 [Qemu-devel] [PATCH 0/6] qdev: handle global properties after all instance_init calls Eduardo Habkost
` (3 preceding siblings ...)
2012-10-03 17:48 ` [Qemu-devel] [PATCH 4/6] tests: unit tests for qdev global-properties handling Eduardo Habkost
@ 2012-10-03 17:48 ` Eduardo Habkost
2012-10-03 17:48 ` [Qemu-devel] [PATCH 6/6] qdev: set globals on " Eduardo Habkost
2013-07-09 14:32 ` [Qemu-devel] [PATCH 0/6] qdev: handle global properties after all instance_init calls Andreas Färber
6 siblings, 0 replies; 17+ messages in thread
From: Eduardo Habkost @ 2012-10-03 17:48 UTC (permalink / raw)
To: qemu-devel; +Cc: Paolo Bonzini, Anthony Liguori, Igor Mammedov
This will allow classes to specify a function to be called after all
instance_init() functions were called.
This will be used by DeviceState to call qdev_prop_set_globals() at the
right moment.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
include/qemu/object.h | 3 +++
qom/object.c | 14 ++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/include/qemu/object.h b/include/qemu/object.h
index cc75fee..ca7e38b 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -276,6 +276,8 @@ struct Object
* @instance_init: This function is called to initialize an object. The parent
* class will have already been initialized so the type is only responsible
* for initializing its own members.
+ * @instance_post_init: This function is called to finish initialization of
+ * an object, after all instance_init functions were called.
* @instance_finalize: This function is called during object destruction. This
* is called before the parent @instance_finalize function has been called.
* An object should only free the members that are unique to its type in this
@@ -311,6 +313,7 @@ struct TypeInfo
size_t instance_size;
void (*instance_init)(Object *obj);
+ void (*instance_post_init)(Object *obj);
void (*instance_finalize)(Object *obj);
bool abstract;
diff --git a/qom/object.c b/qom/object.c
index e3e9242..eed5e05 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -49,6 +49,7 @@ struct TypeImpl
void *class_data;
void (*instance_init)(Object *obj);
+ void (*instance_post_init)(Object *obj);
void (*instance_finalize)(Object *obj);
bool abstract;
@@ -109,6 +110,7 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
ti->class_data = info->class_data;
ti->instance_init = info->instance_init;
+ ti->instance_post_init = info->instance_post_init;
ti->instance_finalize = info->instance_finalize;
ti->abstract = info->abstract;
@@ -295,6 +297,17 @@ static void object_init_with_type(Object *obj, TypeImpl *ti)
}
}
+static void object_post_init_with_type(Object *obj, TypeImpl *ti)
+{
+ if (ti->instance_post_init) {
+ ti->instance_post_init(obj);
+ }
+
+ if (type_has_parent(ti)) {
+ object_post_init_with_type(obj, type_get_parent(ti));
+ }
+}
+
void object_initialize_with_type(void *data, TypeImpl *type)
{
Object *obj = data;
@@ -309,6 +322,7 @@ void object_initialize_with_type(void *data, TypeImpl *type)
obj->class = type->class;
QTAILQ_INIT(&obj->properties);
object_init_with_type(obj, type);
+ object_post_init_with_type(obj, type);
}
void object_initialize(void *data, const char *typename)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 6/6] qdev: set globals on post_init() function
2012-10-03 17:48 [Qemu-devel] [PATCH 0/6] qdev: handle global properties after all instance_init calls Eduardo Habkost
` (4 preceding siblings ...)
2012-10-03 17:48 ` [Qemu-devel] [PATCH 5/6] qom: introduce post_init() function Eduardo Habkost
@ 2012-10-03 17:48 ` Eduardo Habkost
2013-07-09 14:32 ` [Qemu-devel] [PATCH 0/6] qdev: handle global properties after all instance_init calls Andreas Färber
6 siblings, 0 replies; 17+ messages in thread
From: Eduardo Habkost @ 2012-10-03 17:48 UTC (permalink / raw)
To: qemu-devel; +Cc: Paolo Bonzini, Anthony Liguori, Igor Mammedov
This way, properties registerd in the instance_init() function of
children classes will be handled properly by qdev_prop_set_globals(),
too.
Includes a new unit test for the new functionality.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
hw/qdev.c | 9 ++-
tests/Makefile | 4 +-
tests/test-qdev-global-prop.c | 109 -------------------------
tests/test-qdev-global-props.c | 178 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 187 insertions(+), 113 deletions(-)
delete mode 100644 tests/test-qdev-global-prop.c
create mode 100644 tests/test-qdev-global-props.c
diff --git a/hw/qdev.c b/hw/qdev.c
index 9e73655..68c5ccb 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -591,12 +591,16 @@ static void device_initfn(Object *obj)
}
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);
}
+static void device_post_init(Object *obj)
+{
+ DeviceState *dev = DEVICE(obj);
+ qdev_prop_set_globals(dev);
+}
+
/* Unlink device from bus and free the structure. */
static void device_finalize(Object *obj)
{
@@ -659,6 +663,7 @@ static TypeInfo device_type_info = {
.parent = TYPE_OBJECT,
.instance_size = sizeof(DeviceState),
.instance_init = device_initfn,
+ .instance_post_init = device_post_init,
.instance_finalize = device_finalize,
.class_base_init = device_class_base_init,
.abstract = true,
diff --git a/tests/Makefile b/tests/Makefile
index 2433be7..9f86162 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -15,7 +15,7 @@ check-unit-y += tests/test-string-output-visitor$(EXESUF)
check-unit-y += tests/test-coroutine$(EXESUF)
check-unit-y += tests/test-visitor-serialization$(EXESUF)
check-unit-y += tests/test-iov$(EXESUF)
-check-unit-y += tests/test-qdev-global-prop$(EXESUF)
+check-unit-y += tests/test-qdev-global-props$(EXESUF)
check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
@@ -51,7 +51,7 @@ tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o $(tools-obj-y)
tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) $(tools-obj-y)
tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y)
tests/test-iov$(EXESUF): tests/test-iov.o iov.o
-tests/test-qdev-global-prop$(EXESUF): tests/test-qdev-global-prop.o \
+tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
hw/qdev.o hw/qdev-properties.o \
$(test-qapi-obj-y) $(qom-obj-y) \
qemu-option.o \
diff --git a/tests/test-qdev-global-prop.c b/tests/test-qdev-global-prop.c
deleted file mode 100644
index 4c50156..0000000
--- a/tests/test-qdev-global-prop.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Test code for qdev global-properties handling
- *
- * Copyright (c) 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include <glib.h>
-#include <stdint.h>
-
-#include "hw/qdev.h"
-
-
-#define TYPE_STATIC_PROPS "static_prop_type"
-#define STATIC_TYPE(obj) \
- OBJECT_CHECK(MyType, (obj), TYPE_STATIC_PROPS)
-
-#define PROP_DEFAULT 100
-
-typedef struct MyType {
- DeviceState parent_obj;
-
- uint32_t prop1, prop2, prop3;
-} MyType;
-
-static Property static_props[] = {
- DEFINE_PROP_UINT32("prop1", MyType, prop1, PROP_DEFAULT),
- DEFINE_PROP_UINT32("prop2", MyType, prop2, PROP_DEFAULT),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static int mytype_init(DeviceState *dev)
-{
- return 0;
-}
-
-static void static_prop_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- dc->props = static_props;
- dc->init = mytype_init;
-}
-
-static TypeInfo static_prop_type = {
- .name = TYPE_STATIC_PROPS,
- .parent = TYPE_DEVICE,
- .instance_size = sizeof(MyType),
- .class_init = static_prop_class_init,
-};
-
-/* Test simple static property setting to default value */
-static void test_static_prop(void)
-{
- MyType *mt;
-
- mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS));
- qdev_init_nofail(DEVICE(mt));
-
- g_assert_cmpuint(mt->prop1, ==, PROP_DEFAULT);
-}
-
-/* Test setting of static property using global properties */
-static void test_static_globalprop(void)
-{
- MyType *mt;
- GlobalProperty props[] = {
- {TYPE_STATIC_PROPS, "prop1", "200"},
- {}
- };
- qdev_prop_register_global_list(props);
-
- mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS));
- qdev_init_nofail(DEVICE(mt));
-
- g_assert_cmpuint(mt->prop1, ==, 200);
- g_assert_cmpuint(mt->prop2, ==, PROP_DEFAULT);
-}
-
-int main(int argc, char **argv)
-{
- module_call_init(MODULE_INIT_QOM);
- type_register_static(&static_prop_type);
-
- g_test_init(&argc, &argv, NULL);
-
- g_test_add_func("/qdev/properties/static/default", test_static_prop);
- g_test_add_func("/qdev/properties/static/global", test_static_globalprop);
-
- g_test_run();
-
- return 0;
-}
diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c
new file mode 100644
index 0000000..29f602c
--- /dev/null
+++ b/tests/test-qdev-global-props.c
@@ -0,0 +1,178 @@
+/*
+ * Test code for qdev global-properties handling
+ *
+ * Copyright (c) 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <glib.h>
+#include <stdint.h>
+
+#include "hw/qdev.h"
+#include "qemu/object.h"
+#include "qapi/qapi-visit-core.h"
+
+
+#define TYPE_STATIC_PROPS "static_prop_type"
+#define STATIC_TYPE(obj) \
+ OBJECT_CHECK(MyType, (obj), TYPE_STATIC_PROPS)
+
+#define PROP_DEFAULT 100
+
+typedef struct MyType {
+ DeviceState parent_obj;
+
+ uint32_t prop1, prop2, prop3;
+} MyType;
+
+static Property static_props[] = {
+ DEFINE_PROP_UINT32("prop1", MyType, prop1, PROP_DEFAULT),
+ DEFINE_PROP_UINT32("prop2", MyType, prop2, PROP_DEFAULT),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static int mytype_init(DeviceState *dev)
+{
+ return 0;
+}
+
+static void static_prop_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->props = static_props;
+ dc->init = mytype_init;
+}
+
+static TypeInfo static_prop_type = {
+ .name = TYPE_STATIC_PROPS,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(MyType),
+ .class_init = static_prop_class_init,
+};
+
+/* Test simple static property setting to default value */
+static void test_static_prop(void)
+{
+ MyType *mt;
+
+ mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS));
+ qdev_init_nofail(DEVICE(mt));
+
+ g_assert_cmpuint(mt->prop1, ==, PROP_DEFAULT);
+}
+
+/* Test setting of static property using global properties */
+static void test_static_globalprop(void)
+{
+ MyType *mt;
+ static GlobalProperty props[] = {
+ {TYPE_STATIC_PROPS, "prop1", "200"},
+ {}
+ };
+ qdev_prop_register_global_list(props);
+
+ mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS));
+ qdev_init_nofail(DEVICE(mt));
+
+ g_assert_cmpuint(mt->prop1, ==, 200);
+ g_assert_cmpuint(mt->prop2, ==, PROP_DEFAULT);
+}
+
+#define TYPE_DYNAMIC_PROPS "dynamic_prop_type"
+#define DYNAMIC_TYPE(obj) \
+ OBJECT_CHECK(MyType, (obj), TYPE_DYNAMIC_PROPS)
+
+static void prop1_acessor(Object *obj,
+ struct Visitor *v,
+ void *opaque,
+ const char *name,
+ struct Error **errp)
+{
+ MyType *mt = DYNAMIC_TYPE(obj);
+ visit_type_uint32(v, &mt->prop1, name, errp);
+}
+
+static void prop2_acessor(Object *obj,
+ struct Visitor *v,
+ void *opaque,
+ const char *name,
+ struct Error **errp)
+{
+ MyType *mt = DYNAMIC_TYPE(obj);
+ visit_type_uint32(v, &mt->prop2, name, errp);
+}
+
+static void dynamic_instance_init(Object *obj)
+{
+ object_property_add(obj, "prop1", "uint32", prop1_acessor, prop1_acessor,
+ NULL, NULL, NULL);
+ object_property_add(obj, "prop2", "uint32", prop2_acessor, prop2_acessor,
+ NULL, NULL, NULL);
+}
+
+static void dynamic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->init = mytype_init;
+}
+
+
+static TypeInfo dynamic_prop_type = {
+ .name = TYPE_DYNAMIC_PROPS,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(MyType),
+ .instance_init = dynamic_instance_init,
+ .class_init = dynamic_class_init,
+};
+
+/* Test setting of static property using global properties */
+static void test_dynamic_globalprop(void)
+{
+ MyType *mt;
+ static GlobalProperty props[] = {
+ {TYPE_DYNAMIC_PROPS, "prop1", "101"},
+ {TYPE_DYNAMIC_PROPS, "prop2", "102"},
+ {}
+ };
+ qdev_prop_register_global_list(props);
+
+ mt = DYNAMIC_TYPE(object_new(TYPE_DYNAMIC_PROPS));
+ qdev_init_nofail(DEVICE(mt));
+
+ g_assert_cmpuint(mt->prop1, ==, 101);
+ g_assert_cmpuint(mt->prop2, ==, 102);
+}
+
+int main(int argc, char **argv)
+{
+ module_call_init(MODULE_INIT_QOM);
+ type_register_static(&static_prop_type);
+ type_register_static(&dynamic_prop_type);
+
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/qdev/properties/static/default", test_static_prop);
+ g_test_add_func("/qdev/properties/static/global", test_static_globalprop);
+ g_test_add_func("/qdev/properties/dynamic/global", test_dynamic_globalprop);
+
+ g_test_run();
+
+ return 0;
+}
--
1.7.11.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 0/6] qdev: handle global properties after all instance_init calls
2012-10-03 17:48 [Qemu-devel] [PATCH 0/6] qdev: handle global properties after all instance_init calls Eduardo Habkost
` (5 preceding siblings ...)
2012-10-03 17:48 ` [Qemu-devel] [PATCH 6/6] qdev: set globals on " Eduardo Habkost
@ 2013-07-09 14:32 ` Andreas Färber
2013-07-10 20:08 ` [Qemu-devel] [RFC 0/3 v2] " Eduardo Habkost
6 siblings, 1 reply; 17+ messages in thread
From: Andreas Färber @ 2013-07-09 14:32 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Paolo Bonzini, Igor Mammedov, Eduardo Habkost, qemu-devel
Ping for KVM call discussion
Am 03.10.2012 19:48, schrieb Eduardo Habkost:
> Summary:
> - Object properties are registered by the classes' instance_init()
> functions
> - qdev_prop_set_globals() needs all properties to be registered before being
> called.
> - Hence, qdev_prop_set_globals() can't be called from device_initfn().
>
> Reference:
> http://article.gmane.org/gmane.comp.emulators.qemu/173753
>
> This series is a larger than the single-patch suggestion sent by Igor (URL
> above), just because I wanted to include a unit test for the new code. To do
> that, I pulled the qdev-split code sent previously to the list, so a qdev unit
> test could be written without pulling too many dependencies.
>
> Patches 1-3 are just code movement, patch 3 adds the qdev unit test, patches 5-6
> finally introduce post_init(), and move the qdev_prop_set_globals() call to
> post_init().
>
> Anthony Liguori (1):
> qdev: split up header so it can be used in cpu.h
>
> Eduardo Habkost (4):
> qdev: separate core from the code used only by qemu-system-*
> tests: unit tests for qdev global-properties handling
> qom: introduce post_init() function
> qdev: set globals on post_init() function
>
> Igor Mammedov (1):
> qapi-types.h doesn't really need to include qemu-common.h
>
> hw/Makefile.objs | 1 +
> hw/irq.h | 2 +
> hw/mc146818rtc.c | 1 +
> hw/qdev-addr.c | 1 +
> hw/qdev-core.h | 240 ++++++++++++++++++++++++++
> hw/qdev-monitor.h | 16 ++
> hw/qdev-properties-system.c | 329 ++++++++++++++++++++++++++++++++++++
> hw/qdev-properties.c | 321 +----------------------------------
> hw/qdev-properties.h | 131 +++++++++++++++
> hw/qdev-system.c | 93 +++++++++++
> hw/qdev.c | 102 +----------
> hw/qdev.h | 371 +----------------------------------------
> include/qemu/object.h | 3 +
> qom/object.c | 14 ++
> scripts/qapi-types.py | 3 +-
> tests/Makefile | 6 +
> tests/fake-qdev.c | 52 ++++++
> tests/test-qdev-global-props.c | 178 ++++++++++++++++++++
> 18 files changed, 1083 insertions(+), 781 deletions(-)
> create mode 100644 hw/qdev-core.h
> create mode 100644 hw/qdev-monitor.h
> create mode 100644 hw/qdev-properties-system.c
> create mode 100644 hw/qdev-properties.h
> create mode 100644 hw/qdev-system.c
> create mode 100644 tests/fake-qdev.c
> create mode 100644 tests/test-qdev-global-props.c
>
--
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] 17+ messages in thread
* [Qemu-devel] [RFC 0/3 v2] qdev: handle global properties after all instance_init calls
2013-07-09 14:32 ` [Qemu-devel] [PATCH 0/6] qdev: handle global properties after all instance_init calls Andreas Färber
@ 2013-07-10 20:08 ` Eduardo Habkost
2013-07-10 20:08 ` [Qemu-devel] [RFC 1/3 v2] tests: unit tests for qdev global-properties handling Eduardo Habkost
` (3 more replies)
0 siblings, 4 replies; 17+ messages in thread
From: Eduardo Habkost @ 2013-07-10 20:08 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Anthony Liguori, Andreas Färber,
Igor Mammedov
Updated version of the series sent in October 2012.
References:
http://article.gmane.org/gmane.comp.emulators.qemu/173753
(old discussion)
http://article.gmane.org/gmane.comp.emulators.qemu/173782
(previous version of this series)
http://article.gmane.org/gmane.comp.emulators.kvm.devel/112380
(Minutes of last call where this was discussed)
Eduardo Habkost (3):
tests: unit tests for qdev global-properties handling
qom: introduce post_init() function
qdev: set globals on post_init() function
hw/core/qdev.c | 10 ++-
include/qom/object.h | 3 +
qom/object.c | 14 ++++
tests/.gitignore | 1 +
tests/Makefile | 7 ++
tests/test-qdev-global-props.c | 178 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 212 insertions(+), 1 deletion(-)
create mode 100644 tests/test-qdev-global-props.c
--
1.8.1.4
^ permalink raw reply [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC 1/3 v2] tests: unit tests for qdev global-properties handling
2013-07-10 20:08 ` [Qemu-devel] [RFC 0/3 v2] " Eduardo Habkost
@ 2013-07-10 20:08 ` Eduardo Habkost
2013-07-10 20:08 ` [Qemu-devel] [RFC 2/3 v2] qom: introduce post_init() function Eduardo Habkost
` (2 subsequent siblings)
3 siblings, 0 replies; 17+ messages in thread
From: Eduardo Habkost @ 2013-07-10 20:08 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Anthony Liguori, Andreas Färber,
Igor Mammedov
This tests the qdev global-properties handling code.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
tests/.gitignore | 1 +
tests/Makefile | 7 +++
tests/test-qdev-global-props.c | 109 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 117 insertions(+)
create mode 100644 tests/test-qdev-global-props.c
diff --git a/tests/.gitignore b/tests/.gitignore
index fb05c2a..3586416 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -18,4 +18,5 @@ test-qmp-marshal.c
test-thread-pool
test-x86-cpuid
test-xbzrle
+test-qdev-global-props
*-test
diff --git a/tests/Makefile b/tests/Makefile
index 279d5f8..9849441 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -47,6 +47,7 @@ gcov-files-test-mul64-y = util/host-utils.c
check-unit-y += tests/test-int128$(EXESUF)
# all code tested by test-int128 is inside int128.h
gcov-files-test-int128-y =
+check-unit-y += tests/test-qdev-global-props$(EXESUF)
check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
@@ -102,6 +103,12 @@ tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o
tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o xbzrle.o page_cache.o libqemuutil.a
tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o
tests/test-int128$(EXESUF): tests/test-int128.o
+tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
+ hw/core/qdev.o hw/core/qdev-properties.o \
+ hw/core/irq.o \
+ qom/object.o qom/container.o qom/qom-qobject.o \
+ $(test-qapi-obj-y) \
+ libqemuutil.a libqemustub.a
tests/test-qapi-types.c tests/test-qapi-types.h :\
$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c
new file mode 100644
index 0000000..4c50156
--- /dev/null
+++ b/tests/test-qdev-global-props.c
@@ -0,0 +1,109 @@
+/*
+ * Test code for qdev global-properties handling
+ *
+ * Copyright (c) 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <glib.h>
+#include <stdint.h>
+
+#include "hw/qdev.h"
+
+
+#define TYPE_STATIC_PROPS "static_prop_type"
+#define STATIC_TYPE(obj) \
+ OBJECT_CHECK(MyType, (obj), TYPE_STATIC_PROPS)
+
+#define PROP_DEFAULT 100
+
+typedef struct MyType {
+ DeviceState parent_obj;
+
+ uint32_t prop1, prop2, prop3;
+} MyType;
+
+static Property static_props[] = {
+ DEFINE_PROP_UINT32("prop1", MyType, prop1, PROP_DEFAULT),
+ DEFINE_PROP_UINT32("prop2", MyType, prop2, PROP_DEFAULT),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static int mytype_init(DeviceState *dev)
+{
+ return 0;
+}
+
+static void static_prop_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->props = static_props;
+ dc->init = mytype_init;
+}
+
+static TypeInfo static_prop_type = {
+ .name = TYPE_STATIC_PROPS,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(MyType),
+ .class_init = static_prop_class_init,
+};
+
+/* Test simple static property setting to default value */
+static void test_static_prop(void)
+{
+ MyType *mt;
+
+ mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS));
+ qdev_init_nofail(DEVICE(mt));
+
+ g_assert_cmpuint(mt->prop1, ==, PROP_DEFAULT);
+}
+
+/* Test setting of static property using global properties */
+static void test_static_globalprop(void)
+{
+ MyType *mt;
+ GlobalProperty props[] = {
+ {TYPE_STATIC_PROPS, "prop1", "200"},
+ {}
+ };
+ qdev_prop_register_global_list(props);
+
+ mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS));
+ qdev_init_nofail(DEVICE(mt));
+
+ g_assert_cmpuint(mt->prop1, ==, 200);
+ g_assert_cmpuint(mt->prop2, ==, PROP_DEFAULT);
+}
+
+int main(int argc, char **argv)
+{
+ module_call_init(MODULE_INIT_QOM);
+ type_register_static(&static_prop_type);
+
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/qdev/properties/static/default", test_static_prop);
+ g_test_add_func("/qdev/properties/static/global", test_static_globalprop);
+
+ g_test_run();
+
+ return 0;
+}
--
1.8.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC 2/3 v2] qom: introduce post_init() function
2013-07-10 20:08 ` [Qemu-devel] [RFC 0/3 v2] " Eduardo Habkost
2013-07-10 20:08 ` [Qemu-devel] [RFC 1/3 v2] tests: unit tests for qdev global-properties handling Eduardo Habkost
@ 2013-07-10 20:08 ` Eduardo Habkost
2013-07-11 6:29 ` Igor Mammedov
2013-07-10 20:08 ` [Qemu-devel] [RFC 3/3 v2] qdev: set globals on " Eduardo Habkost
2013-07-28 19:44 ` [Qemu-devel] [RFC 0/3 v2] qdev: handle global properties after all instance_init calls Andreas Färber
3 siblings, 1 reply; 17+ messages in thread
From: Eduardo Habkost @ 2013-07-10 20:08 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Anthony Liguori, Andreas Färber,
Igor Mammedov
This will allow classes to specify a function to be called after all
instance_init() functions were called.
This will be used by DeviceState to call qdev_prop_set_globals() at the
right moment.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
include/qom/object.h | 3 +++
qom/object.c | 14 ++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/include/qom/object.h b/include/qom/object.h
index 23fc048..1a54f64 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -398,6 +398,8 @@ struct Object
* @instance_init: This function is called to initialize an object. The parent
* class will have already been initialized so the type is only responsible
* for initializing its own members.
+ * @instance_post_init: This function is called to finish initialization of
+ * an object, after all instance_init functions were called.
* @instance_finalize: This function is called during object destruction. This
* is called before the parent @instance_finalize function has been called.
* An object should only free the members that are unique to its type in this
@@ -433,6 +435,7 @@ struct TypeInfo
size_t instance_size;
void (*instance_init)(Object *obj);
+ void (*instance_post_init)(Object *obj);
void (*instance_finalize)(Object *obj);
bool abstract;
diff --git a/qom/object.c b/qom/object.c
index b2479d1..74fd241 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -51,6 +51,7 @@ struct TypeImpl
void *class_data;
void (*instance_init)(Object *obj);
+ void (*instance_post_init)(Object *obj);
void (*instance_finalize)(Object *obj);
bool abstract;
@@ -111,6 +112,7 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
ti->class_data = info->class_data;
ti->instance_init = info->instance_init;
+ ti->instance_post_init = info->instance_post_init;
ti->instance_finalize = info->instance_finalize;
ti->abstract = info->abstract;
@@ -298,6 +300,17 @@ static void object_init_with_type(Object *obj, TypeImpl *ti)
}
}
+static void object_post_init_with_type(Object *obj, TypeImpl *ti)
+{
+ if (ti->instance_post_init) {
+ ti->instance_post_init(obj);
+ }
+
+ if (type_has_parent(ti)) {
+ object_post_init_with_type(obj, type_get_parent(ti));
+ }
+}
+
void object_initialize_with_type(void *data, TypeImpl *type)
{
Object *obj = data;
@@ -313,6 +326,7 @@ void object_initialize_with_type(void *data, TypeImpl *type)
object_ref(obj);
QTAILQ_INIT(&obj->properties);
object_init_with_type(obj, type);
+ object_post_init_with_type(obj, type);
}
void object_initialize(void *data, const char *typename)
--
1.8.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [RFC 2/3 v2] qom: introduce post_init() function
2013-07-10 20:08 ` [Qemu-devel] [RFC 2/3 v2] qom: introduce post_init() function Eduardo Habkost
@ 2013-07-11 6:29 ` Igor Mammedov
2013-07-12 0:29 ` Eduardo Habkost
0 siblings, 1 reply; 17+ messages in thread
From: Igor Mammedov @ 2013-07-11 6:29 UTC (permalink / raw)
To: Eduardo Habkost
Cc: Paolo Bonzini, Anthony Liguori, qemu-devel, Andreas Färber
On Wed, 10 Jul 2013 17:08:41 -0300
Eduardo Habkost <ehabkost@redhat.com> wrote:
> This will allow classes to specify a function to be called after all
> instance_init() functions were called.
>
> This will be used by DeviceState to call qdev_prop_set_globals() at the
> right moment.
>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> include/qom/object.h | 3 +++
> qom/object.c | 14 ++++++++++++++
> 2 files changed, 17 insertions(+)
>
> diff --git a/include/qom/object.h b/include/qom/object.h
> index 23fc048..1a54f64 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -398,6 +398,8 @@ struct Object
> * @instance_init: This function is called to initialize an object. The parent
> * class will have already been initialized so the type is only responsible
> * for initializing its own members.
> + * @instance_post_init: This function is called to finish initialization of
> + * an object, after all instance_init functions were called.
> * @instance_finalize: This function is called during object destruction. This
> * is called before the parent @instance_finalize function has been called.
> * An object should only free the members that are unique to its type in this
> @@ -433,6 +435,7 @@ struct TypeInfo
[...]
>
> +static void object_post_init_with_type(Object *obj, TypeImpl *ti)
> +{
> + if (ti->instance_post_init) {
> + ti->instance_post_init(obj);
> + }
> +
> + if (type_has_parent(ti)) {
> + object_post_init_with_type(obj, type_get_parent(ti));
> + }
Is there a reason why post init called in opposite order than
instance_init() ?
> +}
> +
> void object_initialize_with_type(void *data, TypeImpl *type)
> {
> Object *obj = data;
> @@ -313,6 +326,7 @@ void object_initialize_with_type(void *data, TypeImpl *type)
> object_ref(obj);
> QTAILQ_INIT(&obj->properties);
> object_init_with_type(obj, type);
> + object_post_init_with_type(obj, type);
> }
>
> void object_initialize(void *data, const char *typename)
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [RFC 2/3 v2] qom: introduce post_init() function
2013-07-11 6:29 ` Igor Mammedov
@ 2013-07-12 0:29 ` Eduardo Habkost
0 siblings, 0 replies; 17+ messages in thread
From: Eduardo Habkost @ 2013-07-12 0:29 UTC (permalink / raw)
To: Igor Mammedov
Cc: Paolo Bonzini, Anthony Liguori, qemu-devel, Andreas Färber
On Thu, Jul 11, 2013 at 08:29:15AM +0200, Igor Mammedov wrote:
> On Wed, 10 Jul 2013 17:08:41 -0300
> Eduardo Habkost <ehabkost@redhat.com> wrote:
>
> > This will allow classes to specify a function to be called after all
> > instance_init() functions were called.
> >
> > This will be used by DeviceState to call qdev_prop_set_globals() at the
> > right moment.
> >
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > ---
> > include/qom/object.h | 3 +++
> > qom/object.c | 14 ++++++++++++++
> > 2 files changed, 17 insertions(+)
> >
> > diff --git a/include/qom/object.h b/include/qom/object.h
> > index 23fc048..1a54f64 100644
> > --- a/include/qom/object.h
> > +++ b/include/qom/object.h
> > @@ -398,6 +398,8 @@ struct Object
> > * @instance_init: This function is called to initialize an object. The parent
> > * class will have already been initialized so the type is only responsible
> > * for initializing its own members.
> > + * @instance_post_init: This function is called to finish initialization of
> > + * an object, after all instance_init functions were called.
> > * @instance_finalize: This function is called during object destruction. This
> > * is called before the parent @instance_finalize function has been called.
> > * An object should only free the members that are unique to its type in this
> > @@ -433,6 +435,7 @@ struct TypeInfo
> [...]
> >
> > +static void object_post_init_with_type(Object *obj, TypeImpl *ti)
> > +{
> > + if (ti->instance_post_init) {
> > + ti->instance_post_init(obj);
> > + }
> > +
> > + if (type_has_parent(ti)) {
> > + object_post_init_with_type(obj, type_get_parent(ti));
> > + }
> Is there a reason why post init called in opposite order than
> instance_init() ?
Because it seems more useful: if parent types want to initialize
something before subclasses, they can use instance_init(). If they want
to initialize something _after_ subclasses, then they can use
instance_post_init().
>
> > +}
> > +
> > void object_initialize_with_type(void *data, TypeImpl *type)
> > {
> > Object *obj = data;
> > @@ -313,6 +326,7 @@ void object_initialize_with_type(void *data, TypeImpl *type)
> > object_ref(obj);
> > QTAILQ_INIT(&obj->properties);
> > object_init_with_type(obj, type);
> > + object_post_init_with_type(obj, type);
> > }
> >
> > void object_initialize(void *data, const char *typename)
>
--
Eduardo
^ permalink raw reply [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC 3/3 v2] qdev: set globals on post_init() function
2013-07-10 20:08 ` [Qemu-devel] [RFC 0/3 v2] " Eduardo Habkost
2013-07-10 20:08 ` [Qemu-devel] [RFC 1/3 v2] tests: unit tests for qdev global-properties handling Eduardo Habkost
2013-07-10 20:08 ` [Qemu-devel] [RFC 2/3 v2] qom: introduce post_init() function Eduardo Habkost
@ 2013-07-10 20:08 ` Eduardo Habkost
2013-07-11 6:48 ` Igor Mammedov
2013-07-28 19:44 ` [Qemu-devel] [RFC 0/3 v2] qdev: handle global properties after all instance_init calls Andreas Färber
3 siblings, 1 reply; 17+ messages in thread
From: Eduardo Habkost @ 2013-07-10 20:08 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Anthony Liguori, Andreas Färber,
Igor Mammedov
This way, properties registered in the instance_init() function of
children classes will be handled properly by qdev_prop_set_globals(),
too.
Includes a new unit test for the new functionality.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
hw/core/qdev.c | 10 +++++-
tests/test-qdev-global-props.c | 71 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 79 insertions(+), 2 deletions(-)
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 9190a7e..e0acb6c 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -752,7 +752,6 @@ static void device_initfn(Object *obj)
}
class = object_class_get_parent(class);
} while (class != object_class_by_name(TYPE_DEVICE));
- qdev_prop_set_globals(dev, &err);
if (err != NULL) {
qerror_report_err(err);
error_free(err);
@@ -764,6 +763,14 @@ static void device_initfn(Object *obj)
assert_no_error(err);
}
+static void device_post_init(Object *obj)
+{
+ Error *err = NULL;
+ DeviceState *dev = DEVICE(obj);
+ qdev_prop_set_globals(dev, &err);
+ assert_no_error(err);
+}
+
/* Unlink device from bus and free the structure. */
static void device_finalize(Object *obj)
{
@@ -853,6 +860,7 @@ static const TypeInfo device_type_info = {
.parent = TYPE_OBJECT,
.instance_size = sizeof(DeviceState),
.instance_init = device_initfn,
+ .instance_post_init = device_post_init,
.instance_finalize = device_finalize,
.class_base_init = device_class_base_init,
.class_init = device_class_init,
diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c
index 4c50156..7b5eb88 100644
--- a/tests/test-qdev-global-props.c
+++ b/tests/test-qdev-global-props.c
@@ -26,6 +26,8 @@
#include <stdint.h>
#include "hw/qdev.h"
+#include "qemu/object.h"
+#include "qapi-visit.h"
#define TYPE_STATIC_PROPS "static_prop_type"
@@ -80,7 +82,7 @@ static void test_static_prop(void)
static void test_static_globalprop(void)
{
MyType *mt;
- GlobalProperty props[] = {
+ static GlobalProperty props[] = {
{TYPE_STATIC_PROPS, "prop1", "200"},
{}
};
@@ -93,15 +95,82 @@ static void test_static_globalprop(void)
g_assert_cmpuint(mt->prop2, ==, PROP_DEFAULT);
}
+#define TYPE_DYNAMIC_PROPS "dynamic_prop_type"
+#define DYNAMIC_TYPE(obj) \
+ OBJECT_CHECK(MyType, (obj), TYPE_DYNAMIC_PROPS)
+
+static void prop1_acessor(Object *obj,
+ struct Visitor *v,
+ void *opaque,
+ const char *name,
+ struct Error **errp)
+{
+ MyType *mt = DYNAMIC_TYPE(obj);
+ visit_type_uint32(v, &mt->prop1, name, errp);
+}
+
+static void prop2_acessor(Object *obj,
+ struct Visitor *v,
+ void *opaque,
+ const char *name,
+ struct Error **errp)
+{
+ MyType *mt = DYNAMIC_TYPE(obj);
+ visit_type_uint32(v, &mt->prop2, name, errp);
+}
+
+static void dynamic_instance_init(Object *obj)
+{
+ object_property_add(obj, "prop1", "uint32", prop1_acessor, prop1_acessor,
+ NULL, NULL, NULL);
+ object_property_add(obj, "prop2", "uint32", prop2_acessor, prop2_acessor,
+ NULL, NULL, NULL);
+}
+
+static void dynamic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->init = mytype_init;
+}
+
+
+static TypeInfo dynamic_prop_type = {
+ .name = TYPE_DYNAMIC_PROPS,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(MyType),
+ .instance_init = dynamic_instance_init,
+ .class_init = dynamic_class_init,
+};
+
+/* Test setting of static property using global properties */
+static void test_dynamic_globalprop(void)
+{
+ MyType *mt;
+ static GlobalProperty props[] = {
+ {TYPE_DYNAMIC_PROPS, "prop1", "101"},
+ {TYPE_DYNAMIC_PROPS, "prop2", "102"},
+ {}
+ };
+ qdev_prop_register_global_list(props);
+
+ mt = DYNAMIC_TYPE(object_new(TYPE_DYNAMIC_PROPS));
+ qdev_init_nofail(DEVICE(mt));
+
+ g_assert_cmpuint(mt->prop1, ==, 101);
+ g_assert_cmpuint(mt->prop2, ==, 102);
+}
+
int main(int argc, char **argv)
{
module_call_init(MODULE_INIT_QOM);
type_register_static(&static_prop_type);
+ type_register_static(&dynamic_prop_type);
g_test_init(&argc, &argv, NULL);
g_test_add_func("/qdev/properties/static/default", test_static_prop);
g_test_add_func("/qdev/properties/static/global", test_static_globalprop);
+ g_test_add_func("/qdev/properties/dynamic/global", test_dynamic_globalprop);
g_test_run();
--
1.8.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [RFC 3/3 v2] qdev: set globals on post_init() function
2013-07-10 20:08 ` [Qemu-devel] [RFC 3/3 v2] qdev: set globals on " Eduardo Habkost
@ 2013-07-11 6:48 ` Igor Mammedov
2013-07-12 14:57 ` Eduardo Habkost
0 siblings, 1 reply; 17+ messages in thread
From: Igor Mammedov @ 2013-07-11 6:48 UTC (permalink / raw)
To: Eduardo Habkost
Cc: Paolo Bonzini, Anthony Liguori, qemu-devel, Andreas Färber
On Wed, 10 Jul 2013 17:08:42 -0300
Eduardo Habkost <ehabkost@redhat.com> wrote:
> This way, properties registered in the instance_init() function of
> children classes will be handled properly by qdev_prop_set_globals(),
> too.
>
> Includes a new unit test for the new functionality.
>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> hw/core/qdev.c | 10 +++++-
> tests/test-qdev-global-props.c | 71 +++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 79 insertions(+), 2 deletions(-)
>
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 9190a7e..e0acb6c 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -752,7 +752,6 @@ static void device_initfn(Object *obj)
> }
> class = object_class_get_parent(class);
> } while (class != object_class_by_name(TYPE_DEVICE));
> - qdev_prop_set_globals(dev, &err);
> if (err != NULL) {
> qerror_report_err(err);
> error_free(err);
> @@ -764,6 +763,14 @@ static void device_initfn(Object *obj)
> assert_no_error(err);
> }
>
> +static void device_post_init(Object *obj)
> +{
> + Error *err = NULL;
> + DeviceState *dev = DEVICE(obj);
> + qdev_prop_set_globals(dev, &err);
> + assert_no_error(err);
> +}
> +
> /* Unlink device from bus and free the structure. */
> static void device_finalize(Object *obj)
> {
> @@ -853,6 +860,7 @@ static const TypeInfo device_type_info = {
> .parent = TYPE_OBJECT,
> .instance_size = sizeof(DeviceState),
> .instance_init = device_initfn,
> + .instance_post_init = device_post_init,
> .instance_finalize = device_finalize,
> .class_base_init = device_class_base_init,
> .class_init = device_class_init,
> diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c
> index 4c50156..7b5eb88 100644
> --- a/tests/test-qdev-global-props.c
> +++ b/tests/test-qdev-global-props.c
> @@ -26,6 +26,8 @@
> #include <stdint.h>
>
> #include "hw/qdev.h"
> +#include "qemu/object.h"
> +#include "qapi-visit.h"
>
>
> #define TYPE_STATIC_PROPS "static_prop_type"
> @@ -80,7 +82,7 @@ static void test_static_prop(void)
> static void test_static_globalprop(void)
> {
> MyType *mt;
> - GlobalProperty props[] = {
> + static GlobalProperty props[] = {
> {TYPE_STATIC_PROPS, "prop1", "200"},
> {}
> };
hunk belongs to the 1st patch?
> @@ -93,15 +95,82 @@ static void test_static_globalprop(void)
> g_assert_cmpuint(mt->prop2, ==, PROP_DEFAULT);
> }
>
> +#define TYPE_DYNAMIC_PROPS "dynamic_prop_type"
> +#define DYNAMIC_TYPE(obj) \
> + OBJECT_CHECK(MyType, (obj), TYPE_DYNAMIC_PROPS)
> +
> +static void prop1_acessor(Object *obj,
> + struct Visitor *v,
> + void *opaque,
> + const char *name,
> + struct Error **errp)
> +{
> + MyType *mt = DYNAMIC_TYPE(obj);
> + visit_type_uint32(v, &mt->prop1, name, errp);
> +}
> +
> +static void prop2_acessor(Object *obj,
> + struct Visitor *v,
> + void *opaque,
> + const char *name,
> + struct Error **errp)
> +{
> + MyType *mt = DYNAMIC_TYPE(obj);
> + visit_type_uint32(v, &mt->prop2, name, errp);
> +}
> +
> +static void dynamic_instance_init(Object *obj)
> +{
> + object_property_add(obj, "prop1", "uint32", prop1_acessor, prop1_acessor,
> + NULL, NULL, NULL);
> + object_property_add(obj, "prop2", "uint32", prop2_acessor, prop2_acessor,
> + NULL, NULL, NULL);
> +}
> +
> +static void dynamic_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + dc->init = mytype_init;
> +}
> +
> +
> +static TypeInfo dynamic_prop_type = {
> + .name = TYPE_DYNAMIC_PROPS,
> + .parent = TYPE_DEVICE,
> + .instance_size = sizeof(MyType),
> + .instance_init = dynamic_instance_init,
> + .class_init = dynamic_class_init,
> +};
> +
> +/* Test setting of static property using global properties */
> +static void test_dynamic_globalprop(void)
> +{
> + MyType *mt;
> + static GlobalProperty props[] = {
> + {TYPE_DYNAMIC_PROPS, "prop1", "101"},
> + {TYPE_DYNAMIC_PROPS, "prop2", "102"},
> + {}
> + };
this list cloud be the same for static and dynamic tests, no need to duplicate
and perhaps one property is enough, like it's done for static one?
> + qdev_prop_register_global_list(props);
> +
> + mt = DYNAMIC_TYPE(object_new(TYPE_DYNAMIC_PROPS));
> + qdev_init_nofail(DEVICE(mt));
> +
> + g_assert_cmpuint(mt->prop1, ==, 101);
> + g_assert_cmpuint(mt->prop2, ==, 102);
> +}
> +
> int main(int argc, char **argv)
> {
> module_call_init(MODULE_INIT_QOM);
> type_register_static(&static_prop_type);
> + type_register_static(&dynamic_prop_type);
>
> g_test_init(&argc, &argv, NULL);
>
> g_test_add_func("/qdev/properties/static/default", test_static_prop);
> g_test_add_func("/qdev/properties/static/global", test_static_globalprop);
> + g_test_add_func("/qdev/properties/dynamic/global", test_dynamic_globalprop);
>
> g_test_run();
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [RFC 3/3 v2] qdev: set globals on post_init() function
2013-07-11 6:48 ` Igor Mammedov
@ 2013-07-12 14:57 ` Eduardo Habkost
0 siblings, 0 replies; 17+ messages in thread
From: Eduardo Habkost @ 2013-07-12 14:57 UTC (permalink / raw)
To: Igor Mammedov
Cc: Paolo Bonzini, Anthony Liguori, qemu-devel, Andreas Färber
On Thu, Jul 11, 2013 at 08:48:44AM +0200, Igor Mammedov wrote:
[...]
> > #define TYPE_STATIC_PROPS "static_prop_type"
> > @@ -80,7 +82,7 @@ static void test_static_prop(void)
> > static void test_static_globalprop(void)
> > {
> > MyType *mt;
> > - GlobalProperty props[] = {
> > + static GlobalProperty props[] = {
> > {TYPE_STATIC_PROPS, "prop1", "200"},
> > {}
> > };
> hunk belongs to the 1st patch?
Yes, thanks for noticing.
>
> > @@ -93,15 +95,82 @@ static void test_static_globalprop(void)
> > g_assert_cmpuint(mt->prop2, ==, PROP_DEFAULT);
> > }
> >
> > +#define TYPE_DYNAMIC_PROPS "dynamic_prop_type"
> > +#define DYNAMIC_TYPE(obj) \
> > + OBJECT_CHECK(MyType, (obj), TYPE_DYNAMIC_PROPS)
> > +
> > +static void prop1_acessor(Object *obj,
> > + struct Visitor *v,
> > + void *opaque,
> > + const char *name,
> > + struct Error **errp)
> > +{
> > + MyType *mt = DYNAMIC_TYPE(obj);
> > + visit_type_uint32(v, &mt->prop1, name, errp);
> > +}
> > +
> > +static void prop2_acessor(Object *obj,
> > + struct Visitor *v,
> > + void *opaque,
> > + const char *name,
> > + struct Error **errp)
> > +{
> > + MyType *mt = DYNAMIC_TYPE(obj);
> > + visit_type_uint32(v, &mt->prop2, name, errp);
> > +}
> > +
> > +static void dynamic_instance_init(Object *obj)
> > +{
> > + object_property_add(obj, "prop1", "uint32", prop1_acessor, prop1_acessor,
> > + NULL, NULL, NULL);
> > + object_property_add(obj, "prop2", "uint32", prop2_acessor, prop2_acessor,
> > + NULL, NULL, NULL);
> > +}
> > +
> > +static void dynamic_class_init(ObjectClass *klass, void *data)
> > +{
> > + DeviceClass *dc = DEVICE_CLASS(klass);
> > + dc->init = mytype_init;
> > +}
> > +
> > +
> > +static TypeInfo dynamic_prop_type = {
> > + .name = TYPE_DYNAMIC_PROPS,
> > + .parent = TYPE_DEVICE,
> > + .instance_size = sizeof(MyType),
> > + .instance_init = dynamic_instance_init,
> > + .class_init = dynamic_class_init,
> > +};
> > +
> > +/* Test setting of static property using global properties */
> > +static void test_dynamic_globalprop(void)
> > +{
> > + MyType *mt;
> > + static GlobalProperty props[] = {
> > + {TYPE_DYNAMIC_PROPS, "prop1", "101"},
> > + {TYPE_DYNAMIC_PROPS, "prop2", "102"},
> > + {}
> > + };
> this list cloud be the same for static and dynamic tests, no need to duplicate
>
> and perhaps one property is enough, like it's done for static one?
I don't know. I like the fact that both test cases are exercising the
property-setting API in different ways and are likely to catch different
types of bugs.
>
>
> > + qdev_prop_register_global_list(props);
> > +
> > + mt = DYNAMIC_TYPE(object_new(TYPE_DYNAMIC_PROPS));
> > + qdev_init_nofail(DEVICE(mt));
> > +
> > + g_assert_cmpuint(mt->prop1, ==, 101);
> > + g_assert_cmpuint(mt->prop2, ==, 102);
> > +}
> > +
> > int main(int argc, char **argv)
> > {
> > module_call_init(MODULE_INIT_QOM);
> > type_register_static(&static_prop_type);
> > + type_register_static(&dynamic_prop_type);
> >
> > g_test_init(&argc, &argv, NULL);
> >
> > g_test_add_func("/qdev/properties/static/default", test_static_prop);
> > g_test_add_func("/qdev/properties/static/global", test_static_globalprop);
> > + g_test_add_func("/qdev/properties/dynamic/global", test_dynamic_globalprop);
> >
> > g_test_run();
> >
>
--
Eduardo
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [RFC 0/3 v2] qdev: handle global properties after all instance_init calls
2013-07-10 20:08 ` [Qemu-devel] [RFC 0/3 v2] " Eduardo Habkost
` (2 preceding siblings ...)
2013-07-10 20:08 ` [Qemu-devel] [RFC 3/3 v2] qdev: set globals on " Eduardo Habkost
@ 2013-07-28 19:44 ` Andreas Färber
3 siblings, 0 replies; 17+ messages in thread
From: Andreas Färber @ 2013-07-28 19:44 UTC (permalink / raw)
To: Eduardo Habkost; +Cc: Paolo Bonzini, Anthony Liguori, qemu-devel, Igor Mammedov
Am 10.07.2013 22:08, schrieb Eduardo Habkost:
> Updated version of the series sent in October 2012.
>
> References:
> http://article.gmane.org/gmane.comp.emulators.qemu/173753
> (old discussion)
> http://article.gmane.org/gmane.comp.emulators.qemu/173782
> (previous version of this series)
> http://article.gmane.org/gmane.comp.emulators.kvm.devel/112380
> (Minutes of last call where this was discussed)
>
> Eduardo Habkost (3):
> tests: unit tests for qdev global-properties handling
> qom: introduce post_init() function
> qdev: set globals on post_init() function
Thanks, I have applied these with some style, spelling and build fixes
to qom-cpu-next:
https://github.com/afaerber/qemu-cpu/commits/qom-cpu-next
Since Igor and me have agreed to continue work on x86 properties on
qom-cpu-next during Hard Freeze, I do not see a need to merge these
patches Last Minute through qom-next for 1.6. If I'm missing some use
case other than x86 subclasses, please let me know.
Regards,
Andreas
> hw/core/qdev.c | 10 ++-
> include/qom/object.h | 3 +
> qom/object.c | 14 ++++
> tests/.gitignore | 1 +
> tests/Makefile | 7 ++
> tests/test-qdev-global-props.c | 178 +++++++++++++++++++++++++++++++++++++++++
> 6 files changed, 212 insertions(+), 1 deletion(-)
> create mode 100644 tests/test-qdev-global-props.c
--
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] 17+ messages in thread