* [Qemu-devel] [PATCH v2 0/2] QOM realize, device-only
@ 2013-01-06 18:48 Andreas Färber
2013-01-06 18:48 ` [Qemu-devel] [PATCH v2 1/2] qdev: Fold state enum into bool realized Andreas Färber
2013-01-06 18:48 ` [Qemu-devel] [PATCH v2 2/2] qdev: Prepare "realized" property Andreas Färber
0 siblings, 2 replies; 4+ messages in thread
From: Andreas Färber @ 2013-01-06 18:48 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Eduardo Habkost, anthony, Igor Mammedov, pbonzini,
Andreas Färber
Hello Anthony,
Here's a rebased version of device-only QOM realization, otherwise unchanged.
This is based on master now and drops all general-purpose qdev cleanups that
potentially conflict with Paolo's reference counting change proposal.
It will trivially conflict with my qdev unparenting fix, pending to be added
to the qom-cpu queue (touches k->unparent in class_init).
Same as v1, this is not the big throw of a recursive, central realization model.
The immediate purpose of this series is to allow CPUs, which partially already
have realizefns prepared, to adjust to the new DeviceState signature (being a
device on qom-cpu branch) and hook them up to DeviceClass::realize rather than
exposing as a function through cpu.h. Please review and apply to qemu.git.
As discussed in the last cover letter, doing realization at DeviceState level
does not allow for trivial [un]realize_children as proposed by Paolo for Object.
An idea how to implement this as a follow-up would be to do a deep search for
child<> properties dynamic_cast'able to DeviceState. Or to simply try setting
a "realized" property and it that fails check for children (but how to differ
between "realized" that failed and "realized" that doesn't exist then?).
Available from:
https://github.com/afaerber/qemu-cpu/commits/realize-qdev.v2
git://github.com/afaerber/qemu-cpu.git realize-qdev.v2
Regards,
Andreas
Cc: Anthony Liguori <anthony@codemonkey.ws>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Andreas Färber (2):
qdev: Fold state enum into bool realized
qdev: Prepare "realized" property
hw/qdev-addr.c | 2 +-
hw/qdev-core.h | 11 ++---
hw/qdev-properties-system.c | 4 +-
hw/qdev-properties.c | 24 +++++-----
hw/qdev.c | 106 +++++++++++++++++++++++++++++++------------
5 Dateien geändert, 97 Zeilen hinzugefügt(+), 50 Zeilen entfernt(-)
--
1.7.10.4
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH v2 1/2] qdev: Fold state enum into bool realized
2013-01-06 18:48 [Qemu-devel] [PATCH v2 0/2] QOM realize, device-only Andreas Färber
@ 2013-01-06 18:48 ` Andreas Färber
2013-01-06 18:48 ` [Qemu-devel] [PATCH v2 2/2] qdev: Prepare "realized" property Andreas Färber
1 sibling, 0 replies; 4+ messages in thread
From: Andreas Färber @ 2013-01-06 18:48 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, Andreas Färber, anthony
Whether the device was initialized or not is QOM-level information and
currently unused. Drop it from qdev. This leaves the boolean state of
whether or not DeviceClass::init was called or not, a.k.a. "realized".
Suggested-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
---
hw/qdev-addr.c | 2 +-
hw/qdev-core.h | 7 +------
hw/qdev-properties-system.c | 4 ++--
hw/qdev-properties.c | 24 ++++++++++++------------
hw/qdev.c | 12 ++++++------
5 Dateien geändert, 22 Zeilen hinzugefügt(+), 27 Zeilen entfernt(-)
diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c
index 3bfe101..b4388f6 100644
--- a/hw/qdev-addr.c
+++ b/hw/qdev-addr.c
@@ -40,7 +40,7 @@ static void set_taddr(Object *obj, Visitor *v, void *opaque,
Error *local_err = NULL;
int64_t value;
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index fdf14ec..5836e35 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -8,11 +8,6 @@
#include "hw/irq.h"
#include "qapi/error.h"
-enum DevState {
- DEV_STATE_CREATED = 1,
- DEV_STATE_INITIALIZED,
-};
-
enum {
DEV_NVECTORS_UNSPECIFIED = -1,
};
@@ -55,7 +50,7 @@ struct DeviceState {
Object parent_obj;
const char *id;
- enum DevState state;
+ bool realized;
QemuOpts *opts;
int hotplugged;
BusState *parent_bus;
diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c
index c73c713..ce0f793 100644
--- a/hw/qdev-properties-system.c
+++ b/hw/qdev-properties-system.c
@@ -42,7 +42,7 @@ static void set_pointer(Object *obj, Visitor *v, Property *prop,
char *str;
int ret;
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
@@ -254,7 +254,7 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque,
int32_t id;
NetClientState *hubport;
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index f724357..a8a31f5 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -32,7 +32,7 @@ static void set_enum(Object *obj, Visitor *v, void *opaque,
Property *prop = opaque;
int *ptr = qdev_get_prop_ptr(dev, prop);
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
@@ -85,7 +85,7 @@ static void set_bit(Object *obj, Visitor *v, void *opaque,
Error *local_err = NULL;
bool value;
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
@@ -125,7 +125,7 @@ static void set_uint8(Object *obj, Visitor *v, void *opaque,
Property *prop = opaque;
uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
@@ -192,7 +192,7 @@ static void set_uint16(Object *obj, Visitor *v, void *opaque,
Property *prop = opaque;
uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
@@ -225,7 +225,7 @@ static void set_uint32(Object *obj, Visitor *v, void *opaque,
Property *prop = opaque;
uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
@@ -250,7 +250,7 @@ static void set_int32(Object *obj, Visitor *v, void *opaque,
Property *prop = opaque;
int32_t *ptr = qdev_get_prop_ptr(dev, prop);
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
@@ -323,7 +323,7 @@ static void set_uint64(Object *obj, Visitor *v, void *opaque,
Property *prop = opaque;
uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
@@ -413,7 +413,7 @@ static void set_string(Object *obj, Visitor *v, void *opaque,
Error *local_err = NULL;
char *str;
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
@@ -477,7 +477,7 @@ static void set_mac(Object *obj, Visitor *v, void *opaque,
int i, pos;
char *str, *p;
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
@@ -569,7 +569,7 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
Error *local_err = NULL;
char *str;
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
@@ -640,7 +640,7 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
const int64_t min = 512;
const int64_t max = 32768;
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
@@ -708,7 +708,7 @@ static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
unsigned long dom = 0, bus = 0;
unsigned int slot = 0, func = 0;
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
diff --git a/hw/qdev.c b/hw/qdev.c
index f2c2484..b214c8a 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -151,7 +151,7 @@ int qdev_init(DeviceState *dev)
DeviceClass *dc = DEVICE_GET_CLASS(dev);
int rc;
- assert(dev->state == DEV_STATE_CREATED);
+ assert(!dev->realized);
rc = dc->init(dev);
if (rc < 0) {
@@ -174,7 +174,7 @@ int qdev_init(DeviceState *dev)
dev->instance_id_alias,
dev->alias_required_for_version);
}
- dev->state = DEV_STATE_INITIALIZED;
+ dev->realized = true;
if (dev->hotplugged) {
device_reset(dev);
}
@@ -184,7 +184,7 @@ int qdev_init(DeviceState *dev)
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
int required_for_version)
{
- assert(dev->state == DEV_STATE_CREATED);
+ assert(!dev->realized);
dev->instance_id_alias = alias_id;
dev->alias_required_for_version = required_for_version;
}
@@ -541,7 +541,7 @@ static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
char *ptr = NULL;
int ret;
- if (dev->state != DEV_STATE_CREATED) {
+ if (dev->realized) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
@@ -648,7 +648,7 @@ static void device_initfn(Object *obj)
}
dev->instance_id_alias = -1;
- dev->state = DEV_STATE_CREATED;
+ dev->realized = false;
class = object_get_class(OBJECT(dev));
do {
@@ -671,7 +671,7 @@ static void device_finalize(Object *obj)
BusState *bus;
DeviceClass *dc = DEVICE_GET_CLASS(dev);
- if (dev->state == DEV_STATE_INITIALIZED) {
+ if (dev->realized) {
while (dev->num_child_bus) {
bus = QLIST_FIRST(&dev->child_bus);
qbus_free(bus);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH v2 2/2] qdev: Prepare "realized" property
2013-01-06 18:48 [Qemu-devel] [PATCH v2 0/2] QOM realize, device-only Andreas Färber
2013-01-06 18:48 ` [Qemu-devel] [PATCH v2 1/2] qdev: Fold state enum into bool realized Andreas Färber
@ 2013-01-06 18:48 ` Andreas Färber
2013-01-07 13:52 ` Eduardo Habkost
1 sibling, 1 reply; 4+ messages in thread
From: Andreas Färber @ 2013-01-06 18:48 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, Andreas Färber, anthony
Based on earlier patches by Paolo and me, introduce the QOM realizefn at
device level only, as requested by Anthony.
For now this just wraps the qdev initfn, which it deprecates.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
Cc: Anthony Liguori <anthony@codemonkey.ws>
---
hw/qdev-core.h | 4 +++
hw/qdev.c | 96 ++++++++++++++++++++++++++++++++++++++++++--------------
2 Dateien geändert, 76 Zeilen hinzugefügt(+), 24 Zeilen entfernt(-)
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index 5836e35..e50c866 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -20,6 +20,8 @@ enum {
typedef int (*qdev_initfn)(DeviceState *dev);
typedef int (*qdev_event)(DeviceState *dev);
typedef void (*qdev_resetfn)(DeviceState *dev);
+typedef void (*DeviceRealize)(DeviceState *dev, Error **err);
+typedef void (*DeviceUnrealize)(DeviceState *dev, Error **err);
struct VMStateDescription;
@@ -38,6 +40,8 @@ typedef struct DeviceClass {
const struct VMStateDescription *vmsd;
/* Private to qdev / bus. */
+ DeviceRealize realize;
+ DeviceUnrealize unrealize;
qdev_initfn init;
qdev_event unplug;
qdev_event exit;
diff --git a/hw/qdev.c b/hw/qdev.c
index b214c8a..f45ab14 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -148,37 +148,30 @@ DeviceState *qdev_try_create(BusState *bus, const char *type)
Return 0 on success. */
int qdev_init(DeviceState *dev)
{
- DeviceClass *dc = DEVICE_GET_CLASS(dev);
- int rc;
+ Error *local_err = NULL;
assert(!dev->realized);
- rc = dc->init(dev);
- if (rc < 0) {
+ object_property_set_bool(OBJECT(dev), true, "realized", &local_err);
+ if (local_err != NULL) {
+ error_free(local_err);
qdev_free(dev);
- return rc;
+ return -1;
}
+ return 0;
+}
- if (!OBJECT(dev)->parent) {
- static int unattached_count = 0;
- gchar *name = g_strdup_printf("device[%d]", unattached_count++);
-
- object_property_add_child(container_get(qdev_get_machine(),
- "/unattached"),
- name, OBJECT(dev), NULL);
- g_free(name);
- }
+static void device_realize(DeviceState *dev, Error **err)
+{
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
- if (qdev_get_vmsd(dev)) {
- vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
- dev->instance_id_alias,
- dev->alias_required_for_version);
- }
- dev->realized = true;
- if (dev->hotplugged) {
- device_reset(dev);
+ if (dc->init) {
+ int rc = dc->init(dev);
+ if (rc < 0) {
+ error_setg(err, "Device initialization failed.");
+ return;
+ }
}
- return 0;
}
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
@@ -636,6 +629,55 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
assert_no_error(local_err);
}
+static bool device_get_realized(Object *obj, Error **err)
+{
+ DeviceState *dev = DEVICE(obj);
+ return dev->realized;
+}
+
+static void device_set_realized(Object *obj, bool value, Error **err)
+{
+ DeviceState *dev = DEVICE(obj);
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
+ Error *local_err = NULL;
+
+ if (value && !dev->realized) {
+ if (dc->realize) {
+ dc->realize(dev, &local_err);
+ }
+
+ if (!obj->parent && local_err == NULL) {
+ static int unattached_count;
+ gchar *name = g_strdup_printf("device[%d]", unattached_count++);
+
+ object_property_add_child(container_get(qdev_get_machine(),
+ "/unattached"),
+ name, obj, &local_err);
+ g_free(name);
+ }
+
+ if (qdev_get_vmsd(dev) && local_err == NULL) {
+ vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
+ dev->instance_id_alias,
+ dev->alias_required_for_version);
+ }
+ if (dev->hotplugged && local_err == NULL) {
+ device_reset(dev);
+ }
+ } else if (!value && dev->realized) {
+ if (dc->unrealize) {
+ dc->unrealize(dev, &local_err);
+ }
+ }
+
+ if (local_err != NULL) {
+ error_propagate(err, local_err);
+ return;
+ }
+
+ dev->realized = value;
+}
+
static void device_initfn(Object *obj)
{
DeviceState *dev = DEVICE(obj);
@@ -650,6 +692,9 @@ static void device_initfn(Object *obj)
dev->instance_id_alias = -1;
dev->realized = false;
+ object_property_add_bool(obj, "realized",
+ device_get_realized, device_set_realized, NULL);
+
class = object_get_class(OBJECT(dev));
do {
for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
@@ -707,7 +752,10 @@ static void qdev_remove_from_bus(Object *obj)
static void device_class_init(ObjectClass *class, void *data)
{
+ DeviceClass *dc = DEVICE_CLASS(class);
+
class->unparent = qdev_remove_from_bus;
+ dc->realize = device_realize;
}
void device_reset(DeviceState *dev)
@@ -730,7 +778,7 @@ Object *qdev_get_machine(void)
return dev;
}
-static TypeInfo device_type_info = {
+static const TypeInfo device_type_info = {
.name = TYPE_DEVICE,
.parent = TYPE_OBJECT,
.instance_size = sizeof(DeviceState),
--
1.7.10.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/2] qdev: Prepare "realized" property
2013-01-06 18:48 ` [Qemu-devel] [PATCH v2 2/2] qdev: Prepare "realized" property Andreas Färber
@ 2013-01-07 13:52 ` Eduardo Habkost
0 siblings, 0 replies; 4+ messages in thread
From: Eduardo Habkost @ 2013-01-07 13:52 UTC (permalink / raw)
To: Andreas Färber; +Cc: pbonzini, qemu-devel, anthony
On Sun, Jan 06, 2013 at 07:48:42PM +0100, Andreas Färber wrote:
> Based on earlier patches by Paolo and me, introduce the QOM realizefn at
> device level only, as requested by Anthony.
>
> For now this just wraps the qdev initfn, which it deprecates.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> Cc: Anthony Liguori <anthony@codemonkey.ws>
> ---
> hw/qdev-core.h | 4 +++
> hw/qdev.c | 96 ++++++++++++++++++++++++++++++++++++++++++--------------
> 2 Dateien geändert, 76 Zeilen hinzugefügt(+), 24 Zeilen entfernt(-)
>
> diff --git a/hw/qdev-core.h b/hw/qdev-core.h
> index 5836e35..e50c866 100644
> --- a/hw/qdev-core.h
> +++ b/hw/qdev-core.h
> @@ -20,6 +20,8 @@ enum {
> typedef int (*qdev_initfn)(DeviceState *dev);
> typedef int (*qdev_event)(DeviceState *dev);
> typedef void (*qdev_resetfn)(DeviceState *dev);
> +typedef void (*DeviceRealize)(DeviceState *dev, Error **err);
> +typedef void (*DeviceUnrealize)(DeviceState *dev, Error **err);
>
> struct VMStateDescription;
>
> @@ -38,6 +40,8 @@ typedef struct DeviceClass {
> const struct VMStateDescription *vmsd;
>
> /* Private to qdev / bus. */
> + DeviceRealize realize;
> + DeviceUnrealize unrealize;
> qdev_initfn init;
Can we get the semantics of the realize/unrealize/init functions
documented here? For example, explicitly document that subclasses are
supposed to call the parent's realize function (this is the case,
right?), and the differences between DeviceState.init and
DeviceState.realize.
I took some time to understand the reason for DeviceState.realize to
exist when we already have DeviceState.init, and I am sure I already
forgot half of the explanation, and I will forget it completely in 1 or
2 months. :-)
> [...]
--
Eduardo
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-01-07 13:50 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-06 18:48 [Qemu-devel] [PATCH v2 0/2] QOM realize, device-only Andreas Färber
2013-01-06 18:48 ` [Qemu-devel] [PATCH v2 1/2] qdev: Fold state enum into bool realized Andreas Färber
2013-01-06 18:48 ` [Qemu-devel] [PATCH v2 2/2] qdev: Prepare "realized" property Andreas Färber
2013-01-07 13:52 ` Eduardo Habkost
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).