* [RFC 0/7] qom: deprecate embedded objects and instance properties
@ 2026-06-16 15:55 Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 1/7] meson: add --enable-deprecations configure flag Daniel P. Berrangé
` (7 more replies)
0 siblings, 8 replies; 14+ messages in thread
From: Daniel P. Berrangé @ 2026-06-16 15:55 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Pierrick Bouvier, Peter Xu,
Hervé Poussineau, Alex Bennée, Michael S. Tsirkin,
Akihiko Odaki, Daniel P. Berrangé, Aurelien Jarno,
Fabiano Rosas, Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
QOM has two rather unusual / surprising features historicall
* The ability to embed a QOM instance's memory inside another
struct
* The ability to register properties against the instnce
instead of struct
While they both look convenient on the surface, they also
have significant undesirable side effects (see the commit
message for each patch for details).
The premise of this series is that their convenience does
not outweigh their downsides, and we would be better off
long term by eliminating their usage, rather than trying
to add more hacks on top to mitigate their downsides.
This comes out of two separate conversations this week
* Migration series where Peter proposed changes that
make use of instance properties. When I commented,
Peter rightly pointed out that our docs do not
discourage use of instance properties:
https://lists.gnu.org/archive/html/qemu-devel/2026-06/msg02368.html
* QOM series where Akihiko proposed some funky hacks
to reference counting to better track object lifecycle
when embedding structs. We had a short discussion about
discouraging QOM embedding, so this is a real world
proposal:
https://lists.gnu.org/archive/html/qemu-devel/2026-06/msg03459.html
This is not likely to be a quick task, so this series
starts small
* Adds a "QEMU_DEPRECATIONS" annotation for internal APIs
* Deprecate the QOM instance embedding
* Deprecate the QOM instance properties
* Deprecate the memory region embedding APIs
* Deprecate the IRQ embedding APIs
* Convert PIIX to eliminate embedding as a
demonstration.
The QEMU_DEPRECATIONS idea is an effect to improve our our
historic practice where we introduce a new preferred API
and never really tell anyone the old APIs is bad to use.
If --enable-deprecations is given to configure, every use
of a deprecated API emits a compiler warning. This is not
enabled by default in this series, since we have -Werror
by default.
Note that the proposal to stop embedding memory regions has
been made by Zoltan earlier this year and was rejected by Paolo:
https://lists.nongnu.org/archive/html/qemu-devel/2026-01/msg05435.html
https://lists.nongnu.org/archive/html/qemu-devel/2026-05/msg06665.html
I don't really agree with the analysis there. IMHO, the
concept of embedding objects is to horrendous to allow to
live any longer. Yes, that's a big job, but long term it
is worth it.
Daniel P. Berrangé (7):
meson: add --enable-deprecations configure flag
qom: deprecated embedding object structs within other objects
qom: deprecate use of instance properties
system: add memory_region_new / memory_region_new_io
system: add qemu_irq_new / qemu_irq_new_child / qemu_irq_new_array
hw/isa: convert PIIX embedded QOM objects to heap allocated
qom: improve error message for invalid ID values
hw/core/irq.c | 35 +++++++++++++
hw/isa/piix.c | 65 ++++++++++++++---------
include/hw/core/irq.h | 75 +++++++++++++++++++++++++--
include/hw/southbridge/piix.h | 12 ++---
include/qemu/osdep.h | 19 +++++++
include/qom/object.h | 98 ++++++++++++++++++++++++++++++-----
include/system/memory.h | 76 +++++++++++++++++++++++----
meson.build | 1 +
meson_options.txt | 2 +
qom/object.c | 36 ++++++++++++-
scripts/meson-buildoptions.sh | 3 ++
system/memory.c | 85 +++++++++++++++++++++++++-----
12 files changed, 433 insertions(+), 74 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC 1/7] meson: add --enable-deprecations configure flag
2026-06-16 15:55 [RFC 0/7] qom: deprecate embedded objects and instance properties Daniel P. Berrangé
@ 2026-06-16 15:55 ` Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 2/7] qom: deprecated embedding object structs within other objects Daniel P. Berrangé
` (6 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Daniel P. Berrangé @ 2026-06-16 15:55 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Pierrick Bouvier, Peter Xu,
Hervé Poussineau, Alex Bennée, Michael S. Tsirkin,
Akihiko Odaki, Daniel P. Berrangé, Aurelien Jarno,
Fabiano Rosas, Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
A challenge with QEMU is that internal APIs get obsoleted but chasing
down use of old APIs is not as simple as it should be. Introduce a
--enable-deprecations configure flag which expands the macro
"QEMU_DEPRECATIONS" into "G_GNUC_DEPRECATED". This will trigger a
compiler warning for any use of the deprecated APIs.
It would generally be a good idea to disable -Werror when turning on
deprecations otherwise the build will quickly abort.
XXX: possibly add -Wno-error=deprecated-declarations, so we have
show deprecations by default despite -Werror being on by default.
This would trigger very many warnings but might be worth it if we
want to strongly nudge maintainers to convert existing code. Our
historical approach of "hope" has never worked to eliminate old
code patterns.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
include/qemu/osdep.h | 19 +++++++++++++++++++
meson.build | 1 +
meson_options.txt | 2 ++
scripts/meson-buildoptions.sh | 3 +++
4 files changed, 25 insertions(+)
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 2f0e61ad6b..99b8f9cbb7 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -447,6 +447,25 @@ void QEMU_ERROR("code path is reachable")
((void)0))
#endif
+/*
+ * Tag an internal APIs which should no longer be used
+ * to emit a warning during build if --enable-deprecations
+ * is used with configure. Use of -Werror will trigger
+ * immediate build failure if this is used.
+ */
+#ifdef CONFIG_DEPRECATIONS
+# define QEMU_DEPRECATED G_GNUC_DEPRECATED
+# define QEMU_DEPRECATIONS_OFF \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+# define QEMU_DEPRECATIONS_ON \
+ _Pragma("GCC diagnostic pop")
+#else
+# define QEMU_DEPRECATED
+# define QEMU_DEPRECATIONS_OFF
+# define QEMU_DEPRECATIONS_ON
+#endif
+
/*
* Minimum function that returns zero only if both values are zero.
* Intended for use with unsigned values only.
diff --git a/meson.build b/meson.build
index 19e123423b..9e863aa897 100644
--- a/meson.build
+++ b/meson.build
@@ -2567,6 +2567,7 @@ config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage')
config_host_data.set('CONFIG_DEBUG_TCG', get_option('debug_tcg'))
config_host_data.set('CONFIG_DEBUG_REMAP', get_option('debug_remap'))
config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
+config_host_data.set('CONFIG_DEPRECATIONS', get_option('deprecations'))
config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
config_host_data.set('CONFIG_FSFREEZE', qga_fsfreeze)
config_host_data.set('CONFIG_FSTRIM', qga_fstrim)
diff --git a/meson_options.txt b/meson_options.txt
index a07cb47d35..8f5924422d 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -367,6 +367,8 @@ option('qom_cast_debug', type: 'boolean', value: true,
description: 'cast debugging support')
option('slirp_smbd', type : 'feature', value : 'auto',
description: 'use smbd (at path --smbd=*) in slirp networking')
+option('deprecations', type: 'boolean', value: true,
+ description: 'enable internal API deprecation warnings')
option('qemu_ga_manufacturer', type: 'string', value: 'QEMU',
description: '"manufacturer" name for qemu-ga registry entries')
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index c003985047..fb57f0610d 100644
--- a/scripts/meson-buildoptions.sh
+++ b/scripts/meson-buildoptions.sh
@@ -13,6 +13,7 @@ meson_options_help() {
printf "%s\n" ' --datadir=VALUE Data file directory [share]'
printf "%s\n" ' --disable-coroutine-pool coroutine freelist (better performance)'
printf "%s\n" ' --disable-debug-info Enable debug symbols and other information'
+ printf "%s\n" ' --disable-deprecations enable internal API deprecation warnings'
printf "%s\n" ' --disable-hexagon-idef-parser'
printf "%s\n" ' use idef-parser to automatically generate TCG'
printf "%s\n" ' code for the Hexagon frontend'
@@ -306,6 +307,8 @@ _meson_option_parse() {
--disable-debug-stack-usage) printf "%s" -Ddebug_stack_usage=false ;;
--enable-debug-tcg) printf "%s" -Ddebug_tcg=true ;;
--disable-debug-tcg) printf "%s" -Ddebug_tcg=false ;;
+ --enable-deprecations) printf "%s" -Ddeprecations=true ;;
+ --disable-deprecations) printf "%s" -Ddeprecations=false ;;
--enable-dmg) printf "%s" -Ddmg=enabled ;;
--disable-dmg) printf "%s" -Ddmg=disabled ;;
--docdir=*) quote_sh "-Ddocdir=$2" ;;
--
2.54.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC 2/7] qom: deprecated embedding object structs within other objects
2026-06-16 15:55 [RFC 0/7] qom: deprecate embedded objects and instance properties Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 1/7] meson: add --enable-deprecations configure flag Daniel P. Berrangé
@ 2026-06-16 15:55 ` Daniel P. Berrangé
2026-06-16 16:15 ` Peter Maydell
2026-06-16 15:55 ` [RFC 3/7] qom: deprecate use of instance properties Daniel P. Berrangé
` (5 subsequent siblings)
7 siblings, 1 reply; 14+ messages in thread
From: Daniel P. Berrangé @ 2026-06-16 15:55 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Pierrick Bouvier, Peter Xu,
Hervé Poussineau, Alex Bennée, Michael S. Tsirkin,
Akihiko Odaki, Daniel P. Berrangé, Aurelien Jarno,
Fabiano Rosas, Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
The QOM APIs currently allow objects to be either allocated directly
on the heap, or statically embedded inside the struct of another object.
For the latter QOM has logic to avoid calling 'free' on the object when
finalizers complete, however, this is not sufficient to make the
practice safe.
Users of QOM expect that if they call "object_ref" to acquire their own
reference, then object will never be freed as long as they hold it.
This expectation is broken when an instance is embedded, as the "owner"
object's may be finalized, which frees the memory that is storing the
embedded QOM instance, even if its ref-count is still live.
Worse still is that a user of a QOM object cannot easily tell if the
instance they're using is embedded or directly heap allocated.
Mark the APIs for embedding objects as deprecated as the first step
towards removal of this flawed design concept. All objects must now
be directly heap allocated going forward, and existing usage must be
incrementally converted.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
include/qom/object.h | 28 ++++++++++++++++++++++++----
qom/object.c | 6 ++++++
2 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/include/qom/object.h b/include/qom/object.h
index 11f55613fc..dd708b1136 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -854,8 +854,13 @@ bool object_set_props_from_keyval(Object *obj, const QDict *qdict,
* This function will initialize an object. The memory for the object should
* have already been allocated. The returned object has a reference count of 1,
* and will be finalized when the last reference is dropped.
+ *
+ * Use of this function is now deprecated. All objects must be
+ * allocated using the object_new() family of functions and not
+ * statically embedded in a larger struct.
*/
-void object_initialize(void *obj, size_t size, const char *typename);
+void object_initialize(void *obj, size_t size, const char *typename)
+ QEMU_DEPRECATED;
/**
* object_initialize_child_with_props:
@@ -873,6 +878,10 @@ void object_initialize(void *obj, size_t size, const char *typename);
* has a reference count of 1 (for the "child<...>" property from the parent),
* so the object will be finalized automatically when the parent gets removed.
*
+ * Use of this function is now deprecated. All objects must be
+ * allocated using the object_new() family of functions and not
+ * statically embedded in a larger struct.
+ *
* The variadic parameters are a list of pairs of (propname, propvalue)
* strings. The propname of %NULL indicates the end of the property list.
* If the object implements the user creatable interface, the object will
@@ -883,7 +892,8 @@ void object_initialize(void *obj, size_t size, const char *typename);
bool object_initialize_child_with_props(Object *parentobj,
const char *propname,
void *childobj, size_t size, const char *type,
- Error **errp, ...) G_GNUC_NULL_TERMINATED;
+ Error **errp, ...) G_GNUC_NULL_TERMINATED
+ QEMU_DEPRECATED;
/**
* object_initialize_child_with_propsv:
@@ -897,12 +907,17 @@ bool object_initialize_child_with_props(Object *parentobj,
*
* See object_initialize_child() for documentation.
*
+ * Use of this function is now deprecated. All objects must be
+ * allocated using the object_new() family of functions and not
+ * statically embedded in a larger struct.
+ *
* Returns: %true on success, %false on failure.
*/
bool object_initialize_child_with_propsv(Object *parentobj,
const char *propname,
void *childobj, size_t size, const char *type,
- Error **errp, va_list vargs);
+ Error **errp, va_list vargs)
+ QEMU_DEPRECATED;
/**
* object_initialize_child:
@@ -917,13 +932,18 @@ bool object_initialize_child_with_propsv(Object *parentobj,
* object_initialize_child_with_props(parent, propname,
* child, sizeof(*child), type,
* &error_abort, NULL)
+ *
+ * Use of this function is now deprecated. All objects must be
+ * allocated using the object_new() family of functions and not
+ * statically embedded in a larger struct.
*/
#define object_initialize_child(parent, propname, child, type) \
object_initialize_child_internal((parent), (propname), \
(child), sizeof(*(child)), (type))
void object_initialize_child_internal(Object *parent, const char *propname,
void *child, size_t size,
- const char *type);
+ const char *type)
+ QEMU_DEPRECATED;
/**
* object_dynamic_cast:
diff --git a/qom/object.c b/qom/object.c
index 0ac201de4c..33b2801ee4 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -522,9 +522,11 @@ bool object_initialize_child_with_props(Object *parentobj,
bool ok;
va_start(vargs, errp);
+QEMU_DEPRECATIONS_OFF;
ok = object_initialize_child_with_propsv(parentobj, propname,
childobj, size, type, errp,
vargs);
+QEMU_DEPRECATIONS_ON;
va_end(vargs);
return ok;
}
@@ -539,7 +541,9 @@ bool object_initialize_child_with_propsv(Object *parentobj,
Object *obj;
UserCreatable *uc;
+QEMU_DEPRECATIONS_OFF;
object_initialize(childobj, size, type);
+QEMU_DEPRECATIONS_ON;
obj = OBJECT(childobj);
if (!object_set_propv(obj, vargs, errp)) {
@@ -576,8 +580,10 @@ void object_initialize_child_internal(Object *parent,
void *child, size_t size,
const char *type)
{
+QEMU_DEPRECATIONS_OFF;
object_initialize_child_with_props(parent, propname, child, size, type,
&error_abort, NULL);
+QEMU_DEPRECATIONS_ON;
}
static inline bool object_property_is_child(ObjectProperty *prop)
--
2.54.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC 3/7] qom: deprecate use of instance properties
2026-06-16 15:55 [RFC 0/7] qom: deprecate embedded objects and instance properties Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 1/7] meson: add --enable-deprecations configure flag Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 2/7] qom: deprecated embedding object structs within other objects Daniel P. Berrangé
@ 2026-06-16 15:55 ` Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 4/7] system: add memory_region_new / memory_region_new_io Daniel P. Berrangé
` (4 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Daniel P. Berrangé @ 2026-06-16 15:55 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Pierrick Bouvier, Peter Xu,
Hervé Poussineau, Alex Bennée, Michael S. Tsirkin,
Akihiko Odaki, Daniel P. Berrangé, Aurelien Jarno,
Fabiano Rosas, Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
The concept of class properties was introduced over 10 years ago.
While there is significant use of class properties, there is a
long way to go before any conversion is complete and new uses are
often introduced as it is not obvious that class properties are
preferred.
The downsides of instances properties are:
* Increased memory usage as the property info is duplicated
across every instance.
* Introspection side effects, since instances need to be created
to be introspected and this can have unexpected side effects
if code is not expecting these throwaway instances to be
around.
* Non-introspectable designs, if properties are conditionally
registered against instances, those props may not be visible
when a dummy instances is created for introspection.
This deprecates the use of instance properties for all regular
scalar properties. ie strings, integers, enums, etc.
It does not deprecate instance properties used for setting up
the QOM composition tree child relationships, nor the link or
alias properties.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
include/qom/object.h | 70 +++++++++++++++++++++++++++++++++++++-------
qom/object.c | 28 ++++++++++++++++++
2 files changed, 88 insertions(+), 10 deletions(-)
diff --git a/include/qom/object.h b/include/qom/object.h
index dd708b1136..e9ce15d595 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -1175,6 +1175,10 @@ void object_unref(void *obj);
* @opaque: an opaque pointer to pass to the callbacks for the property
* @errp: pointer to error object
*
+ * Use of this function is now deprecated. All properties must be
+ * registered against the class, using the object_class_property_add()
+ * function and not registered against instances.
+ *
* Returns: The #ObjectProperty; this can be used to set the @resolve
* callback for child and link properties.
*/
@@ -1183,7 +1187,8 @@ ObjectProperty *object_property_try_add(Object *obj, const char *name,
ObjectPropertyAccessor *get,
ObjectPropertyAccessor *set,
ObjectPropertyRelease *release,
- void *opaque, Error **errp);
+ void *opaque, Error **errp)
+ QEMU_DEPRECATED;
/**
* object_property_add:
@@ -1206,13 +1211,18 @@ ObjectProperty *object_property_try_add(Object *obj, const char *name,
* meant to allow a property to free its opaque upon object
* destruction. This may be NULL.
* @opaque: an opaque pointer to pass to the callbacks for the property
+ *
+ * Use of this function is now deprecated. All properties must be
+ * registered against the class, using the object_class_property_add()
+ * function and not registered against instances.
*/
ObjectProperty *object_property_add(Object *obj, const char *name,
const char *type,
ObjectPropertyAccessor *get,
ObjectPropertyAccessor *set,
ObjectPropertyRelease *release,
- void *opaque);
+ void *opaque)
+ QEMU_DEPRECATED;
void object_property_del(Object *obj, const char *name);
@@ -1873,11 +1883,16 @@ Object *object_resolve_and_typecheck(const char *path, const char *name,
* Add a string property using getters/setters. This function will add a
* property of type 'string'.
*
+ * Use of this function is now deprecated. All properties must be
+ * registered against the class, using the object_class_property_add_str()
+ * function and not registered against instances.
+ *
* Returns: The newly added property on success, or %NULL on failure.
*/
ObjectProperty *object_property_add_str(Object *obj, const char *name,
char *(*get)(Object *, Error **),
- void (*set)(Object *, const char *, Error **));
+ void (*set)(Object *, const char *, Error **))
+ QEMU_DEPRECATED;
ObjectProperty *object_class_property_add_str(ObjectClass *klass,
const char *name,
@@ -1895,11 +1910,16 @@ ObjectProperty *object_class_property_add_str(ObjectClass *klass,
* Add a bool property using getters/setters. This function will add a
* property of type 'bool'.
*
+ * Use of this function is now deprecated. All properties must be
+ * registered against the class, using the object_class_property_add_bool()
+ * function and not registered against instances.
+ *
* Returns: The newly added property on success, or %NULL on failure.
*/
ObjectProperty *object_property_add_bool(Object *obj, const char *name,
bool (*get)(Object *, Error **),
- void (*set)(Object *, bool, Error **));
+ void (*set)(Object *, bool, Error **))
+ QEMU_DEPRECATED;
ObjectProperty *object_class_property_add_bool(ObjectClass *klass,
const char *name,
@@ -1918,13 +1938,18 @@ ObjectProperty *object_class_property_add_bool(ObjectClass *klass,
* Add an enum property using getters/setters. This function will add a
* property of type '@typename'.
*
+ * Use of this function is now deprecated. All properties must be
+ * registered against the class, using the object_class_property_add_enum()
+ * function and not registered against instances.
+ *
* Returns: The newly added property on success, or %NULL on failure.
*/
ObjectProperty *object_property_add_enum(Object *obj, const char *name,
const char *typename,
const QEnumLookup *lookup,
int (*get)(Object *, Error **),
- void (*set)(Object *, int, Error **));
+ void (*set)(Object *, int, Error **))
+ QEMU_DEPRECATED;
ObjectProperty *object_class_property_add_enum(ObjectClass *klass,
const char *name,
@@ -1942,10 +1967,15 @@ ObjectProperty *object_class_property_add_enum(ObjectClass *klass,
* Add a read-only struct tm valued property using a getter function.
* This function will add a property of type 'struct tm'.
*
+ * Use of this function is now deprecated. All properties must be
+ * registered against the class, using the object_class_property_add_tm()
+ * function and not registered against instances.
+ *
* Returns: The newly added property on success, or %NULL on failure.
*/
ObjectProperty *object_property_add_tm(Object *obj, const char *name,
- void (*get)(Object *, struct tm *, Error **));
+ void (*get)(Object *, struct tm *, Error **))
+ QEMU_DEPRECATED;
ObjectProperty *object_class_property_add_tm(ObjectClass *klass,
const char *name,
@@ -1970,11 +2000,16 @@ typedef enum {
* Add an integer property in memory. This function will add a
* property of type 'uint8'.
*
+ * Use of this function is now deprecated. All properties must be
+ * registered against the class, using the object_class_property_add_uint8_ptr()
+ * function and not registered against instances.
+ *
* Returns: The newly added property on success, or %NULL on failure.
*/
ObjectProperty *object_property_add_uint8_ptr(Object *obj, const char *name,
const uint8_t *v,
- ObjectPropertyFlags flags);
+ ObjectPropertyFlags flags)
+ QEMU_DEPRECATED;
ObjectProperty *object_class_property_add_uint8_ptr(ObjectClass *klass,
const char *name,
@@ -1991,11 +2026,16 @@ ObjectProperty *object_class_property_add_uint8_ptr(ObjectClass *klass,
* Add an integer property in memory. This function will add a
* property of type 'uint16'.
*
+ * Use of this function is now deprecated. All properties must be
+ * registered against the class, using the object_class_property_add_uint16_ptr()
+ * function and not registered against instances.
+ *
* Returns: The newly added property on success, or %NULL on failure.
*/
ObjectProperty *object_property_add_uint16_ptr(Object *obj, const char *name,
const uint16_t *v,
- ObjectPropertyFlags flags);
+ ObjectPropertyFlags flags)
+ QEMU_DEPRECATED;
ObjectProperty *object_class_property_add_uint16_ptr(ObjectClass *klass,
const char *name,
@@ -2012,11 +2052,16 @@ ObjectProperty *object_class_property_add_uint16_ptr(ObjectClass *klass,
* Add an integer property in memory. This function will add a
* property of type 'uint32'.
*
+ * Use of this function is now deprecated. All properties must be
+ * registered against the class, using the object_class_property_add_uint32_ptr()
+ * function and not registered against instances.
+ *
* Returns: The newly added property on success, or %NULL on failure.
*/
ObjectProperty *object_property_add_uint32_ptr(Object *obj, const char *name,
const uint32_t *v,
- ObjectPropertyFlags flags);
+ ObjectPropertyFlags flags)
+ QEMU_DEPRECATED;
ObjectProperty *object_class_property_add_uint32_ptr(ObjectClass *klass,
const char *name,
@@ -2033,11 +2078,16 @@ ObjectProperty *object_class_property_add_uint32_ptr(ObjectClass *klass,
* Add an integer property in memory. This function will add a
* property of type 'uint64'.
*
+ * Use of this function is now deprecated. All properties must be
+ * registered against the class, using the object_class_property_add_uint64_ptr()
+ * function and not registered against instances.
+ *
* Returns: The newly added property on success, or %NULL on failure.
*/
ObjectProperty *object_property_add_uint64_ptr(Object *obj, const char *name,
const uint64_t *v,
- ObjectPropertyFlags flags);
+ ObjectPropertyFlags flags)
+ QEMU_DEPRECATED;
ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass,
const char *name,
diff --git a/qom/object.c b/qom/object.c
index 33b2801ee4..415d5c5291 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1362,8 +1362,10 @@ object_property_try_add(Object *obj, const char *name, const char *type,
for (i = 0; i < INT16_MAX; ++i) {
char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
+ QEMU_DEPRECATIONS_OFF;
ret = object_property_try_add(obj, full_name, type, get, set,
release, opaque, NULL);
+ QEMU_DEPRECATIONS_ON;
g_free(full_name);
if (ret) {
break;
@@ -1403,8 +1405,10 @@ object_property_add(Object *obj, const char *name, const char *type,
ObjectPropertyRelease *release,
void *opaque)
{
+ QEMU_DEPRECATIONS_OFF;
return object_property_try_add(obj, name, type, get, set, release,
opaque, &error_abort);
+ QEMU_DEPRECATIONS_ON;
}
ObjectProperty *
@@ -1951,9 +1955,11 @@ object_property_try_add_child(Object *obj, const char *name,
type = g_strdup_printf("child<%s>", object_get_typename(child));
+ QEMU_DEPRECATIONS_OFF;
op = object_property_try_add(obj, name, type, object_get_child_property,
NULL, object_finalize_child_property,
child, errp);
+ QEMU_DEPRECATIONS_ON;
if (!op) {
return NULL;
}
@@ -1967,7 +1973,9 @@ ObjectProperty *
object_property_add_child(Object *obj, const char *name,
Object *child)
{
+ QEMU_DEPRECATIONS_OFF;
return object_property_try_add_child(obj, name, child, &error_abort);
+ QEMU_DEPRECATIONS_ON;
}
void object_property_allow_set_link(const Object *obj, const char *name,
@@ -2145,11 +2153,13 @@ object_add_link_prop(Object *obj, const char *name,
full_type = g_strdup_printf("link<%s>", type);
+ QEMU_DEPRECATIONS_OFF;
op = object_property_add(obj, name, full_type,
object_get_link_property,
check ? object_set_link_property : NULL,
object_release_link_property,
prop);
+ QEMU_DEPRECATIONS_ON;
op->resolve = object_resolve_link_property;
return op;
}
@@ -2442,11 +2452,13 @@ object_property_add_str(Object *obj, const char *name,
prop->get = get;
prop->set = set;
+ QEMU_DEPRECATIONS_OFF;
return object_property_add(obj, name, "string",
get ? property_get_str : NULL,
set ? property_set_str : NULL,
property_release_data,
prop);
+ QEMU_DEPRECATIONS_ON;
}
ObjectProperty *
@@ -2512,11 +2524,13 @@ object_property_add_bool(Object *obj, const char *name,
prop->get = get;
prop->set = set;
+ QEMU_DEPRECATIONS_OFF;
return object_property_add(obj, name, "bool",
get ? property_get_bool : NULL,
set ? property_set_bool : NULL,
property_release_data,
prop);
+ QEMU_DEPRECATIONS_ON;
}
ObjectProperty *
@@ -2577,11 +2591,13 @@ object_property_add_enum(Object *obj, const char *name,
prop->get = get;
prop->set = set;
+ QEMU_DEPRECATIONS_OFF;
return object_property_add(obj, name, typename,
get ? property_get_enum : NULL,
set ? property_set_enum : NULL,
property_release_data,
prop);
+ QEMU_DEPRECATIONS_ON;
}
ObjectProperty *
@@ -2655,10 +2671,12 @@ object_property_add_tm(Object *obj, const char *name,
prop->get = get;
+ QEMU_DEPRECATIONS_OFF;
return object_property_add(obj, name, "struct tm",
get ? property_get_tm : NULL, NULL,
property_release_data,
prop);
+ QEMU_DEPRECATIONS_ON;
}
ObjectProperty *
@@ -2775,8 +2793,10 @@ object_property_add_uint8_ptr(Object *obj, const char *name,
setter = property_set_uint8_ptr;
}
+ QEMU_DEPRECATIONS_OFF;
return object_property_add(obj, name, "uint8",
getter, setter, NULL, (void *)v);
+ QEMU_DEPRECATIONS_ON;
}
ObjectProperty *
@@ -2815,8 +2835,10 @@ object_property_add_uint16_ptr(Object *obj, const char *name,
setter = property_set_uint16_ptr;
}
+ QEMU_DEPRECATIONS_OFF;
return object_property_add(obj, name, "uint16",
getter, setter, NULL, (void *)v);
+ QEMU_DEPRECATIONS_ON;
}
ObjectProperty *
@@ -2855,8 +2877,10 @@ object_property_add_uint32_ptr(Object *obj, const char *name,
setter = property_set_uint32_ptr;
}
+ QEMU_DEPRECATIONS_OFF;
return object_property_add(obj, name, "uint32",
getter, setter, NULL, (void *)v);
+ QEMU_DEPRECATIONS_ON;
}
ObjectProperty *
@@ -2895,8 +2919,10 @@ object_property_add_uint64_ptr(Object *obj, const char *name,
setter = property_set_uint64_ptr;
}
+ QEMU_DEPRECATIONS_OFF;
return object_property_add(obj, name, "uint64",
getter, setter, NULL, (void *)v);
+ QEMU_DEPRECATIONS_ON;
}
ObjectProperty *
@@ -2983,11 +3009,13 @@ object_property_add_alias(Object *obj, const char *name,
prop->target_obj = target_obj;
prop->target_name = g_strdup(target_name);
+ QEMU_DEPRECATIONS_OFF;
op = object_property_add(obj, name, prop_type,
property_get_alias,
property_set_alias,
property_release_alias,
prop);
+ QEMU_DEPRECATIONS_ON;
op->resolve = property_resolve_alias;
if (target_prop->defval) {
op->defval = qobject_ref(target_prop->defval);
--
2.54.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC 4/7] system: add memory_region_new / memory_region_new_io
2026-06-16 15:55 [RFC 0/7] qom: deprecate embedded objects and instance properties Daniel P. Berrangé
` (2 preceding siblings ...)
2026-06-16 15:55 ` [RFC 3/7] qom: deprecate use of instance properties Daniel P. Berrangé
@ 2026-06-16 15:55 ` Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 5/7] system: add qemu_irq_new / qemu_irq_new_child / qemu_irq_new_array Daniel P. Berrangé
` (3 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Daniel P. Berrangé @ 2026-06-16 15:55 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Pierrick Bouvier, Peter Xu,
Hervé Poussineau, Alex Bennée, Michael S. Tsirkin,
Akihiko Odaki, Daniel P. Berrangé, Aurelien Jarno,
Fabiano Rosas, Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
Prepare for the move to dynamically allocated memory regions by
introducing memory_region_new and memory_region_new_io functions
which call through to object_new instead of object_initialize.
TBD: add "new" variants for all the other memory_region_init
variants.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
include/system/memory.h | 76 ++++++++++++++++++++++++++++++------
system/memory.c | 85 ++++++++++++++++++++++++++++++++++-------
2 files changed, 136 insertions(+), 25 deletions(-)
diff --git a/include/system/memory.h b/include/system/memory.h
index 1417132f6d..b4c5a185c0 100644
--- a/include/system/memory.h
+++ b/include/system/memory.h
@@ -1300,19 +1300,44 @@ static inline bool memory_region_section_intersect_range(MemoryRegionSection *s,
/**
* memory_region_init: Initialize a memory region
- *
- * The region typically acts as a container for other memory regions. Use
- * memory_region_add_subregion() to add subregions.
- *
* @mr: the #MemoryRegion to be initialized
* @owner: the object that tracks the region's reference count
* @name: used for debugging; not visible to the user or ABI
* @size: size of the region; any subregions beyond this size will be clipped
+ *
+ * The region typically acts as a container for other memory regions. Use
+ * memory_region_add_subregion() to add subregions.
+ *
+ * Use of this function is now deprecated. All memory regions must be
+ * allocated using the memory_region_new() family of functions and not
+ * statically embedded in a larger struct.
*/
void memory_region_init(MemoryRegion *mr,
Object *owner,
const char *name,
- uint64_t size);
+ uint64_t size)
+ QEMU_DEPRECATED;
+
+
+/**
+ * memory_region_new: Allocate a memory region.
+ * @owner: the object that owns the memory region in the composition tree
+ * @name: used for debugging; not visible to the user or ABI
+ * @size: size of the region; any subregions beyond this size will be clipped
+ *
+ * The region typically acts as a container for other memory regions. Use
+ * memory_region_add_subregion() to add subregions.
+ *
+ * The returned memory region will have a single reference, which is
+ * held by the @owner object in the QOM composition tree. Thus in the
+ * absence of any further references being acquired, the memory region
+ * will be freed when @owner is freed
+ *
+ * Returns: the newly allocated memory region
+ */
+MemoryRegion *memory_region_new(Object *owner,
+ const char *name,
+ uint64_t size);
/**
* memory_region_ref: Add 1 to a memory region's reference count
@@ -1344,11 +1369,7 @@ void memory_region_ref(MemoryRegion *mr);
void memory_region_unref(MemoryRegion *mr);
/**
- * memory_region_init_io: Initialize an I/O memory region.
- *
- * Accesses into the region will cause the callbacks in @ops to be called.
- * if @size is nonzero, subregions will be clipped to @size.
- *
+ * memory_region_init_io: Initialize an I/O memory region
* @mr: the #MemoryRegion to be initialized.
* @owner: the object that tracks the region's reference count
* @ops: a structure containing read and write callbacks to be used when
@@ -1356,13 +1377,46 @@ void memory_region_unref(MemoryRegion *mr);
* @opaque: passed to the read and write callbacks of the @ops structure.
* @name: used for debugging; not visible to the user or ABI
* @size: size of the region.
+ *
+ * Accesses into the region will cause the callbacks in @ops to be called.
+ * if @size is nonzero, subregions will be clipped to @size.
+ *
+ * Use of this function is now deprecated. All memory regions must be
+ * allocated using the memory_region_new() family of functions and not
+ * statically embedded in a larger struct.
*/
void memory_region_init_io(MemoryRegion *mr,
Object *owner,
const MemoryRegionOps *ops,
void *opaque,
const char *name,
- uint64_t size);
+ uint64_t size)
+ QEMU_DEPRECATED;
+
+/**
+ * memory_region_new_io: Allocates an I/O memory region
+ * @owner: the object that tracks the region's reference count
+ * @ops: a structure containing read and write callbacks to be used when
+ * I/O is performed on the region.
+ * @opaque: passed to the read and write callbacks of the @ops structure.
+ * @name: used for debugging; not visible to the user or ABI
+ * @size: size of the region.
+ *
+ * Accesses into the region will cause the callbacks in @ops to be called.
+ * if @size is nonzero, subregions will be clipped to @size.
+ *
+ * The returned memory region will have a single reference, which is
+ * held by the @owner object in the QOM composition tree. Thus in the
+ * absence of any further references being acquired, the memory region
+ * will be freed when @owner is freed
+ *
+ * Returns: the newly allocated memory region
+ */
+MemoryRegion *memory_region_new_io(Object *owner,
+ const MemoryRegionOps *ops,
+ void *opaque,
+ const char *name,
+ uint64_t size);
/**
* memory_region_init_ram_flags_nomigrate: Initialize RAM memory region.
diff --git a/system/memory.c b/system/memory.c
index 739ba11da6..e8a539e37e 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -1214,6 +1214,18 @@ static char *memory_region_escape_name(const char *name)
return escaped;
}
+static char *memory_region_make_child(Object **owner,
+ const char *name)
+{
+ g_autofree char *escaped_name = memory_region_escape_name(name);
+
+ if (!*owner) {
+ *owner = machine_get_container("unattached");
+ }
+
+ return g_strdup_printf("%s[*]", escaped_name);
+}
+
static void memory_region_do_init(MemoryRegion *mr,
Object *owner,
const char *name,
@@ -1227,20 +1239,6 @@ static void memory_region_do_init(MemoryRegion *mr,
mr->owner = owner;
mr->dev = (DeviceState *) object_dynamic_cast(mr->owner, TYPE_DEVICE);
mr->ram_block = NULL;
-
- if (name) {
- char *escaped_name = memory_region_escape_name(name);
- char *name_array = g_strdup_printf("%s[*]", escaped_name);
-
- if (!owner) {
- owner = machine_get_container("unattached");
- }
-
- object_property_add_child(owner, name_array, OBJECT(mr));
- object_unref(OBJECT(mr));
- g_free(name_array);
- g_free(escaped_name);
- }
}
void memory_region_init(MemoryRegion *mr,
@@ -1250,6 +1248,31 @@ void memory_region_init(MemoryRegion *mr,
{
object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
memory_region_do_init(mr, owner, name, size);
+ if (name) {
+ g_autofree char *childname = memory_region_make_child(&owner, name);
+ object_property_add_child(owner, childname, OBJECT(mr));
+ object_unref(OBJECT(mr));
+ }
+}
+
+MemoryRegion *memory_region_new(Object *owner,
+ const char *name,
+ uint64_t size)
+{
+ /*
+ * error_abort is safe, because 'childname' includes a wildcard
+ * for dynamically assigning a unique name. Thus adding the child
+ * property cannot fail
+ */
+ MemoryRegion *mr = MEMORY_REGION(object_new(TYPE_MEMORY_REGION));
+ memory_region_do_init(mr, owner, name, size);
+ if (name) {
+ g_autofree char *childname = memory_region_make_child(&owner, name);
+ object_property_add_child(owner, childname, OBJECT(mr));
+ object_unref(OBJECT(mr));
+
+ }
+ return mr;
}
static void memory_region_get_container(Object *obj, Visitor *v,
@@ -1574,10 +1597,22 @@ void memory_region_init_io(MemoryRegion *mr, Object *owner,
const char *name, uint64_t size)
{
g_assert(!ops || !(ops->impl.unaligned && !ops->valid.unaligned));
+ QEMU_DEPRECATIONS_OFF;
memory_region_init(mr, owner, name, size);
+ QEMU_DEPRECATIONS_ON;
memory_region_set_ops(mr, ops, opaque);
}
+MemoryRegion *memory_region_new_io(Object *owner,
+ const MemoryRegionOps *ops, void *opaque,
+ const char *name, uint64_t size)
+{
+ g_assert(!ops || !(ops->impl.unaligned && !ops->valid.unaligned));
+ MemoryRegion *mr = memory_region_new(owner, name, size);
+ memory_region_set_ops(mr, ops, opaque);
+ return mr;
+}
+
static bool memory_region_set_ram_block(MemoryRegion *mr, RAMBlock *rb)
{
mr->terminates = true;
@@ -1597,7 +1632,9 @@ bool memory_region_init_ram_flags_nomigrate(MemoryRegion *mr, Object *owner,
{
RAMBlock *rb;
+ QEMU_DEPRECATIONS_OFF;
memory_region_init(mr, owner, name, size);
+ QEMU_DEPRECATIONS_ON;
mr->ram = true;
rb = qemu_ram_alloc(size, ram_flags, mr, errp);
return memory_region_set_ram_block(mr, rb);
@@ -1615,7 +1652,9 @@ bool memory_region_init_resizeable_ram(MemoryRegion *mr,
{
RAMBlock *rb;
+ QEMU_DEPRECATIONS_OFF;
memory_region_init(mr, owner, name, size);
+ QEMU_DEPRECATIONS_ON;
mr->ram = true;
rb = qemu_ram_alloc_resizeable(size, max_size, resized, mr, errp);
return memory_region_set_ram_block(mr, rb);
@@ -1630,7 +1669,9 @@ bool memory_region_init_ram_from_file(MemoryRegion *mr, Object *owner,
{
RAMBlock *rb;
+ QEMU_DEPRECATIONS_OFF;
memory_region_init(mr, owner, name, size);
+ QEMU_DEPRECATIONS_ON;
mr->ram = true;
mr->readonly = !!(ram_flags & RAM_READONLY);
mr->align = align;
@@ -1645,7 +1686,9 @@ bool memory_region_init_ram_from_fd(MemoryRegion *mr, Object *owner,
{
RAMBlock *rb;
+ QEMU_DEPRECATIONS_OFF;
memory_region_init(mr, owner, name, size);
+ QEMU_DEPRECATIONS_ON;
mr->ram = true;
mr->readonly = !!(ram_flags & RAM_READONLY);
rb = qemu_ram_alloc_from_fd(size, size, NULL, mr, ram_flags, fd, offset,
@@ -1667,7 +1710,9 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, Object *owner,
const char *name, uint64_t size,
void *ptr)
{
+ QEMU_DEPRECATIONS_OFF;
memory_region_init(mr, owner, name, size);
+ QEMU_DEPRECATIONS_ON;
mr->ram = true;
memory_region_set_ram_ptr(mr, size, ptr);
}
@@ -1676,7 +1721,9 @@ void memory_region_init_ram_device_ptr(MemoryRegion *mr, Object *owner,
const char *name, uint64_t size,
void *ptr)
{
+ QEMU_DEPRECATIONS_OFF;
memory_region_init_io(mr, owner, &ram_device_mem_ops, mr, name, size);
+ QEMU_DEPRECATIONS_ON;
mr->ram = true;
mr->ram_device = true;
memory_region_set_ram_ptr(mr, size, ptr);
@@ -1686,7 +1733,9 @@ void memory_region_init_alias(MemoryRegion *mr, Object *owner,
const char *name, MemoryRegion *orig,
hwaddr offset, uint64_t size)
{
+ QEMU_DEPRECATIONS_OFF;
memory_region_init(mr, owner, name, size);
+ QEMU_DEPRECATIONS_ON;
mr->alias = orig;
mr->alias_offset = offset;
}
@@ -1704,6 +1753,12 @@ void memory_region_init_iommu(void *_iommu_mr,
object_initialize(_iommu_mr, instance_size, mrtypename);
mr = MEMORY_REGION(_iommu_mr);
memory_region_do_init(mr, owner, name, size);
+ if (name) {
+ g_autofree char *childname = memory_region_make_child(&owner, name);
+ object_property_add_child(owner, childname, OBJECT(mr));
+ object_unref(OBJECT(mr));
+ }
+
iommu_mr = IOMMU_MEMORY_REGION(mr);
mr->terminates = true; /* then re-forwards */
QLIST_INIT(&iommu_mr->iommu_notify);
@@ -3703,7 +3758,9 @@ bool memory_region_init_rom_device(MemoryRegion *mr, Object *owner,
RAMBlock *rb;
assert(ops);
+ QEMU_DEPRECATIONS_OFF;
memory_region_init_io(mr, owner, ops, opaque, name, size);
+ QEMU_DEPRECATIONS_ON;
rb = qemu_ram_alloc(size, 0, mr, errp);
if (memory_region_set_ram_block(mr, rb)) {
mr->rom_device = true;
--
2.54.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC 5/7] system: add qemu_irq_new / qemu_irq_new_child / qemu_irq_new_array
2026-06-16 15:55 [RFC 0/7] qom: deprecate embedded objects and instance properties Daniel P. Berrangé
` (3 preceding siblings ...)
2026-06-16 15:55 ` [RFC 4/7] system: add memory_region_new / memory_region_new_io Daniel P. Berrangé
@ 2026-06-16 15:55 ` Daniel P. Berrangé
2026-06-16 16:22 ` Peter Maydell
2026-06-16 15:55 ` [RFC 6/7] hw/isa: convert PIIX embedded QOM objects to heap allocated Daniel P. Berrangé
` (2 subsequent siblings)
7 siblings, 1 reply; 14+ messages in thread
From: Daniel P. Berrangé @ 2026-06-16 15:55 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Pierrick Bouvier, Peter Xu,
Hervé Poussineau, Alex Bennée, Michael S. Tsirkin,
Akihiko Odaki, Daniel P. Berrangé, Aurelien Jarno,
Fabiano Rosas, Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
Prepare for the move to dynamically allocated IRQ objects by
introducing qemu_irq_new / qemu_irq_new_child / qemu_irq_new_array
functions which call through to object_new instead of object_initialize.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
hw/core/irq.c | 35 ++++++++++++++++++++
include/hw/core/irq.h | 75 ++++++++++++++++++++++++++++++++++++++++---
2 files changed, 106 insertions(+), 4 deletions(-)
diff --git a/hw/core/irq.c b/hw/core/irq.c
index 106805e241..e943c87b81 100644
--- a/hw/core/irq.c
+++ b/hw/core/irq.c
@@ -49,6 +49,13 @@ void qemu_init_irq(IRQState *irq, qemu_irq_handler handler, void *opaque,
init_irq_fields(irq, handler, opaque, n);
}
+IRQState *qemu_irq_new(qemu_irq_handler handler, void *opaque, int n)
+{
+ IRQState *irq = IRQ(object_new(TYPE_IRQ));
+ init_irq_fields(irq, handler, opaque, n);
+ return irq;
+}
+
void qemu_init_irq_child(Object *parent, const char *propname,
IRQState *irq, qemu_irq_handler handler,
void *opaque, int n)
@@ -57,14 +64,42 @@ void qemu_init_irq_child(Object *parent, const char *propname,
init_irq_fields(irq, handler, opaque, n);
}
+IRQState *qemu_irq_new_child(Object *parent, const char *propname,
+ qemu_irq_handler handler,
+ void *opaque, int n,
+ Error **errp)
+{
+ IRQState *irq = IRQ(object_new_with_props(TYPE_IRQ, parent, propname,
+ errp, NULL));
+ if (!irq) {
+ return NULL;
+ }
+ init_irq_fields(irq, handler, opaque, n);
+ return irq;
+}
+
+
void qemu_init_irqs(IRQState irq[], size_t count,
qemu_irq_handler handler, void *opaque)
{
for (size_t i = 0; i < count; i++) {
+ QEMU_DEPRECATIONS_OFF;
qemu_init_irq(&irq[i], handler, opaque, i);
+ QEMU_DEPRECATIONS_ON;
}
}
+IRQState **qemu_irq_new_array(size_t count,
+ qemu_irq_handler handler, void *opaque)
+{
+ IRQState **irqs = g_new0(IRQState *, count);
+ for (size_t i = 0; i < count; i++) {
+ irqs[i] = qemu_irq_new(handler, opaque, i);
+ }
+ return irqs;
+}
+
+
qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
void *opaque, int n)
{
diff --git a/include/hw/core/irq.h b/include/hw/core/irq.h
index 291fdd67df..af9bf6fb12 100644
--- a/include/hw/core/irq.h
+++ b/include/hw/core/irq.h
@@ -34,7 +34,12 @@ static inline void qemu_irq_pulse(qemu_irq irq)
qemu_set_irq(irq, 0);
}
-/*
+/**
+ * qemu_init_irq: Initialize IRQ
+ * @handler: handler function for incoming interrupts
+ * @opaque: opaque data to pass to @handler
+ * @n: interrupt number to pass to @handler
+ *
* Init a single IRQ. The irq is assigned with a handler, an opaque data
* and the interrupt number. The caller must free this with qemu_free_irq().
* If you are using this inside a device's init or realize method, then
@@ -42,7 +47,21 @@ static inline void qemu_irq_pulse(qemu_irq irq)
* to manually clean up the IRQ.
*/
void qemu_init_irq(IRQState *irq, qemu_irq_handler handler, void *opaque,
- int n);
+ int n)
+ QEMU_DEPRECATED;
+/**
+ * qemu_new_irq: Allocate IRQ
+ * @handler: handler function for incoming interrupts
+ * @opaque: opaque data to pass to @handler
+ * @n: interrupt number to pass to @handler
+ *
+ * The returned IRQ will have a single reference, which is held by the
+ * caller and must be released to free the returned IRQ object when
+ * no longer required.
+ *
+ * Returns: the newly allocated IRQ
+ */
+IRQState *qemu_irq_new(qemu_irq_handler handler, void *opaque, int n);
/**
* qemu_init_irq_child: Initialize IRQ and make it a QOM child
@@ -56,10 +75,38 @@ void qemu_init_irq(IRQState *irq, qemu_irq_handler handler, void *opaque,
* Init a single IRQ and make the IRQ object a child of @parent with
* the child-property name @propname. The IRQ object will thus be
* automatically freed when @parent is destroyed.
+ *
+ * Use of this function is now deprecated. All IRQs must be
+ * allocated using the qemu_irq_new() family of functions and not
+ * statically embedded in a larger struct.
*/
void qemu_init_irq_child(Object *parent, const char *propname,
IRQState *irq, qemu_irq_handler handler,
- void *opaque, int n);
+ void *opaque, int n)
+ QEMU_DEPRECATED;
+
+/**
+ * qemu_init_irq_child: Allocate IRQ and make it a QOM child
+ * @parent: QOM object which owns this IRQ
+ * @propname: child property name
+ * @handler: handler function for incoming interrupts
+ * @opaque: opaque data to pass to @handler
+ * @n: interrupt number to pass to @handler
+ *
+ * Allocate a single IRQ and make the IRQ object a child of @parent with
+ * the child-property name @propname.
+ *
+ * The returned IRQ will have a single reference, which is held by the
+ * @owner object in the QOM composition tree. Thus in the absence of
+ * any further references being acquired, the IRQ will be freed when
+ * @owner is freed
+ *
+ * Returns: the newly allocated IRQ
+ */
+IRQState *qemu_irq_new_child(Object *parent, const char *propname,
+ qemu_irq_handler handler,
+ void *opaque, int n,
+ Error **errp);
/**
@@ -69,9 +116,29 @@ void qemu_init_irq_child(Object *parent, const char *propname,
* @count: number of IRQs to initialize
* @handler: handler to assign to each IRQ
* @opaque: opaque data to pass to @handler
+ *
+ * Use of this function is now deprecated. All IRQs must be
+ * allocated using the qemu_irq_new() family of functions and not
+ * statically embedded in a larger struct.
*/
void qemu_init_irqs(IRQState irq[], size_t count,
- qemu_irq_handler handler, void *opaque);
+ qemu_irq_handler handler, void *opaque)
+ QEMU_DEPRECATED;
+/**
+ * qemu_irq_new_array: Allocate an array of IRQs.
+ * @count: number of IRQs to initialize
+ * @handler: handler to assign to each IRQ
+ * @opaque: opaque data to pass to @handler
+ *
+ * The returned IRQs will have a single reference, which is held by the
+ * caller and must be released to free the returned IRQs object when
+ * no longer required. The return array memory must also be freed by
+ * the caller.
+ *
+ * Returns: an array of IRQ objects
+ */
+IRQState **qemu_irq_new_array(size_t count,
+ qemu_irq_handler handler, void *opaque);
/* Returns an array of N IRQs. Each IRQ is assigned the argument handler and
* opaque data.
--
2.54.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC 6/7] hw/isa: convert PIIX embedded QOM objects to heap allocated
2026-06-16 15:55 [RFC 0/7] qom: deprecate embedded objects and instance properties Daniel P. Berrangé
` (4 preceding siblings ...)
2026-06-16 15:55 ` [RFC 5/7] system: add qemu_irq_new / qemu_irq_new_child / qemu_irq_new_array Daniel P. Berrangé
@ 2026-06-16 15:55 ` Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 7/7] qom: improve error message for invalid ID values Daniel P. Berrangé
2026-06-16 16:12 ` [RFC 0/7] qom: deprecate embedded objects and instance properties Peter Maydell
7 siblings, 0 replies; 14+ messages in thread
From: Daniel P. Berrangé @ 2026-06-16 15:55 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Pierrick Bouvier, Peter Xu,
Hervé Poussineau, Alex Bennée, Michael S. Tsirkin,
Akihiko Odaki, Daniel P. Berrangé, Aurelien Jarno,
Fabiano Rosas, Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
Update for the new preferred QOM design by removing embedded QOM
objects from the PIIXState struct for the RTC, IDE, UHCI, PM,
IRQ and memory region classes.
XXXX: there seems to be little benefit in having any of the
instance fields for RTC, IDE, UHCI, PM & IRQ objects. These
objects are all kept alive via the 'child' property which owns
the primary reference. The instance fields are accessed durnig
setup and then never again, so all these instances fields could
arguably go away entirely.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
hw/isa/piix.c | 65 ++++++++++++++++++++++-------------
include/hw/southbridge/piix.h | 12 +++----
2 files changed, 47 insertions(+), 30 deletions(-)
diff --git a/hw/isa/piix.c b/hw/isa/piix.c
index 31fa53e6a4..cd23486ef9 100644
--- a/hw/isa/piix.c
+++ b/hw/isa/piix.c
@@ -308,18 +308,22 @@ static void pci_piix_realize(PCIDevice *dev, const char *uhci_type,
return;
}
- memory_region_init_io(&d->rcr_mem, OBJECT(dev), &rcr_ops, d,
- "piix-reset-control", 1);
+ d->rcr_mem = memory_region_new_io(OBJECT(dev), &rcr_ops, d,
+ "piix-reset-control", 1);
memory_region_add_subregion_overlap(pci_address_space_io(dev),
- PIIX_RCR_IOPORT, &d->rcr_mem, 1);
+ PIIX_RCR_IOPORT, d->rcr_mem, 1);
/* PIC */
if (d->has_pic) {
qemu_irq *i8259;
- qemu_init_irq_child(OBJECT(dev), "i8259-irq", &d->i8259_irq,
- piix_request_i8259_irq, d, 0);
- i8259 = i8259_init(isa_bus, &d->i8259_irq);
+ d->i8259_irq = qemu_irq_new_child(OBJECT(dev), "i8259-irq",
+ piix_request_i8259_irq, d, 0,
+ errp);
+ if (!d->i8259_irq) {
+ return;
+ }
+ i8259 = i8259_init(isa_bus, d->i8259_irq);
for (size_t i = 0; i < ISA_NUM_IRQS; i++) {
d->isa_irqs_in[i] = i8259[i];
@@ -340,38 +344,45 @@ static void pci_piix_realize(PCIDevice *dev, const char *uhci_type,
i8257_dma_init(OBJECT(dev), isa_bus, 0);
/* RTC */
- qdev_prop_set_int32(DEVICE(&d->rtc), "base_year", 2000);
- if (!qdev_realize(DEVICE(&d->rtc), BUS(isa_bus), errp)) {
+ qdev_prop_set_int32(DEVICE(d->rtc), "base_year", 2000);
+ if (!qdev_realize(DEVICE(d->rtc), BUS(isa_bus), errp)) {
return;
}
- irq = object_property_get_uint(OBJECT(&d->rtc), "irq", &error_fatal);
- isa_connect_gpio_out(ISA_DEVICE(&d->rtc), 0, irq);
+ irq = object_property_get_uint(OBJECT(d->rtc), "irq", &error_fatal);
+ isa_connect_gpio_out(ISA_DEVICE(d->rtc), 0, irq);
/* IDE */
- qdev_prop_set_int32(DEVICE(&d->ide), "addr", dev->devfn + 1);
- if (!qdev_realize(DEVICE(&d->ide), BUS(pci_bus), errp)) {
+ qdev_prop_set_int32(DEVICE(d->ide), "addr", dev->devfn + 1);
+ if (!qdev_realize(DEVICE(d->ide), BUS(pci_bus), errp)) {
return;
}
/* USB */
if (d->has_usb) {
- object_initialize_child(OBJECT(dev), "uhci", &d->uhci, uhci_type);
- qdev_prop_set_int32(DEVICE(&d->uhci), "addr", dev->devfn + 2);
- if (!qdev_realize(DEVICE(&d->uhci), BUS(pci_bus), errp)) {
+ d->uhci = UHCI(object_new_with_props(
+ uhci_type, OBJECT(d), "uhci", errp, NULL));
+ if (!d->uhci) {
+ return;
+ }
+ qdev_prop_set_int32(DEVICE(d->uhci), "addr", dev->devfn + 2);
+ if (!qdev_realize(DEVICE(d->uhci), BUS(pci_bus), errp)) {
return;
}
}
/* Power Management */
if (d->has_acpi) {
- object_initialize_child(OBJECT(d), "pm", &d->pm, TYPE_PIIX4_PM);
- qdev_prop_set_int32(DEVICE(&d->pm), "addr", dev->devfn + 3);
- qdev_prop_set_uint32(DEVICE(&d->pm), "smb_io_base", d->smb_io_base);
- qdev_prop_set_bit(DEVICE(&d->pm), "smm-enabled", d->smm_enabled);
- if (!qdev_realize(DEVICE(&d->pm), BUS(pci_bus), errp)) {
+ d->pm = PIIX4_PM(object_new_with_props(
+ TYPE_PIIX4_PM, OBJECT(d), "pm", errp, NULL));
+ if (!d->pm) {
+ }
+ qdev_prop_set_int32(DEVICE(d->pm), "addr", dev->devfn + 3);
+ qdev_prop_set_uint32(DEVICE(d->pm), "smb_io_base", d->smb_io_base);
+ qdev_prop_set_bit(DEVICE(d->pm), "smm-enabled", d->smm_enabled);
+ if (!qdev_realize(DEVICE(d->pm), BUS(pci_bus), errp)) {
return;
}
- qdev_connect_gpio_out(DEVICE(&d->pm), 0, d->isa_irqs_in[9]);
+ qdev_connect_gpio_out(DEVICE(d->pm), 0, d->isa_irqs_in[9]);
}
pci_bus_irqs(pci_bus, piix_set_pci_irq, d, PIIX_NUM_PIRQS);
@@ -406,7 +417,9 @@ static void pci_piix_init(Object *obj)
qdev_init_gpio_out_named(DEVICE(obj), d->isa_irqs_in, "isa-irqs",
ISA_NUM_IRQS);
- object_initialize_child(obj, "rtc", &d->rtc, TYPE_MC146818_RTC);
+ d->rtc = MC146818_RTC(
+ object_new_with_props(TYPE_MC146818_RTC, obj, "rtc",
+ &error_abort, NULL));
}
static const Property pci_piix_props[] = {
@@ -462,7 +475,9 @@ static void piix3_init(Object *obj)
{
PIIXState *d = PIIX_PCI_DEVICE(obj);
- object_initialize_child(obj, "ide", &d->ide, TYPE_PIIX3_IDE);
+ d->ide = PCI_IDE(
+ object_new_with_props(TYPE_PIIX3_IDE, obj, "ide",
+ &error_abort, NULL));
}
static void piix3_class_init(ObjectClass *klass, const void *data)
@@ -492,7 +507,9 @@ static void piix4_init(Object *obj)
{
PIIXState *s = PIIX_PCI_DEVICE(obj);
- object_initialize_child(obj, "ide", &s->ide, TYPE_PIIX4_IDE);
+ s->ide = PCI_IDE(
+ object_new_with_props(TYPE_PIIX4_IDE, obj, "ide",
+ &error_abort, NULL));
}
static void piix4_class_init(ObjectClass *klass, const void *data)
diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
index a296b1205a..8bd24946de 100644
--- a/include/hw/southbridge/piix.h
+++ b/include/hw/southbridge/piix.h
@@ -53,15 +53,15 @@ struct PIIXState {
qemu_irq cpu_intr;
qemu_irq isa_irqs_in[ISA_NUM_IRQS];
- IRQState i8259_irq;
+ IRQState *i8259_irq;
/* This member isn't used. Just for save/load compatibility */
int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
- MC146818RtcState rtc;
- PCIIDEState ide;
- UHCIState uhci;
- PIIX4PMState pm;
+ MC146818RtcState *rtc;
+ PCIIDEState *ide;
+ UHCIState *uhci;
+ PIIX4PMState *pm;
uint32_t smb_io_base;
@@ -69,7 +69,7 @@ struct PIIXState {
uint8_t rcr;
/* IO memory region for Reset Control Register (PIIX_RCR_IOPORT) */
- MemoryRegion rcr_mem;
+ MemoryRegion *rcr_mem;
bool has_acpi;
bool has_pic;
--
2.54.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC 7/7] qom: improve error message for invalid ID values
2026-06-16 15:55 [RFC 0/7] qom: deprecate embedded objects and instance properties Daniel P. Berrangé
` (5 preceding siblings ...)
2026-06-16 15:55 ` [RFC 6/7] hw/isa: convert PIIX embedded QOM objects to heap allocated Daniel P. Berrangé
@ 2026-06-16 15:55 ` Daniel P. Berrangé
2026-06-16 16:12 ` [RFC 0/7] qom: deprecate embedded objects and instance properties Peter Maydell
7 siblings, 0 replies; 14+ messages in thread
From: Daniel P. Berrangé @ 2026-06-16 15:55 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Pierrick Bouvier, Peter Xu,
Hervé Poussineau, Alex Bennée, Michael S. Tsirkin,
Akihiko Odaki, Daniel P. Berrangé, Aurelien Jarno,
Fabiano Rosas, Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
Include the actual ID that was validated, since this may not be
obvious in all contexts.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
qom/object.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qom/object.c b/qom/object.c
index 415d5c5291..9cd17e3bcc 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -774,7 +774,7 @@ object_new_with_props_helper(const char *typename,
(id == NULL && parent == NULL));
if (id != NULL && !id_wellformed(id)) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
+ error_setg(errp, "QOM ID value '%s' is not valid", id);
error_append_hint(errp, "Identifiers consist of letters, digits, "
"'-', '.', '_', starting with a letter.\n");
return NULL;
--
2.54.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [RFC 0/7] qom: deprecate embedded objects and instance properties
2026-06-16 15:55 [RFC 0/7] qom: deprecate embedded objects and instance properties Daniel P. Berrangé
` (6 preceding siblings ...)
2026-06-16 15:55 ` [RFC 7/7] qom: improve error message for invalid ID values Daniel P. Berrangé
@ 2026-06-16 16:12 ` Peter Maydell
2026-06-16 16:40 ` Daniel P. Berrangé
7 siblings, 1 reply; 14+ messages in thread
From: Peter Maydell @ 2026-06-16 16:12 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: qemu-devel, Philippe Mathieu-Daudé, Pierrick Bouvier,
Peter Xu, Hervé Poussineau, Alex Bennée,
Michael S. Tsirkin, Akihiko Odaki, Aurelien Jarno, Fabiano Rosas,
Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
On Tue, 16 Jun 2026 at 16:56, Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> QOM has two rather unusual / surprising features historicall
>
> * The ability to embed a QOM instance's memory inside another
> struct
> * The ability to register properties against the instnce
> instead of struct
>
> While they both look convenient on the surface, they also
> have significant undesirable side effects (see the commit
> message for each patch for details).
>
> The premise of this series is that their convenience does
> not outweigh their downsides, and we would be better off
> long term by eliminating their usage, rather than trying
> to add more hacks on top to mitigate their downsides.
The thing I would like to see before we mark object_initialize_child
and friends as deprecated is clear documentation of "this is how
we would like you to write 'container/SoC' style devices, here is
an device written to the approved style you can look at".
Currently we have in the codebase a pretty wide range of
different ways to write devices:
- really ancient, not QOM/qdev at all
- qdev style (lots of Device* pointers)
- embedded-struct style
and I'm not sure if this would be adding a fourth style, or
rolling back to qdev style.
(Borrowing a paragraph I wrote last time this came up:)
I'm not opposed to the idea of making a design decision that this
struct-embedding is no longer what we want to do, and defining
that something else is our new best practice for how to write devices.
But I think we would need to start by reaching a consensus that that
*is* what we want to do, and documenting that "best practice" somewhere
in docs/devel/. Then we can all be on the same page about the design
patterns we want and it will be clearer to reviewers whether new
code and new APIs and conversions of old code fit into those
patterns or not.
I think we're getting closer on the "consensus" part but
the "document the new best practice" part is important I think.
thanks
-- PMM
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC 2/7] qom: deprecated embedding object structs within other objects
2026-06-16 15:55 ` [RFC 2/7] qom: deprecated embedding object structs within other objects Daniel P. Berrangé
@ 2026-06-16 16:15 ` Peter Maydell
2026-06-16 16:43 ` Daniel P. Berrangé
0 siblings, 1 reply; 14+ messages in thread
From: Peter Maydell @ 2026-06-16 16:15 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: qemu-devel, Philippe Mathieu-Daudé, Pierrick Bouvier,
Peter Xu, Hervé Poussineau, Alex Bennée,
Michael S. Tsirkin, Akihiko Odaki, Aurelien Jarno, Fabiano Rosas,
Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
On Tue, 16 Jun 2026 at 16:56, Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> The QOM APIs currently allow objects to be either allocated directly
> on the heap, or statically embedded inside the struct of another object.
>
> For the latter QOM has logic to avoid calling 'free' on the object when
> finalizers complete, however, this is not sufficient to make the
> practice safe.
>
> Users of QOM expect that if they call "object_ref" to acquire their own
> reference, then object will never be freed as long as they hold it.
>
> This expectation is broken when an instance is embedded, as the "owner"
> object's may be finalized, which frees the memory that is storing the
> embedded QOM instance, even if its ref-count is still live.
>
> Worse still is that a user of a QOM object cannot easily tell if the
> instance they're using is embedded or directly heap allocated.
>
> Mark the APIs for embedding objects as deprecated as the first step
> towards removal of this flawed design concept. All objects must now
> be directly heap allocated going forward, and existing usage must be
> incrementally converted.
I think if you mark an API that we call in 800+ places and 150+ files
as deprecated, mostly what will happen is nobody ever turns on the
--enable-deprecated option because the output will be full of noise...
-- PMM
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC 5/7] system: add qemu_irq_new / qemu_irq_new_child / qemu_irq_new_array
2026-06-16 15:55 ` [RFC 5/7] system: add qemu_irq_new / qemu_irq_new_child / qemu_irq_new_array Daniel P. Berrangé
@ 2026-06-16 16:22 ` Peter Maydell
2026-06-16 16:36 ` Daniel P. Berrangé
0 siblings, 1 reply; 14+ messages in thread
From: Peter Maydell @ 2026-06-16 16:22 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: qemu-devel, Philippe Mathieu-Daudé, Pierrick Bouvier,
Peter Xu, Hervé Poussineau, Alex Bennée,
Michael S. Tsirkin, Akihiko Odaki, Aurelien Jarno, Fabiano Rosas,
Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
On Tue, 16 Jun 2026 at 16:57, Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> Prepare for the move to dynamically allocated IRQ objects by
> introducing qemu_irq_new / qemu_irq_new_child / qemu_irq_new_array
> functions which call through to object_new instead of object_initialize.
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
> hw/core/irq.c | 35 ++++++++++++++++++++
> include/hw/core/irq.h | 75 ++++++++++++++++++++++++++++++++++++++++---
> 2 files changed, 106 insertions(+), 4 deletions(-)
>
> diff --git a/hw/core/irq.c b/hw/core/irq.c
> index 106805e241..e943c87b81 100644
> --- a/hw/core/irq.c
> +++ b/hw/core/irq.c
> @@ -49,6 +49,13 @@ void qemu_init_irq(IRQState *irq, qemu_irq_handler handler, void *opaque,
> init_irq_fields(irq, handler, opaque, n);
> }
>
> +IRQState *qemu_irq_new(qemu_irq_handler handler, void *opaque, int n)
> +{
> + IRQState *irq = IRQ(object_new(TYPE_IRQ));
> + init_irq_fields(irq, handler, opaque, n);
> + return irq;
> +}
Isn't this the same as the existing qemu_allocate_irq() ?
(I have over the past few years occasionally been trying to get rid
of existing uses of qemu_allocate_irq() and its cousin
qemu_allocate_irqs(), because they are persistent sources of memory
leaks. The function returns a pointer that the caller has to deal
with and remember to free, whereas using e.g. qdev_init_gpio_*()
makes the new irq objects children of the device they belong to,
so they're automatically freed when the device is destroyed.
qemu_init_irq_child() similarly.)
-- PMM
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC 5/7] system: add qemu_irq_new / qemu_irq_new_child / qemu_irq_new_array
2026-06-16 16:22 ` Peter Maydell
@ 2026-06-16 16:36 ` Daniel P. Berrangé
0 siblings, 0 replies; 14+ messages in thread
From: Daniel P. Berrangé @ 2026-06-16 16:36 UTC (permalink / raw)
To: Peter Maydell
Cc: qemu-devel, Philippe Mathieu-Daudé, Pierrick Bouvier,
Peter Xu, Hervé Poussineau, Alex Bennée,
Michael S. Tsirkin, Akihiko Odaki, Aurelien Jarno, Fabiano Rosas,
Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
On Tue, Jun 16, 2026 at 05:22:05PM +0100, Peter Maydell wrote:
> On Tue, 16 Jun 2026 at 16:57, Daniel P. Berrangé <berrange@redhat.com> wrote:
> >
> > Prepare for the move to dynamically allocated IRQ objects by
> > introducing qemu_irq_new / qemu_irq_new_child / qemu_irq_new_array
> > functions which call through to object_new instead of object_initialize.
> >
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > ---
> > hw/core/irq.c | 35 ++++++++++++++++++++
> > include/hw/core/irq.h | 75 ++++++++++++++++++++++++++++++++++++++++---
> > 2 files changed, 106 insertions(+), 4 deletions(-)
> >
> > diff --git a/hw/core/irq.c b/hw/core/irq.c
> > index 106805e241..e943c87b81 100644
> > --- a/hw/core/irq.c
> > +++ b/hw/core/irq.c
> > @@ -49,6 +49,13 @@ void qemu_init_irq(IRQState *irq, qemu_irq_handler handler, void *opaque,
> > init_irq_fields(irq, handler, opaque, n);
> > }
> >
> > +IRQState *qemu_irq_new(qemu_irq_handler handler, void *opaque, int n)
> > +{
> > + IRQState *irq = IRQ(object_new(TYPE_IRQ));
> > + init_irq_fields(irq, handler, opaque, n);
> > + return irq;
> > +}
>
> Isn't this the same as the existing qemu_allocate_irq() ?
Doh, I missed the very surprising naming pattern where "qemu_irq" is a
typedef of 'struct IRQState *'.
> (I have over the past few years occasionally been trying to get rid
> of existing uses of qemu_allocate_irq() and its cousin
> qemu_allocate_irqs(), because they are persistent sources of memory
> leaks. The function returns a pointer that the caller has to deal
> with and remember to free, whereas using e.g. qdev_init_gpio_*()
> makes the new irq objects children of the device they belong to,
> so they're automatically freed when the device is destroyed.
> qemu_init_irq_child() similarly.)
If we think it is best practice to mandate passing in a parent
object so that every IRQ is gauranteed to be owned by the QOM
tree, that's fine with me.
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC 0/7] qom: deprecate embedded objects and instance properties
2026-06-16 16:12 ` [RFC 0/7] qom: deprecate embedded objects and instance properties Peter Maydell
@ 2026-06-16 16:40 ` Daniel P. Berrangé
0 siblings, 0 replies; 14+ messages in thread
From: Daniel P. Berrangé @ 2026-06-16 16:40 UTC (permalink / raw)
To: Peter Maydell
Cc: qemu-devel, Philippe Mathieu-Daudé, Pierrick Bouvier,
Peter Xu, Hervé Poussineau, Alex Bennée,
Michael S. Tsirkin, Akihiko Odaki, Aurelien Jarno, Fabiano Rosas,
Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
On Tue, Jun 16, 2026 at 05:12:27PM +0100, Peter Maydell wrote:
> On Tue, 16 Jun 2026 at 16:56, Daniel P. Berrangé <berrange@redhat.com> wrote:
> >
> > QOM has two rather unusual / surprising features historicall
> >
> > * The ability to embed a QOM instance's memory inside another
> > struct
> > * The ability to register properties against the instnce
> > instead of struct
> >
> > While they both look convenient on the surface, they also
> > have significant undesirable side effects (see the commit
> > message for each patch for details).
> >
> > The premise of this series is that their convenience does
> > not outweigh their downsides, and we would be better off
> > long term by eliminating their usage, rather than trying
> > to add more hacks on top to mitigate their downsides.
>
> The thing I would like to see before we mark object_initialize_child
> and friends as deprecated is clear documentation of "this is how
> we would like you to write 'container/SoC' style devices, here is
> an device written to the approved style you can look at".
Do we have any documentation currently that touches on
this area that we can start from / adapt to best
practices ? I can do adaptation, but I'm not an expert
on Device code, so probably not best placed to write a
new doc fro mscratch.
> Currently we have in the codebase a pretty wide range of
> different ways to write devices:
> - really ancient, not QOM/qdev at all
> - qdev style (lots of Device* pointers)
> - embedded-struct style
> and I'm not sure if this would be adding a fourth style, or
> rolling back to qdev style.
Per my commit message in the PIIX patch, I'm not convinced
we need to store any device pointers in the instance
structs at all in many (possibly most) cases. The instance
struct fields are mostly only referenced during creation
time and then never again, with the QOM 'child' property
holding the permanent reference.
> I'm not opposed to the idea of making a design decision that this
> struct-embedding is no longer what we want to do, and defining
> that something else is our new best practice for how to write devices.
> But I think we would need to start by reaching a consensus that that
> *is* what we want to do, and documenting that "best practice" somewhere
> in docs/devel/. Then we can all be on the same page about the design
> patterns we want and it will be clearer to reviewers whether new
> code and new APIs and conversions of old code fit into those
> patterns or not.
>
> I think we're getting closer on the "consensus" part but
> the "document the new best practice" part is important I think.
Yep, best practice docs must be a key part of the story.
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC 2/7] qom: deprecated embedding object structs within other objects
2026-06-16 16:15 ` Peter Maydell
@ 2026-06-16 16:43 ` Daniel P. Berrangé
0 siblings, 0 replies; 14+ messages in thread
From: Daniel P. Berrangé @ 2026-06-16 16:43 UTC (permalink / raw)
To: Peter Maydell
Cc: qemu-devel, Philippe Mathieu-Daudé, Pierrick Bouvier,
Peter Xu, Hervé Poussineau, Alex Bennée,
Michael S. Tsirkin, Akihiko Odaki, Aurelien Jarno, Fabiano Rosas,
Paolo Bonzini, BALATON Zoltan, Mark Cave-Ayland,
Marc-André Lureau
On Tue, Jun 16, 2026 at 05:15:22PM +0100, Peter Maydell wrote:
> On Tue, 16 Jun 2026 at 16:56, Daniel P. Berrangé <berrange@redhat.com> wrote:
> >
> > The QOM APIs currently allow objects to be either allocated directly
> > on the heap, or statically embedded inside the struct of another object.
> >
> > For the latter QOM has logic to avoid calling 'free' on the object when
> > finalizers complete, however, this is not sufficient to make the
> > practice safe.
> >
> > Users of QOM expect that if they call "object_ref" to acquire their own
> > reference, then object will never be freed as long as they hold it.
> >
> > This expectation is broken when an instance is embedded, as the "owner"
> > object's may be finalized, which frees the memory that is storing the
> > embedded QOM instance, even if its ref-count is still live.
> >
> > Worse still is that a user of a QOM object cannot easily tell if the
> > instance they're using is embedded or directly heap allocated.
> >
> > Mark the APIs for embedding objects as deprecated as the first step
> > towards removal of this flawed design concept. All objects must now
> > be directly heap allocated going forward, and existing usage must be
> > incrementally converted.
>
> I think if you mark an API that we call in 800+ places and 150+ files
> as deprecated, mostly what will happen is nobody ever turns on the
> --enable-deprecated option because the output will be full of noise...
That is a challenge. The baseline is that developers have no visibility
of use of deprecated APIs at all, and we barely even document them.
My thought is that even if --enable-deprecated is rarely enabled, at
least having QEMU_DEPRECATED visible in the header files is a red flag
for developers to look elsewhere for their solution.
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-06-16 16:44 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-16 15:55 [RFC 0/7] qom: deprecate embedded objects and instance properties Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 1/7] meson: add --enable-deprecations configure flag Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 2/7] qom: deprecated embedding object structs within other objects Daniel P. Berrangé
2026-06-16 16:15 ` Peter Maydell
2026-06-16 16:43 ` Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 3/7] qom: deprecate use of instance properties Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 4/7] system: add memory_region_new / memory_region_new_io Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 5/7] system: add qemu_irq_new / qemu_irq_new_child / qemu_irq_new_array Daniel P. Berrangé
2026-06-16 16:22 ` Peter Maydell
2026-06-16 16:36 ` Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 6/7] hw/isa: convert PIIX embedded QOM objects to heap allocated Daniel P. Berrangé
2026-06-16 15:55 ` [RFC 7/7] qom: improve error message for invalid ID values Daniel P. Berrangé
2026-06-16 16:12 ` [RFC 0/7] qom: deprecate embedded objects and instance properties Peter Maydell
2026-06-16 16:40 ` Daniel P. Berrangé
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.