All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object
@ 2026-06-09 17:25 Peter Xu
  2026-06-09 17:25 ` [PATCH v2 01/10] migration: Use OBJECT_DECLARE_SIMPLE_TYPE Peter Xu
                   ` (10 more replies)
  0 siblings, 11 replies; 30+ messages in thread
From: Peter Xu @ 2026-06-09 17:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Peter Xu,
	Paolo Bonzini, Kevin Wolf, Sana Sharma, Marc-André Lureau,
	Juraj Marcin, qemu-rust, Markus Armbruster, Mark Cave-Ayland

CI: https://gitlab.com/peterx/qemu/-/pipelines/2588717620
    (two irrelevant failures due to no runner)

rfc: https://lore.kernel.org/r/20251209162857.857593-1-peterx@redhat.com
v1:  https://lore.kernel.org/r/20260604231118.1584889-1-peterx@redhat.com

This v2 is a full rewrite of v1, changelog doesn't apply.

This version majorly addressed the concern in v1 having object API exported
in qdev files. Instead of trying to expose qdev properties, this patchset
switched migration object to use the object property API to add properties.

Not all QOM facilities are ready for it, there're a few prior patches to
improve QOM API to achieve it.

The major concept that this series introduces that does not exist
previously is the default value mechanisms for object properties (rather
than object class properties).  Here migration object will rely on that to
set default values.

Patch 1:   A cleanup to use OBJECT_DECLARE_SIMPLE_TYPE for migration
Patch 2-4: Qdev changes needed for the transition
Patch 5-9: Improve QOM API to prepare for the property switch
Patch 10:  Switch migration object to use TYPE_OBJECT and object props

Comments welcomed, thanks.

Peter Xu (10):
  migration: Use OBJECT_DECLARE_SIMPLE_TYPE
  qdev: Export global_props()
  qdev: Introduce DEFINE_PROP_*_NODEFAULT for bool/uint32
  hw/arm: Use nodefault version of qdev props when not needed
  qom: Create object-property-ptr.[ch]
  qom: Add object_property_add_bool_ptr()
  qom: Add object_property_add_size_ptr()
  qom: Add object_property_add_*_ptr_def()
  qom: Allow default values for instance properties
  migration: Switch to TYPE_OBJECT with object properties

 include/hw/core/qdev-properties.h |   7 +
 include/qom/object-property-ptr.h | 162 +++++++++
 include/qom/object.h              |  99 +-----
 migration/migration.h             |   9 +-
 migration/options.h               |   8 +-
 hw/arm/bcm2836.c                  |   3 +-
 hw/core/qdev-properties.c         |   2 +-
 migration/migration.c             |  42 ++-
 migration/options.c               | 526 +++++++++++++++++++-----------
 qom/object-property-ptr.c         | 394 ++++++++++++++++++++++
 qom/object.c                      | 266 ++-------------
 target/arm/cpu64.c                |   3 +-
 qom/meson.build                   |   1 +
 rust/bindings/hwcore-sys/lib.rs   |   2 +-
 14 files changed, 957 insertions(+), 567 deletions(-)
 create mode 100644 include/qom/object-property-ptr.h
 create mode 100644 qom/object-property-ptr.c

-- 
2.53.0



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

* [PATCH v2 01/10] migration: Use OBJECT_DECLARE_SIMPLE_TYPE
  2026-06-09 17:25 [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Peter Xu
@ 2026-06-09 17:25 ` Peter Xu
  2026-06-09 22:55   ` Fabiano Rosas
                     ` (2 more replies)
  2026-06-09 17:25 ` [PATCH v2 02/10] qdev: Export global_props() Peter Xu
                   ` (9 subsequent siblings)
  10 siblings, 3 replies; 30+ messages in thread
From: Peter Xu @ 2026-06-09 17:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Peter Xu,
	Paolo Bonzini, Kevin Wolf, Sana Sharma, Marc-André Lureau,
	Juraj Marcin, qemu-rust, Markus Armbruster, Mark Cave-Ayland

Migration object's class has nothing special, switch to the newly
introduced macro.

Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
 migration/migration.h | 9 +--------
 migration/migration.c | 7 +++----
 2 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/migration/migration.h b/migration/migration.h
index 841f49b215..293ad60e07 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -263,14 +263,7 @@ void fill_destination_postcopy_migration_info(MigrationInfo *info);
 
 #define TYPE_MIGRATION "migration"
 
-typedef struct MigrationClass MigrationClass;
-DECLARE_OBJ_CHECKERS(MigrationState, MigrationClass,
-                     MIGRATION_OBJ, TYPE_MIGRATION)
-
-struct MigrationClass {
-    /*< private >*/
-    DeviceClass parent_class;
-};
+OBJECT_DECLARE_SIMPLE_TYPE(MigrationState, MIGRATION);
 
 struct MigrationState {
     /*< private >*/
diff --git a/migration/migration.c b/migration/migration.c
index 074d3f2c69..278cad502a 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -297,7 +297,7 @@ void migration_object_init(void)
 {
     /* This can only be called once. */
     assert(!current_migration);
-    current_migration = MIGRATION_OBJ(object_new(TYPE_MIGRATION));
+    current_migration = MIGRATION(object_new(TYPE_MIGRATION));
 
     /*
      * Init the migrate incoming object as well no matter whether
@@ -3975,7 +3975,7 @@ static void migration_class_init(ObjectClass *klass, const void *data)
 
 static void migration_instance_finalize(Object *obj)
 {
-    MigrationState *ms = MIGRATION_OBJ(obj);
+    MigrationState *ms = MIGRATION(obj);
 
     qapi_free_BitmapMigrationNodeAliasList(ms->parameters.block_bitmap_mapping);
     qapi_free_strList(ms->parameters.cpr_exec_command);
@@ -3993,7 +3993,7 @@ static void migration_instance_finalize(Object *obj)
 
 static void migration_instance_init(Object *obj)
 {
-    MigrationState *ms = MIGRATION_OBJ(obj);
+    MigrationState *ms = MIGRATION(obj);
 
     ms->state = MIGRATION_STATUS_NONE;
     ms->mbps = -1;
@@ -4040,7 +4040,6 @@ static const TypeInfo migration_type = {
      */
     .parent = TYPE_DEVICE,
     .class_init = migration_class_init,
-    .class_size = sizeof(MigrationClass),
     .instance_size = sizeof(MigrationState),
     .instance_init = migration_instance_init,
     .instance_finalize = migration_instance_finalize,
-- 
2.53.0



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

* [PATCH v2 02/10] qdev: Export global_props()
  2026-06-09 17:25 [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Peter Xu
  2026-06-09 17:25 ` [PATCH v2 01/10] migration: Use OBJECT_DECLARE_SIMPLE_TYPE Peter Xu
@ 2026-06-09 17:25 ` Peter Xu
  2026-06-09 22:55   ` Fabiano Rosas
  2026-06-10 15:18   ` Mark Cave-Ayland
  2026-06-09 17:25 ` [PATCH v2 03/10] qdev: Introduce DEFINE_PROP_*_NODEFAULT for bool/uint32 Peter Xu
                   ` (8 subsequent siblings)
  10 siblings, 2 replies; 30+ messages in thread
From: Peter Xu @ 2026-06-09 17:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Peter Xu,
	Paolo Bonzini, Kevin Wolf, Sana Sharma, Marc-André Lureau,
	Juraj Marcin, qemu-rust, Markus Armbruster, Mark Cave-Ayland

Make it accessible from outside (to apply -global properties).

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/hw/core/qdev-properties.h | 2 ++
 hw/core/qdev-properties.c         | 2 +-
 rust/bindings/hwcore-sys/lib.rs   | 2 +-
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/hw/core/qdev-properties.h b/include/hw/core/qdev-properties.h
index eba5436e53..248bbcbba7 100644
--- a/include/hw/core/qdev-properties.h
+++ b/include/hw/core/qdev-properties.h
@@ -321,4 +321,6 @@ void qdev_prop_allow_set_link_before_realize(const Object *obj,
                                              const char *name,
                                              Object *val, Error **errp);
 
+GPtrArray *global_props(void);
+
 #endif
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 34d7b26a73..1d531189ec 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -958,7 +958,7 @@ void qlist_append_link(QList *qlist, Object *obj)
     qlist_append_str(qlist, path);
 }
 
-static GPtrArray *global_props(void)
+GPtrArray *global_props(void)
 {
     static GPtrArray *gp;
 
diff --git a/rust/bindings/hwcore-sys/lib.rs b/rust/bindings/hwcore-sys/lib.rs
index 8cef4a7961..85e71f5145 100644
--- a/rust/bindings/hwcore-sys/lib.rs
+++ b/rust/bindings/hwcore-sys/lib.rs
@@ -20,7 +20,7 @@
 
 use chardev_sys::Chardev;
 use common::Zeroable;
-use glib_sys::GSList;
+use glib_sys::{GPtrArray, GSList};
 use migration_sys::VMStateDescription;
 use qom_sys::{
     InterfaceClass, Object, ObjectClass, ObjectProperty, ObjectPropertyAccessor,
-- 
2.53.0



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

* [PATCH v2 03/10] qdev: Introduce DEFINE_PROP_*_NODEFAULT for bool/uint32
  2026-06-09 17:25 [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Peter Xu
  2026-06-09 17:25 ` [PATCH v2 01/10] migration: Use OBJECT_DECLARE_SIMPLE_TYPE Peter Xu
  2026-06-09 17:25 ` [PATCH v2 02/10] qdev: Export global_props() Peter Xu
@ 2026-06-09 17:25 ` Peter Xu
  2026-06-10 15:25   ` Mark Cave-Ayland
  2026-06-09 17:25 ` [PATCH v2 04/10] hw/arm: Use nodefault version of qdev props when not needed Peter Xu
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Peter Xu @ 2026-06-09 17:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Peter Xu,
	Paolo Bonzini, Kevin Wolf, Sana Sharma, Marc-André Lureau,
	Juraj Marcin, qemu-rust, Markus Armbruster, Mark Cave-Ayland

Introduce two macros that will be used in follow up patch to create qdev
bool or uint32 properties without a default value.  Do not introduce the
rest until they can be used.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/hw/core/qdev-properties.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/hw/core/qdev-properties.h b/include/hw/core/qdev-properties.h
index 248bbcbba7..43878d1f9e 100644
--- a/include/hw/core/qdev-properties.h
+++ b/include/hw/core/qdev-properties.h
@@ -124,6 +124,9 @@ extern const PropertyInfo qdev_prop_link;
                 .set_default = true,                         \
                 .defval.u    = (bool)_defval)
 
+#define DEFINE_PROP_BOOL_NODEFAULT(_name, _state, _field)     \
+    DEFINE_PROP(_name, _state, _field, qdev_prop_bool, bool)
+
 /**
  * The DEFINE_PROP_UINT64_CHECKMASK macro checks a user-supplied value
  * against corresponding bitmask, rejects the value if it violates.
@@ -201,6 +204,8 @@ extern const PropertyInfo qdev_prop_link;
     DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
 #define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \
     DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
+#define DEFINE_PROP_UINT32_NODEFAULT(_n, _s, _f)                        \
+    DEFINE_PROP_UNSIGNED_NODEFAULT(_n, _s, _f, qdev_prop_uint32, uint32_t)
 #define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \
     DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_int32, int32_t)
 #define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \
-- 
2.53.0



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

* [PATCH v2 04/10] hw/arm: Use nodefault version of qdev props when not needed
  2026-06-09 17:25 [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Peter Xu
                   ` (2 preceding siblings ...)
  2026-06-09 17:25 ` [PATCH v2 03/10] qdev: Introduce DEFINE_PROP_*_NODEFAULT for bool/uint32 Peter Xu
@ 2026-06-09 17:25 ` Peter Xu
  2026-06-10 15:31   ` Mark Cave-Ayland
  2026-06-09 17:25 ` [PATCH v2 05/10] qom: Create object-property-ptr.[ch] Peter Xu
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Peter Xu @ 2026-06-09 17:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Peter Xu,
	Paolo Bonzini, Kevin Wolf, Sana Sharma, Marc-André Lureau,
	Juraj Marcin, qemu-rust, Markus Armbruster, Mark Cave-Ayland,
	Marc Zyngier

We're going to introduce defvars for object properties just like qdev-props
defvars.  It work slightly differently in that props can be added in
instance_init() with default values, then the default values can only apply
after instance_init() completes.

It means any explicit set of property values within instance_init() when
used together with object property's default value (or qdev-prop, which
builts the default value framework on top) will stop working.

This patch touches two of such use cases where the device may add qdev
properties with a default value first, then quickly set another value
within instance_init().

These are the only two outliers I found across the QEMU tree that do it
this way.  Switch them to use qdev-prop's NODEFAULT APIs, and always
initialize the values manually.

Example 1:

bcm283x_base_init() adds qdev prop bcm2836_enabled_cores_property with a
default value 0, then it immediately set another value inside the same
instance_init() hook.

Example 2:

aarch64_add_pauth_properties() adds qdev prop arm_cpu_pauth_property, but
then it will immediately update the same field (cpu->prop_pauth)
conditionally when hwaccel_enabled()==true.

Without the change, some arm test may fail (boot-serial-test) after
introducing object property's default value framework, because devices'
values will be overwritten by the properties' later.

OTOH, this patch itself should introduce no functional change.

Cc: Marc Zyngier <maz@kernel.org>
Cc: Philippe Mathieu-Daudé <philmd@mailo.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
 hw/arm/bcm2836.c   | 3 ++-
 target/arm/cpu64.c | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index f4ecea908b..9e4d30c99c 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -19,7 +19,8 @@
 #include "target/arm/gtimer.h"
 
 static const Property bcm2836_enabled_cores_property =
-    DEFINE_PROP_UINT32("enabled-cpus", BCM283XBaseState, enabled_cpus, 0);
+    DEFINE_PROP_UINT32_NODEFAULT(
+        "enabled-cpus", BCM283XBaseState, enabled_cpus);
 
 static void bcm283x_base_init(Object *obj)
 {
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 2816735577..a3a014a994 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -635,7 +635,7 @@ void aarch64_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
 }
 
 static const Property arm_cpu_pauth_property =
-    DEFINE_PROP_BOOL("pauth", ARMCPU, prop_pauth, true);
+    DEFINE_PROP_BOOL_NODEFAULT("pauth", ARMCPU, prop_pauth);
 static const Property arm_cpu_pauth_impdef_property =
     DEFINE_PROP_BOOL("pauth-impdef", ARMCPU, prop_pauth_impdef, false);
 static const Property arm_cpu_pauth_qarma3_property =
@@ -660,6 +660,7 @@ void aarch64_add_pauth_properties(Object *obj)
          */
         cpu->prop_pauth = cpu_isar_feature(aa64_pauth, cpu);
     } else {
+        cpu->prop_pauth = true;
         qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_impdef_property);
         qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_qarma3_property);
         qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_qarma5_property);
-- 
2.53.0



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

* [PATCH v2 05/10] qom: Create object-property-ptr.[ch]
  2026-06-09 17:25 [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Peter Xu
                   ` (3 preceding siblings ...)
  2026-06-09 17:25 ` [PATCH v2 04/10] hw/arm: Use nodefault version of qdev props when not needed Peter Xu
@ 2026-06-09 17:25 ` Peter Xu
  2026-06-10 16:15   ` Daniel P. Berrangé
  2026-06-09 17:25 ` [PATCH v2 06/10] qom: Add object_property_add_bool_ptr() Peter Xu
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Peter Xu @ 2026-06-09 17:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Peter Xu,
	Paolo Bonzini, Kevin Wolf, Sana Sharma, Marc-André Lureau,
	Juraj Marcin, qemu-rust, Markus Armbruster, Mark Cave-Ayland

Create object-property-ptr.[ch] files to include all the helpers for
object_property_add*_ptr().

These set of helpers are handy because they look extremely familiar with
qdev-properties, allowing the caller to provide a pointer and it will
manage all the setters and getters.

The follow up patches may introduce more of such helpers.  Since object.c
has been already too big, split that part out.

No functional change intended.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/qom/object-property-ptr.h | 103 +++++++++++++
 include/qom/object.h              |  99 +-----------
 qom/object-property-ptr.c         | 248 ++++++++++++++++++++++++++++++
 qom/object.c                      | 240 -----------------------------
 qom/meson.build                   |   1 +
 5 files changed, 358 insertions(+), 333 deletions(-)
 create mode 100644 include/qom/object-property-ptr.h
 create mode 100644 qom/object-property-ptr.c

diff --git a/include/qom/object-property-ptr.h b/include/qom/object-property-ptr.h
new file mode 100644
index 0000000000..6066c377fb
--- /dev/null
+++ b/include/qom/object-property-ptr.h
@@ -0,0 +1,103 @@
+/*
+ * Object property helpers to operate on a pointer.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef QEMU_OBJECT_PROPERTY_PTR_H
+#define QEMU_OBJECT_PROPERTY_PTR_H
+
+typedef enum {
+    /* Automatically add a getter to the property */
+    OBJ_PROP_FLAG_READ = 1 << 0,
+    /* Automatically add a setter to the property */
+    OBJ_PROP_FLAG_WRITE = 1 << 1,
+    /* Automatically add a getter and a setter to the property */
+    OBJ_PROP_FLAG_READWRITE = (OBJ_PROP_FLAG_READ | OBJ_PROP_FLAG_WRITE),
+} ObjectPropertyFlags;
+
+/**
+ * object_property_add_uint8_ptr:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @v: pointer to value
+ * @flags: bitwise-or'd ObjectPropertyFlags
+ *
+ * Add an integer property in memory.  This function will add a
+ * property of type 'uint8'.
+ *
+ * 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);
+
+ObjectProperty *object_class_property_add_uint8_ptr(ObjectClass *klass,
+                                         const char *name,
+                                         const uint8_t *v,
+                                         ObjectPropertyFlags flags);
+
+/**
+ * object_property_add_uint16_ptr:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @v: pointer to value
+ * @flags: bitwise-or'd ObjectPropertyFlags
+ *
+ * Add an integer property in memory.  This function will add a
+ * property of type 'uint16'.
+ *
+ * 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);
+
+ObjectProperty *object_class_property_add_uint16_ptr(ObjectClass *klass,
+                                          const char *name,
+                                          const uint16_t *v,
+                                          ObjectPropertyFlags flags);
+
+/**
+ * object_property_add_uint32_ptr:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @v: pointer to value
+ * @flags: bitwise-or'd ObjectPropertyFlags
+ *
+ * Add an integer property in memory.  This function will add a
+ * property of type 'uint32'.
+ *
+ * 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);
+
+ObjectProperty *object_class_property_add_uint32_ptr(ObjectClass *klass,
+                                          const char *name,
+                                          const uint32_t *v,
+                                          ObjectPropertyFlags flags);
+
+/**
+ * object_property_add_uint64_ptr:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @v: pointer to value
+ * @flags: bitwise-or'd ObjectPropertyFlags
+ *
+ * Add an integer property in memory.  This function will add a
+ * property of type 'uint64'.
+ *
+ * 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);
+
+ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass,
+                                          const char *name,
+                                          const uint64_t *v,
+                                          ObjectPropertyFlags flags);
+
+#endif
diff --git a/include/qom/object.h b/include/qom/object.h
index 11f55613fc..6ea569d580 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -1931,99 +1931,6 @@ ObjectProperty *object_class_property_add_tm(ObjectClass *klass,
                             const char *name,
                             void (*get)(Object *, struct tm *, Error **));
 
-typedef enum {
-    /* Automatically add a getter to the property */
-    OBJ_PROP_FLAG_READ = 1 << 0,
-    /* Automatically add a setter to the property */
-    OBJ_PROP_FLAG_WRITE = 1 << 1,
-    /* Automatically add a getter and a setter to the property */
-    OBJ_PROP_FLAG_READWRITE = (OBJ_PROP_FLAG_READ | OBJ_PROP_FLAG_WRITE),
-} ObjectPropertyFlags;
-
-/**
- * object_property_add_uint8_ptr:
- * @obj: the object to add a property to
- * @name: the name of the property
- * @v: pointer to value
- * @flags: bitwise-or'd ObjectPropertyFlags
- *
- * Add an integer property in memory.  This function will add a
- * property of type 'uint8'.
- *
- * 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);
-
-ObjectProperty *object_class_property_add_uint8_ptr(ObjectClass *klass,
-                                         const char *name,
-                                         const uint8_t *v,
-                                         ObjectPropertyFlags flags);
-
-/**
- * object_property_add_uint16_ptr:
- * @obj: the object to add a property to
- * @name: the name of the property
- * @v: pointer to value
- * @flags: bitwise-or'd ObjectPropertyFlags
- *
- * Add an integer property in memory.  This function will add a
- * property of type 'uint16'.
- *
- * 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);
-
-ObjectProperty *object_class_property_add_uint16_ptr(ObjectClass *klass,
-                                          const char *name,
-                                          const uint16_t *v,
-                                          ObjectPropertyFlags flags);
-
-/**
- * object_property_add_uint32_ptr:
- * @obj: the object to add a property to
- * @name: the name of the property
- * @v: pointer to value
- * @flags: bitwise-or'd ObjectPropertyFlags
- *
- * Add an integer property in memory.  This function will add a
- * property of type 'uint32'.
- *
- * 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);
-
-ObjectProperty *object_class_property_add_uint32_ptr(ObjectClass *klass,
-                                          const char *name,
-                                          const uint32_t *v,
-                                          ObjectPropertyFlags flags);
-
-/**
- * object_property_add_uint64_ptr:
- * @obj: the object to add a property to
- * @name: the name of the property
- * @v: pointer to value
- * @flags: bitwise-or'd ObjectPropertyFlags
- *
- * Add an integer property in memory.  This function will add a
- * property of type 'uint64'.
- *
- * 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);
-
-ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass,
-                                          const char *name,
-                                          const uint64_t *v,
-                                          ObjectPropertyFlags flags);
-
 /**
  * object_property_add_alias:
  * @obj: the object to add a property to
@@ -2141,4 +2048,10 @@ char *object_property_help(const char *name, const char *type,
 
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(Object, object_unref)
 
+/*
+ * Object property ptr helpers cannot be included at the beginning of the
+ * file, because it depends on QOM definitions in current header.
+ */
+#include "qom/object-property-ptr.h"
+
 #endif
diff --git a/qom/object-property-ptr.c b/qom/object-property-ptr.c
new file mode 100644
index 0000000000..02c01ed7f0
--- /dev/null
+++ b/qom/object-property-ptr.c
@@ -0,0 +1,248 @@
+/*
+ * Object property helpers to operate on a pointer.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "qom/object.h"
+#include "qapi/visitor.h"
+
+static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
+                                   void *opaque, Error **errp)
+{
+    uint8_t value = *(uint8_t *)opaque;
+    visit_type_uint8(v, name, &value, errp);
+}
+
+static void property_set_uint8_ptr(Object *obj, Visitor *v, const char *name,
+                                   void *opaque, Error **errp)
+{
+    uint8_t *field = opaque;
+    uint8_t value;
+
+    if (!visit_type_uint8(v, name, &value, errp)) {
+        return;
+    }
+
+    *field = value;
+}
+
+static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name,
+                                    void *opaque, Error **errp)
+{
+    uint16_t value = *(uint16_t *)opaque;
+    visit_type_uint16(v, name, &value, errp);
+}
+
+static void property_set_uint16_ptr(Object *obj, Visitor *v, const char *name,
+                                    void *opaque, Error **errp)
+{
+    uint16_t *field = opaque;
+    uint16_t value;
+
+    if (!visit_type_uint16(v, name, &value, errp)) {
+        return;
+    }
+
+    *field = value;
+}
+
+static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name,
+                                    void *opaque, Error **errp)
+{
+    uint32_t value = *(uint32_t *)opaque;
+    visit_type_uint32(v, name, &value, errp);
+}
+
+static void property_set_uint32_ptr(Object *obj, Visitor *v, const char *name,
+                                    void *opaque, Error **errp)
+{
+    uint32_t *field = opaque;
+    uint32_t value;
+
+    if (!visit_type_uint32(v, name, &value, errp)) {
+        return;
+    }
+
+    *field = value;
+}
+
+static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name,
+                                    void *opaque, Error **errp)
+{
+    uint64_t value = *(uint64_t *)opaque;
+    visit_type_uint64(v, name, &value, errp);
+}
+
+static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name,
+                                    void *opaque, Error **errp)
+{
+    uint64_t *field = opaque;
+    uint64_t value;
+
+    if (!visit_type_uint64(v, name, &value, errp)) {
+        return;
+    }
+
+    *field = value;
+}
+
+ObjectProperty *
+object_property_add_uint8_ptr(Object *obj, const char *name,
+                              const uint8_t *v,
+                              ObjectPropertyFlags flags)
+{
+    ObjectPropertyAccessor *getter = NULL;
+    ObjectPropertyAccessor *setter = NULL;
+
+    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
+        getter = property_get_uint8_ptr;
+    }
+
+    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
+        setter = property_set_uint8_ptr;
+    }
+
+    return object_property_add(obj, name, "uint8",
+                               getter, setter, NULL, (void *)v);
+}
+
+ObjectProperty *
+object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
+                                    const uint8_t *v,
+                                    ObjectPropertyFlags flags)
+{
+    ObjectPropertyAccessor *getter = NULL;
+    ObjectPropertyAccessor *setter = NULL;
+
+    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
+        getter = property_get_uint8_ptr;
+    }
+
+    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
+        setter = property_set_uint8_ptr;
+    }
+
+    return object_class_property_add(klass, name, "uint8",
+                                     getter, setter, NULL, (void *)v);
+}
+
+ObjectProperty *
+object_property_add_uint16_ptr(Object *obj, const char *name,
+                               const uint16_t *v,
+                               ObjectPropertyFlags flags)
+{
+    ObjectPropertyAccessor *getter = NULL;
+    ObjectPropertyAccessor *setter = NULL;
+
+    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
+        getter = property_get_uint16_ptr;
+    }
+
+    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
+        setter = property_set_uint16_ptr;
+    }
+
+    return object_property_add(obj, name, "uint16",
+                               getter, setter, NULL, (void *)v);
+}
+
+ObjectProperty *
+object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
+                                     const uint16_t *v,
+                                     ObjectPropertyFlags flags)
+{
+    ObjectPropertyAccessor *getter = NULL;
+    ObjectPropertyAccessor *setter = NULL;
+
+    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
+        getter = property_get_uint16_ptr;
+    }
+
+    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
+        setter = property_set_uint16_ptr;
+    }
+
+    return object_class_property_add(klass, name, "uint16",
+                                     getter, setter, NULL, (void *)v);
+}
+
+ObjectProperty *
+object_property_add_uint32_ptr(Object *obj, const char *name,
+                               const uint32_t *v,
+                               ObjectPropertyFlags flags)
+{
+    ObjectPropertyAccessor *getter = NULL;
+    ObjectPropertyAccessor *setter = NULL;
+
+    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
+        getter = property_get_uint32_ptr;
+    }
+
+    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
+        setter = property_set_uint32_ptr;
+    }
+
+    return object_property_add(obj, name, "uint32",
+                               getter, setter, NULL, (void *)v);
+}
+
+ObjectProperty *
+object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
+                                     const uint32_t *v,
+                                     ObjectPropertyFlags flags)
+{
+    ObjectPropertyAccessor *getter = NULL;
+    ObjectPropertyAccessor *setter = NULL;
+
+    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
+        getter = property_get_uint32_ptr;
+    }
+
+    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
+        setter = property_set_uint32_ptr;
+    }
+
+    return object_class_property_add(klass, name, "uint32",
+                                     getter, setter, NULL, (void *)v);
+}
+
+ObjectProperty *
+object_property_add_uint64_ptr(Object *obj, const char *name,
+                               const uint64_t *v,
+                               ObjectPropertyFlags flags)
+{
+    ObjectPropertyAccessor *getter = NULL;
+    ObjectPropertyAccessor *setter = NULL;
+
+    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
+        getter = property_get_uint64_ptr;
+    }
+
+    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
+        setter = property_set_uint64_ptr;
+    }
+
+    return object_property_add(obj, name, "uint64",
+                               getter, setter, NULL, (void *)v);
+}
+
+ObjectProperty *
+object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
+                                     const uint64_t *v,
+                                     ObjectPropertyFlags flags)
+{
+    ObjectPropertyAccessor *getter = NULL;
+    ObjectPropertyAccessor *setter = NULL;
+
+    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
+        getter = property_get_uint64_ptr;
+    }
+
+    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
+        setter = property_set_uint64_ptr;
+    }
+
+    return object_class_property_add(klass, name, "uint64",
+                                     getter, setter, NULL, (void *)v);
+}
diff --git a/qom/object.c b/qom/object.c
index 0ac201de4c..fc738549dc 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -2673,246 +2673,6 @@ static char *object_get_type(Object *obj, Error **errp)
     return g_strdup(object_get_typename(obj));
 }
 
-static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
-                                   void *opaque, Error **errp)
-{
-    uint8_t value = *(uint8_t *)opaque;
-    visit_type_uint8(v, name, &value, errp);
-}
-
-static void property_set_uint8_ptr(Object *obj, Visitor *v, const char *name,
-                                   void *opaque, Error **errp)
-{
-    uint8_t *field = opaque;
-    uint8_t value;
-
-    if (!visit_type_uint8(v, name, &value, errp)) {
-        return;
-    }
-
-    *field = value;
-}
-
-static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name,
-                                    void *opaque, Error **errp)
-{
-    uint16_t value = *(uint16_t *)opaque;
-    visit_type_uint16(v, name, &value, errp);
-}
-
-static void property_set_uint16_ptr(Object *obj, Visitor *v, const char *name,
-                                    void *opaque, Error **errp)
-{
-    uint16_t *field = opaque;
-    uint16_t value;
-
-    if (!visit_type_uint16(v, name, &value, errp)) {
-        return;
-    }
-
-    *field = value;
-}
-
-static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name,
-                                    void *opaque, Error **errp)
-{
-    uint32_t value = *(uint32_t *)opaque;
-    visit_type_uint32(v, name, &value, errp);
-}
-
-static void property_set_uint32_ptr(Object *obj, Visitor *v, const char *name,
-                                    void *opaque, Error **errp)
-{
-    uint32_t *field = opaque;
-    uint32_t value;
-
-    if (!visit_type_uint32(v, name, &value, errp)) {
-        return;
-    }
-
-    *field = value;
-}
-
-static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name,
-                                    void *opaque, Error **errp)
-{
-    uint64_t value = *(uint64_t *)opaque;
-    visit_type_uint64(v, name, &value, errp);
-}
-
-static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name,
-                                    void *opaque, Error **errp)
-{
-    uint64_t *field = opaque;
-    uint64_t value;
-
-    if (!visit_type_uint64(v, name, &value, errp)) {
-        return;
-    }
-
-    *field = value;
-}
-
-ObjectProperty *
-object_property_add_uint8_ptr(Object *obj, const char *name,
-                              const uint8_t *v,
-                              ObjectPropertyFlags flags)
-{
-    ObjectPropertyAccessor *getter = NULL;
-    ObjectPropertyAccessor *setter = NULL;
-
-    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
-        getter = property_get_uint8_ptr;
-    }
-
-    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
-        setter = property_set_uint8_ptr;
-    }
-
-    return object_property_add(obj, name, "uint8",
-                               getter, setter, NULL, (void *)v);
-}
-
-ObjectProperty *
-object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
-                                    const uint8_t *v,
-                                    ObjectPropertyFlags flags)
-{
-    ObjectPropertyAccessor *getter = NULL;
-    ObjectPropertyAccessor *setter = NULL;
-
-    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
-        getter = property_get_uint8_ptr;
-    }
-
-    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
-        setter = property_set_uint8_ptr;
-    }
-
-    return object_class_property_add(klass, name, "uint8",
-                                     getter, setter, NULL, (void *)v);
-}
-
-ObjectProperty *
-object_property_add_uint16_ptr(Object *obj, const char *name,
-                               const uint16_t *v,
-                               ObjectPropertyFlags flags)
-{
-    ObjectPropertyAccessor *getter = NULL;
-    ObjectPropertyAccessor *setter = NULL;
-
-    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
-        getter = property_get_uint16_ptr;
-    }
-
-    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
-        setter = property_set_uint16_ptr;
-    }
-
-    return object_property_add(obj, name, "uint16",
-                               getter, setter, NULL, (void *)v);
-}
-
-ObjectProperty *
-object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
-                                     const uint16_t *v,
-                                     ObjectPropertyFlags flags)
-{
-    ObjectPropertyAccessor *getter = NULL;
-    ObjectPropertyAccessor *setter = NULL;
-
-    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
-        getter = property_get_uint16_ptr;
-    }
-
-    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
-        setter = property_set_uint16_ptr;
-    }
-
-    return object_class_property_add(klass, name, "uint16",
-                                     getter, setter, NULL, (void *)v);
-}
-
-ObjectProperty *
-object_property_add_uint32_ptr(Object *obj, const char *name,
-                               const uint32_t *v,
-                               ObjectPropertyFlags flags)
-{
-    ObjectPropertyAccessor *getter = NULL;
-    ObjectPropertyAccessor *setter = NULL;
-
-    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
-        getter = property_get_uint32_ptr;
-    }
-
-    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
-        setter = property_set_uint32_ptr;
-    }
-
-    return object_property_add(obj, name, "uint32",
-                               getter, setter, NULL, (void *)v);
-}
-
-ObjectProperty *
-object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
-                                     const uint32_t *v,
-                                     ObjectPropertyFlags flags)
-{
-    ObjectPropertyAccessor *getter = NULL;
-    ObjectPropertyAccessor *setter = NULL;
-
-    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
-        getter = property_get_uint32_ptr;
-    }
-
-    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
-        setter = property_set_uint32_ptr;
-    }
-
-    return object_class_property_add(klass, name, "uint32",
-                                     getter, setter, NULL, (void *)v);
-}
-
-ObjectProperty *
-object_property_add_uint64_ptr(Object *obj, const char *name,
-                               const uint64_t *v,
-                               ObjectPropertyFlags flags)
-{
-    ObjectPropertyAccessor *getter = NULL;
-    ObjectPropertyAccessor *setter = NULL;
-
-    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
-        getter = property_get_uint64_ptr;
-    }
-
-    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
-        setter = property_set_uint64_ptr;
-    }
-
-    return object_property_add(obj, name, "uint64",
-                               getter, setter, NULL, (void *)v);
-}
-
-ObjectProperty *
-object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
-                                     const uint64_t *v,
-                                     ObjectPropertyFlags flags)
-{
-    ObjectPropertyAccessor *getter = NULL;
-    ObjectPropertyAccessor *setter = NULL;
-
-    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
-        getter = property_get_uint64_ptr;
-    }
-
-    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
-        setter = property_set_uint64_ptr;
-    }
-
-    return object_class_property_add(klass, name, "uint64",
-                                     getter, setter, NULL, (void *)v);
-}
-
 typedef struct {
     Object *target_obj;
     char *target_name;
diff --git a/qom/meson.build b/qom/meson.build
index bd6f4aadd7..2c746aaa9c 100644
--- a/qom/meson.build
+++ b/qom/meson.build
@@ -3,6 +3,7 @@ qom_ss.add(files(
   'container.c',
   'object.c',
   'object_interfaces.c',
+  'object-property-ptr.c',
   'qom-qobject.c',
 ))
 if have_system
-- 
2.53.0



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

* [PATCH v2 06/10] qom: Add object_property_add_bool_ptr()
  2026-06-09 17:25 [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Peter Xu
                   ` (4 preceding siblings ...)
  2026-06-09 17:25 ` [PATCH v2 05/10] qom: Create object-property-ptr.[ch] Peter Xu
@ 2026-06-09 17:25 ` Peter Xu
  2026-06-09 23:18   ` Fabiano Rosas
  2026-06-09 17:25 ` [PATCH v2 07/10] qom: Add object_property_add_size_ptr() Peter Xu
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Peter Xu @ 2026-06-09 17:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Peter Xu,
	Paolo Bonzini, Kevin Wolf, Sana Sharma, Marc-André Lureau,
	Juraj Marcin, qemu-rust, Markus Armbruster, Mark Cave-Ayland

Add a helper to set qom property via a bool pointer.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/qom/object-property-ptr.h | 15 ++++++++++++
 qom/object-property-ptr.c         | 39 +++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/include/qom/object-property-ptr.h b/include/qom/object-property-ptr.h
index 6066c377fb..9cd8600094 100644
--- a/include/qom/object-property-ptr.h
+++ b/include/qom/object-property-ptr.h
@@ -16,6 +16,21 @@ typedef enum {
     OBJ_PROP_FLAG_READWRITE = (OBJ_PROP_FLAG_READ | OBJ_PROP_FLAG_WRITE),
 } ObjectPropertyFlags;
 
+/**
+ * object_property_add_bool_ptr:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @v: pointer to value
+ * @flags: bitwise-or'd ObjectPropertyFlags
+ *
+ * Add a property of type 'bool' to the object.
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
+ */
+ObjectProperty *
+object_property_add_bool_ptr(Object *obj, const char *name, const bool *v,
+                             ObjectPropertyFlags flags);
+
 /**
  * object_property_add_uint8_ptr:
  * @obj: the object to add a property to
diff --git a/qom/object-property-ptr.c b/qom/object-property-ptr.c
index 02c01ed7f0..49f223da7b 100644
--- a/qom/object-property-ptr.c
+++ b/qom/object-property-ptr.c
@@ -7,6 +7,26 @@
 #include "qom/object.h"
 #include "qapi/visitor.h"
 
+static void property_get_bool_ptr(Object *obj, Visitor *v, const char *name,
+                                  void *opaque, Error **errp)
+{
+    bool value = *(bool *)opaque;
+    visit_type_bool(v, name, &value, errp);
+}
+
+static void property_set_bool_ptr(Object *obj, Visitor *v, const char *name,
+                                  void *opaque, Error **errp)
+{
+    bool *field = opaque;
+    bool value;
+
+    if (!visit_type_bool(v, name, &value, errp)) {
+        return;
+    }
+
+    *field = value;
+}
+
 static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
                                    void *opaque, Error **errp)
 {
@@ -87,6 +107,25 @@ static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name,
     *field = value;
 }
 
+ObjectProperty *
+object_property_add_bool_ptr(Object *obj, const char *name,
+                             const bool *v, ObjectPropertyFlags flags)
+{
+    ObjectPropertyAccessor *getter = NULL;
+    ObjectPropertyAccessor *setter = NULL;
+
+    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
+        getter = property_get_bool_ptr;
+    }
+
+    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
+        setter = property_set_bool_ptr;
+    }
+
+    return object_property_add(obj, name, "bool",
+                               getter, setter, NULL, (void *)v);
+}
+
 ObjectProperty *
 object_property_add_uint8_ptr(Object *obj, const char *name,
                               const uint8_t *v,
-- 
2.53.0



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

* [PATCH v2 07/10] qom: Add object_property_add_size_ptr()
  2026-06-09 17:25 [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Peter Xu
                   ` (5 preceding siblings ...)
  2026-06-09 17:25 ` [PATCH v2 06/10] qom: Add object_property_add_bool_ptr() Peter Xu
@ 2026-06-09 17:25 ` Peter Xu
  2026-06-09 23:18   ` Fabiano Rosas
  2026-06-09 17:25 ` [PATCH v2 08/10] qom: Add object_property_add_*_ptr_def() Peter Xu
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Peter Xu @ 2026-06-09 17:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Peter Xu,
	Paolo Bonzini, Kevin Wolf, Sana Sharma, Marc-André Lureau,
	Juraj Marcin, qemu-rust, Markus Armbruster, Mark Cave-Ayland

Add a helper to set qom property via a size pointer.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/qom/object-property-ptr.h | 16 +++++++++++++
 qom/object-property-ptr.c         | 40 +++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/include/qom/object-property-ptr.h b/include/qom/object-property-ptr.h
index 9cd8600094..be467c64af 100644
--- a/include/qom/object-property-ptr.h
+++ b/include/qom/object-property-ptr.h
@@ -115,4 +115,20 @@ ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass,
                                           const uint64_t *v,
                                           ObjectPropertyFlags flags);
 
+/**
+ * object_property_add_size_ptr:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @v: pointer to value
+ * @flags: bitwise-or'd ObjectPropertyFlags
+ *
+ * Add a property of type 'size' to the object.
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
+ */
+ObjectProperty *
+object_property_add_size_ptr(Object *obj, const char *name,
+                             const uint64_t *v,
+                             ObjectPropertyFlags flags);
+
 #endif
diff --git a/qom/object-property-ptr.c b/qom/object-property-ptr.c
index 49f223da7b..21ceb2510d 100644
--- a/qom/object-property-ptr.c
+++ b/qom/object-property-ptr.c
@@ -107,6 +107,26 @@ static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name,
     *field = value;
 }
 
+static void property_get_size_ptr(Object *obj, Visitor *v, const char *name,
+                                  void *opaque, Error **errp)
+{
+    uint64_t value = *(uint64_t *)opaque;
+    visit_type_size(v, name, &value, errp);
+}
+
+static void property_set_size_ptr(Object *obj, Visitor *v, const char *name,
+                                  void *opaque, Error **errp)
+{
+    uint64_t *field = opaque;
+    uint64_t value;
+
+    if (!visit_type_size(v, name, &value, errp)) {
+        return;
+    }
+
+    *field = value;
+}
+
 ObjectProperty *
 object_property_add_bool_ptr(Object *obj, const char *name,
                              const bool *v, ObjectPropertyFlags flags)
@@ -285,3 +305,23 @@ object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
     return object_class_property_add(klass, name, "uint64",
                                      getter, setter, NULL, (void *)v);
 }
+
+ObjectProperty *
+object_property_add_size_ptr(Object *obj, const char *name,
+                             const uint64_t *v,
+                             ObjectPropertyFlags flags)
+{
+    ObjectPropertyAccessor *getter = NULL;
+    ObjectPropertyAccessor *setter = NULL;
+
+    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
+        getter = property_get_size_ptr;
+    }
+
+    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
+        setter = property_set_size_ptr;
+    }
+
+    return object_property_add(obj, name, "size",
+                               getter, setter, NULL, (void *)v);
+}
-- 
2.53.0



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

* [PATCH v2 08/10] qom: Add object_property_add_*_ptr_def()
  2026-06-09 17:25 [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Peter Xu
                   ` (6 preceding siblings ...)
  2026-06-09 17:25 ` [PATCH v2 07/10] qom: Add object_property_add_size_ptr() Peter Xu
@ 2026-06-09 17:25 ` Peter Xu
  2026-06-09 23:21   ` Fabiano Rosas
  2026-06-09 17:25 ` [PATCH v2 09/10] qom: Allow default values for instance properties Peter Xu
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Peter Xu @ 2026-06-09 17:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Peter Xu,
	Paolo Bonzini, Kevin Wolf, Sana Sharma, Marc-André Lureau,
	Juraj Marcin, qemu-rust, Markus Armbruster, Mark Cave-Ayland

Add sister functions for existing pointer versions, to make it even easier
to use by:

- always make properties to be rw-able
- allowing to specify default values
- no retcode needed (assert on failure, always)

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/qom/object-property-ptr.h | 28 +++++++++++++
 qom/object-property-ptr.c         | 67 +++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+)

diff --git a/include/qom/object-property-ptr.h b/include/qom/object-property-ptr.h
index be467c64af..ecd6f7819b 100644
--- a/include/qom/object-property-ptr.h
+++ b/include/qom/object-property-ptr.h
@@ -131,4 +131,32 @@ object_property_add_size_ptr(Object *obj, const char *name,
                              const uint64_t *v,
                              ObjectPropertyFlags flags);
 
+/*
+ * Below are sister helpers of above, except that:
+ *
+ * (1) nothing is returned
+ * (2) always make the property to be both readable and writeable
+ * (3) allow setting default value
+ *
+ * Please refer to the sister functions for the documentation.
+ */
+void
+object_property_add_bool_ptr_def(Object *obj, const char *name,
+                                 const bool *v, bool def);
+void
+object_property_add_uint8_ptr_def(Object *obj, const char *name,
+                                  const uint8_t *v, uint8_t def);
+void
+object_property_add_uint16_ptr_def(Object *obj, const char *name,
+                                   const uint16_t *v, uint16_t def);
+void
+object_property_add_uint32_ptr_def(Object *obj, const char *name,
+                                   const uint32_t *v, uint32_t def);
+void
+object_property_add_uint64_ptr_def(Object *obj, const char *name,
+                                   const uint64_t *v, uint64_t def);
+void
+object_property_add_size_ptr_def(Object *obj, const char *name,
+                                 const uint64_t *v, uint64_t def);
+
 #endif
diff --git a/qom/object-property-ptr.c b/qom/object-property-ptr.c
index 21ceb2510d..ae9081d2d8 100644
--- a/qom/object-property-ptr.c
+++ b/qom/object-property-ptr.c
@@ -325,3 +325,70 @@ object_property_add_size_ptr(Object *obj, const char *name,
     return object_property_add(obj, name, "size",
                                getter, setter, NULL, (void *)v);
 }
+
+void
+object_property_add_bool_ptr_def(Object *obj, const char *name,
+                                 const bool *v, bool def)
+{
+    ObjectProperty *prop;
+
+    prop = object_property_add_bool_ptr(obj, name, v,
+                                        OBJ_PROP_FLAG_READWRITE);
+    object_property_set_default_bool(prop, def);
+}
+
+
+void
+object_property_add_uint8_ptr_def(Object *obj, const char *name,
+                                  const uint8_t *v, uint8_t def)
+{
+    ObjectProperty *prop;
+
+    prop = object_property_add_uint8_ptr(obj, name, v,
+                                         OBJ_PROP_FLAG_READWRITE);
+    object_property_set_default_uint(prop, def);
+}
+
+void
+object_property_add_uint16_ptr_def(Object *obj, const char *name,
+                                   const uint16_t *v, uint16_t def)
+{
+    ObjectProperty *prop;
+
+    prop = object_property_add_uint16_ptr(obj, name, v,
+                                          OBJ_PROP_FLAG_READWRITE);
+    object_property_set_default_uint(prop, def);
+}
+
+void
+object_property_add_uint32_ptr_def(Object *obj, const char *name,
+                                   const uint32_t *v, uint32_t def)
+{
+    ObjectProperty *prop;
+
+    prop = object_property_add_uint32_ptr(obj, name, v,
+                                          OBJ_PROP_FLAG_READWRITE);
+    object_property_set_default_uint(prop, def);
+}
+
+void
+object_property_add_uint64_ptr_def(Object *obj, const char *name,
+                                   const uint64_t *v, uint64_t def)
+{
+    ObjectProperty *prop;
+
+    prop = object_property_add_uint64_ptr(obj, name, v,
+                                          OBJ_PROP_FLAG_READWRITE);
+    object_property_set_default_uint(prop, def);
+}
+
+void
+object_property_add_size_ptr_def(Object *obj, const char *name,
+                                 const uint64_t *v, uint64_t def)
+{
+    ObjectProperty *prop;
+
+    prop = object_property_add_size_ptr(obj, name, v,
+                                        OBJ_PROP_FLAG_READWRITE);
+    object_property_set_default_uint(prop, def);
+}
-- 
2.53.0



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

* [PATCH v2 09/10] qom: Allow default values for instance properties
  2026-06-09 17:25 [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Peter Xu
                   ` (7 preceding siblings ...)
  2026-06-09 17:25 ` [PATCH v2 08/10] qom: Add object_property_add_*_ptr_def() Peter Xu
@ 2026-06-09 17:25 ` Peter Xu
  2026-06-10 16:19   ` Daniel P. Berrangé
  2026-06-09 17:25 ` [PATCH v2 10/10] migration: Switch to TYPE_OBJECT with object properties Peter Xu
  2026-06-09 22:54 ` [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Fabiano Rosas
  10 siblings, 1 reply; 30+ messages in thread
From: Peter Xu @ 2026-06-09 17:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Peter Xu,
	Paolo Bonzini, Kevin Wolf, Sana Sharma, Marc-André Lureau,
	Juraj Marcin, qemu-rust, Markus Armbruster, Mark Cave-Ayland

ObjectProperty allows default value settings via proper setup of
prop->init() and prop->defval.  It currently is only supported in class
properties, not instance properties.

However, since QOM allows class and instance properties, it should also
allow instance to add properties during instance_init() and allow the
default values to be applied properly for this instance only.

Add the logic.  It will be useful for all kinds of pointer based properties
because pointers are normally not accessble in a class but only when an
instance is available.  This will be able to achieve similar function as
what qdev properties have (which works by remembering offsets within a
structure instead).

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 qom/object.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/qom/object.c b/qom/object.c
index fc738549dc..eaef615924 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -487,6 +487,20 @@ static void object_class_property_init_all(Object *obj)
     }
 }
 
+static void object_property_init_all(Object *obj)
+{
+    GHashTableIter iter;
+    gpointer key, val;
+
+    g_hash_table_iter_init(&iter, obj->properties);
+    while (g_hash_table_iter_next(&iter, &key, &val)) {
+        ObjectProperty *prop = val;
+        if (prop->init) {
+            prop->init(obj, prop);
+        }
+    }
+}
+
 static void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type)
 {
     type_initialize(type);
@@ -498,10 +512,22 @@ static void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type
     memset(obj, 0, type->instance_size);
     obj->class = type->class;
     object_ref(obj);
+    /*
+     * A few steps to initialize properties for the objects:
+     *
+     * (1) apply default values from class properties when available
+     * (2) invoke instance_init(), which may add per-instance properties,
+     *     which may further contain default values
+     * (3) apply default values from instance properties when available
+     *
+     * instance_post_init() should happen at last, after the instance is
+     * fully initialized.
+     */
     object_class_property_init_all(obj);
     obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal,
                                             NULL, object_property_free);
     object_init_with_type(obj, type);
+    object_property_init_all(obj);
     object_post_init_with_type(obj, type);
 }
 
-- 
2.53.0



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

* [PATCH v2 10/10] migration: Switch to TYPE_OBJECT with object properties
  2026-06-09 17:25 [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Peter Xu
                   ` (8 preceding siblings ...)
  2026-06-09 17:25 ` [PATCH v2 09/10] qom: Allow default values for instance properties Peter Xu
@ 2026-06-09 17:25 ` Peter Xu
  2026-06-10 16:13   ` Daniel P. Berrangé
  2026-06-10 16:29   ` Daniel P. Berrangé
  2026-06-09 22:54 ` [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Fabiano Rosas
  10 siblings, 2 replies; 30+ messages in thread
From: Peter Xu @ 2026-06-09 17:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Peter Xu,
	Paolo Bonzini, Kevin Wolf, Sana Sharma, Marc-André Lureau,
	Juraj Marcin, qemu-rust, Markus Armbruster, Mark Cave-Ayland

The migration object used to depend on TYPE_DEVICE due to:

- Usage of qdev properties
- Apply compat properties and global properties

This patch re-based the object to TYPE_OBJECT with the changes:

- Switch to object properties API
- Manually apply both compat and global properties in post_init()

Note that to avoid too many property getter/setter helpers, this patch used
the object_property_add_*_ptr_def() APIs so that an pointer is passed to
bind to the property.  Such API is used for most of the conversions.

After patch, the migration object initializes instance properties within
its instance_init() callback, in migrate_params_init().

One side effect of this change is, since we switched to a loop to add all
capabilities, the name of the properties representing a migration
capability may chance from previously hard-coded ones (many with x-).  It's
fine since it's only used in -global so it's only for debugging.

Similarly, I removed "x-" from other properites that used to start with
"x-" but actually are not experimental.

After the whole conversion, we don't need migration_properties or the count
anymore, hence can be removed.  While at it, we can also remove two
DEFINE_PROP*() API that only migration uses (DEFINE_PROP_STR_OR_NULL, and
DEFINE_PROP_MIG_CAP).

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 migration/options.h   |   8 +-
 migration/migration.c |  35 ++-
 migration/options.c   | 526 ++++++++++++++++++++++++++----------------
 3 files changed, 351 insertions(+), 218 deletions(-)

diff --git a/migration/options.h b/migration/options.h
index b46221998a..eadbb8cf61 100644
--- a/migration/options.h
+++ b/migration/options.h
@@ -18,11 +18,6 @@
 #include "hw/core/qdev-properties-system.h"
 #include "migration/client-options.h"
 
-/* migration properties */
-
-extern const Property migration_properties[];
-extern const size_t migration_properties_count;
-
 /* capabilities */
 
 bool migrate_auto_converge(void);
@@ -92,6 +87,7 @@ uint64_t migrate_rdma_chunk_size(void);
 /* parameters helpers */
 
 bool migrate_params_check(MigrationParameters *params, Error **errp);
-void migrate_params_init(MigrationParameters *params);
+void migrate_params_init(MigrationState *s);
 void migrate_tls_opts_free(MigrationParameters *params);
+
 #endif
diff --git a/migration/migration.c b/migration/migration.c
index 278cad502a..ae0c373549 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -3964,15 +3964,6 @@ fail:
     }
 }
 
-static void migration_class_init(ObjectClass *klass, const void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    dc->user_creatable = false;
-    device_class_set_props_n(dc, migration_properties,
-                             migration_properties_count);
-}
-
 static void migration_instance_finalize(Object *obj)
 {
     MigrationState *ms = MIGRATION(obj);
@@ -4001,7 +3992,7 @@ static void migration_instance_init(Object *obj)
     qemu_event_init(&ms->pause_event, false);
     qemu_mutex_init(&ms->error_mutex);
 
-    migrate_params_init(&ms->parameters);
+    migrate_params_init(ms);
 
     qemu_sem_init(&ms->postcopy_pause_sem, 0);
     qemu_sem_init(&ms->rp_state.rp_sem, 0);
@@ -4028,20 +4019,26 @@ static bool migration_object_check(MigrationState *ms, Error **errp)
     return migrate_caps_check(old_caps, ms->capabilities, errp);
 }
 
-static const TypeInfo migration_type = {
-    .name = TYPE_MIGRATION,
+static void migration_instance_post_init(Object *obj)
+{
     /*
-     * NOTE: TYPE_MIGRATION is not really a device, as the object is
-     * not created using qdev_new(), it is not attached to the qdev
-     * device tree, and it is never realized.
+     * Apply these properties on top of default values:
+     *
+     * (1) machine compat properties
+     * (2) -global settings in cmdlines
      *
-     * TODO: Make this TYPE_OBJECT once QOM provides something like
-     * TYPE_DEVICE's "-global" properties.
+     * Need to be applied in order so (2) takes precedence over (1).
      */
-    .parent = TYPE_DEVICE,
-    .class_init = migration_class_init,
+    object_apply_compat_props(obj);
+    object_apply_global_props(obj, global_props(), &error_fatal);
+}
+
+static const TypeInfo migration_type = {
+    .name = TYPE_MIGRATION,
+    .parent = TYPE_OBJECT,
     .instance_size = sizeof(MigrationState),
     .instance_init = migration_instance_init,
+    .instance_post_init = migration_instance_post_init,
     .instance_finalize = migration_instance_finalize,
 };
 
diff --git a/migration/options.c b/migration/options.c
index 5cbfd29099..1cc99382d3 100644
--- a/migration/options.c
+++ b/migration/options.c
@@ -54,7 +54,7 @@
 /* The delay time (in ms) between two COLO checkpoints */
 #define DEFAULT_MIGRATE_X_CHECKPOINT_DELAY (200 * 100)
 #define DEFAULT_MIGRATE_MULTIFD_CHANNELS 2
-#define DEFAULT_MIGRATE_MULTIFD_COMPRESSION MULTIFD_COMPRESSION_NONE
+#define DEFAULT_MIGRATE_MULTIFD_COMPRESSION "none"
 /* 0: means nocompress, 1: best speed, ... 9: best compress ratio */
 #define DEFAULT_MIGRATE_MULTIFD_ZLIB_LEVEL 1
 /*
@@ -81,216 +81,355 @@
 #define DEFAULT_MIGRATE_ANNOUNCE_ROUNDS    5
 #define DEFAULT_MIGRATE_ANNOUNCE_STEP    100
 
-#define DEFINE_PROP_MIG_CAP(name, x)             \
-    DEFINE_PROP_BOOL(name, MigrationState, capabilities[x], false)
-
-const PropertyInfo qdev_prop_StrOrNull;
-#define DEFINE_PROP_STR_OR_NULL(_name, _state, _field)                  \
-    DEFINE_PROP(_name, _state, _field, qdev_prop_StrOrNull, StrOrNull *, \
-                .set_default = true)
-
 #define DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT_PERIOD     1000    /* milliseconds */
 #define DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT            1       /* MB/s */
 #define DEFAULT_MIGRATE_X_RDMA_CHUNK_SIZE           MiB
 
-const Property migration_properties[] = {
-    DEFINE_PROP_BOOL("store-global-state", MigrationState,
-                     store_global_state, true),
-    DEFINE_PROP_BOOL("send-configuration", MigrationState,
-                     send_configuration, true),
-    DEFINE_PROP_BOOL("send-section-footer", MigrationState,
-                     send_section_footer, true),
-    DEFINE_PROP_BOOL("send-switchover-start", MigrationState,
-                     send_switchover_start, true),
-    DEFINE_PROP_BOOL("multifd-flush-after-each-section", MigrationState,
-                      multifd_flush_after_each_section, false),
-    DEFINE_PROP_UINT8("x-clear-bitmap-shift", MigrationState,
-                      clear_bitmap_shift, CLEAR_BITMAP_SHIFT_DEFAULT),
-    DEFINE_PROP_BOOL("x-preempt-pre-7-2", MigrationState,
-                     preempt_pre_7_2, false),
-    DEFINE_PROP_BOOL("multifd-clean-tls-termination", MigrationState,
-                     multifd_clean_tls_termination, true),
-
-    /* Migration parameters */
-    DEFINE_PROP_UINT8("x-throttle-trigger-threshold", MigrationState,
-                      parameters.throttle_trigger_threshold,
-                      DEFAULT_MIGRATE_THROTTLE_TRIGGER_THRESHOLD),
-    DEFINE_PROP_UINT8("x-cpu-throttle-initial", MigrationState,
-                      parameters.cpu_throttle_initial,
-                      DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL),
-    DEFINE_PROP_UINT8("x-cpu-throttle-increment", MigrationState,
-                      parameters.cpu_throttle_increment,
-                      DEFAULT_MIGRATE_CPU_THROTTLE_INCREMENT),
-    DEFINE_PROP_BOOL("x-cpu-throttle-tailslow", MigrationState,
-                      parameters.cpu_throttle_tailslow, false),
-    DEFINE_PROP_SIZE("x-max-bandwidth", MigrationState,
-                      parameters.max_bandwidth, MAX_THROTTLE),
-    DEFINE_PROP_SIZE("avail-switchover-bandwidth", MigrationState,
-                      parameters.avail_switchover_bandwidth, 0),
-    DEFINE_PROP_UINT64("x-downtime-limit", MigrationState,
-                      parameters.downtime_limit,
-                      DEFAULT_MIGRATE_SET_DOWNTIME),
-    DEFINE_PROP_UINT32("x-checkpoint-delay", MigrationState,
-                      parameters.x_checkpoint_delay,
-                      DEFAULT_MIGRATE_X_CHECKPOINT_DELAY),
-    DEFINE_PROP_UINT8("multifd-channels", MigrationState,
-                      parameters.multifd_channels,
-                      DEFAULT_MIGRATE_MULTIFD_CHANNELS),
-    DEFINE_PROP_MULTIFD_COMPRESSION("multifd-compression", MigrationState,
-                      parameters.multifd_compression,
-                      DEFAULT_MIGRATE_MULTIFD_COMPRESSION),
-    DEFINE_PROP_UINT8("multifd-zlib-level", MigrationState,
-                      parameters.multifd_zlib_level,
-                      DEFAULT_MIGRATE_MULTIFD_ZLIB_LEVEL),
-    DEFINE_PROP_UINT8("multifd-qatzip-level", MigrationState,
-                      parameters.multifd_qatzip_level,
-                      DEFAULT_MIGRATE_MULTIFD_QATZIP_LEVEL),
-    DEFINE_PROP_UINT8("multifd-zstd-level", MigrationState,
-                      parameters.multifd_zstd_level,
-                      DEFAULT_MIGRATE_MULTIFD_ZSTD_LEVEL),
-    DEFINE_PROP_SIZE("xbzrle-cache-size", MigrationState,
-                      parameters.xbzrle_cache_size,
-                      DEFAULT_MIGRATE_XBZRLE_CACHE_SIZE),
-    DEFINE_PROP_SIZE("max-postcopy-bandwidth", MigrationState,
-                      parameters.max_postcopy_bandwidth,
-                      DEFAULT_MIGRATE_MAX_POSTCOPY_BANDWIDTH),
-    DEFINE_PROP_UINT8("max-cpu-throttle", MigrationState,
-                      parameters.max_cpu_throttle,
-                      DEFAULT_MIGRATE_MAX_CPU_THROTTLE),
-    DEFINE_PROP_SIZE("announce-initial", MigrationState,
-                      parameters.announce_initial,
-                      DEFAULT_MIGRATE_ANNOUNCE_INITIAL),
-    DEFINE_PROP_SIZE("announce-max", MigrationState,
-                      parameters.announce_max,
-                      DEFAULT_MIGRATE_ANNOUNCE_MAX),
-    DEFINE_PROP_SIZE("announce-rounds", MigrationState,
-                      parameters.announce_rounds,
-                      DEFAULT_MIGRATE_ANNOUNCE_ROUNDS),
-    DEFINE_PROP_SIZE("announce-step", MigrationState,
-                      parameters.announce_step,
-                      DEFAULT_MIGRATE_ANNOUNCE_STEP),
-    DEFINE_PROP_STR_OR_NULL("tls-creds", MigrationState, parameters.tls_creds),
-    DEFINE_PROP_STR_OR_NULL("tls-hostname", MigrationState,
-                            parameters.tls_hostname),
-    DEFINE_PROP_STR_OR_NULL("tls-authz", MigrationState, parameters.tls_authz),
-    DEFINE_PROP_UINT64("x-vcpu-dirty-limit-period", MigrationState,
-                       parameters.x_vcpu_dirty_limit_period,
-                       DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT_PERIOD),
-    DEFINE_PROP_UINT64("vcpu-dirty-limit", MigrationState,
-                       parameters.vcpu_dirty_limit,
-                       DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT),
-    DEFINE_PROP_MIG_MODE("mode", MigrationState,
-                      parameters.mode,
-                      MIG_MODE_NORMAL),
-    DEFINE_PROP_ZERO_PAGE_DETECTION("zero-page-detection", MigrationState,
-                       parameters.zero_page_detection,
-                       ZERO_PAGE_DETECTION_MULTIFD),
-    DEFINE_PROP_UINT64("x-rdma-chunk-size", MigrationState,
-                      parameters.x_rdma_chunk_size,
-                      DEFAULT_MIGRATE_X_RDMA_CHUNK_SIZE),
-
-    /* Migration capabilities */
-    DEFINE_PROP_MIG_CAP("x-xbzrle", MIGRATION_CAPABILITY_XBZRLE),
-    DEFINE_PROP_MIG_CAP("x-rdma-pin-all", MIGRATION_CAPABILITY_RDMA_PIN_ALL),
-    DEFINE_PROP_MIG_CAP("x-auto-converge", MIGRATION_CAPABILITY_AUTO_CONVERGE),
-    DEFINE_PROP_MIG_CAP("x-events", MIGRATION_CAPABILITY_EVENTS),
-    DEFINE_PROP_MIG_CAP("x-postcopy-ram", MIGRATION_CAPABILITY_POSTCOPY_RAM),
-    DEFINE_PROP_MIG_CAP("x-postcopy-preempt",
-                        MIGRATION_CAPABILITY_POSTCOPY_PREEMPT),
-    DEFINE_PROP_MIG_CAP("postcopy-blocktime",
-                        MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME),
-    DEFINE_PROP_MIG_CAP("x-colo", MIGRATION_CAPABILITY_X_COLO),
-    DEFINE_PROP_MIG_CAP("x-release-ram", MIGRATION_CAPABILITY_RELEASE_RAM),
-    DEFINE_PROP_MIG_CAP("x-return-path", MIGRATION_CAPABILITY_RETURN_PATH),
-    DEFINE_PROP_MIG_CAP("x-multifd", MIGRATION_CAPABILITY_MULTIFD),
-    DEFINE_PROP_MIG_CAP("x-background-snapshot",
-            MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT),
-#ifdef CONFIG_LINUX
-    DEFINE_PROP_MIG_CAP("x-zero-copy-send",
-            MIGRATION_CAPABILITY_ZERO_COPY_SEND),
-#endif
-    DEFINE_PROP_MIG_CAP("x-switchover-ack",
-                        MIGRATION_CAPABILITY_SWITCHOVER_ACK),
-    DEFINE_PROP_MIG_CAP("x-dirty-limit", MIGRATION_CAPABILITY_DIRTY_LIMIT),
-    DEFINE_PROP_MIG_CAP("mapped-ram", MIGRATION_CAPABILITY_MAPPED_RAM),
-    DEFINE_PROP_MIG_CAP("x-ignore-shared",
-                        MIGRATION_CAPABILITY_X_IGNORE_SHARED),
-};
-const size_t migration_properties_count = ARRAY_SIZE(migration_properties);
-
-static void get_StrOrNull(Object *obj, Visitor *v, const char *name,
-                          void *opaque, Error **errp)
+static void migration_object_init_props_bool(MigrationState *s)
 {
-    const Property *prop = opaque;
-    StrOrNull **ptr = object_field_prop_ptr(obj, prop);
-    StrOrNull *str_or_null = *ptr;
+    Object *obj = OBJECT(s);
+    int i;
 
-    /*
-     * The property should never be NULL because it's part of
-     * s->parameters and a default value is always set by qdev. It
-     * should also never be QNULL as the setter doesn't allow it.
-     */
-    assert(str_or_null && str_or_null->type != QTYPE_QNULL);
-    visit_type_str(v, name, &str_or_null->u.s, errp);
+    struct MigPropBool {
+        const char *name;
+        void *ptr;
+        bool defvar;
+    } bool_list[] = {
+        {
+            "store-global-state",
+            &s->store_global_state,
+            true,
+        },
+        {
+            "send-configuration",
+            &s->send_configuration,
+            true,
+        },
+        {
+            "send-section-footer",
+            &s->send_section_footer,
+            true,
+        },
+        {
+            "send-switchover-start",
+            &s->send_switchover_start,
+            true,
+        },
+        {
+            "x-preempt-pre-7-2",
+            &s->preempt_pre_7_2,
+            false,
+        },
+        {
+            "x-cpu-throttle-tailslow",
+            &s->parameters.cpu_throttle_tailslow,
+            false,
+        },
+        {
+            "multifd-clean-tls-termination",
+            &s->multifd_clean_tls_termination,
+            true,
+        },
+        {
+            "multifd-flush-after-each-section",
+            &s->multifd_flush_after_each_section,
+            false,
+        },
+    };
+    struct MigPropBool *prop;
+
+    for (i = 0; i < ARRAY_SIZE(bool_list); i++) {
+        prop = &bool_list[i];
+        object_property_add_bool_ptr_def(obj, prop->name,
+                                         prop->ptr, prop->defvar);
+    }
 }
 
-static void set_StrOrNull(Object *obj, Visitor *v, const char *name,
-                          void *opaque, Error **errp)
+static void migration_object_init_props_uint8(MigrationState *s)
 {
-    const Property *prop = opaque;
-    StrOrNull **ptr = object_field_prop_ptr(obj, prop);
-    StrOrNull *str_or_null;
-    char *str;
+    Object *obj = OBJECT(s);
+    int i;
 
-    if (!visit_type_str(v, name, &str, errp)) {
-        return;
-    }
+    struct MigPropUint8 {
+        const char *name;
+        void *ptr;
+        uint8_t defvar;
+    } uint8_list[] = {
+        {
+            "clear-bitmap-shift",
+            &s->clear_bitmap_shift,
+            CLEAR_BITMAP_SHIFT_DEFAULT,
+        },
+        {
+            "throttle-trigger-threshold",
+            &s->parameters.throttle_trigger_threshold,
+            DEFAULT_MIGRATE_THROTTLE_TRIGGER_THRESHOLD,
+        },
+        {
+            "cpu-throttle-initial",
+            &s->parameters.cpu_throttle_initial,
+            DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL,
+        },
+        {
+            "cpu-throttle-increment",
+            &s->parameters.cpu_throttle_increment,
+            DEFAULT_MIGRATE_CPU_THROTTLE_INCREMENT,
+        },
+        {
+            "multifd-channels",
+            &s->parameters.multifd_channels,
+            DEFAULT_MIGRATE_MULTIFD_CHANNELS,
+        },
+        {
+            "multifd-zlib-level",
+            &s->parameters.multifd_zlib_level,
+            DEFAULT_MIGRATE_MULTIFD_ZLIB_LEVEL,
+        },
+        {
+            "multifd-qatzip-level",
+            &s->parameters.multifd_qatzip_level,
+            DEFAULT_MIGRATE_MULTIFD_QATZIP_LEVEL,
+        },
+        {
+            "multifd-zstd-level",
+            &s->parameters.multifd_zstd_level,
+            DEFAULT_MIGRATE_MULTIFD_ZSTD_LEVEL,
+        },
+        {
+            "max-cpu-throttle",
+            &s->parameters.max_cpu_throttle,
+            DEFAULT_MIGRATE_MAX_CPU_THROTTLE,
+        },
+    };
+    struct MigPropUint8 *prop;
 
-    /*
-     * This property only applies to the command line usage of
-     * migration's TLS options (-global migration.tls-*) where the
-     * NULL value cannot be provided as input (only strings are
-     * allowed). Therefore, this StrOrNull implementation never
-     * produces a QNULL value to avoid ever returning values outside
-     * the range of what was previously handled by consumers of the
-     * TLS options.
-     */
-    str_or_null = g_new0(StrOrNull, 1);
-    str_or_null->type = QTYPE_QSTRING;
-    str_or_null->u.s = str;
+    for (i = 0; i < ARRAY_SIZE(uint8_list); i++) {
+        prop = &uint8_list[i];
+        object_property_add_uint8_ptr_def(obj, prop->name,
+                                          prop->ptr, prop->defvar);
+    }
+}
 
-    qapi_free_StrOrNull(*ptr);
-    *ptr = str_or_null;
+static void migration_object_init_props_uint32(MigrationState *s)
+{
+    object_property_add_uint32_ptr_def(OBJECT(s), "x-checkpoint-delay",
+                                       &s->parameters.x_checkpoint_delay,
+                                       DEFAULT_MIGRATE_X_CHECKPOINT_DELAY);
 }
 
-static void release_StrOrNull(Object *obj, const char *name, void *opaque)
+static void migration_object_init_props_uint64(MigrationState *s)
 {
-    const Property *prop = opaque;
-    qapi_free_StrOrNull(*(StrOrNull **)object_field_prop_ptr(obj, prop));
+    Object *obj = OBJECT(s);
+    int i;
+
+    struct MigPropUint64 {
+        const char *name;
+        void *ptr;
+        uint64_t defvar;
+    } uint64_list[] = {
+        {
+            "downtime-limit",
+            &s->parameters.downtime_limit,
+            DEFAULT_MIGRATE_SET_DOWNTIME,
+        },
+        {
+            "x-vcpu-dirty-limit-period",
+            &s->parameters.x_vcpu_dirty_limit_period,
+            DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT_PERIOD,
+        },
+        {
+            "vcpu-dirty-limit",
+            &s->parameters.vcpu_dirty_limit,
+            DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT,
+        },
+        {
+            "x-rdma-chunk-size",
+            &s->parameters.x_rdma_chunk_size,
+            DEFAULT_MIGRATE_X_RDMA_CHUNK_SIZE,
+        },
+    };
+    struct MigPropUint64 *prop;
+
+    for (i = 0; i < ARRAY_SIZE(uint64_list); i++) {
+        prop = &uint64_list[i];
+        object_property_add_uint64_ptr_def(obj, prop->name,
+                                           prop->ptr, prop->defvar);
+    }
 }
 
-static void set_default_value_tls_opt(ObjectProperty *op, const Property *prop)
+static void migration_object_init_props_size(MigrationState *s)
 {
-    /*
-     * Initialization to the empty string here is important so
-     * query-migrate-parameters doesn't need to deal with a NULL value
-     * when it's called before any TLS option has been set.
-     */
-    object_property_set_default_str(op, "");
+    Object *obj = OBJECT(s);
+    int i;
+
+    struct MigPropSize {
+        const char *name;
+        void *ptr;
+        uint64_t defvar;
+    } size_list[] = {
+        {
+            "xbzrle-cache-size",
+            &s->parameters.xbzrle_cache_size,
+            DEFAULT_MIGRATE_XBZRLE_CACHE_SIZE,
+        },
+        {
+            "max-postcopy-bandwidth",
+            &s->parameters.max_postcopy_bandwidth,
+            DEFAULT_MIGRATE_MAX_POSTCOPY_BANDWIDTH,
+        },
+        {
+            "announce-initial",
+            &s->parameters.announce_initial,
+            DEFAULT_MIGRATE_ANNOUNCE_INITIAL,
+        },
+        {
+            "announce-max",
+            &s->parameters.announce_max,
+            DEFAULT_MIGRATE_ANNOUNCE_MAX,
+        },
+        {
+            "announce-rounds",
+            &s->parameters.announce_rounds,
+            DEFAULT_MIGRATE_ANNOUNCE_ROUNDS,
+        },
+        {
+            "announce-step",
+            &s->parameters.announce_step,
+            DEFAULT_MIGRATE_ANNOUNCE_STEP,
+        },
+        {
+            "max-bandwidth",
+            &s->parameters.max_bandwidth,
+            MAX_THROTTLE,
+        },
+        {
+            "avail-switchover-bandwidth",
+            &s->parameters.avail_switchover_bandwidth,
+            0,
+        },
+    };
+    struct MigPropSize *prop;
+
+    for (i = 0; i < ARRAY_SIZE(size_list); i++) {
+        prop = &size_list[i];
+        object_property_add_size_ptr_def(obj, prop->name,
+                                         prop->ptr, prop->defvar);
+    }
 }
 
-/*
- * String property like qdev_prop_string, except it's backed by a
- * StrOrNull instead of a char *.  This is intended for
- * TYPE_MIGRATION's TLS options.
- */
-const PropertyInfo qdev_prop_StrOrNull = {
-    .type  = "StrOrNull",
-    .get = get_StrOrNull,
-    .set = set_StrOrNull,
-    .release = release_StrOrNull,
-    .set_default_value = set_default_value_tls_opt,
-};
+static void migration_object_init_props_caps(MigrationState *s)
+{
+    Object *obj = OBJECT(s);
+    int i;
+
+    /* Migration capabilties are always turned off by default */
+    for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
+        object_property_add_bool_ptr_def(obj,
+                                         MigrationCapability_str(i),
+                                         &s->capabilities[i],
+                                         false);
+    }
+}
+
+#define  DEFINE_TLS_PROP_HELPERS(varname)                               \
+    static char *mig_prop_##varname##_get(Object *obj, Error **errp)    \
+    {                                                                   \
+        MigrationState *s = MIGRATION(obj);                             \
+        StrOrNull *var = s->parameters.varname;                         \
+                                                                        \
+        assert(var->type == QTYPE_QSTRING);                             \
+        return g_strdup(var->u.s);                                      \
+    }                                                                   \
+                                                                        \
+    static void mig_prop_##varname##_set(Object *obj, const char *str,  \
+                                         Error **errp)                  \
+    {                                                                   \
+        MigrationState *s = MIGRATION(obj);                             \
+        StrOrNull *new = g_new0(StrOrNull, 1);                          \
+                                                                        \
+        qapi_free_StrOrNull(s->parameters.varname);                     \
+                                                                        \
+        new->type = QTYPE_QSTRING;                                      \
+        new->u.s = g_strdup(str);                                       \
+        s->parameters.varname = new;                                    \
+    }
+
+DEFINE_TLS_PROP_HELPERS(tls_creds)
+DEFINE_TLS_PROP_HELPERS(tls_authz)
+DEFINE_TLS_PROP_HELPERS(tls_hostname)
+
+static void migration_object_init_props_tls(MigrationState *s)
+{
+    Object *obj = OBJECT(s);
+    ObjectProperty *prop;
+
+    prop = object_property_add_str(obj, "tls-creds",
+                                   mig_prop_tls_creds_get,
+                                   mig_prop_tls_creds_set);
+    object_property_set_default_str(prop, "");
+
+    prop = object_property_add_str(obj, "tls-hostname",
+                                   mig_prop_tls_hostname_get,
+                                   mig_prop_tls_hostname_set);
+    object_property_set_default_str(prop, "");
+
+    prop = object_property_add_str(obj, "tls-authz",
+                                   mig_prop_tls_authz_get,
+                                   mig_prop_tls_authz_set);
+    object_property_set_default_str(prop, "");
+}
+
+#define  DEFINE_ENUM_PROP_HELPERS(param_name)                           \
+    static int mig_prop_##param_name##_get(Object *obj, Error **errp)   \
+    {                                                                   \
+        return (int) MIGRATION(obj)->parameters.param_name;             \
+    }                                                                   \
+                                                                        \
+    static void mig_prop_##param_name##_set(Object *obj, int val,       \
+                                            Error **errp)               \
+    {                                                                   \
+        MIGRATION(obj)->parameters.param_name = val;                    \
+    }
+
+DEFINE_ENUM_PROP_HELPERS(multifd_compression)
+DEFINE_ENUM_PROP_HELPERS(zero_page_detection)
+DEFINE_ENUM_PROP_HELPERS(mode)
+
+static void migration_object_init_props_enum(MigrationState *s)
+{
+    Object *obj = OBJECT(s);
+    ObjectProperty *prop;
+
+    prop = object_property_add_enum(obj, "multifd-compression",
+                                    "MultiFDCompression",
+                                    &MultiFDCompression_lookup,
+                                    mig_prop_multifd_compression_get,
+                                    mig_prop_multifd_compression_set);
+    object_property_set_default_str(prop, DEFAULT_MIGRATE_MULTIFD_COMPRESSION);
+
+    prop = object_property_add_enum(obj, "mode", "MigMode", &MigMode_lookup,
+                                    mig_prop_mode_get, mig_prop_mode_set);
+    object_property_set_default_str(prop, "normal");
+
+    prop = object_property_add_enum(obj, "zero-page-detection",
+                                    "ZeroPageDetection",
+                                    &ZeroPageDetection_lookup,
+                                    mig_prop_zero_page_detection_get,
+                                    mig_prop_zero_page_detection_set);
+    object_property_set_default_str(prop, "multifd");
+}
+
+static void migration_object_init_properties(MigrationState *s)
+{
+    migration_object_init_props_bool(s);
+    migration_object_init_props_uint8(s);
+    migration_object_init_props_uint32(s);
+    migration_object_init_props_uint64(s);
+    migration_object_init_props_size(s);
+    migration_object_init_props_caps(s);
+    migration_object_init_props_tls(s);
+    migration_object_init_props_enum(s);
+}
 
 bool migrate_auto_converge(void)
 {
@@ -1107,9 +1246,10 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
     return params;
 }
 
-void migrate_params_init(MigrationParameters *params)
+void migrate_params_init(MigrationState *s)
 {
-    migrate_mark_all_params_present(params);
+    migration_object_init_properties(s);
+    migrate_mark_all_params_present(&s->parameters);
 }
 
 static void migrate_post_update_params(MigrationParameters *new, Error **errp)
-- 
2.53.0



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

* Re: [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object
  2026-06-09 17:25 [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Peter Xu
                   ` (9 preceding siblings ...)
  2026-06-09 17:25 ` [PATCH v2 10/10] migration: Switch to TYPE_OBJECT with object properties Peter Xu
@ 2026-06-09 22:54 ` Fabiano Rosas
  2026-06-10 18:30   ` Peter Xu
  10 siblings, 1 reply; 30+ messages in thread
From: Fabiano Rosas @ 2026-06-09 22:54 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Vladimir Sementsov-Ogievskiy,
	Peter Maydell, Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki,
	Peter Xu, Paolo Bonzini, Kevin Wolf, Sana Sharma,
	Marc-André Lureau, Juraj Marcin, qemu-rust,
	Markus Armbruster, Mark Cave-Ayland

Peter Xu <peterx@redhat.com> writes:

> CI: https://gitlab.com/peterx/qemu/-/pipelines/2588717620
>     (two irrelevant failures due to no runner)
>
> rfc: https://lore.kernel.org/r/20251209162857.857593-1-peterx@redhat.com
> v1:  https://lore.kernel.org/r/20260604231118.1584889-1-peterx@redhat.com
>
> This v2 is a full rewrite of v1, changelog doesn't apply.
>
> This version majorly addressed the concern in v1 having object API exported
> in qdev files. Instead of trying to expose qdev properties, this patchset
> switched migration object to use the object property API to add properties.
>
> Not all QOM facilities are ready for it, there're a few prior patches to
> improve QOM API to achieve it.
>
> The major concept that this series introduces that does not exist
> previously is the default value mechanisms for object properties (rather
> than object class properties).  Here migration object will rely on that to
> set default values.
>
> Patch 1:   A cleanup to use OBJECT_DECLARE_SIMPLE_TYPE for migration
> Patch 2-4: Qdev changes needed for the transition
> Patch 5-9: Improve QOM API to prepare for the property switch
> Patch 10:  Switch migration object to use TYPE_OBJECT and object props
>
> Comments welcomed, thanks.
>
> Peter Xu (10):
>   migration: Use OBJECT_DECLARE_SIMPLE_TYPE
>   qdev: Export global_props()
>   qdev: Introduce DEFINE_PROP_*_NODEFAULT for bool/uint32
>   hw/arm: Use nodefault version of qdev props when not needed
>   qom: Create object-property-ptr.[ch]
>   qom: Add object_property_add_bool_ptr()
>   qom: Add object_property_add_size_ptr()
>   qom: Add object_property_add_*_ptr_def()
>   qom: Allow default values for instance properties
>   migration: Switch to TYPE_OBJECT with object properties
>
>  include/hw/core/qdev-properties.h |   7 +
>  include/qom/object-property-ptr.h | 162 +++++++++
>  include/qom/object.h              |  99 +-----
>  migration/migration.h             |   9 +-
>  migration/options.h               |   8 +-
>  hw/arm/bcm2836.c                  |   3 +-
>  hw/core/qdev-properties.c         |   2 +-
>  migration/migration.c             |  42 ++-
>  migration/options.c               | 526 +++++++++++++++++++-----------
>  qom/object-property-ptr.c         | 394 ++++++++++++++++++++++
>  qom/object.c                      | 266 ++-------------
>  target/arm/cpu64.c                |   3 +-
>  qom/meson.build                   |   1 +
>  rust/bindings/hwcore-sys/lib.rs   |   2 +-
>  14 files changed, 957 insertions(+), 567 deletions(-)
>  create mode 100644 include/qom/object-property-ptr.h
>  create mode 100644 qom/object-property-ptr.c

Hi,

After we discussed your v1 I started playing with this in parallel and
stumbled into pretty much all of the issues this series resolves. Nice
work!

I applied a patch [0] on top of this series to allow using the
command-line to create the migration object. It can set all (most)
options with -object migration,id=mig1,key=val,...

 $ ~/qemu-system-x86_64 -nodefaults -nographic -S \
 -object migration,id=mig1,announce-initial=99,downtime-limit=99,multifd-channels=99,multifd-compression=zlib,multifd=on
 ...
 (qemu) info migrate_parameters
 (qemu) info migrate_capabilities
 ...
 announce-initial: 99 ms
 downtime-limit: 99 ms
 multifd-channels: 99
 multifd-compression: zlib
 multifd: on

I'm not saying we should do that now. I just want to check with you to
make sure we're not closing the door for future improvements:

1) It seems the "help" option is tied to the class. Setting options
work, but the help says otherwise:

 $ ~/qemu-system-x86_64 -nographic -object migration,id=mig1,help                                                                            
 There are no options for migration.

2) user_creatable_add_qapi

 The command line parsing goes through user_creatable_add_qapi() and
 instantiates an object. Since migrate_params_init runs from inside
 .instance_init, it cannot see any parameters that are set this way.

 Moreover, the migration_object_init() call from vl.c will init a
 second migration object.

 In the patch below I have hacked the current_migration assignment to
 first check if the object has already been created and use that
 instead of creating a new one.

 How does this work for normal objects? I suppose most of them have the
 TYPE_DEVICE as a parent, so they're not hanging in the "objects"
 container.

3) TLS (of course)

 With the patch below, setting TLS options from the cmdline asserts:
 visit_start_alternate: Assertion `!(v->type & VISITOR_INPUT)' failed.
 (just mentioning in case it can affect the design of this series)

[0]
-->8--
From 8c6c0743f1659d9df45e80334e8dc5f068ff984e Mon Sep 17 00:00:00 2001
From: Fabiano Rosas <farosas@suse.de>
Date: Tue, 9 Jun 2026 16:00:21 -0300
Subject: [PATCH] wip

---
 migration/migration.c | 11 ++++++++++-
 migration/options.c   |  1 +
 qapi/qom.json         | 29 +++++++++++++++++++++++++++++
 3 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/migration/migration.c b/migration/migration.c
index ae0c373549..22c8ced766 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -297,7 +297,16 @@ void migration_object_init(void)
 {
     /* This can only be called once. */
     assert(!current_migration);
-    current_migration = MIGRATION(object_new(TYPE_MIGRATION));
+
+    Object *root = object_get_objects_root();
+    ObjectProperty *prop = g_hash_table_lookup(root->properties, "mig1");
+
+    if (prop->opaque) {
+        current_migration = prop->opaque;
+        object_ref(current_migration);
+    } else {
+        current_migration = MIGRATION(object_new(TYPE_MIGRATION));
+    }
 
     /*
      * Init the migrate incoming object as well no matter whether
diff --git a/migration/options.c b/migration/options.c
index 1cc99382d3..88f02c45a1 100644
--- a/migration/options.c
+++ b/migration/options.c
@@ -21,6 +21,7 @@
 #include "qapi/qapi-visit-migration.h"
 #include "qapi/qmp/qerror.h"
 #include "qobject/qnull.h"
+#include "qom/object_interfaces.h"
 #include "system/runstate.h"
 #include "migration/colo.h"
 #include "migration/cpr.h"
diff --git a/qapi/qom.json b/qapi/qom.json
index dd45ac1087..fe7dd4673c 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -8,6 +8,11 @@
 { 'include': 'block-core.json' }
 { 'include': 'common.json' }
 { 'include': 'crypto.json' }
+# FIXME: this requires --disable-tools due to:
+# /usr/bin/ld.bfd: libqemuutil.a.p/meson-generated_.._qapi_qapi-commands-migration.c.o:
+# in function `qmp_marshal_query_migr: qemu/build/qapi/qapi-commands-migration.c:48:(.text+0x181c):
+# undefined reference to `qmp_query_migrate'
+{ 'include': 'migration.json' }
 
 ##
 # ***********************
@@ -1187,6 +1192,28 @@
   'data': { '*cpu-affinity': ['uint16'],
             '*node-affinity': ['uint16'] } }
 
+
+##
+# @MigProperties:
+#
+# Properties for migration objects.
+#
+# @multifd: this is a capability and therefore is not part of
+#     MigrationParameters yet (WIP).  (default: 0)
+#
+# @store-global-state: this is a compat property and therefore is not
+#     part of MigrationParameters.  It's probably best to keep it like
+#     this so we don't have to deal with previously impossible
+#     scenarios if the user tries to set it via set-migrate  (default:
+#     0)
+#
+# Since: 11.1
+##
+{ 'struct': 'MigProperties',
+  'base': 'MigrationParameters',
+  'data': { '*multifd': 'bool',
+            '*store-global-state': 'bool' } }
+
 ##
 # @ObjectType:
 #
@@ -1237,6 +1264,7 @@
     'memory-backend-ram',
     { 'name': 'memory-backend-shm',
       'if': 'CONFIG_POSIX' },
+    'migration',
     'pef-guest',
     { 'name': 'pr-manager-helper',
       'if': 'CONFIG_LINUX' },
@@ -1315,6 +1343,7 @@
       'memory-backend-ram':         'MemoryBackendProperties',
       'memory-backend-shm':         { 'type': 'MemoryBackendShmProperties',
                                       'if': 'CONFIG_POSIX' },
+      'migration':                    'MigProperties',
       'pr-manager-helper':          { 'type': 'PrManagerHelperProperties',
                                       'if': 'CONFIG_LINUX' },
       'qtest':                      'QtestProperties',
-- 
2.53.0




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

* Re: [PATCH v2 01/10] migration: Use OBJECT_DECLARE_SIMPLE_TYPE
  2026-06-09 17:25 ` [PATCH v2 01/10] migration: Use OBJECT_DECLARE_SIMPLE_TYPE Peter Xu
@ 2026-06-09 22:55   ` Fabiano Rosas
  2026-06-10 13:56   ` Daniel P. Berrangé
  2026-06-10 15:15   ` Mark Cave-Ayland
  2 siblings, 0 replies; 30+ messages in thread
From: Fabiano Rosas @ 2026-06-09 22:55 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Vladimir Sementsov-Ogievskiy,
	Peter Maydell, Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki,
	Peter Xu, Paolo Bonzini, Kevin Wolf, Sana Sharma,
	Marc-André Lureau, Juraj Marcin, qemu-rust,
	Markus Armbruster, Mark Cave-Ayland

Peter Xu <peterx@redhat.com> writes:

> Migration object's class has nothing special, switch to the newly
> introduced macro.
>
> Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>  migration/migration.h | 9 +--------
>  migration/migration.c | 7 +++----
>  2 files changed, 4 insertions(+), 12 deletions(-)
>
> diff --git a/migration/migration.h b/migration/migration.h
> index 841f49b215..293ad60e07 100644
> --- a/migration/migration.h
> +++ b/migration/migration.h
> @@ -263,14 +263,7 @@ void fill_destination_postcopy_migration_info(MigrationInfo *info);
>  
>  #define TYPE_MIGRATION "migration"
>  
> -typedef struct MigrationClass MigrationClass;
> -DECLARE_OBJ_CHECKERS(MigrationState, MigrationClass,
> -                     MIGRATION_OBJ, TYPE_MIGRATION)
> -
> -struct MigrationClass {
> -    /*< private >*/
> -    DeviceClass parent_class;
> -};
> +OBJECT_DECLARE_SIMPLE_TYPE(MigrationState, MIGRATION);
>  
>  struct MigrationState {
>      /*< private >*/
> diff --git a/migration/migration.c b/migration/migration.c
> index 074d3f2c69..278cad502a 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -297,7 +297,7 @@ void migration_object_init(void)
>  {
>      /* This can only be called once. */
>      assert(!current_migration);
> -    current_migration = MIGRATION_OBJ(object_new(TYPE_MIGRATION));
> +    current_migration = MIGRATION(object_new(TYPE_MIGRATION));
>  
>      /*
>       * Init the migrate incoming object as well no matter whether
> @@ -3975,7 +3975,7 @@ static void migration_class_init(ObjectClass *klass, const void *data)
>  
>  static void migration_instance_finalize(Object *obj)
>  {
> -    MigrationState *ms = MIGRATION_OBJ(obj);
> +    MigrationState *ms = MIGRATION(obj);
>  
>      qapi_free_BitmapMigrationNodeAliasList(ms->parameters.block_bitmap_mapping);
>      qapi_free_strList(ms->parameters.cpr_exec_command);
> @@ -3993,7 +3993,7 @@ static void migration_instance_finalize(Object *obj)
>  
>  static void migration_instance_init(Object *obj)
>  {
> -    MigrationState *ms = MIGRATION_OBJ(obj);
> +    MigrationState *ms = MIGRATION(obj);
>  
>      ms->state = MIGRATION_STATUS_NONE;
>      ms->mbps = -1;
> @@ -4040,7 +4040,6 @@ static const TypeInfo migration_type = {
>       */
>      .parent = TYPE_DEVICE,
>      .class_init = migration_class_init,
> -    .class_size = sizeof(MigrationClass),
>      .instance_size = sizeof(MigrationState),
>      .instance_init = migration_instance_init,
>      .instance_finalize = migration_instance_finalize,

Reviewed-by: Fabiano Rosas <farosas@suse.de>


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

* Re: [PATCH v2 02/10] qdev: Export global_props()
  2026-06-09 17:25 ` [PATCH v2 02/10] qdev: Export global_props() Peter Xu
@ 2026-06-09 22:55   ` Fabiano Rosas
  2026-06-10 15:18   ` Mark Cave-Ayland
  1 sibling, 0 replies; 30+ messages in thread
From: Fabiano Rosas @ 2026-06-09 22:55 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Vladimir Sementsov-Ogievskiy,
	Peter Maydell, Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki,
	Peter Xu, Paolo Bonzini, Kevin Wolf, Sana Sharma,
	Marc-André Lureau, Juraj Marcin, qemu-rust,
	Markus Armbruster, Mark Cave-Ayland

Peter Xu <peterx@redhat.com> writes:

> Make it accessible from outside (to apply -global properties).
>
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>  include/hw/core/qdev-properties.h | 2 ++
>  hw/core/qdev-properties.c         | 2 +-
>  rust/bindings/hwcore-sys/lib.rs   | 2 +-
>  3 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/include/hw/core/qdev-properties.h b/include/hw/core/qdev-properties.h
> index eba5436e53..248bbcbba7 100644
> --- a/include/hw/core/qdev-properties.h
> +++ b/include/hw/core/qdev-properties.h
> @@ -321,4 +321,6 @@ void qdev_prop_allow_set_link_before_realize(const Object *obj,
>                                               const char *name,
>                                               Object *val, Error **errp);
>  
> +GPtrArray *global_props(void);
> +
>  #endif
> diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
> index 34d7b26a73..1d531189ec 100644
> --- a/hw/core/qdev-properties.c
> +++ b/hw/core/qdev-properties.c
> @@ -958,7 +958,7 @@ void qlist_append_link(QList *qlist, Object *obj)
>      qlist_append_str(qlist, path);
>  }
>  
> -static GPtrArray *global_props(void)
> +GPtrArray *global_props(void)
>  {
>      static GPtrArray *gp;
>  
> diff --git a/rust/bindings/hwcore-sys/lib.rs b/rust/bindings/hwcore-sys/lib.rs
> index 8cef4a7961..85e71f5145 100644
> --- a/rust/bindings/hwcore-sys/lib.rs
> +++ b/rust/bindings/hwcore-sys/lib.rs
> @@ -20,7 +20,7 @@
>  
>  use chardev_sys::Chardev;
>  use common::Zeroable;
> -use glib_sys::GSList;
> +use glib_sys::{GPtrArray, GSList};
>  use migration_sys::VMStateDescription;
>  use qom_sys::{
>      InterfaceClass, Object, ObjectClass, ObjectProperty, ObjectPropertyAccessor,

Reviewed-by: Fabiano Rosas <farosas@suse.de>


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

* Re: [PATCH v2 06/10] qom: Add object_property_add_bool_ptr()
  2026-06-09 17:25 ` [PATCH v2 06/10] qom: Add object_property_add_bool_ptr() Peter Xu
@ 2026-06-09 23:18   ` Fabiano Rosas
  0 siblings, 0 replies; 30+ messages in thread
From: Fabiano Rosas @ 2026-06-09 23:18 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Vladimir Sementsov-Ogievskiy,
	Peter Maydell, Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki,
	Peter Xu, Paolo Bonzini, Kevin Wolf, Sana Sharma,
	Marc-André Lureau, Juraj Marcin, qemu-rust,
	Markus Armbruster, Mark Cave-Ayland

Peter Xu <peterx@redhat.com> writes:

> Add a helper to set qom property via a bool pointer.
>
> Signed-off-by: Peter Xu <peterx@redhat.com>

Reviewed-by: Fabiano Rosas <farosas@suse.de>

> ---
>  include/qom/object-property-ptr.h | 15 ++++++++++++
>  qom/object-property-ptr.c         | 39 +++++++++++++++++++++++++++++++
>  2 files changed, 54 insertions(+)
>
> diff --git a/include/qom/object-property-ptr.h b/include/qom/object-property-ptr.h
> index 6066c377fb..9cd8600094 100644
> --- a/include/qom/object-property-ptr.h
> +++ b/include/qom/object-property-ptr.h
> @@ -16,6 +16,21 @@ typedef enum {
>      OBJ_PROP_FLAG_READWRITE = (OBJ_PROP_FLAG_READ | OBJ_PROP_FLAG_WRITE),
>  } ObjectPropertyFlags;
>  
> +/**
> + * object_property_add_bool_ptr:
> + * @obj: the object to add a property to
> + * @name: the name of the property
> + * @v: pointer to value
> + * @flags: bitwise-or'd ObjectPropertyFlags
> + *
> + * Add a property of type 'bool' to the object.
> + *
> + * Returns: The newly added property on success, or %NULL on failure.
> + */
> +ObjectProperty *
> +object_property_add_bool_ptr(Object *obj, const char *name, const bool *v,
> +                             ObjectPropertyFlags flags);
> +
>  /**
>   * object_property_add_uint8_ptr:
>   * @obj: the object to add a property to
> diff --git a/qom/object-property-ptr.c b/qom/object-property-ptr.c
> index 02c01ed7f0..49f223da7b 100644
> --- a/qom/object-property-ptr.c
> +++ b/qom/object-property-ptr.c
> @@ -7,6 +7,26 @@
>  #include "qom/object.h"
>  #include "qapi/visitor.h"
>  
> +static void property_get_bool_ptr(Object *obj, Visitor *v, const char *name,
> +                                  void *opaque, Error **errp)
> +{
> +    bool value = *(bool *)opaque;
> +    visit_type_bool(v, name, &value, errp);
> +}
> +
> +static void property_set_bool_ptr(Object *obj, Visitor *v, const char *name,
> +                                  void *opaque, Error **errp)
> +{
> +    bool *field = opaque;
> +    bool value;
> +
> +    if (!visit_type_bool(v, name, &value, errp)) {
> +        return;
> +    }
> +
> +    *field = value;
> +}
> +
>  static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
>                                     void *opaque, Error **errp)
>  {
> @@ -87,6 +107,25 @@ static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name,
>      *field = value;
>  }
>  
> +ObjectProperty *
> +object_property_add_bool_ptr(Object *obj, const char *name,
> +                             const bool *v, ObjectPropertyFlags flags)
> +{
> +    ObjectPropertyAccessor *getter = NULL;
> +    ObjectPropertyAccessor *setter = NULL;
> +
> +    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
> +        getter = property_get_bool_ptr;
> +    }
> +
> +    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
> +        setter = property_set_bool_ptr;
> +    }
> +
> +    return object_property_add(obj, name, "bool",
> +                               getter, setter, NULL, (void *)v);
> +}
> +
>  ObjectProperty *
>  object_property_add_uint8_ptr(Object *obj, const char *name,
>                                const uint8_t *v,


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

* Re: [PATCH v2 07/10] qom: Add object_property_add_size_ptr()
  2026-06-09 17:25 ` [PATCH v2 07/10] qom: Add object_property_add_size_ptr() Peter Xu
@ 2026-06-09 23:18   ` Fabiano Rosas
  0 siblings, 0 replies; 30+ messages in thread
From: Fabiano Rosas @ 2026-06-09 23:18 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Vladimir Sementsov-Ogievskiy,
	Peter Maydell, Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki,
	Peter Xu, Paolo Bonzini, Kevin Wolf, Sana Sharma,
	Marc-André Lureau, Juraj Marcin, qemu-rust,
	Markus Armbruster, Mark Cave-Ayland

Peter Xu <peterx@redhat.com> writes:

> Add a helper to set qom property via a size pointer.
>
> Signed-off-by: Peter Xu <peterx@redhat.com>

Reviewed-by: Fabiano Rosas <farosas@suse.de>

> ---
>  include/qom/object-property-ptr.h | 16 +++++++++++++
>  qom/object-property-ptr.c         | 40 +++++++++++++++++++++++++++++++
>  2 files changed, 56 insertions(+)
>
> diff --git a/include/qom/object-property-ptr.h b/include/qom/object-property-ptr.h
> index 9cd8600094..be467c64af 100644
> --- a/include/qom/object-property-ptr.h
> +++ b/include/qom/object-property-ptr.h
> @@ -115,4 +115,20 @@ ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass,
>                                            const uint64_t *v,
>                                            ObjectPropertyFlags flags);
>  
> +/**
> + * object_property_add_size_ptr:
> + * @obj: the object to add a property to
> + * @name: the name of the property
> + * @v: pointer to value
> + * @flags: bitwise-or'd ObjectPropertyFlags
> + *
> + * Add a property of type 'size' to the object.
> + *
> + * Returns: The newly added property on success, or %NULL on failure.
> + */
> +ObjectProperty *
> +object_property_add_size_ptr(Object *obj, const char *name,
> +                             const uint64_t *v,
> +                             ObjectPropertyFlags flags);
> +
>  #endif
> diff --git a/qom/object-property-ptr.c b/qom/object-property-ptr.c
> index 49f223da7b..21ceb2510d 100644
> --- a/qom/object-property-ptr.c
> +++ b/qom/object-property-ptr.c
> @@ -107,6 +107,26 @@ static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name,
>      *field = value;
>  }
>  
> +static void property_get_size_ptr(Object *obj, Visitor *v, const char *name,
> +                                  void *opaque, Error **errp)
> +{
> +    uint64_t value = *(uint64_t *)opaque;
> +    visit_type_size(v, name, &value, errp);
> +}
> +
> +static void property_set_size_ptr(Object *obj, Visitor *v, const char *name,
> +                                  void *opaque, Error **errp)
> +{
> +    uint64_t *field = opaque;
> +    uint64_t value;
> +
> +    if (!visit_type_size(v, name, &value, errp)) {
> +        return;
> +    }
> +
> +    *field = value;
> +}
> +
>  ObjectProperty *
>  object_property_add_bool_ptr(Object *obj, const char *name,
>                               const bool *v, ObjectPropertyFlags flags)
> @@ -285,3 +305,23 @@ object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
>      return object_class_property_add(klass, name, "uint64",
>                                       getter, setter, NULL, (void *)v);
>  }
> +
> +ObjectProperty *
> +object_property_add_size_ptr(Object *obj, const char *name,
> +                             const uint64_t *v,
> +                             ObjectPropertyFlags flags)
> +{
> +    ObjectPropertyAccessor *getter = NULL;
> +    ObjectPropertyAccessor *setter = NULL;
> +
> +    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
> +        getter = property_get_size_ptr;
> +    }
> +
> +    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
> +        setter = property_set_size_ptr;
> +    }
> +
> +    return object_property_add(obj, name, "size",
> +                               getter, setter, NULL, (void *)v);
> +}


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

* Re: [PATCH v2 08/10] qom: Add object_property_add_*_ptr_def()
  2026-06-09 17:25 ` [PATCH v2 08/10] qom: Add object_property_add_*_ptr_def() Peter Xu
@ 2026-06-09 23:21   ` Fabiano Rosas
  0 siblings, 0 replies; 30+ messages in thread
From: Fabiano Rosas @ 2026-06-09 23:21 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Vladimir Sementsov-Ogievskiy,
	Peter Maydell, Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki,
	Peter Xu, Paolo Bonzini, Kevin Wolf, Sana Sharma,
	Marc-André Lureau, Juraj Marcin, qemu-rust,
	Markus Armbruster, Mark Cave-Ayland

Peter Xu <peterx@redhat.com> writes:

> Add sister functions for existing pointer versions, to make it even easier
> to use by:
>
> - always make properties to be rw-able
> - allowing to specify default values
> - no retcode needed (assert on failure, always)
>
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>  include/qom/object-property-ptr.h | 28 +++++++++++++
>  qom/object-property-ptr.c         | 67 +++++++++++++++++++++++++++++++
>  2 files changed, 95 insertions(+)
>
> diff --git a/include/qom/object-property-ptr.h b/include/qom/object-property-ptr.h
> index be467c64af..ecd6f7819b 100644
> --- a/include/qom/object-property-ptr.h
> +++ b/include/qom/object-property-ptr.h
> @@ -131,4 +131,32 @@ object_property_add_size_ptr(Object *obj, const char *name,
>                               const uint64_t *v,
>                               ObjectPropertyFlags flags);
>  
> +/*
> + * Below are sister helpers of above, except that:
> + *
> + * (1) nothing is returned
> + * (2) always make the property to be both readable and writeable
> + * (3) allow setting default value
> + *
> + * Please refer to the sister functions for the documentation.
> + */
> +void
> +object_property_add_bool_ptr_def(Object *obj, const char *name,
> +                                 const bool *v, bool def);
> +void
> +object_property_add_uint8_ptr_def(Object *obj, const char *name,
> +                                  const uint8_t *v, uint8_t def);
> +void
> +object_property_add_uint16_ptr_def(Object *obj, const char *name,
> +                                   const uint16_t *v, uint16_t def);
> +void
> +object_property_add_uint32_ptr_def(Object *obj, const char *name,
> +                                   const uint32_t *v, uint32_t def);
> +void
> +object_property_add_uint64_ptr_def(Object *obj, const char *name,
> +                                   const uint64_t *v, uint64_t def);
> +void
> +object_property_add_size_ptr_def(Object *obj, const char *name,
> +                                 const uint64_t *v, uint64_t def);
> +
>  #endif
> diff --git a/qom/object-property-ptr.c b/qom/object-property-ptr.c
> index 21ceb2510d..ae9081d2d8 100644
> --- a/qom/object-property-ptr.c
> +++ b/qom/object-property-ptr.c
> @@ -325,3 +325,70 @@ object_property_add_size_ptr(Object *obj, const char *name,
>      return object_property_add(obj, name, "size",
>                                 getter, setter, NULL, (void *)v);
>  }
> +
> +void
> +object_property_add_bool_ptr_def(Object *obj, const char *name,
> +                                 const bool *v, bool def)
> +{
> +    ObjectProperty *prop;
> +
> +    prop = object_property_add_bool_ptr(obj, name, v,
> +                                        OBJ_PROP_FLAG_READWRITE);
> +    object_property_set_default_bool(prop, def);
> +}
> +
> +
> +void
> +object_property_add_uint8_ptr_def(Object *obj, const char *name,
> +                                  const uint8_t *v, uint8_t def)
> +{
> +    ObjectProperty *prop;
> +
> +    prop = object_property_add_uint8_ptr(obj, name, v,
> +                                         OBJ_PROP_FLAG_READWRITE);
> +    object_property_set_default_uint(prop, def);
> +}
> +
> +void
> +object_property_add_uint16_ptr_def(Object *obj, const char *name,
> +                                   const uint16_t *v, uint16_t def)
> +{
> +    ObjectProperty *prop;
> +
> +    prop = object_property_add_uint16_ptr(obj, name, v,
> +                                          OBJ_PROP_FLAG_READWRITE);
> +    object_property_set_default_uint(prop, def);
> +}
> +
> +void
> +object_property_add_uint32_ptr_def(Object *obj, const char *name,
> +                                   const uint32_t *v, uint32_t def)
> +{
> +    ObjectProperty *prop;
> +
> +    prop = object_property_add_uint32_ptr(obj, name, v,
> +                                          OBJ_PROP_FLAG_READWRITE);
> +    object_property_set_default_uint(prop, def);
> +}
> +
> +void
> +object_property_add_uint64_ptr_def(Object *obj, const char *name,
> +                                   const uint64_t *v, uint64_t def)
> +{
> +    ObjectProperty *prop;
> +
> +    prop = object_property_add_uint64_ptr(obj, name, v,
> +                                          OBJ_PROP_FLAG_READWRITE);
> +    object_property_set_default_uint(prop, def);
> +}
> +
> +void
> +object_property_add_size_ptr_def(Object *obj, const char *name,
> +                                 const uint64_t *v, uint64_t def)
> +{
> +    ObjectProperty *prop;
> +
> +    prop = object_property_add_size_ptr(obj, name, v,
> +                                        OBJ_PROP_FLAG_READWRITE);
> +    object_property_set_default_uint(prop, def);
> +}

Reviewed-by: Fabiano Rosas <farosas@suse.de>


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

* Re: [PATCH v2 01/10] migration: Use OBJECT_DECLARE_SIMPLE_TYPE
  2026-06-09 17:25 ` [PATCH v2 01/10] migration: Use OBJECT_DECLARE_SIMPLE_TYPE Peter Xu
  2026-06-09 22:55   ` Fabiano Rosas
@ 2026-06-10 13:56   ` Daniel P. Berrangé
  2026-06-10 15:15   ` Mark Cave-Ayland
  2 siblings, 0 replies; 30+ messages in thread
From: Daniel P. Berrangé @ 2026-06-10 13:56 UTC (permalink / raw)
  To: Peter Xu
  Cc: qemu-devel, qemu-arm, Cédric Le Goater,
	Philippe Mathieu-Daudé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Paolo Bonzini,
	Kevin Wolf, Sana Sharma, Marc-André Lureau, Juraj Marcin,
	qemu-rust, Markus Armbruster, Mark Cave-Ayland

On Tue, Jun 09, 2026 at 01:25:05PM -0400, Peter Xu wrote:
> Migration object's class has nothing special, switch to the newly
> introduced macro.
> 
> Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>  migration/migration.h | 9 +--------
>  migration/migration.c | 7 +++----
>  2 files changed, 4 insertions(+), 12 deletions(-)

Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>


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] 30+ messages in thread

* Re: [PATCH v2 01/10] migration: Use OBJECT_DECLARE_SIMPLE_TYPE
  2026-06-09 17:25 ` [PATCH v2 01/10] migration: Use OBJECT_DECLARE_SIMPLE_TYPE Peter Xu
  2026-06-09 22:55   ` Fabiano Rosas
  2026-06-10 13:56   ` Daniel P. Berrangé
@ 2026-06-10 15:15   ` Mark Cave-Ayland
  2 siblings, 0 replies; 30+ messages in thread
From: Mark Cave-Ayland @ 2026-06-10 15:15 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Paolo Bonzini,
	Kevin Wolf, Sana Sharma, Marc-André Lureau, Juraj Marcin,
	qemu-rust, Markus Armbruster

On 09/06/2026 18:25, Peter Xu wrote:

> Migration object's class has nothing special, switch to the newly
> introduced macro.
> 
> Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>   migration/migration.h | 9 +--------
>   migration/migration.c | 7 +++----
>   2 files changed, 4 insertions(+), 12 deletions(-)
> 
> diff --git a/migration/migration.h b/migration/migration.h
> index 841f49b215..293ad60e07 100644
> --- a/migration/migration.h
> +++ b/migration/migration.h
> @@ -263,14 +263,7 @@ void fill_destination_postcopy_migration_info(MigrationInfo *info);
>   
>   #define TYPE_MIGRATION "migration"
>   
> -typedef struct MigrationClass MigrationClass;
> -DECLARE_OBJ_CHECKERS(MigrationState, MigrationClass,
> -                     MIGRATION_OBJ, TYPE_MIGRATION)
> -
> -struct MigrationClass {
> -    /*< private >*/
> -    DeviceClass parent_class;
> -};
> +OBJECT_DECLARE_SIMPLE_TYPE(MigrationState, MIGRATION);
>   
>   struct MigrationState {
>       /*< private >*/
> diff --git a/migration/migration.c b/migration/migration.c
> index 074d3f2c69..278cad502a 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -297,7 +297,7 @@ void migration_object_init(void)
>   {
>       /* This can only be called once. */
>       assert(!current_migration);
> -    current_migration = MIGRATION_OBJ(object_new(TYPE_MIGRATION));
> +    current_migration = MIGRATION(object_new(TYPE_MIGRATION));
>   
>       /*
>        * Init the migrate incoming object as well no matter whether
> @@ -3975,7 +3975,7 @@ static void migration_class_init(ObjectClass *klass, const void *data)
>   
>   static void migration_instance_finalize(Object *obj)
>   {
> -    MigrationState *ms = MIGRATION_OBJ(obj);
> +    MigrationState *ms = MIGRATION(obj);
>   
>       qapi_free_BitmapMigrationNodeAliasList(ms->parameters.block_bitmap_mapping);
>       qapi_free_strList(ms->parameters.cpr_exec_command);
> @@ -3993,7 +3993,7 @@ static void migration_instance_finalize(Object *obj)
>   
>   static void migration_instance_init(Object *obj)
>   {
> -    MigrationState *ms = MIGRATION_OBJ(obj);
> +    MigrationState *ms = MIGRATION(obj);
>   
>       ms->state = MIGRATION_STATUS_NONE;
>       ms->mbps = -1;
> @@ -4040,7 +4040,6 @@ static const TypeInfo migration_type = {
>        */
>       .parent = TYPE_DEVICE,
>       .class_init = migration_class_init,
> -    .class_size = sizeof(MigrationClass),
>       .instance_size = sizeof(MigrationState),
>       .instance_init = migration_instance_init,
>       .instance_finalize = migration_instance_finalize,

Reviewed-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>


ATB,

Mark.



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

* Re: [PATCH v2 02/10] qdev: Export global_props()
  2026-06-09 17:25 ` [PATCH v2 02/10] qdev: Export global_props() Peter Xu
  2026-06-09 22:55   ` Fabiano Rosas
@ 2026-06-10 15:18   ` Mark Cave-Ayland
  1 sibling, 0 replies; 30+ messages in thread
From: Mark Cave-Ayland @ 2026-06-10 15:18 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Paolo Bonzini,
	Kevin Wolf, Sana Sharma, Marc-André Lureau, Juraj Marcin,
	qemu-rust, Markus Armbruster

On 09/06/2026 18:25, Peter Xu wrote:

> Make it accessible from outside (to apply -global properties).
> 
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>   include/hw/core/qdev-properties.h | 2 ++
>   hw/core/qdev-properties.c         | 2 +-
>   rust/bindings/hwcore-sys/lib.rs   | 2 +-
>   3 files changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/include/hw/core/qdev-properties.h b/include/hw/core/qdev-properties.h
> index eba5436e53..248bbcbba7 100644
> --- a/include/hw/core/qdev-properties.h
> +++ b/include/hw/core/qdev-properties.h
> @@ -321,4 +321,6 @@ void qdev_prop_allow_set_link_before_realize(const Object *obj,
>                                                const char *name,
>                                                Object *val, Error **errp);
>   
> +GPtrArray *global_props(void);
> +
>   #endif
> diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
> index 34d7b26a73..1d531189ec 100644
> --- a/hw/core/qdev-properties.c
> +++ b/hw/core/qdev-properties.c
> @@ -958,7 +958,7 @@ void qlist_append_link(QList *qlist, Object *obj)
>       qlist_append_str(qlist, path);
>   }
>   
> -static GPtrArray *global_props(void)
> +GPtrArray *global_props(void)
>   {
>       static GPtrArray *gp;
>   
> diff --git a/rust/bindings/hwcore-sys/lib.rs b/rust/bindings/hwcore-sys/lib.rs
> index 8cef4a7961..85e71f5145 100644
> --- a/rust/bindings/hwcore-sys/lib.rs
> +++ b/rust/bindings/hwcore-sys/lib.rs
> @@ -20,7 +20,7 @@
>   
>   use chardev_sys::Chardev;
>   use common::Zeroable;
> -use glib_sys::GSList;
> +use glib_sys::{GPtrArray, GSList};
>   use migration_sys::VMStateDescription;
>   use qom_sys::{
>       InterfaceClass, Object, ObjectClass, ObjectProperty, ObjectPropertyAccessor,

I'd have to take the Rust part on trust, but at least for the C version:

Reviewed-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>


ATB,

Mark.



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

* Re: [PATCH v2 03/10] qdev: Introduce DEFINE_PROP_*_NODEFAULT for bool/uint32
  2026-06-09 17:25 ` [PATCH v2 03/10] qdev: Introduce DEFINE_PROP_*_NODEFAULT for bool/uint32 Peter Xu
@ 2026-06-10 15:25   ` Mark Cave-Ayland
  0 siblings, 0 replies; 30+ messages in thread
From: Mark Cave-Ayland @ 2026-06-10 15:25 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Paolo Bonzini,
	Kevin Wolf, Sana Sharma, Marc-André Lureau, Juraj Marcin,
	qemu-rust, Markus Armbruster

On 09/06/2026 18:25, Peter Xu wrote:

> Introduce two macros that will be used in follow up patch to create qdev
> bool or uint32 properties without a default value.  Do not introduce the
> rest until they can be used.
> 
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>   include/hw/core/qdev-properties.h | 5 +++++
>   1 file changed, 5 insertions(+)
> 
> diff --git a/include/hw/core/qdev-properties.h b/include/hw/core/qdev-properties.h
> index 248bbcbba7..43878d1f9e 100644
> --- a/include/hw/core/qdev-properties.h
> +++ b/include/hw/core/qdev-properties.h
> @@ -124,6 +124,9 @@ extern const PropertyInfo qdev_prop_link;
>                   .set_default = true,                         \
>                   .defval.u    = (bool)_defval)
>   
> +#define DEFINE_PROP_BOOL_NODEFAULT(_name, _state, _field)     \
> +    DEFINE_PROP(_name, _state, _field, qdev_prop_bool, bool)
> +
>   /**
>    * The DEFINE_PROP_UINT64_CHECKMASK macro checks a user-supplied value
>    * against corresponding bitmask, rejects the value if it violates.
> @@ -201,6 +204,8 @@ extern const PropertyInfo qdev_prop_link;
>       DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
>   #define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \
>       DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
> +#define DEFINE_PROP_UINT32_NODEFAULT(_n, _s, _f)                        \
> +    DEFINE_PROP_UNSIGNED_NODEFAULT(_n, _s, _f, qdev_prop_uint32, uint32_t)
>   #define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \
>       DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_int32, int32_t)
>   #define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \

I think it's worth mentioning in the commit message that this extends 
the existing set of _NODEFAULT() macros, since I had to go and check to 
see if this was something completely new being introduced by the patch 
(it's not something I was familiar with, and we don't appear to mention 
them in our docs!).

Anyhow it seems correct, so:

Reviewed-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>


ATB,

Mark.



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

* Re: [PATCH v2 04/10] hw/arm: Use nodefault version of qdev props when not needed
  2026-06-09 17:25 ` [PATCH v2 04/10] hw/arm: Use nodefault version of qdev props when not needed Peter Xu
@ 2026-06-10 15:31   ` Mark Cave-Ayland
  0 siblings, 0 replies; 30+ messages in thread
From: Mark Cave-Ayland @ 2026-06-10 15:31 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: qemu-arm, Cédric Le Goater, Philippe Mathieu-Daudé,
	Daniel P . Berrangé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Paolo Bonzini,
	Kevin Wolf, Sana Sharma, Marc-André Lureau, Juraj Marcin,
	qemu-rust, Markus Armbruster, Marc Zyngier

On 09/06/2026 18:25, Peter Xu wrote:

> We're going to introduce defvars for object properties just like qdev-props
> defvars.  It work slightly differently in that props can be added in
> instance_init() with default values, then the default values can only apply
> after instance_init() completes.
> 
> It means any explicit set of property values within instance_init() when
> used together with object property's default value (or qdev-prop, which
> builts the default value framework on top) will stop working.
> 
> This patch touches two of such use cases where the device may add qdev
> properties with a default value first, then quickly set another value
> within instance_init().
> 
> These are the only two outliers I found across the QEMU tree that do it
> this way.  Switch them to use qdev-prop's NODEFAULT APIs, and always
> initialize the values manually.
> 
> Example 1:
> 
> bcm283x_base_init() adds qdev prop bcm2836_enabled_cores_property with a
> default value 0, then it immediately set another value inside the same
> instance_init() hook.
> 
> Example 2:
> 
> aarch64_add_pauth_properties() adds qdev prop arm_cpu_pauth_property, but
> then it will immediately update the same field (cpu->prop_pauth)
> conditionally when hwaccel_enabled()==true.
> 
> Without the change, some arm test may fail (boot-serial-test) after
> introducing object property's default value framework, because devices'
> values will be overwritten by the properties' later.
> 
> OTOH, this patch itself should introduce no functional change.
> 
> Cc: Marc Zyngier <maz@kernel.org>
> Cc: Philippe Mathieu-Daudé <philmd@mailo.com>
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>   hw/arm/bcm2836.c   | 3 ++-
>   target/arm/cpu64.c | 3 ++-
>   2 files changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
> index f4ecea908b..9e4d30c99c 100644
> --- a/hw/arm/bcm2836.c
> +++ b/hw/arm/bcm2836.c
> @@ -19,7 +19,8 @@
>   #include "target/arm/gtimer.h"
>   
>   static const Property bcm2836_enabled_cores_property =
> -    DEFINE_PROP_UINT32("enabled-cpus", BCM283XBaseState, enabled_cpus, 0);
> +    DEFINE_PROP_UINT32_NODEFAULT(
> +        "enabled-cpus", BCM283XBaseState, enabled_cpus);
>   
>   static void bcm283x_base_init(Object *obj)
>   {
> diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
> index 2816735577..a3a014a994 100644
> --- a/target/arm/cpu64.c
> +++ b/target/arm/cpu64.c
> @@ -635,7 +635,7 @@ void aarch64_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
>   }
>   
>   static const Property arm_cpu_pauth_property =
> -    DEFINE_PROP_BOOL("pauth", ARMCPU, prop_pauth, true);
> +    DEFINE_PROP_BOOL_NODEFAULT("pauth", ARMCPU, prop_pauth);
>   static const Property arm_cpu_pauth_impdef_property =
>       DEFINE_PROP_BOOL("pauth-impdef", ARMCPU, prop_pauth_impdef, false);
>   static const Property arm_cpu_pauth_qarma3_property =
> @@ -660,6 +660,7 @@ void aarch64_add_pauth_properties(Object *obj)
>            */
>           cpu->prop_pauth = cpu_isar_feature(aa64_pauth, cpu);
>       } else {
> +        cpu->prop_pauth = true;
>           qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_impdef_property);
>           qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_qarma3_property);
>           qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_qarma5_property);

I checked against the commit message for 5cc56cc687 ("qdev: support 
properties which don't set a default value") and this is exactly what 
_NODEFAULT() is intended for, so:

Reviewed-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>


ATB,

Mark.



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

* Re: [PATCH v2 10/10] migration: Switch to TYPE_OBJECT with object properties
  2026-06-09 17:25 ` [PATCH v2 10/10] migration: Switch to TYPE_OBJECT with object properties Peter Xu
@ 2026-06-10 16:13   ` Daniel P. Berrangé
  2026-06-10 18:46     ` Peter Xu
  2026-06-10 16:29   ` Daniel P. Berrangé
  1 sibling, 1 reply; 30+ messages in thread
From: Daniel P. Berrangé @ 2026-06-10 16:13 UTC (permalink / raw)
  To: Peter Xu
  Cc: qemu-devel, qemu-arm, Cédric Le Goater,
	Philippe Mathieu-Daudé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Paolo Bonzini,
	Kevin Wolf, Sana Sharma, Marc-André Lureau, Juraj Marcin,
	qemu-rust, Markus Armbruster, Mark Cave-Ayland

On Tue, Jun 09, 2026 at 01:25:14PM -0400, Peter Xu wrote:
> The migration object used to depend on TYPE_DEVICE due to:
> 
> - Usage of qdev properties
> - Apply compat properties and global properties
> 
> This patch re-based the object to TYPE_OBJECT with the changes:
> 
> - Switch to object properties API
> - Manually apply both compat and global properties in post_init()
> 
> Note that to avoid too many property getter/setter helpers, this patch used
> the object_property_add_*_ptr_def() APIs so that an pointer is passed to
> bind to the property.  Such API is used for most of the conversions.
> 
> After patch, the migration object initializes instance properties within
> its instance_init() callback, in migrate_params_init().
> 
> One side effect of this change is, since we switched to a loop to add all
> capabilities, the name of the properties representing a migration
> capability may chance from previously hard-coded ones (many with x-).  It's
> fine since it's only used in -global so it's only for debugging.
> 
> Similarly, I removed "x-" from other properites that used to start with
> "x-" but actually are not experimental.

Mixing such a change into a refactoring commit is bad practice,
can you keep property changes separated.

> After the whole conversion, we don't need migration_properties or the count
> anymore, hence can be removed.  While at it, we can also remove two
> DEFINE_PROP*() API that only migration uses (DEFINE_PROP_STR_OR_NULL, and
> DEFINE_PROP_MIG_CAP).
> 
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>  migration/options.h   |   8 +-
>  migration/migration.c |  35 ++-
>  migration/options.c   | 526 ++++++++++++++++++++++++++----------------
>  3 files changed, 351 insertions(+), 218 deletions(-)


> diff --git a/migration/options.c b/migration/options.c
> index 5cbfd29099..1cc99382d3 100644
> --- a/migration/options.c
> +++ b/migration/options.c
> @@ -54,7 +54,7 @@


> +static void migration_object_init_props_bool(MigrationState *s)
>  {
> -    const Property *prop = opaque;
> -    StrOrNull **ptr = object_field_prop_ptr(obj, prop);
> -    StrOrNull *str_or_null = *ptr;
> +    Object *obj = OBJECT(s);
> +    int i;
>  
> -    /*
> -     * The property should never be NULL because it's part of
> -     * s->parameters and a default value is always set by qdev. It
> -     * should also never be QNULL as the setter doesn't allow it.
> -     */
> -    assert(str_or_null && str_or_null->type != QTYPE_QNULL);
> -    visit_type_str(v, name, &str_or_null->u.s, errp);
> +    struct MigPropBool {
> +        const char *name;
> +        void *ptr;
> +        bool defvar;
> +    } bool_list[] = {
> +        {
> +            "store-global-state",
> +            &s->store_global_state,
> +            true,
> +        },
> +        {
> +            "send-configuration",
> +            &s->send_configuration,
> +            true,
> +        },
> +        {
> +            "send-section-footer",
> +            &s->send_section_footer,
> +            true,
> +        },
> +        {
> +            "send-switchover-start",
> +            &s->send_switchover_start,
> +            true,
> +        },
> +        {
> +            "x-preempt-pre-7-2",
> +            &s->preempt_pre_7_2,
> +            false,
> +        },
> +        {
> +            "x-cpu-throttle-tailslow",
> +            &s->parameters.cpu_throttle_tailslow,
> +            false,
> +        },
> +        {
> +            "multifd-clean-tls-termination",
> +            &s->multifd_clean_tls_termination,
> +            true,
> +        },
> +        {
> +            "multifd-flush-after-each-section",
> +            &s->multifd_flush_after_each_section,
> +            false,
> +        },
> +    };
> +    struct MigPropBool *prop;

This approach to declaring properties is pretty unpleasant
to follow IMHO. Being a custom different approach from every
other object impl is not a good thing.

> +
> +    for (i = 0; i < ARRAY_SIZE(bool_list); i++) {
> +        prop = &bool_list[i];
> +        object_property_add_bool_ptr_def(obj, prop->name,
> +                                         prop->ptr, prop->defvar);
> +    }

Using instance level properties is the old way to do things,
it is preferred to use class level properties instead.

This means you can't use the "ptr" concept to directly reference
the instance fields and have to provide setters / getters explicitly
instead, but as you've shown with the TLS properties,  a macro can
make it simple to define the repetitive getters/setters.



> +static void migration_object_init_props_enum(MigrationState *s)
> +{
> +    Object *obj = OBJECT(s);
> +    ObjectProperty *prop;
> +
> +    prop = object_property_add_enum(obj, "multifd-compression",
> +                                    "MultiFDCompression",
> +                                    &MultiFDCompression_lookup,
> +                                    mig_prop_multifd_compression_get,
> +                                    mig_prop_multifd_compression_set);
> +    object_property_set_default_str(prop, DEFAULT_MIGRATE_MULTIFD_COMPRESSION);
> +
> +    prop = object_property_add_enum(obj, "mode", "MigMode", &MigMode_lookup,
> +                                    mig_prop_mode_get, mig_prop_mode_set);
> +    object_property_set_default_str(prop, "normal");
> +
> +    prop = object_property_add_enum(obj, "zero-page-detection",
> +                                    "ZeroPageDetection",
> +                                    &ZeroPageDetection_lookup,
> +                                    mig_prop_zero_page_detection_get,
> +                                    mig_prop_zero_page_detection_set);
> +    object_property_set_default_str(prop, "multifd");
> +}

Perhaps I'm missing something, but I'm not seeing the point in
using the set_default methods - in fact I'm not really sure why
they exist in QOM at all.

I'd expect all defaults to be set in the instance _init method.
ie why isn't this done as:

   void migrate_params_init(MigrationState *s)
   {
      s->parameters.mode = MIG_MODE_NORMAL;
      s->parameters.zero_page_detection = ZERO_PAGE_DETECTION_MULTIFD;
      .... all other defaults...
   }


> +
> +static void migration_object_init_properties(MigrationState *s)
> +{
> +    migration_object_init_props_bool(s);
> +    migration_object_init_props_uint8(s);
> +    migration_object_init_props_uint32(s);
> +    migration_object_init_props_uint64(s);
> +    migration_object_init_props_size(s);
> +    migration_object_init_props_caps(s);
> +    migration_object_init_props_tls(s);
> +    migration_object_init_props_enum(s);
> +}

...and class properties be registered in migrate_params_class_init()
and the grouping per type isn't helpful IMHO, just put all the
object_class_property_add calls inline in one place.

>  
>  bool migrate_auto_converge(void)
>  {
> @@ -1107,9 +1246,10 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
>      return params;
>  }
>  
> -void migrate_params_init(MigrationParameters *params)
> +void migrate_params_init(MigrationState *s)
>  {
> -    migrate_mark_all_params_present(params);
> +    migration_object_init_properties(s);
> +    migrate_mark_all_params_present(&s->parameters);
>  }
>  
>  static void migrate_post_update_params(MigrationParameters *new, Error **errp)
> -- 
> 2.53.0
> 

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] 30+ messages in thread

* Re: [PATCH v2 05/10] qom: Create object-property-ptr.[ch]
  2026-06-09 17:25 ` [PATCH v2 05/10] qom: Create object-property-ptr.[ch] Peter Xu
@ 2026-06-10 16:15   ` Daniel P. Berrangé
  2026-06-10 18:39     ` Peter Xu
  0 siblings, 1 reply; 30+ messages in thread
From: Daniel P. Berrangé @ 2026-06-10 16:15 UTC (permalink / raw)
  To: Peter Xu
  Cc: qemu-devel, qemu-arm, Cédric Le Goater,
	Philippe Mathieu-Daudé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Paolo Bonzini,
	Kevin Wolf, Sana Sharma, Marc-André Lureau, Juraj Marcin,
	qemu-rust, Markus Armbruster, Mark Cave-Ayland

On Tue, Jun 09, 2026 at 01:25:09PM -0400, Peter Xu wrote:
> Create object-property-ptr.[ch] files to include all the helpers for
> object_property_add*_ptr().
> 
> These set of helpers are handy because they look extremely familiar with
> qdev-properties, allowing the caller to provide a pointer and it will
> manage all the setters and getters.
> 
> The follow up patches may introduce more of such helpers.  Since object.c
> has been already too big, split that part out.

The "ptr" helpers are all instance level properties which is a concept
we discourage from new usage, in favour of class level properties.

I don't think we should be adding more "ptr" helpers, but rather
planning to eliminiate the (surprisingly little) usage of the
existing ones.

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] 30+ messages in thread

* Re: [PATCH v2 09/10] qom: Allow default values for instance properties
  2026-06-09 17:25 ` [PATCH v2 09/10] qom: Allow default values for instance properties Peter Xu
@ 2026-06-10 16:19   ` Daniel P. Berrangé
  0 siblings, 0 replies; 30+ messages in thread
From: Daniel P. Berrangé @ 2026-06-10 16:19 UTC (permalink / raw)
  To: Peter Xu
  Cc: qemu-devel, qemu-arm, Cédric Le Goater,
	Philippe Mathieu-Daudé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Paolo Bonzini,
	Kevin Wolf, Sana Sharma, Marc-André Lureau, Juraj Marcin,
	qemu-rust, Markus Armbruster, Mark Cave-Ayland

On Tue, Jun 09, 2026 at 01:25:13PM -0400, Peter Xu wrote:
> ObjectProperty allows default value settings via proper setup of
> prop->init() and prop->defval.  It currently is only supported in class
> properties, not instance properties.
> 
> However, since QOM allows class and instance properties, it should also
> allow instance to add properties during instance_init() and allow the
> default values to be applied properly for this instance only.
> 
> Add the logic.  It will be useful for all kinds of pointer based properties
> because pointers are normally not accessble in a class but only when an
> instance is available.  This will be able to achieve similar function as
> what qdev properties have (which works by remembering offsets within a
> structure instead).

Again, I don't think we should be adding more features to the
instance properties concept, as new code should use class
level properties.

> 
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>  qom/object.c | 26 ++++++++++++++++++++++++++
>  1 file changed, 26 insertions(+)

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] 30+ messages in thread

* Re: [PATCH v2 10/10] migration: Switch to TYPE_OBJECT with object properties
  2026-06-09 17:25 ` [PATCH v2 10/10] migration: Switch to TYPE_OBJECT with object properties Peter Xu
  2026-06-10 16:13   ` Daniel P. Berrangé
@ 2026-06-10 16:29   ` Daniel P. Berrangé
  2026-06-10 18:51     ` Peter Xu
  1 sibling, 1 reply; 30+ messages in thread
From: Daniel P. Berrangé @ 2026-06-10 16:29 UTC (permalink / raw)
  To: Peter Xu
  Cc: qemu-devel, qemu-arm, Cédric Le Goater,
	Philippe Mathieu-Daudé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Paolo Bonzini,
	Kevin Wolf, Sana Sharma, Marc-André Lureau, Juraj Marcin,
	qemu-rust, Markus Armbruster, Mark Cave-Ayland

On Tue, Jun 09, 2026 at 01:25:14PM -0400, Peter Xu wrote:
> The migration object used to depend on TYPE_DEVICE due to:
> 
> - Usage of qdev properties
> - Apply compat properties and global properties
> 
> This patch re-based the object to TYPE_OBJECT with the changes:
> 
> - Switch to object properties API
> - Manually apply both compat and global properties in post_init()
> 
> Note that to avoid too many property getter/setter helpers, this patch used
> the object_property_add_*_ptr_def() APIs so that an pointer is passed to
> bind to the property.  Such API is used for most of the conversions.
> 
> After patch, the migration object initializes instance properties within
> its instance_init() callback, in migrate_params_init().
> 
> One side effect of this change is, since we switched to a loop to add all
> capabilities, the name of the properties representing a migration
> capability may chance from previously hard-coded ones (many with x-).  It's
> fine since it's only used in -global so it's only for debugging.
> 
> Similarly, I removed "x-" from other properites that used to start with
> "x-" but actually are not experimental.
> 
> After the whole conversion, we don't need migration_properties or the count
> anymore, hence can be removed.  While at it, we can also remove two
> DEFINE_PROP*() API that only migration uses (DEFINE_PROP_STR_OR_NULL, and
> DEFINE_PROP_MIG_CAP).
> 
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>  migration/options.h   |   8 +-
>  migration/migration.c |  35 ++-
>  migration/options.c   | 526 ++++++++++++++++++++++++++----------------
>  3 files changed, 351 insertions(+), 218 deletions(-)

> +static void migration_instance_post_init(Object *obj)
> +{
>      /*
> -     * NOTE: TYPE_MIGRATION is not really a device, as the object is
> -     * not created using qdev_new(), it is not attached to the qdev
> -     * device tree, and it is never realized.
> +     * Apply these properties on top of default values:
> +     *
> +     * (1) machine compat properties
> +     * (2) -global settings in cmdlines
>       *
> -     * TODO: Make this TYPE_OBJECT once QOM provides something like
> -     * TYPE_DEVICE's "-global" properties.
> +     * Need to be applied in order so (2) takes precedence over (1).
>       */
> -    .parent = TYPE_DEVICE,
> -    .class_init = migration_class_init,
> +    object_apply_compat_props(obj);
> +    object_apply_global_props(obj, global_props(), &error_fatal);

-global is/was intended for devices, primarily those which
are created by default as part of the machine. For dynamically
created devices the docs recommend use of -device instead
of -global.

I get that -global was exposed for migration via the inappropriate
use of TYPE_DEVICE as a parent for TYPE_MIGRATION, but I don't
think we should be prolonging that misuse by exposing use of
-global for things which are QOM rather than QDev.

If we want todo that for the sake of backcompat, IMHO it should
be deprecated so it only lives for a short while after the
conversion to QOM.

This makes me realize that this does not implement the UserCreatable
interface on TYPE_MIGRATION, so I'm presuming the MigrationState is
still created internally. Perhaps we should switch to making it a
full UserCreatable, such that -object can be used to set all migration
parameters on the command line and -global won't be required ? 

> +}
> +
> +static const TypeInfo migration_type = {
> +    .name = TYPE_MIGRATION,
> +    .parent = TYPE_OBJECT,
>      .instance_size = sizeof(MigrationState),
>      .instance_init = migration_instance_init,
> +    .instance_post_init = migration_instance_post_init,
>      .instance_finalize = migration_instance_finalize,
>  };

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] 30+ messages in thread

* Re: [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object
  2026-06-09 22:54 ` [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Fabiano Rosas
@ 2026-06-10 18:30   ` Peter Xu
  0 siblings, 0 replies; 30+ messages in thread
From: Peter Xu @ 2026-06-10 18:30 UTC (permalink / raw)
  To: Fabiano Rosas
  Cc: qemu-devel, qemu-arm, Cédric Le Goater,
	Philippe Mathieu-Daudé, Daniel P . Berrangé,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Paolo Bonzini,
	Kevin Wolf, Sana Sharma, Marc-André Lureau, Juraj Marcin,
	qemu-rust, Markus Armbruster, Mark Cave-Ayland

On Tue, Jun 09, 2026 at 07:54:56PM -0300, Fabiano Rosas wrote:
> Hi,
> 
> After we discussed your v1 I started playing with this in parallel and
> stumbled into pretty much all of the issues this series resolves. Nice
> work!

Good to know at least it looks reasonable for someone.. thanks. :)

Looks like Dan still has concern that I use the ptrs in obj props but I'll
discuss it later separately.

> 
> I applied a patch [0] on top of this series to allow using the
> command-line to create the migration object. It can set all (most)
> options with -object migration,id=mig1,key=val,...
> 
>  $ ~/qemu-system-x86_64 -nodefaults -nographic -S \
>  -object migration,id=mig1,announce-initial=99,downtime-limit=99,multifd-channels=99,multifd-compression=zlib,multifd=on
>  ...
>  (qemu) info migrate_parameters
>  (qemu) info migrate_capabilities
>  ...
>  announce-initial: 99 ms
>  downtime-limit: 99 ms
>  multifd-channels: 99
>  multifd-compression: zlib
>  multifd: on
> 
> I'm not saying we should do that now. I just want to check with you to
> make sure we're not closing the door for future improvements:

IIUC it works, maybe indeed it's a better way than "-incoming config:" at
least in that we stick with the current APIs.

Said that, it does bypass the singleton work I did previously:

https://lore.kernel.org/r/20241029211607.2114845-1-peterx@redhat.com

Which was also unfortunately got rejected..

So, I suppose this is still fine that all the tricks resides in migration/
so far, maybe this is acceptable.

But then, we'll need to make sure the rest QEMU object code doesn't have
assumption that all objects can be created more than one.. and making sure
nothing crash elsewhere: when it crashes or works inproperly, we may face
again that singleton problem one way or another.  That's so far the only
concern I have.

> 
> 1) It seems the "help" option is tied to the class. Setting options
> work, but the help says otherwise:
> 
>  $ ~/qemu-system-x86_64 -nographic -object migration,id=mig1,help                                                                            
>  There are no options for migration.

This one is easy, something like this should work:

 bool type_print_class_properties(const char *type)
 {
+    g_autoptr(Object) obj = NULL;                                                                                                       
     ObjectClass *klass;
     ObjectPropertyIterator iter;
     ObjectProperty *prop;
@@ -134,7 +135,12 @@ bool type_print_class_properties(const char *type)
     }
 
     array = g_ptr_array_new();
-    object_class_property_iter_init(&iter, klass);                                                                                      
+    if (object_class_is_abstract(klass)) {                                                                                              
+        object_class_property_iter_init(&iter, klass);                                                                                  
+    } else {                                                                                                                            
+        obj = object_new_with_class(klass);                                                                                             
+        object_property_iter_init(&iter, obj);                                                                                          
+    }                                                                                                                                   
     while ((prop = object_property_iter_next(&iter))) {
         if (!prop->set) {
             continue;

> 
> 2) user_creatable_add_qapi
> 
>  The command line parsing goes through user_creatable_add_qapi() and
>  instantiates an object. Since migrate_params_init runs from inside
>  .instance_init, it cannot see any parameters that are set this way.
> 
>  Moreover, the migration_object_init() call from vl.c will init a
>  second migration object.
> 
>  In the patch below I have hacked the current_migration assignment to
>  first check if the object has already been created and use that
>  instead of creating a new one.

Yeah that trick should work at least for now, except the concern I raised
above.

Since the tap work is unblocked (by temporarily introducing the tap flag),
I plan to put aside the "-incoming config:*" work a bit.  We'll need to
pick it up at least when there's yet another similiar use case like tap or
"mode" of CPR, but then lower priority. But let me know if you or anyone
still think we should have it land earlier, I can re-prioritize that.

> 
>  How does this work for normal objects? I suppose most of them have the
>  TYPE_DEVICE as a parent, so they're not hanging in the "objects"
>  container.

I may not get the real question behind, but.. iiuc normal objects shouldn't
be sub-class of TYPE_DEVICE, and they should work fine with -object *help,
and they should be able to be created with multiple instances in most
cases.

> 
> 3) TLS (of course)
> 
>  With the patch below, setting TLS options from the cmdline asserts:
>  visit_start_alternate: Assertion `!(v->type & VISITOR_INPUT)' failed.
>  (just mentioning in case it can affect the design of this series)

Oh, I didn't really notice we'll have issue with it.. I did the string prop
solution for tls* by pure accident, because we already assumed it's always
strings anyway and it's trivial to use the object prop str helpers.  I
didn't expect it an issue when used with string inputs.  So I assume for
those we need to rely on JSON formats?

  -object '{"qom-type": "migration", "id": "mig1", "tls-creds": "SOMETHING"}'

> 
> [0]
> -->8--
> From 8c6c0743f1659d9df45e80334e8dc5f068ff984e Mon Sep 17 00:00:00 2001
> From: Fabiano Rosas <farosas@suse.de>
> Date: Tue, 9 Jun 2026 16:00:21 -0300
> Subject: [PATCH] wip
> 
> ---
>  migration/migration.c | 11 ++++++++++-
>  migration/options.c   |  1 +
>  qapi/qom.json         | 29 +++++++++++++++++++++++++++++
>  3 files changed, 40 insertions(+), 1 deletion(-)
> 
> diff --git a/migration/migration.c b/migration/migration.c
> index ae0c373549..22c8ced766 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -297,7 +297,16 @@ void migration_object_init(void)
>  {
>      /* This can only be called once. */
>      assert(!current_migration);
> -    current_migration = MIGRATION(object_new(TYPE_MIGRATION));
> +
> +    Object *root = object_get_objects_root();
> +    ObjectProperty *prop = g_hash_table_lookup(root->properties, "mig1");
> +
> +    if (prop->opaque) {
> +        current_migration = prop->opaque;
> +        object_ref(current_migration);
> +    } else {
> +        current_migration = MIGRATION(object_new(TYPE_MIGRATION));
> +    }

A quick comment for this one; maybe better with:

     Object *mig_obj = object_resolve_path_component(object_get_objects_root(),                                                          
                                                     "mig1");                                                                            

Or even better:

static int find_migration_object(Object *obj, void *opaque)
{
    if (object_dynamic_cast(obj, TYPE_MIGRATION)) {
        *(Object **)opaque = obj;
        return 1;
    }
    return 0;
}

Then:

     object_child_foreach(object_get_objects_root(),
                          find_migration_object, &existing);

>  
>      /*
>       * Init the migrate incoming object as well no matter whether
> diff --git a/migration/options.c b/migration/options.c
> index 1cc99382d3..88f02c45a1 100644
> --- a/migration/options.c
> +++ b/migration/options.c
> @@ -21,6 +21,7 @@
>  #include "qapi/qapi-visit-migration.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qobject/qnull.h"
> +#include "qom/object_interfaces.h"
>  #include "system/runstate.h"
>  #include "migration/colo.h"
>  #include "migration/cpr.h"
> diff --git a/qapi/qom.json b/qapi/qom.json
> index dd45ac1087..fe7dd4673c 100644
> --- a/qapi/qom.json
> +++ b/qapi/qom.json
> @@ -8,6 +8,11 @@
>  { 'include': 'block-core.json' }
>  { 'include': 'common.json' }
>  { 'include': 'crypto.json' }
> +# FIXME: this requires --disable-tools due to:
> +# /usr/bin/ld.bfd: libqemuutil.a.p/meson-generated_.._qapi_qapi-commands-migration.c.o:
> +# in function `qmp_marshal_query_migr: qemu/build/qapi/qapi-commands-migration.c:48:(.text+0x181c):
> +# undefined reference to `qmp_query_migrate'
> +{ 'include': 'migration.json' }
>  
>  ##
>  # ***********************
> @@ -1187,6 +1192,28 @@
>    'data': { '*cpu-affinity': ['uint16'],
>              '*node-affinity': ['uint16'] } }
>  
> +
> +##
> +# @MigProperties:
> +#
> +# Properties for migration objects.
> +#
> +# @multifd: this is a capability and therefore is not part of
> +#     MigrationParameters yet (WIP).  (default: 0)
> +#
> +# @store-global-state: this is a compat property and therefore is not
> +#     part of MigrationParameters.  It's probably best to keep it like
> +#     this so we don't have to deal with previously impossible
> +#     scenarios if the user tries to set it via set-migrate  (default:
> +#     0)
> +#
> +# Since: 11.1
> +##
> +{ 'struct': 'MigProperties',
> +  'base': 'MigrationParameters',
> +  'data': { '*multifd': 'bool',
> +            '*store-global-state': 'bool' } }
> +
>  ##
>  # @ObjectType:
>  #
> @@ -1237,6 +1264,7 @@
>      'memory-backend-ram',
>      { 'name': 'memory-backend-shm',
>        'if': 'CONFIG_POSIX' },
> +    'migration',
>      'pef-guest',
>      { 'name': 'pr-manager-helper',
>        'if': 'CONFIG_LINUX' },
> @@ -1315,6 +1343,7 @@
>        'memory-backend-ram':         'MemoryBackendProperties',
>        'memory-backend-shm':         { 'type': 'MemoryBackendShmProperties',
>                                        'if': 'CONFIG_POSIX' },
> +      'migration':                    'MigProperties',
>        'pr-manager-helper':          { 'type': 'PrManagerHelperProperties',
>                                        'if': 'CONFIG_LINUX' },
>        'qtest':                      'QtestProperties',
> -- 
> 2.53.0
> 
> 

-- 
Peter Xu



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

* Re: [PATCH v2 05/10] qom: Create object-property-ptr.[ch]
  2026-06-10 16:15   ` Daniel P. Berrangé
@ 2026-06-10 18:39     ` Peter Xu
  0 siblings, 0 replies; 30+ messages in thread
From: Peter Xu @ 2026-06-10 18:39 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-arm, Cédric Le Goater,
	Philippe Mathieu-Daudé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Paolo Bonzini,
	Kevin Wolf, Sana Sharma, Marc-André Lureau, Juraj Marcin,
	qemu-rust, Markus Armbruster, Mark Cave-Ayland

On Wed, Jun 10, 2026 at 05:15:59PM +0100, Daniel P. Berrangé wrote:
> On Tue, Jun 09, 2026 at 01:25:09PM -0400, Peter Xu wrote:
> > Create object-property-ptr.[ch] files to include all the helpers for
> > object_property_add*_ptr().
> > 
> > These set of helpers are handy because they look extremely familiar with
> > qdev-properties, allowing the caller to provide a pointer and it will
> > manage all the setters and getters.
> > 
> > The follow up patches may introduce more of such helpers.  Since object.c
> > has been already too big, split that part out.
> 
> The "ptr" helpers are all instance level properties which is a concept
> we discourage from new usage, in favour of class level properties.
> 
> I don't think we should be adding more "ptr" helpers, but rather
> planning to eliminiate the (surprisingly little) usage of the
> existing ones.

The other way to do similar thing is qdev's offset way, but IMHO that's
more awkward to remember an offset of a pointer then do math everytime.
Essentially, from technical pov we need at least one uintptr_t to store
either (1) offset, or (2) field pointer when there's a field that is bound
to a prop.  IMHO (2) can be better otherwise we'll need to do all the maths
to calculate offsets then when access we add the offset back and do a force
cast.  It seems not necessary.

OTOH, I still see value on non-class instance properties (that sometimes we
don't even want to have some props avail for the class, but conditional to
some instances when created dynamically).  If that is needed, IMHO it's
fine we still provide per-instance properties.

Is there any pointer I can read about the discussion previously on this?

Thanks,

-- 
Peter Xu



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

* Re: [PATCH v2 10/10] migration: Switch to TYPE_OBJECT with object properties
  2026-06-10 16:13   ` Daniel P. Berrangé
@ 2026-06-10 18:46     ` Peter Xu
  0 siblings, 0 replies; 30+ messages in thread
From: Peter Xu @ 2026-06-10 18:46 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-arm, Cédric Le Goater,
	Philippe Mathieu-Daudé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Paolo Bonzini,
	Kevin Wolf, Sana Sharma, Marc-André Lureau, Juraj Marcin,
	qemu-rust, Markus Armbruster, Mark Cave-Ayland

On Wed, Jun 10, 2026 at 05:13:47PM +0100, Daniel P. Berrangé wrote:
> On Tue, Jun 09, 2026 at 01:25:14PM -0400, Peter Xu wrote:
> > The migration object used to depend on TYPE_DEVICE due to:
> > 
> > - Usage of qdev properties
> > - Apply compat properties and global properties
> > 
> > This patch re-based the object to TYPE_OBJECT with the changes:
> > 
> > - Switch to object properties API
> > - Manually apply both compat and global properties in post_init()
> > 
> > Note that to avoid too many property getter/setter helpers, this patch used
> > the object_property_add_*_ptr_def() APIs so that an pointer is passed to
> > bind to the property.  Such API is used for most of the conversions.
> > 
> > After patch, the migration object initializes instance properties within
> > its instance_init() callback, in migrate_params_init().
> > 
> > One side effect of this change is, since we switched to a loop to add all
> > capabilities, the name of the properties representing a migration
> > capability may chance from previously hard-coded ones (many with x-).  It's
> > fine since it's only used in -global so it's only for debugging.
> > 
> > Similarly, I removed "x-" from other properites that used to start with
> > "x-" but actually are not experimental.
> 
> Mixing such a change into a refactoring commit is bad practice,
> can you keep property changes separated.

Sure.

> 
> > After the whole conversion, we don't need migration_properties or the count
> > anymore, hence can be removed.  While at it, we can also remove two
> > DEFINE_PROP*() API that only migration uses (DEFINE_PROP_STR_OR_NULL, and
> > DEFINE_PROP_MIG_CAP).
> > 
> > Signed-off-by: Peter Xu <peterx@redhat.com>
> > ---
> >  migration/options.h   |   8 +-
> >  migration/migration.c |  35 ++-
> >  migration/options.c   | 526 ++++++++++++++++++++++++++----------------
> >  3 files changed, 351 insertions(+), 218 deletions(-)
> 
> 
> > diff --git a/migration/options.c b/migration/options.c
> > index 5cbfd29099..1cc99382d3 100644
> > --- a/migration/options.c
> > +++ b/migration/options.c
> > @@ -54,7 +54,7 @@
> 
> 
> > +static void migration_object_init_props_bool(MigrationState *s)
> >  {
> > -    const Property *prop = opaque;
> > -    StrOrNull **ptr = object_field_prop_ptr(obj, prop);
> > -    StrOrNull *str_or_null = *ptr;
> > +    Object *obj = OBJECT(s);
> > +    int i;
> >  
> > -    /*
> > -     * The property should never be NULL because it's part of
> > -     * s->parameters and a default value is always set by qdev. It
> > -     * should also never be QNULL as the setter doesn't allow it.
> > -     */
> > -    assert(str_or_null && str_or_null->type != QTYPE_QNULL);
> > -    visit_type_str(v, name, &str_or_null->u.s, errp);
> > +    struct MigPropBool {
> > +        const char *name;
> > +        void *ptr;
> > +        bool defvar;
> > +    } bool_list[] = {
> > +        {
> > +            "store-global-state",
> > +            &s->store_global_state,
> > +            true,
> > +        },
> > +        {
> > +            "send-configuration",
> > +            &s->send_configuration,
> > +            true,
> > +        },
> > +        {
> > +            "send-section-footer",
> > +            &s->send_section_footer,
> > +            true,
> > +        },
> > +        {
> > +            "send-switchover-start",
> > +            &s->send_switchover_start,
> > +            true,
> > +        },
> > +        {
> > +            "x-preempt-pre-7-2",
> > +            &s->preempt_pre_7_2,
> > +            false,
> > +        },
> > +        {
> > +            "x-cpu-throttle-tailslow",
> > +            &s->parameters.cpu_throttle_tailslow,
> > +            false,
> > +        },
> > +        {
> > +            "multifd-clean-tls-termination",
> > +            &s->multifd_clean_tls_termination,
> > +            true,
> > +        },
> > +        {
> > +            "multifd-flush-after-each-section",
> > +            &s->multifd_flush_after_each_section,
> > +            false,
> > +        },
> > +    };
> > +    struct MigPropBool *prop;
> 
> This approach to declaring properties is pretty unpleasant
> to follow IMHO. Being a custom different approach from every
> other object impl is not a good thing.

[I asked this question elsewhere, I'll keep the discussion there]

> 
> > +
> > +    for (i = 0; i < ARRAY_SIZE(bool_list); i++) {
> > +        prop = &bool_list[i];
> > +        object_property_add_bool_ptr_def(obj, prop->name,
> > +                                         prop->ptr, prop->defvar);
> > +    }
> 
> Using instance level properties is the old way to do things,
> it is preferred to use class level properties instead.
> 
> This means you can't use the "ptr" concept to directly reference
> the instance fields and have to provide setters / getters explicitly
> instead, but as you've shown with the TLS properties,  a macro can
> make it simple to define the repetitive getters/setters.

If pointer is unwanted, I can switch to some more macro magic.  But since
this series got rewrote the 3rd time..  I'll make sure it's extremely
required before doing it..

> > +static void migration_object_init_props_enum(MigrationState *s)
> > +{
> > +    Object *obj = OBJECT(s);
> > +    ObjectProperty *prop;
> > +
> > +    prop = object_property_add_enum(obj, "multifd-compression",
> > +                                    "MultiFDCompression",
> > +                                    &MultiFDCompression_lookup,
> > +                                    mig_prop_multifd_compression_get,
> > +                                    mig_prop_multifd_compression_set);
> > +    object_property_set_default_str(prop, DEFAULT_MIGRATE_MULTIFD_COMPRESSION);
> > +
> > +    prop = object_property_add_enum(obj, "mode", "MigMode", &MigMode_lookup,
> > +                                    mig_prop_mode_get, mig_prop_mode_set);
> > +    object_property_set_default_str(prop, "normal");
> > +
> > +    prop = object_property_add_enum(obj, "zero-page-detection",
> > +                                    "ZeroPageDetection",
> > +                                    &ZeroPageDetection_lookup,
> > +                                    mig_prop_zero_page_detection_get,
> > +                                    mig_prop_zero_page_detection_set);
> > +    object_property_set_default_str(prop, "multifd");
> > +}
> 
> Perhaps I'm missing something, but I'm not seeing the point in
> using the set_default methods - in fact I'm not really sure why
> they exist in QOM at all.
> 
> I'd expect all defaults to be set in the instance _init method.
> ie why isn't this done as:
> 
>    void migrate_params_init(MigrationState *s)
>    {
>       s->parameters.mode = MIG_MODE_NORMAL;
>       s->parameters.zero_page_detection = ZERO_PAGE_DETECTION_MULTIFD;
>       .... all other defaults...
>    }

Yes frankly I asked myself the same question when looking at this.

I still saw quite some defvar references, type_print_class_properties() can
be one example where we dump help message with default values but without
the need to apply.  I didn't check the rest.  If the concept exists and if
we will be using qobj props, IMHO sticking with it is defintely safer so
that all qom future defvar changes will apply and it'll just work there.

> 
> 
> > +
> > +static void migration_object_init_properties(MigrationState *s)
> > +{
> > +    migration_object_init_props_bool(s);
> > +    migration_object_init_props_uint8(s);
> > +    migration_object_init_props_uint32(s);
> > +    migration_object_init_props_uint64(s);
> > +    migration_object_init_props_size(s);
> > +    migration_object_init_props_caps(s);
> > +    migration_object_init_props_tls(s);
> > +    migration_object_init_props_enum(s);
> > +}
> 
> ...and class properties be registered in migrate_params_class_init()
> and the grouping per type isn't helpful IMHO, just put all the
> object_class_property_add calls inline in one place.

I still want to avoid long functions, one way or another.

Hopefully it makes sense when I have those arrays to init different type of
props it makes sense to split with this, but I'm open to other way to
split.  I still want to not make it a extremely long function.

Thanks,

> 
> >  
> >  bool migrate_auto_converge(void)
> >  {
> > @@ -1107,9 +1246,10 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
> >      return params;
> >  }
> >  
> > -void migrate_params_init(MigrationParameters *params)
> > +void migrate_params_init(MigrationState *s)
> >  {
> > -    migrate_mark_all_params_present(params);
> > +    migration_object_init_properties(s);
> > +    migrate_mark_all_params_present(&s->parameters);
> >  }
> >  
> >  static void migrate_post_update_params(MigrationParameters *new, Error **errp)
> > -- 
> > 2.53.0
> > 
> 
> 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 :|
> 

-- 
Peter Xu



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

* Re: [PATCH v2 10/10] migration: Switch to TYPE_OBJECT with object properties
  2026-06-10 16:29   ` Daniel P. Berrangé
@ 2026-06-10 18:51     ` Peter Xu
  0 siblings, 0 replies; 30+ messages in thread
From: Peter Xu @ 2026-06-10 18:51 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-arm, Cédric Le Goater,
	Philippe Mathieu-Daudé, Fabiano Rosas,
	Vladimir Sementsov-Ogievskiy, Peter Maydell,
	Dr . David Alan Gilbert, Eric Blake, Akihiko Odaki, Paolo Bonzini,
	Kevin Wolf, Sana Sharma, Marc-André Lureau, Juraj Marcin,
	qemu-rust, Markus Armbruster, Mark Cave-Ayland

On Wed, Jun 10, 2026 at 05:29:59PM +0100, Daniel P. Berrangé wrote:
> -global is/was intended for devices, primarily those which
> are created by default as part of the machine. For dynamically
> created devices the docs recommend use of -device instead
> of -global.

I wished it was called -device-global then it'll be clearer, otherwise from
an API perspective it really shouldn't be limited to qdev..

It makes sense to not call it -device-global, IMHO essentially because we
don't necessarily need to restrict it to -device.

> 
> I get that -global was exposed for migration via the inappropriate
> use of TYPE_DEVICE as a parent for TYPE_MIGRATION, but I don't
> think we should be prolonging that misuse by exposing use of
> -global for things which are QOM rather than QDev.
> 
> If we want todo that for the sake of backcompat, IMHO it should
> be deprecated so it only lives for a short while after the
> conversion to QOM.
> 
> This makes me realize that this does not implement the UserCreatable
> interface on TYPE_MIGRATION, so I'm presuming the MigrationState is
> still created internally. Perhaps we should switch to making it a
> full UserCreatable, such that -object can be used to set all migration
> parameters on the command line and -global won't be required ? 

This is what Fabiano suggested in his reply here:

https://lore.kernel.org/qemu-devel/87jys75npb.fsf@suse.de/

I wonder what's your view on that when put together the singleton series I
used to post, where I also mentioned in the reply:

https://lore.kernel.org/qemu-devel/aimtYbka4GB9Qyk6@x1.local/

If you think that's the right approach, we can try to have it to replace
-global.  -global is debug API for migration, we don't need to obsolete it.
Compat property is, which is unaffected by this.  So we can remove -global
support for migration, but it'll always be good to have a replacement for
scripts.

Thanks,

-- 
Peter Xu



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

end of thread, other threads:[~2026-06-10 18:51 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-09 17:25 [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Peter Xu
2026-06-09 17:25 ` [PATCH v2 01/10] migration: Use OBJECT_DECLARE_SIMPLE_TYPE Peter Xu
2026-06-09 22:55   ` Fabiano Rosas
2026-06-10 13:56   ` Daniel P. Berrangé
2026-06-10 15:15   ` Mark Cave-Ayland
2026-06-09 17:25 ` [PATCH v2 02/10] qdev: Export global_props() Peter Xu
2026-06-09 22:55   ` Fabiano Rosas
2026-06-10 15:18   ` Mark Cave-Ayland
2026-06-09 17:25 ` [PATCH v2 03/10] qdev: Introduce DEFINE_PROP_*_NODEFAULT for bool/uint32 Peter Xu
2026-06-10 15:25   ` Mark Cave-Ayland
2026-06-09 17:25 ` [PATCH v2 04/10] hw/arm: Use nodefault version of qdev props when not needed Peter Xu
2026-06-10 15:31   ` Mark Cave-Ayland
2026-06-09 17:25 ` [PATCH v2 05/10] qom: Create object-property-ptr.[ch] Peter Xu
2026-06-10 16:15   ` Daniel P. Berrangé
2026-06-10 18:39     ` Peter Xu
2026-06-09 17:25 ` [PATCH v2 06/10] qom: Add object_property_add_bool_ptr() Peter Xu
2026-06-09 23:18   ` Fabiano Rosas
2026-06-09 17:25 ` [PATCH v2 07/10] qom: Add object_property_add_size_ptr() Peter Xu
2026-06-09 23:18   ` Fabiano Rosas
2026-06-09 17:25 ` [PATCH v2 08/10] qom: Add object_property_add_*_ptr_def() Peter Xu
2026-06-09 23:21   ` Fabiano Rosas
2026-06-09 17:25 ` [PATCH v2 09/10] qom: Allow default values for instance properties Peter Xu
2026-06-10 16:19   ` Daniel P. Berrangé
2026-06-09 17:25 ` [PATCH v2 10/10] migration: Switch to TYPE_OBJECT with object properties Peter Xu
2026-06-10 16:13   ` Daniel P. Berrangé
2026-06-10 18:46     ` Peter Xu
2026-06-10 16:29   ` Daniel P. Berrangé
2026-06-10 18:51     ` Peter Xu
2026-06-09 22:54 ` [PATCH v2 00/10] migration/qom: Remove TYPE_DEVICE dependency on migration object Fabiano Rosas
2026-06-10 18:30   ` Peter Xu

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.