All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties
@ 2016-10-29  1:47 Eduardo Habkost
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 1/8] tests: check-qom-proplist: Remove duplicate "bv" property Eduardo Habkost
                   ` (8 more replies)
  0 siblings, 9 replies; 50+ messages in thread
From: Eduardo Habkost @ 2016-10-29  1:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: Markus Armbruster, Andreas Färber, Daniel P. Berrange,
	Igor Mammedov

Changes v3 -> v4:
* FIx "make check" failures:
  * Fix e1000e initialization ordering (fixes
    tests/device-introspect-test failure)
    * Reported-by: Igor Mammedov <imammedo@redhat.com>
  * Call prop->info->release on instance_finalize (fixes
    tests/drive_del-test failure)
* See individual patches for other minor/style changes

Changes v2 -> v3:
* Small alignment fix in patch 3/6
* Included patches from "tests: A few check-qom-proplist fixes"
  in the series
* Rebased to latest qemu.git master

Changes v1 -> v2:
* s/qdev_class_set_props/device_class_set_props/
  * Suggested-by: Andreas Färber <afaerber@suse.de>

A git branch containing this series can be seen at:
  https://github.com/ehabkost/qemu-hacks.git work/device-list-abstract-properties

Eduardo Habkost (8):
  tests: check-qom-proplist: Remove duplicate "bv" property
  tests: check-qom-proplist: Use &error_abort to catch errors
  qdev: device_class_set_props() function
  qdev: Extract property-default code to qdev_property_set_to_default()
  qdev: Register static properties as class properties
  qom: object_class_property_iter_init() function
  qmp: Support abstract classes on device-list-properties
  qdev: Warning about using qdev_property_add_static() in new code

 hw/9pfs/virtio-9p-device.c          |   2 +-
 hw/acpi/piix4.c                     |   2 +-
 hw/arm/armv7m.c                     |   2 +-
 hw/arm/bcm2836.c                    |   2 +-
 hw/arm/integratorcp.c               |   2 +-
 hw/arm/musicpal.c                   |   2 +-
 hw/arm/pxa2xx.c                     |   4 +-
 hw/arm/pxa2xx_gpio.c                |   2 +-
 hw/arm/spitz.c                      |   2 +-
 hw/arm/stm32f205_soc.c              |   2 +-
 hw/arm/strongarm.c                  |   2 +-
 hw/arm/xlnx-zynqmp.c                |   2 +-
 hw/audio/ac97.c                     |   2 +-
 hw/audio/adlib.c                    |   2 +-
 hw/audio/cs4231.c                   |   2 +-
 hw/audio/cs4231a.c                  |   2 +-
 hw/audio/gus.c                      |   2 +-
 hw/audio/hda-codec.c                |   2 +-
 hw/audio/intel-hda.c                |   4 +-
 hw/audio/marvell_88w8618.c          |   2 +-
 hw/audio/pcspk.c                    |   2 +-
 hw/audio/pl041.c                    |   2 +-
 hw/audio/sb16.c                     |   2 +-
 hw/block/fdc.c                      |   8 +--
 hw/block/m25p80.c                   |   2 +-
 hw/block/nand.c                     |   2 +-
 hw/block/nvme.c                     |   2 +-
 hw/block/onenand.c                  |   2 +-
 hw/block/pflash_cfi01.c             |   2 +-
 hw/block/pflash_cfi02.c             |   2 +-
 hw/block/virtio-blk.c               |   2 +-
 hw/char/bcm2835_aux.c               |   2 +-
 hw/char/cadence_uart.c              |   2 +-
 hw/char/debugcon.c                  |   2 +-
 hw/char/digic-uart.c                |   2 +-
 hw/char/escc.c                      |   2 +-
 hw/char/etraxfs_ser.c               |   2 +-
 hw/char/exynos4210_uart.c           |   2 +-
 hw/char/grlib_apbuart.c             |   2 +-
 hw/char/imx_serial.c                |   2 +-
 hw/char/ipoctal232.c                |   2 +-
 hw/char/lm32_juart.c                |   2 +-
 hw/char/lm32_uart.c                 |   2 +-
 hw/char/milkymist-uart.c            |   2 +-
 hw/char/parallel.c                  |   2 +-
 hw/char/pl011.c                     |   2 +-
 hw/char/sclpconsole-lm.c            |   2 +-
 hw/char/sclpconsole.c               |   2 +-
 hw/char/serial-isa.c                |   2 +-
 hw/char/serial-pci.c                |   6 +-
 hw/char/spapr_vty.c                 |   2 +-
 hw/char/stm32f2xx_usart.c           |   2 +-
 hw/char/virtio-console.c            |   2 +-
 hw/char/virtio-serial-bus.c         |   4 +-
 hw/char/xilinx_uartlite.c           |   2 +-
 hw/core/generic-loader.c            |   2 +-
 hw/core/or-irq.c                    |   2 +-
 hw/core/platform-bus.c              |   2 +-
 hw/core/qdev.c                      | 125 ++++++++++++++++++++++++++++++------
 hw/cpu/a15mpcore.c                  |   2 +-
 hw/cpu/a9mpcore.c                   |   2 +-
 hw/cpu/arm11mpcore.c                |   2 +-
 hw/cpu/realview_mpcore.c            |   2 +-
 hw/display/bcm2835_fb.c             |   2 +-
 hw/display/cg3.c                    |   2 +-
 hw/display/cirrus_vga.c             |   4 +-
 hw/display/g364fb.c                 |   2 +-
 hw/display/milkymist-vgafb.c        |   2 +-
 hw/display/qxl.c                    |   2 +-
 hw/display/tcx.c                    |   2 +-
 hw/display/vga-isa.c                |   2 +-
 hw/display/vga-pci.c                |   4 +-
 hw/display/virtio-gpu-pci.c         |   2 +-
 hw/display/virtio-gpu.c             |   2 +-
 hw/display/virtio-vga.c             |   2 +-
 hw/display/vmware_vga.c             |   2 +-
 hw/dma/i82374.c                     |   2 +-
 hw/dma/i8257.c                      |   2 +-
 hw/dma/pl330.c                      |   2 +-
 hw/dma/pxa2xx_dma.c                 |   2 +-
 hw/dma/sparc32_dma.c                |   2 +-
 hw/dma/sun4m_iommu.c                |   2 +-
 hw/dma/xilinx_axidma.c              |   2 +-
 hw/gpio/imx_gpio.c                  |   2 +-
 hw/gpio/omap_gpio.c                 |   4 +-
 hw/i2c/core.c                       |   2 +-
 hw/i2c/omap_i2c.c                   |   2 +-
 hw/i2c/smbus_eeprom.c               |   2 +-
 hw/i386/intel_iommu.c               |   2 +-
 hw/i386/kvm/i8254.c                 |   2 +-
 hw/i386/kvm/ioapic.c                |   2 +-
 hw/i386/kvm/pci-assign.c            |   2 +-
 hw/i386/xen/xen_pvdevice.c          |   2 +-
 hw/ide/ahci.c                       |   2 +-
 hw/ide/cmd646.c                     |   2 +-
 hw/ide/isa.c                        |   2 +-
 hw/ide/mmio.c                       |   2 +-
 hw/ide/qdev.c                       |   8 +--
 hw/input/milkymist-softusb.c        |   2 +-
 hw/input/virtio-input-hid.c         |   2 +-
 hw/input/virtio-input-host.c        |   2 +-
 hw/input/virtio-input.c             |   2 +-
 hw/input/vmmouse.c                  |   2 +-
 hw/intc/apic_common.c               |   2 +-
 hw/intc/arm_gic_common.c            |   2 +-
 hw/intc/arm_gicv2m.c                |   2 +-
 hw/intc/arm_gicv3_common.c          |   2 +-
 hw/intc/etraxfs_pic.c               |   2 +-
 hw/intc/exynos4210_combiner.c       |   2 +-
 hw/intc/exynos4210_gic.c            |   4 +-
 hw/intc/grlib_irqmp.c               |   2 +-
 hw/intc/i8259_common.c              |   2 +-
 hw/intc/ioapic.c                    |   2 +-
 hw/intc/mips_gic.c                  |   2 +-
 hw/intc/omap_intc.c                 |   4 +-
 hw/intc/openpic.c                   |   2 +-
 hw/intc/openpic_kvm.c               |   2 +-
 hw/intc/xilinx_intc.c               |   2 +-
 hw/ipack/ipack.c                    |   2 +-
 hw/ipmi/ipmi.c                      |   2 +-
 hw/ipmi/ipmi_bmc_extern.c           |   2 +-
 hw/ipmi/isa_ipmi_bt.c               |   2 +-
 hw/ipmi/isa_ipmi_kcs.c              |   2 +-
 hw/isa/lpc_ich9.c                   |   2 +-
 hw/isa/pc87312.c                    |   2 +-
 hw/isa/vt82c686.c                   |   2 +-
 hw/mem/pc-dimm.c                    |   2 +-
 hw/mips/cps.c                       |   2 +-
 hw/misc/a9scu.c                     |   2 +-
 hw/misc/applesmc.c                  |   2 +-
 hw/misc/arm11scu.c                  |   2 +-
 hw/misc/arm_l2x0.c                  |   2 +-
 hw/misc/arm_sysctl.c                |   2 +-
 hw/misc/aspeed_scu.c                |   2 +-
 hw/misc/aspeed_sdmc.c               |   2 +-
 hw/misc/bcm2835_property.c          |   2 +-
 hw/misc/debugexit.c                 |   2 +-
 hw/misc/eccmemctl.c                 |   2 +-
 hw/misc/ivshmem.c                   |   6 +-
 hw/misc/macio/cuda.c                |   2 +-
 hw/misc/macio/macio.c               |   2 +-
 hw/misc/mips_cmgcr.c                |   2 +-
 hw/misc/mips_cpc.c                  |   2 +-
 hw/misc/mips_itu.c                  |   2 +-
 hw/misc/pvpanic.c                   |   2 +-
 hw/net/allwinner_emac.c             |   2 +-
 hw/net/cadence_gem.c                |   2 +-
 hw/net/dp8393x.c                    |   2 +-
 hw/net/e1000.c                      |   2 +-
 hw/net/e1000e.c                     |   3 +-
 hw/net/eepro100.c                   |   2 +-
 hw/net/etraxfs_eth.c                |   2 +-
 hw/net/fsl_etsec/etsec.c            |   2 +-
 hw/net/imx_fec.c                    |   2 +-
 hw/net/lan9118.c                    |   2 +-
 hw/net/lance.c                      |   2 +-
 hw/net/milkymist-minimac2.c         |   2 +-
 hw/net/mipsnet.c                    |   2 +-
 hw/net/ne2000-isa.c                 |   2 +-
 hw/net/ne2000.c                     |   2 +-
 hw/net/opencores_eth.c              |   2 +-
 hw/net/pcnet-pci.c                  |   2 +-
 hw/net/rocker/rocker.c              |   2 +-
 hw/net/rtl8139.c                    |   2 +-
 hw/net/smc91c111.c                  |   2 +-
 hw/net/spapr_llan.c                 |   2 +-
 hw/net/stellaris_enet.c             |   2 +-
 hw/net/virtio-net.c                 |   2 +-
 hw/net/vmxnet3.c                    |   2 +-
 hw/net/xgmac.c                      |   2 +-
 hw/net/xilinx_axienet.c             |   2 +-
 hw/net/xilinx_ethlite.c             |   2 +-
 hw/nvram/ds1225y.c                  |   2 +-
 hw/nvram/fw_cfg.c                   |   4 +-
 hw/nvram/mac_nvram.c                |   2 +-
 hw/nvram/spapr_nvram.c              |   2 +-
 hw/pci-bridge/ioh3420.c             |   2 +-
 hw/pci-bridge/pci_bridge_dev.c      |   2 +-
 hw/pci-bridge/pci_expander_bridge.c |   4 +-
 hw/pci-bridge/xio3130_downstream.c  |   2 +-
 hw/pci-host/piix.c                  |   2 +-
 hw/pci-host/ppce500.c               |   2 +-
 hw/pci-host/prep.c                  |   2 +-
 hw/pci-host/q35.c                   |   2 +-
 hw/pci-host/versatile.c             |   2 +-
 hw/pci/pci.c                        |   2 +-
 hw/pci/pcie_port.c                  |   4 +-
 hw/ppc/pnv.c                        |   2 +-
 hw/ppc/pnv_core.c                   |   2 +-
 hw/ppc/spapr_pci.c                  |   2 +-
 hw/ppc/spapr_pci_vfio.c             |   2 +-
 hw/ppc/spapr_rng.c                  |   2 +-
 hw/ppc/spapr_vio.c                  |   2 +-
 hw/s390x/css-bridge.c               |   2 +-
 hw/s390x/ipl.c                      |   2 +-
 hw/s390x/s390-pci-bus.c             |   2 +-
 hw/s390x/virtio-ccw.c               |  18 +++---
 hw/scsi/megasas.c                   |   2 +-
 hw/scsi/mptsas.c                    |   2 +-
 hw/scsi/scsi-bus.c                  |   2 +-
 hw/scsi/scsi-disk.c                 |   8 +--
 hw/scsi/scsi-generic.c              |   2 +-
 hw/scsi/spapr_vscsi.c               |   2 +-
 hw/scsi/vhost-scsi.c                |   2 +-
 hw/scsi/virtio-scsi.c               |   2 +-
 hw/scsi/vmw_pvscsi.c                |   2 +-
 hw/sd/sd.c                          |   2 +-
 hw/sd/sdhci.c                       |   4 +-
 hw/sparc/sun4m.c                    |   4 +-
 hw/sparc64/sun4u.c                  |   4 +-
 hw/ssi/aspeed_smc.c                 |   2 +-
 hw/ssi/xilinx_spi.c                 |   2 +-
 hw/ssi/xilinx_spips.c               |   2 +-
 hw/timer/a9gtimer.c                 |   2 +-
 hw/timer/allwinner-a10-pit.c        |   2 +-
 hw/timer/arm_mptimer.c              |   2 +-
 hw/timer/arm_timer.c                |   2 +-
 hw/timer/grlib_gptimer.c            |   2 +-
 hw/timer/hpet.c                     |   2 +-
 hw/timer/i8254.c                    |   2 +-
 hw/timer/lm32_timer.c               |   2 +-
 hw/timer/m48t59.c                   |   4 +-
 hw/timer/mc146818rtc.c              |   2 +-
 hw/timer/milkymist-sysctl.c         |   2 +-
 hw/timer/pxa2xx_timer.c             |   4 +-
 hw/timer/slavio_timer.c             |   2 +-
 hw/timer/stm32f2xx_timer.c          |   2 +-
 hw/timer/xilinx_timer.c             |   2 +-
 hw/tpm/tpm_tis.c                    |   2 +-
 hw/usb/bus.c                        |   2 +-
 hw/usb/ccid-card-emulated.c         |   2 +-
 hw/usb/ccid-card-passthru.c         |   2 +-
 hw/usb/dev-audio.c                  |   2 +-
 hw/usb/dev-hid.c                    |   6 +-
 hw/usb/dev-mtp.c                    |   2 +-
 hw/usb/dev-network.c                |   2 +-
 hw/usb/dev-serial.c                 |   4 +-
 hw/usb/dev-smartcard-reader.c       |   4 +-
 hw/usb/dev-storage.c                |   2 +-
 hw/usb/dev-uas.c                    |   2 +-
 hw/usb/hcd-ehci-pci.c               |   2 +-
 hw/usb/hcd-ehci-sysbus.c            |   2 +-
 hw/usb/hcd-ohci.c                   |   4 +-
 hw/usb/hcd-uhci.c                   |   4 +-
 hw/usb/hcd-xhci.c                   |   2 +-
 hw/usb/host-libusb.c                |   2 +-
 hw/usb/redirect.c                   |   2 +-
 hw/vfio/pci.c                       |   2 +-
 hw/vfio/platform.c                  |   2 +-
 hw/virtio/vhost-vsock.c             |   2 +-
 hw/virtio/virtio-balloon.c          |   2 +-
 hw/virtio/virtio-mmio.c             |   2 +-
 hw/virtio/virtio-pci.c              |  20 +++---
 hw/virtio/virtio-rng.c              |   2 +-
 hw/virtio/virtio.c                  |   2 +-
 hw/xen/xen_backend.c                |   2 +-
 hw/xen/xen_pt.c                     |   2 +-
 include/hw/qdev-core.h              |   6 ++
 include/qom/object.h                |  14 ++++
 qmp.c                               |  21 +++---
 qom/object.c                        |  10 ++-
 target-arm/cpu.c                    |   2 +-
 target-i386/cpu.c                   |   4 +-
 target-microblaze/cpu.c             |   2 +-
 target-ppc/translate_init.c         |   6 +-
 tests/check-qom-proplist.c          |  46 +++++++++----
 tests/test-qdev-global-props.c      |   2 +-
 267 files changed, 493 insertions(+), 362 deletions(-)

-- 
2.7.4

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

* [Qemu-devel] [PATCH v4 1/8] tests: check-qom-proplist: Remove duplicate "bv" property
  2016-10-29  1:47 [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties Eduardo Habkost
@ 2016-10-29  1:48 ` Eduardo Habkost
  2016-11-04 11:22   ` Markus Armbruster
  2016-11-04 15:56   ` Andreas Färber
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 2/8] tests: check-qom-proplist: Use &error_abort to catch errors Eduardo Habkost
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 50+ messages in thread
From: Eduardo Habkost @ 2016-10-29  1:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Markus Armbruster, Andreas Färber, Daniel P. Berrange,
	Igor Mammedov

The object_property_add_bool() call in dummy_init() is always
failing because there is an existing "bv" class property. We need
to remove either the "bv" class property or the "bv" instance
property.

Remove the class property so both object properties and class
properties are covered by the test code.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes series v2 -> v3:
* Patch imported from "tests: A few check-qom-proplist fixes"
  series
* Reworded commit message for clarity

Changes series v3 -> v4:
* (none)
---
 tests/check-qom-proplist.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
index a16cefc..693dc4c 100644
--- a/tests/check-qom-proplist.c
+++ b/tests/check-qom-proplist.c
@@ -129,10 +129,6 @@ static void dummy_init(Object *obj)
 
 static void dummy_class_init(ObjectClass *cls, void *data)
 {
-    object_class_property_add_bool(cls, "bv",
-                                   dummy_get_bv,
-                                   dummy_set_bv,
-                                   NULL);
     object_class_property_add_str(cls, "sv",
                                   dummy_get_sv,
                                   dummy_set_sv,
-- 
2.7.4

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

* [Qemu-devel] [PATCH v4 2/8] tests: check-qom-proplist: Use &error_abort to catch errors
  2016-10-29  1:47 [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties Eduardo Habkost
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 1/8] tests: check-qom-proplist: Remove duplicate "bv" property Eduardo Habkost
@ 2016-10-29  1:48 ` Eduardo Habkost
  2016-10-31 10:14   ` Igor Mammedov
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 3/8] qdev: device_class_set_props() function Eduardo Habkost
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 50+ messages in thread
From: Eduardo Habkost @ 2016-10-29  1:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Markus Armbruster, Andreas Färber, Daniel P. Berrange,
	Igor Mammedov

Use &error_abort so we don't ignore any errors on the property
registration calls.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes series v2 -> v3:
* Patch imported from "tests: A few check-qom-proplist fixes"
  series

Changes series v3 -> v4:
* Added &error_abort to more object_property_{add,del}_*()
  calls
  * Suggested-by: Igor Mammedov <imammedo@redhat.com>
---
 tests/check-qom-proplist.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
index 693dc4c..766a4a1 100644
--- a/tests/check-qom-proplist.c
+++ b/tests/check-qom-proplist.c
@@ -123,7 +123,7 @@ static void dummy_init(Object *obj)
     object_property_add_bool(obj, "bv",
                              dummy_get_bv,
                              dummy_set_bv,
-                             NULL);
+                             &error_abort);
 }
 
 
@@ -132,13 +132,13 @@ static void dummy_class_init(ObjectClass *cls, void *data)
     object_class_property_add_str(cls, "sv",
                                   dummy_get_sv,
                                   dummy_set_sv,
-                                  NULL);
+                                  &error_abort);
     object_class_property_add_enum(cls, "av",
                                    "DummyAnimal",
                                    dummy_animal_map,
                                    dummy_get_av,
                                    dummy_set_av,
-                                   NULL);
+                                   &error_abort);
 }
 
 
@@ -239,13 +239,13 @@ static void dummy_dev_init(Object *obj)
     DummyBus *bus = DUMMY_BUS(object_new(TYPE_DUMMY_BUS));
     DummyBackend *backend = DUMMY_BACKEND(object_new(TYPE_DUMMY_BACKEND));
 
-    object_property_add_child(obj, "bus", OBJECT(bus), NULL);
+    object_property_add_child(obj, "bus", OBJECT(bus), &error_abort);
     dev->bus = bus;
-    object_property_add_child(OBJECT(bus), "backend", OBJECT(backend), NULL);
+    object_property_add_child(OBJECT(bus), "backend", OBJECT(backend), &error_abort);
     bus->backend = backend;
 
     object_property_add_link(obj, "backend", TYPE_DUMMY_BACKEND,
-                             (Object **)&bus->backend, NULL, 0, NULL);
+                             (Object **)&bus->backend, NULL, 0, &error_abort);
 }
 
 static void dummy_dev_unparent(Object *obj)
@@ -274,7 +274,7 @@ static void dummy_bus_init(Object *obj)
 static void dummy_bus_unparent(Object *obj)
 {
     DummyBus *bus = DUMMY_BUS(obj);
-    object_property_del(obj->parent, "backend", NULL);
+    object_property_del(obj->parent, "backend", &error_abort);
     object_unparent(OBJECT(bus->backend));
 }
 
-- 
2.7.4

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

* [Qemu-devel] [PATCH v4 3/8] qdev: device_class_set_props() function
  2016-10-29  1:47 [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties Eduardo Habkost
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 1/8] tests: check-qom-proplist: Remove duplicate "bv" property Eduardo Habkost
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 2/8] tests: check-qom-proplist: Use &error_abort to catch errors Eduardo Habkost
@ 2016-10-29  1:48 ` Eduardo Habkost
  2016-11-01 15:02   ` Igor Mammedov
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 4/8] qdev: Extract property-default code to qdev_property_set_to_default() Eduardo Habkost
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 50+ messages in thread
From: Eduardo Habkost @ 2016-10-29  1:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Markus Armbruster, Andreas Färber, Daniel P. Berrange,
	Igor Mammedov

Replace direct assignment of DeviceClass::props with a
device_class_set_props() function. The new function will handle
registration of class properties, later.

Most of the existing code was converted using the Coccinelle
patch below. Exceptions are:
* manual conversion of target-ppc/translate_init.c;
* reordering of code at e1000e_class_init() to ensure
  device_class_set_props() is called after initialization
  of the PropertyInfo structs.

Coccinelle patch:

  @@
  identifier DC;
  expression PROPS;
  typedef DeviceClass;
  @@
   DeviceClass *DC;
   ...
  -DC->props = PROPS;
  +device_class_set_props(DC, PROPS);

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes v1 -> v2:
* s/qdev_class_set_props/device_class_set_props/
  * Suggested-by: Andreas Färber <afaerber@suse.de>

Changes v2 -> v3:
* Rebased to latest qemu.git master

Changes v3 -> v4:
* Fix e1000e initialization ordering (fixes "make check" failure)
  * Reported-by: Igor Mammedov <imammedo@redhat.com>
* Rebased to latest qemu.git master (new functions changed:
  floppy_drive_class_init(), pnv_chip_class_init(),
  pnv_core_class_init())
---
 hw/9pfs/virtio-9p-device.c          |  2 +-
 hw/acpi/piix4.c                     |  2 +-
 hw/arm/armv7m.c                     |  2 +-
 hw/arm/bcm2836.c                    |  2 +-
 hw/arm/integratorcp.c               |  2 +-
 hw/arm/musicpal.c                   |  2 +-
 hw/arm/pxa2xx.c                     |  4 ++--
 hw/arm/pxa2xx_gpio.c                |  2 +-
 hw/arm/spitz.c                      |  2 +-
 hw/arm/stm32f205_soc.c              |  2 +-
 hw/arm/strongarm.c                  |  2 +-
 hw/arm/xlnx-zynqmp.c                |  2 +-
 hw/audio/ac97.c                     |  2 +-
 hw/audio/adlib.c                    |  2 +-
 hw/audio/cs4231.c                   |  2 +-
 hw/audio/cs4231a.c                  |  2 +-
 hw/audio/gus.c                      |  2 +-
 hw/audio/hda-codec.c                |  2 +-
 hw/audio/intel-hda.c                |  4 ++--
 hw/audio/marvell_88w8618.c          |  2 +-
 hw/audio/pcspk.c                    |  2 +-
 hw/audio/pl041.c                    |  2 +-
 hw/audio/sb16.c                     |  2 +-
 hw/block/fdc.c                      |  8 ++++----
 hw/block/m25p80.c                   |  2 +-
 hw/block/nand.c                     |  2 +-
 hw/block/nvme.c                     |  2 +-
 hw/block/onenand.c                  |  2 +-
 hw/block/pflash_cfi01.c             |  2 +-
 hw/block/pflash_cfi02.c             |  2 +-
 hw/block/virtio-blk.c               |  2 +-
 hw/char/bcm2835_aux.c               |  2 +-
 hw/char/cadence_uart.c              |  2 +-
 hw/char/debugcon.c                  |  2 +-
 hw/char/digic-uart.c                |  2 +-
 hw/char/escc.c                      |  2 +-
 hw/char/etraxfs_ser.c               |  2 +-
 hw/char/exynos4210_uart.c           |  2 +-
 hw/char/grlib_apbuart.c             |  2 +-
 hw/char/imx_serial.c                |  2 +-
 hw/char/ipoctal232.c                |  2 +-
 hw/char/lm32_juart.c                |  2 +-
 hw/char/lm32_uart.c                 |  2 +-
 hw/char/milkymist-uart.c            |  2 +-
 hw/char/parallel.c                  |  2 +-
 hw/char/pl011.c                     |  2 +-
 hw/char/sclpconsole-lm.c            |  2 +-
 hw/char/sclpconsole.c               |  2 +-
 hw/char/serial-isa.c                |  2 +-
 hw/char/serial-pci.c                |  6 +++---
 hw/char/spapr_vty.c                 |  2 +-
 hw/char/stm32f2xx_usart.c           |  2 +-
 hw/char/virtio-console.c            |  2 +-
 hw/char/virtio-serial-bus.c         |  4 ++--
 hw/char/xilinx_uartlite.c           |  2 +-
 hw/core/generic-loader.c            |  2 +-
 hw/core/or-irq.c                    |  2 +-
 hw/core/platform-bus.c              |  2 +-
 hw/core/qdev.c                      |  6 ++++++
 hw/cpu/a15mpcore.c                  |  2 +-
 hw/cpu/a9mpcore.c                   |  2 +-
 hw/cpu/arm11mpcore.c                |  2 +-
 hw/cpu/realview_mpcore.c            |  2 +-
 hw/display/bcm2835_fb.c             |  2 +-
 hw/display/cg3.c                    |  2 +-
 hw/display/cirrus_vga.c             |  4 ++--
 hw/display/g364fb.c                 |  2 +-
 hw/display/milkymist-vgafb.c        |  2 +-
 hw/display/qxl.c                    |  2 +-
 hw/display/tcx.c                    |  2 +-
 hw/display/vga-isa.c                |  2 +-
 hw/display/vga-pci.c                |  4 ++--
 hw/display/virtio-gpu-pci.c         |  2 +-
 hw/display/virtio-gpu.c             |  2 +-
 hw/display/virtio-vga.c             |  2 +-
 hw/display/vmware_vga.c             |  2 +-
 hw/dma/i82374.c                     |  2 +-
 hw/dma/i8257.c                      |  2 +-
 hw/dma/pl330.c                      |  2 +-
 hw/dma/pxa2xx_dma.c                 |  2 +-
 hw/dma/sparc32_dma.c                |  2 +-
 hw/dma/sun4m_iommu.c                |  2 +-
 hw/dma/xilinx_axidma.c              |  2 +-
 hw/gpio/imx_gpio.c                  |  2 +-
 hw/gpio/omap_gpio.c                 |  4 ++--
 hw/i2c/core.c                       |  2 +-
 hw/i2c/omap_i2c.c                   |  2 +-
 hw/i2c/smbus_eeprom.c               |  2 +-
 hw/i386/intel_iommu.c               |  2 +-
 hw/i386/kvm/i8254.c                 |  2 +-
 hw/i386/kvm/ioapic.c                |  2 +-
 hw/i386/kvm/pci-assign.c            |  2 +-
 hw/i386/xen/xen_pvdevice.c          |  2 +-
 hw/ide/ahci.c                       |  2 +-
 hw/ide/cmd646.c                     |  2 +-
 hw/ide/isa.c                        |  2 +-
 hw/ide/mmio.c                       |  2 +-
 hw/ide/qdev.c                       |  8 ++++----
 hw/input/milkymist-softusb.c        |  2 +-
 hw/input/virtio-input-hid.c         |  2 +-
 hw/input/virtio-input-host.c        |  2 +-
 hw/input/virtio-input.c             |  2 +-
 hw/input/vmmouse.c                  |  2 +-
 hw/intc/apic_common.c               |  2 +-
 hw/intc/arm_gic_common.c            |  2 +-
 hw/intc/arm_gicv2m.c                |  2 +-
 hw/intc/arm_gicv3_common.c          |  2 +-
 hw/intc/etraxfs_pic.c               |  2 +-
 hw/intc/exynos4210_combiner.c       |  2 +-
 hw/intc/exynos4210_gic.c            |  4 ++--
 hw/intc/grlib_irqmp.c               |  2 +-
 hw/intc/i8259_common.c              |  2 +-
 hw/intc/ioapic.c                    |  2 +-
 hw/intc/mips_gic.c                  |  2 +-
 hw/intc/omap_intc.c                 |  4 ++--
 hw/intc/openpic.c                   |  2 +-
 hw/intc/openpic_kvm.c               |  2 +-
 hw/intc/xilinx_intc.c               |  2 +-
 hw/ipack/ipack.c                    |  2 +-
 hw/ipmi/ipmi.c                      |  2 +-
 hw/ipmi/ipmi_bmc_extern.c           |  2 +-
 hw/ipmi/isa_ipmi_bt.c               |  2 +-
 hw/ipmi/isa_ipmi_kcs.c              |  2 +-
 hw/isa/lpc_ich9.c                   |  2 +-
 hw/isa/pc87312.c                    |  2 +-
 hw/isa/vt82c686.c                   |  2 +-
 hw/mem/pc-dimm.c                    |  2 +-
 hw/mips/cps.c                       |  2 +-
 hw/misc/a9scu.c                     |  2 +-
 hw/misc/applesmc.c                  |  2 +-
 hw/misc/arm11scu.c                  |  2 +-
 hw/misc/arm_l2x0.c                  |  2 +-
 hw/misc/arm_sysctl.c                |  2 +-
 hw/misc/aspeed_scu.c                |  2 +-
 hw/misc/aspeed_sdmc.c               |  2 +-
 hw/misc/bcm2835_property.c          |  2 +-
 hw/misc/debugexit.c                 |  2 +-
 hw/misc/eccmemctl.c                 |  2 +-
 hw/misc/ivshmem.c                   |  6 +++---
 hw/misc/macio/cuda.c                |  2 +-
 hw/misc/macio/macio.c               |  2 +-
 hw/misc/mips_cmgcr.c                |  2 +-
 hw/misc/mips_cpc.c                  |  2 +-
 hw/misc/mips_itu.c                  |  2 +-
 hw/misc/pvpanic.c                   |  2 +-
 hw/net/allwinner_emac.c             |  2 +-
 hw/net/cadence_gem.c                |  2 +-
 hw/net/dp8393x.c                    |  2 +-
 hw/net/e1000.c                      |  2 +-
 hw/net/e1000e.c                     |  3 ++-
 hw/net/eepro100.c                   |  2 +-
 hw/net/etraxfs_eth.c                |  2 +-
 hw/net/fsl_etsec/etsec.c            |  2 +-
 hw/net/imx_fec.c                    |  2 +-
 hw/net/lan9118.c                    |  2 +-
 hw/net/lance.c                      |  2 +-
 hw/net/milkymist-minimac2.c         |  2 +-
 hw/net/mipsnet.c                    |  2 +-
 hw/net/ne2000-isa.c                 |  2 +-
 hw/net/ne2000.c                     |  2 +-
 hw/net/opencores_eth.c              |  2 +-
 hw/net/pcnet-pci.c                  |  2 +-
 hw/net/rocker/rocker.c              |  2 +-
 hw/net/rtl8139.c                    |  2 +-
 hw/net/smc91c111.c                  |  2 +-
 hw/net/spapr_llan.c                 |  2 +-
 hw/net/stellaris_enet.c             |  2 +-
 hw/net/virtio-net.c                 |  2 +-
 hw/net/vmxnet3.c                    |  2 +-
 hw/net/xgmac.c                      |  2 +-
 hw/net/xilinx_axienet.c             |  2 +-
 hw/net/xilinx_ethlite.c             |  2 +-
 hw/nvram/ds1225y.c                  |  2 +-
 hw/nvram/fw_cfg.c                   |  4 ++--
 hw/nvram/mac_nvram.c                |  2 +-
 hw/nvram/spapr_nvram.c              |  2 +-
 hw/pci-bridge/ioh3420.c             |  2 +-
 hw/pci-bridge/pci_bridge_dev.c      |  2 +-
 hw/pci-bridge/pci_expander_bridge.c |  4 ++--
 hw/pci-bridge/xio3130_downstream.c  |  2 +-
 hw/pci-host/piix.c                  |  2 +-
 hw/pci-host/ppce500.c               |  2 +-
 hw/pci-host/prep.c                  |  2 +-
 hw/pci-host/q35.c                   |  2 +-
 hw/pci-host/versatile.c             |  2 +-
 hw/pci/pci.c                        |  2 +-
 hw/pci/pcie_port.c                  |  4 ++--
 hw/ppc/pnv.c                        |  2 +-
 hw/ppc/pnv_core.c                   |  2 +-
 hw/ppc/spapr_pci.c                  |  2 +-
 hw/ppc/spapr_pci_vfio.c             |  2 +-
 hw/ppc/spapr_rng.c                  |  2 +-
 hw/ppc/spapr_vio.c                  |  2 +-
 hw/s390x/css-bridge.c               |  2 +-
 hw/s390x/ipl.c                      |  2 +-
 hw/s390x/s390-pci-bus.c             |  2 +-
 hw/s390x/virtio-ccw.c               | 18 +++++++++---------
 hw/scsi/megasas.c                   |  2 +-
 hw/scsi/mptsas.c                    |  2 +-
 hw/scsi/scsi-bus.c                  |  2 +-
 hw/scsi/scsi-disk.c                 |  8 ++++----
 hw/scsi/scsi-generic.c              |  2 +-
 hw/scsi/spapr_vscsi.c               |  2 +-
 hw/scsi/vhost-scsi.c                |  2 +-
 hw/scsi/virtio-scsi.c               |  2 +-
 hw/scsi/vmw_pvscsi.c                |  2 +-
 hw/sd/sd.c                          |  2 +-
 hw/sd/sdhci.c                       |  4 ++--
 hw/sparc/sun4m.c                    |  4 ++--
 hw/sparc64/sun4u.c                  |  4 ++--
 hw/ssi/aspeed_smc.c                 |  2 +-
 hw/ssi/xilinx_spi.c                 |  2 +-
 hw/ssi/xilinx_spips.c               |  2 +-
 hw/timer/a9gtimer.c                 |  2 +-
 hw/timer/allwinner-a10-pit.c        |  2 +-
 hw/timer/arm_mptimer.c              |  2 +-
 hw/timer/arm_timer.c                |  2 +-
 hw/timer/grlib_gptimer.c            |  2 +-
 hw/timer/hpet.c                     |  2 +-
 hw/timer/i8254.c                    |  2 +-
 hw/timer/lm32_timer.c               |  2 +-
 hw/timer/m48t59.c                   |  4 ++--
 hw/timer/mc146818rtc.c              |  2 +-
 hw/timer/milkymist-sysctl.c         |  2 +-
 hw/timer/pxa2xx_timer.c             |  4 ++--
 hw/timer/slavio_timer.c             |  2 +-
 hw/timer/stm32f2xx_timer.c          |  2 +-
 hw/timer/xilinx_timer.c             |  2 +-
 hw/tpm/tpm_tis.c                    |  2 +-
 hw/usb/bus.c                        |  2 +-
 hw/usb/ccid-card-emulated.c         |  2 +-
 hw/usb/ccid-card-passthru.c         |  2 +-
 hw/usb/dev-audio.c                  |  2 +-
 hw/usb/dev-hid.c                    |  6 +++---
 hw/usb/dev-mtp.c                    |  2 +-
 hw/usb/dev-network.c                |  2 +-
 hw/usb/dev-serial.c                 |  4 ++--
 hw/usb/dev-smartcard-reader.c       |  4 ++--
 hw/usb/dev-storage.c                |  2 +-
 hw/usb/dev-uas.c                    |  2 +-
 hw/usb/hcd-ehci-pci.c               |  2 +-
 hw/usb/hcd-ehci-sysbus.c            |  2 +-
 hw/usb/hcd-ohci.c                   |  4 ++--
 hw/usb/hcd-uhci.c                   |  4 ++--
 hw/usb/hcd-xhci.c                   |  2 +-
 hw/usb/host-libusb.c                |  2 +-
 hw/usb/redirect.c                   |  2 +-
 hw/vfio/pci.c                       |  2 +-
 hw/vfio/platform.c                  |  2 +-
 hw/virtio/vhost-vsock.c             |  2 +-
 hw/virtio/virtio-balloon.c          |  2 +-
 hw/virtio/virtio-mmio.c             |  2 +-
 hw/virtio/virtio-pci.c              | 20 ++++++++++----------
 hw/virtio/virtio-rng.c              |  2 +-
 hw/virtio/virtio.c                  |  2 +-
 hw/xen/xen_backend.c                |  2 +-
 hw/xen/xen_pt.c                     |  2 +-
 include/hw/qdev-core.h              |  6 ++++++
 target-arm/cpu.c                    |  2 +-
 target-i386/cpu.c                   |  4 ++--
 target-microblaze/cpu.c             |  2 +-
 target-ppc/translate_init.c         |  6 +++---
 tests/test-qdev-global-props.c      |  2 +-
 263 files changed, 329 insertions(+), 316 deletions(-)

diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 1782e4a..10d1a82 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -207,7 +207,7 @@ static void virtio_9p_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
 
-    dc->props = virtio_9p_properties;
+    device_class_set_props(dc, virtio_9p_properties);
     dc->vmsd = &vmstate_virtio_9p;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
     vdc->realize = virtio_9p_device_realize;
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 2adc246..fce2b65 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -687,7 +687,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_BRIDGE_OTHER;
     dc->desc = "PM";
     dc->vmsd = &vmstate_acpi;
-    dc->props = piix4_pm_properties;
+    device_class_set_props(dc, piix4_pm_properties);
     /*
      * Reason: part of PIIX4 southbridge, needs to be wired up,
      * e.g. by mips_malta_init()
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index 49d3078..e14e28a 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -245,7 +245,7 @@ static void bitband_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = bitband_properties;
+    device_class_set_props(dc, bitband_properties);
 }
 
 static const TypeInfo bitband_info = {
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index 8451190..14f2db0 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -158,7 +158,7 @@ static void bcm2836_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
 
-    dc->props = bcm2836_props;
+    device_class_set_props(dc, bcm2836_props);
     dc->realize = bcm2836_realize;
 
     /*
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index 039812a..93e5326 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -638,7 +638,7 @@ static void core_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = core_properties;
+    device_class_set_props(dc, core_properties);
     dc->realize = integratorcm_realize;
 }
 
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index cbbca4e..c3a2430 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -431,7 +431,7 @@ static void mv88w8618_eth_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->vmsd = &mv88w8618_eth_vmsd;
-    dc->props = mv88w8618_eth_properties;
+    device_class_set_props(dc, mv88w8618_eth_properties);
     dc->realize = mv88w8618_eth_realize;
 }
 
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 42cdde0..59b143a 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1530,7 +1530,7 @@ static void pxa2xx_i2c_class_init(ObjectClass *klass, void *data)
 
     dc->desc = "PXA2xx I2C Bus Controller";
     dc->vmsd = &vmstate_pxa2xx_i2c;
-    dc->props = pxa2xx_i2c_properties;
+    device_class_set_props(dc, pxa2xx_i2c_properties);
 }
 
 static const TypeInfo pxa2xx_i2c_info = {
@@ -2013,7 +2013,7 @@ static void pxa2xx_fir_class_init(ObjectClass *klass, void *data)
 
     dc->realize = pxa2xx_fir_realize;
     dc->vmsd = &pxa2xx_fir_vmsd;
-    dc->props = pxa2xx_fir_properties;
+    device_class_set_props(dc, pxa2xx_fir_properties);
     dc->reset = pxa2xx_fir_reset;
 }
 
diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c
index 521dbad..ff8c8e0 100644
--- a/hw/arm/pxa2xx_gpio.c
+++ b/hw/arm/pxa2xx_gpio.c
@@ -343,7 +343,7 @@ static void pxa2xx_gpio_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->desc = "PXA2xx GPIO controller";
-    dc->props = pxa2xx_gpio_properties;
+    device_class_set_props(dc, pxa2xx_gpio_properties);
     dc->vmsd = &vmstate_pxa2xx_gpio_regs;
     dc->realize = pxa2xx_gpio_realize;
 }
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 41cc2ee..6cd8bf4 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -1060,7 +1060,7 @@ static void sl_nand_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->vmsd = &vmstate_sl_nand_info;
-    dc->props = sl_nand_properties;
+    device_class_set_props(dc, sl_nand_properties);
     /* Reason: init() method uses drive_get() */
     dc->cannot_instantiate_with_device_add_yet = true;
 }
diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c
index 38425bd..4a9ae54 100644
--- a/hw/arm/stm32f205_soc.c
+++ b/hw/arm/stm32f205_soc.c
@@ -202,7 +202,7 @@ static void stm32f205_soc_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = stm32f205_soc_realize;
-    dc->props = stm32f205_soc_properties;
+    device_class_set_props(dc, stm32f205_soc_properties);
 }
 
 static const TypeInfo stm32f205_soc_info = {
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index 3311cc3..d458802 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -1320,7 +1320,7 @@ static void strongarm_uart_class_init(ObjectClass *klass, void *data)
     dc->desc = "StrongARM UART controller";
     dc->reset = strongarm_uart_reset;
     dc->vmsd = &vmstate_strongarm_uart_regs;
-    dc->props = strongarm_uart_properties;
+    device_class_set_props(dc, strongarm_uart_properties);
     dc->realize = strongarm_uart_realize;
 }
 
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 0d86ba3..a194480 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -435,7 +435,7 @@ static void xlnx_zynqmp_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
 
-    dc->props = xlnx_zynqmp_props;
+    device_class_set_props(dc, xlnx_zynqmp_props);
     dc->realize = xlnx_zynqmp_realize;
 
     /*
diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c
index cbd959e..2147c8a 100644
--- a/hw/audio/ac97.c
+++ b/hw/audio/ac97.c
@@ -1411,7 +1411,7 @@ static void ac97_class_init (ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
     dc->desc = "Intel 82801AA AC97 Audio";
     dc->vmsd = &vmstate_ac97;
-    dc->props = ac97_properties;
+    device_class_set_props(dc, ac97_properties);
     dc->reset = ac97_on_reset;
 }
 
diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c
index 7836446..b375cef 100644
--- a/hw/audio/adlib.c
+++ b/hw/audio/adlib.c
@@ -361,7 +361,7 @@ static void adlib_class_initfn (ObjectClass *klass, void *data)
     dc->realize = adlib_realizefn;
     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
     dc->desc = ADLIB_DESC;
-    dc->props = adlib_properties;
+    device_class_set_props(dc, adlib_properties);
 }
 
 static const TypeInfo adlib_info = {
diff --git a/hw/audio/cs4231.c b/hw/audio/cs4231.c
index 30690f9..159b43d 100644
--- a/hw/audio/cs4231.c
+++ b/hw/audio/cs4231.c
@@ -166,7 +166,7 @@ static void cs4231_class_init(ObjectClass *klass, void *data)
 
     dc->reset = cs_reset;
     dc->vmsd = &vmstate_cs4231;
-    dc->props = cs4231_properties;
+    device_class_set_props(dc, cs4231_properties);
 }
 
 static const TypeInfo cs4231_info = {
diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c
index 3ecd058..ec2c74c 100644
--- a/hw/audio/cs4231a.c
+++ b/hw/audio/cs4231a.c
@@ -695,7 +695,7 @@ static void cs4231a_class_initfn (ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
     dc->desc = "Crystal Semiconductor CS4231A";
     dc->vmsd = &vmstate_cs4231a;
-    dc->props = cs4231a_properties;
+    device_class_set_props(dc, cs4231a_properties);
 }
 
 static const TypeInfo cs4231a_info = {
diff --git a/hw/audio/gus.c b/hw/audio/gus.c
index 3d08a65..c69a8c8 100644
--- a/hw/audio/gus.c
+++ b/hw/audio/gus.c
@@ -305,7 +305,7 @@ static void gus_class_initfn (ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
     dc->desc = "Gravis Ultrasound GF1";
     dc->vmsd = &vmstate_gus;
-    dc->props = gus_properties;
+    device_class_set_props(dc, gus_properties);
 }
 
 static const TypeInfo gus_info = {
diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c
index 52d4640..9dd7624 100644
--- a/hw/audio/hda-codec.c
+++ b/hw/audio/hda-codec.c
@@ -663,7 +663,7 @@ static void hda_audio_base_class_init(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
     dc->reset = hda_audio_reset;
     dc->vmsd = &vmstate_hda_audio;
-    dc->props = hda_audio_properties;
+    device_class_set_props(dc, hda_audio_properties);
 }
 
 static const TypeInfo hda_audio_info = {
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index 537face..d1b83ac 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -1269,7 +1269,7 @@ static void intel_hda_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_MULTIMEDIA_HD_AUDIO;
     dc->reset = intel_hda_reset;
     dc->vmsd = &vmstate_intel_hda;
-    dc->props = intel_hda_properties;
+    device_class_set_props(dc, intel_hda_properties);
 }
 
 static void intel_hda_class_init_ich6(ObjectClass *klass, void *data)
@@ -1321,7 +1321,7 @@ static void hda_codec_device_class_init(ObjectClass *klass, void *data)
     k->exit = hda_codec_dev_exit;
     set_bit(DEVICE_CATEGORY_SOUND, k->categories);
     k->bus_type = TYPE_HDA_BUS;
-    k->props = hda_props;
+    device_class_set_props(k, hda_props);
 }
 
 static const TypeInfo hda_codec_device_type_info = {
diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c
index a6ca180..fe6a9ba 100644
--- a/hw/audio/marvell_88w8618.c
+++ b/hw/audio/marvell_88w8618.c
@@ -287,7 +287,7 @@ static void mv88w8618_audio_class_init(ObjectClass *klass, void *data)
     k->init = mv88w8618_audio_init;
     dc->reset = mv88w8618_audio_reset;
     dc->vmsd = &mv88w8618_audio_vmsd;
-    dc->props = mv88w8618_audio_properties;
+    device_class_set_props(dc, mv88w8618_audio_properties);
     /* Reason: pointer property "wm8750" */
     dc->cannot_instantiate_with_device_add_yet = true;
 }
diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
index 984534b..2484075 100644
--- a/hw/audio/pcspk.c
+++ b/hw/audio/pcspk.c
@@ -211,7 +211,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data)
     dc->realize = pcspk_realizefn;
     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
     dc->vmsd = &vmstate_spk;
-    dc->props = pcspk_properties;
+    device_class_set_props(dc, pcspk_properties);
     /* Reason: realize sets global pcspk_state */
     dc->cannot_instantiate_with_device_add_yet = true;
 }
diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c
index 6e9c104..738d0de 100644
--- a/hw/audio/pl041.c
+++ b/hw/audio/pl041.c
@@ -633,7 +633,7 @@ static void pl041_device_class_init(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
     dc->reset = pl041_device_reset;
     dc->vmsd = &vmstate_pl041;
-    dc->props = pl041_device_properties;
+    device_class_set_props(dc, pl041_device_properties);
 }
 
 static const TypeInfo pl041_device_info = {
diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c
index 6b4427f..2e6c602 100644
--- a/hw/audio/sb16.c
+++ b/hw/audio/sb16.c
@@ -1418,7 +1418,7 @@ static void sb16_class_initfn (ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
     dc->desc = "Creative Sound Blaster 16";
     dc->vmsd = &vmstate_sb16;
-    dc->props = sb16_properties;
+    device_class_set_props(dc, sb16_properties);
 }
 
 static const TypeInfo sb16_info = {
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 17d29e7..6976bf4 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -587,7 +587,7 @@ static void floppy_drive_class_init(ObjectClass *klass, void *data)
     k->init = floppy_drive_init;
     set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
     k->bus_type = TYPE_FLOPPY_BUS;
-    k->props = floppy_drive_properties;
+    device_class_set_props(k, floppy_drive_properties);
     k->desc = "virtual floppy drive";
 }
 
@@ -2803,7 +2803,7 @@ static void isabus_fdc_class_init(ObjectClass *klass, void *data)
     dc->fw_name = "fdc";
     dc->reset = fdctrl_external_reset_isa;
     dc->vmsd = &vmstate_isa_fdc;
-    dc->props = isa_fdc_properties;
+    device_class_set_props(dc, isa_fdc_properties);
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
 
@@ -2856,7 +2856,7 @@ static void sysbus_fdc_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = sysbus_fdc_properties;
+    device_class_set_props(dc, sysbus_fdc_properties);
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
 
@@ -2882,7 +2882,7 @@ static void sun4m_fdc_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = sun4m_fdc_properties;
+    device_class_set_props(dc, sun4m_fdc_properties);
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
 
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index d29ff4c..e2c9c52 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -1228,7 +1228,7 @@ static void m25p80_class_init(ObjectClass *klass, void *data)
     k->set_cs = m25p80_cs;
     k->cs_polarity = SSI_CS_LOW;
     dc->vmsd = &vmstate_m25p80;
-    dc->props = m25p80_properties;
+    device_class_set_props(dc, m25p80_properties);
     dc->reset = m25p80_reset;
     mc->pi = data;
 }
diff --git a/hw/block/nand.c b/hw/block/nand.c
index c69e675..d4561fb 100644
--- a/hw/block/nand.c
+++ b/hw/block/nand.c
@@ -437,7 +437,7 @@ static void nand_class_init(ObjectClass *klass, void *data)
     dc->realize = nand_realize;
     dc->reset = nand_reset;
     dc->vmsd = &vmstate_nand;
-    dc->props = nand_properties;
+    device_class_set_props(dc, nand_properties);
 }
 
 static const TypeInfo nand_info = {
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index b380142..48eb372 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -961,7 +961,7 @@ static void nvme_class_init(ObjectClass *oc, void *data)
 
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
     dc->desc = "Non-Volatile Memory Express";
-    dc->props = nvme_props;
+    device_class_set_props(dc, nvme_props);
     dc->vmsd = &nvme_vmstate;
 }
 
diff --git a/hw/block/onenand.c b/hw/block/onenand.c
index 8d84227..56a7262 100644
--- a/hw/block/onenand.c
+++ b/hw/block/onenand.c
@@ -838,7 +838,7 @@ static void onenand_class_init(ObjectClass *klass, void *data)
 
     k->init = onenand_initfn;
     dc->reset = onenand_system_reset;
-    dc->props = onenand_properties;
+    device_class_set_props(dc, onenand_properties);
 }
 
 static const TypeInfo onenand_info = {
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 62d7a56..0550d35 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -893,7 +893,7 @@ static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = pflash_cfi01_realize;
-    dc->props = pflash_cfi01_properties;
+    device_class_set_props(dc, pflash_cfi01_properties);
     dc->vmsd = &vmstate_pflash;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index 4f6105c..ba1437e 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -744,7 +744,7 @@ static void pflash_cfi02_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = pflash_cfi02_realize;
-    dc->props = pflash_cfi02_properties;
+    device_class_set_props(dc, pflash_cfi02_properties);
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
 
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 37fe72b..0e40676 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -990,7 +990,7 @@ static void virtio_blk_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
 
-    dc->props = virtio_blk_properties;
+    device_class_set_props(dc, virtio_blk_properties);
     dc->vmsd = &vmstate_virtio_blk;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
     vdc->realize = virtio_blk_device_realize;
diff --git a/hw/char/bcm2835_aux.c b/hw/char/bcm2835_aux.c
index 4d46ad6..b6613e3 100644
--- a/hw/char/bcm2835_aux.c
+++ b/hw/char/bcm2835_aux.c
@@ -294,7 +294,7 @@ static void bcm2835_aux_class_init(ObjectClass *oc, void *data)
     dc->realize = bcm2835_aux_realize;
     dc->vmsd = &vmstate_bcm2835_aux;
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-    dc->props = bcm2835_aux_props;
+    device_class_set_props(dc, bcm2835_aux_props);
 }
 
 static const TypeInfo bcm2835_aux_info = {
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index c2b9154..fed2c41 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -522,7 +522,7 @@ static void cadence_uart_class_init(ObjectClass *klass, void *data)
     dc->realize = cadence_uart_realize;
     dc->vmsd = &vmstate_cadence_uart;
     dc->reset = cadence_uart_reset;
-    dc->props = cadence_uart_properties;
+    device_class_set_props(dc, cadence_uart_properties);
   }
 
 static const TypeInfo cadence_uart_info = {
diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c
index 80dce07..c54a45c 100644
--- a/hw/char/debugcon.c
+++ b/hw/char/debugcon.c
@@ -125,7 +125,7 @@ static void debugcon_isa_class_initfn(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = debugcon_isa_realizefn;
-    dc->props = debugcon_isa_properties;
+    device_class_set_props(dc, debugcon_isa_properties);
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c
index 029f5bb..0dab6a7 100644
--- a/hw/char/digic-uart.c
+++ b/hw/char/digic-uart.c
@@ -181,7 +181,7 @@ static void digic_uart_class_init(ObjectClass *klass, void *data)
     dc->realize = digic_uart_realize;
     dc->reset = digic_uart_reset;
     dc->vmsd = &vmstate_digic_uart;
-    dc->props = digic_uart_properties;
+    device_class_set_props(dc, digic_uart_properties);
 }
 
 static const TypeInfo digic_uart_info = {
diff --git a/hw/char/escc.c b/hw/char/escc.c
index d6662dc..47175d9 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -1048,7 +1048,7 @@ static void escc_class_init(ObjectClass *klass, void *data)
     dc->reset = escc_reset;
     dc->realize = escc_realize;
     dc->vmsd = &vmstate_escc;
-    dc->props = escc_properties;
+    device_class_set_props(dc, escc_properties);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c
index 5438387..7536615 100644
--- a/hw/char/etraxfs_ser.c
+++ b/hw/char/etraxfs_ser.c
@@ -241,7 +241,7 @@ static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->reset = etraxfs_ser_reset;
-    dc->props = etraxfs_ser_properties;
+    device_class_set_props(dc, etraxfs_ser_properties);
     dc->realize = etraxfs_ser_realize;
 }
 
diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
index 571c324..a7ac2fb 100644
--- a/hw/char/exynos4210_uart.c
+++ b/hw/char/exynos4210_uart.c
@@ -662,7 +662,7 @@ static void exynos4210_uart_class_init(ObjectClass *klass, void *data)
 
     k->init = exynos4210_uart_init;
     dc->reset = exynos4210_uart_reset;
-    dc->props = exynos4210_uart_properties;
+    device_class_set_props(dc, exynos4210_uart_properties);
     dc->vmsd = &vmstate_exynos4210_uart;
 }
 
diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c
index db686e6..cfa33be 100644
--- a/hw/char/grlib_apbuart.c
+++ b/hw/char/grlib_apbuart.c
@@ -284,7 +284,7 @@ static void grlib_apbuart_class_init(ObjectClass *klass, void *data)
 
     k->init = grlib_apbuart_init;
     dc->reset = grlib_apbuart_reset;
-    dc->props = grlib_apbuart_properties;
+    device_class_set_props(dc, grlib_apbuart_properties);
 }
 
 static const TypeInfo grlib_apbuart_info = {
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index 99545fc..fb4c615 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -344,7 +344,7 @@ static void imx_serial_class_init(ObjectClass *klass, void *data)
     dc->reset = imx_serial_reset_at_boot;
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
     dc->desc = "i.MX series UART";
-    dc->props = imx_serial_properties;
+    device_class_set_props(dc, imx_serial_properties);
 }
 
 static const TypeInfo imx_serial_info = {
diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c
index 93929c2..38cf137 100644
--- a/hw/char/ipoctal232.c
+++ b/hw/char/ipoctal232.c
@@ -584,7 +584,7 @@ static void ipoctal_class_init(ObjectClass *klass, void *data)
 
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
     dc->desc    = "GE IP-Octal 232 8-channel RS-232 IndustryPack";
-    dc->props   = ipoctal_properties;
+    device_class_set_props(dc, ipoctal_properties);
     dc->vmsd    = &vmstate_ipoctal;
 }
 
diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c
index f8c1e0d..65db163 100644
--- a/hw/char/lm32_juart.c
+++ b/hw/char/lm32_juart.c
@@ -144,7 +144,7 @@ static void lm32_juart_class_init(ObjectClass *klass, void *data)
 
     dc->reset = juart_reset;
     dc->vmsd = &vmstate_lm32_juart;
-    dc->props = lm32_juart_properties;
+    device_class_set_props(dc, lm32_juart_properties);
     dc->realize = lm32_juart_realize;
 }
 
diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c
index 7f3597c..4b1ba40 100644
--- a/hw/char/lm32_uart.c
+++ b/hw/char/lm32_uart.c
@@ -290,7 +290,7 @@ static void lm32_uart_class_init(ObjectClass *klass, void *data)
 
     dc->reset = uart_reset;
     dc->vmsd = &vmstate_lm32_uart;
-    dc->props = lm32_uart_properties;
+    device_class_set_props(dc, lm32_uart_properties);
     dc->realize = lm32_uart_realize;
 }
 
diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c
index ae8e2f3..34e37c3 100644
--- a/hw/char/milkymist-uart.c
+++ b/hw/char/milkymist-uart.c
@@ -236,7 +236,7 @@ static void milkymist_uart_class_init(ObjectClass *klass, void *data)
     dc->realize = milkymist_uart_realize;
     dc->reset = milkymist_uart_reset;
     dc->vmsd = &vmstate_milkymist_uart;
-    dc->props = milkymist_uart_properties;
+    device_class_set_props(dc, milkymist_uart_properties);
 }
 
 static const TypeInfo milkymist_uart_info = {
diff --git a/hw/char/parallel.c b/hw/char/parallel.c
index f2d5666..151cf73 100644
--- a/hw/char/parallel.c
+++ b/hw/char/parallel.c
@@ -633,7 +633,7 @@ static void parallel_isa_class_initfn(ObjectClass *klass, void *data)
 
     dc->realize = parallel_isa_realizefn;
     dc->vmsd = &vmstate_parallel_isa;
-    dc->props = parallel_isa_properties;
+    device_class_set_props(dc, parallel_isa_properties);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 24ea973..6e7044f 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -338,7 +338,7 @@ static void pl011_class_init(ObjectClass *oc, void *data)
 
     dc->realize = pl011_realize;
     dc->vmsd = &vmstate_pl011;
-    dc->props = pl011_properties;
+    device_class_set_props(dc, pl011_properties);
 }
 
 static const TypeInfo pl011_arm_info = {
diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index 07d6ebd..e2e11d5 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -345,7 +345,7 @@ static void console_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     SCLPEventClass *ec = SCLP_EVENT_CLASS(klass);
 
-    dc->props = console_properties;
+    device_class_set_props(dc, console_properties);
     dc->reset = console_reset;
     dc->vmsd = &vmstate_sclplmconsole;
     ec->init = console_init;
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index b78f240..1b04cbb 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -261,7 +261,7 @@ static void console_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     SCLPEventClass *ec = SCLP_EVENT_CLASS(klass);
 
-    dc->props = console_properties;
+    device_class_set_props(dc, console_properties);
     dc->reset = console_reset;
     dc->vmsd = &vmstate_sclpconsole;
     ec->init = console_init;
diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c
index 54d3a12..8314bf3 100644
--- a/hw/char/serial-isa.c
+++ b/hw/char/serial-isa.c
@@ -103,7 +103,7 @@ static void serial_isa_class_initfn(ObjectClass *klass, void *data)
 
     dc->realize = serial_isa_realizefn;
     dc->vmsd = &vmstate_isa_serial;
-    dc->props = serial_isa_properties;
+    device_class_set_props(dc, serial_isa_properties);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c
index 303104d..1480699 100644
--- a/hw/char/serial-pci.c
+++ b/hw/char/serial-pci.c
@@ -211,7 +211,7 @@ static void serial_pci_class_initfn(ObjectClass *klass, void *data)
     pc->revision = 1;
     pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
     dc->vmsd = &vmstate_pci_serial;
-    dc->props = serial_pci_properties;
+    device_class_set_props(dc, serial_pci_properties);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
@@ -226,7 +226,7 @@ static void multi_2x_serial_pci_class_initfn(ObjectClass *klass, void *data)
     pc->revision = 1;
     pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
     dc->vmsd = &vmstate_pci_multi_serial;
-    dc->props = multi_2x_serial_pci_properties;
+    device_class_set_props(dc, multi_2x_serial_pci_properties);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
@@ -241,7 +241,7 @@ static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data)
     pc->revision = 1;
     pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
     dc->vmsd = &vmstate_pci_multi_serial;
-    dc->props = multi_4x_serial_pci_properties;
+    device_class_set_props(dc, multi_4x_serial_pci_properties);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
index 31822fe..c62bff3 100644
--- a/hw/char/spapr_vty.c
+++ b/hw/char/spapr_vty.c
@@ -171,7 +171,7 @@ static void spapr_vty_class_init(ObjectClass *klass, void *data)
     k->dt_type = "serial";
     k->dt_compatible = "hvterm1";
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-    dc->props = spapr_vty_properties;
+    device_class_set_props(dc, spapr_vty_properties);
     dc->vmsd = &vmstate_spapr_vty;
 }
 
diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c
index 59872e6..b994033 100644
--- a/hw/char/stm32f2xx_usart.c
+++ b/hw/char/stm32f2xx_usart.c
@@ -215,7 +215,7 @@ static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->reset = stm32f2xx_usart_reset;
-    dc->props = stm32f2xx_usart_properties;
+    device_class_set_props(dc, stm32f2xx_usart_properties);
     dc->realize = stm32f2xx_usart_realize;
 }
 
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index 776205b..2e2aa38 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -234,7 +234,7 @@ static void virtserialport_class_init(ObjectClass *klass, void *data)
     k->have_data = flush_buf;
     k->set_guest_connected = set_guest_connected;
     k->guest_writable = guest_writable;
-    dc->props = virtserialport_properties;
+    device_class_set_props(dc, virtserialport_properties);
 }
 
 static const TypeInfo virtserialport_info = {
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 7975c2c..3f43ef9 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -1091,7 +1091,7 @@ static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
     k->bus_type = TYPE_VIRTIO_SERIAL_BUS;
     k->realize = virtser_port_device_realize;
     k->unrealize = virtser_port_device_unrealize;
-    k->props = virtser_props;
+    device_class_set_props(k, virtser_props);
 }
 
 static const TypeInfo virtio_serial_port_type_info = {
@@ -1149,7 +1149,7 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data)
 
     QLIST_INIT(&vserdevices.devices);
 
-    dc->props = virtio_serial_properties;
+    device_class_set_props(dc, virtio_serial_properties);
     dc->vmsd = &vmstate_virtio_console;
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
     vdc->realize = virtio_serial_device_realize;
diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c
index 37d313b..1ea812c 100644
--- a/hw/char/xilinx_uartlite.c
+++ b/hw/char/xilinx_uartlite.c
@@ -232,7 +232,7 @@ static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
 
     dc->reset = xilinx_uartlite_reset;
     dc->realize = xilinx_uartlite_realize;
-    dc->props = xilinx_uartlite_properties;
+    device_class_set_props(dc, xilinx_uartlite_properties);
 }
 
 static const TypeInfo xilinx_uartlite_info = {
diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c
index 79ab6df..1918792 100644
--- a/hw/core/generic-loader.c
+++ b/hw/core/generic-loader.c
@@ -192,7 +192,7 @@ static void generic_loader_class_init(ObjectClass *klass, void *data)
      */
     dc->realize = generic_loader_realize;
     dc->unrealize = generic_loader_unrealize;
-    dc->props = generic_loader_props;
+    device_class_set_props(dc, generic_loader_props);
     dc->desc = "Generic Loader";
 }
 
diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c
index 1ac090d..b5f653c 100644
--- a/hw/core/or-irq.c
+++ b/hw/core/or-irq.c
@@ -86,7 +86,7 @@ static void or_irq_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->reset = or_irq_reset;
-    dc->props = or_irq_properties;
+    device_class_set_props(dc, or_irq_properties);
     dc->realize = or_irq_realize;
     dc->vmsd = &vmstate_or_irq;
 }
diff --git a/hw/core/platform-bus.c b/hw/core/platform-bus.c
index 329ac67..86df136 100644
--- a/hw/core/platform-bus.c
+++ b/hw/core/platform-bus.c
@@ -230,7 +230,7 @@ static void platform_bus_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = platform_bus_realize;
-    dc->props = platform_bus_properties;
+    device_class_set_props(dc, platform_bus_properties);
 }
 
 static const TypeInfo platform_bus_info = {
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 5783442..36ca5e7 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -848,6 +848,12 @@ void qdev_alias_all_properties(DeviceState *target, Object *source)
     } while (class != object_class_by_name(TYPE_DEVICE));
 }
 
+void device_class_set_props(DeviceClass *dc, Property *props)
+{
+    assert(!dc->props);
+    dc->props = props;
+}
+
 static int qdev_add_hotpluggable_device(Object *obj, void *opaque)
 {
     GSList **list = opaque;
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index bc05152..55d3dae 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -138,7 +138,7 @@ static void a15mp_priv_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = a15mp_priv_realize;
-    dc->props = a15mp_priv_properties;
+    device_class_set_props(dc, a15mp_priv_properties);
     /* We currently have no savable state */
 }
 
diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
index f17f292..422effb 100644
--- a/hw/cpu/a9mpcore.c
+++ b/hw/cpu/a9mpcore.c
@@ -174,7 +174,7 @@ static void a9mp_priv_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = a9mp_priv_realize;
-    dc->props = a9mp_priv_properties;
+    device_class_set_props(dc, a9mp_priv_properties);
 }
 
 static const TypeInfo a9mp_priv_info = {
diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c
index eb24465..62b919d 100644
--- a/hw/cpu/arm11mpcore.c
+++ b/hw/cpu/arm11mpcore.c
@@ -155,7 +155,7 @@ static void mpcore_priv_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = mpcore_priv_realize;
-    dc->props = mpcore_priv_properties;
+    device_class_set_props(dc, mpcore_priv_properties);
 }
 
 static const TypeInfo mpcore_priv_info = {
diff --git a/hw/cpu/realview_mpcore.c b/hw/cpu/realview_mpcore.c
index 39d4ebe..12d2f09 100644
--- a/hw/cpu/realview_mpcore.c
+++ b/hw/cpu/realview_mpcore.c
@@ -122,7 +122,7 @@ static void mpcore_rirq_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = realview_mpcore_realize;
-    dc->props = mpcore_rirq_properties;
+    device_class_set_props(dc, mpcore_rirq_properties);
 }
 
 static const TypeInfo mpcore_rirq_info = {
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
index 7eab927..3d38df0 100644
--- a/hw/display/bcm2835_fb.c
+++ b/hw/display/bcm2835_fb.c
@@ -404,7 +404,7 @@ static void bcm2835_fb_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = bcm2835_fb_props;
+    device_class_set_props(dc, bcm2835_fb_props);
     dc->realize = bcm2835_fb_realize;
     dc->reset = bcm2835_fb_reset;
     dc->vmsd = &vmstate_bcm2835_fb;
diff --git a/hw/display/cg3.c b/hw/display/cg3.c
index 1174220..b6d86b7 100644
--- a/hw/display/cg3.c
+++ b/hw/display/cg3.c
@@ -382,7 +382,7 @@ static void cg3_class_init(ObjectClass *klass, void *data)
     dc->realize = cg3_realizefn;
     dc->reset = cg3_reset;
     dc->vmsd = &vmstate_cg3;
-    dc->props = cg3_properties;
+    device_class_set_props(dc, cg3_properties);
 }
 
 static const TypeInfo cg3_info = {
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 3d712d5..53e7b45 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -2995,7 +2995,7 @@ static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data)
 
     dc->vmsd  = &vmstate_cirrus_vga;
     dc->realize = isa_cirrus_vga_realizefn;
-    dc->props = isa_cirrus_vga_properties;
+    device_class_set_props(dc, isa_cirrus_vga_properties);
     set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
 }
 
@@ -3071,7 +3071,7 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
     dc->desc = "Cirrus CLGD 54xx VGA";
     dc->vmsd = &vmstate_pci_cirrus_vga;
-    dc->props = pci_vga_cirrus_properties;
+    device_class_set_props(dc, pci_vga_cirrus_properties);
     dc->hotpluggable = false;
 }
 
diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c
index 70ef2c7..a230b7f 100644
--- a/hw/display/g364fb.c
+++ b/hw/display/g364fb.c
@@ -541,7 +541,7 @@ static void g364fb_sysbus_class_init(ObjectClass *klass, void *data)
     dc->desc = "G364 framebuffer";
     dc->reset = g364fb_sysbus_reset;
     dc->vmsd = &vmstate_g364fb;
-    dc->props = g364fb_sysbus_properties;
+    device_class_set_props(dc, g364fb_sysbus_properties);
 }
 
 static const TypeInfo g364fb_sysbus_info = {
diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c
index 177fdac..730615d 100644
--- a/hw/display/milkymist-vgafb.c
+++ b/hw/display/milkymist-vgafb.c
@@ -338,7 +338,7 @@ static void milkymist_vgafb_class_init(ObjectClass *klass, void *data)
 
     dc->reset = milkymist_vgafb_reset;
     dc->vmsd = &vmstate_milkymist_vgafb;
-    dc->props = milkymist_vgafb_properties;
+    device_class_set_props(dc, milkymist_vgafb_properties);
     dc->realize = milkymist_vgafb_realize;
 }
 
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 0e2682d..aa2f4a1 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -2339,7 +2339,7 @@ static void qxl_pci_class_init(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
     dc->reset = qxl_reset_handler;
     dc->vmsd = &qxl_vmstate;
-    dc->props = qxl_properties;
+    device_class_set_props(dc, qxl_properties);
 }
 
 static const TypeInfo qxl_pci_type_info = {
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
index 8e26aae..a429cdf 100644
--- a/hw/display/tcx.c
+++ b/hw/display/tcx.c
@@ -1087,7 +1087,7 @@ static void tcx_class_init(ObjectClass *klass, void *data)
     dc->realize = tcx_realizefn;
     dc->reset = tcx_reset;
     dc->vmsd = &vmstate_tcx;
-    dc->props = tcx_properties;
+    device_class_set_props(dc, tcx_properties);
 }
 
 static const TypeInfo tcx_info = {
diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c
index 1af9556..cdc3290 100644
--- a/hw/display/vga-isa.c
+++ b/hw/display/vga-isa.c
@@ -91,7 +91,7 @@ static void vga_isa_class_initfn(ObjectClass *klass, void *data)
     dc->realize = vga_isa_realizefn;
     dc->reset = vga_isa_reset;
     dc->vmsd = &vmstate_vga_common;
-    dc->props = vga_isa_properties;
+    device_class_set_props(dc, vga_isa_properties);
     set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
 }
 
diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
index ac9a764..be26772 100644
--- a/hw/display/vga-pci.c
+++ b/hw/display/vga-pci.c
@@ -348,7 +348,7 @@ static void vga_class_init(ObjectClass *klass, void *data)
     k->realize = pci_std_vga_realize;
     k->romfile = "vgabios-stdvga.bin";
     k->class_id = PCI_CLASS_DISPLAY_VGA;
-    dc->props = vga_pci_properties;
+    device_class_set_props(dc, vga_pci_properties);
     dc->hotpluggable = false;
 }
 
@@ -359,7 +359,7 @@ static void secondary_class_init(ObjectClass *klass, void *data)
 
     k->realize = pci_secondary_vga_realize;
     k->class_id = PCI_CLASS_DISPLAY_OTHER;
-    dc->props = secondary_pci_properties;
+    device_class_set_props(dc, secondary_pci_properties);
     dc->reset = pci_secondary_vga_reset;
 }
 
diff --git a/hw/display/virtio-gpu-pci.c b/hw/display/virtio-gpu-pci.c
index ef92c4a..6122fc2 100644
--- a/hw/display/virtio-gpu-pci.c
+++ b/hw/display/virtio-gpu-pci.c
@@ -47,7 +47,7 @@ static void virtio_gpu_pci_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 
     set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
-    dc->props = virtio_gpu_pci_properties;
+    device_class_set_props(dc, virtio_gpu_pci_properties);
     dc->hotpluggable = false;
     k->realize = virtio_gpu_pci_realize;
     pcidev_k->class_id = PCI_CLASS_DISPLAY_OTHER;
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 60bce94..fff8674 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1263,7 +1263,7 @@ static void virtio_gpu_class_init(ObjectClass *klass, void *data)
 
     vdc->reset = virtio_gpu_reset;
 
-    dc->props = virtio_gpu_properties;
+    device_class_set_props(dc, virtio_gpu_properties);
     dc->vmsd = &vmstate_virtio_gpu;
 }
 
diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
index f9b017d..f370a2a 100644
--- a/hw/display/virtio-vga.c
+++ b/hw/display/virtio-vga.c
@@ -186,7 +186,7 @@ static void virtio_vga_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 
     set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
-    dc->props = virtio_vga_properties;
+    device_class_set_props(dc, virtio_vga_properties);
     dc->reset = virtio_vga_reset;
     dc->vmsd = &vmstate_virtio_vga;
     dc->hotpluggable = false;
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 6599cf0..2463cf4 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -1356,7 +1356,7 @@ static void vmsvga_class_init(ObjectClass *klass, void *data)
     k->subsystem_id = SVGA_PCI_DEVICE_ID;
     dc->reset = vmsvga_reset;
     dc->vmsd = &vmstate_vmware_vga;
-    dc->props = vga_vmware_properties;
+    device_class_set_props(dc, vga_vmware_properties);
     dc->hotpluggable = false;
     set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
 }
diff --git a/hw/dma/i82374.c b/hw/dma/i82374.c
index 6c0f975..0cbc61b 100644
--- a/hw/dma/i82374.c
+++ b/hw/dma/i82374.c
@@ -138,7 +138,7 @@ static void i82374_class_init(ObjectClass *klass, void *data)
     
     dc->realize = i82374_realize;
     dc->vmsd = &vmstate_i82374;
-    dc->props = i82374_properties;
+    device_class_set_props(dc, i82374_properties);
 }
 
 static const TypeInfo i82374_info = {
diff --git a/hw/dma/i8257.c b/hw/dma/i8257.c
index 8bd82e8..15909a8 100644
--- a/hw/dma/i8257.c
+++ b/hw/dma/i8257.c
@@ -590,7 +590,7 @@ static void i8257_class_init(ObjectClass *klass, void *data)
     dc->realize = i8257_realize;
     dc->reset = i8257_reset;
     dc->vmsd = &vmstate_i8257;
-    dc->props = i8257_properties;
+    device_class_set_props(dc, i8257_properties);
 
     idc->get_transfer_mode = i8257_dma_get_transfer_mode;
     idc->has_autoinitialization = i8257_dma_has_autoinitialization;
diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c
index c0bd9fe..3902df2 100644
--- a/hw/dma/pl330.c
+++ b/hw/dma/pl330.c
@@ -1650,7 +1650,7 @@ static void pl330_class_init(ObjectClass *klass, void *data)
 
     dc->realize = pl330_realize;
     dc->reset = pl330_reset;
-    dc->props = pl330_properties;
+    device_class_set_props(dc, pl330_properties);
     dc->vmsd = &vmstate_pl330;
 }
 
diff --git a/hw/dma/pxa2xx_dma.c b/hw/dma/pxa2xx_dma.c
index 634a432..99569a6 100644
--- a/hw/dma/pxa2xx_dma.c
+++ b/hw/dma/pxa2xx_dma.c
@@ -562,7 +562,7 @@ static void pxa2xx_dma_class_init(ObjectClass *klass, void *data)
 
     dc->desc = "PXA2xx DMA controller";
     dc->vmsd = &vmstate_pxa2xx_dma;
-    dc->props = pxa2xx_dma_properties;
+    device_class_set_props(dc, pxa2xx_dma_properties);
     dc->realize = pxa2xx_dma_realize;
 }
 
diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c
index 9d545e4..056b31c 100644
--- a/hw/dma/sparc32_dma.c
+++ b/hw/dma/sparc32_dma.c
@@ -303,7 +303,7 @@ static void sparc32_dma_class_init(ObjectClass *klass, void *data)
     k->init = sparc32_dma_init1;
     dc->reset = dma_reset;
     dc->vmsd = &vmstate_dma;
-    dc->props = sparc32_dma_properties;
+    device_class_set_props(dc, sparc32_dma_properties);
     /* Reason: pointer property "iommu_opaque" */
     dc->cannot_instantiate_with_device_add_yet = true;
 }
diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c
index b3cbc54..0c0adfd 100644
--- a/hw/dma/sun4m_iommu.c
+++ b/hw/dma/sun4m_iommu.c
@@ -375,7 +375,7 @@ static void iommu_class_init(ObjectClass *klass, void *data)
     k->init = iommu_init1;
     dc->reset = iommu_reset;
     dc->vmsd = &vmstate_iommu;
-    dc->props = iommu_properties;
+    device_class_set_props(dc, iommu_properties);
 }
 
 static const TypeInfo iommu_info = {
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index 6065689..38a2ba6 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -604,7 +604,7 @@ static void axidma_class_init(ObjectClass *klass, void *data)
 
     dc->realize = xilinx_axidma_realize,
     dc->reset = xilinx_axidma_reset;
-    dc->props = axidma_properties;
+    device_class_set_props(dc, axidma_properties);
 }
 
 static StreamSlaveClass xilinx_axidma_data_stream_class = {
diff --git a/hw/gpio/imx_gpio.c b/hw/gpio/imx_gpio.c
index f3574aa..d1325e6 100644
--- a/hw/gpio/imx_gpio.c
+++ b/hw/gpio/imx_gpio.c
@@ -331,7 +331,7 @@ static void imx_gpio_class_init(ObjectClass *klass, void *data)
 
     dc->realize = imx_gpio_realize;
     dc->reset = imx_gpio_reset;
-    dc->props = imx_gpio_properties;
+    device_class_set_props(dc, imx_gpio_properties);
     dc->vmsd = &vmstate_imx_gpio;
     dc->desc = "i.MX GPIO controller";
 }
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
index dabef4a..66fbecb 100644
--- a/hw/gpio/omap_gpio.c
+++ b/hw/gpio/omap_gpio.c
@@ -771,7 +771,7 @@ static void omap_gpio_class_init(ObjectClass *klass, void *data)
 
     dc->realize = omap_gpio_realize;
     dc->reset = omap_gpif_reset;
-    dc->props = omap_gpio_properties;
+    device_class_set_props(dc, omap_gpio_properties);
     /* Reason: pointer property "clk" */
     dc->cannot_instantiate_with_device_add_yet = true;
 }
@@ -802,7 +802,7 @@ static void omap2_gpio_class_init(ObjectClass *klass, void *data)
 
     dc->realize = omap2_gpio_realize;
     dc->reset = omap2_gpif_reset;
-    dc->props = omap2_gpio_properties;
+    device_class_set_props(dc, omap2_gpio_properties);
     /* Reason: pointer properties "iclk", "fclk0", ..., "fclk5" */
     dc->cannot_instantiate_with_device_add_yet = true;
 }
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
index abd4c4c..bb2c12a 100644
--- a/hw/i2c/core.c
+++ b/hw/i2c/core.c
@@ -279,7 +279,7 @@ static void i2c_slave_class_init(ObjectClass *klass, void *data)
     k->init = i2c_slave_qdev_init;
     set_bit(DEVICE_CATEGORY_MISC, k->categories);
     k->bus_type = TYPE_I2C_BUS;
-    k->props = i2c_props;
+    device_class_set_props(k, i2c_props);
 }
 
 static const TypeInfo i2c_slave_type_info = {
diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c
index f7c92ea..2031009 100644
--- a/hw/i2c/omap_i2c.c
+++ b/hw/i2c/omap_i2c.c
@@ -488,7 +488,7 @@ static void omap_i2c_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = omap_i2c_properties;
+    device_class_set_props(dc, omap_i2c_properties);
     dc->reset = omap_i2c_reset;
     /* Reason: pointer properties "iclk", "fclk" */
     dc->cannot_instantiate_with_device_add_yet = true;
diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c
index 5b7bd89..bbb5294 100644
--- a/hw/i2c/smbus_eeprom.c
+++ b/hw/i2c/smbus_eeprom.c
@@ -121,7 +121,7 @@ static void smbus_eeprom_class_initfn(ObjectClass *klass, void *data)
     sc->receive_byte = eeprom_receive_byte;
     sc->write_data = eeprom_write_data;
     sc->read_data = eeprom_read_data;
-    dc->props = smbus_eeprom_properties;
+    device_class_set_props(dc, smbus_eeprom_properties);
     /* Reason: pointer property "data" */
     dc->cannot_instantiate_with_device_add_yet = true;
 }
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 1655a65..c2e119f 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2542,7 +2542,7 @@ static void vtd_class_init(ObjectClass *klass, void *data)
 
     dc->reset = vtd_reset;
     dc->vmsd = &vtd_vmstate;
-    dc->props = vtd_properties;
+    device_class_set_props(dc, vtd_properties);
     dc->hotpluggable = false;
     x86_class->realize = vtd_realize;
     x86_class->int_remap = vtd_int_remap;
diff --git a/hw/i386/kvm/i8254.c b/hw/i386/kvm/i8254.c
index 521a584..1586b8a 100644
--- a/hw/i386/kvm/i8254.c
+++ b/hw/i386/kvm/i8254.c
@@ -320,7 +320,7 @@ static void kvm_pit_class_init(ObjectClass *klass, void *data)
     k->set_channel_gate = kvm_pit_set_gate;
     k->get_channel_info = kvm_pit_get_channel_info;
     dc->reset = kvm_pit_reset;
-    dc->props = kvm_pit_properties;
+    device_class_set_props(dc, kvm_pit_properties);
 }
 
 static const TypeInfo kvm_pit_info = {
diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c
index 8eb2c7a..e137d10 100644
--- a/hw/i386/kvm/ioapic.c
+++ b/hw/i386/kvm/ioapic.c
@@ -161,7 +161,7 @@ static void kvm_ioapic_class_init(ObjectClass *klass, void *data)
     k->pre_save  = kvm_ioapic_get;
     k->post_load = kvm_ioapic_put;
     dc->reset    = kvm_ioapic_reset;
-    dc->props    = kvm_ioapic_properties;
+    device_class_set_props(dc, kvm_ioapic_properties);
 }
 
 static const TypeInfo kvm_ioapic_info = {
diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c
index 8238fbc..e6596d3 100644
--- a/hw/i386/kvm/pci-assign.c
+++ b/hw/i386/kvm/pci-assign.c
@@ -1861,7 +1861,7 @@ static void assign_class_init(ObjectClass *klass, void *data)
     k->exit         = assigned_exitfn;
     k->config_read  = assigned_dev_pci_read_config;
     k->config_write = assigned_dev_pci_write_config;
-    dc->props       = assigned_dev_properties;
+    device_class_set_props(dc, assigned_dev_properties);
     dc->vmsd        = &vmstate_assigned_device;
     dc->reset       = reset_assigned_device;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
diff --git a/hw/i386/xen/xen_pvdevice.c b/hw/i386/xen/xen_pvdevice.c
index c093b34..1a6189f 100644
--- a/hw/i386/xen/xen_pvdevice.c
+++ b/hw/i386/xen/xen_pvdevice.c
@@ -119,7 +119,7 @@ static void xen_pv_class_init(ObjectClass *klass, void *data)
     k->realize = xen_pv_realize;
     k->class_id = PCI_CLASS_SYSTEM_OTHER;
     dc->desc = "Xen PV Device";
-    dc->props = xen_pv_props;
+    device_class_set_props(dc, xen_pv_props);
 }
 
 static const TypeInfo xen_pv_type_info = {
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 3c19bda..6956abd 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1706,7 +1706,7 @@ static void sysbus_ahci_class_init(ObjectClass *klass, void *data)
 
     dc->realize = sysbus_ahci_realize;
     dc->vmsd = &vmstate_sysbus_ahci;
-    dc->props = sysbus_ahci_properties;
+    device_class_set_props(dc, sysbus_ahci_properties);
     dc->reset = sysbus_ahci_reset;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 9ebb8d4..029906d 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -417,7 +417,7 @@ static void cmd646_ide_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_STORAGE_IDE;
     k->config_read = cmd646_pci_config_read;
     k->config_write = cmd646_pci_config_write;
-    dc->props = cmd646_ide_properties;
+    device_class_set_props(dc, cmd646_ide_properties);
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
 
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index 40213d6..66f7c6b 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -116,7 +116,7 @@ static void isa_ide_class_initfn(ObjectClass *klass, void *data)
     dc->realize = isa_ide_realizefn;
     dc->fw_name = "ide";
     dc->reset = isa_ide_reset;
-    dc->props = isa_ide_properties;
+    device_class_set_props(dc, isa_ide_properties);
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
 
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index 6f12f45..1f48be8 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -152,7 +152,7 @@ static void mmio_ide_class_init(ObjectClass *oc, void *data)
 
     dc->realize = mmio_ide_realizefn;
     dc->reset = mmio_ide_reset;
-    dc->props = mmio_ide_properties;
+    device_class_set_props(dc, mmio_ide_properties);
     dc->vmsd = &vmstate_ide_mmio;
 }
 
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index dbaa75c..430b535 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -305,7 +305,7 @@ static void ide_hd_class_init(ObjectClass *klass, void *data)
     k->init = ide_hd_initfn;
     dc->fw_name = "drive";
     dc->desc = "virtual IDE disk";
-    dc->props = ide_hd_properties;
+    device_class_set_props(dc, ide_hd_properties);
 }
 
 static const TypeInfo ide_hd_info = {
@@ -327,7 +327,7 @@ static void ide_cd_class_init(ObjectClass *klass, void *data)
     k->init = ide_cd_initfn;
     dc->fw_name = "drive";
     dc->desc = "virtual IDE CD-ROM";
-    dc->props = ide_cd_properties;
+    device_class_set_props(dc, ide_cd_properties);
 }
 
 static const TypeInfo ide_cd_info = {
@@ -349,7 +349,7 @@ static void ide_drive_class_init(ObjectClass *klass, void *data)
     k->init = ide_drive_initfn;
     dc->fw_name = "drive";
     dc->desc = "virtual IDE disk or CD-ROM (legacy)";
-    dc->props = ide_drive_properties;
+    device_class_set_props(dc, ide_drive_properties);
 }
 
 static const TypeInfo ide_drive_info = {
@@ -366,7 +366,7 @@ static void ide_device_class_init(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
     k->bus_type = TYPE_IDE_BUS;
     k->unrealize = idebus_unrealize;
-    k->props = ide_props;
+    device_class_set_props(k, ide_props);
 }
 
 static const TypeInfo ide_device_type_info = {
diff --git a/hw/input/milkymist-softusb.c b/hw/input/milkymist-softusb.c
index 40dfca1..7f577d3 100644
--- a/hw/input/milkymist-softusb.c
+++ b/hw/input/milkymist-softusb.c
@@ -301,7 +301,7 @@ static void milkymist_softusb_class_init(ObjectClass *klass, void *data)
     k->init = milkymist_softusb_init;
     dc->reset = milkymist_softusb_reset;
     dc->vmsd = &vmstate_milkymist_softusb;
-    dc->props = milkymist_softusb_properties;
+    device_class_set_props(dc, milkymist_softusb_properties);
 }
 
 static const TypeInfo milkymist_softusb_info = {
diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c
index 3ee0c18..9ded80f 100644
--- a/hw/input/virtio-input-hid.c
+++ b/hw/input/virtio-input-hid.c
@@ -327,7 +327,7 @@ static void virtio_input_hid_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
 
-    dc->props          = virtio_input_hid_properties;
+    device_class_set_props(dc, virtio_input_hid_properties);
     vic->realize       = virtio_input_hid_realize;
     vic->unrealize     = virtio_input_hid_unrealize;
     vic->change_active = virtio_input_hid_change_active;
diff --git a/hw/input/virtio-input-host.c b/hw/input/virtio-input-host.c
index cb79e80..e122a68 100644
--- a/hw/input/virtio-input-host.c
+++ b/hw/input/virtio-input-host.c
@@ -226,7 +226,7 @@ static void virtio_input_host_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->vmsd           = &vmstate_virtio_input_host;
-    dc->props          = virtio_input_host_properties;
+    device_class_set_props(dc, virtio_input_host_properties);
     vic->realize       = virtio_input_host_realize;
     vic->unrealize     = virtio_input_host_unrealize;
     vic->handle_status = virtio_input_host_handle_status;
diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c
index b678ee9..039457e 100644
--- a/hw/input/virtio-input.c
+++ b/hw/input/virtio-input.c
@@ -310,7 +310,7 @@ static void virtio_input_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
 
-    dc->props          = virtio_input_properties;
+    device_class_set_props(dc, virtio_input_properties);
     dc->vmsd           = &vmstate_virtio_input;
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
     vdc->realize      = virtio_input_device_realize;
diff --git a/hw/input/vmmouse.c b/hw/input/vmmouse.c
index 6d15a88..5778a8b 100644
--- a/hw/input/vmmouse.c
+++ b/hw/input/vmmouse.c
@@ -284,7 +284,7 @@ static void vmmouse_class_initfn(ObjectClass *klass, void *data)
     dc->realize = vmmouse_realizefn;
     dc->reset = vmmouse_reset;
     dc->vmsd = &vmstate_vmmouse;
-    dc->props = vmmouse_properties;
+    device_class_set_props(dc, vmmouse_properties);
     /* Reason: pointer property "ps2_mouse" */
     dc->cannot_instantiate_with_device_add_yet = true;
 }
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index d78c885..113b9e1 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -491,7 +491,7 @@ static void apic_common_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->reset = apic_reset_common;
-    dc->props = apic_properties_common;
+    device_class_set_props(dc, apic_properties_common);
     dc->realize = apic_common_realize;
     dc->unrealize = apic_common_unrealize;
     /*
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
index 0a1f56a..b48a588 100644
--- a/hw/intc/arm_gic_common.c
+++ b/hw/intc/arm_gic_common.c
@@ -264,7 +264,7 @@ static void arm_gic_common_class_init(ObjectClass *klass, void *data)
 
     dc->reset = arm_gic_common_reset;
     dc->realize = arm_gic_common_realize;
-    dc->props = arm_gic_common_properties;
+    device_class_set_props(dc, arm_gic_common_properties);
     dc->vmsd = &vmstate_gic;
     albifc->arm_linux_init = arm_gic_common_linux_init;
 }
diff --git a/hw/intc/arm_gicv2m.c b/hw/intc/arm_gicv2m.c
index 3922fbc..3d99e73 100644
--- a/hw/intc/arm_gicv2m.c
+++ b/hw/intc/arm_gicv2m.c
@@ -176,7 +176,7 @@ static void gicv2m_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = gicv2m_properties;
+    device_class_set_props(dc, gicv2m_properties);
     dc->realize = gicv2m_realize;
 }
 
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 0f8c4b8..67cc7e3 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -325,7 +325,7 @@ static void arm_gicv3_common_class_init(ObjectClass *klass, void *data)
 
     dc->reset = arm_gicv3_common_reset;
     dc->realize = arm_gicv3_common_realize;
-    dc->props = arm_gicv3_common_properties;
+    device_class_set_props(dc, arm_gicv3_common_properties);
     dc->vmsd = &vmstate_gicv3;
     albifc->arm_linux_init = arm_gic_common_linux_init;
 }
diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c
index 64a6f4b..00f9268 100644
--- a/hw/intc/etraxfs_pic.c
+++ b/hw/intc/etraxfs_pic.c
@@ -170,7 +170,7 @@ static void etraxfs_pic_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = etraxfs_pic_properties;
+    device_class_set_props(dc, etraxfs_pic_properties);
     /*
      * Note: pointer property "interrupt_vector" may remain null, thus
      * no need for dc->cannot_instantiate_with_device_add_yet = true;
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
index f19a706..8b2bb68 100644
--- a/hw/intc/exynos4210_combiner.c
+++ b/hw/intc/exynos4210_combiner.c
@@ -437,7 +437,7 @@ static void exynos4210_combiner_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->reset = exynos4210_combiner_reset;
-    dc->props = exynos4210_combiner_properties;
+    device_class_set_props(dc, exynos4210_combiner_properties);
     dc->vmsd = &vmstate_exynos4210_combiner;
 }
 
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
index fd7a8f3..1135335 100644
--- a/hw/intc/exynos4210_gic.c
+++ b/hw/intc/exynos4210_gic.c
@@ -346,7 +346,7 @@ static void exynos4210_gic_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = exynos4210_gic_properties;
+    device_class_set_props(dc, exynos4210_gic_properties);
 }
 
 static const TypeInfo exynos4210_gic_info = {
@@ -453,7 +453,7 @@ static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data)
 
     dc->reset = exynos4210_irq_gate_reset;
     dc->vmsd = &vmstate_exynos4210_irq_gate;
-    dc->props = exynos4210_irq_gate_properties;
+    device_class_set_props(dc, exynos4210_irq_gate_properties);
     dc->realize = exynos4210_irq_gate_realize;
 }
 
diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c
index ac7e63f..929dc06 100644
--- a/hw/intc/grlib_irqmp.c
+++ b/hw/intc/grlib_irqmp.c
@@ -358,7 +358,7 @@ static void grlib_irqmp_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->reset = grlib_irqmp_reset;
-    dc->props = grlib_irqmp_properties;
+    device_class_set_props(dc, grlib_irqmp_properties);
     /* Reason: pointer properties "set_pil_in", "set_pil_in_opaque" */
     dc->cannot_instantiate_with_device_add_yet = true;
     dc->realize = grlib_irqmp_realize;
diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c
index d9a5e8b..846fadb 100644
--- a/hw/intc/i8259_common.c
+++ b/hw/intc/i8259_common.c
@@ -136,7 +136,7 @@ static void pic_common_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->vmsd = &vmstate_pic_common;
-    dc->props = pic_properties_common;
+    device_class_set_props(dc, pic_properties_common);
     dc->realize = pic_common_realize;
     /*
      * Reason: unlike ordinary ISA devices, the PICs need additional
diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c
index fd9208f..0112066 100644
--- a/hw/intc/ioapic.c
+++ b/hw/intc/ioapic.c
@@ -427,7 +427,7 @@ static void ioapic_class_init(ObjectClass *klass, void *data)
 
     k->realize = ioapic_realize;
     dc->reset = ioapic_reset_common;
-    dc->props = ioapic_properties;
+    device_class_set_props(dc, ioapic_properties);
 }
 
 static const TypeInfo ioapic_info = {
diff --git a/hw/intc/mips_gic.c b/hw/intc/mips_gic.c
index 6e25773..cdd4d74 100644
--- a/hw/intc/mips_gic.c
+++ b/hw/intc/mips_gic.c
@@ -440,7 +440,7 @@ static void mips_gic_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = mips_gic_properties;
+    device_class_set_props(dc, mips_gic_properties);
     dc->realize = mips_gic_realize;
 }
 
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
index 877be67..8f357c1 100644
--- a/hw/intc/omap_intc.c
+++ b/hw/intc/omap_intc.c
@@ -399,7 +399,7 @@ static void omap_intc_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->reset = omap_inth_reset;
-    dc->props = omap_intc_properties;
+    device_class_set_props(dc, omap_intc_properties);
     /* Reason: pointer property "clk" */
     dc->cannot_instantiate_with_device_add_yet = true;
     dc->realize = omap_intc_realize;
@@ -654,7 +654,7 @@ static void omap2_intc_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->reset = omap_inth_reset;
-    dc->props = omap2_intc_properties;
+    device_class_set_props(dc, omap2_intc_properties);
     /* Reason: pointer property "iclk", "fclk" */
     dc->cannot_instantiate_with_device_add_yet = true;
     dc->realize = omap2_intc_realize;
diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
index 4349e45..1262b89 100644
--- a/hw/intc/openpic.c
+++ b/hw/intc/openpic.c
@@ -1643,7 +1643,7 @@ static void openpic_class_init(ObjectClass *oc, void *data)
     DeviceClass *dc = DEVICE_CLASS(oc);
 
     dc->realize = openpic_realize;
-    dc->props = openpic_properties;
+    device_class_set_props(dc, openpic_properties);
     dc->reset = openpic_reset;
     dc->vmsd = &vmstate_openpic;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c
index 0518e01..1d178d7 100644
--- a/hw/intc/openpic_kvm.c
+++ b/hw/intc/openpic_kvm.c
@@ -277,7 +277,7 @@ static void kvm_openpic_class_init(ObjectClass *oc, void *data)
     DeviceClass *dc = DEVICE_CLASS(oc);
 
     dc->realize = kvm_openpic_realize;
-    dc->props = kvm_openpic_properties;
+    device_class_set_props(dc, kvm_openpic_properties);
     dc->reset = kvm_openpic_reset;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c
index 9d8139b..8a5b64c 100644
--- a/hw/intc/xilinx_intc.c
+++ b/hw/intc/xilinx_intc.c
@@ -183,7 +183,7 @@ static void xilinx_intc_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = xilinx_intc_properties;
+    device_class_set_props(dc, xilinx_intc_properties);
 }
 
 static const TypeInfo xilinx_intc_info = {
diff --git a/hw/ipack/ipack.c b/hw/ipack/ipack.c
index 6021e6d..a052d97 100644
--- a/hw/ipack/ipack.c
+++ b/hw/ipack/ipack.c
@@ -84,7 +84,7 @@ static void ipack_device_class_init(ObjectClass *klass, void *data)
     k->bus_type = TYPE_IPACK_BUS;
     k->realize = ipack_device_realize;
     k->unrealize = ipack_device_unrealize;
-    k->props = ipack_device_props;
+    device_class_set_props(k, ipack_device_props);
 }
 
 const VMStateDescription vmstate_ipack_device = {
diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
index f09f217..971c0d7 100644
--- a/hw/ipmi/ipmi.c
+++ b/hw/ipmi/ipmi.c
@@ -110,7 +110,7 @@ static void bmc_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
 
-    dc->props = ipmi_bmc_properties;
+    device_class_set_props(dc, ipmi_bmc_properties);
 }
 
 static TypeInfo ipmi_bmc_type_info = {
diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c
index 4b310e5..3a4e61a 100644
--- a/hw/ipmi/ipmi_bmc_extern.c
+++ b/hw/ipmi/ipmi_bmc_extern.c
@@ -513,7 +513,7 @@ static void ipmi_bmc_extern_class_init(ObjectClass *oc, void *data)
     bk->handle_command = ipmi_bmc_extern_handle_command;
     bk->handle_reset = ipmi_bmc_extern_handle_reset;
     dc->realize = ipmi_bmc_extern_realize;
-    dc->props = ipmi_bmc_extern_properties;
+    device_class_set_props(dc, ipmi_bmc_extern_properties);
 }
 
 static const TypeInfo ipmi_bmc_extern_type = {
diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c
index f036617..d133ed4 100644
--- a/hw/ipmi/isa_ipmi_bt.c
+++ b/hw/ipmi/isa_ipmi_bt.c
@@ -511,7 +511,7 @@ static void isa_ipmi_bt_class_init(ObjectClass *oc, void *data)
     IPMIInterfaceClass *iic = IPMI_INTERFACE_CLASS(oc);
 
     dc->realize = isa_ipmi_bt_realize;
-    dc->props = ipmi_isa_properties;
+    device_class_set_props(dc, ipmi_isa_properties);
 
     iic->get_backend_data = isa_ipmi_bt_get_backend_data;
     ipmi_bt_class_init(iic);
diff --git a/hw/ipmi/isa_ipmi_kcs.c b/hw/ipmi/isa_ipmi_kcs.c
index 9a38f8a..90c7532 100644
--- a/hw/ipmi/isa_ipmi_kcs.c
+++ b/hw/ipmi/isa_ipmi_kcs.c
@@ -475,7 +475,7 @@ static void isa_ipmi_kcs_class_init(ObjectClass *oc, void *data)
     IPMIInterfaceClass *iic = IPMI_INTERFACE_CLASS(oc);
 
     dc->realize = ipmi_isa_realize;
-    dc->props = ipmi_isa_properties;
+    device_class_set_props(dc, ipmi_isa_properties);
 
     iic->get_backend_data = isa_ipmi_kcs_get_backend_data;
     ipmi_kcs_class_init(iic);
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index 10d1ee8..c7ed99a 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -710,7 +710,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data)
     dc->reset = ich9_lpc_reset;
     k->realize = ich9_lpc_realize;
     dc->vmsd = &vmstate_ich9_lpc;
-    dc->props = ich9_lpc_properties;
+    device_class_set_props(dc, ich9_lpc_properties);
     k->config_write = ich9_lpc_config_write;
     dc->desc = "ICH9 LPC bridge";
     k->vendor_id = PCI_VENDOR_ID_INTEL;
diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c
index b1c1a0a..ec0effc 100644
--- a/hw/isa/pc87312.c
+++ b/hw/isa/pc87312.c
@@ -385,7 +385,7 @@ static void pc87312_class_init(ObjectClass *klass, void *data)
     dc->realize = pc87312_realize;
     dc->reset = pc87312_reset;
     dc->vmsd = &vmstate_pc87312;
-    dc->props = pc87312_properties;
+    device_class_set_props(dc, pc87312_properties);
 }
 
 static const TypeInfo pc87312_type_info = {
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index 41d5254..ddf5c89 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -411,7 +411,7 @@ static void via_pm_class_init(ObjectClass *klass, void *data)
     dc->desc = "PM";
     dc->vmsd = &vmstate_acpi;
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
-    dc->props = via_pm_properties;
+    device_class_set_props(dc, via_pm_properties);
 }
 
 static const TypeInfo via_pm_info = {
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 9e8dab0..f8aa649 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -443,7 +443,7 @@ static void pc_dimm_class_init(ObjectClass *oc, void *data)
 
     dc->realize = pc_dimm_realize;
     dc->unrealize = pc_dimm_unrealize;
-    dc->props = pc_dimm_properties;
+    device_class_set_props(dc, pc_dimm_properties);
     dc->desc = "DIMM memory module";
 
     ddc->get_memory_region = pc_dimm_get_memory_region;
diff --git a/hw/mips/cps.c b/hw/mips/cps.c
index 4ef337d..1753d82 100644
--- a/hw/mips/cps.c
+++ b/hw/mips/cps.c
@@ -173,7 +173,7 @@ static void mips_cps_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = mips_cps_realize;
-    dc->props = mips_cps_properties;
+    device_class_set_props(dc, mips_cps_properties);
 }
 
 static const TypeInfo mips_cps_info = {
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
index 3e8ad8c..687656f 100644
--- a/hw/misc/a9scu.c
+++ b/hw/misc/a9scu.c
@@ -132,7 +132,7 @@ static void a9_scu_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = a9_scu_properties;
+    device_class_set_props(dc, a9_scu_properties);
     dc->vmsd = &vmstate_a9_scu;
     dc->reset = a9_scu_reset;
 }
diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
index 77fab5b..99ea90d 100644
--- a/hw/misc/applesmc.c
+++ b/hw/misc/applesmc.c
@@ -261,7 +261,7 @@ static void qdev_applesmc_class_init(ObjectClass *klass, void *data)
 
     dc->realize = applesmc_isa_realize;
     dc->reset = qdev_applesmc_isa_reset;
-    dc->props = applesmc_isa_properties;
+    device_class_set_props(dc, applesmc_isa_properties);
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
diff --git a/hw/misc/arm11scu.c b/hw/misc/arm11scu.c
index 7042ce1..f8c103d 100644
--- a/hw/misc/arm11scu.c
+++ b/hw/misc/arm11scu.c
@@ -83,7 +83,7 @@ static void arm11_scu_class_init(ObjectClass *oc, void *data)
     DeviceClass *dc = DEVICE_CLASS(oc);
 
     dc->realize = arm11_scu_realize;
-    dc->props = arm11_scu_properties;
+    device_class_set_props(dc, arm11_scu_properties);
 }
 
 static const TypeInfo arm11_scu_type_info = {
diff --git a/hw/misc/arm_l2x0.c b/hw/misc/arm_l2x0.c
index 66a0787..ac35ae3 100644
--- a/hw/misc/arm_l2x0.c
+++ b/hw/misc/arm_l2x0.c
@@ -179,7 +179,7 @@ static void l2x0_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->vmsd = &vmstate_l2x0;
-    dc->props = l2x0_properties;
+    device_class_set_props(dc, l2x0_properties);
     dc->reset = l2x0_priv_reset;
 }
 
diff --git a/hw/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c
index 8524008..2d43904 100644
--- a/hw/misc/arm_sysctl.c
+++ b/hw/misc/arm_sysctl.c
@@ -639,7 +639,7 @@ static void arm_sysctl_class_init(ObjectClass *klass, void *data)
     dc->realize = arm_sysctl_realize;
     dc->reset = arm_sysctl_reset;
     dc->vmsd = &vmstate_arm_sysctl;
-    dc->props = arm_sysctl_properties;
+    device_class_set_props(dc, arm_sysctl_properties);
 }
 
 static const TypeInfo arm_sysctl_info = {
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index b1f3e6f..885048f 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -307,7 +307,7 @@ static void aspeed_scu_class_init(ObjectClass *klass, void *data)
     dc->reset = aspeed_scu_reset;
     dc->desc = "ASPEED System Control Unit";
     dc->vmsd = &vmstate_aspeed_scu;
-    dc->props = aspeed_scu_properties;
+    device_class_set_props(dc, aspeed_scu_properties);
 }
 
 static const TypeInfo aspeed_scu_info = {
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index 8830dc0..7830b25 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -262,7 +262,7 @@ static void aspeed_sdmc_class_init(ObjectClass *klass, void *data)
     dc->reset = aspeed_sdmc_reset;
     dc->desc = "ASPEED SDRAM Memory Controller";
     dc->vmsd = &vmstate_aspeed_sdmc;
-    dc->props = aspeed_sdmc_properties;
+    device_class_set_props(dc, aspeed_sdmc_properties);
 }
 
 static const TypeInfo aspeed_sdmc_info = {
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
index 70eaafd..522d580 100644
--- a/hw/misc/bcm2835_property.c
+++ b/hw/misc/bcm2835_property.c
@@ -419,7 +419,7 @@ static void bcm2835_property_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = bcm2835_property_props;
+    device_class_set_props(dc, bcm2835_property_props);
     dc->realize = bcm2835_property_realize;
     dc->vmsd = &vmstate_bcm2835_property;
 }
diff --git a/hw/misc/debugexit.c b/hw/misc/debugexit.c
index 84fa1a5..f729901 100644
--- a/hw/misc/debugexit.c
+++ b/hw/misc/debugexit.c
@@ -58,7 +58,7 @@ static void debug_exit_class_initfn(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = debug_exit_realizefn;
-    dc->props = debug_exit_properties;
+    device_class_set_props(dc, debug_exit_properties);
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
diff --git a/hw/misc/eccmemctl.c b/hw/misc/eccmemctl.c
index a0071f3..b9c0e17 100644
--- a/hw/misc/eccmemctl.c
+++ b/hw/misc/eccmemctl.c
@@ -326,7 +326,7 @@ static void ecc_class_init(ObjectClass *klass, void *data)
     k->init = ecc_init1;
     dc->reset = ecc_reset;
     dc->vmsd = &vmstate_ecc;
-    dc->props = ecc_properties;
+    device_class_set_props(dc, ecc_properties);
 }
 
 static const TypeInfo ecc_info = {
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 230e51b..81a5796 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -1074,7 +1074,7 @@ static void ivshmem_plain_class_init(ObjectClass *klass, void *data)
 
     k->realize = ivshmem_plain_realize;
     k->exit = ivshmem_plain_exit;
-    dc->props = ivshmem_plain_properties;
+    device_class_set_props(dc, ivshmem_plain_properties);
     dc->vmsd = &ivshmem_plain_vmsd;
 }
 
@@ -1136,7 +1136,7 @@ static void ivshmem_doorbell_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
     k->realize = ivshmem_doorbell_realize;
-    dc->props = ivshmem_doorbell_properties;
+    device_class_set_props(dc, ivshmem_doorbell_properties);
     dc->vmsd = &ivshmem_doorbell_vmsd;
 }
 
@@ -1304,7 +1304,7 @@ static void ivshmem_class_init(ObjectClass *klass, void *data)
     k->realize = ivshmem_realize;
     k->revision = 0;
     dc->desc = "Inter-VM shared memory (legacy)";
-    dc->props = ivshmem_properties;
+    device_class_set_props(dc, ivshmem_properties);
     dc->vmsd = &ivshmem_vmsd;
 }
 
diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
index 05c02fb..6e0dd0c 100644
--- a/hw/misc/macio/cuda.c
+++ b/hw/misc/macio/cuda.c
@@ -945,7 +945,7 @@ static void cuda_class_init(ObjectClass *oc, void *data)
     dc->realize = cuda_realizefn;
     dc->reset = cuda_reset;
     dc->vmsd = &vmstate_cuda;
-    dc->props = cuda_properties;
+    device_class_set_props(dc, cuda_properties);
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 }
 
diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
index 5d57f45..8708985 100644
--- a/hw/misc/macio/macio.c
+++ b/hw/misc/macio/macio.c
@@ -388,7 +388,7 @@ static void macio_class_init(ObjectClass *klass, void *data)
 
     k->vendor_id = PCI_VENDOR_ID_APPLE;
     k->class_id = PCI_CLASS_OTHERS << 8;
-    dc->props = macio_properties;
+    device_class_set_props(dc, macio_properties);
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 }
 
diff --git a/hw/misc/mips_cmgcr.c b/hw/misc/mips_cmgcr.c
index b3ba166..c103ded 100644
--- a/hw/misc/mips_cmgcr.c
+++ b/hw/misc/mips_cmgcr.c
@@ -224,7 +224,7 @@ static void mips_gcr_realize(DeviceState *dev, Error **errp)
 static void mips_gcr_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    dc->props = mips_gcr_properties;
+    device_class_set_props(dc, mips_gcr_properties);
     dc->vmsd = &vmstate_mips_gcr;
     dc->reset = mips_gcr_reset;
     dc->realize = mips_gcr_realize;
diff --git a/hw/misc/mips_cpc.c b/hw/misc/mips_cpc.c
index 6d34574..52661ca 100644
--- a/hw/misc/mips_cpc.c
+++ b/hw/misc/mips_cpc.c
@@ -159,7 +159,7 @@ static void mips_cpc_class_init(ObjectClass *klass, void *data)
     dc->realize = mips_cpc_realize;
     dc->reset = mips_cpc_reset;
     dc->vmsd = &vmstate_mips_cpc;
-    dc->props = mips_cpc_properties;
+    device_class_set_props(dc, mips_cpc_properties);
 }
 
 static const TypeInfo mips_cpc_info = {
diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c
index ef935b5..a148a28 100644
--- a/hw/misc/mips_itu.c
+++ b/hw/misc/mips_itu.c
@@ -503,7 +503,7 @@ static void mips_itu_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = mips_itu_properties;
+    device_class_set_props(dc, mips_itu_properties);
     dc->realize = mips_itu_realize;
     dc->reset = mips_itu_reset;
 }
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
index 0ac1e6a..14b7cfb 100644
--- a/hw/misc/pvpanic.c
+++ b/hw/misc/pvpanic.c
@@ -124,7 +124,7 @@ static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = pvpanic_isa_realizefn;
-    dc->props = pvpanic_isa_properties;
+    device_class_set_props(dc, pvpanic_isa_properties);
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c
index 50e8361..2132d8a 100644
--- a/hw/net/allwinner_emac.c
+++ b/hw/net/allwinner_emac.c
@@ -514,7 +514,7 @@ static void aw_emac_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = aw_emac_realize;
-    dc->props = aw_emac_properties;
+    device_class_set_props(dc, aw_emac_properties);
     dc->reset = aw_emac_reset;
     dc->vmsd = &vmstate_aw_emac;
 }
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index 7915732..d0c0b26 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -1522,7 +1522,7 @@ static void gem_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = gem_realize;
-    dc->props = gem_properties;
+    device_class_set_props(dc, gem_properties);
     dc->vmsd = &vmstate_cadence_gem;
     dc->reset = gem_reset;
 }
diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 17f0338..a165886 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -891,7 +891,7 @@ static void dp8393x_class_init(ObjectClass *klass, void *data)
     dc->realize = dp8393x_realize;
     dc->reset = dp8393x_reset;
     dc->vmsd = &vmstate_dp8393x;
-    dc->props = dp8393x_properties;
+    device_class_set_props(dc, dp8393x_properties);
     /* Reason: dma_mr property can't be set */
     dc->cannot_instantiate_with_device_add_yet = true;
 }
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 9324949..0df3f2f 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -1667,7 +1667,7 @@ static void e1000_class_init(ObjectClass *klass, void *data)
     dc->desc = "Intel Gigabit Ethernet";
     dc->reset = qdev_e1000_reset;
     dc->vmsd = &vmstate_e1000;
-    dc->props = e1000_properties;
+    device_class_set_props(dc, e1000_properties);
 }
 
 static void e1000_instance_init(Object *obj)
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index 4994e1c..032d90f 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -671,7 +671,6 @@ static void e1000e_class_init(ObjectClass *class, void *data)
     dc->desc = "Intel 82574L GbE Controller";
     dc->reset = e1000e_qdev_reset;
     dc->vmsd = &e1000e_vmstate;
-    dc->props = e1000e_properties;
 
     e1000e_prop_disable_vnet = qdev_prop_uint8;
     e1000e_prop_disable_vnet.description = "Do not use virtio headers, "
@@ -684,6 +683,8 @@ static void e1000e_class_init(ObjectClass *class, void *data)
     e1000e_prop_subsys = qdev_prop_uint16;
     e1000e_prop_subsys.description = "PCI device Subsystem ID";
 
+    device_class_set_props(dc, e1000e_properties);
+
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 }
 
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index 4bf71f2..9de9169 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -2082,7 +2082,7 @@ static void eepro100_class_init(ObjectClass *klass, void *data)
     info = eepro100_get_class_by_name(object_class_get_name(klass));
 
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
-    dc->props = e100_properties;
+    device_class_set_props(dc, e100_properties);
     dc->desc = info->desc;
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->class_id = PCI_CLASS_NETWORK_ETHERNET;
diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c
index efaa49f..2070e75 100644
--- a/hw/net/etraxfs_eth.c
+++ b/hw/net/etraxfs_eth.c
@@ -628,7 +628,7 @@ static void etraxfs_eth_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
     k->init = fs_eth_init;
-    dc->props = etraxfs_eth_properties;
+    device_class_set_props(dc, etraxfs_eth_properties);
     /* Reason: pointer properties "dma_out", "dma_in" */
     dc->cannot_instantiate_with_device_add_yet = true;
 }
diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c
index 951c5f0..ca3e78f 100644
--- a/hw/net/fsl_etsec/etsec.c
+++ b/hw/net/fsl_etsec/etsec.c
@@ -416,7 +416,7 @@ static void etsec_class_init(ObjectClass *klass, void *data)
 
     dc->realize = etsec_realize;
     dc->reset = etsec_reset;
-    dc->props = etsec_properties;
+    device_class_set_props(dc, etsec_properties);
 }
 
 static TypeInfo etsec_info = {
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 50c7564..a4ac141 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1189,7 +1189,7 @@ static void imx_eth_class_init(ObjectClass *klass, void *data)
 
     dc->vmsd    = &vmstate_imx_eth;
     dc->reset   = imx_eth_reset;
-    dc->props   = imx_eth_properties;
+    device_class_set_props(dc, imx_eth_properties);
     dc->realize = imx_eth_realize;
     dc->desc    = "i.MX FEC/ENET Ethernet Controller";
 }
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index 3db8937..cf8b4f0 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -1365,7 +1365,7 @@ static void lan9118_class_init(ObjectClass *klass, void *data)
 
     k->init = lan9118_init1;
     dc->reset = lan9118_reset;
-    dc->props = lan9118_properties;
+    device_class_set_props(dc, lan9118_properties);
     dc->vmsd = &vmstate_lan9118;
 }
 
diff --git a/hw/net/lance.c b/hw/net/lance.c
index 573d724..c4796fa 100644
--- a/hw/net/lance.c
+++ b/hw/net/lance.c
@@ -163,7 +163,7 @@ static void lance_class_init(ObjectClass *klass, void *data)
     dc->fw_name = "ethernet";
     dc->reset = lance_reset;
     dc->vmsd = &vmstate_lance;
-    dc->props = lance_properties;
+    device_class_set_props(dc, lance_properties);
     /* Reason: pointer property "dma" */
     dc->cannot_instantiate_with_device_add_yet = true;
 }
diff --git a/hw/net/milkymist-minimac2.c b/hw/net/milkymist-minimac2.c
index c3a12e1..6aaeaf0 100644
--- a/hw/net/milkymist-minimac2.c
+++ b/hw/net/milkymist-minimac2.c
@@ -526,7 +526,7 @@ static void milkymist_minimac2_class_init(ObjectClass *klass, void *data)
     k->init = milkymist_minimac2_init;
     dc->reset = milkymist_minimac2_reset;
     dc->vmsd = &vmstate_milkymist_minimac2;
-    dc->props = milkymist_minimac2_properties;
+    device_class_set_props(dc, milkymist_minimac2_properties);
 }
 
 static const TypeInfo milkymist_minimac2_info = {
diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c
index 5a63df7..3cc735d 100644
--- a/hw/net/mipsnet.c
+++ b/hw/net/mipsnet.c
@@ -274,7 +274,7 @@ static void mipsnet_class_init(ObjectClass *klass, void *data)
     dc->desc = "MIPS Simulator network device";
     dc->reset = mipsnet_sysbus_reset;
     dc->vmsd = &vmstate_mipsnet;
-    dc->props = mipsnet_properties;
+    device_class_set_props(dc, mipsnet_properties);
 }
 
 static const TypeInfo mipsnet_info = {
diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c
index f345533..23f9c6f 100644
--- a/hw/net/ne2000-isa.c
+++ b/hw/net/ne2000-isa.c
@@ -90,7 +90,7 @@ static void isa_ne2000_class_initfn(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = isa_ne2000_realizefn;
-    dc->props = ne2000_isa_properties;
+    device_class_set_props(dc, ne2000_isa_properties);
     dc->vmsd = &vmstate_isa_ne2000;
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 }
diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
index 798d681..32c0bd5 100644
--- a/hw/net/ne2000.c
+++ b/hw/net/ne2000.c
@@ -776,7 +776,7 @@ static void ne2000_class_init(ObjectClass *klass, void *data)
     k->device_id = PCI_DEVICE_ID_REALTEK_8029;
     k->class_id = PCI_CLASS_NETWORK_ETHERNET;
     dc->vmsd = &vmstate_pci_ne2000;
-    dc->props = ne2000_properties;
+    device_class_set_props(dc, ne2000_properties);
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 }
 
diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c
index 268d6a7..6084502 100644
--- a/hw/net/opencores_eth.c
+++ b/hw/net/opencores_eth.c
@@ -755,7 +755,7 @@ static void open_eth_class_init(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
     dc->desc = "Opencores 10/100 Mbit Ethernet";
     dc->reset = qdev_open_eth_reset;
-    dc->props = open_eth_properties;
+    device_class_set_props(dc, open_eth_properties);
 }
 
 static const TypeInfo open_eth_info = {
diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c
index 0acf8a4..e52e970 100644
--- a/hw/net/pcnet-pci.c
+++ b/hw/net/pcnet-pci.c
@@ -355,7 +355,7 @@ static void pcnet_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_NETWORK_ETHERNET;
     dc->reset = pci_reset;
     dc->vmsd = &vmstate_pci_pcnet;
-    dc->props = pcnet_properties;
+    device_class_set_props(dc, pcnet_properties);
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 }
 
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
index e9d215a..8505e75 100644
--- a/hw/net/rocker/rocker.c
+++ b/hw/net/rocker/rocker.c
@@ -1565,7 +1565,7 @@ static void rocker_class_init(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
     dc->desc = "Rocker Switch";
     dc->reset = rocker_reset;
-    dc->props = rocker_properties;
+    device_class_set_props(dc, rocker_properties);
     dc->vmsd = &rocker_vmsd;
 }
 
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index f05e59c..91dc9a5 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -3471,7 +3471,7 @@ static void rtl8139_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_NETWORK_ETHERNET;
     dc->reset = rtl8139_reset;
     dc->vmsd = &vmstate_rtl8139;
-    dc->props = rtl8139_properties;
+    device_class_set_props(dc, rtl8139_properties);
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 }
 
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
index 3b16dcf..49533af 100644
--- a/hw/net/smc91c111.c
+++ b/hw/net/smc91c111.c
@@ -791,7 +791,7 @@ static void smc91c111_class_init(ObjectClass *klass, void *data)
     k->init = smc91c111_init1;
     dc->reset = smc91c111_reset;
     dc->vmsd = &vmstate_smc91c111;
-    dc->props = smc91c111_properties;
+    device_class_set_props(dc, smc91c111_properties);
 }
 
 static const TypeInfo smc91c111_info = {
diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
index 01ecb02..2783dcd 100644
--- a/hw/net/spapr_llan.c
+++ b/hw/net/spapr_llan.c
@@ -849,7 +849,7 @@ static void spapr_vlan_class_init(ObjectClass *klass, void *data)
     k->dt_compatible = "IBM,l-lan";
     k->signal_mask = 0x1;
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
-    dc->props = spapr_vlan_properties;
+    device_class_set_props(dc, spapr_vlan_properties);
     k->rtce_window_size = 0x10000000;
     dc->vmsd = &vmstate_spapr_llan;
 }
diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c
index 957730e..5211d40 100644
--- a/hw/net/stellaris_enet.c
+++ b/hw/net/stellaris_enet.c
@@ -495,7 +495,7 @@ static void stellaris_enet_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
     k->init = stellaris_enet_init;
-    dc->props = stellaris_enet_properties;
+    device_class_set_props(dc, stellaris_enet_properties);
     dc->vmsd = &vmstate_stellaris_enet;
 }
 
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 06bfe4b..252313b 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1926,7 +1926,7 @@ static void virtio_net_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
 
-    dc->props = virtio_net_properties;
+    device_class_set_props(dc, virtio_net_properties);
     dc->vmsd = &vmstate_virtio_net;
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
     vdc->realize = virtio_net_device_realize;
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 92f6af9..e452413 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -2715,7 +2715,7 @@ static void vmxnet3_class_init(ObjectClass *class, void *data)
     dc->desc = "VMWare Paravirtualized Ethernet v3";
     dc->reset = vmxnet3_qdev_reset;
     dc->vmsd = &vmstate_vmxnet3;
-    dc->props = vmxnet3_properties;
+    device_class_set_props(dc, vmxnet3_properties);
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 }
 
diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c
index 46b1aa1..a7992f2 100644
--- a/hw/net/xgmac.c
+++ b/hw/net/xgmac.c
@@ -415,7 +415,7 @@ static void xgmac_enet_class_init(ObjectClass *klass, void *data)
 
     sbc->init = xgmac_enet_init;
     dc->vmsd = &vmstate_xgmac;
-    dc->props = xgmac_properties;
+    device_class_set_props(dc, xgmac_properties);
 }
 
 static const TypeInfo xgmac_enet_info = {
diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
index b670184..4586b20 100644
--- a/hw/net/xilinx_axienet.c
+++ b/hw/net/xilinx_axienet.c
@@ -1031,7 +1031,7 @@ static void xilinx_enet_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = xilinx_enet_realize;
-    dc->props = xilinx_enet_properties;
+    device_class_set_props(dc, xilinx_enet_properties);
     dc->reset = xilinx_axienet_reset;
 }
 
diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
index 35de353..a8e0a0a 100644
--- a/hw/net/xilinx_ethlite.c
+++ b/hw/net/xilinx_ethlite.c
@@ -261,7 +261,7 @@ static void xilinx_ethlite_class_init(ObjectClass *klass, void *data)
 
     dc->realize = xilinx_ethlite_realize;
     dc->reset = xilinx_ethlite_reset;
-    dc->props = xilinx_ethlite_properties;
+    device_class_set_props(dc, xilinx_ethlite_properties);
 }
 
 static const TypeInfo xilinx_ethlite_info = {
diff --git a/hw/nvram/ds1225y.c b/hw/nvram/ds1225y.c
index 57d5ab2..78fc9cf 100644
--- a/hw/nvram/ds1225y.c
+++ b/hw/nvram/ds1225y.c
@@ -152,7 +152,7 @@ static void nvram_sysbus_class_init(ObjectClass *klass, void *data)
 
     k->init = nvram_sysbus_initfn;
     dc->vmsd = &vmstate_nvram;
-    dc->props = nvram_sysbus_properties;
+    device_class_set_props(dc, nvram_sysbus_properties);
 }
 
 static const TypeInfo nvram_sysbus_info = {
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 92aa563..aa1f040 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -1029,7 +1029,7 @@ static void fw_cfg_io_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = fw_cfg_io_realize;
-    dc->props = fw_cfg_io_properties;
+    device_class_set_props(dc, fw_cfg_io_properties);
 }
 
 static const TypeInfo fw_cfg_io_info = {
@@ -1086,7 +1086,7 @@ static void fw_cfg_mem_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = fw_cfg_mem_realize;
-    dc->props = fw_cfg_mem_properties;
+    device_class_set_props(dc, fw_cfg_mem_properties);
 }
 
 static const TypeInfo fw_cfg_mem_info = {
diff --git a/hw/nvram/mac_nvram.c b/hw/nvram/mac_nvram.c
index 63f9ed1..39ac159 100644
--- a/hw/nvram/mac_nvram.c
+++ b/hw/nvram/mac_nvram.c
@@ -125,7 +125,7 @@ static void macio_nvram_class_init(ObjectClass *oc, void *data)
     dc->unrealize = macio_nvram_unrealizefn;
     dc->reset = macio_nvram_reset;
     dc->vmsd = &vmstate_macio_nvram;
-    dc->props = macio_nvram_properties;
+    device_class_set_props(dc, macio_nvram_properties);
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c
index eb42ea3..ee8a0c3 100644
--- a/hw/nvram/spapr_nvram.c
+++ b/hw/nvram/spapr_nvram.c
@@ -246,7 +246,7 @@ static void spapr_nvram_class_init(ObjectClass *klass, void *data)
     k->dt_type = "nvram";
     k->dt_compatible = "qemu,spapr-nvram";
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
-    dc->props = spapr_nvram_properties;
+    device_class_set_props(dc, spapr_nvram_properties);
     dc->vmsd = &vmstate_spapr_nvram;
 }
 
diff --git a/hw/pci-bridge/ioh3420.c b/hw/pci-bridge/ioh3420.c
index c8b5ac4..ed9f827 100644
--- a/hw/pci-bridge/ioh3420.c
+++ b/hw/pci-bridge/ioh3420.c
@@ -202,7 +202,7 @@ static void ioh3420_class_init(ObjectClass *klass, void *data)
     dc->desc = "Intel IOH device id 3420 PCIE Root Port";
     dc->reset = ioh3420_reset;
     dc->vmsd = &vmstate_ioh3420;
-    dc->props = ioh3420_props;
+    device_class_set_props(dc, ioh3420_props);
 }
 
 static const TypeInfo ioh3420_info = {
diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c
index 5dbd933..629df64 100644
--- a/hw/pci-bridge/pci_bridge_dev.c
+++ b/hw/pci-bridge/pci_bridge_dev.c
@@ -225,7 +225,7 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
     k->is_bridge = 1,
     dc->desc = "Standard PCI Bridge";
     dc->reset = qdev_pci_bridge_dev_reset;
-    dc->props = pci_bridge_dev_properties;
+    device_class_set_props(dc, pci_bridge_dev_properties);
     dc->vmsd = &pci_bridge_dev_vmstate;
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
     hc->plug = pci_bridge_dev_hotplug_cb;
diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c
index 1cc598f..d5660b9 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -307,7 +307,7 @@ static void pxb_dev_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_BRIDGE_HOST;
 
     dc->desc = "PCI Expander Bridge";
-    dc->props = pxb_dev_properties;
+    device_class_set_props(dc, pxb_dev_properties);
     dc->hotpluggable = false;
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 }
@@ -341,7 +341,7 @@ static void pxb_pcie_dev_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_BRIDGE_HOST;
 
     dc->desc = "PCI Express Expander Bridge";
-    dc->props = pxb_dev_properties;
+    device_class_set_props(dc, pxb_dev_properties);
     dc->hotpluggable = false;
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 }
diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c
index cef6e13..4b3d136 100644
--- a/hw/pci-bridge/xio3130_downstream.c
+++ b/hw/pci-bridge/xio3130_downstream.c
@@ -188,7 +188,7 @@ static void xio3130_downstream_class_init(ObjectClass *klass, void *data)
     dc->desc = "TI X3130 Downstream Port of PCI Express Switch";
     dc->reset = xio3130_downstream_reset;
     dc->vmsd = &vmstate_xio3130_downstream;
-    dc->props = xio3130_downstream_props;
+    device_class_set_props(dc, xio3130_downstream_props);
 }
 
 static const TypeInfo xio3130_downstream_info = {
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index f9218aa..0b41f62 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -872,7 +872,7 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
     hc->root_bus_path = i440fx_pcihost_root_bus_path;
     dc->realize = i440fx_pcihost_realize;
     dc->fw_name = "pci";
-    dc->props = i440fx_props;
+    device_class_set_props(dc, i440fx_props);
     /* Reason: needs to be wired up by pc_init1 */
     dc->cannot_instantiate_with_device_add_yet = true;
 }
diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
index e502bc0..9c1bfc3 100644
--- a/hw/pci-host/ppce500.c
+++ b/hw/pci-host/ppce500.c
@@ -531,7 +531,7 @@ static void e500_pcihost_class_init(ObjectClass *klass, void *data)
 
     k->init = e500_pcihost_initfn;
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
-    dc->props = pcihost_properties;
+    device_class_set_props(dc, pcihost_properties);
     dc->vmsd = &vmstate_ppce500_pci;
 }
 
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
index 5580293..ce55eb7 100644
--- a/hw/pci-host/prep.c
+++ b/hw/pci-host/prep.c
@@ -386,7 +386,7 @@ static void raven_pcihost_class_init(ObjectClass *klass, void *data)
 
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
     dc->realize = raven_pcihost_realizefn;
-    dc->props = raven_pcihost_properties;
+    device_class_set_props(dc, raven_pcihost_properties);
     dc->fw_name = "pci";
 }
 
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 344f77b..72cabb9 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -154,7 +154,7 @@ static void q35_host_class_init(ObjectClass *klass, void *data)
 
     hc->root_bus_path = q35_host_root_bus_path;
     dc->realize = q35_host_realize;
-    dc->props = mch_props;
+    device_class_set_props(dc, mch_props);
     /* Reason: needs to be wired up by pc_q35_init */
     dc->cannot_instantiate_with_device_add_yet = true;
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
index 467cbb9..1c4b9e3 100644
--- a/hw/pci-host/versatile.c
+++ b/hw/pci-host/versatile.c
@@ -502,7 +502,7 @@ static void pci_vpb_class_init(ObjectClass *klass, void *data)
     dc->realize = pci_vpb_realize;
     dc->reset = pci_vpb_reset;
     dc->vmsd = &pci_vpb_vmstate;
-    dc->props = pci_vpb_properties;
+    device_class_set_props(dc, pci_vpb_properties);
     /* Reason: object_unref() hangs */
     dc->cannot_destroy_with_object_finalize_yet = true;
 }
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 24fae16..8d93a47 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -2492,7 +2492,7 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
     k->realize = pci_qdev_realize;
     k->unrealize = pci_qdev_unrealize;
     k->bus_type = TYPE_PCI_BUS;
-    k->props = pci_props;
+    device_class_set_props(k, pci_props);
     pc->realize = pci_default_realize;
 }
 
diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c
index 6432b9a..8bcca7c 100644
--- a/hw/pci/pcie_port.c
+++ b/hw/pci/pcie_port.c
@@ -131,7 +131,7 @@ static void pcie_port_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
 
-    dc->props = pcie_port_props;
+    device_class_set_props(dc, pcie_port_props);
 }
 
 static const TypeInfo pcie_port_type_info = {
@@ -153,7 +153,7 @@ static void pcie_slot_class_init(ObjectClass *oc, void *data)
     DeviceClass *dc = DEVICE_CLASS(oc);
     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
 
-    dc->props = pcie_slot_props;
+    device_class_set_props(dc, pcie_slot_props);
     hc->plug = pcie_cap_slot_hotplug_cb;
     hc->unplug_request = pcie_cap_slot_hot_unplug_request_cb;
 }
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 82276e0..94aef9c 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -721,7 +721,7 @@ static void pnv_chip_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = pnv_chip_realize;
-    dc->props = pnv_chip_properties;
+    device_class_set_props(dc, pnv_chip_properties);
     dc->desc = "PowerNV Chip";
 }
 
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 2acda96..7ec9d26 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -190,7 +190,7 @@ static void pnv_core_class_init(ObjectClass *oc, void *data)
     PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
 
     dc->realize = pnv_core_realize;
-    dc->props = pnv_core_properties;
+    device_class_set_props(dc, pnv_core_properties);
     pcc->cpu_oc = cpu_class_by_name(TYPE_POWERPC_CPU, data);
 }
 
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 7cde30e..341a04b 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1696,7 +1696,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
 
     hc->root_bus_path = spapr_phb_root_bus_path;
     dc->realize = spapr_phb_realize;
-    dc->props = spapr_phb_properties;
+    device_class_set_props(dc, spapr_phb_properties);
     dc->reset = spapr_phb_reset;
     dc->vmsd = &vmstate_spapr_pci;
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
index 8448e0b..605a9c1 100644
--- a/hw/ppc/spapr_pci_vfio.c
+++ b/hw/ppc/spapr_pci_vfio.c
@@ -223,7 +223,7 @@ static void spapr_phb_vfio_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->props = spapr_phb_vfio_properties;
+    device_class_set_props(dc, spapr_phb_vfio_properties);
 }
 
 static const TypeInfo spapr_phb_vfio_info = {
diff --git a/hw/ppc/spapr_rng.c b/hw/ppc/spapr_rng.c
index 80515eb..16091ab 100644
--- a/hw/ppc/spapr_rng.c
+++ b/hw/ppc/spapr_rng.c
@@ -172,7 +172,7 @@ static void spapr_rng_class_init(ObjectClass *oc, void *data)
 
     dc->realize = spapr_rng_realize;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
-    dc->props = spapr_rng_properties;
+    device_class_set_props(dc, spapr_rng_properties);
     dc->hotpluggable = false;
 }
 
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index cc1e09c..2d23e16 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -586,7 +586,7 @@ static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
     k->realize = spapr_vio_busdev_realize;
     k->reset = spapr_vio_busdev_reset;
     k->bus_type = TYPE_SPAPR_VIO_BUS;
-    k->props = spapr_vio_props;
+    device_class_set_props(k, spapr_vio_props);
 }
 
 static const TypeInfo spapr_vio_type_info = {
diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c
index 9a7f7ee..a332af8 100644
--- a/hw/s390x/css-bridge.c
+++ b/hw/s390x/css-bridge.c
@@ -125,7 +125,7 @@ static void virtual_css_bridge_class_init(ObjectClass *klass, void *data)
 
     hc->unplug = ccw_device_unplug;
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
-    dc->props = virtual_css_bridge_properties;
+    device_class_set_props(dc, virtual_css_bridge_properties);
 }
 
 static const TypeInfo virtual_css_bridge_info = {
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 2e2664f..947cf12 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -315,7 +315,7 @@ static void s390_ipl_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = s390_ipl_realize;
-    dc->props = s390_ipl_properties;
+    device_class_set_props(dc, s390_ipl_properties);
     dc->reset = s390_ipl_reset;
     dc->vmsd = &vmstate_ipl;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index b7f8bca..9d8d13f 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -942,7 +942,7 @@ static void s390_pci_device_class_init(ObjectClass *klass, void *data)
     dc->reset = s390_pci_device_reset;
     dc->bus_type = TYPE_S390_PCI_BUS;
     dc->realize = s390_pci_device_realize;
-    dc->props = s390_pci_device_properties;
+    device_class_set_props(dc, s390_pci_device_properties);
 }
 
 static const TypeInfo s390_pci_device_info = {
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index ee136ab..6454fcb 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1347,7 +1347,7 @@ static void virtio_ccw_net_class_init(ObjectClass *klass, void *data)
     k->realize = virtio_ccw_net_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
-    dc->props = virtio_ccw_net_properties;
+    device_class_set_props(dc, virtio_ccw_net_properties);
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 }
 
@@ -1376,7 +1376,7 @@ static void virtio_ccw_blk_class_init(ObjectClass *klass, void *data)
     k->realize = virtio_ccw_blk_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
-    dc->props = virtio_ccw_blk_properties;
+    device_class_set_props(dc, virtio_ccw_blk_properties);
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
 
@@ -1405,7 +1405,7 @@ static void virtio_ccw_serial_class_init(ObjectClass *klass, void *data)
     k->realize = virtio_ccw_serial_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
-    dc->props = virtio_ccw_serial_properties;
+    device_class_set_props(dc, virtio_ccw_serial_properties);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
@@ -1434,7 +1434,7 @@ static void virtio_ccw_balloon_class_init(ObjectClass *klass, void *data)
     k->realize = virtio_ccw_balloon_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
-    dc->props = virtio_ccw_balloon_properties;
+    device_class_set_props(dc, virtio_ccw_balloon_properties);
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
@@ -1463,7 +1463,7 @@ static void virtio_ccw_scsi_class_init(ObjectClass *klass, void *data)
     k->realize = virtio_ccw_scsi_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
-    dc->props = virtio_ccw_scsi_properties;
+    device_class_set_props(dc, virtio_ccw_scsi_properties);
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
 
@@ -1491,7 +1491,7 @@ static void vhost_ccw_scsi_class_init(ObjectClass *klass, void *data)
     k->realize = vhost_ccw_scsi_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
-    dc->props = vhost_ccw_scsi_properties;
+    device_class_set_props(dc, vhost_ccw_scsi_properties);
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
 
@@ -1531,7 +1531,7 @@ static void virtio_ccw_rng_class_init(ObjectClass *klass, void *data)
     k->realize = virtio_ccw_rng_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
-    dc->props = virtio_ccw_rng_properties;
+    device_class_set_props(dc, virtio_ccw_rng_properties);
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
@@ -1657,7 +1657,7 @@ static void virtio_ccw_9p_class_init(ObjectClass *klass, void *data)
     k->exit = virtio_ccw_exit;
     k->realize = virtio_ccw_9p_realize;
     dc->reset = virtio_ccw_reset;
-    dc->props = virtio_ccw_9p_properties;
+    device_class_set_props(dc, virtio_ccw_9p_properties);
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
 
@@ -1708,7 +1708,7 @@ static void vhost_vsock_ccw_class_init(ObjectClass *klass, void *data)
     k->realize = vhost_vsock_ccw_realize;
     k->exit = virtio_ccw_exit;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
-    dc->props = vhost_vsock_ccw_properties;
+    device_class_set_props(dc, vhost_vsock_ccw_properties);
     dc->reset = virtio_ccw_reset;
 }
 
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 52a4123..63dfcf5 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -2515,7 +2515,7 @@ static void megasas_class_init(ObjectClass *oc, void *data)
     e->osts = info->osts;
     e->product_name = info->product_name;
     e->product_version = info->product_version;
-    dc->props = info->props;
+    device_class_set_props(dc, info->props);
     dc->reset = megasas_scsi_reset;
     dc->vmsd = info->vmsd;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c
index ad87e78..2fa622e 100644
--- a/hw/scsi/mptsas.c
+++ b/hw/scsi/mptsas.c
@@ -1434,7 +1434,7 @@ static void mptsas1068_class_init(ObjectClass *oc, void *data)
     pc->subsystem_vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
     pc->subsystem_id = 0x8000;
     pc->class_id = PCI_CLASS_STORAGE_SCSI;
-    dc->props = mptsas_properties;
+    device_class_set_props(dc, mptsas_properties);
     dc->reset = mptsas_reset;
     dc->vmsd = &vmstate_mptsas;
     dc->desc = "LSI SAS 1068";
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 297216d..54fcc54 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -2069,7 +2069,7 @@ static void scsi_device_class_init(ObjectClass *klass, void *data)
     k->bus_type  = TYPE_SCSI_BUS;
     k->realize   = scsi_qdev_realize;
     k->unrealize = scsi_qdev_unrealize;
-    k->props     = scsi_props;
+    device_class_set_props(k, scsi_props);
 }
 
 static void scsi_dev_instance_init(Object *obj)
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index a963191..9c1ce3c 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2897,7 +2897,7 @@ static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
     sc->alloc_req    = scsi_new_request;
     sc->unit_attention_reported = scsi_disk_unit_attention_reported;
     dc->desc = "virtual SCSI disk";
-    dc->props = scsi_hd_properties;
+    device_class_set_props(dc, scsi_hd_properties);
     dc->vmsd  = &vmstate_scsi_disk_state;
 }
 
@@ -2926,7 +2926,7 @@ static void scsi_cd_class_initfn(ObjectClass *klass, void *data)
     sc->alloc_req    = scsi_new_request;
     sc->unit_attention_reported = scsi_disk_unit_attention_reported;
     dc->desc = "virtual SCSI CD-ROM";
-    dc->props = scsi_cd_properties;
+    device_class_set_props(dc, scsi_cd_properties);
     dc->vmsd  = &vmstate_scsi_disk_state;
 }
 
@@ -2955,7 +2955,7 @@ static void scsi_block_class_initfn(ObjectClass *klass, void *data)
     sdc->dma_writev  = scsi_block_dma_writev;
     sdc->need_fua_emulation = scsi_block_no_fua;
     dc->desc = "SCSI block device passthrough";
-    dc->props = scsi_block_properties;
+    device_class_set_props(dc, scsi_block_properties);
     dc->vmsd  = &vmstate_scsi_disk_state;
 }
 
@@ -2993,7 +2993,7 @@ static void scsi_disk_class_initfn(ObjectClass *klass, void *data)
     dc->fw_name = "disk";
     dc->desc = "virtual SCSI disk or CD-ROM (legacy)";
     dc->reset = scsi_disk_reset;
-    dc->props = scsi_disk_properties;
+    device_class_set_props(dc, scsi_disk_properties);
     dc->vmsd  = &vmstate_scsi_disk_state;
 }
 
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
index 7a588a7..3a5182c 100644
--- a/hw/scsi/scsi-generic.c
+++ b/hw/scsi/scsi-generic.c
@@ -605,7 +605,7 @@ static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
     dc->fw_name = "disk";
     dc->desc = "pass through generic scsi device (/dev/sg*)";
     dc->reset = scsi_generic_reset;
-    dc->props = scsi_generic_properties;
+    device_class_set_props(dc, scsi_generic_properties);
     dc->vmsd  = &vmstate_scsi_device;
 }
 
diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
index 6090a20..cb11a7e 100644
--- a/hw/scsi/spapr_vscsi.c
+++ b/hw/scsi/spapr_vscsi.c
@@ -1268,7 +1268,7 @@ static void spapr_vscsi_class_init(ObjectClass *klass, void *data)
     k->dt_compatible = "IBM,v-scsi";
     k->signal_mask = 0x00000001;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
-    dc->props = spapr_vscsi_properties;
+    device_class_set_props(dc, spapr_vscsi_properties);
     k->rtce_window_size = 0x10000000;
     dc->vmsd = &vmstate_spapr_vscsi;
 }
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 5b26946..9833d8b 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -314,7 +314,7 @@ static void vhost_scsi_class_init(ObjectClass *klass, void *data)
     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
     FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(klass);
 
-    dc->props = vhost_scsi_properties;
+    device_class_set_props(dc, vhost_scsi_properties);
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
     vdc->realize = vhost_scsi_realize;
     vdc->unrealize = vhost_scsi_unrealize;
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 4762f05..32f131a 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -949,7 +949,7 @@ static void virtio_scsi_class_init(ObjectClass *klass, void *data)
     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
 
-    dc->props = virtio_scsi_properties;
+    device_class_set_props(dc, virtio_scsi_properties);
     dc->vmsd = &vmstate_virtio_scsi;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
     vdc->realize = virtio_scsi_device_realize;
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index a5ce7de..b5c525c 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -1292,7 +1292,7 @@ static void pvscsi_class_init(ObjectClass *klass, void *data)
     dc->realize = pvscsi_realize;
     dc->reset = pvscsi_reset;
     dc->vmsd = &vmstate_pvscsi;
-    dc->props = pvscsi_properties;
+    device_class_set_props(dc, pvscsi_properties);
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
     hc->unplug = pvscsi_hot_unplug;
     hc->plug = pvscsi_hotplug;
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 8e88e83..e87f40f 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1914,7 +1914,7 @@ static void sd_class_init(ObjectClass *klass, void *data)
     SDCardClass *sc = SD_CARD_CLASS(klass);
 
     dc->realize = sd_realize;
-    dc->props = sd_properties;
+    device_class_set_props(dc, sd_properties);
     dc->vmsd = &sd_vmstate;
     dc->reset = sd_reset;
     dc->bus_type = TYPE_SD_BUS;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 01fbf22..1a30f89 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1305,7 +1305,7 @@ static void sdhci_pci_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_SYSTEM_SDHCI;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
     dc->vmsd = &sdhci_vmstate;
-    dc->props = sdhci_pci_properties;
+    device_class_set_props(dc, sdhci_pci_properties);
     dc->reset = sdhci_poweron_reset;
 }
 
@@ -1356,7 +1356,7 @@ static void sdhci_sysbus_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->vmsd = &sdhci_vmstate;
-    dc->props = sdhci_sysbus_properties;
+    device_class_set_props(dc, sdhci_sysbus_properties);
     dc->realize = sdhci_sysbus_realize;
     dc->reset = sdhci_poweron_reset;
 }
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 6224288..19930b7 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -728,7 +728,7 @@ static void prom_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
     k->init = prom_init1;
-    dc->props = prom_properties;
+    device_class_set_props(dc, prom_properties);
 }
 
 static const TypeInfo prom_info = {
@@ -795,7 +795,7 @@ static void ram_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
     k->init = ram_init1;
-    dc->props = ram_properties;
+    device_class_set_props(dc, ram_properties);
 }
 
 static const TypeInfo ram_info = {
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 271d8bc..f5eccc3 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -652,7 +652,7 @@ static void prom_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
     k->init = prom_init1;
-    dc->props = prom_properties;
+    device_class_set_props(dc, prom_properties);
 }
 
 static const TypeInfo prom_info = {
@@ -713,7 +713,7 @@ static void ram_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
     k->init = ram_init1;
-    dc->props = ram_properties;
+    device_class_set_props(dc, ram_properties);
 }
 
 static const TypeInfo ram_info = {
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 6e8403e..5e3b95e 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -605,7 +605,7 @@ static void aspeed_smc_class_init(ObjectClass *klass, void *data)
 
     dc->realize = aspeed_smc_realize;
     dc->reset = aspeed_smc_reset;
-    dc->props = aspeed_smc_properties;
+    device_class_set_props(dc, aspeed_smc_properties);
     dc->vmsd = &vmstate_aspeed_smc;
     mc->ctrl = data;
 }
diff --git a/hw/ssi/xilinx_spi.c b/hw/ssi/xilinx_spi.c
index 33482f0..82cc089 100644
--- a/hw/ssi/xilinx_spi.c
+++ b/hw/ssi/xilinx_spi.c
@@ -372,7 +372,7 @@ static void xilinx_spi_class_init(ObjectClass *klass, void *data)
 
     k->init = xilinx_spi_init;
     dc->reset = xlx_spi_reset;
-    dc->props = xilinx_spi_properties;
+    device_class_set_props(dc, xilinx_spi_properties);
     dc->vmsd = &vmstate_xilinx_spi;
 }
 
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index da8adfa..a73f4f9 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -705,7 +705,7 @@ static void xilinx_spips_class_init(ObjectClass *klass, void *data)
 
     dc->realize = xilinx_spips_realize;
     dc->reset = xilinx_spips_reset;
-    dc->props = xilinx_spips_properties;
+    device_class_set_props(dc, xilinx_spips_properties);
     dc->vmsd = &vmstate_xilinx_spips;
 
     xsc->reg_ops = &spips_ops;
diff --git a/hw/timer/a9gtimer.c b/hw/timer/a9gtimer.c
index ce1dc63..6f1a73c 100644
--- a/hw/timer/a9gtimer.c
+++ b/hw/timer/a9gtimer.c
@@ -354,7 +354,7 @@ static void a9_gtimer_class_init(ObjectClass *klass, void *data)
     dc->realize = a9_gtimer_realize;
     dc->vmsd = &vmstate_a9_gtimer;
     dc->reset = a9_gtimer_reset;
-    dc->props = a9_gtimer_properties;
+    device_class_set_props(dc, a9_gtimer_properties);
 }
 
 static const TypeInfo a9_gtimer_info = {
diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c
index 22ceabe..a1ac96e 100644
--- a/hw/timer/allwinner-a10-pit.c
+++ b/hw/timer/allwinner-a10-pit.c
@@ -276,7 +276,7 @@ static void a10_pit_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->reset = a10_pit_reset;
-    dc->props = a10_pit_properties;
+    device_class_set_props(dc, a10_pit_properties);
     dc->desc = "allwinner a10 timer";
     dc->vmsd = &vmstate_a10_pit;
 }
diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
index daf6c48..401a6f6 100644
--- a/hw/timer/arm_mptimer.c
+++ b/hw/timer/arm_mptimer.c
@@ -299,7 +299,7 @@ static void arm_mptimer_class_init(ObjectClass *klass, void *data)
     dc->realize = arm_mptimer_realize;
     dc->vmsd = &vmstate_arm_mptimer;
     dc->reset = arm_mptimer_reset;
-    dc->props = arm_mptimer_properties;
+    device_class_set_props(dc, arm_mptimer_properties);
 }
 
 static const TypeInfo arm_mptimer_info = {
diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
index 98fddd7..91f5184 100644
--- a/hw/timer/arm_timer.c
+++ b/hw/timer/arm_timer.c
@@ -389,7 +389,7 @@ static void sp804_class_init(ObjectClass *klass, void *data)
     DeviceClass *k = DEVICE_CLASS(klass);
 
     k->realize = sp804_realize;
-    k->props = sp804_properties;
+    device_class_set_props(k, sp804_properties);
     k->vmsd = &vmstate_sp804;
 }
 
diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
index 712d1ae..fcde90a 100644
--- a/hw/timer/grlib_gptimer.c
+++ b/hw/timer/grlib_gptimer.c
@@ -394,7 +394,7 @@ static void grlib_gptimer_class_init(ObjectClass *klass, void *data)
 
     k->init = grlib_gptimer_init;
     dc->reset = grlib_gptimer_reset;
-    dc->props = grlib_gptimer_properties;
+    device_class_set_props(dc, grlib_gptimer_properties);
 }
 
 static const TypeInfo grlib_gptimer_info = {
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index a2c18b3..3c47ef1 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -770,7 +770,7 @@ static void hpet_device_class_init(ObjectClass *klass, void *data)
     dc->realize = hpet_realize;
     dc->reset = hpet_reset;
     dc->vmsd = &vmstate_hpet;
-    dc->props = hpet_device_properties;
+    device_class_set_props(dc, hpet_device_properties);
 }
 
 static const TypeInfo hpet_device_info = {
diff --git a/hw/timer/i8254.c b/hw/timer/i8254.c
index 5e61ad5..bbecf49 100644
--- a/hw/timer/i8254.c
+++ b/hw/timer/i8254.c
@@ -365,7 +365,7 @@ static void pit_class_initfn(ObjectClass *klass, void *data)
     k->get_channel_info = pit_get_channel_info_common;
     k->post_load = pit_post_load;
     dc->reset = pit_reset;
-    dc->props = pit_properties;
+    device_class_set_props(dc, pit_properties);
 }
 
 static const TypeInfo pit_info = {
diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c
index 2a07b59..4eeb216 100644
--- a/hw/timer/lm32_timer.c
+++ b/hw/timer/lm32_timer.c
@@ -222,7 +222,7 @@ static void lm32_timer_class_init(ObjectClass *klass, void *data)
     dc->realize = lm32_timer_realize;
     dc->reset = timer_reset;
     dc->vmsd = &vmstate_lm32_timer;
-    dc->props = lm32_timer_properties;
+    device_class_set_props(dc, lm32_timer_properties);
 }
 
 static const TypeInfo lm32_timer_info = {
diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
index e46ca88..2c07345 100644
--- a/hw/timer/m48t59.c
+++ b/hw/timer/m48t59.c
@@ -822,7 +822,7 @@ static void m48txx_isa_class_init(ObjectClass *klass, void *data)
 
     dc->realize = m48t59_isa_realize;
     dc->reset = m48t59_reset_isa;
-    dc->props = m48t59_isa_properties;
+    device_class_set_props(dc, m48t59_isa_properties);
     nc->read = m48txx_isa_read;
     nc->write = m48txx_isa_write;
     nc->toggle_lock = m48txx_isa_toggle_lock;
@@ -867,7 +867,7 @@ static void m48txx_sysbus_class_init(ObjectClass *klass, void *data)
 
     k->init = m48t59_init1;
     dc->reset = m48t59_reset_sysbus;
-    dc->props = m48t59_sysbus_properties;
+    device_class_set_props(dc, m48t59_sysbus_properties);
     nc->read = m48txx_sysbus_read;
     nc->write = m48txx_sysbus_write;
     nc->toggle_lock = m48txx_sysbus_toggle_lock;
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index da209d0..9d9b998 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -952,7 +952,7 @@ static void rtc_class_initfn(ObjectClass *klass, void *data)
 
     dc->realize = rtc_realizefn;
     dc->vmsd = &vmstate_rtc;
-    dc->props = mc146818rtc_properties;
+    device_class_set_props(dc, mc146818rtc_properties);
     /* Reason: needs to be wired up by rtc_init() */
     dc->cannot_instantiate_with_device_add_yet = true;
 }
diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
index 4488590..aafbe54 100644
--- a/hw/timer/milkymist-sysctl.c
+++ b/hw/timer/milkymist-sysctl.c
@@ -328,7 +328,7 @@ static void milkymist_sysctl_class_init(ObjectClass *klass, void *data)
     dc->realize = milkymist_sysctl_realize;
     dc->reset = milkymist_sysctl_reset;
     dc->vmsd = &vmstate_milkymist_sysctl;
-    dc->props = milkymist_sysctl_properties;
+    device_class_set_props(dc, milkymist_sysctl_properties);
 }
 
 static const TypeInfo milkymist_sysctl_info = {
diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c
index 59002b4..aa5679b 100644
--- a/hw/timer/pxa2xx_timer.c
+++ b/hw/timer/pxa2xx_timer.c
@@ -546,7 +546,7 @@ static void pxa25x_timer_dev_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->desc = "PXA25x timer";
-    dc->props = pxa25x_timer_dev_properties;
+    device_class_set_props(dc, pxa25x_timer_dev_properties);
 }
 
 static const TypeInfo pxa25x_timer_dev_info = {
@@ -568,7 +568,7 @@ static void pxa27x_timer_dev_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->desc = "PXA27x timer";
-    dc->props = pxa27x_timer_dev_properties;
+    device_class_set_props(dc, pxa27x_timer_dev_properties);
 }
 
 static const TypeInfo pxa27x_timer_dev_info = {
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
index bfee1f3..c14a240 100644
--- a/hw/timer/slavio_timer.c
+++ b/hw/timer/slavio_timer.c
@@ -417,7 +417,7 @@ static void slavio_timer_class_init(ObjectClass *klass, void *data)
     k->init = slavio_timer_init1;
     dc->reset = slavio_timer_reset;
     dc->vmsd = &vmstate_slavio_timer;
-    dc->props = slavio_timer_properties;
+    device_class_set_props(dc, slavio_timer_properties);
 }
 
 static const TypeInfo slavio_timer_info = {
diff --git a/hw/timer/stm32f2xx_timer.c b/hw/timer/stm32f2xx_timer.c
index e5f5e14..6ef3d91 100644
--- a/hw/timer/stm32f2xx_timer.c
+++ b/hw/timer/stm32f2xx_timer.c
@@ -319,7 +319,7 @@ static void stm32f2xx_timer_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->reset = stm32f2xx_timer_reset;
-    dc->props = stm32f2xx_timer_properties;
+    device_class_set_props(dc, stm32f2xx_timer_properties);
     dc->vmsd = &vmstate_stm32f2xx_timer;
 }
 
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
index 59439c0..953d442 100644
--- a/hw/timer/xilinx_timer.c
+++ b/hw/timer/xilinx_timer.c
@@ -247,7 +247,7 @@ static void xilinx_timer_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = xilinx_timer_realize;
-    dc->props = xilinx_timer_properties;
+    device_class_set_props(dc, xilinx_timer_properties);
 }
 
 static const TypeInfo xilinx_timer_info = {
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index 381e726..d290c30 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -1079,7 +1079,7 @@ static void tpm_tis_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = tpm_tis_realizefn;
-    dc->props = tpm_tis_properties;
+    device_class_set_props(dc, tpm_tis_properties);
     dc->reset = tpm_tis_reset;
     dc->vmsd  = &vmstate_tpm_tis;
 }
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 25913ad..2507576 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -791,7 +791,7 @@ static void usb_device_class_init(ObjectClass *klass, void *data)
     k->bus_type = TYPE_USB_BUS;
     k->realize  = usb_qdev_realize;
     k->unrealize = usb_qdev_unrealize;
-    k->props    = usb_props;
+    device_class_set_props(k, usb_props);
 }
 
 static const TypeInfo usb_device_type_info = {
diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c
index 3213f9f..5992d70 100644
--- a/hw/usb/ccid-card-emulated.c
+++ b/hw/usb/ccid-card-emulated.c
@@ -588,7 +588,7 @@ static void emulated_class_initfn(ObjectClass *klass, void *data)
     cc->apdu_from_guest = emulated_apdu_from_guest;
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
     dc->desc = "emulated smartcard";
-    dc->props = emulated_card_properties;
+    device_class_set_props(dc, emulated_card_properties);
 }
 
 static const TypeInfo emulated_card_info = {
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 325129a..2f4fecc 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -402,7 +402,7 @@ static void passthru_class_initfn(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
     dc->desc = "passthrough smartcard";
     dc->vmsd = &passthru_vmstate;
-    dc->props = passthru_card_properties;
+    device_class_set_props(dc, passthru_card_properties);
 }
 
 static const TypeInfo passthru_card_info = {
diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
index 87cab0a..f783f7a 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -675,7 +675,7 @@ static void usb_audio_class_init(ObjectClass *klass, void *data)
     USBDeviceClass *k = USB_DEVICE_CLASS(klass);
 
     dc->vmsd          = &vmstate_usb_audio;
-    dc->props         = usb_audio_properties;
+    device_class_set_props(dc, usb_audio_properties);
     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
     k->product_desc   = "QEMU USB Audio Interface";
     k->usb_desc       = &desc_audio;
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
index 24d05f7..cdc7795 100644
--- a/hw/usb/dev-hid.c
+++ b/hw/usb/dev-hid.c
@@ -812,7 +812,7 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
     uc->realize        = usb_tablet_realize;
     uc->product_desc   = "QEMU USB Tablet";
     dc->vmsd = &vmstate_usb_ptr;
-    dc->props = usb_tablet_properties;
+    device_class_set_props(dc, usb_tablet_properties);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
@@ -835,7 +835,7 @@ static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
     uc->realize        = usb_mouse_realize;
     uc->product_desc   = "QEMU USB Mouse";
     dc->vmsd = &vmstate_usb_ptr;
-    dc->props = usb_mouse_properties;
+    device_class_set_props(dc, usb_mouse_properties);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
@@ -859,7 +859,7 @@ static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
     uc->realize        = usb_keyboard_realize;
     uc->product_desc   = "QEMU USB Keyboard";
     dc->vmsd = &vmstate_usb_kbd;
-    dc->props = usb_keyboard_properties;
+    device_class_set_props(dc, usb_keyboard_properties);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 58d95ff..b9f1cbf 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -1583,7 +1583,7 @@ static void usb_mtp_class_initfn(ObjectClass *klass, void *data)
     uc->handle_data    = usb_mtp_handle_data;
     dc->fw_name = "mtp";
     dc->vmsd = &vmstate_usb_mtp;
-    dc->props = mtp_properties;
+    device_class_set_props(dc, mtp_properties);
 }
 
 static TypeInfo mtp_info = {
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index c0f1193..4f9016e 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1432,7 +1432,7 @@ static void usb_net_class_initfn(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
     dc->fw_name = "network";
     dc->vmsd = &vmstate_usb_net;
-    dc->props = net_properties;
+    device_class_set_props(dc, net_properties);
 }
 
 static const TypeInfo net_info = {
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 6066d9b..a912f44 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -613,7 +613,7 @@ static void usb_serial_class_initfn(ObjectClass *klass, void *data)
 
     uc->product_desc   = "QEMU USB Serial";
     uc->usb_desc       = &desc_serial;
-    dc->props = serial_properties;
+    device_class_set_props(dc, serial_properties);
 }
 
 static const TypeInfo serial_info = {
@@ -634,7 +634,7 @@ static void usb_braille_class_initfn(ObjectClass *klass, void *data)
 
     uc->product_desc   = "QEMU USB Braille";
     uc->usb_desc       = &desc_braille;
-    dc->props = braille_properties;
+    device_class_set_props(dc, braille_properties);
 }
 
 static const TypeInfo braille_info = {
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index af4b851..ed9e759 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1462,7 +1462,7 @@ static void ccid_class_initfn(ObjectClass *klass, void *data)
     uc->handle_destroy = ccid_handle_destroy;
     dc->desc = "CCID Rev 1.1 smartcard reader";
     dc->vmsd = &ccid_vmstate;
-    dc->props = ccid_properties;
+    device_class_set_props(dc, ccid_properties);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
     hc->unplug = qdev_simple_device_unplug_cb;
 }
@@ -1484,7 +1484,7 @@ static void ccid_card_class_init(ObjectClass *klass, void *data)
     k->bus_type = TYPE_CCID_BUS;
     k->init = ccid_card_init;
     k->exit = ccid_card_exit;
-    k->props = ccid_props;
+    device_class_set_props(k, ccid_props);
 }
 
 static const TypeInfo ccid_card_type_info = {
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index c607f76..47ff7b5 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -755,7 +755,7 @@ static void usb_msd_class_initfn_storage(ObjectClass *klass, void *data)
     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 
     uc->realize = usb_msd_realize_storage;
-    dc->props = msd_properties;
+    device_class_set_props(dc, msd_properties);
 }
 
 static void usb_msd_get_bootindex(Object *obj, Visitor *v, const char *name,
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 3a8ff18..5bf7c81 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -948,7 +948,7 @@ static void usb_uas_class_initfn(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
     dc->fw_name = "storage";
     dc->vmsd = &vmstate_usb_uas;
-    dc->props = uas_properties;
+    device_class_set_props(dc, uas_properties);
 }
 
 static const TypeInfo uas_info = {
diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c
index 5657705..8cda359 100644
--- a/hw/usb/hcd-ehci-pci.c
+++ b/hw/usb/hcd-ehci-pci.c
@@ -150,7 +150,7 @@ static void ehci_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_SERIAL_USB;
     k->config_write = usb_ehci_pci_write_config;
     dc->vmsd = &vmstate_ehci_pci;
-    dc->props = ehci_pci_properties;
+    device_class_set_props(dc, ehci_pci_properties);
     dc->reset = usb_ehci_pci_reset;
 }
 
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
index 6c20604..2264b66 100644
--- a/hw/usb/hcd-ehci-sysbus.c
+++ b/hw/usb/hcd-ehci-sysbus.c
@@ -79,7 +79,7 @@ static void ehci_sysbus_class_init(ObjectClass *klass, void *data)
 
     dc->realize = usb_ehci_sysbus_realize;
     dc->vmsd = &vmstate_ehci_sysbus;
-    dc->props = ehci_sysbus_properties;
+    device_class_set_props(dc, ehci_sysbus_properties);
     dc->reset = usb_ehci_sysbus_reset;
     set_bit(DEVICE_CATEGORY_USB, dc->categories);
 }
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index c82a92f..0cdb549 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -2124,7 +2124,7 @@ static void ohci_pci_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_SERIAL_USB;
     set_bit(DEVICE_CATEGORY_USB, dc->categories);
     dc->desc = "Apple USB Controller";
-    dc->props = ohci_pci_properties;
+    device_class_set_props(dc, ohci_pci_properties);
     dc->hotpluggable = false;
     dc->vmsd = &vmstate_ohci;
     dc->reset = usb_ohci_reset_pci;
@@ -2150,7 +2150,7 @@ static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
     dc->realize = ohci_realize_pxa;
     set_bit(DEVICE_CATEGORY_USB, dc->categories);
     dc->desc = "OHCI USB Controller";
-    dc->props = ohci_sysbus_properties;
+    device_class_set_props(dc, ohci_sysbus_properties);
     dc->reset = usb_ohci_reset_sysbus;
 }
 
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index ca72a80..47fa0a0 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -1340,9 +1340,9 @@ static void uhci_data_class_init(ObjectClass *klass, void *data)
     if (!info->unplug) {
         /* uhci controllers in companion setups can't be hotplugged */
         dc->hotpluggable = false;
-        dc->props = uhci_properties_companion;
+        device_class_set_props(dc, uhci_properties_companion);
     } else {
-        dc->props = uhci_properties_standalone;
+        device_class_set_props(dc, uhci_properties_standalone);
     }
     u->info = *info;
 }
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 4acf0c6..4b33e6e 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -3945,7 +3945,7 @@ static void xhci_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->vmsd    = &vmstate_xhci;
-    dc->props   = xhci_properties;
+    device_class_set_props(dc, xhci_properties);
     dc->reset   = xhci_reset;
     set_bit(DEVICE_CATEGORY_USB, dc->categories);
     k->realize      = usb_xhci_realize;
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index bd81d71..f8dacb5 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -1573,7 +1573,7 @@ static void usb_host_class_initfn(ObjectClass *klass, void *data)
     uc->alloc_streams  = usb_host_alloc_streams;
     uc->free_streams   = usb_host_free_streams;
     dc->vmsd = &vmstate_usb_host;
-    dc->props = usb_host_dev_properties;
+    device_class_set_props(dc, usb_host_dev_properties);
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 }
 
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 528081e..6a0b900 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -2508,7 +2508,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data)
     uc->alloc_streams  = usbredir_alloc_streams;
     uc->free_streams   = usbredir_free_streams;
     dc->vmsd           = &usbredir_vmstate;
-    dc->props          = usbredir_properties;
+    device_class_set_props(dc, usbredir_properties);
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 65d30fd..a17c264 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2886,7 +2886,7 @@ static void vfio_pci_dev_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(klass);
 
     dc->reset = vfio_pci_reset;
-    dc->props = vfio_pci_dev_properties;
+    device_class_set_props(dc, vfio_pci_dev_properties);
     dc->vmsd = &vfio_pci_vmstate;
     dc->desc = "VFIO-based PCI device assignment";
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
index a4663c9..9f618ba 100644
--- a/hw/vfio/platform.c
+++ b/hw/vfio/platform.c
@@ -691,7 +691,7 @@ static void vfio_platform_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
 
     dc->realize = vfio_platform_realize;
-    dc->props = vfio_platform_dev_properties;
+    device_class_set_props(dc, vfio_platform_dev_properties);
     dc->vmsd = &vfio_platform_vmstate;
     dc->desc = "VFIO-based platform device assignment";
     sbc->connect_irq_notifier = vfio_start_irqfd_injection;
diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c
index b481562..80718d8 100644
--- a/hw/virtio/vhost-vsock.c
+++ b/hw/virtio/vhost-vsock.c
@@ -390,7 +390,7 @@ static void vhost_vsock_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
 
-    dc->props = vhost_vsock_properties;
+    device_class_set_props(dc, vhost_vsock_properties);
     dc->vmsd = &vmstate_virtio_vhost_vsock;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
     vdc->realize = vhost_vsock_device_realize;
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 1d77028..fc67ea7 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -508,7 +508,7 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
 
-    dc->props = virtio_balloon_properties;
+    device_class_set_props(dc, virtio_balloon_properties);
     dc->vmsd = &vmstate_virtio_balloon;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
     vdc->realize = virtio_balloon_device_realize;
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index 13798b3..14c98f7 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -496,7 +496,7 @@ static void virtio_mmio_class_init(ObjectClass *klass, void *data)
     dc->realize = virtio_mmio_realizefn;
     dc->reset = virtio_mmio_reset;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
-    dc->props = virtio_mmio_properties;
+    device_class_set_props(dc, virtio_mmio_properties);
 }
 
 static const TypeInfo virtio_mmio_info = {
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 06831de..f44860d 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1137,7 +1137,7 @@ static void virtio_9p_pci_class_init(ObjectClass *klass, void *data)
     pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
     pcidev_k->class_id = 0x2;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
-    dc->props = virtio_9p_pci_properties;
+    device_class_set_props(dc, virtio_9p_pci_properties);
 }
 
 static void virtio_9p_pci_instance_init(Object *obj)
@@ -1899,7 +1899,7 @@ static void virtio_pci_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass);
 
-    dc->props = virtio_pci_properties;
+    device_class_set_props(dc, virtio_pci_properties);
     k->realize = virtio_pci_realize;
     k->exit = virtio_pci_exit;
     k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
@@ -1945,7 +1945,7 @@ static void virtio_blk_pci_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
-    dc->props = virtio_blk_pci_properties;
+    device_class_set_props(dc, virtio_blk_pci_properties);
     k->realize = virtio_blk_pci_realize;
     pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
     pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK;
@@ -2017,7 +2017,7 @@ static void virtio_scsi_pci_class_init(ObjectClass *klass, void *data)
 
     k->realize = virtio_scsi_pci_realize;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
-    dc->props = virtio_scsi_pci_properties;
+    device_class_set_props(dc, virtio_scsi_pci_properties);
     pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
     pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
     pcidev_k->revision = 0x00;
@@ -2072,7 +2072,7 @@ static void vhost_scsi_pci_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
     k->realize = vhost_scsi_pci_realize;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
-    dc->props = vhost_scsi_pci_properties;
+    device_class_set_props(dc, vhost_scsi_pci_properties);
     pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
     pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
     pcidev_k->revision = 0x00;
@@ -2122,7 +2122,7 @@ static void vhost_vsock_pci_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
     k->realize = vhost_vsock_pci_realize;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
-    dc->props = vhost_vsock_pci_properties;
+    device_class_set_props(dc, vhost_vsock_pci_properties);
     pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
     pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_VSOCK;
     pcidev_k->revision = 0x00;
@@ -2174,7 +2174,7 @@ static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
     k->realize = virtio_balloon_pci_realize;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
-    dc->props = virtio_balloon_pci_properties;
+    device_class_set_props(dc, virtio_balloon_pci_properties);
     pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
     pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
     pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
@@ -2252,7 +2252,7 @@ static void virtio_serial_pci_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
     k->realize = virtio_serial_pci_realize;
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-    dc->props = virtio_serial_pci_properties;
+    device_class_set_props(dc, virtio_serial_pci_properties);
     pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
     pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE;
     pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
@@ -2308,7 +2308,7 @@ static void virtio_net_pci_class_init(ObjectClass *klass, void *data)
     k->revision = VIRTIO_PCI_ABI_VERSION;
     k->class_id = PCI_CLASS_NETWORK_ETHERNET;
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
-    dc->props = virtio_net_properties;
+    device_class_set_props(dc, virtio_net_properties);
     vpciklass->realize = virtio_net_pci_realize;
 }
 
@@ -2406,7 +2406,7 @@ static void virtio_input_pci_class_init(ObjectClass *klass, void *data)
     VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
     PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 
-    dc->props = virtio_input_pci_properties;
+    device_class_set_props(dc, virtio_input_pci_properties);
     k->realize = virtio_input_pci_realize;
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index 9639f4e..0ce422e 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -237,7 +237,7 @@ static void virtio_rng_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
 
-    dc->props = virtio_rng_properties;
+    device_class_set_props(dc, virtio_rng_properties);
     dc->vmsd = &vmstate_virtio_rng;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
     vdc->realize = virtio_rng_device_realize;
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index d48d1a9..f089ed8 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2166,7 +2166,7 @@ static void virtio_device_class_init(ObjectClass *klass, void *data)
     dc->realize = virtio_device_realize;
     dc->unrealize = virtio_device_unrealize;
     dc->bus_type = TYPE_VIRTIO_BUS;
-    dc->props = virtio_properties;
+    device_class_set_props(dc, virtio_properties);
 }
 
 static const TypeInfo virtio_device_info = {
diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
index 69a2388..60b8d46 100644
--- a/hw/xen/xen_backend.c
+++ b/hw/xen/xen_backend.c
@@ -877,7 +877,7 @@ static void xen_sysdev_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
     k->init = xen_sysdev_init;
-    dc->props = xen_sysdev_properties;
+    device_class_set_props(dc, xen_sysdev_properties);
 }
 
 static const TypeInfo xensysdev_info = {
diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
index b6d71bb..592dc2b 100644
--- a/hw/xen/xen_pt.c
+++ b/hw/xen/xen_pt.c
@@ -948,7 +948,7 @@ static void xen_pci_passthrough_class_init(ObjectClass *klass, void *data)
     k->config_write = xen_pt_pci_write_config;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
     dc->desc = "Assign an host PCI device with Xen";
-    dc->props = xen_pci_passthrough_properties;
+    device_class_set_props(dc, xen_pci_passthrough_properties);
 };
 
 static void xen_pci_passthrough_finalize(Object *obj)
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 2c97347..6a41308 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -401,6 +401,12 @@ static inline bool qbus_is_hotpluggable(BusState *bus)
    return bus->hotplug_handler;
 }
 
+/* Set list of static properties for class
+ *
+ * It can be called only once per class.
+ */
+void device_class_set_props(DeviceClass *dc, Property *props);
+
 void device_listener_register(DeviceListener *listener);
 void device_listener_unregister(DeviceListener *listener);
 
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 2439ca5..ac8dd5d 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -1531,7 +1531,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
 
     acc->parent_realize = dc->realize;
     dc->realize = arm_cpu_realizefn;
-    dc->props = arm_cpu_properties;
+    device_class_set_props(dc, arm_cpu_properties);
 
     acc->parent_reset = cc->reset;
     cc->reset = arm_cpu_reset;
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 83998a8..ca9eaa5 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1579,7 +1579,7 @@ static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
      * instance_init, because they require KVM to be initialized.
      */
 
-    dc->props = host_x86_cpu_properties;
+    device_class_set_props(dc, host_x86_cpu_properties);
     /* Reason: host_x86_cpu_initfn() dies when !kvm_enabled() */
     dc->cannot_destroy_with_object_finalize_yet = true;
 }
@@ -3651,7 +3651,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
     xcc->parent_unrealize = dc->unrealize;
     dc->realize = x86_cpu_realizefn;
     dc->unrealize = x86_cpu_unrealizefn;
-    dc->props = x86_cpu_properties;
+    device_class_set_props(dc, x86_cpu_properties);
 
     xcc->parent_reset = cc->reset;
     cc->reset = x86_cpu_reset;
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 389c7b6..222b54c 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -269,7 +269,7 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
     cc->get_phys_page_debug = mb_cpu_get_phys_page_debug;
 #endif
     dc->vmsd = &vmstate_mb_cpu;
-    dc->props = mb_properties;
+    device_class_set_props(dc, mb_properties);
     cc->gdb_num_core_regs = 32 + 5;
 
     cc->disas_set_info = mb_disas_set_info;
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 208fa1e..c5d2de7 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8586,7 +8586,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
 
     dc->fw_name = "PowerPC,POWER7";
     dc->desc = "POWER7";
-    dc->props = powerpc_servercpu_properties;
+    device_class_set_props(dc, powerpc_servercpu_properties);
     pcc->pvr_match = ppc_pvr_match_power7;
     pcc->pcr_mask = PCR_VEC_DIS | PCR_VSX_DIS | PCR_COMPAT_2_05;
     pcc->pcr_supported = PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
@@ -8713,7 +8713,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
 
     dc->fw_name = "PowerPC,POWER8";
     dc->desc = "POWER8";
-    dc->props = powerpc_servercpu_properties;
+    device_class_set_props(dc, powerpc_servercpu_properties);
     pcc->pvr_match = ppc_pvr_match_power8;
     pcc->pcr_mask = PCR_TM_DIS | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
     pcc->pcr_supported = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
@@ -8794,7 +8794,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
 
     dc->fw_name = "PowerPC,POWER9";
     dc->desc = "POWER9";
-    dc->props = powerpc_servercpu_properties;
+    device_class_set_props(dc, powerpc_servercpu_properties);
     pcc->pvr_match = ppc_pvr_match_power9;
     pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07;
     pcc->init_proc = init_proc_POWER9;
diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c
index 48e5b73..2e9d6b9 100644
--- a/tests/test-qdev-global-props.c
+++ b/tests/test-qdev-global-props.c
@@ -53,7 +53,7 @@ static void static_prop_class_init(ObjectClass *oc, void *data)
     DeviceClass *dc = DEVICE_CLASS(oc);
 
     dc->realize = NULL;
-    dc->props = static_props;
+    device_class_set_props(dc, static_props);
 }
 
 static const TypeInfo static_prop_type = {
-- 
2.7.4

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

* [Qemu-devel] [PATCH v4 4/8] qdev: Extract property-default code to qdev_property_set_to_default()
  2016-10-29  1:47 [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties Eduardo Habkost
                   ` (2 preceding siblings ...)
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 3/8] qdev: device_class_set_props() function Eduardo Habkost
@ 2016-10-29  1:48 ` Eduardo Habkost
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 5/8] qdev: Register static properties as class properties Eduardo Habkost
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 50+ messages in thread
From: Eduardo Habkost @ 2016-10-29  1:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Markus Armbruster, Andreas Färber, Daniel P. Berrange,
	Igor Mammedov

The code that registers qdev properties will be split from the
code that initializes default values on instance_init, so move it
to a separate function.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes series v1 -> v4:
* (none)
---
 hw/core/qdev.c | 41 +++++++++++++++++++++++++++++------------
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 36ca5e7..85952e8 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -775,6 +775,34 @@ static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
 }
 
 /**
+ * qdev_property_set_to_default:
+ * @dev: Device where the property will be reset
+ * @prop: The qdev property definition
+ * @errp: location to store error information
+ *
+ * Reset the value of property @prop in @dev to its default value.
+ * On error, store error in @errp.
+ */
+static void qdev_property_set_to_default(DeviceState *dev, Property *prop,
+                                         Error **errp)
+{
+    Object *obj = OBJECT(dev);
+
+    if (prop->qtype == QTYPE_NONE) {
+        return;
+    }
+
+    if (prop->qtype == QTYPE_QBOOL) {
+        object_property_set_bool(obj, prop->defval, prop->name, errp);
+    } else if (prop->info->enum_table) {
+        object_property_set_str(obj, prop->info->enum_table[prop->defval],
+                                prop->name, errp);
+    } else if (prop->qtype == QTYPE_QINT) {
+        object_property_set_int(obj, prop->defval, prop->name, errp);
+    }
+}
+
+/**
  * qdev_property_add_static:
  * @dev: Device to add the property to.
  * @prop: The qdev property definition.
@@ -813,18 +841,7 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
                                     prop->info->description,
                                     &error_abort);
 
-    if (prop->qtype == QTYPE_NONE) {
-        return;
-    }
-
-    if (prop->qtype == QTYPE_QBOOL) {
-        object_property_set_bool(obj, prop->defval, prop->name, &error_abort);
-    } else if (prop->info->enum_table) {
-        object_property_set_str(obj, prop->info->enum_table[prop->defval],
-                                prop->name, &error_abort);
-    } else if (prop->qtype == QTYPE_QINT) {
-        object_property_set_int(obj, prop->defval, prop->name, &error_abort);
-    }
+    qdev_property_set_to_default(dev, prop, &error_abort);
 }
 
 /* @qdev_alias_all_properties - Add alias properties to the source object for
-- 
2.7.4

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

* [Qemu-devel] [PATCH v4 5/8] qdev: Register static properties as class properties
  2016-10-29  1:47 [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties Eduardo Habkost
                   ` (3 preceding siblings ...)
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 4/8] qdev: Extract property-default code to qdev_property_set_to_default() Eduardo Habkost
@ 2016-10-29  1:48 ` Eduardo Habkost
  2016-10-31 12:06   ` Igor Mammedov
  2016-11-04 15:22   ` Markus Armbruster
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 6/8] qom: object_class_property_iter_init() function Eduardo Habkost
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 50+ messages in thread
From: Eduardo Habkost @ 2016-10-29  1:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Markus Armbruster, Andreas Färber, Daniel P. Berrange,
	Igor Mammedov

Instead of registering qdev static properties on instance_init,
register them as class properties, at qdev_class_set_props().

qdev_property_add_legacy() was replaced by an equivalent
qdev_class_property_add_legacy() function.
qdev_property_add_static(), on the other hand, can't be
eliminated yet because it is used by arm_cpu_post_init().

As class properties don't have a release function called when an
object instance is destroyed, the release functions for
properties are called manually from device_finalize().

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes series v1 -> v2:
* (none)

Changes v2 -> v3:
* Fix code alignemnt
  * Reported-by: Igor Mammedov <imammedo@redhat.com>

Changes series v3 -> v4:
* s/Device/Class/ on qdev_class_property_add_legacy() doc comment
  * Reported-by: Igor Mammedov <imammedo@redhat.com>
* Call prop->info->release on instance_finalize (fix
  tests/drive_del-test failure)
---
 hw/core/qdev.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 69 insertions(+), 13 deletions(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 85952e8..e695fa8 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -739,12 +739,12 @@ static void qdev_get_legacy_property(Object *obj, Visitor *v,
 }
 
 /**
- * qdev_property_add_legacy:
- * @dev: Device to add the property to.
+ * qdev_class_property_add_legacy:
+ * @oc: Class to add the property to.
  * @prop: The qdev property definition.
  * @errp: location to store error information.
  *
- * Add a legacy QOM property to @dev for qdev property @prop.
+ * Add a legacy QOM property to @oc for qdev property @prop.
  * On error, store error in @errp.
  *
  * Legacy properties are string versions of QOM properties.  The format of
@@ -754,8 +754,8 @@ static void qdev_get_legacy_property(Object *obj, Visitor *v,
  * Do not use this is new code!  QOM Properties added through this interface
  * will be given names in the "legacy" namespace.
  */
-static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
-                                     Error **errp)
+static void qdev_class_property_add_legacy(ObjectClass *oc, Property *prop,
+                                           Error **errp)
 {
     gchar *name;
 
@@ -765,11 +765,12 @@ static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
     }
 
     name = g_strdup_printf("legacy-%s", prop->name);
-    object_property_add(OBJECT(dev), name, "str",
-                        prop->info->print ? qdev_get_legacy_property : prop->info->get,
-                        NULL,
-                        NULL,
-                        prop, errp);
+    object_class_property_add(oc, name, "str",
+                              prop->info->print ?
+                                  qdev_get_legacy_property :
+                                  prop->info->get,
+                              NULL, NULL,
+                              prop, errp);
 
     g_free(name);
 }
@@ -844,6 +845,48 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
     qdev_property_set_to_default(dev, prop, &error_abort);
 }
 
+/**
+ * qdev_class_property_add_static:
+ * @oc: Class to add the property to.
+ * @prop: The qdev property definition.
+ * @errp: location to store error information.
+ *
+ * Add a static QOM property to @oc for qdev property @prop.
+ * On error, store error in @errp.  Static properties access data in a struct.
+ * The type of the QOM property is derived from prop->info.
+ */
+static void qdev_class_property_add_static(ObjectClass *oc, Property *prop,
+                                           Error **errp)
+{
+    Error *local_err = NULL;
+
+    /*
+     * TODO qdev_prop_ptr does not have getters or setters.  It must
+     * go now that it can be replaced with links.  The test should be
+     * removed along with it: all static properties are read/write.
+     */
+    if (!prop->info->get && !prop->info->set) {
+        return;
+    }
+
+    /* Note: prop->info->release is called on device_finalize(),
+     * because it needs to be called on instaqnce destruction, not on
+     * class property removal.
+     */
+    object_class_property_add(oc, prop->name, prop->info->name,
+                              prop->info->get, prop->info->set,
+                              NULL, prop, &local_err);
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    object_class_property_set_description(oc, prop->name,
+                                          prop->info->description,
+                                          &error_abort);
+}
+
 /* @qdev_alias_all_properties - Add alias properties to the source object for
  * all qdev properties on the target DeviceState.
  */
@@ -867,8 +910,15 @@ void qdev_alias_all_properties(DeviceState *target, Object *source)
 
 void device_class_set_props(DeviceClass *dc, Property *props)
 {
+    Property *prop;
+    ObjectClass *oc = OBJECT_CLASS(dc);
+
     assert(!dc->props);
     dc->props = props;
+    for (prop = dc->props; prop && prop->name; prop++) {
+        qdev_class_property_add_legacy(oc, prop, &error_abort);
+        qdev_class_property_add_static(oc, prop, &error_abort);
+    }
 }
 
 static int qdev_add_hotpluggable_device(Object *obj, void *opaque)
@@ -1068,8 +1118,7 @@ static void device_initfn(Object *obj)
     class = object_get_class(OBJECT(dev));
     do {
         for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
-            qdev_property_add_legacy(dev, prop, &error_abort);
-            qdev_property_add_static(dev, prop, &error_abort);
+            qdev_property_set_to_default(dev, prop, &error_abort);
         }
         class = object_class_get_parent(class);
     } while (class != object_class_by_name(TYPE_DEVICE));
@@ -1088,9 +1137,16 @@ static void device_post_init(Object *obj)
 /* Unlink device from bus and free the structure.  */
 static void device_finalize(Object *obj)
 {
+    DeviceState *dev = DEVICE(obj);
+    DeviceClass *dc = DEVICE_GET_CLASS(dev);
+    Property *prop;
     NamedGPIOList *ngl, *next;
 
-    DeviceState *dev = DEVICE(obj);
+    for (prop = dc->props; prop && prop->name; prop++) {
+        if (prop->info->release) {
+            prop->info->release(obj, prop->name, prop);
+        }
+    }
 
     QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) {
         QLIST_REMOVE(ngl, node);
-- 
2.7.4

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

* [Qemu-devel] [PATCH v4 6/8] qom: object_class_property_iter_init() function
  2016-10-29  1:47 [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties Eduardo Habkost
                   ` (4 preceding siblings ...)
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 5/8] qdev: Register static properties as class properties Eduardo Habkost
@ 2016-10-29  1:48 ` Eduardo Habkost
  2016-10-31 13:45   ` Igor Mammedov
  2016-11-04 15:31   ` Markus Armbruster
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties Eduardo Habkost
                   ` (2 subsequent siblings)
  8 siblings, 2 replies; 50+ messages in thread
From: Eduardo Habkost @ 2016-10-29  1:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Markus Armbruster, Andreas Färber, Daniel P. Berrange,
	Igor Mammedov

The new function will allow us to iterate over class properties
using the same logic we use for object properties. Unit test
included.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes series v1 -> v3:
* (none)

Changes series v3 -> v4:
* Trivial whitespace change (removed extra newline)
---
 include/qom/object.h       | 14 ++++++++++++++
 qom/object.c               | 10 ++++++++--
 tests/check-qom-proplist.c | 28 ++++++++++++++++++++++++++++
 3 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/include/qom/object.h b/include/qom/object.h
index 5ecc2d1..6e3646e 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -995,6 +995,20 @@ void object_property_iter_init(ObjectPropertyIterator *iter,
                                Object *obj);
 
 /**
+ * object_class_property_iter_init:
+ * @klass: the class
+ *
+ * Initializes an iterator for traversing all properties
+ * registered against an object class and all parent classes.
+ *
+ * It is forbidden to modify the property list while iterating,
+ * whether removing or adding properties.
+ */
+void object_class_property_iter_init(ObjectPropertyIterator *iter,
+                                     ObjectClass *klass);
+
+
+/**
  * object_property_iter_next:
  * @iter: the iterator instance
  *
diff --git a/qom/object.c b/qom/object.c
index 7a05e35..0cbe228 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1010,6 +1010,13 @@ void object_property_iter_init(ObjectPropertyIterator *iter,
     iter->nextclass = object_get_class(obj);
 }
 
+void object_class_property_iter_init(ObjectPropertyIterator *iter,
+                                     ObjectClass *klass)
+{
+    g_hash_table_iter_init(&iter->iter, klass->properties);
+    iter->nextclass = object_class_get_parent(klass);
+}
+
 ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
 {
     gpointer key, val;
@@ -1017,8 +1024,7 @@ ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
         if (!iter->nextclass) {
             return NULL;
         }
-        g_hash_table_iter_init(&iter->iter, iter->nextclass->properties);
-        iter->nextclass = object_class_get_parent(iter->nextclass);
+        object_class_property_iter_init(iter, iter->nextclass);
     }
     return val;
 }
diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
index 766a4a1..9536415 100644
--- a/tests/check-qom-proplist.c
+++ b/tests/check-qom-proplist.c
@@ -496,6 +496,33 @@ static void test_dummy_iterator(void)
 }
 
 
+static void test_dummy_class_iterator(void)
+{
+    ObjectClass *klass = object_class_by_name(TYPE_DUMMY);
+    ObjectProperty *prop;
+    ObjectPropertyIterator iter;
+    bool seensv = false, seenav = false, seentype;
+
+    object_class_property_iter_init(&iter, klass);
+    while ((prop = object_property_iter_next(&iter))) {
+        if (g_str_equal(prop->name, "sv")) {
+            seensv = true;
+        } else if (g_str_equal(prop->name, "av")) {
+            seenav = true;
+        } else if (g_str_equal(prop->name, "type")) {
+            /* This prop comes from the base Object class */
+            seentype = true;
+        } else {
+            g_printerr("Found prop '%s'\n", prop->name);
+            g_assert_not_reached();
+        }
+    }
+    g_assert(seenav);
+    g_assert(seensv);
+    g_assert(seentype);
+}
+
+
 static void test_dummy_delchild(void)
 {
     Object *parent = object_get_objects_root();
@@ -524,6 +551,7 @@ int main(int argc, char **argv)
     g_test_add_func("/qom/proplist/badenum", test_dummy_badenum);
     g_test_add_func("/qom/proplist/getenum", test_dummy_getenum);
     g_test_add_func("/qom/proplist/iterator", test_dummy_iterator);
+    g_test_add_func("/qom/proplist/class_iterator", test_dummy_class_iterator);
     g_test_add_func("/qom/proplist/delchild", test_dummy_delchild);
 
     return g_test_run();
-- 
2.7.4

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

* [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-10-29  1:47 [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties Eduardo Habkost
                   ` (5 preceding siblings ...)
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 6/8] qom: object_class_property_iter_init() function Eduardo Habkost
@ 2016-10-29  1:48 ` Eduardo Habkost
  2016-10-31 14:07   ` Igor Mammedov
  2016-11-07 12:45   ` Halil Pasic
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 8/8] qdev: Warning about using qdev_property_add_static() in new code Eduardo Habkost
  2016-11-04 15:52 ` [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties Markus Armbruster
  8 siblings, 2 replies; 50+ messages in thread
From: Eduardo Habkost @ 2016-10-29  1:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Markus Armbruster, Andreas Färber, Daniel P. Berrange,
	Igor Mammedov

When an abstract class is used on device-list-properties, we can
simply return the class properties registered for the class.

This will be useful if management software needs to query for
supported options that apply to all devices of a given type (e.g.
options supported by all CPU models, options supported by all PCI
devices).

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes series v1 -> v2:
* (none)

Changes series v2 -> v3:
* Reworded commit message

Changes series v3 -> v4:
* (none)
---
 qmp.c | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/qmp.c b/qmp.c
index a06cb7b..1e7e60d 100644
--- a/qmp.c
+++ b/qmp.c
@@ -518,7 +518,7 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
                                                    Error **errp)
 {
     ObjectClass *klass;
-    Object *obj;
+    Object *obj = NULL;
     ObjectProperty *prop;
     ObjectPropertyIterator iter;
     DevicePropertyInfoList *prop_list = NULL;
@@ -537,19 +537,16 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
     }
 
     if (object_class_is_abstract(klass)) {
-        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "name",
-                   "non-abstract device type");
-        return NULL;
-    }
-
-    if (DEVICE_CLASS(klass)->cannot_destroy_with_object_finalize_yet) {
-        error_setg(errp, "Can't list properties of device '%s'", typename);
-        return NULL;
+        object_class_property_iter_init(&iter, klass);
+    } else {
+        if (DEVICE_CLASS(klass)->cannot_destroy_with_object_finalize_yet) {
+            error_setg(errp, "Can't list properties of device '%s'", typename);
+            return NULL;
+        }
+        obj = object_new(typename);
+        object_property_iter_init(&iter, obj);
     }
 
-    obj = object_new(typename);
-
-    object_property_iter_init(&iter, obj);
     while ((prop = object_property_iter_next(&iter))) {
         DevicePropertyInfo *info;
         DevicePropertyInfoList *entry;
-- 
2.7.4

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

* [Qemu-devel] [PATCH v4 8/8] qdev: Warning about using qdev_property_add_static() in new code
  2016-10-29  1:47 [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties Eduardo Habkost
                   ` (6 preceding siblings ...)
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties Eduardo Habkost
@ 2016-10-29  1:48 ` Eduardo Habkost
  2016-10-31 14:05   ` Igor Mammedov
  2016-11-04 15:52 ` [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties Markus Armbruster
  8 siblings, 1 reply; 50+ messages in thread
From: Eduardo Habkost @ 2016-10-29  1:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Markus Armbruster, Andreas Färber, Daniel P. Berrange,
	Igor Mammedov, Peter Maydell, qemu-arm

The only remaining user of qdev_property_add_static() is
arm_cpu_post_init(), but removing it may take some work. While we
don't change it, warn people to not use the function in new code.

Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: qemu-arm@nongnu.org
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes series v1 -> v3:
* (none)

Changes series v3 -> v4:
* Rewrote commit message to refer to correct function name
* s/qdev_class_set_props/device_class_set_props/ (function had
  been renamed in series v3)
---
 hw/core/qdev.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index e695fa8..ae772fc 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -812,6 +812,10 @@ static void qdev_property_set_to_default(DeviceState *dev, Property *prop,
  * Add a static QOM property to @dev for qdev property @prop.
  * On error, store error in @errp.  Static properties access data in a struct.
  * The type of the QOM property is derived from prop->info.
+ *
+ * Do not use this in new code. Either use device_class_set_props(),
+ * or register regular QOM properties using object_property_add() or
+ * object_class_property_add().
  */
 void qdev_property_add_static(DeviceState *dev, Property *prop,
                               Error **errp)
-- 
2.7.4

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

* Re: [Qemu-devel] [PATCH v4 2/8] tests: check-qom-proplist: Use &error_abort to catch errors
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 2/8] tests: check-qom-proplist: Use &error_abort to catch errors Eduardo Habkost
@ 2016-10-31 10:14   ` Igor Mammedov
  0 siblings, 0 replies; 50+ messages in thread
From: Igor Mammedov @ 2016-10-31 10:14 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: qemu-devel, Markus Armbruster, Andreas Färber, Daniel P. Berrange

On Fri, 28 Oct 2016 23:48:01 -0200
Eduardo Habkost <ehabkost@redhat.com> wrote:

> Use &error_abort so we don't ignore any errors on the property
> registration calls.
> 
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> Changes series v2 -> v3:
> * Patch imported from "tests: A few check-qom-proplist fixes"
>   series
> 
> Changes series v3 -> v4:
> * Added &error_abort to more object_property_{add,del}_*()
>   calls
>   * Suggested-by: Igor Mammedov <imammedo@redhat.com>
> ---
>  tests/check-qom-proplist.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
> index 693dc4c..766a4a1 100644
> --- a/tests/check-qom-proplist.c
> +++ b/tests/check-qom-proplist.c
> @@ -123,7 +123,7 @@ static void dummy_init(Object *obj)
>      object_property_add_bool(obj, "bv",
>                               dummy_get_bv,
>                               dummy_set_bv,
> -                             NULL);
> +                             &error_abort);
>  }
>  
>  
> @@ -132,13 +132,13 @@ static void dummy_class_init(ObjectClass *cls, void *data)
>      object_class_property_add_str(cls, "sv",
>                                    dummy_get_sv,
>                                    dummy_set_sv,
> -                                  NULL);
> +                                  &error_abort);
>      object_class_property_add_enum(cls, "av",
>                                     "DummyAnimal",
>                                     dummy_animal_map,
>                                     dummy_get_av,
>                                     dummy_set_av,
> -                                   NULL);
> +                                   &error_abort);
>  }
>  
>  
> @@ -239,13 +239,13 @@ static void dummy_dev_init(Object *obj)
>      DummyBus *bus = DUMMY_BUS(object_new(TYPE_DUMMY_BUS));
>      DummyBackend *backend = DUMMY_BACKEND(object_new(TYPE_DUMMY_BACKEND));
>  
> -    object_property_add_child(obj, "bus", OBJECT(bus), NULL);
> +    object_property_add_child(obj, "bus", OBJECT(bus), &error_abort);
>      dev->bus = bus;
> -    object_property_add_child(OBJECT(bus), "backend", OBJECT(backend), NULL);
> +    object_property_add_child(OBJECT(bus), "backend", OBJECT(backend), &error_abort);
looks like line is over 80 characters

with that fixed
Reviewed-by: Igor Mammedov <imammedo@redhat.com>

>      bus->backend = backend;
>  
>      object_property_add_link(obj, "backend", TYPE_DUMMY_BACKEND,
> -                             (Object **)&bus->backend, NULL, 0, NULL);
> +                             (Object **)&bus->backend, NULL, 0, &error_abort);
>  }
>  
>  static void dummy_dev_unparent(Object *obj)
> @@ -274,7 +274,7 @@ static void dummy_bus_init(Object *obj)
>  static void dummy_bus_unparent(Object *obj)
>  {
>      DummyBus *bus = DUMMY_BUS(obj);
> -    object_property_del(obj->parent, "backend", NULL);
> +    object_property_del(obj->parent, "backend", &error_abort);
>      object_unparent(OBJECT(bus->backend));
>  }
>  

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

* Re: [Qemu-devel] [PATCH v4 5/8] qdev: Register static properties as class properties
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 5/8] qdev: Register static properties as class properties Eduardo Habkost
@ 2016-10-31 12:06   ` Igor Mammedov
  2016-11-04 15:22   ` Markus Armbruster
  1 sibling, 0 replies; 50+ messages in thread
From: Igor Mammedov @ 2016-10-31 12:06 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: qemu-devel, Markus Armbruster, Andreas Färber, Daniel P. Berrange

On Fri, 28 Oct 2016 23:48:04 -0200
Eduardo Habkost <ehabkost@redhat.com> wrote:

> Instead of registering qdev static properties on instance_init,
> register them as class properties, at qdev_class_set_props().
> 
> qdev_property_add_legacy() was replaced by an equivalent
> qdev_class_property_add_legacy() function.
> qdev_property_add_static(), on the other hand, can't be
> eliminated yet because it is used by arm_cpu_post_init().
> 
> As class properties don't have a release function called when an
> object instance is destroyed, the release functions for
> properties are called manually from device_finalize().
> 
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> Changes series v1 -> v2:
> * (none)
> 
> Changes v2 -> v3:
> * Fix code alignemnt
>   * Reported-by: Igor Mammedov <imammedo@redhat.com>
> 
> Changes series v3 -> v4:
> * s/Device/Class/ on qdev_class_property_add_legacy() doc comment
>   * Reported-by: Igor Mammedov <imammedo@redhat.com>
> * Call prop->info->release on instance_finalize (fix
>   tests/drive_del-test failure)
> ---
>  hw/core/qdev.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++----------
>  1 file changed, 69 insertions(+), 13 deletions(-)
> 
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 85952e8..e695fa8 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -739,12 +739,12 @@ static void qdev_get_legacy_property(Object *obj, Visitor *v,
>  }
>  
>  /**
> - * qdev_property_add_legacy:
> - * @dev: Device to add the property to.
> + * qdev_class_property_add_legacy:
> + * @oc: Class to add the property to.
>   * @prop: The qdev property definition.
>   * @errp: location to store error information.
>   *
> - * Add a legacy QOM property to @dev for qdev property @prop.
> + * Add a legacy QOM property to @oc for qdev property @prop.
>   * On error, store error in @errp.
>   *
>   * Legacy properties are string versions of QOM properties.  The format of
> @@ -754,8 +754,8 @@ static void qdev_get_legacy_property(Object *obj, Visitor *v,
>   * Do not use this is new code!  QOM Properties added through this interface
>   * will be given names in the "legacy" namespace.
>   */
> -static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
> -                                     Error **errp)
> +static void qdev_class_property_add_legacy(ObjectClass *oc, Property *prop,
> +                                           Error **errp)
>  {
>      gchar *name;
>  
> @@ -765,11 +765,12 @@ static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
>      }
>  
>      name = g_strdup_printf("legacy-%s", prop->name);
> -    object_property_add(OBJECT(dev), name, "str",
> -                        prop->info->print ? qdev_get_legacy_property : prop->info->get,
> -                        NULL,
> -                        NULL,
> -                        prop, errp);
> +    object_class_property_add(oc, name, "str",
> +                              prop->info->print ?
> +                                  qdev_get_legacy_property :
> +                                  prop->info->get,
> +                              NULL, NULL,
> +                              prop, errp);
>  
>      g_free(name);
>  }
> @@ -844,6 +845,48 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
>      qdev_property_set_to_default(dev, prop, &error_abort);
>  }
>  
> +/**
> + * qdev_class_property_add_static:
> + * @oc: Class to add the property to.
> + * @prop: The qdev property definition.
> + * @errp: location to store error information.
> + *
> + * Add a static QOM property to @oc for qdev property @prop.
> + * On error, store error in @errp.  Static properties access data in a struct.
> + * The type of the QOM property is derived from prop->info.
> + */
> +static void qdev_class_property_add_static(ObjectClass *oc, Property *prop,
> +                                           Error **errp)
> +{
> +    Error *local_err = NULL;
> +
> +    /*
> +     * TODO qdev_prop_ptr does not have getters or setters.  It must
> +     * go now that it can be replaced with links.  The test should be
> +     * removed along with it: all static properties are read/write.
> +     */
> +    if (!prop->info->get && !prop->info->set) {
> +        return;
> +    }
> +
> +    /* Note: prop->info->release is called on device_finalize(),
> +     * because it needs to be called on instaqnce destruction, not on
s/instaqnce/instance/

with this fixed:
Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> +     * class property removal.
> +     */
> +    object_class_property_add(oc, prop->name, prop->info->name,
> +                              prop->info->get, prop->info->set,
> +                              NULL, prop, &local_err);
> +
> +    if (local_err) {
> +        error_propagate(errp, local_err);
> +        return;
> +    }
> +
> +    object_class_property_set_description(oc, prop->name,
> +                                          prop->info->description,
> +                                          &error_abort);
> +}
> +
>  /* @qdev_alias_all_properties - Add alias properties to the source object for
>   * all qdev properties on the target DeviceState.
>   */
> @@ -867,8 +910,15 @@ void qdev_alias_all_properties(DeviceState *target, Object *source)
>  
>  void device_class_set_props(DeviceClass *dc, Property *props)
>  {
> +    Property *prop;
> +    ObjectClass *oc = OBJECT_CLASS(dc);
> +
>      assert(!dc->props);
>      dc->props = props;
> +    for (prop = dc->props; prop && prop->name; prop++) {
> +        qdev_class_property_add_legacy(oc, prop, &error_abort);
> +        qdev_class_property_add_static(oc, prop, &error_abort);
> +    }
>  }
>  
>  static int qdev_add_hotpluggable_device(Object *obj, void *opaque)
> @@ -1068,8 +1118,7 @@ static void device_initfn(Object *obj)
>      class = object_get_class(OBJECT(dev));
>      do {
>          for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
> -            qdev_property_add_legacy(dev, prop, &error_abort);
> -            qdev_property_add_static(dev, prop, &error_abort);
> +            qdev_property_set_to_default(dev, prop, &error_abort);
>          }
>          class = object_class_get_parent(class);
>      } while (class != object_class_by_name(TYPE_DEVICE));
> @@ -1088,9 +1137,16 @@ static void device_post_init(Object *obj)
>  /* Unlink device from bus and free the structure.  */
>  static void device_finalize(Object *obj)
>  {
> +    DeviceState *dev = DEVICE(obj);
> +    DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +    Property *prop;
>      NamedGPIOList *ngl, *next;
>  
> -    DeviceState *dev = DEVICE(obj);
> +    for (prop = dc->props; prop && prop->name; prop++) {
> +        if (prop->info->release) {
> +            prop->info->release(obj, prop->name, prop);
> +        }
> +    }
>  
>      QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) {
>          QLIST_REMOVE(ngl, node);

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

* Re: [Qemu-devel] [PATCH v4 6/8] qom: object_class_property_iter_init() function
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 6/8] qom: object_class_property_iter_init() function Eduardo Habkost
@ 2016-10-31 13:45   ` Igor Mammedov
  2016-11-04 15:31   ` Markus Armbruster
  1 sibling, 0 replies; 50+ messages in thread
From: Igor Mammedov @ 2016-10-31 13:45 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: qemu-devel, Markus Armbruster, Andreas Färber, Daniel P. Berrange

On Fri, 28 Oct 2016 23:48:05 -0200
Eduardo Habkost <ehabkost@redhat.com> wrote:

> The new function will allow us to iterate over class properties
> using the same logic we use for object properties. Unit test
> included.
> 
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
> Changes series v1 -> v3:
> * (none)
> 
> Changes series v3 -> v4:
> * Trivial whitespace change (removed extra newline)
> ---
>  include/qom/object.h       | 14 ++++++++++++++
>  qom/object.c               | 10 ++++++++--
>  tests/check-qom-proplist.c | 28 ++++++++++++++++++++++++++++
>  3 files changed, 50 insertions(+), 2 deletions(-)
> 
> diff --git a/include/qom/object.h b/include/qom/object.h
> index 5ecc2d1..6e3646e 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -995,6 +995,20 @@ void object_property_iter_init(ObjectPropertyIterator *iter,
>                                 Object *obj);
>  
>  /**
> + * object_class_property_iter_init:
> + * @klass: the class
> + *
> + * Initializes an iterator for traversing all properties
> + * registered against an object class and all parent classes.
> + *
> + * It is forbidden to modify the property list while iterating,
> + * whether removing or adding properties.
> + */
> +void object_class_property_iter_init(ObjectPropertyIterator *iter,
> +                                     ObjectClass *klass);
> +
> +
> +/**
>   * object_property_iter_next:
>   * @iter: the iterator instance
>   *
> diff --git a/qom/object.c b/qom/object.c
> index 7a05e35..0cbe228 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -1010,6 +1010,13 @@ void object_property_iter_init(ObjectPropertyIterator *iter,
>      iter->nextclass = object_get_class(obj);
>  }
>  
> +void object_class_property_iter_init(ObjectPropertyIterator *iter,
> +                                     ObjectClass *klass)
> +{
> +    g_hash_table_iter_init(&iter->iter, klass->properties);
> +    iter->nextclass = object_class_get_parent(klass);
> +}
> +
>  ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
>  {
>      gpointer key, val;
> @@ -1017,8 +1024,7 @@ ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
>          if (!iter->nextclass) {
>              return NULL;
>          }
> -        g_hash_table_iter_init(&iter->iter, iter->nextclass->properties);
> -        iter->nextclass = object_class_get_parent(iter->nextclass);
> +        object_class_property_iter_init(iter, iter->nextclass);
>      }
>      return val;
>  }
> diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
> index 766a4a1..9536415 100644
> --- a/tests/check-qom-proplist.c
> +++ b/tests/check-qom-proplist.c
> @@ -496,6 +496,33 @@ static void test_dummy_iterator(void)
>  }
>  
>  
> +static void test_dummy_class_iterator(void)
> +{
> +    ObjectClass *klass = object_class_by_name(TYPE_DUMMY);
> +    ObjectProperty *prop;
> +    ObjectPropertyIterator iter;
> +    bool seensv = false, seenav = false, seentype;
> +
> +    object_class_property_iter_init(&iter, klass);
> +    while ((prop = object_property_iter_next(&iter))) {
> +        if (g_str_equal(prop->name, "sv")) {
> +            seensv = true;
> +        } else if (g_str_equal(prop->name, "av")) {
> +            seenav = true;
> +        } else if (g_str_equal(prop->name, "type")) {
> +            /* This prop comes from the base Object class */
> +            seentype = true;
> +        } else {
> +            g_printerr("Found prop '%s'\n", prop->name);
> +            g_assert_not_reached();
> +        }
> +    }
> +    g_assert(seenav);
> +    g_assert(seensv);
> +    g_assert(seentype);
> +}
> +
> +
>  static void test_dummy_delchild(void)
>  {
>      Object *parent = object_get_objects_root();
> @@ -524,6 +551,7 @@ int main(int argc, char **argv)
>      g_test_add_func("/qom/proplist/badenum", test_dummy_badenum);
>      g_test_add_func("/qom/proplist/getenum", test_dummy_getenum);
>      g_test_add_func("/qom/proplist/iterator", test_dummy_iterator);
> +    g_test_add_func("/qom/proplist/class_iterator", test_dummy_class_iterator);
>      g_test_add_func("/qom/proplist/delchild", test_dummy_delchild);
>  
>      return g_test_run();

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

* Re: [Qemu-devel] [PATCH v4 8/8] qdev: Warning about using qdev_property_add_static() in new code
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 8/8] qdev: Warning about using qdev_property_add_static() in new code Eduardo Habkost
@ 2016-10-31 14:05   ` Igor Mammedov
  0 siblings, 0 replies; 50+ messages in thread
From: Igor Mammedov @ 2016-10-31 14:05 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: qemu-devel, Markus Armbruster, Andreas Färber,
	Daniel P. Berrange, Peter Maydell, qemu-arm

On Fri, 28 Oct 2016 23:48:07 -0200
Eduardo Habkost <ehabkost@redhat.com> wrote:

> The only remaining user of qdev_property_add_static() is
> arm_cpu_post_init(), but removing it may take some work. While we
> don't change it, warn people to not use the function in new code.
> 
> Cc: Peter Maydell <peter.maydell@linaro.org>
> Cc: qemu-arm@nongnu.org
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
> Changes series v1 -> v3:
> * (none)
> 
> Changes series v3 -> v4:
> * Rewrote commit message to refer to correct function name
> * s/qdev_class_set_props/device_class_set_props/ (function had
>   been renamed in series v3)
> ---
>  hw/core/qdev.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index e695fa8..ae772fc 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -812,6 +812,10 @@ static void qdev_property_set_to_default(DeviceState *dev, Property *prop,
>   * Add a static QOM property to @dev for qdev property @prop.
>   * On error, store error in @errp.  Static properties access data in a struct.
>   * The type of the QOM property is derived from prop->info.
> + *
> + * Do not use this in new code. Either use device_class_set_props(),
> + * or register regular QOM properties using object_property_add() or
> + * object_class_property_add().
>   */
>  void qdev_property_add_static(DeviceState *dev, Property *prop,
>                                Error **errp)

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties Eduardo Habkost
@ 2016-10-31 14:07   ` Igor Mammedov
  2016-10-31 14:36     ` Eduardo Habkost
  2016-11-07 12:45   ` Halil Pasic
  1 sibling, 1 reply; 50+ messages in thread
From: Igor Mammedov @ 2016-10-31 14:07 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: qemu-devel, Markus Armbruster, Andreas Färber, Daniel P. Berrange

On Fri, 28 Oct 2016 23:48:06 -0200
Eduardo Habkost <ehabkost@redhat.com> wrote:

> When an abstract class is used on device-list-properties, we can
> simply return the class properties registered for the class.
> 
> This will be useful if management software needs to query for
> supported options that apply to all devices of a given type (e.g.
> options supported by all CPU models, options supported by all PCI
> devices).
Patch looks fine to me but I'm not qmp interface guru
so I'd leave review up to maintainers.

One question though,
How would management software discover typename of abstract class?

Perhaps this patch should be part of some other series.

> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> Changes series v1 -> v2:
> * (none)
> 
> Changes series v2 -> v3:
> * Reworded commit message
> 
> Changes series v3 -> v4:
> * (none)
> ---
>  qmp.c | 21 +++++++++------------
>  1 file changed, 9 insertions(+), 12 deletions(-)
> 
> diff --git a/qmp.c b/qmp.c
> index a06cb7b..1e7e60d 100644
> --- a/qmp.c
> +++ b/qmp.c
> @@ -518,7 +518,7 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
>                                                     Error **errp)
>  {
>      ObjectClass *klass;
> -    Object *obj;
> +    Object *obj = NULL;
>      ObjectProperty *prop;
>      ObjectPropertyIterator iter;
>      DevicePropertyInfoList *prop_list = NULL;
> @@ -537,19 +537,16 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
>      }
>  
>      if (object_class_is_abstract(klass)) {
> -        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "name",
> -                   "non-abstract device type");
> -        return NULL;
> -    }
> -
> -    if (DEVICE_CLASS(klass)->cannot_destroy_with_object_finalize_yet) {
> -        error_setg(errp, "Can't list properties of device '%s'", typename);
> -        return NULL;
> +        object_class_property_iter_init(&iter, klass);
> +    } else {
> +        if (DEVICE_CLASS(klass)->cannot_destroy_with_object_finalize_yet) {
> +            error_setg(errp, "Can't list properties of device '%s'", typename);
> +            return NULL;
> +        }
> +        obj = object_new(typename);
> +        object_property_iter_init(&iter, obj);
>      }
>  
> -    obj = object_new(typename);
> -
> -    object_property_iter_init(&iter, obj);
>      while ((prop = object_property_iter_next(&iter))) {
>          DevicePropertyInfo *info;
>          DevicePropertyInfoList *entry;

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-10-31 14:07   ` Igor Mammedov
@ 2016-10-31 14:36     ` Eduardo Habkost
  2016-11-04 15:45       ` Markus Armbruster
  0 siblings, 1 reply; 50+ messages in thread
From: Eduardo Habkost @ 2016-10-31 14:36 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: qemu-devel, Markus Armbruster, Andreas Färber,
	Daniel P. Berrange, libvir-list, Jiri Denemark

(CCing libvirt people, as I forgot to CC them)

On Mon, Oct 31, 2016 at 03:07:23PM +0100, Igor Mammedov wrote:
> On Fri, 28 Oct 2016 23:48:06 -0200
> Eduardo Habkost <ehabkost@redhat.com> wrote:
> 
> > When an abstract class is used on device-list-properties, we can
> > simply return the class properties registered for the class.
> > 
> > This will be useful if management software needs to query for
> > supported options that apply to all devices of a given type (e.g.
> > options supported by all CPU models, options supported by all PCI
> > devices).
> Patch looks fine to me but I'm not qmp interface guru
> so I'd leave review up to maintainers.
> 
> One question though,
> How would management software discover typename of abstract class?

It depends on the use case. On some cases, management may already
have bus-specific logic that will know what's the base type it
needs to query (e.g. it may query "pci-device" to find out if all
PCI devices support a given option). On other cases, it may be
discovered using other commands.

For the CPU case, I will propose adding the base QOM CPU typename
in the query-target command.

> 
> Perhaps this patch should be part of some other series.

This is a valid point. In this case, it depends on the approach
we want to take: do we want to provide a flexible interface for
management, let them find ways to make it useful and give us
feedback on what is lacking; or do we want to provide the new
interface only after we have specified the complete solution for
the problem?

I don't know the answer. I will let the qdev/QOM/QMP maintainers
answer that.

> 
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > ---
> > Changes series v1 -> v2:
> > * (none)
> > 
> > Changes series v2 -> v3:
> > * Reworded commit message
> > 
> > Changes series v3 -> v4:
> > * (none)
> > ---
> >  qmp.c | 21 +++++++++------------
> >  1 file changed, 9 insertions(+), 12 deletions(-)
> > 
> > diff --git a/qmp.c b/qmp.c
> > index a06cb7b..1e7e60d 100644
> > --- a/qmp.c
> > +++ b/qmp.c
> > @@ -518,7 +518,7 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
> >                                                     Error **errp)
> >  {
> >      ObjectClass *klass;
> > -    Object *obj;
> > +    Object *obj = NULL;
> >      ObjectProperty *prop;
> >      ObjectPropertyIterator iter;
> >      DevicePropertyInfoList *prop_list = NULL;
> > @@ -537,19 +537,16 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
> >      }
> >  
> >      if (object_class_is_abstract(klass)) {
> > -        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "name",
> > -                   "non-abstract device type");
> > -        return NULL;
> > -    }
> > -
> > -    if (DEVICE_CLASS(klass)->cannot_destroy_with_object_finalize_yet) {
> > -        error_setg(errp, "Can't list properties of device '%s'", typename);
> > -        return NULL;
> > +        object_class_property_iter_init(&iter, klass);
> > +    } else {
> > +        if (DEVICE_CLASS(klass)->cannot_destroy_with_object_finalize_yet) {
> > +            error_setg(errp, "Can't list properties of device '%s'", typename);
> > +            return NULL;
> > +        }
> > +        obj = object_new(typename);
> > +        object_property_iter_init(&iter, obj);
> >      }
> >  
> > -    obj = object_new(typename);
> > -
> > -    object_property_iter_init(&iter, obj);
> >      while ((prop = object_property_iter_next(&iter))) {
> >          DevicePropertyInfo *info;
> >          DevicePropertyInfoList *entry;
> 

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v4 3/8] qdev: device_class_set_props() function
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 3/8] qdev: device_class_set_props() function Eduardo Habkost
@ 2016-11-01 15:02   ` Igor Mammedov
  0 siblings, 0 replies; 50+ messages in thread
From: Igor Mammedov @ 2016-11-01 15:02 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: qemu-devel, Markus Armbruster, Andreas Färber, Daniel P. Berrange

On Fri, 28 Oct 2016 23:48:02 -0200
Eduardo Habkost <ehabkost@redhat.com> wrote:

> Replace direct assignment of DeviceClass::props with a
> device_class_set_props() function. The new function will handle
> registration of class properties, later.
> 
> Most of the existing code was converted using the Coccinelle
> patch below. Exceptions are:
> * manual conversion of target-ppc/translate_init.c;
> * reordering of code at e1000e_class_init() to ensure
>   device_class_set_props() is called after initialization
>   of the PropertyInfo structs.
> 
> Coccinelle patch:
> 
>   @@
>   identifier DC;
>   expression PROPS;
>   typedef DeviceClass;
>   @@
>    DeviceClass *DC;
>    ...
>   -DC->props = PROPS;
>   +device_class_set_props(DC, PROPS);
> 
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
> Changes v1 -> v2:
> * s/qdev_class_set_props/device_class_set_props/
>   * Suggested-by: Andreas Färber <afaerber@suse.de>
> 
> Changes v2 -> v3:
> * Rebased to latest qemu.git master
> 
> Changes v3 -> v4:
> * Fix e1000e initialization ordering (fixes "make check" failure)
>   * Reported-by: Igor Mammedov <imammedo@redhat.com>
> * Rebased to latest qemu.git master (new functions changed:
>   floppy_drive_class_init(), pnv_chip_class_init(),
>   pnv_core_class_init())
> ---
>  hw/9pfs/virtio-9p-device.c          |  2 +-
>  hw/acpi/piix4.c                     |  2 +-
>  hw/arm/armv7m.c                     |  2 +-
>  hw/arm/bcm2836.c                    |  2 +-
>  hw/arm/integratorcp.c               |  2 +-
>  hw/arm/musicpal.c                   |  2 +-
>  hw/arm/pxa2xx.c                     |  4 ++--
>  hw/arm/pxa2xx_gpio.c                |  2 +-
>  hw/arm/spitz.c                      |  2 +-
>  hw/arm/stm32f205_soc.c              |  2 +-
>  hw/arm/strongarm.c                  |  2 +-
>  hw/arm/xlnx-zynqmp.c                |  2 +-
>  hw/audio/ac97.c                     |  2 +-
>  hw/audio/adlib.c                    |  2 +-
>  hw/audio/cs4231.c                   |  2 +-
>  hw/audio/cs4231a.c                  |  2 +-
>  hw/audio/gus.c                      |  2 +-
>  hw/audio/hda-codec.c                |  2 +-
>  hw/audio/intel-hda.c                |  4 ++--
>  hw/audio/marvell_88w8618.c          |  2 +-
>  hw/audio/pcspk.c                    |  2 +-
>  hw/audio/pl041.c                    |  2 +-
>  hw/audio/sb16.c                     |  2 +-
>  hw/block/fdc.c                      |  8 ++++----
>  hw/block/m25p80.c                   |  2 +-
>  hw/block/nand.c                     |  2 +-
>  hw/block/nvme.c                     |  2 +-
>  hw/block/onenand.c                  |  2 +-
>  hw/block/pflash_cfi01.c             |  2 +-
>  hw/block/pflash_cfi02.c             |  2 +-
>  hw/block/virtio-blk.c               |  2 +-
>  hw/char/bcm2835_aux.c               |  2 +-
>  hw/char/cadence_uart.c              |  2 +-
>  hw/char/debugcon.c                  |  2 +-
>  hw/char/digic-uart.c                |  2 +-
>  hw/char/escc.c                      |  2 +-
>  hw/char/etraxfs_ser.c               |  2 +-
>  hw/char/exynos4210_uart.c           |  2 +-
>  hw/char/grlib_apbuart.c             |  2 +-
>  hw/char/imx_serial.c                |  2 +-
>  hw/char/ipoctal232.c                |  2 +-
>  hw/char/lm32_juart.c                |  2 +-
>  hw/char/lm32_uart.c                 |  2 +-
>  hw/char/milkymist-uart.c            |  2 +-
>  hw/char/parallel.c                  |  2 +-
>  hw/char/pl011.c                     |  2 +-
>  hw/char/sclpconsole-lm.c            |  2 +-
>  hw/char/sclpconsole.c               |  2 +-
>  hw/char/serial-isa.c                |  2 +-
>  hw/char/serial-pci.c                |  6 +++---
>  hw/char/spapr_vty.c                 |  2 +-
>  hw/char/stm32f2xx_usart.c           |  2 +-
>  hw/char/virtio-console.c            |  2 +-
>  hw/char/virtio-serial-bus.c         |  4 ++--
>  hw/char/xilinx_uartlite.c           |  2 +-
>  hw/core/generic-loader.c            |  2 +-
>  hw/core/or-irq.c                    |  2 +-
>  hw/core/platform-bus.c              |  2 +-
>  hw/core/qdev.c                      |  6 ++++++
>  hw/cpu/a15mpcore.c                  |  2 +-
>  hw/cpu/a9mpcore.c                   |  2 +-
>  hw/cpu/arm11mpcore.c                |  2 +-
>  hw/cpu/realview_mpcore.c            |  2 +-
>  hw/display/bcm2835_fb.c             |  2 +-
>  hw/display/cg3.c                    |  2 +-
>  hw/display/cirrus_vga.c             |  4 ++--
>  hw/display/g364fb.c                 |  2 +-
>  hw/display/milkymist-vgafb.c        |  2 +-
>  hw/display/qxl.c                    |  2 +-
>  hw/display/tcx.c                    |  2 +-
>  hw/display/vga-isa.c                |  2 +-
>  hw/display/vga-pci.c                |  4 ++--
>  hw/display/virtio-gpu-pci.c         |  2 +-
>  hw/display/virtio-gpu.c             |  2 +-
>  hw/display/virtio-vga.c             |  2 +-
>  hw/display/vmware_vga.c             |  2 +-
>  hw/dma/i82374.c                     |  2 +-
>  hw/dma/i8257.c                      |  2 +-
>  hw/dma/pl330.c                      |  2 +-
>  hw/dma/pxa2xx_dma.c                 |  2 +-
>  hw/dma/sparc32_dma.c                |  2 +-
>  hw/dma/sun4m_iommu.c                |  2 +-
>  hw/dma/xilinx_axidma.c              |  2 +-
>  hw/gpio/imx_gpio.c                  |  2 +-
>  hw/gpio/omap_gpio.c                 |  4 ++--
>  hw/i2c/core.c                       |  2 +-
>  hw/i2c/omap_i2c.c                   |  2 +-
>  hw/i2c/smbus_eeprom.c               |  2 +-
>  hw/i386/intel_iommu.c               |  2 +-
>  hw/i386/kvm/i8254.c                 |  2 +-
>  hw/i386/kvm/ioapic.c                |  2 +-
>  hw/i386/kvm/pci-assign.c            |  2 +-
>  hw/i386/xen/xen_pvdevice.c          |  2 +-
>  hw/ide/ahci.c                       |  2 +-
>  hw/ide/cmd646.c                     |  2 +-
>  hw/ide/isa.c                        |  2 +-
>  hw/ide/mmio.c                       |  2 +-
>  hw/ide/qdev.c                       |  8 ++++----
>  hw/input/milkymist-softusb.c        |  2 +-
>  hw/input/virtio-input-hid.c         |  2 +-
>  hw/input/virtio-input-host.c        |  2 +-
>  hw/input/virtio-input.c             |  2 +-
>  hw/input/vmmouse.c                  |  2 +-
>  hw/intc/apic_common.c               |  2 +-
>  hw/intc/arm_gic_common.c            |  2 +-
>  hw/intc/arm_gicv2m.c                |  2 +-
>  hw/intc/arm_gicv3_common.c          |  2 +-
>  hw/intc/etraxfs_pic.c               |  2 +-
>  hw/intc/exynos4210_combiner.c       |  2 +-
>  hw/intc/exynos4210_gic.c            |  4 ++--
>  hw/intc/grlib_irqmp.c               |  2 +-
>  hw/intc/i8259_common.c              |  2 +-
>  hw/intc/ioapic.c                    |  2 +-
>  hw/intc/mips_gic.c                  |  2 +-
>  hw/intc/omap_intc.c                 |  4 ++--
>  hw/intc/openpic.c                   |  2 +-
>  hw/intc/openpic_kvm.c               |  2 +-
>  hw/intc/xilinx_intc.c               |  2 +-
>  hw/ipack/ipack.c                    |  2 +-
>  hw/ipmi/ipmi.c                      |  2 +-
>  hw/ipmi/ipmi_bmc_extern.c           |  2 +-
>  hw/ipmi/isa_ipmi_bt.c               |  2 +-
>  hw/ipmi/isa_ipmi_kcs.c              |  2 +-
>  hw/isa/lpc_ich9.c                   |  2 +-
>  hw/isa/pc87312.c                    |  2 +-
>  hw/isa/vt82c686.c                   |  2 +-
>  hw/mem/pc-dimm.c                    |  2 +-
>  hw/mips/cps.c                       |  2 +-
>  hw/misc/a9scu.c                     |  2 +-
>  hw/misc/applesmc.c                  |  2 +-
>  hw/misc/arm11scu.c                  |  2 +-
>  hw/misc/arm_l2x0.c                  |  2 +-
>  hw/misc/arm_sysctl.c                |  2 +-
>  hw/misc/aspeed_scu.c                |  2 +-
>  hw/misc/aspeed_sdmc.c               |  2 +-
>  hw/misc/bcm2835_property.c          |  2 +-
>  hw/misc/debugexit.c                 |  2 +-
>  hw/misc/eccmemctl.c                 |  2 +-
>  hw/misc/ivshmem.c                   |  6 +++---
>  hw/misc/macio/cuda.c                |  2 +-
>  hw/misc/macio/macio.c               |  2 +-
>  hw/misc/mips_cmgcr.c                |  2 +-
>  hw/misc/mips_cpc.c                  |  2 +-
>  hw/misc/mips_itu.c                  |  2 +-
>  hw/misc/pvpanic.c                   |  2 +-
>  hw/net/allwinner_emac.c             |  2 +-
>  hw/net/cadence_gem.c                |  2 +-
>  hw/net/dp8393x.c                    |  2 +-
>  hw/net/e1000.c                      |  2 +-
>  hw/net/e1000e.c                     |  3 ++-
>  hw/net/eepro100.c                   |  2 +-
>  hw/net/etraxfs_eth.c                |  2 +-
>  hw/net/fsl_etsec/etsec.c            |  2 +-
>  hw/net/imx_fec.c                    |  2 +-
>  hw/net/lan9118.c                    |  2 +-
>  hw/net/lance.c                      |  2 +-
>  hw/net/milkymist-minimac2.c         |  2 +-
>  hw/net/mipsnet.c                    |  2 +-
>  hw/net/ne2000-isa.c                 |  2 +-
>  hw/net/ne2000.c                     |  2 +-
>  hw/net/opencores_eth.c              |  2 +-
>  hw/net/pcnet-pci.c                  |  2 +-
>  hw/net/rocker/rocker.c              |  2 +-
>  hw/net/rtl8139.c                    |  2 +-
>  hw/net/smc91c111.c                  |  2 +-
>  hw/net/spapr_llan.c                 |  2 +-
>  hw/net/stellaris_enet.c             |  2 +-
>  hw/net/virtio-net.c                 |  2 +-
>  hw/net/vmxnet3.c                    |  2 +-
>  hw/net/xgmac.c                      |  2 +-
>  hw/net/xilinx_axienet.c             |  2 +-
>  hw/net/xilinx_ethlite.c             |  2 +-
>  hw/nvram/ds1225y.c                  |  2 +-
>  hw/nvram/fw_cfg.c                   |  4 ++--
>  hw/nvram/mac_nvram.c                |  2 +-
>  hw/nvram/spapr_nvram.c              |  2 +-
>  hw/pci-bridge/ioh3420.c             |  2 +-
>  hw/pci-bridge/pci_bridge_dev.c      |  2 +-
>  hw/pci-bridge/pci_expander_bridge.c |  4 ++--
>  hw/pci-bridge/xio3130_downstream.c  |  2 +-
>  hw/pci-host/piix.c                  |  2 +-
>  hw/pci-host/ppce500.c               |  2 +-
>  hw/pci-host/prep.c                  |  2 +-
>  hw/pci-host/q35.c                   |  2 +-
>  hw/pci-host/versatile.c             |  2 +-
>  hw/pci/pci.c                        |  2 +-
>  hw/pci/pcie_port.c                  |  4 ++--
>  hw/ppc/pnv.c                        |  2 +-
>  hw/ppc/pnv_core.c                   |  2 +-
>  hw/ppc/spapr_pci.c                  |  2 +-
>  hw/ppc/spapr_pci_vfio.c             |  2 +-
>  hw/ppc/spapr_rng.c                  |  2 +-
>  hw/ppc/spapr_vio.c                  |  2 +-
>  hw/s390x/css-bridge.c               |  2 +-
>  hw/s390x/ipl.c                      |  2 +-
>  hw/s390x/s390-pci-bus.c             |  2 +-
>  hw/s390x/virtio-ccw.c               | 18 +++++++++---------
>  hw/scsi/megasas.c                   |  2 +-
>  hw/scsi/mptsas.c                    |  2 +-
>  hw/scsi/scsi-bus.c                  |  2 +-
>  hw/scsi/scsi-disk.c                 |  8 ++++----
>  hw/scsi/scsi-generic.c              |  2 +-
>  hw/scsi/spapr_vscsi.c               |  2 +-
>  hw/scsi/vhost-scsi.c                |  2 +-
>  hw/scsi/virtio-scsi.c               |  2 +-
>  hw/scsi/vmw_pvscsi.c                |  2 +-
>  hw/sd/sd.c                          |  2 +-
>  hw/sd/sdhci.c                       |  4 ++--
>  hw/sparc/sun4m.c                    |  4 ++--
>  hw/sparc64/sun4u.c                  |  4 ++--
>  hw/ssi/aspeed_smc.c                 |  2 +-
>  hw/ssi/xilinx_spi.c                 |  2 +-
>  hw/ssi/xilinx_spips.c               |  2 +-
>  hw/timer/a9gtimer.c                 |  2 +-
>  hw/timer/allwinner-a10-pit.c        |  2 +-
>  hw/timer/arm_mptimer.c              |  2 +-
>  hw/timer/arm_timer.c                |  2 +-
>  hw/timer/grlib_gptimer.c            |  2 +-
>  hw/timer/hpet.c                     |  2 +-
>  hw/timer/i8254.c                    |  2 +-
>  hw/timer/lm32_timer.c               |  2 +-
>  hw/timer/m48t59.c                   |  4 ++--
>  hw/timer/mc146818rtc.c              |  2 +-
>  hw/timer/milkymist-sysctl.c         |  2 +-
>  hw/timer/pxa2xx_timer.c             |  4 ++--
>  hw/timer/slavio_timer.c             |  2 +-
>  hw/timer/stm32f2xx_timer.c          |  2 +-
>  hw/timer/xilinx_timer.c             |  2 +-
>  hw/tpm/tpm_tis.c                    |  2 +-
>  hw/usb/bus.c                        |  2 +-
>  hw/usb/ccid-card-emulated.c         |  2 +-
>  hw/usb/ccid-card-passthru.c         |  2 +-
>  hw/usb/dev-audio.c                  |  2 +-
>  hw/usb/dev-hid.c                    |  6 +++---
>  hw/usb/dev-mtp.c                    |  2 +-
>  hw/usb/dev-network.c                |  2 +-
>  hw/usb/dev-serial.c                 |  4 ++--
>  hw/usb/dev-smartcard-reader.c       |  4 ++--
>  hw/usb/dev-storage.c                |  2 +-
>  hw/usb/dev-uas.c                    |  2 +-
>  hw/usb/hcd-ehci-pci.c               |  2 +-
>  hw/usb/hcd-ehci-sysbus.c            |  2 +-
>  hw/usb/hcd-ohci.c                   |  4 ++--
>  hw/usb/hcd-uhci.c                   |  4 ++--
>  hw/usb/hcd-xhci.c                   |  2 +-
>  hw/usb/host-libusb.c                |  2 +-
>  hw/usb/redirect.c                   |  2 +-
>  hw/vfio/pci.c                       |  2 +-
>  hw/vfio/platform.c                  |  2 +-
>  hw/virtio/vhost-vsock.c             |  2 +-
>  hw/virtio/virtio-balloon.c          |  2 +-
>  hw/virtio/virtio-mmio.c             |  2 +-
>  hw/virtio/virtio-pci.c              | 20 ++++++++++----------
>  hw/virtio/virtio-rng.c              |  2 +-
>  hw/virtio/virtio.c                  |  2 +-
>  hw/xen/xen_backend.c                |  2 +-
>  hw/xen/xen_pt.c                     |  2 +-
>  include/hw/qdev-core.h              |  6 ++++++
>  target-arm/cpu.c                    |  2 +-
>  target-i386/cpu.c                   |  4 ++--
>  target-microblaze/cpu.c             |  2 +-
>  target-ppc/translate_init.c         |  6 +++---
>  tests/test-qdev-global-props.c      |  2 +-
>  263 files changed, 329 insertions(+), 316 deletions(-)
> 
> diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
> index 1782e4a..10d1a82 100644
> --- a/hw/9pfs/virtio-9p-device.c
> +++ b/hw/9pfs/virtio-9p-device.c
> @@ -207,7 +207,7 @@ static void virtio_9p_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
>  
> -    dc->props = virtio_9p_properties;
> +    device_class_set_props(dc, virtio_9p_properties);
>      dc->vmsd = &vmstate_virtio_9p;
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>      vdc->realize = virtio_9p_device_realize;
> diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
> index 2adc246..fce2b65 100644
> --- a/hw/acpi/piix4.c
> +++ b/hw/acpi/piix4.c
> @@ -687,7 +687,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data)
>      k->class_id = PCI_CLASS_BRIDGE_OTHER;
>      dc->desc = "PM";
>      dc->vmsd = &vmstate_acpi;
> -    dc->props = piix4_pm_properties;
> +    device_class_set_props(dc, piix4_pm_properties);
>      /*
>       * Reason: part of PIIX4 southbridge, needs to be wired up,
>       * e.g. by mips_malta_init()
> diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
> index 49d3078..e14e28a 100644
> --- a/hw/arm/armv7m.c
> +++ b/hw/arm/armv7m.c
> @@ -245,7 +245,7 @@ static void bitband_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = bitband_properties;
> +    device_class_set_props(dc, bitband_properties);
>  }
>  
>  static const TypeInfo bitband_info = {
> diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
> index 8451190..14f2db0 100644
> --- a/hw/arm/bcm2836.c
> +++ b/hw/arm/bcm2836.c
> @@ -158,7 +158,7 @@ static void bcm2836_class_init(ObjectClass *oc, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(oc);
>  
> -    dc->props = bcm2836_props;
> +    device_class_set_props(dc, bcm2836_props);
>      dc->realize = bcm2836_realize;
>  
>      /*
> diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
> index 039812a..93e5326 100644
> --- a/hw/arm/integratorcp.c
> +++ b/hw/arm/integratorcp.c
> @@ -638,7 +638,7 @@ static void core_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = core_properties;
> +    device_class_set_props(dc, core_properties);
>      dc->realize = integratorcm_realize;
>  }
>  
> diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
> index cbbca4e..c3a2430 100644
> --- a/hw/arm/musicpal.c
> +++ b/hw/arm/musicpal.c
> @@ -431,7 +431,7 @@ static void mv88w8618_eth_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->vmsd = &mv88w8618_eth_vmsd;
> -    dc->props = mv88w8618_eth_properties;
> +    device_class_set_props(dc, mv88w8618_eth_properties);
>      dc->realize = mv88w8618_eth_realize;
>  }
>  
> diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
> index 42cdde0..59b143a 100644
> --- a/hw/arm/pxa2xx.c
> +++ b/hw/arm/pxa2xx.c
> @@ -1530,7 +1530,7 @@ static void pxa2xx_i2c_class_init(ObjectClass *klass, void *data)
>  
>      dc->desc = "PXA2xx I2C Bus Controller";
>      dc->vmsd = &vmstate_pxa2xx_i2c;
> -    dc->props = pxa2xx_i2c_properties;
> +    device_class_set_props(dc, pxa2xx_i2c_properties);
>  }
>  
>  static const TypeInfo pxa2xx_i2c_info = {
> @@ -2013,7 +2013,7 @@ static void pxa2xx_fir_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = pxa2xx_fir_realize;
>      dc->vmsd = &pxa2xx_fir_vmsd;
> -    dc->props = pxa2xx_fir_properties;
> +    device_class_set_props(dc, pxa2xx_fir_properties);
>      dc->reset = pxa2xx_fir_reset;
>  }
>  
> diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c
> index 521dbad..ff8c8e0 100644
> --- a/hw/arm/pxa2xx_gpio.c
> +++ b/hw/arm/pxa2xx_gpio.c
> @@ -343,7 +343,7 @@ static void pxa2xx_gpio_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->desc = "PXA2xx GPIO controller";
> -    dc->props = pxa2xx_gpio_properties;
> +    device_class_set_props(dc, pxa2xx_gpio_properties);
>      dc->vmsd = &vmstate_pxa2xx_gpio_regs;
>      dc->realize = pxa2xx_gpio_realize;
>  }
> diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
> index 41cc2ee..6cd8bf4 100644
> --- a/hw/arm/spitz.c
> +++ b/hw/arm/spitz.c
> @@ -1060,7 +1060,7 @@ static void sl_nand_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->vmsd = &vmstate_sl_nand_info;
> -    dc->props = sl_nand_properties;
> +    device_class_set_props(dc, sl_nand_properties);
>      /* Reason: init() method uses drive_get() */
>      dc->cannot_instantiate_with_device_add_yet = true;
>  }
> diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c
> index 38425bd..4a9ae54 100644
> --- a/hw/arm/stm32f205_soc.c
> +++ b/hw/arm/stm32f205_soc.c
> @@ -202,7 +202,7 @@ static void stm32f205_soc_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = stm32f205_soc_realize;
> -    dc->props = stm32f205_soc_properties;
> +    device_class_set_props(dc, stm32f205_soc_properties);
>  }
>  
>  static const TypeInfo stm32f205_soc_info = {
> diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
> index 3311cc3..d458802 100644
> --- a/hw/arm/strongarm.c
> +++ b/hw/arm/strongarm.c
> @@ -1320,7 +1320,7 @@ static void strongarm_uart_class_init(ObjectClass *klass, void *data)
>      dc->desc = "StrongARM UART controller";
>      dc->reset = strongarm_uart_reset;
>      dc->vmsd = &vmstate_strongarm_uart_regs;
> -    dc->props = strongarm_uart_properties;
> +    device_class_set_props(dc, strongarm_uart_properties);
>      dc->realize = strongarm_uart_realize;
>  }
>  
> diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
> index 0d86ba3..a194480 100644
> --- a/hw/arm/xlnx-zynqmp.c
> +++ b/hw/arm/xlnx-zynqmp.c
> @@ -435,7 +435,7 @@ static void xlnx_zynqmp_class_init(ObjectClass *oc, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(oc);
>  
> -    dc->props = xlnx_zynqmp_props;
> +    device_class_set_props(dc, xlnx_zynqmp_props);
>      dc->realize = xlnx_zynqmp_realize;
>  
>      /*
> diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c
> index cbd959e..2147c8a 100644
> --- a/hw/audio/ac97.c
> +++ b/hw/audio/ac97.c
> @@ -1411,7 +1411,7 @@ static void ac97_class_init (ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
>      dc->desc = "Intel 82801AA AC97 Audio";
>      dc->vmsd = &vmstate_ac97;
> -    dc->props = ac97_properties;
> +    device_class_set_props(dc, ac97_properties);
>      dc->reset = ac97_on_reset;
>  }
>  
> diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c
> index 7836446..b375cef 100644
> --- a/hw/audio/adlib.c
> +++ b/hw/audio/adlib.c
> @@ -361,7 +361,7 @@ static void adlib_class_initfn (ObjectClass *klass, void *data)
>      dc->realize = adlib_realizefn;
>      set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
>      dc->desc = ADLIB_DESC;
> -    dc->props = adlib_properties;
> +    device_class_set_props(dc, adlib_properties);
>  }
>  
>  static const TypeInfo adlib_info = {
> diff --git a/hw/audio/cs4231.c b/hw/audio/cs4231.c
> index 30690f9..159b43d 100644
> --- a/hw/audio/cs4231.c
> +++ b/hw/audio/cs4231.c
> @@ -166,7 +166,7 @@ static void cs4231_class_init(ObjectClass *klass, void *data)
>  
>      dc->reset = cs_reset;
>      dc->vmsd = &vmstate_cs4231;
> -    dc->props = cs4231_properties;
> +    device_class_set_props(dc, cs4231_properties);
>  }
>  
>  static const TypeInfo cs4231_info = {
> diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c
> index 3ecd058..ec2c74c 100644
> --- a/hw/audio/cs4231a.c
> +++ b/hw/audio/cs4231a.c
> @@ -695,7 +695,7 @@ static void cs4231a_class_initfn (ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
>      dc->desc = "Crystal Semiconductor CS4231A";
>      dc->vmsd = &vmstate_cs4231a;
> -    dc->props = cs4231a_properties;
> +    device_class_set_props(dc, cs4231a_properties);
>  }
>  
>  static const TypeInfo cs4231a_info = {
> diff --git a/hw/audio/gus.c b/hw/audio/gus.c
> index 3d08a65..c69a8c8 100644
> --- a/hw/audio/gus.c
> +++ b/hw/audio/gus.c
> @@ -305,7 +305,7 @@ static void gus_class_initfn (ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
>      dc->desc = "Gravis Ultrasound GF1";
>      dc->vmsd = &vmstate_gus;
> -    dc->props = gus_properties;
> +    device_class_set_props(dc, gus_properties);
>  }
>  
>  static const TypeInfo gus_info = {
> diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c
> index 52d4640..9dd7624 100644
> --- a/hw/audio/hda-codec.c
> +++ b/hw/audio/hda-codec.c
> @@ -663,7 +663,7 @@ static void hda_audio_base_class_init(ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
>      dc->reset = hda_audio_reset;
>      dc->vmsd = &vmstate_hda_audio;
> -    dc->props = hda_audio_properties;
> +    device_class_set_props(dc, hda_audio_properties);
>  }
>  
>  static const TypeInfo hda_audio_info = {
> diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
> index 537face..d1b83ac 100644
> --- a/hw/audio/intel-hda.c
> +++ b/hw/audio/intel-hda.c
> @@ -1269,7 +1269,7 @@ static void intel_hda_class_init(ObjectClass *klass, void *data)
>      k->class_id = PCI_CLASS_MULTIMEDIA_HD_AUDIO;
>      dc->reset = intel_hda_reset;
>      dc->vmsd = &vmstate_intel_hda;
> -    dc->props = intel_hda_properties;
> +    device_class_set_props(dc, intel_hda_properties);
>  }
>  
>  static void intel_hda_class_init_ich6(ObjectClass *klass, void *data)
> @@ -1321,7 +1321,7 @@ static void hda_codec_device_class_init(ObjectClass *klass, void *data)
>      k->exit = hda_codec_dev_exit;
>      set_bit(DEVICE_CATEGORY_SOUND, k->categories);
>      k->bus_type = TYPE_HDA_BUS;
> -    k->props = hda_props;
> +    device_class_set_props(k, hda_props);
>  }
>  
>  static const TypeInfo hda_codec_device_type_info = {
> diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c
> index a6ca180..fe6a9ba 100644
> --- a/hw/audio/marvell_88w8618.c
> +++ b/hw/audio/marvell_88w8618.c
> @@ -287,7 +287,7 @@ static void mv88w8618_audio_class_init(ObjectClass *klass, void *data)
>      k->init = mv88w8618_audio_init;
>      dc->reset = mv88w8618_audio_reset;
>      dc->vmsd = &mv88w8618_audio_vmsd;
> -    dc->props = mv88w8618_audio_properties;
> +    device_class_set_props(dc, mv88w8618_audio_properties);
>      /* Reason: pointer property "wm8750" */
>      dc->cannot_instantiate_with_device_add_yet = true;
>  }
> diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
> index 984534b..2484075 100644
> --- a/hw/audio/pcspk.c
> +++ b/hw/audio/pcspk.c
> @@ -211,7 +211,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data)
>      dc->realize = pcspk_realizefn;
>      set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
>      dc->vmsd = &vmstate_spk;
> -    dc->props = pcspk_properties;
> +    device_class_set_props(dc, pcspk_properties);
>      /* Reason: realize sets global pcspk_state */
>      dc->cannot_instantiate_with_device_add_yet = true;
>  }
> diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c
> index 6e9c104..738d0de 100644
> --- a/hw/audio/pl041.c
> +++ b/hw/audio/pl041.c
> @@ -633,7 +633,7 @@ static void pl041_device_class_init(ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
>      dc->reset = pl041_device_reset;
>      dc->vmsd = &vmstate_pl041;
> -    dc->props = pl041_device_properties;
> +    device_class_set_props(dc, pl041_device_properties);
>  }
>  
>  static const TypeInfo pl041_device_info = {
> diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c
> index 6b4427f..2e6c602 100644
> --- a/hw/audio/sb16.c
> +++ b/hw/audio/sb16.c
> @@ -1418,7 +1418,7 @@ static void sb16_class_initfn (ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
>      dc->desc = "Creative Sound Blaster 16";
>      dc->vmsd = &vmstate_sb16;
> -    dc->props = sb16_properties;
> +    device_class_set_props(dc, sb16_properties);
>  }
>  
>  static const TypeInfo sb16_info = {
> diff --git a/hw/block/fdc.c b/hw/block/fdc.c
> index 17d29e7..6976bf4 100644
> --- a/hw/block/fdc.c
> +++ b/hw/block/fdc.c
> @@ -587,7 +587,7 @@ static void floppy_drive_class_init(ObjectClass *klass, void *data)
>      k->init = floppy_drive_init;
>      set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
>      k->bus_type = TYPE_FLOPPY_BUS;
> -    k->props = floppy_drive_properties;
> +    device_class_set_props(k, floppy_drive_properties);
>      k->desc = "virtual floppy drive";
>  }
>  
> @@ -2803,7 +2803,7 @@ static void isabus_fdc_class_init(ObjectClass *klass, void *data)
>      dc->fw_name = "fdc";
>      dc->reset = fdctrl_external_reset_isa;
>      dc->vmsd = &vmstate_isa_fdc;
> -    dc->props = isa_fdc_properties;
> +    device_class_set_props(dc, isa_fdc_properties);
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>  }
>  
> @@ -2856,7 +2856,7 @@ static void sysbus_fdc_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = sysbus_fdc_properties;
> +    device_class_set_props(dc, sysbus_fdc_properties);
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>  }
>  
> @@ -2882,7 +2882,7 @@ static void sun4m_fdc_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = sun4m_fdc_properties;
> +    device_class_set_props(dc, sun4m_fdc_properties);
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>  }
>  
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index d29ff4c..e2c9c52 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -1228,7 +1228,7 @@ static void m25p80_class_init(ObjectClass *klass, void *data)
>      k->set_cs = m25p80_cs;
>      k->cs_polarity = SSI_CS_LOW;
>      dc->vmsd = &vmstate_m25p80;
> -    dc->props = m25p80_properties;
> +    device_class_set_props(dc, m25p80_properties);
>      dc->reset = m25p80_reset;
>      mc->pi = data;
>  }
> diff --git a/hw/block/nand.c b/hw/block/nand.c
> index c69e675..d4561fb 100644
> --- a/hw/block/nand.c
> +++ b/hw/block/nand.c
> @@ -437,7 +437,7 @@ static void nand_class_init(ObjectClass *klass, void *data)
>      dc->realize = nand_realize;
>      dc->reset = nand_reset;
>      dc->vmsd = &vmstate_nand;
> -    dc->props = nand_properties;
> +    device_class_set_props(dc, nand_properties);
>  }
>  
>  static const TypeInfo nand_info = {
> diff --git a/hw/block/nvme.c b/hw/block/nvme.c
> index b380142..48eb372 100644
> --- a/hw/block/nvme.c
> +++ b/hw/block/nvme.c
> @@ -961,7 +961,7 @@ static void nvme_class_init(ObjectClass *oc, void *data)
>  
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>      dc->desc = "Non-Volatile Memory Express";
> -    dc->props = nvme_props;
> +    device_class_set_props(dc, nvme_props);
>      dc->vmsd = &nvme_vmstate;
>  }
>  
> diff --git a/hw/block/onenand.c b/hw/block/onenand.c
> index 8d84227..56a7262 100644
> --- a/hw/block/onenand.c
> +++ b/hw/block/onenand.c
> @@ -838,7 +838,7 @@ static void onenand_class_init(ObjectClass *klass, void *data)
>  
>      k->init = onenand_initfn;
>      dc->reset = onenand_system_reset;
> -    dc->props = onenand_properties;
> +    device_class_set_props(dc, onenand_properties);
>  }
>  
>  static const TypeInfo onenand_info = {
> diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
> index 62d7a56..0550d35 100644
> --- a/hw/block/pflash_cfi01.c
> +++ b/hw/block/pflash_cfi01.c
> @@ -893,7 +893,7 @@ static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = pflash_cfi01_realize;
> -    dc->props = pflash_cfi01_properties;
> +    device_class_set_props(dc, pflash_cfi01_properties);
>      dc->vmsd = &vmstate_pflash;
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>  }
> diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
> index 4f6105c..ba1437e 100644
> --- a/hw/block/pflash_cfi02.c
> +++ b/hw/block/pflash_cfi02.c
> @@ -744,7 +744,7 @@ static void pflash_cfi02_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = pflash_cfi02_realize;
> -    dc->props = pflash_cfi02_properties;
> +    device_class_set_props(dc, pflash_cfi02_properties);
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>  }
>  
> diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
> index 37fe72b..0e40676 100644
> --- a/hw/block/virtio-blk.c
> +++ b/hw/block/virtio-blk.c
> @@ -990,7 +990,7 @@ static void virtio_blk_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
>  
> -    dc->props = virtio_blk_properties;
> +    device_class_set_props(dc, virtio_blk_properties);
>      dc->vmsd = &vmstate_virtio_blk;
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>      vdc->realize = virtio_blk_device_realize;
> diff --git a/hw/char/bcm2835_aux.c b/hw/char/bcm2835_aux.c
> index 4d46ad6..b6613e3 100644
> --- a/hw/char/bcm2835_aux.c
> +++ b/hw/char/bcm2835_aux.c
> @@ -294,7 +294,7 @@ static void bcm2835_aux_class_init(ObjectClass *oc, void *data)
>      dc->realize = bcm2835_aux_realize;
>      dc->vmsd = &vmstate_bcm2835_aux;
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
> -    dc->props = bcm2835_aux_props;
> +    device_class_set_props(dc, bcm2835_aux_props);
>  }
>  
>  static const TypeInfo bcm2835_aux_info = {
> diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
> index c2b9154..fed2c41 100644
> --- a/hw/char/cadence_uart.c
> +++ b/hw/char/cadence_uart.c
> @@ -522,7 +522,7 @@ static void cadence_uart_class_init(ObjectClass *klass, void *data)
>      dc->realize = cadence_uart_realize;
>      dc->vmsd = &vmstate_cadence_uart;
>      dc->reset = cadence_uart_reset;
> -    dc->props = cadence_uart_properties;
> +    device_class_set_props(dc, cadence_uart_properties);
>    }
>  
>  static const TypeInfo cadence_uart_info = {
> diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c
> index 80dce07..c54a45c 100644
> --- a/hw/char/debugcon.c
> +++ b/hw/char/debugcon.c
> @@ -125,7 +125,7 @@ static void debugcon_isa_class_initfn(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = debugcon_isa_realizefn;
> -    dc->props = debugcon_isa_properties;
> +    device_class_set_props(dc, debugcon_isa_properties);
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>  }
>  
> diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c
> index 029f5bb..0dab6a7 100644
> --- a/hw/char/digic-uart.c
> +++ b/hw/char/digic-uart.c
> @@ -181,7 +181,7 @@ static void digic_uart_class_init(ObjectClass *klass, void *data)
>      dc->realize = digic_uart_realize;
>      dc->reset = digic_uart_reset;
>      dc->vmsd = &vmstate_digic_uart;
> -    dc->props = digic_uart_properties;
> +    device_class_set_props(dc, digic_uart_properties);
>  }
>  
>  static const TypeInfo digic_uart_info = {
> diff --git a/hw/char/escc.c b/hw/char/escc.c
> index d6662dc..47175d9 100644
> --- a/hw/char/escc.c
> +++ b/hw/char/escc.c
> @@ -1048,7 +1048,7 @@ static void escc_class_init(ObjectClass *klass, void *data)
>      dc->reset = escc_reset;
>      dc->realize = escc_realize;
>      dc->vmsd = &vmstate_escc;
> -    dc->props = escc_properties;
> +    device_class_set_props(dc, escc_properties);
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>  }
>  
> diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c
> index 5438387..7536615 100644
> --- a/hw/char/etraxfs_ser.c
> +++ b/hw/char/etraxfs_ser.c
> @@ -241,7 +241,7 @@ static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->reset = etraxfs_ser_reset;
> -    dc->props = etraxfs_ser_properties;
> +    device_class_set_props(dc, etraxfs_ser_properties);
>      dc->realize = etraxfs_ser_realize;
>  }
>  
> diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
> index 571c324..a7ac2fb 100644
> --- a/hw/char/exynos4210_uart.c
> +++ b/hw/char/exynos4210_uart.c
> @@ -662,7 +662,7 @@ static void exynos4210_uart_class_init(ObjectClass *klass, void *data)
>  
>      k->init = exynos4210_uart_init;
>      dc->reset = exynos4210_uart_reset;
> -    dc->props = exynos4210_uart_properties;
> +    device_class_set_props(dc, exynos4210_uart_properties);
>      dc->vmsd = &vmstate_exynos4210_uart;
>  }
>  
> diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c
> index db686e6..cfa33be 100644
> --- a/hw/char/grlib_apbuart.c
> +++ b/hw/char/grlib_apbuart.c
> @@ -284,7 +284,7 @@ static void grlib_apbuart_class_init(ObjectClass *klass, void *data)
>  
>      k->init = grlib_apbuart_init;
>      dc->reset = grlib_apbuart_reset;
> -    dc->props = grlib_apbuart_properties;
> +    device_class_set_props(dc, grlib_apbuart_properties);
>  }
>  
>  static const TypeInfo grlib_apbuart_info = {
> diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
> index 99545fc..fb4c615 100644
> --- a/hw/char/imx_serial.c
> +++ b/hw/char/imx_serial.c
> @@ -344,7 +344,7 @@ static void imx_serial_class_init(ObjectClass *klass, void *data)
>      dc->reset = imx_serial_reset_at_boot;
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>      dc->desc = "i.MX series UART";
> -    dc->props = imx_serial_properties;
> +    device_class_set_props(dc, imx_serial_properties);
>  }
>  
>  static const TypeInfo imx_serial_info = {
> diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c
> index 93929c2..38cf137 100644
> --- a/hw/char/ipoctal232.c
> +++ b/hw/char/ipoctal232.c
> @@ -584,7 +584,7 @@ static void ipoctal_class_init(ObjectClass *klass, void *data)
>  
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>      dc->desc    = "GE IP-Octal 232 8-channel RS-232 IndustryPack";
> -    dc->props   = ipoctal_properties;
> +    device_class_set_props(dc, ipoctal_properties);
>      dc->vmsd    = &vmstate_ipoctal;
>  }
>  
> diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c
> index f8c1e0d..65db163 100644
> --- a/hw/char/lm32_juart.c
> +++ b/hw/char/lm32_juart.c
> @@ -144,7 +144,7 @@ static void lm32_juart_class_init(ObjectClass *klass, void *data)
>  
>      dc->reset = juart_reset;
>      dc->vmsd = &vmstate_lm32_juart;
> -    dc->props = lm32_juart_properties;
> +    device_class_set_props(dc, lm32_juart_properties);
>      dc->realize = lm32_juart_realize;
>  }
>  
> diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c
> index 7f3597c..4b1ba40 100644
> --- a/hw/char/lm32_uart.c
> +++ b/hw/char/lm32_uart.c
> @@ -290,7 +290,7 @@ static void lm32_uart_class_init(ObjectClass *klass, void *data)
>  
>      dc->reset = uart_reset;
>      dc->vmsd = &vmstate_lm32_uart;
> -    dc->props = lm32_uart_properties;
> +    device_class_set_props(dc, lm32_uart_properties);
>      dc->realize = lm32_uart_realize;
>  }
>  
> diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c
> index ae8e2f3..34e37c3 100644
> --- a/hw/char/milkymist-uart.c
> +++ b/hw/char/milkymist-uart.c
> @@ -236,7 +236,7 @@ static void milkymist_uart_class_init(ObjectClass *klass, void *data)
>      dc->realize = milkymist_uart_realize;
>      dc->reset = milkymist_uart_reset;
>      dc->vmsd = &vmstate_milkymist_uart;
> -    dc->props = milkymist_uart_properties;
> +    device_class_set_props(dc, milkymist_uart_properties);
>  }
>  
>  static const TypeInfo milkymist_uart_info = {
> diff --git a/hw/char/parallel.c b/hw/char/parallel.c
> index f2d5666..151cf73 100644
> --- a/hw/char/parallel.c
> +++ b/hw/char/parallel.c
> @@ -633,7 +633,7 @@ static void parallel_isa_class_initfn(ObjectClass *klass, void *data)
>  
>      dc->realize = parallel_isa_realizefn;
>      dc->vmsd = &vmstate_parallel_isa;
> -    dc->props = parallel_isa_properties;
> +    device_class_set_props(dc, parallel_isa_properties);
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>  }
>  
> diff --git a/hw/char/pl011.c b/hw/char/pl011.c
> index 24ea973..6e7044f 100644
> --- a/hw/char/pl011.c
> +++ b/hw/char/pl011.c
> @@ -338,7 +338,7 @@ static void pl011_class_init(ObjectClass *oc, void *data)
>  
>      dc->realize = pl011_realize;
>      dc->vmsd = &vmstate_pl011;
> -    dc->props = pl011_properties;
> +    device_class_set_props(dc, pl011_properties);
>  }
>  
>  static const TypeInfo pl011_arm_info = {
> diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
> index 07d6ebd..e2e11d5 100644
> --- a/hw/char/sclpconsole-lm.c
> +++ b/hw/char/sclpconsole-lm.c
> @@ -345,7 +345,7 @@ static void console_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      SCLPEventClass *ec = SCLP_EVENT_CLASS(klass);
>  
> -    dc->props = console_properties;
> +    device_class_set_props(dc, console_properties);
>      dc->reset = console_reset;
>      dc->vmsd = &vmstate_sclplmconsole;
>      ec->init = console_init;
> diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
> index b78f240..1b04cbb 100644
> --- a/hw/char/sclpconsole.c
> +++ b/hw/char/sclpconsole.c
> @@ -261,7 +261,7 @@ static void console_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      SCLPEventClass *ec = SCLP_EVENT_CLASS(klass);
>  
> -    dc->props = console_properties;
> +    device_class_set_props(dc, console_properties);
>      dc->reset = console_reset;
>      dc->vmsd = &vmstate_sclpconsole;
>      ec->init = console_init;
> diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c
> index 54d3a12..8314bf3 100644
> --- a/hw/char/serial-isa.c
> +++ b/hw/char/serial-isa.c
> @@ -103,7 +103,7 @@ static void serial_isa_class_initfn(ObjectClass *klass, void *data)
>  
>      dc->realize = serial_isa_realizefn;
>      dc->vmsd = &vmstate_isa_serial;
> -    dc->props = serial_isa_properties;
> +    device_class_set_props(dc, serial_isa_properties);
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>  }
>  
> diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c
> index 303104d..1480699 100644
> --- a/hw/char/serial-pci.c
> +++ b/hw/char/serial-pci.c
> @@ -211,7 +211,7 @@ static void serial_pci_class_initfn(ObjectClass *klass, void *data)
>      pc->revision = 1;
>      pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
>      dc->vmsd = &vmstate_pci_serial;
> -    dc->props = serial_pci_properties;
> +    device_class_set_props(dc, serial_pci_properties);
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>  }
>  
> @@ -226,7 +226,7 @@ static void multi_2x_serial_pci_class_initfn(ObjectClass *klass, void *data)
>      pc->revision = 1;
>      pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
>      dc->vmsd = &vmstate_pci_multi_serial;
> -    dc->props = multi_2x_serial_pci_properties;
> +    device_class_set_props(dc, multi_2x_serial_pci_properties);
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>  }
>  
> @@ -241,7 +241,7 @@ static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data)
>      pc->revision = 1;
>      pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
>      dc->vmsd = &vmstate_pci_multi_serial;
> -    dc->props = multi_4x_serial_pci_properties;
> +    device_class_set_props(dc, multi_4x_serial_pci_properties);
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>  }
>  
> diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
> index 31822fe..c62bff3 100644
> --- a/hw/char/spapr_vty.c
> +++ b/hw/char/spapr_vty.c
> @@ -171,7 +171,7 @@ static void spapr_vty_class_init(ObjectClass *klass, void *data)
>      k->dt_type = "serial";
>      k->dt_compatible = "hvterm1";
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
> -    dc->props = spapr_vty_properties;
> +    device_class_set_props(dc, spapr_vty_properties);
>      dc->vmsd = &vmstate_spapr_vty;
>  }
>  
> diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c
> index 59872e6..b994033 100644
> --- a/hw/char/stm32f2xx_usart.c
> +++ b/hw/char/stm32f2xx_usart.c
> @@ -215,7 +215,7 @@ static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->reset = stm32f2xx_usart_reset;
> -    dc->props = stm32f2xx_usart_properties;
> +    device_class_set_props(dc, stm32f2xx_usart_properties);
>      dc->realize = stm32f2xx_usart_realize;
>  }
>  
> diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
> index 776205b..2e2aa38 100644
> --- a/hw/char/virtio-console.c
> +++ b/hw/char/virtio-console.c
> @@ -234,7 +234,7 @@ static void virtserialport_class_init(ObjectClass *klass, void *data)
>      k->have_data = flush_buf;
>      k->set_guest_connected = set_guest_connected;
>      k->guest_writable = guest_writable;
> -    dc->props = virtserialport_properties;
> +    device_class_set_props(dc, virtserialport_properties);
>  }
>  
>  static const TypeInfo virtserialport_info = {
> diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
> index 7975c2c..3f43ef9 100644
> --- a/hw/char/virtio-serial-bus.c
> +++ b/hw/char/virtio-serial-bus.c
> @@ -1091,7 +1091,7 @@ static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
>      k->bus_type = TYPE_VIRTIO_SERIAL_BUS;
>      k->realize = virtser_port_device_realize;
>      k->unrealize = virtser_port_device_unrealize;
> -    k->props = virtser_props;
> +    device_class_set_props(k, virtser_props);
>  }
>  
>  static const TypeInfo virtio_serial_port_type_info = {
> @@ -1149,7 +1149,7 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data)
>  
>      QLIST_INIT(&vserdevices.devices);
>  
> -    dc->props = virtio_serial_properties;
> +    device_class_set_props(dc, virtio_serial_properties);
>      dc->vmsd = &vmstate_virtio_console;
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>      vdc->realize = virtio_serial_device_realize;
> diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c
> index 37d313b..1ea812c 100644
> --- a/hw/char/xilinx_uartlite.c
> +++ b/hw/char/xilinx_uartlite.c
> @@ -232,7 +232,7 @@ static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
>  
>      dc->reset = xilinx_uartlite_reset;
>      dc->realize = xilinx_uartlite_realize;
> -    dc->props = xilinx_uartlite_properties;
> +    device_class_set_props(dc, xilinx_uartlite_properties);
>  }
>  
>  static const TypeInfo xilinx_uartlite_info = {
> diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c
> index 79ab6df..1918792 100644
> --- a/hw/core/generic-loader.c
> +++ b/hw/core/generic-loader.c
> @@ -192,7 +192,7 @@ static void generic_loader_class_init(ObjectClass *klass, void *data)
>       */
>      dc->realize = generic_loader_realize;
>      dc->unrealize = generic_loader_unrealize;
> -    dc->props = generic_loader_props;
> +    device_class_set_props(dc, generic_loader_props);
>      dc->desc = "Generic Loader";
>  }
>  
> diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c
> index 1ac090d..b5f653c 100644
> --- a/hw/core/or-irq.c
> +++ b/hw/core/or-irq.c
> @@ -86,7 +86,7 @@ static void or_irq_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->reset = or_irq_reset;
> -    dc->props = or_irq_properties;
> +    device_class_set_props(dc, or_irq_properties);
>      dc->realize = or_irq_realize;
>      dc->vmsd = &vmstate_or_irq;
>  }
> diff --git a/hw/core/platform-bus.c b/hw/core/platform-bus.c
> index 329ac67..86df136 100644
> --- a/hw/core/platform-bus.c
> +++ b/hw/core/platform-bus.c
> @@ -230,7 +230,7 @@ static void platform_bus_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = platform_bus_realize;
> -    dc->props = platform_bus_properties;
> +    device_class_set_props(dc, platform_bus_properties);
>  }
>  
>  static const TypeInfo platform_bus_info = {
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 5783442..36ca5e7 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -848,6 +848,12 @@ void qdev_alias_all_properties(DeviceState *target, Object *source)
>      } while (class != object_class_by_name(TYPE_DEVICE));
>  }
>  
> +void device_class_set_props(DeviceClass *dc, Property *props)
> +{
> +    assert(!dc->props);
> +    dc->props = props;
> +}
> +
>  static int qdev_add_hotpluggable_device(Object *obj, void *opaque)
>  {
>      GSList **list = opaque;
> diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
> index bc05152..55d3dae 100644
> --- a/hw/cpu/a15mpcore.c
> +++ b/hw/cpu/a15mpcore.c
> @@ -138,7 +138,7 @@ static void a15mp_priv_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = a15mp_priv_realize;
> -    dc->props = a15mp_priv_properties;
> +    device_class_set_props(dc, a15mp_priv_properties);
>      /* We currently have no savable state */
>  }
>  
> diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
> index f17f292..422effb 100644
> --- a/hw/cpu/a9mpcore.c
> +++ b/hw/cpu/a9mpcore.c
> @@ -174,7 +174,7 @@ static void a9mp_priv_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = a9mp_priv_realize;
> -    dc->props = a9mp_priv_properties;
> +    device_class_set_props(dc, a9mp_priv_properties);
>  }
>  
>  static const TypeInfo a9mp_priv_info = {
> diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c
> index eb24465..62b919d 100644
> --- a/hw/cpu/arm11mpcore.c
> +++ b/hw/cpu/arm11mpcore.c
> @@ -155,7 +155,7 @@ static void mpcore_priv_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = mpcore_priv_realize;
> -    dc->props = mpcore_priv_properties;
> +    device_class_set_props(dc, mpcore_priv_properties);
>  }
>  
>  static const TypeInfo mpcore_priv_info = {
> diff --git a/hw/cpu/realview_mpcore.c b/hw/cpu/realview_mpcore.c
> index 39d4ebe..12d2f09 100644
> --- a/hw/cpu/realview_mpcore.c
> +++ b/hw/cpu/realview_mpcore.c
> @@ -122,7 +122,7 @@ static void mpcore_rirq_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = realview_mpcore_realize;
> -    dc->props = mpcore_rirq_properties;
> +    device_class_set_props(dc, mpcore_rirq_properties);
>  }
>  
>  static const TypeInfo mpcore_rirq_info = {
> diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
> index 7eab927..3d38df0 100644
> --- a/hw/display/bcm2835_fb.c
> +++ b/hw/display/bcm2835_fb.c
> @@ -404,7 +404,7 @@ static void bcm2835_fb_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = bcm2835_fb_props;
> +    device_class_set_props(dc, bcm2835_fb_props);
>      dc->realize = bcm2835_fb_realize;
>      dc->reset = bcm2835_fb_reset;
>      dc->vmsd = &vmstate_bcm2835_fb;
> diff --git a/hw/display/cg3.c b/hw/display/cg3.c
> index 1174220..b6d86b7 100644
> --- a/hw/display/cg3.c
> +++ b/hw/display/cg3.c
> @@ -382,7 +382,7 @@ static void cg3_class_init(ObjectClass *klass, void *data)
>      dc->realize = cg3_realizefn;
>      dc->reset = cg3_reset;
>      dc->vmsd = &vmstate_cg3;
> -    dc->props = cg3_properties;
> +    device_class_set_props(dc, cg3_properties);
>  }
>  
>  static const TypeInfo cg3_info = {
> diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
> index 3d712d5..53e7b45 100644
> --- a/hw/display/cirrus_vga.c
> +++ b/hw/display/cirrus_vga.c
> @@ -2995,7 +2995,7 @@ static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data)
>  
>      dc->vmsd  = &vmstate_cirrus_vga;
>      dc->realize = isa_cirrus_vga_realizefn;
> -    dc->props = isa_cirrus_vga_properties;
> +    device_class_set_props(dc, isa_cirrus_vga_properties);
>      set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
>  }
>  
> @@ -3071,7 +3071,7 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
>      dc->desc = "Cirrus CLGD 54xx VGA";
>      dc->vmsd = &vmstate_pci_cirrus_vga;
> -    dc->props = pci_vga_cirrus_properties;
> +    device_class_set_props(dc, pci_vga_cirrus_properties);
>      dc->hotpluggable = false;
>  }
>  
> diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c
> index 70ef2c7..a230b7f 100644
> --- a/hw/display/g364fb.c
> +++ b/hw/display/g364fb.c
> @@ -541,7 +541,7 @@ static void g364fb_sysbus_class_init(ObjectClass *klass, void *data)
>      dc->desc = "G364 framebuffer";
>      dc->reset = g364fb_sysbus_reset;
>      dc->vmsd = &vmstate_g364fb;
> -    dc->props = g364fb_sysbus_properties;
> +    device_class_set_props(dc, g364fb_sysbus_properties);
>  }
>  
>  static const TypeInfo g364fb_sysbus_info = {
> diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c
> index 177fdac..730615d 100644
> --- a/hw/display/milkymist-vgafb.c
> +++ b/hw/display/milkymist-vgafb.c
> @@ -338,7 +338,7 @@ static void milkymist_vgafb_class_init(ObjectClass *klass, void *data)
>  
>      dc->reset = milkymist_vgafb_reset;
>      dc->vmsd = &vmstate_milkymist_vgafb;
> -    dc->props = milkymist_vgafb_properties;
> +    device_class_set_props(dc, milkymist_vgafb_properties);
>      dc->realize = milkymist_vgafb_realize;
>  }
>  
> diff --git a/hw/display/qxl.c b/hw/display/qxl.c
> index 0e2682d..aa2f4a1 100644
> --- a/hw/display/qxl.c
> +++ b/hw/display/qxl.c
> @@ -2339,7 +2339,7 @@ static void qxl_pci_class_init(ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
>      dc->reset = qxl_reset_handler;
>      dc->vmsd = &qxl_vmstate;
> -    dc->props = qxl_properties;
> +    device_class_set_props(dc, qxl_properties);
>  }
>  
>  static const TypeInfo qxl_pci_type_info = {
> diff --git a/hw/display/tcx.c b/hw/display/tcx.c
> index 8e26aae..a429cdf 100644
> --- a/hw/display/tcx.c
> +++ b/hw/display/tcx.c
> @@ -1087,7 +1087,7 @@ static void tcx_class_init(ObjectClass *klass, void *data)
>      dc->realize = tcx_realizefn;
>      dc->reset = tcx_reset;
>      dc->vmsd = &vmstate_tcx;
> -    dc->props = tcx_properties;
> +    device_class_set_props(dc, tcx_properties);
>  }
>  
>  static const TypeInfo tcx_info = {
> diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c
> index 1af9556..cdc3290 100644
> --- a/hw/display/vga-isa.c
> +++ b/hw/display/vga-isa.c
> @@ -91,7 +91,7 @@ static void vga_isa_class_initfn(ObjectClass *klass, void *data)
>      dc->realize = vga_isa_realizefn;
>      dc->reset = vga_isa_reset;
>      dc->vmsd = &vmstate_vga_common;
> -    dc->props = vga_isa_properties;
> +    device_class_set_props(dc, vga_isa_properties);
>      set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
>  }
>  
> diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
> index ac9a764..be26772 100644
> --- a/hw/display/vga-pci.c
> +++ b/hw/display/vga-pci.c
> @@ -348,7 +348,7 @@ static void vga_class_init(ObjectClass *klass, void *data)
>      k->realize = pci_std_vga_realize;
>      k->romfile = "vgabios-stdvga.bin";
>      k->class_id = PCI_CLASS_DISPLAY_VGA;
> -    dc->props = vga_pci_properties;
> +    device_class_set_props(dc, vga_pci_properties);
>      dc->hotpluggable = false;
>  }
>  
> @@ -359,7 +359,7 @@ static void secondary_class_init(ObjectClass *klass, void *data)
>  
>      k->realize = pci_secondary_vga_realize;
>      k->class_id = PCI_CLASS_DISPLAY_OTHER;
> -    dc->props = secondary_pci_properties;
> +    device_class_set_props(dc, secondary_pci_properties);
>      dc->reset = pci_secondary_vga_reset;
>  }
>  
> diff --git a/hw/display/virtio-gpu-pci.c b/hw/display/virtio-gpu-pci.c
> index ef92c4a..6122fc2 100644
> --- a/hw/display/virtio-gpu-pci.c
> +++ b/hw/display/virtio-gpu-pci.c
> @@ -47,7 +47,7 @@ static void virtio_gpu_pci_class_init(ObjectClass *klass, void *data)
>      PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
>  
>      set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
> -    dc->props = virtio_gpu_pci_properties;
> +    device_class_set_props(dc, virtio_gpu_pci_properties);
>      dc->hotpluggable = false;
>      k->realize = virtio_gpu_pci_realize;
>      pcidev_k->class_id = PCI_CLASS_DISPLAY_OTHER;
> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> index 60bce94..fff8674 100644
> --- a/hw/display/virtio-gpu.c
> +++ b/hw/display/virtio-gpu.c
> @@ -1263,7 +1263,7 @@ static void virtio_gpu_class_init(ObjectClass *klass, void *data)
>  
>      vdc->reset = virtio_gpu_reset;
>  
> -    dc->props = virtio_gpu_properties;
> +    device_class_set_props(dc, virtio_gpu_properties);
>      dc->vmsd = &vmstate_virtio_gpu;
>  }
>  
> diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
> index f9b017d..f370a2a 100644
> --- a/hw/display/virtio-vga.c
> +++ b/hw/display/virtio-vga.c
> @@ -186,7 +186,7 @@ static void virtio_vga_class_init(ObjectClass *klass, void *data)
>      PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
>  
>      set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
> -    dc->props = virtio_vga_properties;
> +    device_class_set_props(dc, virtio_vga_properties);
>      dc->reset = virtio_vga_reset;
>      dc->vmsd = &vmstate_virtio_vga;
>      dc->hotpluggable = false;
> diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
> index 6599cf0..2463cf4 100644
> --- a/hw/display/vmware_vga.c
> +++ b/hw/display/vmware_vga.c
> @@ -1356,7 +1356,7 @@ static void vmsvga_class_init(ObjectClass *klass, void *data)
>      k->subsystem_id = SVGA_PCI_DEVICE_ID;
>      dc->reset = vmsvga_reset;
>      dc->vmsd = &vmstate_vmware_vga;
> -    dc->props = vga_vmware_properties;
> +    device_class_set_props(dc, vga_vmware_properties);
>      dc->hotpluggable = false;
>      set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
>  }
> diff --git a/hw/dma/i82374.c b/hw/dma/i82374.c
> index 6c0f975..0cbc61b 100644
> --- a/hw/dma/i82374.c
> +++ b/hw/dma/i82374.c
> @@ -138,7 +138,7 @@ static void i82374_class_init(ObjectClass *klass, void *data)
>      
>      dc->realize = i82374_realize;
>      dc->vmsd = &vmstate_i82374;
> -    dc->props = i82374_properties;
> +    device_class_set_props(dc, i82374_properties);
>  }
>  
>  static const TypeInfo i82374_info = {
> diff --git a/hw/dma/i8257.c b/hw/dma/i8257.c
> index 8bd82e8..15909a8 100644
> --- a/hw/dma/i8257.c
> +++ b/hw/dma/i8257.c
> @@ -590,7 +590,7 @@ static void i8257_class_init(ObjectClass *klass, void *data)
>      dc->realize = i8257_realize;
>      dc->reset = i8257_reset;
>      dc->vmsd = &vmstate_i8257;
> -    dc->props = i8257_properties;
> +    device_class_set_props(dc, i8257_properties);
>  
>      idc->get_transfer_mode = i8257_dma_get_transfer_mode;
>      idc->has_autoinitialization = i8257_dma_has_autoinitialization;
> diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c
> index c0bd9fe..3902df2 100644
> --- a/hw/dma/pl330.c
> +++ b/hw/dma/pl330.c
> @@ -1650,7 +1650,7 @@ static void pl330_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = pl330_realize;
>      dc->reset = pl330_reset;
> -    dc->props = pl330_properties;
> +    device_class_set_props(dc, pl330_properties);
>      dc->vmsd = &vmstate_pl330;
>  }
>  
> diff --git a/hw/dma/pxa2xx_dma.c b/hw/dma/pxa2xx_dma.c
> index 634a432..99569a6 100644
> --- a/hw/dma/pxa2xx_dma.c
> +++ b/hw/dma/pxa2xx_dma.c
> @@ -562,7 +562,7 @@ static void pxa2xx_dma_class_init(ObjectClass *klass, void *data)
>  
>      dc->desc = "PXA2xx DMA controller";
>      dc->vmsd = &vmstate_pxa2xx_dma;
> -    dc->props = pxa2xx_dma_properties;
> +    device_class_set_props(dc, pxa2xx_dma_properties);
>      dc->realize = pxa2xx_dma_realize;
>  }
>  
> diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c
> index 9d545e4..056b31c 100644
> --- a/hw/dma/sparc32_dma.c
> +++ b/hw/dma/sparc32_dma.c
> @@ -303,7 +303,7 @@ static void sparc32_dma_class_init(ObjectClass *klass, void *data)
>      k->init = sparc32_dma_init1;
>      dc->reset = dma_reset;
>      dc->vmsd = &vmstate_dma;
> -    dc->props = sparc32_dma_properties;
> +    device_class_set_props(dc, sparc32_dma_properties);
>      /* Reason: pointer property "iommu_opaque" */
>      dc->cannot_instantiate_with_device_add_yet = true;
>  }
> diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c
> index b3cbc54..0c0adfd 100644
> --- a/hw/dma/sun4m_iommu.c
> +++ b/hw/dma/sun4m_iommu.c
> @@ -375,7 +375,7 @@ static void iommu_class_init(ObjectClass *klass, void *data)
>      k->init = iommu_init1;
>      dc->reset = iommu_reset;
>      dc->vmsd = &vmstate_iommu;
> -    dc->props = iommu_properties;
> +    device_class_set_props(dc, iommu_properties);
>  }
>  
>  static const TypeInfo iommu_info = {
> diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
> index 6065689..38a2ba6 100644
> --- a/hw/dma/xilinx_axidma.c
> +++ b/hw/dma/xilinx_axidma.c
> @@ -604,7 +604,7 @@ static void axidma_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = xilinx_axidma_realize,
>      dc->reset = xilinx_axidma_reset;
> -    dc->props = axidma_properties;
> +    device_class_set_props(dc, axidma_properties);
>  }
>  
>  static StreamSlaveClass xilinx_axidma_data_stream_class = {
> diff --git a/hw/gpio/imx_gpio.c b/hw/gpio/imx_gpio.c
> index f3574aa..d1325e6 100644
> --- a/hw/gpio/imx_gpio.c
> +++ b/hw/gpio/imx_gpio.c
> @@ -331,7 +331,7 @@ static void imx_gpio_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = imx_gpio_realize;
>      dc->reset = imx_gpio_reset;
> -    dc->props = imx_gpio_properties;
> +    device_class_set_props(dc, imx_gpio_properties);
>      dc->vmsd = &vmstate_imx_gpio;
>      dc->desc = "i.MX GPIO controller";
>  }
> diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
> index dabef4a..66fbecb 100644
> --- a/hw/gpio/omap_gpio.c
> +++ b/hw/gpio/omap_gpio.c
> @@ -771,7 +771,7 @@ static void omap_gpio_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = omap_gpio_realize;
>      dc->reset = omap_gpif_reset;
> -    dc->props = omap_gpio_properties;
> +    device_class_set_props(dc, omap_gpio_properties);
>      /* Reason: pointer property "clk" */
>      dc->cannot_instantiate_with_device_add_yet = true;
>  }
> @@ -802,7 +802,7 @@ static void omap2_gpio_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = omap2_gpio_realize;
>      dc->reset = omap2_gpif_reset;
> -    dc->props = omap2_gpio_properties;
> +    device_class_set_props(dc, omap2_gpio_properties);
>      /* Reason: pointer properties "iclk", "fclk0", ..., "fclk5" */
>      dc->cannot_instantiate_with_device_add_yet = true;
>  }
> diff --git a/hw/i2c/core.c b/hw/i2c/core.c
> index abd4c4c..bb2c12a 100644
> --- a/hw/i2c/core.c
> +++ b/hw/i2c/core.c
> @@ -279,7 +279,7 @@ static void i2c_slave_class_init(ObjectClass *klass, void *data)
>      k->init = i2c_slave_qdev_init;
>      set_bit(DEVICE_CATEGORY_MISC, k->categories);
>      k->bus_type = TYPE_I2C_BUS;
> -    k->props = i2c_props;
> +    device_class_set_props(k, i2c_props);
>  }
>  
>  static const TypeInfo i2c_slave_type_info = {
> diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c
> index f7c92ea..2031009 100644
> --- a/hw/i2c/omap_i2c.c
> +++ b/hw/i2c/omap_i2c.c
> @@ -488,7 +488,7 @@ static void omap_i2c_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = omap_i2c_properties;
> +    device_class_set_props(dc, omap_i2c_properties);
>      dc->reset = omap_i2c_reset;
>      /* Reason: pointer properties "iclk", "fclk" */
>      dc->cannot_instantiate_with_device_add_yet = true;
> diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c
> index 5b7bd89..bbb5294 100644
> --- a/hw/i2c/smbus_eeprom.c
> +++ b/hw/i2c/smbus_eeprom.c
> @@ -121,7 +121,7 @@ static void smbus_eeprom_class_initfn(ObjectClass *klass, void *data)
>      sc->receive_byte = eeprom_receive_byte;
>      sc->write_data = eeprom_write_data;
>      sc->read_data = eeprom_read_data;
> -    dc->props = smbus_eeprom_properties;
> +    device_class_set_props(dc, smbus_eeprom_properties);
>      /* Reason: pointer property "data" */
>      dc->cannot_instantiate_with_device_add_yet = true;
>  }
> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
> index 1655a65..c2e119f 100644
> --- a/hw/i386/intel_iommu.c
> +++ b/hw/i386/intel_iommu.c
> @@ -2542,7 +2542,7 @@ static void vtd_class_init(ObjectClass *klass, void *data)
>  
>      dc->reset = vtd_reset;
>      dc->vmsd = &vtd_vmstate;
> -    dc->props = vtd_properties;
> +    device_class_set_props(dc, vtd_properties);
>      dc->hotpluggable = false;
>      x86_class->realize = vtd_realize;
>      x86_class->int_remap = vtd_int_remap;
> diff --git a/hw/i386/kvm/i8254.c b/hw/i386/kvm/i8254.c
> index 521a584..1586b8a 100644
> --- a/hw/i386/kvm/i8254.c
> +++ b/hw/i386/kvm/i8254.c
> @@ -320,7 +320,7 @@ static void kvm_pit_class_init(ObjectClass *klass, void *data)
>      k->set_channel_gate = kvm_pit_set_gate;
>      k->get_channel_info = kvm_pit_get_channel_info;
>      dc->reset = kvm_pit_reset;
> -    dc->props = kvm_pit_properties;
> +    device_class_set_props(dc, kvm_pit_properties);
>  }
>  
>  static const TypeInfo kvm_pit_info = {
> diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c
> index 8eb2c7a..e137d10 100644
> --- a/hw/i386/kvm/ioapic.c
> +++ b/hw/i386/kvm/ioapic.c
> @@ -161,7 +161,7 @@ static void kvm_ioapic_class_init(ObjectClass *klass, void *data)
>      k->pre_save  = kvm_ioapic_get;
>      k->post_load = kvm_ioapic_put;
>      dc->reset    = kvm_ioapic_reset;
> -    dc->props    = kvm_ioapic_properties;
> +    device_class_set_props(dc, kvm_ioapic_properties);
>  }
>  
>  static const TypeInfo kvm_ioapic_info = {
> diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c
> index 8238fbc..e6596d3 100644
> --- a/hw/i386/kvm/pci-assign.c
> +++ b/hw/i386/kvm/pci-assign.c
> @@ -1861,7 +1861,7 @@ static void assign_class_init(ObjectClass *klass, void *data)
>      k->exit         = assigned_exitfn;
>      k->config_read  = assigned_dev_pci_read_config;
>      k->config_write = assigned_dev_pci_write_config;
> -    dc->props       = assigned_dev_properties;
> +    device_class_set_props(dc, assigned_dev_properties);
>      dc->vmsd        = &vmstate_assigned_device;
>      dc->reset       = reset_assigned_device;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> diff --git a/hw/i386/xen/xen_pvdevice.c b/hw/i386/xen/xen_pvdevice.c
> index c093b34..1a6189f 100644
> --- a/hw/i386/xen/xen_pvdevice.c
> +++ b/hw/i386/xen/xen_pvdevice.c
> @@ -119,7 +119,7 @@ static void xen_pv_class_init(ObjectClass *klass, void *data)
>      k->realize = xen_pv_realize;
>      k->class_id = PCI_CLASS_SYSTEM_OTHER;
>      dc->desc = "Xen PV Device";
> -    dc->props = xen_pv_props;
> +    device_class_set_props(dc, xen_pv_props);
>  }
>  
>  static const TypeInfo xen_pv_type_info = {
> diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
> index 3c19bda..6956abd 100644
> --- a/hw/ide/ahci.c
> +++ b/hw/ide/ahci.c
> @@ -1706,7 +1706,7 @@ static void sysbus_ahci_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = sysbus_ahci_realize;
>      dc->vmsd = &vmstate_sysbus_ahci;
> -    dc->props = sysbus_ahci_properties;
> +    device_class_set_props(dc, sysbus_ahci_properties);
>      dc->reset = sysbus_ahci_reset;
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>  }
> diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
> index 9ebb8d4..029906d 100644
> --- a/hw/ide/cmd646.c
> +++ b/hw/ide/cmd646.c
> @@ -417,7 +417,7 @@ static void cmd646_ide_class_init(ObjectClass *klass, void *data)
>      k->class_id = PCI_CLASS_STORAGE_IDE;
>      k->config_read = cmd646_pci_config_read;
>      k->config_write = cmd646_pci_config_write;
> -    dc->props = cmd646_ide_properties;
> +    device_class_set_props(dc, cmd646_ide_properties);
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>  }
>  
> diff --git a/hw/ide/isa.c b/hw/ide/isa.c
> index 40213d6..66f7c6b 100644
> --- a/hw/ide/isa.c
> +++ b/hw/ide/isa.c
> @@ -116,7 +116,7 @@ static void isa_ide_class_initfn(ObjectClass *klass, void *data)
>      dc->realize = isa_ide_realizefn;
>      dc->fw_name = "ide";
>      dc->reset = isa_ide_reset;
> -    dc->props = isa_ide_properties;
> +    device_class_set_props(dc, isa_ide_properties);
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>  }
>  
> diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
> index 6f12f45..1f48be8 100644
> --- a/hw/ide/mmio.c
> +++ b/hw/ide/mmio.c
> @@ -152,7 +152,7 @@ static void mmio_ide_class_init(ObjectClass *oc, void *data)
>  
>      dc->realize = mmio_ide_realizefn;
>      dc->reset = mmio_ide_reset;
> -    dc->props = mmio_ide_properties;
> +    device_class_set_props(dc, mmio_ide_properties);
>      dc->vmsd = &vmstate_ide_mmio;
>  }
>  
> diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
> index dbaa75c..430b535 100644
> --- a/hw/ide/qdev.c
> +++ b/hw/ide/qdev.c
> @@ -305,7 +305,7 @@ static void ide_hd_class_init(ObjectClass *klass, void *data)
>      k->init = ide_hd_initfn;
>      dc->fw_name = "drive";
>      dc->desc = "virtual IDE disk";
> -    dc->props = ide_hd_properties;
> +    device_class_set_props(dc, ide_hd_properties);
>  }
>  
>  static const TypeInfo ide_hd_info = {
> @@ -327,7 +327,7 @@ static void ide_cd_class_init(ObjectClass *klass, void *data)
>      k->init = ide_cd_initfn;
>      dc->fw_name = "drive";
>      dc->desc = "virtual IDE CD-ROM";
> -    dc->props = ide_cd_properties;
> +    device_class_set_props(dc, ide_cd_properties);
>  }
>  
>  static const TypeInfo ide_cd_info = {
> @@ -349,7 +349,7 @@ static void ide_drive_class_init(ObjectClass *klass, void *data)
>      k->init = ide_drive_initfn;
>      dc->fw_name = "drive";
>      dc->desc = "virtual IDE disk or CD-ROM (legacy)";
> -    dc->props = ide_drive_properties;
> +    device_class_set_props(dc, ide_drive_properties);
>  }
>  
>  static const TypeInfo ide_drive_info = {
> @@ -366,7 +366,7 @@ static void ide_device_class_init(ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
>      k->bus_type = TYPE_IDE_BUS;
>      k->unrealize = idebus_unrealize;
> -    k->props = ide_props;
> +    device_class_set_props(k, ide_props);
>  }
>  
>  static const TypeInfo ide_device_type_info = {
> diff --git a/hw/input/milkymist-softusb.c b/hw/input/milkymist-softusb.c
> index 40dfca1..7f577d3 100644
> --- a/hw/input/milkymist-softusb.c
> +++ b/hw/input/milkymist-softusb.c
> @@ -301,7 +301,7 @@ static void milkymist_softusb_class_init(ObjectClass *klass, void *data)
>      k->init = milkymist_softusb_init;
>      dc->reset = milkymist_softusb_reset;
>      dc->vmsd = &vmstate_milkymist_softusb;
> -    dc->props = milkymist_softusb_properties;
> +    device_class_set_props(dc, milkymist_softusb_properties);
>  }
>  
>  static const TypeInfo milkymist_softusb_info = {
> diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c
> index 3ee0c18..9ded80f 100644
> --- a/hw/input/virtio-input-hid.c
> +++ b/hw/input/virtio-input-hid.c
> @@ -327,7 +327,7 @@ static void virtio_input_hid_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
>  
> -    dc->props          = virtio_input_hid_properties;
> +    device_class_set_props(dc, virtio_input_hid_properties);
>      vic->realize       = virtio_input_hid_realize;
>      vic->unrealize     = virtio_input_hid_unrealize;
>      vic->change_active = virtio_input_hid_change_active;
> diff --git a/hw/input/virtio-input-host.c b/hw/input/virtio-input-host.c
> index cb79e80..e122a68 100644
> --- a/hw/input/virtio-input-host.c
> +++ b/hw/input/virtio-input-host.c
> @@ -226,7 +226,7 @@ static void virtio_input_host_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->vmsd           = &vmstate_virtio_input_host;
> -    dc->props          = virtio_input_host_properties;
> +    device_class_set_props(dc, virtio_input_host_properties);
>      vic->realize       = virtio_input_host_realize;
>      vic->unrealize     = virtio_input_host_unrealize;
>      vic->handle_status = virtio_input_host_handle_status;
> diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c
> index b678ee9..039457e 100644
> --- a/hw/input/virtio-input.c
> +++ b/hw/input/virtio-input.c
> @@ -310,7 +310,7 @@ static void virtio_input_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
>  
> -    dc->props          = virtio_input_properties;
> +    device_class_set_props(dc, virtio_input_properties);
>      dc->vmsd           = &vmstate_virtio_input;
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>      vdc->realize      = virtio_input_device_realize;
> diff --git a/hw/input/vmmouse.c b/hw/input/vmmouse.c
> index 6d15a88..5778a8b 100644
> --- a/hw/input/vmmouse.c
> +++ b/hw/input/vmmouse.c
> @@ -284,7 +284,7 @@ static void vmmouse_class_initfn(ObjectClass *klass, void *data)
>      dc->realize = vmmouse_realizefn;
>      dc->reset = vmmouse_reset;
>      dc->vmsd = &vmstate_vmmouse;
> -    dc->props = vmmouse_properties;
> +    device_class_set_props(dc, vmmouse_properties);
>      /* Reason: pointer property "ps2_mouse" */
>      dc->cannot_instantiate_with_device_add_yet = true;
>  }
> diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
> index d78c885..113b9e1 100644
> --- a/hw/intc/apic_common.c
> +++ b/hw/intc/apic_common.c
> @@ -491,7 +491,7 @@ static void apic_common_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->reset = apic_reset_common;
> -    dc->props = apic_properties_common;
> +    device_class_set_props(dc, apic_properties_common);
>      dc->realize = apic_common_realize;
>      dc->unrealize = apic_common_unrealize;
>      /*
> diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
> index 0a1f56a..b48a588 100644
> --- a/hw/intc/arm_gic_common.c
> +++ b/hw/intc/arm_gic_common.c
> @@ -264,7 +264,7 @@ static void arm_gic_common_class_init(ObjectClass *klass, void *data)
>  
>      dc->reset = arm_gic_common_reset;
>      dc->realize = arm_gic_common_realize;
> -    dc->props = arm_gic_common_properties;
> +    device_class_set_props(dc, arm_gic_common_properties);
>      dc->vmsd = &vmstate_gic;
>      albifc->arm_linux_init = arm_gic_common_linux_init;
>  }
> diff --git a/hw/intc/arm_gicv2m.c b/hw/intc/arm_gicv2m.c
> index 3922fbc..3d99e73 100644
> --- a/hw/intc/arm_gicv2m.c
> +++ b/hw/intc/arm_gicv2m.c
> @@ -176,7 +176,7 @@ static void gicv2m_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = gicv2m_properties;
> +    device_class_set_props(dc, gicv2m_properties);
>      dc->realize = gicv2m_realize;
>  }
>  
> diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
> index 0f8c4b8..67cc7e3 100644
> --- a/hw/intc/arm_gicv3_common.c
> +++ b/hw/intc/arm_gicv3_common.c
> @@ -325,7 +325,7 @@ static void arm_gicv3_common_class_init(ObjectClass *klass, void *data)
>  
>      dc->reset = arm_gicv3_common_reset;
>      dc->realize = arm_gicv3_common_realize;
> -    dc->props = arm_gicv3_common_properties;
> +    device_class_set_props(dc, arm_gicv3_common_properties);
>      dc->vmsd = &vmstate_gicv3;
>      albifc->arm_linux_init = arm_gic_common_linux_init;
>  }
> diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c
> index 64a6f4b..00f9268 100644
> --- a/hw/intc/etraxfs_pic.c
> +++ b/hw/intc/etraxfs_pic.c
> @@ -170,7 +170,7 @@ static void etraxfs_pic_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = etraxfs_pic_properties;
> +    device_class_set_props(dc, etraxfs_pic_properties);
>      /*
>       * Note: pointer property "interrupt_vector" may remain null, thus
>       * no need for dc->cannot_instantiate_with_device_add_yet = true;
> diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
> index f19a706..8b2bb68 100644
> --- a/hw/intc/exynos4210_combiner.c
> +++ b/hw/intc/exynos4210_combiner.c
> @@ -437,7 +437,7 @@ static void exynos4210_combiner_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->reset = exynos4210_combiner_reset;
> -    dc->props = exynos4210_combiner_properties;
> +    device_class_set_props(dc, exynos4210_combiner_properties);
>      dc->vmsd = &vmstate_exynos4210_combiner;
>  }
>  
> diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
> index fd7a8f3..1135335 100644
> --- a/hw/intc/exynos4210_gic.c
> +++ b/hw/intc/exynos4210_gic.c
> @@ -346,7 +346,7 @@ static void exynos4210_gic_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = exynos4210_gic_properties;
> +    device_class_set_props(dc, exynos4210_gic_properties);
>  }
>  
>  static const TypeInfo exynos4210_gic_info = {
> @@ -453,7 +453,7 @@ static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data)
>  
>      dc->reset = exynos4210_irq_gate_reset;
>      dc->vmsd = &vmstate_exynos4210_irq_gate;
> -    dc->props = exynos4210_irq_gate_properties;
> +    device_class_set_props(dc, exynos4210_irq_gate_properties);
>      dc->realize = exynos4210_irq_gate_realize;
>  }
>  
> diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c
> index ac7e63f..929dc06 100644
> --- a/hw/intc/grlib_irqmp.c
> +++ b/hw/intc/grlib_irqmp.c
> @@ -358,7 +358,7 @@ static void grlib_irqmp_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->reset = grlib_irqmp_reset;
> -    dc->props = grlib_irqmp_properties;
> +    device_class_set_props(dc, grlib_irqmp_properties);
>      /* Reason: pointer properties "set_pil_in", "set_pil_in_opaque" */
>      dc->cannot_instantiate_with_device_add_yet = true;
>      dc->realize = grlib_irqmp_realize;
> diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c
> index d9a5e8b..846fadb 100644
> --- a/hw/intc/i8259_common.c
> +++ b/hw/intc/i8259_common.c
> @@ -136,7 +136,7 @@ static void pic_common_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->vmsd = &vmstate_pic_common;
> -    dc->props = pic_properties_common;
> +    device_class_set_props(dc, pic_properties_common);
>      dc->realize = pic_common_realize;
>      /*
>       * Reason: unlike ordinary ISA devices, the PICs need additional
> diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c
> index fd9208f..0112066 100644
> --- a/hw/intc/ioapic.c
> +++ b/hw/intc/ioapic.c
> @@ -427,7 +427,7 @@ static void ioapic_class_init(ObjectClass *klass, void *data)
>  
>      k->realize = ioapic_realize;
>      dc->reset = ioapic_reset_common;
> -    dc->props = ioapic_properties;
> +    device_class_set_props(dc, ioapic_properties);
>  }
>  
>  static const TypeInfo ioapic_info = {
> diff --git a/hw/intc/mips_gic.c b/hw/intc/mips_gic.c
> index 6e25773..cdd4d74 100644
> --- a/hw/intc/mips_gic.c
> +++ b/hw/intc/mips_gic.c
> @@ -440,7 +440,7 @@ static void mips_gic_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = mips_gic_properties;
> +    device_class_set_props(dc, mips_gic_properties);
>      dc->realize = mips_gic_realize;
>  }
>  
> diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
> index 877be67..8f357c1 100644
> --- a/hw/intc/omap_intc.c
> +++ b/hw/intc/omap_intc.c
> @@ -399,7 +399,7 @@ static void omap_intc_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->reset = omap_inth_reset;
> -    dc->props = omap_intc_properties;
> +    device_class_set_props(dc, omap_intc_properties);
>      /* Reason: pointer property "clk" */
>      dc->cannot_instantiate_with_device_add_yet = true;
>      dc->realize = omap_intc_realize;
> @@ -654,7 +654,7 @@ static void omap2_intc_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->reset = omap_inth_reset;
> -    dc->props = omap2_intc_properties;
> +    device_class_set_props(dc, omap2_intc_properties);
>      /* Reason: pointer property "iclk", "fclk" */
>      dc->cannot_instantiate_with_device_add_yet = true;
>      dc->realize = omap2_intc_realize;
> diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
> index 4349e45..1262b89 100644
> --- a/hw/intc/openpic.c
> +++ b/hw/intc/openpic.c
> @@ -1643,7 +1643,7 @@ static void openpic_class_init(ObjectClass *oc, void *data)
>      DeviceClass *dc = DEVICE_CLASS(oc);
>  
>      dc->realize = openpic_realize;
> -    dc->props = openpic_properties;
> +    device_class_set_props(dc, openpic_properties);
>      dc->reset = openpic_reset;
>      dc->vmsd = &vmstate_openpic;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c
> index 0518e01..1d178d7 100644
> --- a/hw/intc/openpic_kvm.c
> +++ b/hw/intc/openpic_kvm.c
> @@ -277,7 +277,7 @@ static void kvm_openpic_class_init(ObjectClass *oc, void *data)
>      DeviceClass *dc = DEVICE_CLASS(oc);
>  
>      dc->realize = kvm_openpic_realize;
> -    dc->props = kvm_openpic_properties;
> +    device_class_set_props(dc, kvm_openpic_properties);
>      dc->reset = kvm_openpic_reset;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>  }
> diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c
> index 9d8139b..8a5b64c 100644
> --- a/hw/intc/xilinx_intc.c
> +++ b/hw/intc/xilinx_intc.c
> @@ -183,7 +183,7 @@ static void xilinx_intc_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = xilinx_intc_properties;
> +    device_class_set_props(dc, xilinx_intc_properties);
>  }
>  
>  static const TypeInfo xilinx_intc_info = {
> diff --git a/hw/ipack/ipack.c b/hw/ipack/ipack.c
> index 6021e6d..a052d97 100644
> --- a/hw/ipack/ipack.c
> +++ b/hw/ipack/ipack.c
> @@ -84,7 +84,7 @@ static void ipack_device_class_init(ObjectClass *klass, void *data)
>      k->bus_type = TYPE_IPACK_BUS;
>      k->realize = ipack_device_realize;
>      k->unrealize = ipack_device_unrealize;
> -    k->props = ipack_device_props;
> +    device_class_set_props(k, ipack_device_props);
>  }
>  
>  const VMStateDescription vmstate_ipack_device = {
> diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
> index f09f217..971c0d7 100644
> --- a/hw/ipmi/ipmi.c
> +++ b/hw/ipmi/ipmi.c
> @@ -110,7 +110,7 @@ static void bmc_class_init(ObjectClass *oc, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(oc);
>  
> -    dc->props = ipmi_bmc_properties;
> +    device_class_set_props(dc, ipmi_bmc_properties);
>  }
>  
>  static TypeInfo ipmi_bmc_type_info = {
> diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c
> index 4b310e5..3a4e61a 100644
> --- a/hw/ipmi/ipmi_bmc_extern.c
> +++ b/hw/ipmi/ipmi_bmc_extern.c
> @@ -513,7 +513,7 @@ static void ipmi_bmc_extern_class_init(ObjectClass *oc, void *data)
>      bk->handle_command = ipmi_bmc_extern_handle_command;
>      bk->handle_reset = ipmi_bmc_extern_handle_reset;
>      dc->realize = ipmi_bmc_extern_realize;
> -    dc->props = ipmi_bmc_extern_properties;
> +    device_class_set_props(dc, ipmi_bmc_extern_properties);
>  }
>  
>  static const TypeInfo ipmi_bmc_extern_type = {
> diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c
> index f036617..d133ed4 100644
> --- a/hw/ipmi/isa_ipmi_bt.c
> +++ b/hw/ipmi/isa_ipmi_bt.c
> @@ -511,7 +511,7 @@ static void isa_ipmi_bt_class_init(ObjectClass *oc, void *data)
>      IPMIInterfaceClass *iic = IPMI_INTERFACE_CLASS(oc);
>  
>      dc->realize = isa_ipmi_bt_realize;
> -    dc->props = ipmi_isa_properties;
> +    device_class_set_props(dc, ipmi_isa_properties);
>  
>      iic->get_backend_data = isa_ipmi_bt_get_backend_data;
>      ipmi_bt_class_init(iic);
> diff --git a/hw/ipmi/isa_ipmi_kcs.c b/hw/ipmi/isa_ipmi_kcs.c
> index 9a38f8a..90c7532 100644
> --- a/hw/ipmi/isa_ipmi_kcs.c
> +++ b/hw/ipmi/isa_ipmi_kcs.c
> @@ -475,7 +475,7 @@ static void isa_ipmi_kcs_class_init(ObjectClass *oc, void *data)
>      IPMIInterfaceClass *iic = IPMI_INTERFACE_CLASS(oc);
>  
>      dc->realize = ipmi_isa_realize;
> -    dc->props = ipmi_isa_properties;
> +    device_class_set_props(dc, ipmi_isa_properties);
>  
>      iic->get_backend_data = isa_ipmi_kcs_get_backend_data;
>      ipmi_kcs_class_init(iic);
> diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
> index 10d1ee8..c7ed99a 100644
> --- a/hw/isa/lpc_ich9.c
> +++ b/hw/isa/lpc_ich9.c
> @@ -710,7 +710,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data)
>      dc->reset = ich9_lpc_reset;
>      k->realize = ich9_lpc_realize;
>      dc->vmsd = &vmstate_ich9_lpc;
> -    dc->props = ich9_lpc_properties;
> +    device_class_set_props(dc, ich9_lpc_properties);
>      k->config_write = ich9_lpc_config_write;
>      dc->desc = "ICH9 LPC bridge";
>      k->vendor_id = PCI_VENDOR_ID_INTEL;
> diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c
> index b1c1a0a..ec0effc 100644
> --- a/hw/isa/pc87312.c
> +++ b/hw/isa/pc87312.c
> @@ -385,7 +385,7 @@ static void pc87312_class_init(ObjectClass *klass, void *data)
>      dc->realize = pc87312_realize;
>      dc->reset = pc87312_reset;
>      dc->vmsd = &vmstate_pc87312;
> -    dc->props = pc87312_properties;
> +    device_class_set_props(dc, pc87312_properties);
>  }
>  
>  static const TypeInfo pc87312_type_info = {
> diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
> index 41d5254..ddf5c89 100644
> --- a/hw/isa/vt82c686.c
> +++ b/hw/isa/vt82c686.c
> @@ -411,7 +411,7 @@ static void via_pm_class_init(ObjectClass *klass, void *data)
>      dc->desc = "PM";
>      dc->vmsd = &vmstate_acpi;
>      set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
> -    dc->props = via_pm_properties;
> +    device_class_set_props(dc, via_pm_properties);
>  }
>  
>  static const TypeInfo via_pm_info = {
> diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
> index 9e8dab0..f8aa649 100644
> --- a/hw/mem/pc-dimm.c
> +++ b/hw/mem/pc-dimm.c
> @@ -443,7 +443,7 @@ static void pc_dimm_class_init(ObjectClass *oc, void *data)
>  
>      dc->realize = pc_dimm_realize;
>      dc->unrealize = pc_dimm_unrealize;
> -    dc->props = pc_dimm_properties;
> +    device_class_set_props(dc, pc_dimm_properties);
>      dc->desc = "DIMM memory module";
>  
>      ddc->get_memory_region = pc_dimm_get_memory_region;
> diff --git a/hw/mips/cps.c b/hw/mips/cps.c
> index 4ef337d..1753d82 100644
> --- a/hw/mips/cps.c
> +++ b/hw/mips/cps.c
> @@ -173,7 +173,7 @@ static void mips_cps_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = mips_cps_realize;
> -    dc->props = mips_cps_properties;
> +    device_class_set_props(dc, mips_cps_properties);
>  }
>  
>  static const TypeInfo mips_cps_info = {
> diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
> index 3e8ad8c..687656f 100644
> --- a/hw/misc/a9scu.c
> +++ b/hw/misc/a9scu.c
> @@ -132,7 +132,7 @@ static void a9_scu_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = a9_scu_properties;
> +    device_class_set_props(dc, a9_scu_properties);
>      dc->vmsd = &vmstate_a9_scu;
>      dc->reset = a9_scu_reset;
>  }
> diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
> index 77fab5b..99ea90d 100644
> --- a/hw/misc/applesmc.c
> +++ b/hw/misc/applesmc.c
> @@ -261,7 +261,7 @@ static void qdev_applesmc_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = applesmc_isa_realize;
>      dc->reset = qdev_applesmc_isa_reset;
> -    dc->props = applesmc_isa_properties;
> +    device_class_set_props(dc, applesmc_isa_properties);
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>  }
>  
> diff --git a/hw/misc/arm11scu.c b/hw/misc/arm11scu.c
> index 7042ce1..f8c103d 100644
> --- a/hw/misc/arm11scu.c
> +++ b/hw/misc/arm11scu.c
> @@ -83,7 +83,7 @@ static void arm11_scu_class_init(ObjectClass *oc, void *data)
>      DeviceClass *dc = DEVICE_CLASS(oc);
>  
>      dc->realize = arm11_scu_realize;
> -    dc->props = arm11_scu_properties;
> +    device_class_set_props(dc, arm11_scu_properties);
>  }
>  
>  static const TypeInfo arm11_scu_type_info = {
> diff --git a/hw/misc/arm_l2x0.c b/hw/misc/arm_l2x0.c
> index 66a0787..ac35ae3 100644
> --- a/hw/misc/arm_l2x0.c
> +++ b/hw/misc/arm_l2x0.c
> @@ -179,7 +179,7 @@ static void l2x0_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->vmsd = &vmstate_l2x0;
> -    dc->props = l2x0_properties;
> +    device_class_set_props(dc, l2x0_properties);
>      dc->reset = l2x0_priv_reset;
>  }
>  
> diff --git a/hw/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c
> index 8524008..2d43904 100644
> --- a/hw/misc/arm_sysctl.c
> +++ b/hw/misc/arm_sysctl.c
> @@ -639,7 +639,7 @@ static void arm_sysctl_class_init(ObjectClass *klass, void *data)
>      dc->realize = arm_sysctl_realize;
>      dc->reset = arm_sysctl_reset;
>      dc->vmsd = &vmstate_arm_sysctl;
> -    dc->props = arm_sysctl_properties;
> +    device_class_set_props(dc, arm_sysctl_properties);
>  }
>  
>  static const TypeInfo arm_sysctl_info = {
> diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
> index b1f3e6f..885048f 100644
> --- a/hw/misc/aspeed_scu.c
> +++ b/hw/misc/aspeed_scu.c
> @@ -307,7 +307,7 @@ static void aspeed_scu_class_init(ObjectClass *klass, void *data)
>      dc->reset = aspeed_scu_reset;
>      dc->desc = "ASPEED System Control Unit";
>      dc->vmsd = &vmstate_aspeed_scu;
> -    dc->props = aspeed_scu_properties;
> +    device_class_set_props(dc, aspeed_scu_properties);
>  }
>  
>  static const TypeInfo aspeed_scu_info = {
> diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
> index 8830dc0..7830b25 100644
> --- a/hw/misc/aspeed_sdmc.c
> +++ b/hw/misc/aspeed_sdmc.c
> @@ -262,7 +262,7 @@ static void aspeed_sdmc_class_init(ObjectClass *klass, void *data)
>      dc->reset = aspeed_sdmc_reset;
>      dc->desc = "ASPEED SDRAM Memory Controller";
>      dc->vmsd = &vmstate_aspeed_sdmc;
> -    dc->props = aspeed_sdmc_properties;
> +    device_class_set_props(dc, aspeed_sdmc_properties);
>  }
>  
>  static const TypeInfo aspeed_sdmc_info = {
> diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
> index 70eaafd..522d580 100644
> --- a/hw/misc/bcm2835_property.c
> +++ b/hw/misc/bcm2835_property.c
> @@ -419,7 +419,7 @@ static void bcm2835_property_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = bcm2835_property_props;
> +    device_class_set_props(dc, bcm2835_property_props);
>      dc->realize = bcm2835_property_realize;
>      dc->vmsd = &vmstate_bcm2835_property;
>  }
> diff --git a/hw/misc/debugexit.c b/hw/misc/debugexit.c
> index 84fa1a5..f729901 100644
> --- a/hw/misc/debugexit.c
> +++ b/hw/misc/debugexit.c
> @@ -58,7 +58,7 @@ static void debug_exit_class_initfn(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = debug_exit_realizefn;
> -    dc->props = debug_exit_properties;
> +    device_class_set_props(dc, debug_exit_properties);
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>  }
>  
> diff --git a/hw/misc/eccmemctl.c b/hw/misc/eccmemctl.c
> index a0071f3..b9c0e17 100644
> --- a/hw/misc/eccmemctl.c
> +++ b/hw/misc/eccmemctl.c
> @@ -326,7 +326,7 @@ static void ecc_class_init(ObjectClass *klass, void *data)
>      k->init = ecc_init1;
>      dc->reset = ecc_reset;
>      dc->vmsd = &vmstate_ecc;
> -    dc->props = ecc_properties;
> +    device_class_set_props(dc, ecc_properties);
>  }
>  
>  static const TypeInfo ecc_info = {
> diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
> index 230e51b..81a5796 100644
> --- a/hw/misc/ivshmem.c
> +++ b/hw/misc/ivshmem.c
> @@ -1074,7 +1074,7 @@ static void ivshmem_plain_class_init(ObjectClass *klass, void *data)
>  
>      k->realize = ivshmem_plain_realize;
>      k->exit = ivshmem_plain_exit;
> -    dc->props = ivshmem_plain_properties;
> +    device_class_set_props(dc, ivshmem_plain_properties);
>      dc->vmsd = &ivshmem_plain_vmsd;
>  }
>  
> @@ -1136,7 +1136,7 @@ static void ivshmem_doorbell_class_init(ObjectClass *klass, void *data)
>      PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
>  
>      k->realize = ivshmem_doorbell_realize;
> -    dc->props = ivshmem_doorbell_properties;
> +    device_class_set_props(dc, ivshmem_doorbell_properties);
>      dc->vmsd = &ivshmem_doorbell_vmsd;
>  }
>  
> @@ -1304,7 +1304,7 @@ static void ivshmem_class_init(ObjectClass *klass, void *data)
>      k->realize = ivshmem_realize;
>      k->revision = 0;
>      dc->desc = "Inter-VM shared memory (legacy)";
> -    dc->props = ivshmem_properties;
> +    device_class_set_props(dc, ivshmem_properties);
>      dc->vmsd = &ivshmem_vmsd;
>  }
>  
> diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
> index 05c02fb..6e0dd0c 100644
> --- a/hw/misc/macio/cuda.c
> +++ b/hw/misc/macio/cuda.c
> @@ -945,7 +945,7 @@ static void cuda_class_init(ObjectClass *oc, void *data)
>      dc->realize = cuda_realizefn;
>      dc->reset = cuda_reset;
>      dc->vmsd = &vmstate_cuda;
> -    dc->props = cuda_properties;
> +    device_class_set_props(dc, cuda_properties);
>      set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
>  }
>  
> diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
> index 5d57f45..8708985 100644
> --- a/hw/misc/macio/macio.c
> +++ b/hw/misc/macio/macio.c
> @@ -388,7 +388,7 @@ static void macio_class_init(ObjectClass *klass, void *data)
>  
>      k->vendor_id = PCI_VENDOR_ID_APPLE;
>      k->class_id = PCI_CLASS_OTHERS << 8;
> -    dc->props = macio_properties;
> +    device_class_set_props(dc, macio_properties);
>      set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
>  }
>  
> diff --git a/hw/misc/mips_cmgcr.c b/hw/misc/mips_cmgcr.c
> index b3ba166..c103ded 100644
> --- a/hw/misc/mips_cmgcr.c
> +++ b/hw/misc/mips_cmgcr.c
> @@ -224,7 +224,7 @@ static void mips_gcr_realize(DeviceState *dev, Error **errp)
>  static void mips_gcr_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> -    dc->props = mips_gcr_properties;
> +    device_class_set_props(dc, mips_gcr_properties);
>      dc->vmsd = &vmstate_mips_gcr;
>      dc->reset = mips_gcr_reset;
>      dc->realize = mips_gcr_realize;
> diff --git a/hw/misc/mips_cpc.c b/hw/misc/mips_cpc.c
> index 6d34574..52661ca 100644
> --- a/hw/misc/mips_cpc.c
> +++ b/hw/misc/mips_cpc.c
> @@ -159,7 +159,7 @@ static void mips_cpc_class_init(ObjectClass *klass, void *data)
>      dc->realize = mips_cpc_realize;
>      dc->reset = mips_cpc_reset;
>      dc->vmsd = &vmstate_mips_cpc;
> -    dc->props = mips_cpc_properties;
> +    device_class_set_props(dc, mips_cpc_properties);
>  }
>  
>  static const TypeInfo mips_cpc_info = {
> diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c
> index ef935b5..a148a28 100644
> --- a/hw/misc/mips_itu.c
> +++ b/hw/misc/mips_itu.c
> @@ -503,7 +503,7 @@ static void mips_itu_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = mips_itu_properties;
> +    device_class_set_props(dc, mips_itu_properties);
>      dc->realize = mips_itu_realize;
>      dc->reset = mips_itu_reset;
>  }
> diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
> index 0ac1e6a..14b7cfb 100644
> --- a/hw/misc/pvpanic.c
> +++ b/hw/misc/pvpanic.c
> @@ -124,7 +124,7 @@ static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = pvpanic_isa_realizefn;
> -    dc->props = pvpanic_isa_properties;
> +    device_class_set_props(dc, pvpanic_isa_properties);
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>  }
>  
> diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c
> index 50e8361..2132d8a 100644
> --- a/hw/net/allwinner_emac.c
> +++ b/hw/net/allwinner_emac.c
> @@ -514,7 +514,7 @@ static void aw_emac_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = aw_emac_realize;
> -    dc->props = aw_emac_properties;
> +    device_class_set_props(dc, aw_emac_properties);
>      dc->reset = aw_emac_reset;
>      dc->vmsd = &vmstate_aw_emac;
>  }
> diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
> index 7915732..d0c0b26 100644
> --- a/hw/net/cadence_gem.c
> +++ b/hw/net/cadence_gem.c
> @@ -1522,7 +1522,7 @@ static void gem_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = gem_realize;
> -    dc->props = gem_properties;
> +    device_class_set_props(dc, gem_properties);
>      dc->vmsd = &vmstate_cadence_gem;
>      dc->reset = gem_reset;
>  }
> diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
> index 17f0338..a165886 100644
> --- a/hw/net/dp8393x.c
> +++ b/hw/net/dp8393x.c
> @@ -891,7 +891,7 @@ static void dp8393x_class_init(ObjectClass *klass, void *data)
>      dc->realize = dp8393x_realize;
>      dc->reset = dp8393x_reset;
>      dc->vmsd = &vmstate_dp8393x;
> -    dc->props = dp8393x_properties;
> +    device_class_set_props(dc, dp8393x_properties);
>      /* Reason: dma_mr property can't be set */
>      dc->cannot_instantiate_with_device_add_yet = true;
>  }
> diff --git a/hw/net/e1000.c b/hw/net/e1000.c
> index 9324949..0df3f2f 100644
> --- a/hw/net/e1000.c
> +++ b/hw/net/e1000.c
> @@ -1667,7 +1667,7 @@ static void e1000_class_init(ObjectClass *klass, void *data)
>      dc->desc = "Intel Gigabit Ethernet";
>      dc->reset = qdev_e1000_reset;
>      dc->vmsd = &vmstate_e1000;
> -    dc->props = e1000_properties;
> +    device_class_set_props(dc, e1000_properties);
>  }
>  
>  static void e1000_instance_init(Object *obj)
> diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
> index 4994e1c..032d90f 100644
> --- a/hw/net/e1000e.c
> +++ b/hw/net/e1000e.c
> @@ -671,7 +671,6 @@ static void e1000e_class_init(ObjectClass *class, void *data)
>      dc->desc = "Intel 82574L GbE Controller";
>      dc->reset = e1000e_qdev_reset;
>      dc->vmsd = &e1000e_vmstate;
> -    dc->props = e1000e_properties;
>  
>      e1000e_prop_disable_vnet = qdev_prop_uint8;
>      e1000e_prop_disable_vnet.description = "Do not use virtio headers, "
> @@ -684,6 +683,8 @@ static void e1000e_class_init(ObjectClass *class, void *data)
>      e1000e_prop_subsys = qdev_prop_uint16;
>      e1000e_prop_subsys.description = "PCI device Subsystem ID";
>  
> +    device_class_set_props(dc, e1000e_properties);
> +
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
>  }
>  
> diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
> index 4bf71f2..9de9169 100644
> --- a/hw/net/eepro100.c
> +++ b/hw/net/eepro100.c
> @@ -2082,7 +2082,7 @@ static void eepro100_class_init(ObjectClass *klass, void *data)
>      info = eepro100_get_class_by_name(object_class_get_name(klass));
>  
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
> -    dc->props = e100_properties;
> +    device_class_set_props(dc, e100_properties);
>      dc->desc = info->desc;
>      k->vendor_id = PCI_VENDOR_ID_INTEL;
>      k->class_id = PCI_CLASS_NETWORK_ETHERNET;
> diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c
> index efaa49f..2070e75 100644
> --- a/hw/net/etraxfs_eth.c
> +++ b/hw/net/etraxfs_eth.c
> @@ -628,7 +628,7 @@ static void etraxfs_eth_class_init(ObjectClass *klass, void *data)
>      SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
>  
>      k->init = fs_eth_init;
> -    dc->props = etraxfs_eth_properties;
> +    device_class_set_props(dc, etraxfs_eth_properties);
>      /* Reason: pointer properties "dma_out", "dma_in" */
>      dc->cannot_instantiate_with_device_add_yet = true;
>  }
> diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c
> index 951c5f0..ca3e78f 100644
> --- a/hw/net/fsl_etsec/etsec.c
> +++ b/hw/net/fsl_etsec/etsec.c
> @@ -416,7 +416,7 @@ static void etsec_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = etsec_realize;
>      dc->reset = etsec_reset;
> -    dc->props = etsec_properties;
> +    device_class_set_props(dc, etsec_properties);
>  }
>  
>  static TypeInfo etsec_info = {
> diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
> index 50c7564..a4ac141 100644
> --- a/hw/net/imx_fec.c
> +++ b/hw/net/imx_fec.c
> @@ -1189,7 +1189,7 @@ static void imx_eth_class_init(ObjectClass *klass, void *data)
>  
>      dc->vmsd    = &vmstate_imx_eth;
>      dc->reset   = imx_eth_reset;
> -    dc->props   = imx_eth_properties;
> +    device_class_set_props(dc, imx_eth_properties);
>      dc->realize = imx_eth_realize;
>      dc->desc    = "i.MX FEC/ENET Ethernet Controller";
>  }
> diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
> index 3db8937..cf8b4f0 100644
> --- a/hw/net/lan9118.c
> +++ b/hw/net/lan9118.c
> @@ -1365,7 +1365,7 @@ static void lan9118_class_init(ObjectClass *klass, void *data)
>  
>      k->init = lan9118_init1;
>      dc->reset = lan9118_reset;
> -    dc->props = lan9118_properties;
> +    device_class_set_props(dc, lan9118_properties);
>      dc->vmsd = &vmstate_lan9118;
>  }
>  
> diff --git a/hw/net/lance.c b/hw/net/lance.c
> index 573d724..c4796fa 100644
> --- a/hw/net/lance.c
> +++ b/hw/net/lance.c
> @@ -163,7 +163,7 @@ static void lance_class_init(ObjectClass *klass, void *data)
>      dc->fw_name = "ethernet";
>      dc->reset = lance_reset;
>      dc->vmsd = &vmstate_lance;
> -    dc->props = lance_properties;
> +    device_class_set_props(dc, lance_properties);
>      /* Reason: pointer property "dma" */
>      dc->cannot_instantiate_with_device_add_yet = true;
>  }
> diff --git a/hw/net/milkymist-minimac2.c b/hw/net/milkymist-minimac2.c
> index c3a12e1..6aaeaf0 100644
> --- a/hw/net/milkymist-minimac2.c
> +++ b/hw/net/milkymist-minimac2.c
> @@ -526,7 +526,7 @@ static void milkymist_minimac2_class_init(ObjectClass *klass, void *data)
>      k->init = milkymist_minimac2_init;
>      dc->reset = milkymist_minimac2_reset;
>      dc->vmsd = &vmstate_milkymist_minimac2;
> -    dc->props = milkymist_minimac2_properties;
> +    device_class_set_props(dc, milkymist_minimac2_properties);
>  }
>  
>  static const TypeInfo milkymist_minimac2_info = {
> diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c
> index 5a63df7..3cc735d 100644
> --- a/hw/net/mipsnet.c
> +++ b/hw/net/mipsnet.c
> @@ -274,7 +274,7 @@ static void mipsnet_class_init(ObjectClass *klass, void *data)
>      dc->desc = "MIPS Simulator network device";
>      dc->reset = mipsnet_sysbus_reset;
>      dc->vmsd = &vmstate_mipsnet;
> -    dc->props = mipsnet_properties;
> +    device_class_set_props(dc, mipsnet_properties);
>  }
>  
>  static const TypeInfo mipsnet_info = {
> diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c
> index f345533..23f9c6f 100644
> --- a/hw/net/ne2000-isa.c
> +++ b/hw/net/ne2000-isa.c
> @@ -90,7 +90,7 @@ static void isa_ne2000_class_initfn(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = isa_ne2000_realizefn;
> -    dc->props = ne2000_isa_properties;
> +    device_class_set_props(dc, ne2000_isa_properties);
>      dc->vmsd = &vmstate_isa_ne2000;
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
>  }
> diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
> index 798d681..32c0bd5 100644
> --- a/hw/net/ne2000.c
> +++ b/hw/net/ne2000.c
> @@ -776,7 +776,7 @@ static void ne2000_class_init(ObjectClass *klass, void *data)
>      k->device_id = PCI_DEVICE_ID_REALTEK_8029;
>      k->class_id = PCI_CLASS_NETWORK_ETHERNET;
>      dc->vmsd = &vmstate_pci_ne2000;
> -    dc->props = ne2000_properties;
> +    device_class_set_props(dc, ne2000_properties);
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
>  }
>  
> diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c
> index 268d6a7..6084502 100644
> --- a/hw/net/opencores_eth.c
> +++ b/hw/net/opencores_eth.c
> @@ -755,7 +755,7 @@ static void open_eth_class_init(ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
>      dc->desc = "Opencores 10/100 Mbit Ethernet";
>      dc->reset = qdev_open_eth_reset;
> -    dc->props = open_eth_properties;
> +    device_class_set_props(dc, open_eth_properties);
>  }
>  
>  static const TypeInfo open_eth_info = {
> diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c
> index 0acf8a4..e52e970 100644
> --- a/hw/net/pcnet-pci.c
> +++ b/hw/net/pcnet-pci.c
> @@ -355,7 +355,7 @@ static void pcnet_class_init(ObjectClass *klass, void *data)
>      k->class_id = PCI_CLASS_NETWORK_ETHERNET;
>      dc->reset = pci_reset;
>      dc->vmsd = &vmstate_pci_pcnet;
> -    dc->props = pcnet_properties;
> +    device_class_set_props(dc, pcnet_properties);
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
>  }
>  
> diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
> index e9d215a..8505e75 100644
> --- a/hw/net/rocker/rocker.c
> +++ b/hw/net/rocker/rocker.c
> @@ -1565,7 +1565,7 @@ static void rocker_class_init(ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
>      dc->desc = "Rocker Switch";
>      dc->reset = rocker_reset;
> -    dc->props = rocker_properties;
> +    device_class_set_props(dc, rocker_properties);
>      dc->vmsd = &rocker_vmsd;
>  }
>  
> diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
> index f05e59c..91dc9a5 100644
> --- a/hw/net/rtl8139.c
> +++ b/hw/net/rtl8139.c
> @@ -3471,7 +3471,7 @@ static void rtl8139_class_init(ObjectClass *klass, void *data)
>      k->class_id = PCI_CLASS_NETWORK_ETHERNET;
>      dc->reset = rtl8139_reset;
>      dc->vmsd = &vmstate_rtl8139;
> -    dc->props = rtl8139_properties;
> +    device_class_set_props(dc, rtl8139_properties);
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
>  }
>  
> diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
> index 3b16dcf..49533af 100644
> --- a/hw/net/smc91c111.c
> +++ b/hw/net/smc91c111.c
> @@ -791,7 +791,7 @@ static void smc91c111_class_init(ObjectClass *klass, void *data)
>      k->init = smc91c111_init1;
>      dc->reset = smc91c111_reset;
>      dc->vmsd = &vmstate_smc91c111;
> -    dc->props = smc91c111_properties;
> +    device_class_set_props(dc, smc91c111_properties);
>  }
>  
>  static const TypeInfo smc91c111_info = {
> diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
> index 01ecb02..2783dcd 100644
> --- a/hw/net/spapr_llan.c
> +++ b/hw/net/spapr_llan.c
> @@ -849,7 +849,7 @@ static void spapr_vlan_class_init(ObjectClass *klass, void *data)
>      k->dt_compatible = "IBM,l-lan";
>      k->signal_mask = 0x1;
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
> -    dc->props = spapr_vlan_properties;
> +    device_class_set_props(dc, spapr_vlan_properties);
>      k->rtce_window_size = 0x10000000;
>      dc->vmsd = &vmstate_spapr_llan;
>  }
> diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c
> index 957730e..5211d40 100644
> --- a/hw/net/stellaris_enet.c
> +++ b/hw/net/stellaris_enet.c
> @@ -495,7 +495,7 @@ static void stellaris_enet_class_init(ObjectClass *klass, void *data)
>      SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
>  
>      k->init = stellaris_enet_init;
> -    dc->props = stellaris_enet_properties;
> +    device_class_set_props(dc, stellaris_enet_properties);
>      dc->vmsd = &vmstate_stellaris_enet;
>  }
>  
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index 06bfe4b..252313b 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -1926,7 +1926,7 @@ static void virtio_net_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
>  
> -    dc->props = virtio_net_properties;
> +    device_class_set_props(dc, virtio_net_properties);
>      dc->vmsd = &vmstate_virtio_net;
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
>      vdc->realize = virtio_net_device_realize;
> diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
> index 92f6af9..e452413 100644
> --- a/hw/net/vmxnet3.c
> +++ b/hw/net/vmxnet3.c
> @@ -2715,7 +2715,7 @@ static void vmxnet3_class_init(ObjectClass *class, void *data)
>      dc->desc = "VMWare Paravirtualized Ethernet v3";
>      dc->reset = vmxnet3_qdev_reset;
>      dc->vmsd = &vmstate_vmxnet3;
> -    dc->props = vmxnet3_properties;
> +    device_class_set_props(dc, vmxnet3_properties);
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
>  }
>  
> diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c
> index 46b1aa1..a7992f2 100644
> --- a/hw/net/xgmac.c
> +++ b/hw/net/xgmac.c
> @@ -415,7 +415,7 @@ static void xgmac_enet_class_init(ObjectClass *klass, void *data)
>  
>      sbc->init = xgmac_enet_init;
>      dc->vmsd = &vmstate_xgmac;
> -    dc->props = xgmac_properties;
> +    device_class_set_props(dc, xgmac_properties);
>  }
>  
>  static const TypeInfo xgmac_enet_info = {
> diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
> index b670184..4586b20 100644
> --- a/hw/net/xilinx_axienet.c
> +++ b/hw/net/xilinx_axienet.c
> @@ -1031,7 +1031,7 @@ static void xilinx_enet_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = xilinx_enet_realize;
> -    dc->props = xilinx_enet_properties;
> +    device_class_set_props(dc, xilinx_enet_properties);
>      dc->reset = xilinx_axienet_reset;
>  }
>  
> diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
> index 35de353..a8e0a0a 100644
> --- a/hw/net/xilinx_ethlite.c
> +++ b/hw/net/xilinx_ethlite.c
> @@ -261,7 +261,7 @@ static void xilinx_ethlite_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = xilinx_ethlite_realize;
>      dc->reset = xilinx_ethlite_reset;
> -    dc->props = xilinx_ethlite_properties;
> +    device_class_set_props(dc, xilinx_ethlite_properties);
>  }
>  
>  static const TypeInfo xilinx_ethlite_info = {
> diff --git a/hw/nvram/ds1225y.c b/hw/nvram/ds1225y.c
> index 57d5ab2..78fc9cf 100644
> --- a/hw/nvram/ds1225y.c
> +++ b/hw/nvram/ds1225y.c
> @@ -152,7 +152,7 @@ static void nvram_sysbus_class_init(ObjectClass *klass, void *data)
>  
>      k->init = nvram_sysbus_initfn;
>      dc->vmsd = &vmstate_nvram;
> -    dc->props = nvram_sysbus_properties;
> +    device_class_set_props(dc, nvram_sysbus_properties);
>  }
>  
>  static const TypeInfo nvram_sysbus_info = {
> diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
> index 92aa563..aa1f040 100644
> --- a/hw/nvram/fw_cfg.c
> +++ b/hw/nvram/fw_cfg.c
> @@ -1029,7 +1029,7 @@ static void fw_cfg_io_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = fw_cfg_io_realize;
> -    dc->props = fw_cfg_io_properties;
> +    device_class_set_props(dc, fw_cfg_io_properties);
>  }
>  
>  static const TypeInfo fw_cfg_io_info = {
> @@ -1086,7 +1086,7 @@ static void fw_cfg_mem_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = fw_cfg_mem_realize;
> -    dc->props = fw_cfg_mem_properties;
> +    device_class_set_props(dc, fw_cfg_mem_properties);
>  }
>  
>  static const TypeInfo fw_cfg_mem_info = {
> diff --git a/hw/nvram/mac_nvram.c b/hw/nvram/mac_nvram.c
> index 63f9ed1..39ac159 100644
> --- a/hw/nvram/mac_nvram.c
> +++ b/hw/nvram/mac_nvram.c
> @@ -125,7 +125,7 @@ static void macio_nvram_class_init(ObjectClass *oc, void *data)
>      dc->unrealize = macio_nvram_unrealizefn;
>      dc->reset = macio_nvram_reset;
>      dc->vmsd = &vmstate_macio_nvram;
> -    dc->props = macio_nvram_properties;
> +    device_class_set_props(dc, macio_nvram_properties);
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>  }
>  
> diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c
> index eb42ea3..ee8a0c3 100644
> --- a/hw/nvram/spapr_nvram.c
> +++ b/hw/nvram/spapr_nvram.c
> @@ -246,7 +246,7 @@ static void spapr_nvram_class_init(ObjectClass *klass, void *data)
>      k->dt_type = "nvram";
>      k->dt_compatible = "qemu,spapr-nvram";
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> -    dc->props = spapr_nvram_properties;
> +    device_class_set_props(dc, spapr_nvram_properties);
>      dc->vmsd = &vmstate_spapr_nvram;
>  }
>  
> diff --git a/hw/pci-bridge/ioh3420.c b/hw/pci-bridge/ioh3420.c
> index c8b5ac4..ed9f827 100644
> --- a/hw/pci-bridge/ioh3420.c
> +++ b/hw/pci-bridge/ioh3420.c
> @@ -202,7 +202,7 @@ static void ioh3420_class_init(ObjectClass *klass, void *data)
>      dc->desc = "Intel IOH device id 3420 PCIE Root Port";
>      dc->reset = ioh3420_reset;
>      dc->vmsd = &vmstate_ioh3420;
> -    dc->props = ioh3420_props;
> +    device_class_set_props(dc, ioh3420_props);
>  }
>  
>  static const TypeInfo ioh3420_info = {
> diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c
> index 5dbd933..629df64 100644
> --- a/hw/pci-bridge/pci_bridge_dev.c
> +++ b/hw/pci-bridge/pci_bridge_dev.c
> @@ -225,7 +225,7 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
>      k->is_bridge = 1,
>      dc->desc = "Standard PCI Bridge";
>      dc->reset = qdev_pci_bridge_dev_reset;
> -    dc->props = pci_bridge_dev_properties;
> +    device_class_set_props(dc, pci_bridge_dev_properties);
>      dc->vmsd = &pci_bridge_dev_vmstate;
>      set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
>      hc->plug = pci_bridge_dev_hotplug_cb;
> diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c
> index 1cc598f..d5660b9 100644
> --- a/hw/pci-bridge/pci_expander_bridge.c
> +++ b/hw/pci-bridge/pci_expander_bridge.c
> @@ -307,7 +307,7 @@ static void pxb_dev_class_init(ObjectClass *klass, void *data)
>      k->class_id = PCI_CLASS_BRIDGE_HOST;
>  
>      dc->desc = "PCI Expander Bridge";
> -    dc->props = pxb_dev_properties;
> +    device_class_set_props(dc, pxb_dev_properties);
>      dc->hotpluggable = false;
>      set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
>  }
> @@ -341,7 +341,7 @@ static void pxb_pcie_dev_class_init(ObjectClass *klass, void *data)
>      k->class_id = PCI_CLASS_BRIDGE_HOST;
>  
>      dc->desc = "PCI Express Expander Bridge";
> -    dc->props = pxb_dev_properties;
> +    device_class_set_props(dc, pxb_dev_properties);
>      dc->hotpluggable = false;
>      set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
>  }
> diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c
> index cef6e13..4b3d136 100644
> --- a/hw/pci-bridge/xio3130_downstream.c
> +++ b/hw/pci-bridge/xio3130_downstream.c
> @@ -188,7 +188,7 @@ static void xio3130_downstream_class_init(ObjectClass *klass, void *data)
>      dc->desc = "TI X3130 Downstream Port of PCI Express Switch";
>      dc->reset = xio3130_downstream_reset;
>      dc->vmsd = &vmstate_xio3130_downstream;
> -    dc->props = xio3130_downstream_props;
> +    device_class_set_props(dc, xio3130_downstream_props);
>  }
>  
>  static const TypeInfo xio3130_downstream_info = {
> diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
> index f9218aa..0b41f62 100644
> --- a/hw/pci-host/piix.c
> +++ b/hw/pci-host/piix.c
> @@ -872,7 +872,7 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
>      hc->root_bus_path = i440fx_pcihost_root_bus_path;
>      dc->realize = i440fx_pcihost_realize;
>      dc->fw_name = "pci";
> -    dc->props = i440fx_props;
> +    device_class_set_props(dc, i440fx_props);
>      /* Reason: needs to be wired up by pc_init1 */
>      dc->cannot_instantiate_with_device_add_yet = true;
>  }
> diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
> index e502bc0..9c1bfc3 100644
> --- a/hw/pci-host/ppce500.c
> +++ b/hw/pci-host/ppce500.c
> @@ -531,7 +531,7 @@ static void e500_pcihost_class_init(ObjectClass *klass, void *data)
>  
>      k->init = e500_pcihost_initfn;
>      set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
> -    dc->props = pcihost_properties;
> +    device_class_set_props(dc, pcihost_properties);
>      dc->vmsd = &vmstate_ppce500_pci;
>  }
>  
> diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
> index 5580293..ce55eb7 100644
> --- a/hw/pci-host/prep.c
> +++ b/hw/pci-host/prep.c
> @@ -386,7 +386,7 @@ static void raven_pcihost_class_init(ObjectClass *klass, void *data)
>  
>      set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
>      dc->realize = raven_pcihost_realizefn;
> -    dc->props = raven_pcihost_properties;
> +    device_class_set_props(dc, raven_pcihost_properties);
>      dc->fw_name = "pci";
>  }
>  
> diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
> index 344f77b..72cabb9 100644
> --- a/hw/pci-host/q35.c
> +++ b/hw/pci-host/q35.c
> @@ -154,7 +154,7 @@ static void q35_host_class_init(ObjectClass *klass, void *data)
>  
>      hc->root_bus_path = q35_host_root_bus_path;
>      dc->realize = q35_host_realize;
> -    dc->props = mch_props;
> +    device_class_set_props(dc, mch_props);
>      /* Reason: needs to be wired up by pc_q35_init */
>      dc->cannot_instantiate_with_device_add_yet = true;
>      set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
> diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
> index 467cbb9..1c4b9e3 100644
> --- a/hw/pci-host/versatile.c
> +++ b/hw/pci-host/versatile.c
> @@ -502,7 +502,7 @@ static void pci_vpb_class_init(ObjectClass *klass, void *data)
>      dc->realize = pci_vpb_realize;
>      dc->reset = pci_vpb_reset;
>      dc->vmsd = &pci_vpb_vmstate;
> -    dc->props = pci_vpb_properties;
> +    device_class_set_props(dc, pci_vpb_properties);
>      /* Reason: object_unref() hangs */
>      dc->cannot_destroy_with_object_finalize_yet = true;
>  }
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index 24fae16..8d93a47 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -2492,7 +2492,7 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
>      k->realize = pci_qdev_realize;
>      k->unrealize = pci_qdev_unrealize;
>      k->bus_type = TYPE_PCI_BUS;
> -    k->props = pci_props;
> +    device_class_set_props(k, pci_props);
>      pc->realize = pci_default_realize;
>  }
>  
> diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c
> index 6432b9a..8bcca7c 100644
> --- a/hw/pci/pcie_port.c
> +++ b/hw/pci/pcie_port.c
> @@ -131,7 +131,7 @@ static void pcie_port_class_init(ObjectClass *oc, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(oc);
>  
> -    dc->props = pcie_port_props;
> +    device_class_set_props(dc, pcie_port_props);
>  }
>  
>  static const TypeInfo pcie_port_type_info = {
> @@ -153,7 +153,7 @@ static void pcie_slot_class_init(ObjectClass *oc, void *data)
>      DeviceClass *dc = DEVICE_CLASS(oc);
>      HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
>  
> -    dc->props = pcie_slot_props;
> +    device_class_set_props(dc, pcie_slot_props);
>      hc->plug = pcie_cap_slot_hotplug_cb;
>      hc->unplug_request = pcie_cap_slot_hot_unplug_request_cb;
>  }
> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> index 82276e0..94aef9c 100644
> --- a/hw/ppc/pnv.c
> +++ b/hw/ppc/pnv.c
> @@ -721,7 +721,7 @@ static void pnv_chip_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = pnv_chip_realize;
> -    dc->props = pnv_chip_properties;
> +    device_class_set_props(dc, pnv_chip_properties);
>      dc->desc = "PowerNV Chip";
>  }
>  
> diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
> index 2acda96..7ec9d26 100644
> --- a/hw/ppc/pnv_core.c
> +++ b/hw/ppc/pnv_core.c
> @@ -190,7 +190,7 @@ static void pnv_core_class_init(ObjectClass *oc, void *data)
>      PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
>  
>      dc->realize = pnv_core_realize;
> -    dc->props = pnv_core_properties;
> +    device_class_set_props(dc, pnv_core_properties);
>      pcc->cpu_oc = cpu_class_by_name(TYPE_POWERPC_CPU, data);
>  }
>  
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index 7cde30e..341a04b 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -1696,7 +1696,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
>  
>      hc->root_bus_path = spapr_phb_root_bus_path;
>      dc->realize = spapr_phb_realize;
> -    dc->props = spapr_phb_properties;
> +    device_class_set_props(dc, spapr_phb_properties);
>      dc->reset = spapr_phb_reset;
>      dc->vmsd = &vmstate_spapr_pci;
>      set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
> diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
> index 8448e0b..605a9c1 100644
> --- a/hw/ppc/spapr_pci_vfio.c
> +++ b/hw/ppc/spapr_pci_vfio.c
> @@ -223,7 +223,7 @@ static void spapr_phb_vfio_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->props = spapr_phb_vfio_properties;
> +    device_class_set_props(dc, spapr_phb_vfio_properties);
>  }
>  
>  static const TypeInfo spapr_phb_vfio_info = {
> diff --git a/hw/ppc/spapr_rng.c b/hw/ppc/spapr_rng.c
> index 80515eb..16091ab 100644
> --- a/hw/ppc/spapr_rng.c
> +++ b/hw/ppc/spapr_rng.c
> @@ -172,7 +172,7 @@ static void spapr_rng_class_init(ObjectClass *oc, void *data)
>  
>      dc->realize = spapr_rng_realize;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> -    dc->props = spapr_rng_properties;
> +    device_class_set_props(dc, spapr_rng_properties);
>      dc->hotpluggable = false;
>  }
>  
> diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
> index cc1e09c..2d23e16 100644
> --- a/hw/ppc/spapr_vio.c
> +++ b/hw/ppc/spapr_vio.c
> @@ -586,7 +586,7 @@ static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
>      k->realize = spapr_vio_busdev_realize;
>      k->reset = spapr_vio_busdev_reset;
>      k->bus_type = TYPE_SPAPR_VIO_BUS;
> -    k->props = spapr_vio_props;
> +    device_class_set_props(k, spapr_vio_props);
>  }
>  
>  static const TypeInfo spapr_vio_type_info = {
> diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c
> index 9a7f7ee..a332af8 100644
> --- a/hw/s390x/css-bridge.c
> +++ b/hw/s390x/css-bridge.c
> @@ -125,7 +125,7 @@ static void virtual_css_bridge_class_init(ObjectClass *klass, void *data)
>  
>      hc->unplug = ccw_device_unplug;
>      set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
> -    dc->props = virtual_css_bridge_properties;
> +    device_class_set_props(dc, virtual_css_bridge_properties);
>  }
>  
>  static const TypeInfo virtual_css_bridge_info = {
> diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
> index 2e2664f..947cf12 100644
> --- a/hw/s390x/ipl.c
> +++ b/hw/s390x/ipl.c
> @@ -315,7 +315,7 @@ static void s390_ipl_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = s390_ipl_realize;
> -    dc->props = s390_ipl_properties;
> +    device_class_set_props(dc, s390_ipl_properties);
>      dc->reset = s390_ipl_reset;
>      dc->vmsd = &vmstate_ipl;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
> index b7f8bca..9d8d13f 100644
> --- a/hw/s390x/s390-pci-bus.c
> +++ b/hw/s390x/s390-pci-bus.c
> @@ -942,7 +942,7 @@ static void s390_pci_device_class_init(ObjectClass *klass, void *data)
>      dc->reset = s390_pci_device_reset;
>      dc->bus_type = TYPE_S390_PCI_BUS;
>      dc->realize = s390_pci_device_realize;
> -    dc->props = s390_pci_device_properties;
> +    device_class_set_props(dc, s390_pci_device_properties);
>  }
>  
>  static const TypeInfo s390_pci_device_info = {
> diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
> index ee136ab..6454fcb 100644
> --- a/hw/s390x/virtio-ccw.c
> +++ b/hw/s390x/virtio-ccw.c
> @@ -1347,7 +1347,7 @@ static void virtio_ccw_net_class_init(ObjectClass *klass, void *data)
>      k->realize = virtio_ccw_net_realize;
>      k->exit = virtio_ccw_exit;
>      dc->reset = virtio_ccw_reset;
> -    dc->props = virtio_ccw_net_properties;
> +    device_class_set_props(dc, virtio_ccw_net_properties);
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
>  }
>  
> @@ -1376,7 +1376,7 @@ static void virtio_ccw_blk_class_init(ObjectClass *klass, void *data)
>      k->realize = virtio_ccw_blk_realize;
>      k->exit = virtio_ccw_exit;
>      dc->reset = virtio_ccw_reset;
> -    dc->props = virtio_ccw_blk_properties;
> +    device_class_set_props(dc, virtio_ccw_blk_properties);
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>  }
>  
> @@ -1405,7 +1405,7 @@ static void virtio_ccw_serial_class_init(ObjectClass *klass, void *data)
>      k->realize = virtio_ccw_serial_realize;
>      k->exit = virtio_ccw_exit;
>      dc->reset = virtio_ccw_reset;
> -    dc->props = virtio_ccw_serial_properties;
> +    device_class_set_props(dc, virtio_ccw_serial_properties);
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>  }
>  
> @@ -1434,7 +1434,7 @@ static void virtio_ccw_balloon_class_init(ObjectClass *klass, void *data)
>      k->realize = virtio_ccw_balloon_realize;
>      k->exit = virtio_ccw_exit;
>      dc->reset = virtio_ccw_reset;
> -    dc->props = virtio_ccw_balloon_properties;
> +    device_class_set_props(dc, virtio_ccw_balloon_properties);
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>  }
>  
> @@ -1463,7 +1463,7 @@ static void virtio_ccw_scsi_class_init(ObjectClass *klass, void *data)
>      k->realize = virtio_ccw_scsi_realize;
>      k->exit = virtio_ccw_exit;
>      dc->reset = virtio_ccw_reset;
> -    dc->props = virtio_ccw_scsi_properties;
> +    device_class_set_props(dc, virtio_ccw_scsi_properties);
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>  }
>  
> @@ -1491,7 +1491,7 @@ static void vhost_ccw_scsi_class_init(ObjectClass *klass, void *data)
>      k->realize = vhost_ccw_scsi_realize;
>      k->exit = virtio_ccw_exit;
>      dc->reset = virtio_ccw_reset;
> -    dc->props = vhost_ccw_scsi_properties;
> +    device_class_set_props(dc, vhost_ccw_scsi_properties);
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>  }
>  
> @@ -1531,7 +1531,7 @@ static void virtio_ccw_rng_class_init(ObjectClass *klass, void *data)
>      k->realize = virtio_ccw_rng_realize;
>      k->exit = virtio_ccw_exit;
>      dc->reset = virtio_ccw_reset;
> -    dc->props = virtio_ccw_rng_properties;
> +    device_class_set_props(dc, virtio_ccw_rng_properties);
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>  }
>  
> @@ -1657,7 +1657,7 @@ static void virtio_ccw_9p_class_init(ObjectClass *klass, void *data)
>      k->exit = virtio_ccw_exit;
>      k->realize = virtio_ccw_9p_realize;
>      dc->reset = virtio_ccw_reset;
> -    dc->props = virtio_ccw_9p_properties;
> +    device_class_set_props(dc, virtio_ccw_9p_properties);
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>  }
>  
> @@ -1708,7 +1708,7 @@ static void vhost_vsock_ccw_class_init(ObjectClass *klass, void *data)
>      k->realize = vhost_vsock_ccw_realize;
>      k->exit = virtio_ccw_exit;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> -    dc->props = vhost_vsock_ccw_properties;
> +    device_class_set_props(dc, vhost_vsock_ccw_properties);
>      dc->reset = virtio_ccw_reset;
>  }
>  
> diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
> index 52a4123..63dfcf5 100644
> --- a/hw/scsi/megasas.c
> +++ b/hw/scsi/megasas.c
> @@ -2515,7 +2515,7 @@ static void megasas_class_init(ObjectClass *oc, void *data)
>      e->osts = info->osts;
>      e->product_name = info->product_name;
>      e->product_version = info->product_version;
> -    dc->props = info->props;
> +    device_class_set_props(dc, info->props);
>      dc->reset = megasas_scsi_reset;
>      dc->vmsd = info->vmsd;
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
> diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c
> index ad87e78..2fa622e 100644
> --- a/hw/scsi/mptsas.c
> +++ b/hw/scsi/mptsas.c
> @@ -1434,7 +1434,7 @@ static void mptsas1068_class_init(ObjectClass *oc, void *data)
>      pc->subsystem_vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
>      pc->subsystem_id = 0x8000;
>      pc->class_id = PCI_CLASS_STORAGE_SCSI;
> -    dc->props = mptsas_properties;
> +    device_class_set_props(dc, mptsas_properties);
>      dc->reset = mptsas_reset;
>      dc->vmsd = &vmstate_mptsas;
>      dc->desc = "LSI SAS 1068";
> diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
> index 297216d..54fcc54 100644
> --- a/hw/scsi/scsi-bus.c
> +++ b/hw/scsi/scsi-bus.c
> @@ -2069,7 +2069,7 @@ static void scsi_device_class_init(ObjectClass *klass, void *data)
>      k->bus_type  = TYPE_SCSI_BUS;
>      k->realize   = scsi_qdev_realize;
>      k->unrealize = scsi_qdev_unrealize;
> -    k->props     = scsi_props;
> +    device_class_set_props(k, scsi_props);
>  }
>  
>  static void scsi_dev_instance_init(Object *obj)
> diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
> index a963191..9c1ce3c 100644
> --- a/hw/scsi/scsi-disk.c
> +++ b/hw/scsi/scsi-disk.c
> @@ -2897,7 +2897,7 @@ static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
>      sc->alloc_req    = scsi_new_request;
>      sc->unit_attention_reported = scsi_disk_unit_attention_reported;
>      dc->desc = "virtual SCSI disk";
> -    dc->props = scsi_hd_properties;
> +    device_class_set_props(dc, scsi_hd_properties);
>      dc->vmsd  = &vmstate_scsi_disk_state;
>  }
>  
> @@ -2926,7 +2926,7 @@ static void scsi_cd_class_initfn(ObjectClass *klass, void *data)
>      sc->alloc_req    = scsi_new_request;
>      sc->unit_attention_reported = scsi_disk_unit_attention_reported;
>      dc->desc = "virtual SCSI CD-ROM";
> -    dc->props = scsi_cd_properties;
> +    device_class_set_props(dc, scsi_cd_properties);
>      dc->vmsd  = &vmstate_scsi_disk_state;
>  }
>  
> @@ -2955,7 +2955,7 @@ static void scsi_block_class_initfn(ObjectClass *klass, void *data)
>      sdc->dma_writev  = scsi_block_dma_writev;
>      sdc->need_fua_emulation = scsi_block_no_fua;
>      dc->desc = "SCSI block device passthrough";
> -    dc->props = scsi_block_properties;
> +    device_class_set_props(dc, scsi_block_properties);
>      dc->vmsd  = &vmstate_scsi_disk_state;
>  }
>  
> @@ -2993,7 +2993,7 @@ static void scsi_disk_class_initfn(ObjectClass *klass, void *data)
>      dc->fw_name = "disk";
>      dc->desc = "virtual SCSI disk or CD-ROM (legacy)";
>      dc->reset = scsi_disk_reset;
> -    dc->props = scsi_disk_properties;
> +    device_class_set_props(dc, scsi_disk_properties);
>      dc->vmsd  = &vmstate_scsi_disk_state;
>  }
>  
> diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
> index 7a588a7..3a5182c 100644
> --- a/hw/scsi/scsi-generic.c
> +++ b/hw/scsi/scsi-generic.c
> @@ -605,7 +605,7 @@ static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
>      dc->fw_name = "disk";
>      dc->desc = "pass through generic scsi device (/dev/sg*)";
>      dc->reset = scsi_generic_reset;
> -    dc->props = scsi_generic_properties;
> +    device_class_set_props(dc, scsi_generic_properties);
>      dc->vmsd  = &vmstate_scsi_device;
>  }
>  
> diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
> index 6090a20..cb11a7e 100644
> --- a/hw/scsi/spapr_vscsi.c
> +++ b/hw/scsi/spapr_vscsi.c
> @@ -1268,7 +1268,7 @@ static void spapr_vscsi_class_init(ObjectClass *klass, void *data)
>      k->dt_compatible = "IBM,v-scsi";
>      k->signal_mask = 0x00000001;
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
> -    dc->props = spapr_vscsi_properties;
> +    device_class_set_props(dc, spapr_vscsi_properties);
>      k->rtce_window_size = 0x10000000;
>      dc->vmsd = &vmstate_spapr_vscsi;
>  }
> diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
> index 5b26946..9833d8b 100644
> --- a/hw/scsi/vhost-scsi.c
> +++ b/hw/scsi/vhost-scsi.c
> @@ -314,7 +314,7 @@ static void vhost_scsi_class_init(ObjectClass *klass, void *data)
>      VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
>      FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(klass);
>  
> -    dc->props = vhost_scsi_properties;
> +    device_class_set_props(dc, vhost_scsi_properties);
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>      vdc->realize = vhost_scsi_realize;
>      vdc->unrealize = vhost_scsi_unrealize;
> diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
> index 4762f05..32f131a 100644
> --- a/hw/scsi/virtio-scsi.c
> +++ b/hw/scsi/virtio-scsi.c
> @@ -949,7 +949,7 @@ static void virtio_scsi_class_init(ObjectClass *klass, void *data)
>      VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
>      HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
>  
> -    dc->props = virtio_scsi_properties;
> +    device_class_set_props(dc, virtio_scsi_properties);
>      dc->vmsd = &vmstate_virtio_scsi;
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>      vdc->realize = virtio_scsi_device_realize;
> diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
> index a5ce7de..b5c525c 100644
> --- a/hw/scsi/vmw_pvscsi.c
> +++ b/hw/scsi/vmw_pvscsi.c
> @@ -1292,7 +1292,7 @@ static void pvscsi_class_init(ObjectClass *klass, void *data)
>      dc->realize = pvscsi_realize;
>      dc->reset = pvscsi_reset;
>      dc->vmsd = &vmstate_pvscsi;
> -    dc->props = pvscsi_properties;
> +    device_class_set_props(dc, pvscsi_properties);
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>      hc->unplug = pvscsi_hot_unplug;
>      hc->plug = pvscsi_hotplug;
> diff --git a/hw/sd/sd.c b/hw/sd/sd.c
> index 8e88e83..e87f40f 100644
> --- a/hw/sd/sd.c
> +++ b/hw/sd/sd.c
> @@ -1914,7 +1914,7 @@ static void sd_class_init(ObjectClass *klass, void *data)
>      SDCardClass *sc = SD_CARD_CLASS(klass);
>  
>      dc->realize = sd_realize;
> -    dc->props = sd_properties;
> +    device_class_set_props(dc, sd_properties);
>      dc->vmsd = &sd_vmstate;
>      dc->reset = sd_reset;
>      dc->bus_type = TYPE_SD_BUS;
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index 01fbf22..1a30f89 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -1305,7 +1305,7 @@ static void sdhci_pci_class_init(ObjectClass *klass, void *data)
>      k->class_id = PCI_CLASS_SYSTEM_SDHCI;
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>      dc->vmsd = &sdhci_vmstate;
> -    dc->props = sdhci_pci_properties;
> +    device_class_set_props(dc, sdhci_pci_properties);
>      dc->reset = sdhci_poweron_reset;
>  }
>  
> @@ -1356,7 +1356,7 @@ static void sdhci_sysbus_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->vmsd = &sdhci_vmstate;
> -    dc->props = sdhci_sysbus_properties;
> +    device_class_set_props(dc, sdhci_sysbus_properties);
>      dc->realize = sdhci_sysbus_realize;
>      dc->reset = sdhci_poweron_reset;
>  }
> diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
> index 6224288..19930b7 100644
> --- a/hw/sparc/sun4m.c
> +++ b/hw/sparc/sun4m.c
> @@ -728,7 +728,7 @@ static void prom_class_init(ObjectClass *klass, void *data)
>      SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
>  
>      k->init = prom_init1;
> -    dc->props = prom_properties;
> +    device_class_set_props(dc, prom_properties);
>  }
>  
>  static const TypeInfo prom_info = {
> @@ -795,7 +795,7 @@ static void ram_class_init(ObjectClass *klass, void *data)
>      SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
>  
>      k->init = ram_init1;
> -    dc->props = ram_properties;
> +    device_class_set_props(dc, ram_properties);
>  }
>  
>  static const TypeInfo ram_info = {
> diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
> index 271d8bc..f5eccc3 100644
> --- a/hw/sparc64/sun4u.c
> +++ b/hw/sparc64/sun4u.c
> @@ -652,7 +652,7 @@ static void prom_class_init(ObjectClass *klass, void *data)
>      SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
>  
>      k->init = prom_init1;
> -    dc->props = prom_properties;
> +    device_class_set_props(dc, prom_properties);
>  }
>  
>  static const TypeInfo prom_info = {
> @@ -713,7 +713,7 @@ static void ram_class_init(ObjectClass *klass, void *data)
>      SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
>  
>      k->init = ram_init1;
> -    dc->props = ram_properties;
> +    device_class_set_props(dc, ram_properties);
>  }
>  
>  static const TypeInfo ram_info = {
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 6e8403e..5e3b95e 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -605,7 +605,7 @@ static void aspeed_smc_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = aspeed_smc_realize;
>      dc->reset = aspeed_smc_reset;
> -    dc->props = aspeed_smc_properties;
> +    device_class_set_props(dc, aspeed_smc_properties);
>      dc->vmsd = &vmstate_aspeed_smc;
>      mc->ctrl = data;
>  }
> diff --git a/hw/ssi/xilinx_spi.c b/hw/ssi/xilinx_spi.c
> index 33482f0..82cc089 100644
> --- a/hw/ssi/xilinx_spi.c
> +++ b/hw/ssi/xilinx_spi.c
> @@ -372,7 +372,7 @@ static void xilinx_spi_class_init(ObjectClass *klass, void *data)
>  
>      k->init = xilinx_spi_init;
>      dc->reset = xlx_spi_reset;
> -    dc->props = xilinx_spi_properties;
> +    device_class_set_props(dc, xilinx_spi_properties);
>      dc->vmsd = &vmstate_xilinx_spi;
>  }
>  
> diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
> index da8adfa..a73f4f9 100644
> --- a/hw/ssi/xilinx_spips.c
> +++ b/hw/ssi/xilinx_spips.c
> @@ -705,7 +705,7 @@ static void xilinx_spips_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = xilinx_spips_realize;
>      dc->reset = xilinx_spips_reset;
> -    dc->props = xilinx_spips_properties;
> +    device_class_set_props(dc, xilinx_spips_properties);
>      dc->vmsd = &vmstate_xilinx_spips;
>  
>      xsc->reg_ops = &spips_ops;
> diff --git a/hw/timer/a9gtimer.c b/hw/timer/a9gtimer.c
> index ce1dc63..6f1a73c 100644
> --- a/hw/timer/a9gtimer.c
> +++ b/hw/timer/a9gtimer.c
> @@ -354,7 +354,7 @@ static void a9_gtimer_class_init(ObjectClass *klass, void *data)
>      dc->realize = a9_gtimer_realize;
>      dc->vmsd = &vmstate_a9_gtimer;
>      dc->reset = a9_gtimer_reset;
> -    dc->props = a9_gtimer_properties;
> +    device_class_set_props(dc, a9_gtimer_properties);
>  }
>  
>  static const TypeInfo a9_gtimer_info = {
> diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c
> index 22ceabe..a1ac96e 100644
> --- a/hw/timer/allwinner-a10-pit.c
> +++ b/hw/timer/allwinner-a10-pit.c
> @@ -276,7 +276,7 @@ static void a10_pit_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->reset = a10_pit_reset;
> -    dc->props = a10_pit_properties;
> +    device_class_set_props(dc, a10_pit_properties);
>      dc->desc = "allwinner a10 timer";
>      dc->vmsd = &vmstate_a10_pit;
>  }
> diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
> index daf6c48..401a6f6 100644
> --- a/hw/timer/arm_mptimer.c
> +++ b/hw/timer/arm_mptimer.c
> @@ -299,7 +299,7 @@ static void arm_mptimer_class_init(ObjectClass *klass, void *data)
>      dc->realize = arm_mptimer_realize;
>      dc->vmsd = &vmstate_arm_mptimer;
>      dc->reset = arm_mptimer_reset;
> -    dc->props = arm_mptimer_properties;
> +    device_class_set_props(dc, arm_mptimer_properties);
>  }
>  
>  static const TypeInfo arm_mptimer_info = {
> diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
> index 98fddd7..91f5184 100644
> --- a/hw/timer/arm_timer.c
> +++ b/hw/timer/arm_timer.c
> @@ -389,7 +389,7 @@ static void sp804_class_init(ObjectClass *klass, void *data)
>      DeviceClass *k = DEVICE_CLASS(klass);
>  
>      k->realize = sp804_realize;
> -    k->props = sp804_properties;
> +    device_class_set_props(k, sp804_properties);
>      k->vmsd = &vmstate_sp804;
>  }
>  
> diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
> index 712d1ae..fcde90a 100644
> --- a/hw/timer/grlib_gptimer.c
> +++ b/hw/timer/grlib_gptimer.c
> @@ -394,7 +394,7 @@ static void grlib_gptimer_class_init(ObjectClass *klass, void *data)
>  
>      k->init = grlib_gptimer_init;
>      dc->reset = grlib_gptimer_reset;
> -    dc->props = grlib_gptimer_properties;
> +    device_class_set_props(dc, grlib_gptimer_properties);
>  }
>  
>  static const TypeInfo grlib_gptimer_info = {
> diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
> index a2c18b3..3c47ef1 100644
> --- a/hw/timer/hpet.c
> +++ b/hw/timer/hpet.c
> @@ -770,7 +770,7 @@ static void hpet_device_class_init(ObjectClass *klass, void *data)
>      dc->realize = hpet_realize;
>      dc->reset = hpet_reset;
>      dc->vmsd = &vmstate_hpet;
> -    dc->props = hpet_device_properties;
> +    device_class_set_props(dc, hpet_device_properties);
>  }
>  
>  static const TypeInfo hpet_device_info = {
> diff --git a/hw/timer/i8254.c b/hw/timer/i8254.c
> index 5e61ad5..bbecf49 100644
> --- a/hw/timer/i8254.c
> +++ b/hw/timer/i8254.c
> @@ -365,7 +365,7 @@ static void pit_class_initfn(ObjectClass *klass, void *data)
>      k->get_channel_info = pit_get_channel_info_common;
>      k->post_load = pit_post_load;
>      dc->reset = pit_reset;
> -    dc->props = pit_properties;
> +    device_class_set_props(dc, pit_properties);
>  }
>  
>  static const TypeInfo pit_info = {
> diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c
> index 2a07b59..4eeb216 100644
> --- a/hw/timer/lm32_timer.c
> +++ b/hw/timer/lm32_timer.c
> @@ -222,7 +222,7 @@ static void lm32_timer_class_init(ObjectClass *klass, void *data)
>      dc->realize = lm32_timer_realize;
>      dc->reset = timer_reset;
>      dc->vmsd = &vmstate_lm32_timer;
> -    dc->props = lm32_timer_properties;
> +    device_class_set_props(dc, lm32_timer_properties);
>  }
>  
>  static const TypeInfo lm32_timer_info = {
> diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
> index e46ca88..2c07345 100644
> --- a/hw/timer/m48t59.c
> +++ b/hw/timer/m48t59.c
> @@ -822,7 +822,7 @@ static void m48txx_isa_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = m48t59_isa_realize;
>      dc->reset = m48t59_reset_isa;
> -    dc->props = m48t59_isa_properties;
> +    device_class_set_props(dc, m48t59_isa_properties);
>      nc->read = m48txx_isa_read;
>      nc->write = m48txx_isa_write;
>      nc->toggle_lock = m48txx_isa_toggle_lock;
> @@ -867,7 +867,7 @@ static void m48txx_sysbus_class_init(ObjectClass *klass, void *data)
>  
>      k->init = m48t59_init1;
>      dc->reset = m48t59_reset_sysbus;
> -    dc->props = m48t59_sysbus_properties;
> +    device_class_set_props(dc, m48t59_sysbus_properties);
>      nc->read = m48txx_sysbus_read;
>      nc->write = m48txx_sysbus_write;
>      nc->toggle_lock = m48txx_sysbus_toggle_lock;
> diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
> index da209d0..9d9b998 100644
> --- a/hw/timer/mc146818rtc.c
> +++ b/hw/timer/mc146818rtc.c
> @@ -952,7 +952,7 @@ static void rtc_class_initfn(ObjectClass *klass, void *data)
>  
>      dc->realize = rtc_realizefn;
>      dc->vmsd = &vmstate_rtc;
> -    dc->props = mc146818rtc_properties;
> +    device_class_set_props(dc, mc146818rtc_properties);
>      /* Reason: needs to be wired up by rtc_init() */
>      dc->cannot_instantiate_with_device_add_yet = true;
>  }
> diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
> index 4488590..aafbe54 100644
> --- a/hw/timer/milkymist-sysctl.c
> +++ b/hw/timer/milkymist-sysctl.c
> @@ -328,7 +328,7 @@ static void milkymist_sysctl_class_init(ObjectClass *klass, void *data)
>      dc->realize = milkymist_sysctl_realize;
>      dc->reset = milkymist_sysctl_reset;
>      dc->vmsd = &vmstate_milkymist_sysctl;
> -    dc->props = milkymist_sysctl_properties;
> +    device_class_set_props(dc, milkymist_sysctl_properties);
>  }
>  
>  static const TypeInfo milkymist_sysctl_info = {
> diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c
> index 59002b4..aa5679b 100644
> --- a/hw/timer/pxa2xx_timer.c
> +++ b/hw/timer/pxa2xx_timer.c
> @@ -546,7 +546,7 @@ static void pxa25x_timer_dev_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->desc = "PXA25x timer";
> -    dc->props = pxa25x_timer_dev_properties;
> +    device_class_set_props(dc, pxa25x_timer_dev_properties);
>  }
>  
>  static const TypeInfo pxa25x_timer_dev_info = {
> @@ -568,7 +568,7 @@ static void pxa27x_timer_dev_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->desc = "PXA27x timer";
> -    dc->props = pxa27x_timer_dev_properties;
> +    device_class_set_props(dc, pxa27x_timer_dev_properties);
>  }
>  
>  static const TypeInfo pxa27x_timer_dev_info = {
> diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
> index bfee1f3..c14a240 100644
> --- a/hw/timer/slavio_timer.c
> +++ b/hw/timer/slavio_timer.c
> @@ -417,7 +417,7 @@ static void slavio_timer_class_init(ObjectClass *klass, void *data)
>      k->init = slavio_timer_init1;
>      dc->reset = slavio_timer_reset;
>      dc->vmsd = &vmstate_slavio_timer;
> -    dc->props = slavio_timer_properties;
> +    device_class_set_props(dc, slavio_timer_properties);
>  }
>  
>  static const TypeInfo slavio_timer_info = {
> diff --git a/hw/timer/stm32f2xx_timer.c b/hw/timer/stm32f2xx_timer.c
> index e5f5e14..6ef3d91 100644
> --- a/hw/timer/stm32f2xx_timer.c
> +++ b/hw/timer/stm32f2xx_timer.c
> @@ -319,7 +319,7 @@ static void stm32f2xx_timer_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->reset = stm32f2xx_timer_reset;
> -    dc->props = stm32f2xx_timer_properties;
> +    device_class_set_props(dc, stm32f2xx_timer_properties);
>      dc->vmsd = &vmstate_stm32f2xx_timer;
>  }
>  
> diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
> index 59439c0..953d442 100644
> --- a/hw/timer/xilinx_timer.c
> +++ b/hw/timer/xilinx_timer.c
> @@ -247,7 +247,7 @@ static void xilinx_timer_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = xilinx_timer_realize;
> -    dc->props = xilinx_timer_properties;
> +    device_class_set_props(dc, xilinx_timer_properties);
>  }
>  
>  static const TypeInfo xilinx_timer_info = {
> diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
> index 381e726..d290c30 100644
> --- a/hw/tpm/tpm_tis.c
> +++ b/hw/tpm/tpm_tis.c
> @@ -1079,7 +1079,7 @@ static void tpm_tis_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->realize = tpm_tis_realizefn;
> -    dc->props = tpm_tis_properties;
> +    device_class_set_props(dc, tpm_tis_properties);
>      dc->reset = tpm_tis_reset;
>      dc->vmsd  = &vmstate_tpm_tis;
>  }
> diff --git a/hw/usb/bus.c b/hw/usb/bus.c
> index 25913ad..2507576 100644
> --- a/hw/usb/bus.c
> +++ b/hw/usb/bus.c
> @@ -791,7 +791,7 @@ static void usb_device_class_init(ObjectClass *klass, void *data)
>      k->bus_type = TYPE_USB_BUS;
>      k->realize  = usb_qdev_realize;
>      k->unrealize = usb_qdev_unrealize;
> -    k->props    = usb_props;
> +    device_class_set_props(k, usb_props);
>  }
>  
>  static const TypeInfo usb_device_type_info = {
> diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c
> index 3213f9f..5992d70 100644
> --- a/hw/usb/ccid-card-emulated.c
> +++ b/hw/usb/ccid-card-emulated.c
> @@ -588,7 +588,7 @@ static void emulated_class_initfn(ObjectClass *klass, void *data)
>      cc->apdu_from_guest = emulated_apdu_from_guest;
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>      dc->desc = "emulated smartcard";
> -    dc->props = emulated_card_properties;
> +    device_class_set_props(dc, emulated_card_properties);
>  }
>  
>  static const TypeInfo emulated_card_info = {
> diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
> index 325129a..2f4fecc 100644
> --- a/hw/usb/ccid-card-passthru.c
> +++ b/hw/usb/ccid-card-passthru.c
> @@ -402,7 +402,7 @@ static void passthru_class_initfn(ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>      dc->desc = "passthrough smartcard";
>      dc->vmsd = &passthru_vmstate;
> -    dc->props = passthru_card_properties;
> +    device_class_set_props(dc, passthru_card_properties);
>  }
>  
>  static const TypeInfo passthru_card_info = {
> diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
> index 87cab0a..f783f7a 100644
> --- a/hw/usb/dev-audio.c
> +++ b/hw/usb/dev-audio.c
> @@ -675,7 +675,7 @@ static void usb_audio_class_init(ObjectClass *klass, void *data)
>      USBDeviceClass *k = USB_DEVICE_CLASS(klass);
>  
>      dc->vmsd          = &vmstate_usb_audio;
> -    dc->props         = usb_audio_properties;
> +    device_class_set_props(dc, usb_audio_properties);
>      set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
>      k->product_desc   = "QEMU USB Audio Interface";
>      k->usb_desc       = &desc_audio;
> diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
> index 24d05f7..cdc7795 100644
> --- a/hw/usb/dev-hid.c
> +++ b/hw/usb/dev-hid.c
> @@ -812,7 +812,7 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
>      uc->realize        = usb_tablet_realize;
>      uc->product_desc   = "QEMU USB Tablet";
>      dc->vmsd = &vmstate_usb_ptr;
> -    dc->props = usb_tablet_properties;
> +    device_class_set_props(dc, usb_tablet_properties);
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>  }
>  
> @@ -835,7 +835,7 @@ static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
>      uc->realize        = usb_mouse_realize;
>      uc->product_desc   = "QEMU USB Mouse";
>      dc->vmsd = &vmstate_usb_ptr;
> -    dc->props = usb_mouse_properties;
> +    device_class_set_props(dc, usb_mouse_properties);
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>  }
>  
> @@ -859,7 +859,7 @@ static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
>      uc->realize        = usb_keyboard_realize;
>      uc->product_desc   = "QEMU USB Keyboard";
>      dc->vmsd = &vmstate_usb_kbd;
> -    dc->props = usb_keyboard_properties;
> +    device_class_set_props(dc, usb_keyboard_properties);
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>  }
>  
> diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
> index 58d95ff..b9f1cbf 100644
> --- a/hw/usb/dev-mtp.c
> +++ b/hw/usb/dev-mtp.c
> @@ -1583,7 +1583,7 @@ static void usb_mtp_class_initfn(ObjectClass *klass, void *data)
>      uc->handle_data    = usb_mtp_handle_data;
>      dc->fw_name = "mtp";
>      dc->vmsd = &vmstate_usb_mtp;
> -    dc->props = mtp_properties;
> +    device_class_set_props(dc, mtp_properties);
>  }
>  
>  static TypeInfo mtp_info = {
> diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
> index c0f1193..4f9016e 100644
> --- a/hw/usb/dev-network.c
> +++ b/hw/usb/dev-network.c
> @@ -1432,7 +1432,7 @@ static void usb_net_class_initfn(ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
>      dc->fw_name = "network";
>      dc->vmsd = &vmstate_usb_net;
> -    dc->props = net_properties;
> +    device_class_set_props(dc, net_properties);
>  }
>  
>  static const TypeInfo net_info = {
> diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
> index 6066d9b..a912f44 100644
> --- a/hw/usb/dev-serial.c
> +++ b/hw/usb/dev-serial.c
> @@ -613,7 +613,7 @@ static void usb_serial_class_initfn(ObjectClass *klass, void *data)
>  
>      uc->product_desc   = "QEMU USB Serial";
>      uc->usb_desc       = &desc_serial;
> -    dc->props = serial_properties;
> +    device_class_set_props(dc, serial_properties);
>  }
>  
>  static const TypeInfo serial_info = {
> @@ -634,7 +634,7 @@ static void usb_braille_class_initfn(ObjectClass *klass, void *data)
>  
>      uc->product_desc   = "QEMU USB Braille";
>      uc->usb_desc       = &desc_braille;
> -    dc->props = braille_properties;
> +    device_class_set_props(dc, braille_properties);
>  }
>  
>  static const TypeInfo braille_info = {
> diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
> index af4b851..ed9e759 100644
> --- a/hw/usb/dev-smartcard-reader.c
> +++ b/hw/usb/dev-smartcard-reader.c
> @@ -1462,7 +1462,7 @@ static void ccid_class_initfn(ObjectClass *klass, void *data)
>      uc->handle_destroy = ccid_handle_destroy;
>      dc->desc = "CCID Rev 1.1 smartcard reader";
>      dc->vmsd = &ccid_vmstate;
> -    dc->props = ccid_properties;
> +    device_class_set_props(dc, ccid_properties);
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>      hc->unplug = qdev_simple_device_unplug_cb;
>  }
> @@ -1484,7 +1484,7 @@ static void ccid_card_class_init(ObjectClass *klass, void *data)
>      k->bus_type = TYPE_CCID_BUS;
>      k->init = ccid_card_init;
>      k->exit = ccid_card_exit;
> -    k->props = ccid_props;
> +    device_class_set_props(k, ccid_props);
>  }
>  
>  static const TypeInfo ccid_card_type_info = {
> diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
> index c607f76..47ff7b5 100644
> --- a/hw/usb/dev-storage.c
> +++ b/hw/usb/dev-storage.c
> @@ -755,7 +755,7 @@ static void usb_msd_class_initfn_storage(ObjectClass *klass, void *data)
>      USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
>  
>      uc->realize = usb_msd_realize_storage;
> -    dc->props = msd_properties;
> +    device_class_set_props(dc, msd_properties);
>  }
>  
>  static void usb_msd_get_bootindex(Object *obj, Visitor *v, const char *name,
> diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
> index 3a8ff18..5bf7c81 100644
> --- a/hw/usb/dev-uas.c
> +++ b/hw/usb/dev-uas.c
> @@ -948,7 +948,7 @@ static void usb_uas_class_initfn(ObjectClass *klass, void *data)
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
>      dc->fw_name = "storage";
>      dc->vmsd = &vmstate_usb_uas;
> -    dc->props = uas_properties;
> +    device_class_set_props(dc, uas_properties);
>  }
>  
>  static const TypeInfo uas_info = {
> diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c
> index 5657705..8cda359 100644
> --- a/hw/usb/hcd-ehci-pci.c
> +++ b/hw/usb/hcd-ehci-pci.c
> @@ -150,7 +150,7 @@ static void ehci_class_init(ObjectClass *klass, void *data)
>      k->class_id = PCI_CLASS_SERIAL_USB;
>      k->config_write = usb_ehci_pci_write_config;
>      dc->vmsd = &vmstate_ehci_pci;
> -    dc->props = ehci_pci_properties;
> +    device_class_set_props(dc, ehci_pci_properties);
>      dc->reset = usb_ehci_pci_reset;
>  }
>  
> diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
> index 6c20604..2264b66 100644
> --- a/hw/usb/hcd-ehci-sysbus.c
> +++ b/hw/usb/hcd-ehci-sysbus.c
> @@ -79,7 +79,7 @@ static void ehci_sysbus_class_init(ObjectClass *klass, void *data)
>  
>      dc->realize = usb_ehci_sysbus_realize;
>      dc->vmsd = &vmstate_ehci_sysbus;
> -    dc->props = ehci_sysbus_properties;
> +    device_class_set_props(dc, ehci_sysbus_properties);
>      dc->reset = usb_ehci_sysbus_reset;
>      set_bit(DEVICE_CATEGORY_USB, dc->categories);
>  }
> diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
> index c82a92f..0cdb549 100644
> --- a/hw/usb/hcd-ohci.c
> +++ b/hw/usb/hcd-ohci.c
> @@ -2124,7 +2124,7 @@ static void ohci_pci_class_init(ObjectClass *klass, void *data)
>      k->class_id = PCI_CLASS_SERIAL_USB;
>      set_bit(DEVICE_CATEGORY_USB, dc->categories);
>      dc->desc = "Apple USB Controller";
> -    dc->props = ohci_pci_properties;
> +    device_class_set_props(dc, ohci_pci_properties);
>      dc->hotpluggable = false;
>      dc->vmsd = &vmstate_ohci;
>      dc->reset = usb_ohci_reset_pci;
> @@ -2150,7 +2150,7 @@ static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
>      dc->realize = ohci_realize_pxa;
>      set_bit(DEVICE_CATEGORY_USB, dc->categories);
>      dc->desc = "OHCI USB Controller";
> -    dc->props = ohci_sysbus_properties;
> +    device_class_set_props(dc, ohci_sysbus_properties);
>      dc->reset = usb_ohci_reset_sysbus;
>  }
>  
> diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
> index ca72a80..47fa0a0 100644
> --- a/hw/usb/hcd-uhci.c
> +++ b/hw/usb/hcd-uhci.c
> @@ -1340,9 +1340,9 @@ static void uhci_data_class_init(ObjectClass *klass, void *data)
>      if (!info->unplug) {
>          /* uhci controllers in companion setups can't be hotplugged */
>          dc->hotpluggable = false;
> -        dc->props = uhci_properties_companion;
> +        device_class_set_props(dc, uhci_properties_companion);
>      } else {
> -        dc->props = uhci_properties_standalone;
> +        device_class_set_props(dc, uhci_properties_standalone);
>      }
>      u->info = *info;
>  }
> diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
> index 4acf0c6..4b33e6e 100644
> --- a/hw/usb/hcd-xhci.c
> +++ b/hw/usb/hcd-xhci.c
> @@ -3945,7 +3945,7 @@ static void xhci_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->vmsd    = &vmstate_xhci;
> -    dc->props   = xhci_properties;
> +    device_class_set_props(dc, xhci_properties);
>      dc->reset   = xhci_reset;
>      set_bit(DEVICE_CATEGORY_USB, dc->categories);
>      k->realize      = usb_xhci_realize;
> diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
> index bd81d71..f8dacb5 100644
> --- a/hw/usb/host-libusb.c
> +++ b/hw/usb/host-libusb.c
> @@ -1573,7 +1573,7 @@ static void usb_host_class_initfn(ObjectClass *klass, void *data)
>      uc->alloc_streams  = usb_host_alloc_streams;
>      uc->free_streams   = usb_host_free_streams;
>      dc->vmsd = &vmstate_usb_host;
> -    dc->props = usb_host_dev_properties;
> +    device_class_set_props(dc, usb_host_dev_properties);
>      set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
>  }
>  
> diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
> index 528081e..6a0b900 100644
> --- a/hw/usb/redirect.c
> +++ b/hw/usb/redirect.c
> @@ -2508,7 +2508,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data)
>      uc->alloc_streams  = usbredir_alloc_streams;
>      uc->free_streams   = usbredir_free_streams;
>      dc->vmsd           = &usbredir_vmstate;
> -    dc->props          = usbredir_properties;
> +    device_class_set_props(dc, usbredir_properties);
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>  }
>  
> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> index 65d30fd..a17c264 100644
> --- a/hw/vfio/pci.c
> +++ b/hw/vfio/pci.c
> @@ -2886,7 +2886,7 @@ static void vfio_pci_dev_class_init(ObjectClass *klass, void *data)
>      PCIDeviceClass *pdc = PCI_DEVICE_CLASS(klass);
>  
>      dc->reset = vfio_pci_reset;
> -    dc->props = vfio_pci_dev_properties;
> +    device_class_set_props(dc, vfio_pci_dev_properties);
>      dc->vmsd = &vfio_pci_vmstate;
>      dc->desc = "VFIO-based PCI device assignment";
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
> index a4663c9..9f618ba 100644
> --- a/hw/vfio/platform.c
> +++ b/hw/vfio/platform.c
> @@ -691,7 +691,7 @@ static void vfio_platform_class_init(ObjectClass *klass, void *data)
>      SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
>  
>      dc->realize = vfio_platform_realize;
> -    dc->props = vfio_platform_dev_properties;
> +    device_class_set_props(dc, vfio_platform_dev_properties);
>      dc->vmsd = &vfio_platform_vmstate;
>      dc->desc = "VFIO-based platform device assignment";
>      sbc->connect_irq_notifier = vfio_start_irqfd_injection;
> diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c
> index b481562..80718d8 100644
> --- a/hw/virtio/vhost-vsock.c
> +++ b/hw/virtio/vhost-vsock.c
> @@ -390,7 +390,7 @@ static void vhost_vsock_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
>  
> -    dc->props = vhost_vsock_properties;
> +    device_class_set_props(dc, vhost_vsock_properties);
>      dc->vmsd = &vmstate_virtio_vhost_vsock;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>      vdc->realize = vhost_vsock_device_realize;
> diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
> index 1d77028..fc67ea7 100644
> --- a/hw/virtio/virtio-balloon.c
> +++ b/hw/virtio/virtio-balloon.c
> @@ -508,7 +508,7 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
>  
> -    dc->props = virtio_balloon_properties;
> +    device_class_set_props(dc, virtio_balloon_properties);
>      dc->vmsd = &vmstate_virtio_balloon;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>      vdc->realize = virtio_balloon_device_realize;
> diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
> index 13798b3..14c98f7 100644
> --- a/hw/virtio/virtio-mmio.c
> +++ b/hw/virtio/virtio-mmio.c
> @@ -496,7 +496,7 @@ static void virtio_mmio_class_init(ObjectClass *klass, void *data)
>      dc->realize = virtio_mmio_realizefn;
>      dc->reset = virtio_mmio_reset;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> -    dc->props = virtio_mmio_properties;
> +    device_class_set_props(dc, virtio_mmio_properties);
>  }
>  
>  static const TypeInfo virtio_mmio_info = {
> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index 06831de..f44860d 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -1137,7 +1137,7 @@ static void virtio_9p_pci_class_init(ObjectClass *klass, void *data)
>      pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
>      pcidev_k->class_id = 0x2;
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
> -    dc->props = virtio_9p_pci_properties;
> +    device_class_set_props(dc, virtio_9p_pci_properties);
>  }
>  
>  static void virtio_9p_pci_instance_init(Object *obj)
> @@ -1899,7 +1899,7 @@ static void virtio_pci_class_init(ObjectClass *klass, void *data)
>      PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
>      VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass);
>  
> -    dc->props = virtio_pci_properties;
> +    device_class_set_props(dc, virtio_pci_properties);
>      k->realize = virtio_pci_realize;
>      k->exit = virtio_pci_exit;
>      k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
> @@ -1945,7 +1945,7 @@ static void virtio_blk_pci_class_init(ObjectClass *klass, void *data)
>      PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
>  
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
> -    dc->props = virtio_blk_pci_properties;
> +    device_class_set_props(dc, virtio_blk_pci_properties);
>      k->realize = virtio_blk_pci_realize;
>      pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
>      pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK;
> @@ -2017,7 +2017,7 @@ static void virtio_scsi_pci_class_init(ObjectClass *klass, void *data)
>  
>      k->realize = virtio_scsi_pci_realize;
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
> -    dc->props = virtio_scsi_pci_properties;
> +    device_class_set_props(dc, virtio_scsi_pci_properties);
>      pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
>      pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
>      pcidev_k->revision = 0x00;
> @@ -2072,7 +2072,7 @@ static void vhost_scsi_pci_class_init(ObjectClass *klass, void *data)
>      PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
>      k->realize = vhost_scsi_pci_realize;
>      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
> -    dc->props = vhost_scsi_pci_properties;
> +    device_class_set_props(dc, vhost_scsi_pci_properties);
>      pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
>      pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
>      pcidev_k->revision = 0x00;
> @@ -2122,7 +2122,7 @@ static void vhost_vsock_pci_class_init(ObjectClass *klass, void *data)
>      PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
>      k->realize = vhost_vsock_pci_realize;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> -    dc->props = vhost_vsock_pci_properties;
> +    device_class_set_props(dc, vhost_vsock_pci_properties);
>      pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
>      pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_VSOCK;
>      pcidev_k->revision = 0x00;
> @@ -2174,7 +2174,7 @@ static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data)
>      PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
>      k->realize = virtio_balloon_pci_realize;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> -    dc->props = virtio_balloon_pci_properties;
> +    device_class_set_props(dc, virtio_balloon_pci_properties);
>      pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
>      pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
>      pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
> @@ -2252,7 +2252,7 @@ static void virtio_serial_pci_class_init(ObjectClass *klass, void *data)
>      PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
>      k->realize = virtio_serial_pci_realize;
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
> -    dc->props = virtio_serial_pci_properties;
> +    device_class_set_props(dc, virtio_serial_pci_properties);
>      pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
>      pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE;
>      pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
> @@ -2308,7 +2308,7 @@ static void virtio_net_pci_class_init(ObjectClass *klass, void *data)
>      k->revision = VIRTIO_PCI_ABI_VERSION;
>      k->class_id = PCI_CLASS_NETWORK_ETHERNET;
>      set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
> -    dc->props = virtio_net_properties;
> +    device_class_set_props(dc, virtio_net_properties);
>      vpciklass->realize = virtio_net_pci_realize;
>  }
>  
> @@ -2406,7 +2406,7 @@ static void virtio_input_pci_class_init(ObjectClass *klass, void *data)
>      VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
>      PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
>  
> -    dc->props = virtio_input_pci_properties;
> +    device_class_set_props(dc, virtio_input_pci_properties);
>      k->realize = virtio_input_pci_realize;
>      set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
>  
> diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
> index 9639f4e..0ce422e 100644
> --- a/hw/virtio/virtio-rng.c
> +++ b/hw/virtio/virtio-rng.c
> @@ -237,7 +237,7 @@ static void virtio_rng_class_init(ObjectClass *klass, void *data)
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
>  
> -    dc->props = virtio_rng_properties;
> +    device_class_set_props(dc, virtio_rng_properties);
>      dc->vmsd = &vmstate_virtio_rng;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>      vdc->realize = virtio_rng_device_realize;
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index d48d1a9..f089ed8 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -2166,7 +2166,7 @@ static void virtio_device_class_init(ObjectClass *klass, void *data)
>      dc->realize = virtio_device_realize;
>      dc->unrealize = virtio_device_unrealize;
>      dc->bus_type = TYPE_VIRTIO_BUS;
> -    dc->props = virtio_properties;
> +    device_class_set_props(dc, virtio_properties);
>  }
>  
>  static const TypeInfo virtio_device_info = {
> diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
> index 69a2388..60b8d46 100644
> --- a/hw/xen/xen_backend.c
> +++ b/hw/xen/xen_backend.c
> @@ -877,7 +877,7 @@ static void xen_sysdev_class_init(ObjectClass *klass, void *data)
>      SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
>  
>      k->init = xen_sysdev_init;
> -    dc->props = xen_sysdev_properties;
> +    device_class_set_props(dc, xen_sysdev_properties);
>  }
>  
>  static const TypeInfo xensysdev_info = {
> diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
> index b6d71bb..592dc2b 100644
> --- a/hw/xen/xen_pt.c
> +++ b/hw/xen/xen_pt.c
> @@ -948,7 +948,7 @@ static void xen_pci_passthrough_class_init(ObjectClass *klass, void *data)
>      k->config_write = xen_pt_pci_write_config;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>      dc->desc = "Assign an host PCI device with Xen";
> -    dc->props = xen_pci_passthrough_properties;
> +    device_class_set_props(dc, xen_pci_passthrough_properties);
>  };
>  
>  static void xen_pci_passthrough_finalize(Object *obj)
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index 2c97347..6a41308 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -401,6 +401,12 @@ static inline bool qbus_is_hotpluggable(BusState *bus)
>     return bus->hotplug_handler;
>  }
>  
> +/* Set list of static properties for class
> + *
> + * It can be called only once per class.
> + */
> +void device_class_set_props(DeviceClass *dc, Property *props);
> +
>  void device_listener_register(DeviceListener *listener);
>  void device_listener_unregister(DeviceListener *listener);
>  
> diff --git a/target-arm/cpu.c b/target-arm/cpu.c
> index 2439ca5..ac8dd5d 100644
> --- a/target-arm/cpu.c
> +++ b/target-arm/cpu.c
> @@ -1531,7 +1531,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
>  
>      acc->parent_realize = dc->realize;
>      dc->realize = arm_cpu_realizefn;
> -    dc->props = arm_cpu_properties;
> +    device_class_set_props(dc, arm_cpu_properties);
>  
>      acc->parent_reset = cc->reset;
>      cc->reset = arm_cpu_reset;
> diff --git a/target-i386/cpu.c b/target-i386/cpu.c
> index 83998a8..ca9eaa5 100644
> --- a/target-i386/cpu.c
> +++ b/target-i386/cpu.c
> @@ -1579,7 +1579,7 @@ static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
>       * instance_init, because they require KVM to be initialized.
>       */
>  
> -    dc->props = host_x86_cpu_properties;
> +    device_class_set_props(dc, host_x86_cpu_properties);
>      /* Reason: host_x86_cpu_initfn() dies when !kvm_enabled() */
>      dc->cannot_destroy_with_object_finalize_yet = true;
>  }
> @@ -3651,7 +3651,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
>      xcc->parent_unrealize = dc->unrealize;
>      dc->realize = x86_cpu_realizefn;
>      dc->unrealize = x86_cpu_unrealizefn;
> -    dc->props = x86_cpu_properties;
> +    device_class_set_props(dc, x86_cpu_properties);
>  
>      xcc->parent_reset = cc->reset;
>      cc->reset = x86_cpu_reset;
> diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
> index 389c7b6..222b54c 100644
> --- a/target-microblaze/cpu.c
> +++ b/target-microblaze/cpu.c
> @@ -269,7 +269,7 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
>      cc->get_phys_page_debug = mb_cpu_get_phys_page_debug;
>  #endif
>      dc->vmsd = &vmstate_mb_cpu;
> -    dc->props = mb_properties;
> +    device_class_set_props(dc, mb_properties);
>      cc->gdb_num_core_regs = 32 + 5;
>  
>      cc->disas_set_info = mb_disas_set_info;
> diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
> index 208fa1e..c5d2de7 100644
> --- a/target-ppc/translate_init.c
> +++ b/target-ppc/translate_init.c
> @@ -8586,7 +8586,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
>  
>      dc->fw_name = "PowerPC,POWER7";
>      dc->desc = "POWER7";
> -    dc->props = powerpc_servercpu_properties;
> +    device_class_set_props(dc, powerpc_servercpu_properties);
>      pcc->pvr_match = ppc_pvr_match_power7;
>      pcc->pcr_mask = PCR_VEC_DIS | PCR_VSX_DIS | PCR_COMPAT_2_05;
>      pcc->pcr_supported = PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
> @@ -8713,7 +8713,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
>  
>      dc->fw_name = "PowerPC,POWER8";
>      dc->desc = "POWER8";
> -    dc->props = powerpc_servercpu_properties;
> +    device_class_set_props(dc, powerpc_servercpu_properties);
>      pcc->pvr_match = ppc_pvr_match_power8;
>      pcc->pcr_mask = PCR_TM_DIS | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
>      pcc->pcr_supported = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
> @@ -8794,7 +8794,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
>  
>      dc->fw_name = "PowerPC,POWER9";
>      dc->desc = "POWER9";
> -    dc->props = powerpc_servercpu_properties;
> +    device_class_set_props(dc, powerpc_servercpu_properties);
>      pcc->pvr_match = ppc_pvr_match_power9;
>      pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07;
>      pcc->init_proc = init_proc_POWER9;
> diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c
> index 48e5b73..2e9d6b9 100644
> --- a/tests/test-qdev-global-props.c
> +++ b/tests/test-qdev-global-props.c
> @@ -53,7 +53,7 @@ static void static_prop_class_init(ObjectClass *oc, void *data)
>      DeviceClass *dc = DEVICE_CLASS(oc);
>  
>      dc->realize = NULL;
> -    dc->props = static_props;
> +    device_class_set_props(dc, static_props);
>  }
>  
>  static const TypeInfo static_prop_type = {

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

* Re: [Qemu-devel] [PATCH v4 1/8] tests: check-qom-proplist: Remove duplicate "bv" property
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 1/8] tests: check-qom-proplist: Remove duplicate "bv" property Eduardo Habkost
@ 2016-11-04 11:22   ` Markus Armbruster
  2016-11-04 15:10     ` Markus Armbruster
  2016-11-04 15:56   ` Andreas Färber
  1 sibling, 1 reply; 50+ messages in thread
From: Markus Armbruster @ 2016-11-04 11:22 UTC (permalink / raw)
  To: Eduardo Habkost; +Cc: qemu-devel, Igor Mammedov, Andreas Färber

Eduardo Habkost <ehabkost@redhat.com> writes:

> The object_property_add_bool() call in dummy_init() is always
> failing because there is an existing "bv" class property. We need
> to remove either the "bv" class property or the "bv" instance
> property.
>
> Remove the class property so both object properties and class
> properties are covered by the test code.
>
> Reviewed-by: Igor Mammedov <imammedo@redhat.com>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>

I accidentally reviewed an older version of this patch.  Just in case:
Reviewed-by: Markus Armbruster <armbru@redhat.com>

The multiple colons in the subject are a bit odd.  Suggest
"tests/check-qom-proplist:".

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

* Re: [Qemu-devel] [PATCH v4 1/8] tests: check-qom-proplist: Remove duplicate "bv" property
  2016-11-04 11:22   ` Markus Armbruster
@ 2016-11-04 15:10     ` Markus Armbruster
  0 siblings, 0 replies; 50+ messages in thread
From: Markus Armbruster @ 2016-11-04 15:10 UTC (permalink / raw)
  To: Eduardo Habkost; +Cc: qemu-devel, Igor Mammedov, Andreas Färber

Markus Armbruster <armbru@redhat.com> writes:

> Eduardo Habkost <ehabkost@redhat.com> writes:
>
>> The object_property_add_bool() call in dummy_init() is always
>> failing because there is an existing "bv" class property. We need
>> to remove either the "bv" class property or the "bv" instance
>> property.
>>
>> Remove the class property so both object properties and class
>> properties are covered by the test code.
>>
>> Reviewed-by: Igor Mammedov <imammedo@redhat.com>
>> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
>
> I accidentally reviewed an older version of this patch.  Just in case:
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>
> The multiple colons in the subject are a bit odd.  Suggest
> "tests/check-qom-proplist:".

One more thing: you could test that adding a duplicate property fails.

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

* Re: [Qemu-devel] [PATCH v4 5/8] qdev: Register static properties as class properties
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 5/8] qdev: Register static properties as class properties Eduardo Habkost
  2016-10-31 12:06   ` Igor Mammedov
@ 2016-11-04 15:22   ` Markus Armbruster
  2016-11-04 16:00     ` Eduardo Habkost
  1 sibling, 1 reply; 50+ messages in thread
From: Markus Armbruster @ 2016-11-04 15:22 UTC (permalink / raw)
  To: Eduardo Habkost; +Cc: qemu-devel, Igor Mammedov, Andreas Färber

Eduardo Habkost <ehabkost@redhat.com> writes:

> Instead of registering qdev static properties on instance_init,
> register them as class properties, at qdev_class_set_props().
>
> qdev_property_add_legacy() was replaced by an equivalent
> qdev_class_property_add_legacy() function.
> qdev_property_add_static(), on the other hand, can't be
> eliminated yet because it is used by arm_cpu_post_init().
>
> As class properties don't have a release function called when an
> object instance is destroyed, the release functions for
> properties are called manually from device_finalize().

Ignorant question: should class properties have such a release function?

Hmm, I see object_class_property_add() does take a release().  Is that
one called at the wrong time?

One typo noted below.

> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> Changes series v1 -> v2:
> * (none)
>
> Changes v2 -> v3:
> * Fix code alignemnt
>   * Reported-by: Igor Mammedov <imammedo@redhat.com>
>
> Changes series v3 -> v4:
> * s/Device/Class/ on qdev_class_property_add_legacy() doc comment
>   * Reported-by: Igor Mammedov <imammedo@redhat.com>
> * Call prop->info->release on instance_finalize (fix
>   tests/drive_del-test failure)
> ---
>  hw/core/qdev.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++----------
>  1 file changed, 69 insertions(+), 13 deletions(-)
>
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 85952e8..e695fa8 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -739,12 +739,12 @@ static void qdev_get_legacy_property(Object *obj, Visitor *v,
>  }
>  
>  /**
> - * qdev_property_add_legacy:
> - * @dev: Device to add the property to.
> + * qdev_class_property_add_legacy:
> + * @oc: Class to add the property to.
>   * @prop: The qdev property definition.
>   * @errp: location to store error information.
>   *
> - * Add a legacy QOM property to @dev for qdev property @prop.
> + * Add a legacy QOM property to @oc for qdev property @prop.
>   * On error, store error in @errp.
>   *
>   * Legacy properties are string versions of QOM properties.  The format of
> @@ -754,8 +754,8 @@ static void qdev_get_legacy_property(Object *obj, Visitor *v,
>   * Do not use this is new code!  QOM Properties added through this interface
>   * will be given names in the "legacy" namespace.
>   */
> -static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
> -                                     Error **errp)
> +static void qdev_class_property_add_legacy(ObjectClass *oc, Property *prop,
> +                                           Error **errp)
>  {
>      gchar *name;
>  
> @@ -765,11 +765,12 @@ static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
>      }
>  
>      name = g_strdup_printf("legacy-%s", prop->name);
> -    object_property_add(OBJECT(dev), name, "str",
> -                        prop->info->print ? qdev_get_legacy_property : prop->info->get,
> -                        NULL,
> -                        NULL,
> -                        prop, errp);
> +    object_class_property_add(oc, name, "str",
> +                              prop->info->print ?
> +                                  qdev_get_legacy_property :
> +                                  prop->info->get,
> +                              NULL, NULL,
> +                              prop, errp);
>  
>      g_free(name);
>  }
> @@ -844,6 +845,48 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
>      qdev_property_set_to_default(dev, prop, &error_abort);
>  }
>  
> +/**
> + * qdev_class_property_add_static:
> + * @oc: Class to add the property to.
> + * @prop: The qdev property definition.
> + * @errp: location to store error information.
> + *
> + * Add a static QOM property to @oc for qdev property @prop.
> + * On error, store error in @errp.  Static properties access data in a struct.
> + * The type of the QOM property is derived from prop->info.
> + */
> +static void qdev_class_property_add_static(ObjectClass *oc, Property *prop,
> +                                           Error **errp)
> +{
> +    Error *local_err = NULL;
> +
> +    /*
> +     * TODO qdev_prop_ptr does not have getters or setters.  It must
> +     * go now that it can be replaced with links.  The test should be
> +     * removed along with it: all static properties are read/write.
> +     */
> +    if (!prop->info->get && !prop->info->set) {
> +        return;
> +    }
> +
> +    /* Note: prop->info->release is called on device_finalize(),
> +     * because it needs to be called on instaqnce destruction, not on

instance

> +     * class property removal.
> +     */
> +    object_class_property_add(oc, prop->name, prop->info->name,
> +                              prop->info->get, prop->info->set,
> +                              NULL, prop, &local_err);
> +
> +    if (local_err) {
> +        error_propagate(errp, local_err);
> +        return;
> +    }
> +
> +    object_class_property_set_description(oc, prop->name,
> +                                          prop->info->description,
> +                                          &error_abort);
> +}
> +
>  /* @qdev_alias_all_properties - Add alias properties to the source object for
>   * all qdev properties on the target DeviceState.
>   */
> @@ -867,8 +910,15 @@ void qdev_alias_all_properties(DeviceState *target, Object *source)
>  
>  void device_class_set_props(DeviceClass *dc, Property *props)
>  {
> +    Property *prop;
> +    ObjectClass *oc = OBJECT_CLASS(dc);
> +
>      assert(!dc->props);
>      dc->props = props;
> +    for (prop = dc->props; prop && prop->name; prop++) {
> +        qdev_class_property_add_legacy(oc, prop, &error_abort);
> +        qdev_class_property_add_static(oc, prop, &error_abort);
> +    }
>  }
>  
>  static int qdev_add_hotpluggable_device(Object *obj, void *opaque)
> @@ -1068,8 +1118,7 @@ static void device_initfn(Object *obj)
>      class = object_get_class(OBJECT(dev));
>      do {
>          for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
> -            qdev_property_add_legacy(dev, prop, &error_abort);
> -            qdev_property_add_static(dev, prop, &error_abort);
> +            qdev_property_set_to_default(dev, prop, &error_abort);
>          }
>          class = object_class_get_parent(class);
>      } while (class != object_class_by_name(TYPE_DEVICE));
> @@ -1088,9 +1137,16 @@ static void device_post_init(Object *obj)
>  /* Unlink device from bus and free the structure.  */
>  static void device_finalize(Object *obj)
>  {
> +    DeviceState *dev = DEVICE(obj);
> +    DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +    Property *prop;
>      NamedGPIOList *ngl, *next;
>  
> -    DeviceState *dev = DEVICE(obj);
> +    for (prop = dc->props; prop && prop->name; prop++) {
> +        if (prop->info->release) {
> +            prop->info->release(obj, prop->name, prop);
> +        }
> +    }
>  
>      QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) {
>          QLIST_REMOVE(ngl, node);

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

* Re: [Qemu-devel] [PATCH v4 6/8] qom: object_class_property_iter_init() function
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 6/8] qom: object_class_property_iter_init() function Eduardo Habkost
  2016-10-31 13:45   ` Igor Mammedov
@ 2016-11-04 15:31   ` Markus Armbruster
  1 sibling, 0 replies; 50+ messages in thread
From: Markus Armbruster @ 2016-11-04 15:31 UTC (permalink / raw)
  To: Eduardo Habkost; +Cc: qemu-devel, Igor Mammedov, Andreas Färber

Eduardo Habkost <ehabkost@redhat.com> writes:

> The new function will allow us to iterate over class properties
> using the same logic we use for object properties. Unit test
> included.
>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> Changes series v1 -> v3:
> * (none)
>
> Changes series v3 -> v4:
> * Trivial whitespace change (removed extra newline)
> ---
>  include/qom/object.h       | 14 ++++++++++++++
>  qom/object.c               | 10 ++++++++--
>  tests/check-qom-proplist.c | 28 ++++++++++++++++++++++++++++
>  3 files changed, 50 insertions(+), 2 deletions(-)
>
> diff --git a/include/qom/object.h b/include/qom/object.h
> index 5ecc2d1..6e3646e 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -995,6 +995,20 @@ void object_property_iter_init(ObjectPropertyIterator *iter,
>                                 Object *obj);
>  
>  /**
> + * object_class_property_iter_init:
> + * @klass: the class
> + *
> + * Initializes an iterator for traversing all properties
> + * registered against an object class and all parent classes.
> + *
> + * It is forbidden to modify the property list while iterating,
> + * whether removing or adding properties.

You chose not to duplicate the example from
object_property_iter_init()'s function comment.  That's okay, but you
might want to point to it.

> + */
> +void object_class_property_iter_init(ObjectPropertyIterator *iter,
> +                                     ObjectClass *klass);
> +
> +
> +/**
>   * object_property_iter_next:
>   * @iter: the iterator instance
>   *
[...]

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-10-31 14:36     ` Eduardo Habkost
@ 2016-11-04 15:45       ` Markus Armbruster
  2016-11-04 16:04         ` Eduardo Habkost
  0 siblings, 1 reply; 50+ messages in thread
From: Markus Armbruster @ 2016-11-04 15:45 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Igor Mammedov, libvir-list, qemu-devel, Jiri Denemark,
	Andreas Färber

Eduardo Habkost <ehabkost@redhat.com> writes:

> (CCing libvirt people, as I forgot to CC them)
>
> On Mon, Oct 31, 2016 at 03:07:23PM +0100, Igor Mammedov wrote:
>> On Fri, 28 Oct 2016 23:48:06 -0200
>> Eduardo Habkost <ehabkost@redhat.com> wrote:
>> 
>> > When an abstract class is used on device-list-properties, we can
>> > simply return the class properties registered for the class.
>> > 
>> > This will be useful if management software needs to query for
>> > supported options that apply to all devices of a given type (e.g.
>> > options supported by all CPU models, options supported by all PCI
>> > devices).
>> Patch looks fine to me but I'm not qmp interface guru
>> so I'd leave review up to maintainers.
>> 
>> One question though,
>> How would management software discover typename of abstract class?
>
> It depends on the use case. On some cases, management may already
> have bus-specific logic that will know what's the base type it
> needs to query (e.g. it may query "pci-device" to find out if all
> PCI devices support a given option). On other cases, it may be
> discovered using other commands.

The stated purpose of this feature is to let management software "query
for supported options that apply to all devices of a given type".  I
suspect that when management software has a notion of "a given type", it
knows its name.

Will management software go fishing for subtype relationships beyond the
types it knows?  I doubt it.  Of course, management software developers
are welcome to educate me :)

> For the CPU case, I will propose adding the base QOM CPU typename
> in the query-target command.

Does this type name vary?  If yes, can you give examples?

>> Perhaps this patch should be part of some other series.
>
> This is a valid point. In this case, it depends on the approach
> we want to take: do we want to provide a flexible interface for
> management, let them find ways to make it useful and give us
> feedback on what is lacking; or do we want to provide the new
> interface only after we have specified the complete solution for
> the problem?
>
> I don't know the answer. I will let the qdev/QOM/QMP maintainers
> answer that.

I'm reluctant to add QMP features just because we think they might be
useful to someone.  We should talk to users to confirm our hunch before
we act on it.

That said, this one isn't exactly a biggie.

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

* Re: [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties
  2016-10-29  1:47 [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties Eduardo Habkost
                   ` (7 preceding siblings ...)
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 8/8] qdev: Warning about using qdev_property_add_static() in new code Eduardo Habkost
@ 2016-11-04 15:52 ` Markus Armbruster
  8 siblings, 0 replies; 50+ messages in thread
From: Markus Armbruster @ 2016-11-04 15:52 UTC (permalink / raw)
  To: Eduardo Habkost; +Cc: qemu-devel, Igor Mammedov, Andreas Färber

Just minor comments, do series
Reviewed-by: Markus Armbruster <armbru@redhat.com>

I'd like to see a clearer need for PATCH 7, though.  Shouldn't hold up
the rest.

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

* Re: [Qemu-devel] [PATCH v4 1/8] tests: check-qom-proplist: Remove duplicate "bv" property
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 1/8] tests: check-qom-proplist: Remove duplicate "bv" property Eduardo Habkost
  2016-11-04 11:22   ` Markus Armbruster
@ 2016-11-04 15:56   ` Andreas Färber
  2016-11-04 16:07     ` Eduardo Habkost
  1 sibling, 1 reply; 50+ messages in thread
From: Andreas Färber @ 2016-11-04 15:56 UTC (permalink / raw)
  To: Eduardo Habkost, qemu-devel; +Cc: Igor Mammedov, Markus Armbruster

Am 29.10.2016 um 03:48 schrieb Eduardo Habkost:
> The object_property_add_bool() call in dummy_init() is always
> failing because there is an existing "bv" class property. We need
> to remove either the "bv" class property or the "bv" instance
> property.
> 
> Remove the class property so both object properties and class
> properties are covered by the test code.
> 
> Reviewed-by: Igor Mammedov <imammedo@redhat.com>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> Changes series v2 -> v3:
> * Patch imported from "tests: A few check-qom-proplist fixes"
>   series
> * Reworded commit message for clarity

So I understand this patch was reordered from a previous separate
series. Surely Peter did not merge any pulls that cause test failures,
so the first paragraph in the commit message needs rewording?

Regards,
Andreas

-- 
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)

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

* Re: [Qemu-devel] [PATCH v4 5/8] qdev: Register static properties as class properties
  2016-11-04 15:22   ` Markus Armbruster
@ 2016-11-04 16:00     ` Eduardo Habkost
  0 siblings, 0 replies; 50+ messages in thread
From: Eduardo Habkost @ 2016-11-04 16:00 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Igor Mammedov, Andreas Färber

On Fri, Nov 04, 2016 at 04:22:40PM +0100, Markus Armbruster wrote:
> Eduardo Habkost <ehabkost@redhat.com> writes:
> 
> > Instead of registering qdev static properties on instance_init,
> > register them as class properties, at qdev_class_set_props().
> >
> > qdev_property_add_legacy() was replaced by an equivalent
> > qdev_class_property_add_legacy() function.
> > qdev_property_add_static(), on the other hand, can't be
> > eliminated yet because it is used by arm_cpu_post_init().
> >
> > As class properties don't have a release function called when an
> > object instance is destroyed, the release functions for
> > properties are called manually from device_finalize().
> 
> Ignorant question: should class properties have such a release function?

I don't think they need one (because it is not possible to
destroy classes yet). Even if they should, most of the existing
QOM release functions are not meant to be called every time an
object is destroyed (but still get Object* as argument, which is
confusing).

qdev property release functions, on the other hand, are actually
meant to be called every time an object is destroyed.
(Confusing, uh?)

I have patches to remove the release function and to clarify the
intent of qdev release functions. I just didn't include them in
this series to keep it simpler.

> 
> Hmm, I see object_class_property_add() does take a release().  Is that
> one called at the wrong time?

The function is actually never called. I thought they were meant
to be called when the object is destroyed, but most (but not
all?) of the existing release functions are meant to be called to
release its void* opaque pointer (so they were really supposed to
be called only if the class is being destroyed).

> 
> One typo noted below.
> 
[...]
> > +    /* Note: prop->info->release is called on device_finalize(),
> > +     * because it needs to be called on instaqnce destruction, not on
> 
> instance

Thanks. I will fix it in the next version.

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-04 15:45       ` Markus Armbruster
@ 2016-11-04 16:04         ` Eduardo Habkost
  2016-11-07  8:09           ` Markus Armbruster
  0 siblings, 1 reply; 50+ messages in thread
From: Eduardo Habkost @ 2016-11-04 16:04 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Igor Mammedov, libvir-list, qemu-devel, Jiri Denemark,
	Andreas Färber

On Fri, Nov 04, 2016 at 04:45:17PM +0100, Markus Armbruster wrote:
> Eduardo Habkost <ehabkost@redhat.com> writes:
> 
> > (CCing libvirt people, as I forgot to CC them)
> >
> > On Mon, Oct 31, 2016 at 03:07:23PM +0100, Igor Mammedov wrote:
> >> On Fri, 28 Oct 2016 23:48:06 -0200
> >> Eduardo Habkost <ehabkost@redhat.com> wrote:
> >> 
> >> > When an abstract class is used on device-list-properties, we can
> >> > simply return the class properties registered for the class.
> >> > 
> >> > This will be useful if management software needs to query for
> >> > supported options that apply to all devices of a given type (e.g.
> >> > options supported by all CPU models, options supported by all PCI
> >> > devices).
> >> Patch looks fine to me but I'm not qmp interface guru
> >> so I'd leave review up to maintainers.
> >> 
> >> One question though,
> >> How would management software discover typename of abstract class?
> >
> > It depends on the use case. On some cases, management may already
> > have bus-specific logic that will know what's the base type it
> > needs to query (e.g. it may query "pci-device" to find out if all
> > PCI devices support a given option). On other cases, it may be
> > discovered using other commands.
> 
> The stated purpose of this feature is to let management software "query
> for supported options that apply to all devices of a given type".  I
> suspect that when management software has a notion of "a given type", it
> knows its name.
> 
> Will management software go fishing for subtype relationships beyond the
> types it knows?  I doubt it.  Of course, management software developers
> are welcome to educate me :)
> 
> > For the CPU case, I will propose adding the base QOM CPU typename
> > in the query-target command.
> 
> Does this type name vary?  If yes, can you give examples?

It does. x86-specific CPU properties are on the x86_64-cpu and
i386-cpu classes. arm-specific CPU properties are on the arm-cpu
class.

> 
> >> Perhaps this patch should be part of some other series.
> >
> > This is a valid point. In this case, it depends on the approach
> > we want to take: do we want to provide a flexible interface for
> > management, let them find ways to make it useful and give us
> > feedback on what is lacking; or do we want to provide the new
> > interface only after we have specified the complete solution for
> > the problem?
> >
> > I don't know the answer. I will let the qdev/QOM/QMP maintainers
> > answer that.
> 
> I'm reluctant to add QMP features just because we think they might be
> useful to someone.  We should talk to users to confirm our hunch before
> we act on it.
> 
> That said, this one isn't exactly a biggie.

Considering we are past soft freeze, I can document a more
concrete usage example when I submit the next version.

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v4 1/8] tests: check-qom-proplist: Remove duplicate "bv" property
  2016-11-04 15:56   ` Andreas Färber
@ 2016-11-04 16:07     ` Eduardo Habkost
  2016-11-04 16:11       ` Andreas Färber
  0 siblings, 1 reply; 50+ messages in thread
From: Eduardo Habkost @ 2016-11-04 16:07 UTC (permalink / raw)
  To: Andreas Färber; +Cc: qemu-devel, Igor Mammedov, Markus Armbruster

On Fri, Nov 04, 2016 at 04:56:29PM +0100, Andreas Färber wrote:
> Am 29.10.2016 um 03:48 schrieb Eduardo Habkost:
> > The object_property_add_bool() call in dummy_init() is always
> > failing because there is an existing "bv" class property. We need
> > to remove either the "bv" class property or the "bv" instance
> > property.
> > 
> > Remove the class property so both object properties and class
> > properties are covered by the test code.
> > 
> > Reviewed-by: Igor Mammedov <imammedo@redhat.com>
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > ---
> > Changes series v2 -> v3:
> > * Patch imported from "tests: A few check-qom-proplist fixes"
> >   series
> > * Reworded commit message for clarity
> 
> So I understand this patch was reordered from a previous separate
> series. Surely Peter did not merge any pulls that cause test failures,
> so the first paragraph in the commit message needs rewording?

The object_property_add_bool() call is always failing on current
master. It doesn't mean the test case is failing (because the
errors reported by object_property_add_bool() are being silently
ignored).

Would it be clearer if I rewrite it as "The object_property_add_bool()
call in dummy_init() is always failing (but the error is being
silently ignored) because [...]"?

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v4 1/8] tests: check-qom-proplist: Remove duplicate "bv" property
  2016-11-04 16:07     ` Eduardo Habkost
@ 2016-11-04 16:11       ` Andreas Färber
  0 siblings, 0 replies; 50+ messages in thread
From: Andreas Färber @ 2016-11-04 16:11 UTC (permalink / raw)
  To: Eduardo Habkost; +Cc: qemu-devel, Igor Mammedov, Markus Armbruster

Am 04.11.2016 um 17:07 schrieb Eduardo Habkost:
> On Fri, Nov 04, 2016 at 04:56:29PM +0100, Andreas Färber wrote:
>> Am 29.10.2016 um 03:48 schrieb Eduardo Habkost:
>>> The object_property_add_bool() call in dummy_init() is always
>>> failing because there is an existing "bv" class property. We need
>>> to remove either the "bv" class property or the "bv" instance
>>> property.
>>>
>>> Remove the class property so both object properties and class
>>> properties are covered by the test code.
>>>
>>> Reviewed-by: Igor Mammedov <imammedo@redhat.com>
>>> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
>>> ---
>>> Changes series v2 -> v3:
>>> * Patch imported from "tests: A few check-qom-proplist fixes"
>>>   series
>>> * Reworded commit message for clarity
>>
>> So I understand this patch was reordered from a previous separate
>> series. Surely Peter did not merge any pulls that cause test failures,
>> so the first paragraph in the commit message needs rewording?
> 
> The object_property_add_bool() call is always failing on current
> master. It doesn't mean the test case is failing (because the
> errors reported by object_property_add_bool() are being silently
> ignored).
> 
> Would it be clearer if I rewrite it as "The object_property_add_bool()
> call in dummy_init() is always failing (but the error is being
> silently ignored) because [...]"?

Thanks, I can make that tweak myself then.

Regards,
Andreas

-- 
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-04 16:04         ` Eduardo Habkost
@ 2016-11-07  8:09           ` Markus Armbruster
  2016-11-07 12:38             ` Eduardo Habkost
  0 siblings, 1 reply; 50+ messages in thread
From: Markus Armbruster @ 2016-11-07  8:09 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: libvir-list, Igor Mammedov, Jiri Denemark, qemu-devel,
	Andreas Färber

Eduardo Habkost <ehabkost@redhat.com> writes:

> On Fri, Nov 04, 2016 at 04:45:17PM +0100, Markus Armbruster wrote:
>> Eduardo Habkost <ehabkost@redhat.com> writes:
>> 
>> > (CCing libvirt people, as I forgot to CC them)
>> >
>> > On Mon, Oct 31, 2016 at 03:07:23PM +0100, Igor Mammedov wrote:
>> >> On Fri, 28 Oct 2016 23:48:06 -0200
>> >> Eduardo Habkost <ehabkost@redhat.com> wrote:
>> >> 
>> >> > When an abstract class is used on device-list-properties, we can
>> >> > simply return the class properties registered for the class.
>> >> > 
>> >> > This will be useful if management software needs to query for
>> >> > supported options that apply to all devices of a given type (e.g.
>> >> > options supported by all CPU models, options supported by all PCI
>> >> > devices).
>> >> Patch looks fine to me but I'm not qmp interface guru
>> >> so I'd leave review up to maintainers.
>> >> 
>> >> One question though,
>> >> How would management software discover typename of abstract class?
>> >
>> > It depends on the use case. On some cases, management may already
>> > have bus-specific logic that will know what's the base type it
>> > needs to query (e.g. it may query "pci-device" to find out if all
>> > PCI devices support a given option). On other cases, it may be
>> > discovered using other commands.
>> 
>> The stated purpose of this feature is to let management software "query
>> for supported options that apply to all devices of a given type".  I
>> suspect that when management software has a notion of "a given type", it
>> knows its name.
>> 
>> Will management software go fishing for subtype relationships beyond the
>> types it knows?  I doubt it.  Of course, management software developers
>> are welcome to educate me :)
>> 
>> > For the CPU case, I will propose adding the base QOM CPU typename
>> > in the query-target command.
>> 
>> Does this type name vary?  If yes, can you give examples?
>
> It does. x86-specific CPU properties are on the x86_64-cpu and
> i386-cpu classes. arm-specific CPU properties are on the arm-cpu
> class.

I see we have concrete CPUs (such as "Westmere-x86_64-cpu"), which are
subtypes of an abstract CPU (such as "x86_64-cpu"), which is a subtype
of "cpu", which is a subtype of "device", which is a subtype of
"object".

The chain "cpu" - "device" - "object" is fixed and well-known.

The link from there to the concrete CPU varies.  Whether it could be
considered well-known or not is debatable.

My true question is: should we have a special purpose interface to get
the abstract supertype of concrete CPU types, or should be have general
purpose means to introspect the subtype hierarchy?

Note that we have the latter already, although in a rather cumbersome
form:

    { "execute": "qom-list-types",
      "arguments": { "implements": T, "abstract": true } }

lists all subtypes of T.  You can filter out the concrete subtypes by
subtracting the same query with "abstract": false.  Start with the
type you're interested in, find all its abstract supertypes.  If you
need to know more, repeat for the types you found.

>> >> Perhaps this patch should be part of some other series.
>> >
>> > This is a valid point. In this case, it depends on the approach
>> > we want to take: do we want to provide a flexible interface for
>> > management, let them find ways to make it useful and give us
>> > feedback on what is lacking; or do we want to provide the new
>> > interface only after we have specified the complete solution for
>> > the problem?
>> >
>> > I don't know the answer. I will let the qdev/QOM/QMP maintainers
>> > answer that.
>> 
>> I'm reluctant to add QMP features just because we think they might be
>> useful to someone.  We should talk to users to confirm our hunch before
>> we act on it.
>> 
>> That said, this one isn't exactly a biggie.
>
> Considering we are past soft freeze, I can document a more
> concrete usage example when I submit the next version.

I recommend you get libvirt developers to buy into this feature first.

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07  8:09           ` Markus Armbruster
@ 2016-11-07 12:38             ` Eduardo Habkost
  2016-11-07 14:40               ` Markus Armbruster
  0 siblings, 1 reply; 50+ messages in thread
From: Eduardo Habkost @ 2016-11-07 12:38 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: libvir-list, Igor Mammedov, Jiri Denemark, qemu-devel,
	Andreas Färber

On Mon, Nov 07, 2016 at 09:09:58AM +0100, Markus Armbruster wrote:
> Eduardo Habkost <ehabkost@redhat.com> writes:
> 
> > On Fri, Nov 04, 2016 at 04:45:17PM +0100, Markus Armbruster wrote:
> >> Eduardo Habkost <ehabkost@redhat.com> writes:
> >> 
> >> > (CCing libvirt people, as I forgot to CC them)
> >> >
> >> > On Mon, Oct 31, 2016 at 03:07:23PM +0100, Igor Mammedov wrote:
> >> >> On Fri, 28 Oct 2016 23:48:06 -0200
> >> >> Eduardo Habkost <ehabkost@redhat.com> wrote:
> >> >> 
> >> >> > When an abstract class is used on device-list-properties, we can
> >> >> > simply return the class properties registered for the class.
> >> >> > 
> >> >> > This will be useful if management software needs to query for
> >> >> > supported options that apply to all devices of a given type (e.g.
> >> >> > options supported by all CPU models, options supported by all PCI
> >> >> > devices).
> >> >> Patch looks fine to me but I'm not qmp interface guru
> >> >> so I'd leave review up to maintainers.
> >> >> 
> >> >> One question though,
> >> >> How would management software discover typename of abstract class?
> >> >
> >> > It depends on the use case. On some cases, management may already
> >> > have bus-specific logic that will know what's the base type it
> >> > needs to query (e.g. it may query "pci-device" to find out if all
> >> > PCI devices support a given option). On other cases, it may be
> >> > discovered using other commands.
> >> 
> >> The stated purpose of this feature is to let management software "query
> >> for supported options that apply to all devices of a given type".  I
> >> suspect that when management software has a notion of "a given type", it
> >> knows its name.
> >> 
> >> Will management software go fishing for subtype relationships beyond the
> >> types it knows?  I doubt it.  Of course, management software developers
> >> are welcome to educate me :)
> >> 
> >> > For the CPU case, I will propose adding the base QOM CPU typename
> >> > in the query-target command.
> >> 
> >> Does this type name vary?  If yes, can you give examples?
> >
> > It does. x86-specific CPU properties are on the x86_64-cpu and
> > i386-cpu classes. arm-specific CPU properties are on the arm-cpu
> > class.
> 
> I see we have concrete CPUs (such as "Westmere-x86_64-cpu"), which are
> subtypes of an abstract CPU (such as "x86_64-cpu"), which is a subtype
> of "cpu", which is a subtype of "device", which is a subtype of
> "object".
> 
> The chain "cpu" - "device" - "object" is fixed and well-known.
> 
> The link from there to the concrete CPU varies.  Whether it could be
> considered well-known or not is debatable.
> 
> My true question is: should we have a special purpose interface to get
> the abstract supertype of concrete CPU types, or should be have general
> purpose means to introspect the subtype hierarchy?
> 
> Note that we have the latter already, although in a rather cumbersome
> form:
> 
>     { "execute": "qom-list-types",
>       "arguments": { "implements": T, "abstract": true } }
> 
> lists all subtypes of T.  You can filter out the concrete subtypes by
> subtracting the same query with "abstract": false.  Start with the
> type you're interested in, find all its abstract supertypes.  If you
> need to know more, repeat for the types you found.

Looks cumbersome, because I don't see a way to find all
supertypes of a given type without walking the whole tree
starting from "object" (is there one?). But it could be improved
a bit if we added a "implements" field to ObjectTypeInfo.

But, maybe we should take a step back: my original goal was to
let libvirt know which properties are supported by any CPU model
when using "-cpu". Maybe we should make QEMU do the QOM->option
translation and implement "-cpu" support in
query-command-line-options? We already do something similar with
"-machine".

> 
> >> >> Perhaps this patch should be part of some other series.
> >> >
> >> > This is a valid point. In this case, it depends on the approach
> >> > we want to take: do we want to provide a flexible interface for
> >> > management, let them find ways to make it useful and give us
> >> > feedback on what is lacking; or do we want to provide the new
> >> > interface only after we have specified the complete solution for
> >> > the problem?
> >> >
> >> > I don't know the answer. I will let the qdev/QOM/QMP maintainers
> >> > answer that.
> >> 
> >> I'm reluctant to add QMP features just because we think they might be
> >> useful to someone.  We should talk to users to confirm our hunch before
> >> we act on it.
> >> 
> >> That said, this one isn't exactly a biggie.
> >
> > Considering we are past soft freeze, I can document a more
> > concrete usage example when I submit the next version.
> 
> I recommend you get libvirt developers to buy into this feature first.

Sure. This series originated from a request by Jiri to let him
know which options are supported by "-cpu".

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties Eduardo Habkost
  2016-10-31 14:07   ` Igor Mammedov
@ 2016-11-07 12:45   ` Halil Pasic
  2016-11-07 13:05     ` Eduardo Habkost
  1 sibling, 1 reply; 50+ messages in thread
From: Halil Pasic @ 2016-11-07 12:45 UTC (permalink / raw)
  To: Eduardo Habkost, qemu-devel
  Cc: Igor Mammedov, Markus Armbruster, Andreas Färber



On 10/29/2016 03:48 AM, Eduardo Habkost wrote:
> When an abstract class is used on device-list-properties, we can
> simply return the class properties registered for the class.
> 
> This will be useful if management software needs to query for
> supported options that apply to all devices of a given type (e.g.
> options supported by all CPU models, options supported by all PCI
> devices).

This will question is slightly off topic (sorry about that) but it does
concern the feature you are trying to establish. 

I stumbled upon this while trying clean up qdev properties in
virtio-ccw. What I dislike is that there is a bunch of properties which
are conceptually inherited from ancestor classes (like devno from
CcwDevice) yet the qdev properties are independent at the moment (that
is each device declares the devno property for itself -- lots of code
duplication).

Now here comes the problem. The ioeventfd property is a property of the
transport (that is logically belonging to VirtioCcwDevice) and tells if
QEMU should use ioeventfd for notifiers. The trouble is this property is
not present for vhost devices since basically the ioeventfd is used by
the in host kernel vhost driver, so the degree of freedom is gone. By
the way, we have the same with virtio-pci and there the ioeventfd
property was simply left out of common virtio-pci properties regardless
of the properties memory backing (where the set writes to and get reads
from) sitting in that is the base class.

Now I think loosing a degree of freedom in the process of specialization
is not something outrageous, but I was unable to figure out how this is
to be modeled with your class based property approach. Can you help me
here?

With the old object anchored properties I was tempted to do something
like simply just removing the property form the object or overriding it
with a read only property but this would now break the semantic of
class properties. Of course having the data backing in the parent and
the property in the child does work but is IMHO kind of ugly.

Regards,
Halil


> 
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07 12:45   ` Halil Pasic
@ 2016-11-07 13:05     ` Eduardo Habkost
  2016-11-07 14:48       ` Halil Pasic
  0 siblings, 1 reply; 50+ messages in thread
From: Eduardo Habkost @ 2016-11-07 13:05 UTC (permalink / raw)
  To: Halil Pasic
  Cc: qemu-devel, Igor Mammedov, Markus Armbruster, Andreas Färber

On Mon, Nov 07, 2016 at 01:45:59PM +0100, Halil Pasic wrote:
> 
> 
> On 10/29/2016 03:48 AM, Eduardo Habkost wrote:
> > When an abstract class is used on device-list-properties, we can
> > simply return the class properties registered for the class.
> > 
> > This will be useful if management software needs to query for
> > supported options that apply to all devices of a given type (e.g.
> > options supported by all CPU models, options supported by all PCI
> > devices).
> 
> This will question is slightly off topic (sorry about that) but it does
> concern the feature you are trying to establish. 
> 
> I stumbled upon this while trying clean up qdev properties in
> virtio-ccw. What I dislike is that there is a bunch of properties which
> are conceptually inherited from ancestor classes (like devno from
> CcwDevice) yet the qdev properties are independent at the moment (that
> is each device declares the devno property for itself -- lots of code
> duplication).
> 
> Now here comes the problem. The ioeventfd property is a property of the
> transport (that is logically belonging to VirtioCcwDevice) and tells if
> QEMU should use ioeventfd for notifiers. The trouble is this property is
> not present for vhost devices since basically the ioeventfd is used by
> the in host kernel vhost driver, so the degree of freedom is gone. By
> the way, we have the same with virtio-pci and there the ioeventfd
> property was simply left out of common virtio-pci properties regardless
> of the properties memory backing (where the set writes to and get reads
> from) sitting in that is the base class.
> 
> Now I think loosing a degree of freedom in the process of specialization
> is not something outrageous, but I was unable to figure out how this is
> to be modeled with your class based property approach. Can you help me
> here?
> 
> With the old object anchored properties I was tempted to do something
> like simply just removing the property form the object or overriding it
> with a read only property but this would now break the semantic of
> class properties. Of course having the data backing in the parent and
> the property in the child does work but is IMHO kind of ugly.

If you want some subclasses to not have the property, then I
recommend not registering it as a class property on the base
class in the first place. I don't expect to see a mechanism to
allow subclasses to remove or override class properties from
parent classes.

You have many alternatives in this case: you could use instance
properties, or register it as class property only on some
subclasses (class_base_init could you help you do it on a single
place, instead of duplicating the property registration code on
subclasses).

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07 12:38             ` Eduardo Habkost
@ 2016-11-07 14:40               ` Markus Armbruster
  2016-11-07 17:11                 ` Eduardo Habkost
  0 siblings, 1 reply; 50+ messages in thread
From: Markus Armbruster @ 2016-11-07 14:40 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: libvir-list, Igor Mammedov, Jiri Denemark, qemu-devel,
	Andreas Färber

Eduardo Habkost <ehabkost@redhat.com> writes:

> On Mon, Nov 07, 2016 at 09:09:58AM +0100, Markus Armbruster wrote:
>> Eduardo Habkost <ehabkost@redhat.com> writes:
>> 
>> > On Fri, Nov 04, 2016 at 04:45:17PM +0100, Markus Armbruster wrote:
>> >> Eduardo Habkost <ehabkost@redhat.com> writes:
>> >> 
>> >> > (CCing libvirt people, as I forgot to CC them)
>> >> >
>> >> > On Mon, Oct 31, 2016 at 03:07:23PM +0100, Igor Mammedov wrote:
>> >> >> On Fri, 28 Oct 2016 23:48:06 -0200
>> >> >> Eduardo Habkost <ehabkost@redhat.com> wrote:
>> >> >> 
>> >> >> > When an abstract class is used on device-list-properties, we can
>> >> >> > simply return the class properties registered for the class.
>> >> >> > 
>> >> >> > This will be useful if management software needs to query for
>> >> >> > supported options that apply to all devices of a given type (e.g.
>> >> >> > options supported by all CPU models, options supported by all PCI
>> >> >> > devices).
>> >> >> Patch looks fine to me but I'm not qmp interface guru
>> >> >> so I'd leave review up to maintainers.
>> >> >> 
>> >> >> One question though,
>> >> >> How would management software discover typename of abstract class?
>> >> >
>> >> > It depends on the use case. On some cases, management may already
>> >> > have bus-specific logic that will know what's the base type it
>> >> > needs to query (e.g. it may query "pci-device" to find out if all
>> >> > PCI devices support a given option). On other cases, it may be
>> >> > discovered using other commands.
>> >> 
>> >> The stated purpose of this feature is to let management software "query
>> >> for supported options that apply to all devices of a given type".  I
>> >> suspect that when management software has a notion of "a given type", it
>> >> knows its name.
>> >> 
>> >> Will management software go fishing for subtype relationships beyond the
>> >> types it knows?  I doubt it.  Of course, management software developers
>> >> are welcome to educate me :)
>> >> 
>> >> > For the CPU case, I will propose adding the base QOM CPU typename
>> >> > in the query-target command.
>> >> 
>> >> Does this type name vary?  If yes, can you give examples?
>> >
>> > It does. x86-specific CPU properties are on the x86_64-cpu and
>> > i386-cpu classes. arm-specific CPU properties are on the arm-cpu
>> > class.
>> 
>> I see we have concrete CPUs (such as "Westmere-x86_64-cpu"), which are
>> subtypes of an abstract CPU (such as "x86_64-cpu"), which is a subtype
>> of "cpu", which is a subtype of "device", which is a subtype of
>> "object".
>> 
>> The chain "cpu" - "device" - "object" is fixed and well-known.
>> 
>> The link from there to the concrete CPU varies.  Whether it could be
>> considered well-known or not is debatable.
>> 
>> My true question is: should we have a special purpose interface to get
>> the abstract supertype of concrete CPU types, or should be have general
>> purpose means to introspect the subtype hierarchy?
>> 
>> Note that we have the latter already, although in a rather cumbersome
>> form:
>> 
>>     { "execute": "qom-list-types",
>>       "arguments": { "implements": T, "abstract": true } }
>> 
>> lists all subtypes of T.  You can filter out the concrete subtypes by
>> subtracting the same query with "abstract": false.  Start with the
>> type you're interested in, find all its abstract supertypes.  If you
>> need to know more, repeat for the types you found.
>
> Looks cumbersome, because I don't see a way to find all
> supertypes of a given type without walking the whole tree
> starting from "object" (is there one?). But it could be improved
> a bit if we added a "implements" field to ObjectTypeInfo.

My point is: we can skip discussing whether we should expose the subtype
relation, because we already do.

> But, maybe we should take a step back: my original goal was to
> let libvirt know which properties are supported by any CPU model
> when using "-cpu".

Why is that useful?

>                    Maybe we should make QEMU do the QOM->option
> translation and implement "-cpu" support in
> query-command-line-options? We already do something similar with
> "-machine".

query-command-line-options is flawed, and the less it's used, the
happier I am.

Real command line introspection would be nice, but getting it will
involve cleaning up the unholy mess our command line has become.  Don't
hold your breath.

My preferred workaround is to find something equivalent to introspect
via QMP.

That said, if you come up with a patch that solves a real problem now, I
won't object to it just because it involves query-command-line-options.

[...]

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07 13:05     ` Eduardo Habkost
@ 2016-11-07 14:48       ` Halil Pasic
  2016-11-07 15:01         ` Daniel P. Berrange
  0 siblings, 1 reply; 50+ messages in thread
From: Halil Pasic @ 2016-11-07 14:48 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: qemu-devel, Igor Mammedov, Markus Armbruster, Andreas Färber

[-- Attachment #1: Type: text/plain, Size: 1808 bytes --]



On 11/07/2016 02:05 PM, Eduardo Habkost wrote:
> If you want some subclasses to not have the property, then I
> recommend not registering it as a class property on the base
> class in the first place. I don't expect to see a mechanism to
> allow subclasses to remove or override class properties from
> parent classes.
> 

Thank you very much for your reply.

I understand, yet I see potential problems. The example with ioeventfd
and vhost in virtio-pci is a good one also because  the first there was
the ioeventfd property with commit 653ced07 and then the vhost case came
along with commit 50787628ee3 (ok ioeventfd is not there for some non
vhost virtio-pci devices for reasons I do not understand).

To rephrase this in generic context a specialization for which a
property does not make sense might come along after the property at the
base class was established.

Now AFAIU properties are external API, so having to make a compatibility
breaking change there might not be fun. Does this mean one should be
very careful to put only use class level properties on abstract classes
where its certain that the property always makes sense including it's
access control?

If yes, how does this relate to patch 5 "Register static properties as
class properties" where the object level properties are converted to
class level properties?

> You have many alternatives in this case: you could use instance
> properties

What are inheritance properties? Sorry I'm not quite that deep
yet to know myself.

> , or register it as class property only on some
> subclasses (class_base_init could you help you do it on a single
> place, instead of duplicating the property registration code on
> subclasses).

Thanks again, and sorry if I'm a bother.

Cheers,
Halil


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07 14:48       ` Halil Pasic
@ 2016-11-07 15:01         ` Daniel P. Berrange
  2016-11-07 15:51           ` Markus Armbruster
  0 siblings, 1 reply; 50+ messages in thread
From: Daniel P. Berrange @ 2016-11-07 15:01 UTC (permalink / raw)
  To: Halil Pasic
  Cc: Eduardo Habkost, Igor Mammedov, qemu-devel, Andreas Färber,
	Markus Armbruster

On Mon, Nov 07, 2016 at 03:48:49PM +0100, Halil Pasic wrote:
> 
> 
> On 11/07/2016 02:05 PM, Eduardo Habkost wrote:
> > If you want some subclasses to not have the property, then I
> > recommend not registering it as a class property on the base
> > class in the first place. I don't expect to see a mechanism to
> > allow subclasses to remove or override class properties from
> > parent classes.
> > 
> 
> Thank you very much for your reply.
> 
> I understand, yet I see potential problems. The example with ioeventfd
> and vhost in virtio-pci is a good one also because  the first there was
> the ioeventfd property with commit 653ced07 and then the vhost case came
> along with commit 50787628ee3 (ok ioeventfd is not there for some non
> vhost virtio-pci devices for reasons I do not understand).
> 
> To rephrase this in generic context a specialization for which a
> property does not make sense might come along after the property at the
> base class was established.
> 
> Now AFAIU properties are external API, so having to make a compatibility
> breaking change there might not be fun. Does this mean one should be
> very careful to put only use class level properties on abstract classes
> where its certain that the property always makes sense including it's
> access control?

This could be an argument for *NOT* allowing introspectiing of properties
against abstract parent classes. If you only ever allow introspecting against
leaf node non-abstract classes, then QEMU retains the freedom to move props
from a base class down to an leaf class without risk of breaking mgmt apps.

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://entangle-photo.org       -o-    http://search.cpan.org/~danberr/ :|

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07 15:01         ` Daniel P. Berrange
@ 2016-11-07 15:51           ` Markus Armbruster
  2016-11-07 17:27             ` Eduardo Habkost
  0 siblings, 1 reply; 50+ messages in thread
From: Markus Armbruster @ 2016-11-07 15:51 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Halil Pasic, Igor Mammedov, Eduardo Habkost, Andreas Färber,
	qemu-devel

"Daniel P. Berrange" <berrange@redhat.com> writes:

> On Mon, Nov 07, 2016 at 03:48:49PM +0100, Halil Pasic wrote:
>> 
>> 
>> On 11/07/2016 02:05 PM, Eduardo Habkost wrote:
>> > If you want some subclasses to not have the property, then I
>> > recommend not registering it as a class property on the base
>> > class in the first place. I don't expect to see a mechanism to
>> > allow subclasses to remove or override class properties from
>> > parent classes.
>> > 
>> 
>> Thank you very much for your reply.
>> 
>> I understand, yet I see potential problems. The example with ioeventfd
>> and vhost in virtio-pci is a good one also because  the first there was
>> the ioeventfd property with commit 653ced07 and then the vhost case came
>> along with commit 50787628ee3 (ok ioeventfd is not there for some non
>> vhost virtio-pci devices for reasons I do not understand).
>> 
>> To rephrase this in generic context a specialization for which a
>> property does not make sense might come along after the property at the
>> base class was established.
>> 
>> Now AFAIU properties are external API, so having to make a compatibility
>> breaking change there might not be fun. Does this mean one should be
>> very careful to put only use class level properties on abstract classes
>> where its certain that the property always makes sense including it's
>> access control?
>
> This could be an argument for *NOT* allowing introspectiing of properties
> against abstract parent classes. If you only ever allow introspecting against
> leaf node non-abstract classes, then QEMU retains the freedom to move props
> from a base class down to an leaf class without risk of breaking mgmt apps.

That's a really good point.  To generalize it a bit, introspection of
actual interfaces is fine, but permitting introspection of how they are
made can add artificial constraints.

Introspecting the subtype relation is already problematic in this view.

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07 14:40               ` Markus Armbruster
@ 2016-11-07 17:11                 ` Eduardo Habkost
  2016-11-08  7:29                   ` Markus Armbruster
  0 siblings, 1 reply; 50+ messages in thread
From: Eduardo Habkost @ 2016-11-07 17:11 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: libvir-list, Igor Mammedov, Jiri Denemark, qemu-devel,
	Andreas Färber

On Mon, Nov 07, 2016 at 03:40:57PM +0100, Markus Armbruster wrote:
> Eduardo Habkost <ehabkost@redhat.com> writes:
> 
> > On Mon, Nov 07, 2016 at 09:09:58AM +0100, Markus Armbruster wrote:
> >> Eduardo Habkost <ehabkost@redhat.com> writes:
> >> 
> >> > On Fri, Nov 04, 2016 at 04:45:17PM +0100, Markus Armbruster wrote:
> >> >> Eduardo Habkost <ehabkost@redhat.com> writes:
> >> >> 
> >> >> > (CCing libvirt people, as I forgot to CC them)
> >> >> >
> >> >> > On Mon, Oct 31, 2016 at 03:07:23PM +0100, Igor Mammedov wrote:
> >> >> >> On Fri, 28 Oct 2016 23:48:06 -0200
> >> >> >> Eduardo Habkost <ehabkost@redhat.com> wrote:
> >> >> >> 
> >> >> >> > When an abstract class is used on device-list-properties, we can
> >> >> >> > simply return the class properties registered for the class.
> >> >> >> > 
> >> >> >> > This will be useful if management software needs to query for
> >> >> >> > supported options that apply to all devices of a given type (e.g.
> >> >> >> > options supported by all CPU models, options supported by all PCI
> >> >> >> > devices).
> >> >> >> Patch looks fine to me but I'm not qmp interface guru
> >> >> >> so I'd leave review up to maintainers.
> >> >> >> 
> >> >> >> One question though,
> >> >> >> How would management software discover typename of abstract class?
> >> >> >
> >> >> > It depends on the use case. On some cases, management may already
> >> >> > have bus-specific logic that will know what's the base type it
> >> >> > needs to query (e.g. it may query "pci-device" to find out if all
> >> >> > PCI devices support a given option). On other cases, it may be
> >> >> > discovered using other commands.
> >> >> 
> >> >> The stated purpose of this feature is to let management software "query
> >> >> for supported options that apply to all devices of a given type".  I
> >> >> suspect that when management software has a notion of "a given type", it
> >> >> knows its name.
> >> >> 
> >> >> Will management software go fishing for subtype relationships beyond the
> >> >> types it knows?  I doubt it.  Of course, management software developers
> >> >> are welcome to educate me :)
> >> >> 
> >> >> > For the CPU case, I will propose adding the base QOM CPU typename
> >> >> > in the query-target command.
> >> >> 
> >> >> Does this type name vary?  If yes, can you give examples?
> >> >
> >> > It does. x86-specific CPU properties are on the x86_64-cpu and
> >> > i386-cpu classes. arm-specific CPU properties are on the arm-cpu
> >> > class.
> >> 
> >> I see we have concrete CPUs (such as "Westmere-x86_64-cpu"), which are
> >> subtypes of an abstract CPU (such as "x86_64-cpu"), which is a subtype
> >> of "cpu", which is a subtype of "device", which is a subtype of
> >> "object".
> >> 
> >> The chain "cpu" - "device" - "object" is fixed and well-known.
> >> 
> >> The link from there to the concrete CPU varies.  Whether it could be
> >> considered well-known or not is debatable.
> >> 
> >> My true question is: should we have a special purpose interface to get
> >> the abstract supertype of concrete CPU types, or should be have general
> >> purpose means to introspect the subtype hierarchy?
> >> 
> >> Note that we have the latter already, although in a rather cumbersome
> >> form:
> >> 
> >>     { "execute": "qom-list-types",
> >>       "arguments": { "implements": T, "abstract": true } }
> >> 
> >> lists all subtypes of T.  You can filter out the concrete subtypes by
> >> subtracting the same query with "abstract": false.  Start with the
> >> type you're interested in, find all its abstract supertypes.  If you
> >> need to know more, repeat for the types you found.
> >
> > Looks cumbersome, because I don't see a way to find all
> > supertypes of a given type without walking the whole tree
> > starting from "object" (is there one?). But it could be improved
> > a bit if we added a "implements" field to ObjectTypeInfo.
> 
> My point is: we can skip discussing whether we should expose the subtype
> relation, because we already do.

Correct. My only problem is that it seems to add extra
assumptions to the code (e.g. that there's only one abstract CPU
type). But if libvirt is careful, it doesn't need to make any
assumptions: it can explore the type hierarchy and confirm that
the assumptions are correct.

> 
> > But, maybe we should take a step back: my original goal was to
> > let libvirt know which properties are supported by any CPU model
> > when using "-cpu".
> 
> Why is that useful?

libvirt wants to know if the QEMU binary supports a given -cpu
option (normally CPU features that can be enabled/disabled using
"+foo"/"-foo").

> 
> >                    Maybe we should make QEMU do the QOM->option
> > translation and implement "-cpu" support in
> > query-command-line-options? We already do something similar with
> > "-machine".
> 
> query-command-line-options is flawed, and the less it's used, the
> happier I am.

No problem, let's just forget my suggestion.  :)

> 
> Real command line introspection would be nice, but getting it will
> involve cleaning up the unholy mess our command line has become.  Don't
> hold your breath.
> 
> My preferred workaround is to find something equivalent to introspect
> via QMP.

Sounds good to me.

> 
> That said, if you come up with a patch that solves a real problem now, I
> won't object to it just because it involves query-command-line-options.

I think I will keep the current approach. Changing
query-command-line-option would probably be more complex and
solve only the -cpu problem. Making QOM introspection better
looks simpler and will probably be useful for other use cases.

I am still tempted to try to make QOM->query-command-line-option
mapping easier and simpler, but it doesn't seem to be the answer
to the current problem.

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07 15:51           ` Markus Armbruster
@ 2016-11-07 17:27             ` Eduardo Habkost
  2016-11-07 17:41               ` Daniel P. Berrange
  0 siblings, 1 reply; 50+ messages in thread
From: Eduardo Habkost @ 2016-11-07 17:27 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Daniel P. Berrange, Halil Pasic, Igor Mammedov,
	Andreas Färber, qemu-devel

On Mon, Nov 07, 2016 at 04:51:57PM +0100, Markus Armbruster wrote:
> "Daniel P. Berrange" <berrange@redhat.com> writes:
> 
> > On Mon, Nov 07, 2016 at 03:48:49PM +0100, Halil Pasic wrote:
> >> 
> >> 
> >> On 11/07/2016 02:05 PM, Eduardo Habkost wrote:
> >> > If you want some subclasses to not have the property, then I
> >> > recommend not registering it as a class property on the base
> >> > class in the first place. I don't expect to see a mechanism to
> >> > allow subclasses to remove or override class properties from
> >> > parent classes.
> >> > 
> >> 
> >> Thank you very much for your reply.
> >> 
> >> I understand, yet I see potential problems. The example with ioeventfd
> >> and vhost in virtio-pci is a good one also because  the first there was
> >> the ioeventfd property with commit 653ced07 and then the vhost case came
> >> along with commit 50787628ee3 (ok ioeventfd is not there for some non
> >> vhost virtio-pci devices for reasons I do not understand).
> >> 
> >> To rephrase this in generic context a specialization for which a
> >> property does not make sense might come along after the property at the
> >> base class was established.
> >> 
> >> Now AFAIU properties are external API, so having to make a compatibility
> >> breaking change there might not be fun. Does this mean one should be
> >> very careful to put only use class level properties on abstract classes
> >> where its certain that the property always makes sense including it's
> >> access control?
> >
> > This could be an argument for *NOT* allowing introspectiing of properties
> > against abstract parent classes. If you only ever allow introspecting against
> > leaf node non-abstract classes, then QEMU retains the freedom to move props
> > from a base class down to an leaf class without risk of breaking mgmt apps.
> 
> That's a really good point.  To generalize it a bit, introspection of
> actual interfaces is fine, but permitting introspection of how they are
> made can add artificial constraints.
> 
> Introspecting the subtype relation is already problematic in this view.

Yes, that's a very good point. But note that that this means
making things more complex for libvirt.

In the case of -cpu, if we don't expose (or allow libvirt to
making assumptions about) subtype relations, the only way libvirt
can conclude that "+foo can be used as -cpu option with any CPU
model", is to query each and every CPU model type, and see if all
of them support the "foo" property.

It's a trade-off between an interface that's more complex to use
and having less freedom to change the class hierarchy.
Personally, I don't mind going either way, if we have a good
reason for that.

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07 17:27             ` Eduardo Habkost
@ 2016-11-07 17:41               ` Daniel P. Berrange
  2016-11-07 18:03                 ` Eduardo Habkost
  0 siblings, 1 reply; 50+ messages in thread
From: Daniel P. Berrange @ 2016-11-07 17:41 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Markus Armbruster, Halil Pasic, Igor Mammedov,
	Andreas Färber, qemu-devel

On Mon, Nov 07, 2016 at 03:27:31PM -0200, Eduardo Habkost wrote:
> On Mon, Nov 07, 2016 at 04:51:57PM +0100, Markus Armbruster wrote:
> > "Daniel P. Berrange" <berrange@redhat.com> writes:
> > 
> > > On Mon, Nov 07, 2016 at 03:48:49PM +0100, Halil Pasic wrote:
> > >> 
> > >> 
> > >> On 11/07/2016 02:05 PM, Eduardo Habkost wrote:
> > >> > If you want some subclasses to not have the property, then I
> > >> > recommend not registering it as a class property on the base
> > >> > class in the first place. I don't expect to see a mechanism to
> > >> > allow subclasses to remove or override class properties from
> > >> > parent classes.
> > >> > 
> > >> 
> > >> Thank you very much for your reply.
> > >> 
> > >> I understand, yet I see potential problems. The example with ioeventfd
> > >> and vhost in virtio-pci is a good one also because  the first there was
> > >> the ioeventfd property with commit 653ced07 and then the vhost case came
> > >> along with commit 50787628ee3 (ok ioeventfd is not there for some non
> > >> vhost virtio-pci devices for reasons I do not understand).
> > >> 
> > >> To rephrase this in generic context a specialization for which a
> > >> property does not make sense might come along after the property at the
> > >> base class was established.
> > >> 
> > >> Now AFAIU properties are external API, so having to make a compatibility
> > >> breaking change there might not be fun. Does this mean one should be
> > >> very careful to put only use class level properties on abstract classes
> > >> where its certain that the property always makes sense including it's
> > >> access control?
> > >
> > > This could be an argument for *NOT* allowing introspectiing of properties
> > > against abstract parent classes. If you only ever allow introspecting against
> > > leaf node non-abstract classes, then QEMU retains the freedom to move props
> > > from a base class down to an leaf class without risk of breaking mgmt apps.
> > 
> > That's a really good point.  To generalize it a bit, introspection of
> > actual interfaces is fine, but permitting introspection of how they are
> > made can add artificial constraints.
> > 
> > Introspecting the subtype relation is already problematic in this view.
> 
> Yes, that's a very good point. But note that that this means
> making things more complex for libvirt.
> 
> In the case of -cpu, if we don't expose (or allow libvirt to
> making assumptions about) subtype relations, the only way libvirt
> can conclude that "+foo can be used as -cpu option with any CPU
> model", is to query each and every CPU model type, and see if all
> of them support the "foo" property.
>
> It's a trade-off between an interface that's more complex to use
> and having less freedom to change the class hierarchy.
> Personally, I don't mind going either way, if we have a good
> reason for that.

Or could do a tradeoff where we allow introspection of abstract
parent classes, but explicitly document that we reserve the right
to move properties to leaf nodes ?


Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://entangle-photo.org       -o-    http://search.cpan.org/~danberr/ :|

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07 17:41               ` Daniel P. Berrange
@ 2016-11-07 18:03                 ` Eduardo Habkost
  2016-11-07 18:08                   ` Daniel P. Berrange
  0 siblings, 1 reply; 50+ messages in thread
From: Eduardo Habkost @ 2016-11-07 18:03 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Markus Armbruster, Halil Pasic, Igor Mammedov,
	Andreas Färber, qemu-devel

On Mon, Nov 07, 2016 at 05:41:01PM +0000, Daniel P. Berrange wrote:
> On Mon, Nov 07, 2016 at 03:27:31PM -0200, Eduardo Habkost wrote:
> > On Mon, Nov 07, 2016 at 04:51:57PM +0100, Markus Armbruster wrote:
> > > "Daniel P. Berrange" <berrange@redhat.com> writes:
> > > 
> > > > On Mon, Nov 07, 2016 at 03:48:49PM +0100, Halil Pasic wrote:
> > > >> 
> > > >> 
> > > >> On 11/07/2016 02:05 PM, Eduardo Habkost wrote:
> > > >> > If you want some subclasses to not have the property, then I
> > > >> > recommend not registering it as a class property on the base
> > > >> > class in the first place. I don't expect to see a mechanism to
> > > >> > allow subclasses to remove or override class properties from
> > > >> > parent classes.
> > > >> > 
> > > >> 
> > > >> Thank you very much for your reply.
> > > >> 
> > > >> I understand, yet I see potential problems. The example with ioeventfd
> > > >> and vhost in virtio-pci is a good one also because  the first there was
> > > >> the ioeventfd property with commit 653ced07 and then the vhost case came
> > > >> along with commit 50787628ee3 (ok ioeventfd is not there for some non
> > > >> vhost virtio-pci devices for reasons I do not understand).
> > > >> 
> > > >> To rephrase this in generic context a specialization for which a
> > > >> property does not make sense might come along after the property at the
> > > >> base class was established.
> > > >> 
> > > >> Now AFAIU properties are external API, so having to make a compatibility
> > > >> breaking change there might not be fun. Does this mean one should be
> > > >> very careful to put only use class level properties on abstract classes
> > > >> where its certain that the property always makes sense including it's
> > > >> access control?
> > > >
> > > > This could be an argument for *NOT* allowing introspectiing of properties
> > > > against abstract parent classes. If you only ever allow introspecting against
> > > > leaf node non-abstract classes, then QEMU retains the freedom to move props
> > > > from a base class down to an leaf class without risk of breaking mgmt apps.
> > > 
> > > That's a really good point.  To generalize it a bit, introspection of
> > > actual interfaces is fine, but permitting introspection of how they are
> > > made can add artificial constraints.
> > > 
> > > Introspecting the subtype relation is already problematic in this view.
> > 
> > Yes, that's a very good point. But note that that this means
> > making things more complex for libvirt.
> > 
> > In the case of -cpu, if we don't expose (or allow libvirt to
> > making assumptions about) subtype relations, the only way libvirt
> > can conclude that "+foo can be used as -cpu option with any CPU
> > model", is to query each and every CPU model type, and see if all
> > of them support the "foo" property.
> >
> > It's a trade-off between an interface that's more complex to use
> > and having less freedom to change the class hierarchy.
> > Personally, I don't mind going either way, if we have a good
> > reason for that.
> 
> Or could do a tradeoff where we allow introspection of abstract
> parent classes, but explicitly document that we reserve the right
> to move properties to leaf nodes ?

Reserving the right to move properties to leaf nodes would be
welcome. But it would force libvirt to query all leaf nodes if it
wants to be sure the option is really unsupported by the QEMU
binary, so why would libvirt query the parent class in the first
place?

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07 18:03                 ` Eduardo Habkost
@ 2016-11-07 18:08                   ` Daniel P. Berrange
  2016-11-07 18:28                     ` Eduardo Habkost
  0 siblings, 1 reply; 50+ messages in thread
From: Daniel P. Berrange @ 2016-11-07 18:08 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Markus Armbruster, Halil Pasic, Igor Mammedov,
	Andreas Färber, qemu-devel

On Mon, Nov 07, 2016 at 04:03:58PM -0200, Eduardo Habkost wrote:
> On Mon, Nov 07, 2016 at 05:41:01PM +0000, Daniel P. Berrange wrote:
> > On Mon, Nov 07, 2016 at 03:27:31PM -0200, Eduardo Habkost wrote:
> > > On Mon, Nov 07, 2016 at 04:51:57PM +0100, Markus Armbruster wrote:
> > > > "Daniel P. Berrange" <berrange@redhat.com> writes:
> > > > 
> > > > > On Mon, Nov 07, 2016 at 03:48:49PM +0100, Halil Pasic wrote:
> > > > >> 
> > > > >> 
> > > > >> On 11/07/2016 02:05 PM, Eduardo Habkost wrote:
> > > > >> > If you want some subclasses to not have the property, then I
> > > > >> > recommend not registering it as a class property on the base
> > > > >> > class in the first place. I don't expect to see a mechanism to
> > > > >> > allow subclasses to remove or override class properties from
> > > > >> > parent classes.
> > > > >> > 
> > > > >> 
> > > > >> Thank you very much for your reply.
> > > > >> 
> > > > >> I understand, yet I see potential problems. The example with ioeventfd
> > > > >> and vhost in virtio-pci is a good one also because  the first there was
> > > > >> the ioeventfd property with commit 653ced07 and then the vhost case came
> > > > >> along with commit 50787628ee3 (ok ioeventfd is not there for some non
> > > > >> vhost virtio-pci devices for reasons I do not understand).
> > > > >> 
> > > > >> To rephrase this in generic context a specialization for which a
> > > > >> property does not make sense might come along after the property at the
> > > > >> base class was established.
> > > > >> 
> > > > >> Now AFAIU properties are external API, so having to make a compatibility
> > > > >> breaking change there might not be fun. Does this mean one should be
> > > > >> very careful to put only use class level properties on abstract classes
> > > > >> where its certain that the property always makes sense including it's
> > > > >> access control?
> > > > >
> > > > > This could be an argument for *NOT* allowing introspectiing of properties
> > > > > against abstract parent classes. If you only ever allow introspecting against
> > > > > leaf node non-abstract classes, then QEMU retains the freedom to move props
> > > > > from a base class down to an leaf class without risk of breaking mgmt apps.
> > > > 
> > > > That's a really good point.  To generalize it a bit, introspection of
> > > > actual interfaces is fine, but permitting introspection of how they are
> > > > made can add artificial constraints.
> > > > 
> > > > Introspecting the subtype relation is already problematic in this view.
> > > 
> > > Yes, that's a very good point. But note that that this means
> > > making things more complex for libvirt.
> > > 
> > > In the case of -cpu, if we don't expose (or allow libvirt to
> > > making assumptions about) subtype relations, the only way libvirt
> > > can conclude that "+foo can be used as -cpu option with any CPU
> > > model", is to query each and every CPU model type, and see if all
> > > of them support the "foo" property.
> > >
> > > It's a trade-off between an interface that's more complex to use
> > > and having less freedom to change the class hierarchy.
> > > Personally, I don't mind going either way, if we have a good
> > > reason for that.
> > 
> > Or could do a tradeoff where we allow introspection of abstract
> > parent classes, but explicitly document that we reserve the right
> > to move properties to leaf nodes ?
> 
> Reserving the right to move properties to leaf nodes would be
> welcome. But it would force libvirt to query all leaf nodes if it
> wants to be sure the option is really unsupported by the QEMU
> binary, so why would libvirt query the parent class in the first
> place?

The introspection API is quite general purpose so its semantics have to
be suitable for all types of object, but some types of object may not need
the full degree of flexibility. So what I meant was that while we want
to be able to move props down to leaf classes for objects in general,
we could perhaps assume that this will never happen for CPU model objects.

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://entangle-photo.org       -o-    http://search.cpan.org/~danberr/ :|

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07 18:08                   ` Daniel P. Berrange
@ 2016-11-07 18:28                     ` Eduardo Habkost
  2016-11-08  7:37                       ` Markus Armbruster
  0 siblings, 1 reply; 50+ messages in thread
From: Eduardo Habkost @ 2016-11-07 18:28 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Markus Armbruster, Halil Pasic, Igor Mammedov,
	Andreas Färber, qemu-devel

On Mon, Nov 07, 2016 at 06:08:42PM +0000, Daniel P. Berrange wrote:
> On Mon, Nov 07, 2016 at 04:03:58PM -0200, Eduardo Habkost wrote:
> > On Mon, Nov 07, 2016 at 05:41:01PM +0000, Daniel P. Berrange wrote:
> > > On Mon, Nov 07, 2016 at 03:27:31PM -0200, Eduardo Habkost wrote:
> > > > On Mon, Nov 07, 2016 at 04:51:57PM +0100, Markus Armbruster wrote:
> > > > > "Daniel P. Berrange" <berrange@redhat.com> writes:
> > > > > 
> > > > > > On Mon, Nov 07, 2016 at 03:48:49PM +0100, Halil Pasic wrote:
> > > > > >> 
> > > > > >> 
> > > > > >> On 11/07/2016 02:05 PM, Eduardo Habkost wrote:
> > > > > >> > If you want some subclasses to not have the property, then I
> > > > > >> > recommend not registering it as a class property on the base
> > > > > >> > class in the first place. I don't expect to see a mechanism to
> > > > > >> > allow subclasses to remove or override class properties from
> > > > > >> > parent classes.
> > > > > >> > 
> > > > > >> 
> > > > > >> Thank you very much for your reply.
> > > > > >> 
> > > > > >> I understand, yet I see potential problems. The example with ioeventfd
> > > > > >> and vhost in virtio-pci is a good one also because  the first there was
> > > > > >> the ioeventfd property with commit 653ced07 and then the vhost case came
> > > > > >> along with commit 50787628ee3 (ok ioeventfd is not there for some non
> > > > > >> vhost virtio-pci devices for reasons I do not understand).
> > > > > >> 
> > > > > >> To rephrase this in generic context a specialization for which a
> > > > > >> property does not make sense might come along after the property at the
> > > > > >> base class was established.
> > > > > >> 
> > > > > >> Now AFAIU properties are external API, so having to make a compatibility
> > > > > >> breaking change there might not be fun. Does this mean one should be
> > > > > >> very careful to put only use class level properties on abstract classes
> > > > > >> where its certain that the property always makes sense including it's
> > > > > >> access control?
> > > > > >
> > > > > > This could be an argument for *NOT* allowing introspectiing of properties
> > > > > > against abstract parent classes. If you only ever allow introspecting against
> > > > > > leaf node non-abstract classes, then QEMU retains the freedom to move props
> > > > > > from a base class down to an leaf class without risk of breaking mgmt apps.
> > > > > 
> > > > > That's a really good point.  To generalize it a bit, introspection of
> > > > > actual interfaces is fine, but permitting introspection of how they are
> > > > > made can add artificial constraints.
> > > > > 
> > > > > Introspecting the subtype relation is already problematic in this view.
> > > > 
> > > > Yes, that's a very good point. But note that that this means
> > > > making things more complex for libvirt.
> > > > 
> > > > In the case of -cpu, if we don't expose (or allow libvirt to
> > > > making assumptions about) subtype relations, the only way libvirt
> > > > can conclude that "+foo can be used as -cpu option with any CPU
> > > > model", is to query each and every CPU model type, and see if all
> > > > of them support the "foo" property.
> > > >
> > > > It's a trade-off between an interface that's more complex to use
> > > > and having less freedom to change the class hierarchy.
> > > > Personally, I don't mind going either way, if we have a good
> > > > reason for that.
> > > 
> > > Or could do a tradeoff where we allow introspection of abstract
> > > parent classes, but explicitly document that we reserve the right
> > > to move properties to leaf nodes ?
> > 
> > Reserving the right to move properties to leaf nodes would be
> > welcome. But it would force libvirt to query all leaf nodes if it
> > wants to be sure the option is really unsupported by the QEMU
> > binary, so why would libvirt query the parent class in the first
> > place?
> 
> The introspection API is quite general purpose so its semantics have to
> be suitable for all types of object, but some types of object may not need
> the full degree of flexibility. So what I meant was that while we want
> to be able to move props down to leaf classes for objects in general,
> we could perhaps assume that this will never happen for CPU model objects.

This would work for me. I only worry that any code that makes the
wrong assumptions (on either QEMU or libvirt) would easily go
unnoticed until we try to change the class hierarchy and it
breaks something.

Markus, what do you think?

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07 17:11                 ` Eduardo Habkost
@ 2016-11-08  7:29                   ` Markus Armbruster
  2016-11-11 12:17                     ` Jiri Denemark
  0 siblings, 1 reply; 50+ messages in thread
From: Markus Armbruster @ 2016-11-08  7:29 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: libvir-list, Igor Mammedov, Jiri Denemark, qemu-devel,
	Andreas Färber

Eduardo Habkost <ehabkost@redhat.com> writes:

> On Mon, Nov 07, 2016 at 03:40:57PM +0100, Markus Armbruster wrote:
>> Eduardo Habkost <ehabkost@redhat.com> writes:
>> 
>> > On Mon, Nov 07, 2016 at 09:09:58AM +0100, Markus Armbruster wrote:
>> >> Eduardo Habkost <ehabkost@redhat.com> writes:
>> >> 
>> >> > On Fri, Nov 04, 2016 at 04:45:17PM +0100, Markus Armbruster wrote:
>> >> >> Eduardo Habkost <ehabkost@redhat.com> writes:
>> >> >> 
>> >> >> > (CCing libvirt people, as I forgot to CC them)
>> >> >> >
>> >> >> > On Mon, Oct 31, 2016 at 03:07:23PM +0100, Igor Mammedov wrote:
>> >> >> >> On Fri, 28 Oct 2016 23:48:06 -0200
>> >> >> >> Eduardo Habkost <ehabkost@redhat.com> wrote:
>> >> >> >> 
>> >> >> >> > When an abstract class is used on device-list-properties, we can
>> >> >> >> > simply return the class properties registered for the class.
>> >> >> >> > 
>> >> >> >> > This will be useful if management software needs to query for
>> >> >> >> > supported options that apply to all devices of a given type (e.g.
>> >> >> >> > options supported by all CPU models, options supported by all PCI
>> >> >> >> > devices).
>> >> >> >> Patch looks fine to me but I'm not qmp interface guru
>> >> >> >> so I'd leave review up to maintainers.
>> >> >> >> 
>> >> >> >> One question though,
>> >> >> >> How would management software discover typename of abstract class?
>> >> >> >
>> >> >> > It depends on the use case. On some cases, management may already
>> >> >> > have bus-specific logic that will know what's the base type it
>> >> >> > needs to query (e.g. it may query "pci-device" to find out if all
>> >> >> > PCI devices support a given option). On other cases, it may be
>> >> >> > discovered using other commands.
>> >> >> 
>> >> >> The stated purpose of this feature is to let management software "query
>> >> >> for supported options that apply to all devices of a given type".  I
>> >> >> suspect that when management software has a notion of "a given type", it
>> >> >> knows its name.
>> >> >> 
>> >> >> Will management software go fishing for subtype relationships beyond the
>> >> >> types it knows?  I doubt it.  Of course, management software developers
>> >> >> are welcome to educate me :)
>> >> >> 
>> >> >> > For the CPU case, I will propose adding the base QOM CPU typename
>> >> >> > in the query-target command.
>> >> >> 
>> >> >> Does this type name vary?  If yes, can you give examples?
>> >> >
>> >> > It does. x86-specific CPU properties are on the x86_64-cpu and
>> >> > i386-cpu classes. arm-specific CPU properties are on the arm-cpu
>> >> > class.
>> >> 
>> >> I see we have concrete CPUs (such as "Westmere-x86_64-cpu"), which are
>> >> subtypes of an abstract CPU (such as "x86_64-cpu"), which is a subtype
>> >> of "cpu", which is a subtype of "device", which is a subtype of
>> >> "object".
>> >> 
>> >> The chain "cpu" - "device" - "object" is fixed and well-known.
>> >> 
>> >> The link from there to the concrete CPU varies.  Whether it could be
>> >> considered well-known or not is debatable.
>> >> 
>> >> My true question is: should we have a special purpose interface to get
>> >> the abstract supertype of concrete CPU types, or should be have general
>> >> purpose means to introspect the subtype hierarchy?
>> >> 
>> >> Note that we have the latter already, although in a rather cumbersome
>> >> form:
>> >> 
>> >>     { "execute": "qom-list-types",
>> >>       "arguments": { "implements": T, "abstract": true } }
>> >> 
>> >> lists all subtypes of T.  You can filter out the concrete subtypes by
>> >> subtracting the same query with "abstract": false.  Start with the
>> >> type you're interested in, find all its abstract supertypes.  If you
>> >> need to know more, repeat for the types you found.
>> >
>> > Looks cumbersome, because I don't see a way to find all
>> > supertypes of a given type without walking the whole tree
>> > starting from "object" (is there one?). But it could be improved
>> > a bit if we added a "implements" field to ObjectTypeInfo.
>> 
>> My point is: we can skip discussing whether we should expose the subtype
>> relation, because we already do.
>
> Correct. My only problem is that it seems to add extra
> assumptions to the code (e.g. that there's only one abstract CPU
> type). But if libvirt is careful, it doesn't need to make any
> assumptions: it can explore the type hierarchy and confirm that
> the assumptions are correct.
>
>> 
>> > But, maybe we should take a step back: my original goal was to
>> > let libvirt know which properties are supported by any CPU model
>> > when using "-cpu".
>> 
>> Why is that useful?
>
> libvirt wants to know if the QEMU binary supports a given -cpu
> option (normally CPU features that can be enabled/disabled using
> "+foo"/"-foo").

The obvious way to check whether a specific CPU supports it is to
introspect that CPU.

The obvious way to check whether all CPUs of interest support it
(assuming that is a productive question) is to introspect all CPUs of
interest.  Works regardless of whether the option is inherited, which is
really an implementation detail.

>> >                    Maybe we should make QEMU do the QOM->option
>> > translation and implement "-cpu" support in
>> > query-command-line-options? We already do something similar with
>> > "-machine".
>> 
>> query-command-line-options is flawed, and the less it's used, the
>> happier I am.
>
> No problem, let's just forget my suggestion.  :)
>
>> 
>> Real command line introspection would be nice, but getting it will
>> involve cleaning up the unholy mess our command line has become.  Don't
>> hold your breath.
>> 
>> My preferred workaround is to find something equivalent to introspect
>> via QMP.
>
> Sounds good to me.
>
>> 
>> That said, if you come up with a patch that solves a real problem now, I
>> won't object to it just because it involves query-command-line-options.
>
> I think I will keep the current approach. Changing
> query-command-line-option would probably be more complex and
> solve only the -cpu problem. Making QOM introspection better
> looks simpler and will probably be useful for other use cases.

Makes sense.

> I am still tempted to try to make QOM->query-command-line-option
> mapping easier and simpler, but it doesn't seem to be the answer
> to the current problem.

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-07 18:28                     ` Eduardo Habkost
@ 2016-11-08  7:37                       ` Markus Armbruster
  2016-11-08 10:09                         ` Daniel P. Berrange
  2016-11-08 10:11                         ` Halil Pasic
  0 siblings, 2 replies; 50+ messages in thread
From: Markus Armbruster @ 2016-11-08  7:37 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Daniel P. Berrange, qemu-devel, Igor Mammedov, Halil Pasic,
	Andreas Färber

Eduardo Habkost <ehabkost@redhat.com> writes:

> On Mon, Nov 07, 2016 at 06:08:42PM +0000, Daniel P. Berrange wrote:
>> On Mon, Nov 07, 2016 at 04:03:58PM -0200, Eduardo Habkost wrote:
>> > On Mon, Nov 07, 2016 at 05:41:01PM +0000, Daniel P. Berrange wrote:
>> > > On Mon, Nov 07, 2016 at 03:27:31PM -0200, Eduardo Habkost wrote:
>> > > > On Mon, Nov 07, 2016 at 04:51:57PM +0100, Markus Armbruster wrote:
>> > > > > "Daniel P. Berrange" <berrange@redhat.com> writes:
>> > > > > 
>> > > > > > On Mon, Nov 07, 2016 at 03:48:49PM +0100, Halil Pasic wrote:
>> > > > > >> 
>> > > > > >> 
>> > > > > >> On 11/07/2016 02:05 PM, Eduardo Habkost wrote:
>> > > > > >> > If you want some subclasses to not have the property, then I
>> > > > > >> > recommend not registering it as a class property on the base
>> > > > > >> > class in the first place. I don't expect to see a mechanism to
>> > > > > >> > allow subclasses to remove or override class properties from
>> > > > > >> > parent classes.
>> > > > > >> > 
>> > > > > >> 
>> > > > > >> Thank you very much for your reply.
>> > > > > >> 
>> > > > > >> I understand, yet I see potential problems. The example with ioeventfd
>> > > > > >> and vhost in virtio-pci is a good one also because  the first there was
>> > > > > >> the ioeventfd property with commit 653ced07 and then the vhost case came
>> > > > > >> along with commit 50787628ee3 (ok ioeventfd is not there for some non
>> > > > > >> vhost virtio-pci devices for reasons I do not understand).
>> > > > > >> 
>> > > > > >> To rephrase this in generic context a specialization for which a
>> > > > > >> property does not make sense might come along after the property at the
>> > > > > >> base class was established.
>> > > > > >> 
>> > > > > >> Now AFAIU properties are external API, so having to make a compatibility
>> > > > > >> breaking change there might not be fun. Does this mean one should be
>> > > > > >> very careful to put only use class level properties on abstract classes
>> > > > > >> where its certain that the property always makes sense including it's
>> > > > > >> access control?
>> > > > > >
>> > > > > > This could be an argument for *NOT* allowing introspectiing of properties
>> > > > > > against abstract parent classes. If you only ever allow introspecting against
>> > > > > > leaf node non-abstract classes, then QEMU retains the freedom to move props
>> > > > > > from a base class down to an leaf class without risk of breaking mgmt apps.
>> > > > > 
>> > > > > That's a really good point.  To generalize it a bit, introspection of
>> > > > > actual interfaces is fine, but permitting introspection of how they are
>> > > > > made can add artificial constraints.
>> > > > > 
>> > > > > Introspecting the subtype relation is already problematic in this view.
>> > > > 
>> > > > Yes, that's a very good point. But note that that this means
>> > > > making things more complex for libvirt.
>> > > > 
>> > > > In the case of -cpu, if we don't expose (or allow libvirt to
>> > > > making assumptions about) subtype relations, the only way libvirt
>> > > > can conclude that "+foo can be used as -cpu option with any CPU
>> > > > model", is to query each and every CPU model type, and see if all
>> > > > of them support the "foo" property.
>> > > >
>> > > > It's a trade-off between an interface that's more complex to use
>> > > > and having less freedom to change the class hierarchy.
>> > > > Personally, I don't mind going either way, if we have a good
>> > > > reason for that.
>> > > 
>> > > Or could do a tradeoff where we allow introspection of abstract
>> > > parent classes, but explicitly document that we reserve the right
>> > > to move properties to leaf nodes ?
>> > 
>> > Reserving the right to move properties to leaf nodes would be
>> > welcome. But it would force libvirt to query all leaf nodes if it
>> > wants to be sure the option is really unsupported by the QEMU
>> > binary, so why would libvirt query the parent class in the first
>> > place?
>> 
>> The introspection API is quite general purpose so its semantics have to
>> be suitable for all types of object, but some types of object may not need
>> the full degree of flexibility. So what I meant was that while we want
>> to be able to move props down to leaf classes for objects in general,
>> we could perhaps assume that this will never happen for CPU model objects.
>
> This would work for me. I only worry that any code that makes the
> wrong assumptions (on either QEMU or libvirt) would easily go
> unnoticed until we try to change the class hierarchy and it
> breaks something.
>
> Markus, what do you think?

I dislike complexity in interface contracts.

Guidance like "if you want to learn the properties of a type T,
introspect T" is simple.

Guidance like "if you want to learn the properties common to all
subtypes of T, you need to introspect all subtypes of T, except when T
is "cpu", you can take a shortcut and introspect T instead" is not
simple, and the precedent opens the gates to even more complexity.

Is introspecting all CPU types of interest really that bad?

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-08  7:37                       ` Markus Armbruster
@ 2016-11-08 10:09                         ` Daniel P. Berrange
  2016-11-08 14:35                           ` Markus Armbruster
  2016-11-08 10:11                         ` Halil Pasic
  1 sibling, 1 reply; 50+ messages in thread
From: Daniel P. Berrange @ 2016-11-08 10:09 UTC (permalink / raw)
  To: Markus Armbruster, Jiri Denemark
  Cc: Eduardo Habkost, qemu-devel, Igor Mammedov, Halil Pasic,
	Andreas Färber

On Tue, Nov 08, 2016 at 08:37:20AM +0100, Markus Armbruster wrote:
> Eduardo Habkost <ehabkost@redhat.com> writes:
> 
> > On Mon, Nov 07, 2016 at 06:08:42PM +0000, Daniel P. Berrange wrote:
> >> On Mon, Nov 07, 2016 at 04:03:58PM -0200, Eduardo Habkost wrote:
> >> > On Mon, Nov 07, 2016 at 05:41:01PM +0000, Daniel P. Berrange wrote:
> >> > > On Mon, Nov 07, 2016 at 03:27:31PM -0200, Eduardo Habkost wrote:
> >> > > > On Mon, Nov 07, 2016 at 04:51:57PM +0100, Markus Armbruster wrote:
> >> > > > > "Daniel P. Berrange" <berrange@redhat.com> writes:
> >> > > > > 
> >> > > > > > On Mon, Nov 07, 2016 at 03:48:49PM +0100, Halil Pasic wrote:
> >> > > > > >> 
> >> > > > > >> 
> >> > > > > >> On 11/07/2016 02:05 PM, Eduardo Habkost wrote:
> >> > > > > >> > If you want some subclasses to not have the property, then I
> >> > > > > >> > recommend not registering it as a class property on the base
> >> > > > > >> > class in the first place. I don't expect to see a mechanism to
> >> > > > > >> > allow subclasses to remove or override class properties from
> >> > > > > >> > parent classes.
> >> > > > > >> > 
> >> > > > > >> 
> >> > > > > >> Thank you very much for your reply.
> >> > > > > >> 
> >> > > > > >> I understand, yet I see potential problems. The example with ioeventfd
> >> > > > > >> and vhost in virtio-pci is a good one also because  the first there was
> >> > > > > >> the ioeventfd property with commit 653ced07 and then the vhost case came
> >> > > > > >> along with commit 50787628ee3 (ok ioeventfd is not there for some non
> >> > > > > >> vhost virtio-pci devices for reasons I do not understand).
> >> > > > > >> 
> >> > > > > >> To rephrase this in generic context a specialization for which a
> >> > > > > >> property does not make sense might come along after the property at the
> >> > > > > >> base class was established.
> >> > > > > >> 
> >> > > > > >> Now AFAIU properties are external API, so having to make a compatibility
> >> > > > > >> breaking change there might not be fun. Does this mean one should be
> >> > > > > >> very careful to put only use class level properties on abstract classes
> >> > > > > >> where its certain that the property always makes sense including it's
> >> > > > > >> access control?
> >> > > > > >
> >> > > > > > This could be an argument for *NOT* allowing introspectiing of properties
> >> > > > > > against abstract parent classes. If you only ever allow introspecting against
> >> > > > > > leaf node non-abstract classes, then QEMU retains the freedom to move props
> >> > > > > > from a base class down to an leaf class without risk of breaking mgmt apps.
> >> > > > > 
> >> > > > > That's a really good point.  To generalize it a bit, introspection of
> >> > > > > actual interfaces is fine, but permitting introspection of how they are
> >> > > > > made can add artificial constraints.
> >> > > > > 
> >> > > > > Introspecting the subtype relation is already problematic in this view.
> >> > > > 
> >> > > > Yes, that's a very good point. But note that that this means
> >> > > > making things more complex for libvirt.
> >> > > > 
> >> > > > In the case of -cpu, if we don't expose (or allow libvirt to
> >> > > > making assumptions about) subtype relations, the only way libvirt
> >> > > > can conclude that "+foo can be used as -cpu option with any CPU
> >> > > > model", is to query each and every CPU model type, and see if all
> >> > > > of them support the "foo" property.
> >> > > >
> >> > > > It's a trade-off between an interface that's more complex to use
> >> > > > and having less freedom to change the class hierarchy.
> >> > > > Personally, I don't mind going either way, if we have a good
> >> > > > reason for that.
> >> > > 
> >> > > Or could do a tradeoff where we allow introspection of abstract
> >> > > parent classes, but explicitly document that we reserve the right
> >> > > to move properties to leaf nodes ?
> >> > 
> >> > Reserving the right to move properties to leaf nodes would be
> >> > welcome. But it would force libvirt to query all leaf nodes if it
> >> > wants to be sure the option is really unsupported by the QEMU
> >> > binary, so why would libvirt query the parent class in the first
> >> > place?
> >> 
> >> The introspection API is quite general purpose so its semantics have to
> >> be suitable for all types of object, but some types of object may not need
> >> the full degree of flexibility. So what I meant was that while we want
> >> to be able to move props down to leaf classes for objects in general,
> >> we could perhaps assume that this will never happen for CPU model objects.
> >
> > This would work for me. I only worry that any code that makes the
> > wrong assumptions (on either QEMU or libvirt) would easily go
> > unnoticed until we try to change the class hierarchy and it
> > breaks something.
> >
> > Markus, what do you think?
> 
> I dislike complexity in interface contracts.
> 
> Guidance like "if you want to learn the properties of a type T,
> introspect T" is simple.
> 
> Guidance like "if you want to learn the properties common to all
> subtypes of T, you need to introspect all subtypes of T, except when T
> is "cpu", you can take a shortcut and introspect T instead" is not
> simple, and the precedent opens the gates to even more complexity.
> 
> Is introspecting all CPU types of interest really that bad?

I'm no sure - adding Jiri who'll ultimately be writing this code ?

If we have to introspect M cpu flags * N cpu models, this will get slow
very quickly as IIRC there's 100+ cpu flags, and 10+ models, so 1000+
combinations

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://entangle-photo.org       -o-    http://search.cpan.org/~danberr/ :|

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-08  7:37                       ` Markus Armbruster
  2016-11-08 10:09                         ` Daniel P. Berrange
@ 2016-11-08 10:11                         ` Halil Pasic
  1 sibling, 0 replies; 50+ messages in thread
From: Halil Pasic @ 2016-11-08 10:11 UTC (permalink / raw)
  To: Markus Armbruster, Eduardo Habkost
  Cc: Igor Mammedov, qemu-devel, Andreas Färber



On 11/08/2016 08:37 AM, Markus Armbruster wrote:
> Eduardo Habkost <ehabkost@redhat.com> writes:
> 
>> On Mon, Nov 07, 2016 at 06:08:42PM +0000, Daniel P. Berrange wrote:
>>> On Mon, Nov 07, 2016 at 04:03:58PM -0200, Eduardo Habkost wrote:
>>>> On Mon, Nov 07, 2016 at 05:41:01PM +0000, Daniel P. Berrange wrote:
>>>>> On Mon, Nov 07, 2016 at 03:27:31PM -0200, Eduardo Habkost wrote:
>>>>>> On Mon, Nov 07, 2016 at 04:51:57PM +0100, Markus Armbruster wrote:
>>>>>>> "Daniel P. Berrange" <berrange@redhat.com> writes:
>>>>>>>
>>>>>>>> On Mon, Nov 07, 2016 at 03:48:49PM +0100, Halil Pasic wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 11/07/2016 02:05 PM, Eduardo Habkost wrote:
>>>>>>>>>> If you want some subclasses to not have the property, then I
>>>>>>>>>> recommend not registering it as a class property on the base
>>>>>>>>>> class in the first place. I don't expect to see a mechanism to
>>>>>>>>>> allow subclasses to remove or override class properties from
>>>>>>>>>> parent classes.
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Thank you very much for your reply.
>>>>>>>>>
>>>>>>>>> I understand, yet I see potential problems. The example with ioeventfd
>>>>>>>>> and vhost in virtio-pci is a good one also because  the first there was
>>>>>>>>> the ioeventfd property with commit 653ced07 and then the vhost case came
>>>>>>>>> along with commit 50787628ee3 (ok ioeventfd is not there for some non
>>>>>>>>> vhost virtio-pci devices for reasons I do not understand).
>>>>>>>>>
>>>>>>>>> To rephrase this in generic context a specialization for which a
>>>>>>>>> property does not make sense might come along after the property at the
>>>>>>>>> base class was established.
>>>>>>>>>
>>>>>>>>> Now AFAIU properties are external API, so having to make a compatibility
>>>>>>>>> breaking change there might not be fun. Does this mean one should be
>>>>>>>>> very careful to put only use class level properties on abstract classes
>>>>>>>>> where its certain that the property always makes sense including it's
>>>>>>>>> access control?
>>>>>>>>
>>>>>>>> This could be an argument for *NOT* allowing introspectiing of properties
>>>>>>>> against abstract parent classes. If you only ever allow introspecting against
>>>>>>>> leaf node non-abstract classes, then QEMU retains the freedom to move props
>>>>>>>> from a base class down to an leaf class without risk of breaking mgmt apps.
>>>>>>>
>>>>>>> That's a really good point.  To generalize it a bit, introspection of
>>>>>>> actual interfaces is fine, but permitting introspection of how they are
>>>>>>> made can add artificial constraints.
>>>>>>>
>>>>>>> Introspecting the subtype relation is already problematic in this view.
>>>>>>
>>>>>> Yes, that's a very good point. But note that that this means
>>>>>> making things more complex for libvirt.
>>>>>>
>>>>>> In the case of -cpu, if we don't expose (or allow libvirt to
>>>>>> making assumptions about) subtype relations, the only way libvirt
>>>>>> can conclude that "+foo can be used as -cpu option with any CPU
>>>>>> model", is to query each and every CPU model type, and see if all
>>>>>> of them support the "foo" property.
>>>>>>
>>>>>> It's a trade-off between an interface that's more complex to use
>>>>>> and having less freedom to change the class hierarchy.
>>>>>> Personally, I don't mind going either way, if we have a good
>>>>>> reason for that.
>>>>>
>>>>> Or could do a tradeoff where we allow introspection of abstract
>>>>> parent classes, but explicitly document that we reserve the right
>>>>> to move properties to leaf nodes ?
>>>>
>>>> Reserving the right to move properties to leaf nodes would be
>>>> welcome. But it would force libvirt to query all leaf nodes if it
>>>> wants to be sure the option is really unsupported by the QEMU
>>>> binary, so why would libvirt query the parent class in the first
>>>> place?
>>>
>>> The introspection API is quite general purpose so its semantics have to
>>> be suitable for all types of object, but some types of object may not need
>>> the full degree of flexibility. So what I meant was that while we want
>>> to be able to move props down to leaf classes for objects in general,
>>> we could perhaps assume that this will never happen for CPU model objects.
>>
>> This would work for me. I only worry that any code that makes the
>> wrong assumptions (on either QEMU or libvirt) would easily go
>> unnoticed until we try to change the class hierarchy and it
>> breaks something.
>>
>> Markus, what do you think?
> 
> I dislike complexity in interface contracts.
> 
> Guidance like "if you want to learn the properties of a type T,
> introspect T" is simple.
> 
> Guidance like "if you want to learn the properties common to all
> subtypes of T, you need to introspect all subtypes of T, except when T
> is "cpu", you can take a shortcut and introspect T instead" is not
> simple, and the precedent opens the gates to even more complexity.
> 

+1

> Is introspecting all CPU types of interest really that bad?
> 

A simple to use interface could eventually also be achieved by introducing
operations for these things which currently seem cumbersome with 
(e.g. properties common to all subtypes of T) the current set of (primitive)
operations. This would also leave us more degrees of freedom regarding
implementation details and also other stuff. (Sorry if this was
already discussed with previous versions of the patchset).

Regards,
Halil

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-08 10:09                         ` Daniel P. Berrange
@ 2016-11-08 14:35                           ` Markus Armbruster
  2016-11-08 16:16                             ` Eduardo Habkost
  0 siblings, 1 reply; 50+ messages in thread
From: Markus Armbruster @ 2016-11-08 14:35 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Jiri Denemark, Igor Mammedov, Halil Pasic, Eduardo Habkost,
	Andreas Färber, qemu-devel

"Daniel P. Berrange" <berrange@redhat.com> writes:

> On Tue, Nov 08, 2016 at 08:37:20AM +0100, Markus Armbruster wrote:
>> Eduardo Habkost <ehabkost@redhat.com> writes:
>> 
>> > On Mon, Nov 07, 2016 at 06:08:42PM +0000, Daniel P. Berrange wrote:
>> >> On Mon, Nov 07, 2016 at 04:03:58PM -0200, Eduardo Habkost wrote:
>> >> > On Mon, Nov 07, 2016 at 05:41:01PM +0000, Daniel P. Berrange wrote:
>> >> > > On Mon, Nov 07, 2016 at 03:27:31PM -0200, Eduardo Habkost wrote:
>> >> > > > On Mon, Nov 07, 2016 at 04:51:57PM +0100, Markus Armbruster wrote:
>> >> > > > > "Daniel P. Berrange" <berrange@redhat.com> writes:
>> >> > > > > 
>> >> > > > > > On Mon, Nov 07, 2016 at 03:48:49PM +0100, Halil Pasic wrote:
>> >> > > > > >> 
>> >> > > > > >> 
>> >> > > > > >> On 11/07/2016 02:05 PM, Eduardo Habkost wrote:
>> >> > > > > >> > If you want some subclasses to not have the property, then I
>> >> > > > > >> > recommend not registering it as a class property on the base
>> >> > > > > >> > class in the first place. I don't expect to see a mechanism to
>> >> > > > > >> > allow subclasses to remove or override class properties from
>> >> > > > > >> > parent classes.
>> >> > > > > >> > 
>> >> > > > > >> 
>> >> > > > > >> Thank you very much for your reply.
>> >> > > > > >> 
>> >> > > > > >> I understand, yet I see potential problems. The example with ioeventfd
>> >> > > > > >> and vhost in virtio-pci is a good one also because  the first there was
>> >> > > > > >> the ioeventfd property with commit 653ced07 and then the vhost case came
>> >> > > > > >> along with commit 50787628ee3 (ok ioeventfd is not there for some non
>> >> > > > > >> vhost virtio-pci devices for reasons I do not understand).
>> >> > > > > >> 
>> >> > > > > >> To rephrase this in generic context a specialization for which a
>> >> > > > > >> property does not make sense might come along after the property at the
>> >> > > > > >> base class was established.
>> >> > > > > >> 
>> >> > > > > >> Now AFAIU properties are external API, so having to make a compatibility
>> >> > > > > >> breaking change there might not be fun. Does this mean one should be
>> >> > > > > >> very careful to put only use class level properties on abstract classes
>> >> > > > > >> where its certain that the property always makes sense including it's
>> >> > > > > >> access control?
>> >> > > > > >
>> >> > > > > > This could be an argument for *NOT* allowing introspectiing of properties
>> >> > > > > > against abstract parent classes. If you only ever allow introspecting against
>> >> > > > > > leaf node non-abstract classes, then QEMU retains the freedom to move props
>> >> > > > > > from a base class down to an leaf class without risk of breaking mgmt apps.
>> >> > > > > 
>> >> > > > > That's a really good point.  To generalize it a bit, introspection of
>> >> > > > > actual interfaces is fine, but permitting introspection of how they are
>> >> > > > > made can add artificial constraints.
>> >> > > > > 
>> >> > > > > Introspecting the subtype relation is already problematic in this view.
>> >> > > > 
>> >> > > > Yes, that's a very good point. But note that that this means
>> >> > > > making things more complex for libvirt.
>> >> > > > 
>> >> > > > In the case of -cpu, if we don't expose (or allow libvirt to
>> >> > > > making assumptions about) subtype relations, the only way libvirt
>> >> > > > can conclude that "+foo can be used as -cpu option with any CPU
>> >> > > > model", is to query each and every CPU model type, and see if all
>> >> > > > of them support the "foo" property.
>> >> > > >
>> >> > > > It's a trade-off between an interface that's more complex to use
>> >> > > > and having less freedom to change the class hierarchy.
>> >> > > > Personally, I don't mind going either way, if we have a good
>> >> > > > reason for that.
>> >> > > 
>> >> > > Or could do a tradeoff where we allow introspection of abstract
>> >> > > parent classes, but explicitly document that we reserve the right
>> >> > > to move properties to leaf nodes ?
>> >> > 
>> >> > Reserving the right to move properties to leaf nodes would be
>> >> > welcome. But it would force libvirt to query all leaf nodes if it
>> >> > wants to be sure the option is really unsupported by the QEMU
>> >> > binary, so why would libvirt query the parent class in the first
>> >> > place?
>> >> 
>> >> The introspection API is quite general purpose so its semantics have to
>> >> be suitable for all types of object, but some types of object may not need
>> >> the full degree of flexibility. So what I meant was that while we want
>> >> to be able to move props down to leaf classes for objects in general,
>> >> we could perhaps assume that this will never happen for CPU model objects.
>> >
>> > This would work for me. I only worry that any code that makes the
>> > wrong assumptions (on either QEMU or libvirt) would easily go
>> > unnoticed until we try to change the class hierarchy and it
>> > breaks something.
>> >
>> > Markus, what do you think?
>> 
>> I dislike complexity in interface contracts.
>> 
>> Guidance like "if you want to learn the properties of a type T,
>> introspect T" is simple.
>> 
>> Guidance like "if you want to learn the properties common to all
>> subtypes of T, you need to introspect all subtypes of T, except when T
>> is "cpu", you can take a shortcut and introspect T instead" is not
>> simple, and the precedent opens the gates to even more complexity.
>> 
>> Is introspecting all CPU types of interest really that bad?
>
> I'm no sure - adding Jiri who'll ultimately be writing this code ?
>
> If we have to introspect M cpu flags * N cpu models, this will get slow
> very quickly as IIRC there's 100+ cpu flags, and 10+ models, so 1000+
> combinations

for CPU in CPUs
    if this is the first one
        common_flags = CPU's flags
    else
        common_flags &= CPU's flags

Yes, that's O(M*N), but the I/O is O(N): you query for each CPU just
once.  I'd expect I/O to dominate even with hundreds of CPU flags.

In general, if a management application introspects the same things via
QMP multiple times, it's probably doing it wrong.

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-08 14:35                           ` Markus Armbruster
@ 2016-11-08 16:16                             ` Eduardo Habkost
  0 siblings, 0 replies; 50+ messages in thread
From: Eduardo Habkost @ 2016-11-08 16:16 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Daniel P. Berrange, Jiri Denemark, Igor Mammedov, Halil Pasic,
	Andreas Färber, qemu-devel

On Tue, Nov 08, 2016 at 03:35:08PM +0100, Markus Armbruster wrote:
> "Daniel P. Berrange" <berrange@redhat.com> writes:
> 
> > On Tue, Nov 08, 2016 at 08:37:20AM +0100, Markus Armbruster wrote:
> >> Eduardo Habkost <ehabkost@redhat.com> writes:
> >> 
> >> > On Mon, Nov 07, 2016 at 06:08:42PM +0000, Daniel P. Berrange wrote:
> >> >> On Mon, Nov 07, 2016 at 04:03:58PM -0200, Eduardo Habkost wrote:
> >> >> > On Mon, Nov 07, 2016 at 05:41:01PM +0000, Daniel P. Berrange wrote:
> >> >> > > On Mon, Nov 07, 2016 at 03:27:31PM -0200, Eduardo Habkost wrote:
> >> >> > > > On Mon, Nov 07, 2016 at 04:51:57PM +0100, Markus Armbruster wrote:
> >> >> > > > > "Daniel P. Berrange" <berrange@redhat.com> writes:
> >> >> > > > > 
> >> >> > > > > > On Mon, Nov 07, 2016 at 03:48:49PM +0100, Halil Pasic wrote:
> >> >> > > > > >> 
> >> >> > > > > >> 
> >> >> > > > > >> On 11/07/2016 02:05 PM, Eduardo Habkost wrote:
> >> >> > > > > >> > If you want some subclasses to not have the property, then I
> >> >> > > > > >> > recommend not registering it as a class property on the base
> >> >> > > > > >> > class in the first place. I don't expect to see a mechanism to
> >> >> > > > > >> > allow subclasses to remove or override class properties from
> >> >> > > > > >> > parent classes.
> >> >> > > > > >> > 
> >> >> > > > > >> 
> >> >> > > > > >> Thank you very much for your reply.
> >> >> > > > > >> 
> >> >> > > > > >> I understand, yet I see potential problems. The example with ioeventfd
> >> >> > > > > >> and vhost in virtio-pci is a good one also because  the first there was
> >> >> > > > > >> the ioeventfd property with commit 653ced07 and then the vhost case came
> >> >> > > > > >> along with commit 50787628ee3 (ok ioeventfd is not there for some non
> >> >> > > > > >> vhost virtio-pci devices for reasons I do not understand).
> >> >> > > > > >> 
> >> >> > > > > >> To rephrase this in generic context a specialization for which a
> >> >> > > > > >> property does not make sense might come along after the property at the
> >> >> > > > > >> base class was established.
> >> >> > > > > >> 
> >> >> > > > > >> Now AFAIU properties are external API, so having to make a compatibility
> >> >> > > > > >> breaking change there might not be fun. Does this mean one should be
> >> >> > > > > >> very careful to put only use class level properties on abstract classes
> >> >> > > > > >> where its certain that the property always makes sense including it's
> >> >> > > > > >> access control?
> >> >> > > > > >
> >> >> > > > > > This could be an argument for *NOT* allowing introspectiing of properties
> >> >> > > > > > against abstract parent classes. If you only ever allow introspecting against
> >> >> > > > > > leaf node non-abstract classes, then QEMU retains the freedom to move props
> >> >> > > > > > from a base class down to an leaf class without risk of breaking mgmt apps.
> >> >> > > > > 
> >> >> > > > > That's a really good point.  To generalize it a bit, introspection of
> >> >> > > > > actual interfaces is fine, but permitting introspection of how they are
> >> >> > > > > made can add artificial constraints.
> >> >> > > > > 
> >> >> > > > > Introspecting the subtype relation is already problematic in this view.
> >> >> > > > 
> >> >> > > > Yes, that's a very good point. But note that that this means
> >> >> > > > making things more complex for libvirt.
> >> >> > > > 
> >> >> > > > In the case of -cpu, if we don't expose (or allow libvirt to
> >> >> > > > making assumptions about) subtype relations, the only way libvirt
> >> >> > > > can conclude that "+foo can be used as -cpu option with any CPU
> >> >> > > > model", is to query each and every CPU model type, and see if all
> >> >> > > > of them support the "foo" property.
> >> >> > > >
> >> >> > > > It's a trade-off between an interface that's more complex to use
> >> >> > > > and having less freedom to change the class hierarchy.
> >> >> > > > Personally, I don't mind going either way, if we have a good
> >> >> > > > reason for that.
> >> >> > > 
> >> >> > > Or could do a tradeoff where we allow introspection of abstract
> >> >> > > parent classes, but explicitly document that we reserve the right
> >> >> > > to move properties to leaf nodes ?
> >> >> > 
> >> >> > Reserving the right to move properties to leaf nodes would be
> >> >> > welcome. But it would force libvirt to query all leaf nodes if it
> >> >> > wants to be sure the option is really unsupported by the QEMU
> >> >> > binary, so why would libvirt query the parent class in the first
> >> >> > place?
> >> >> 
> >> >> The introspection API is quite general purpose so its semantics have to
> >> >> be suitable for all types of object, but some types of object may not need
> >> >> the full degree of flexibility. So what I meant was that while we want
> >> >> to be able to move props down to leaf classes for objects in general,
> >> >> we could perhaps assume that this will never happen for CPU model objects.
> >> >
> >> > This would work for me. I only worry that any code that makes the
> >> > wrong assumptions (on either QEMU or libvirt) would easily go
> >> > unnoticed until we try to change the class hierarchy and it
> >> > breaks something.
> >> >
> >> > Markus, what do you think?
> >> 
> >> I dislike complexity in interface contracts.
> >> 
> >> Guidance like "if you want to learn the properties of a type T,
> >> introspect T" is simple.
> >> 
> >> Guidance like "if you want to learn the properties common to all
> >> subtypes of T, you need to introspect all subtypes of T, except when T
> >> is "cpu", you can take a shortcut and introspect T instead" is not
> >> simple, and the precedent opens the gates to even more complexity.
> >> 
> >> Is introspecting all CPU types of interest really that bad?
> >
> > I'm no sure - adding Jiri who'll ultimately be writing this code ?
> >
> > If we have to introspect M cpu flags * N cpu models, this will get slow
> > very quickly as IIRC there's 100+ cpu flags, and 10+ models, so 1000+
> > combinations
> 
> for CPU in CPUs
>     if this is the first one
>         common_flags = CPU's flags
>     else
>         common_flags &= CPU's flags
> 
> Yes, that's O(M*N), but the I/O is O(N): you query for each CPU just
> once.  I'd expect I/O to dominate even with hundreds of CPU flags.
> 
> In general, if a management application introspects the same things via
> QMP multiple times, it's probably doing it wrong.

Or they could query only the CPU model that is being used for a
VM, when validating the VM configuration. But I'm not sure when
exactly this information is going to be used by libvirt.

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-08  7:29                   ` Markus Armbruster
@ 2016-11-11 12:17                     ` Jiri Denemark
  2016-11-11 12:34                       ` Eduardo Habkost
  2016-11-11 14:29                       ` Markus Armbruster
  0 siblings, 2 replies; 50+ messages in thread
From: Jiri Denemark @ 2016-11-11 12:17 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Eduardo Habkost, libvir-list, Igor Mammedov, qemu-devel,
	Andreas Färber

On Tue, Nov 08, 2016 at 08:29:41 +0100, Markus Armbruster wrote:
> Eduardo Habkost <ehabkost@redhat.com> writes:
> > libvirt wants to know if the QEMU binary supports a given -cpu
> > option (normally CPU features that can be enabled/disabled using
> > "+foo"/"-foo").
> 
> The obvious way to check whether a specific CPU supports it is to
> introspect that CPU.
> 
> The obvious way to check whether all CPUs of interest support it
> (assuming that is a productive question) is to introspect all CPUs of
> interest.  Works regardless of whether the option is inherited, which is
> really an implementation detail.

As Eduardo said, libvirt wants to know whether it can use a given CPU
feature with current QEMU binary. In -cpu help, we can see a list of
models and features QEMU understands, but we need to get similar info
via QMP. CPU models are easy, but how do we get the list of CPU
features? If introspection is the way to get it, I'm fine with that,
just beware that we don't actually know the name of the CPU object
(Westmere-x86_64-cpu), we only know the name of the CPU model
(Westmere). So if the object name is needed, we need to query the
mapping from CPU model names to CPU object names.

Jirka

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-11 12:17                     ` Jiri Denemark
@ 2016-11-11 12:34                       ` Eduardo Habkost
  2016-11-11 14:29                       ` Markus Armbruster
  1 sibling, 0 replies; 50+ messages in thread
From: Eduardo Habkost @ 2016-11-11 12:34 UTC (permalink / raw)
  To: Markus Armbruster, libvir-list, Igor Mammedov, qemu-devel,
	Andreas Färber

On Fri, Nov 11, 2016 at 01:17:44PM +0100, Jiri Denemark wrote:
> On Tue, Nov 08, 2016 at 08:29:41 +0100, Markus Armbruster wrote:
> > Eduardo Habkost <ehabkost@redhat.com> writes:
> > > libvirt wants to know if the QEMU binary supports a given -cpu
> > > option (normally CPU features that can be enabled/disabled using
> > > "+foo"/"-foo").
> > 
> > The obvious way to check whether a specific CPU supports it is to
> > introspect that CPU.
> > 
> > The obvious way to check whether all CPUs of interest support it
> > (assuming that is a productive question) is to introspect all CPUs of
> > interest.  Works regardless of whether the option is inherited, which is
> > really an implementation detail.
> 
> As Eduardo said, libvirt wants to know whether it can use a given CPU
> feature with current QEMU binary. In -cpu help, we can see a list of
> models and features QEMU understands, but we need to get similar info
> via QMP. CPU models are easy, but how do we get the list of CPU
> features? If introspection is the way to get it, I'm fine with that,
> just beware that we don't actually know the name of the CPU object
> (Westmere-x86_64-cpu), we only know the name of the CPU model
> (Westmere). So if the object name is needed, we need to query the
> mapping from CPU model names to CPU object names.

I have patches to add the QOM type name to query-cpu-definitions.
I don't remember if I submitted them to qemu-devel already. I
will check.

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
  2016-11-11 12:17                     ` Jiri Denemark
  2016-11-11 12:34                       ` Eduardo Habkost
@ 2016-11-11 14:29                       ` Markus Armbruster
  1 sibling, 0 replies; 50+ messages in thread
From: Markus Armbruster @ 2016-11-11 14:29 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: libvir-list, Igor Mammedov, qemu-devel, Andreas Färber

Jiri Denemark <jdenemar@redhat.com> writes:

> On Tue, Nov 08, 2016 at 08:29:41 +0100, Markus Armbruster wrote:
>> Eduardo Habkost <ehabkost@redhat.com> writes:
>> > libvirt wants to know if the QEMU binary supports a given -cpu
>> > option (normally CPU features that can be enabled/disabled using
>> > "+foo"/"-foo").
>> 
>> The obvious way to check whether a specific CPU supports it is to
>> introspect that CPU.
>> 
>> The obvious way to check whether all CPUs of interest support it
>> (assuming that is a productive question) is to introspect all CPUs of
>> interest.  Works regardless of whether the option is inherited, which is
>> really an implementation detail.
>
> As Eduardo said, libvirt wants to know whether it can use a given CPU
> feature with current QEMU binary. In -cpu help, we can see a list of
> models and features QEMU understands, but we need to get similar info
> via QMP. CPU models are easy, but how do we get the list of CPU
> features? If introspection is the way to get it, I'm fine with that,
> just beware that we don't actually know the name of the CPU object
> (Westmere-x86_64-cpu), we only know the name of the CPU model
> (Westmere).

Actually, you do:

    { "execute": "qom-list-types", "arguments": { "implements": "cpu" } }
    {"return": [{"name": "Westmere-x86_64-cpu"}, ...]}

>             So if the object name is needed, we need to query the
> mapping from CPU model names to CPU object names.

Hmm.  The problem is that some interfaces such as -cpu require a "CPU
model name", but introspection gives you the QOM type name.  The mapping
from "model name" to type name even depends on the target: it's CPUClass
method class_by_name().

Can't say I like that, but we got to play the hand we were dealt, and
that means we need to provide a way to introspect the mapping between
CPU model name and QOM type name.  Eduardo's plan to add the QOM type
name to query-cpu-definitions makes more sense to me now.

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

end of thread, other threads:[~2016-11-11 14:29 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-29  1:47 [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties Eduardo Habkost
2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 1/8] tests: check-qom-proplist: Remove duplicate "bv" property Eduardo Habkost
2016-11-04 11:22   ` Markus Armbruster
2016-11-04 15:10     ` Markus Armbruster
2016-11-04 15:56   ` Andreas Färber
2016-11-04 16:07     ` Eduardo Habkost
2016-11-04 16:11       ` Andreas Färber
2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 2/8] tests: check-qom-proplist: Use &error_abort to catch errors Eduardo Habkost
2016-10-31 10:14   ` Igor Mammedov
2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 3/8] qdev: device_class_set_props() function Eduardo Habkost
2016-11-01 15:02   ` Igor Mammedov
2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 4/8] qdev: Extract property-default code to qdev_property_set_to_default() Eduardo Habkost
2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 5/8] qdev: Register static properties as class properties Eduardo Habkost
2016-10-31 12:06   ` Igor Mammedov
2016-11-04 15:22   ` Markus Armbruster
2016-11-04 16:00     ` Eduardo Habkost
2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 6/8] qom: object_class_property_iter_init() function Eduardo Habkost
2016-10-31 13:45   ` Igor Mammedov
2016-11-04 15:31   ` Markus Armbruster
2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties Eduardo Habkost
2016-10-31 14:07   ` Igor Mammedov
2016-10-31 14:36     ` Eduardo Habkost
2016-11-04 15:45       ` Markus Armbruster
2016-11-04 16:04         ` Eduardo Habkost
2016-11-07  8:09           ` Markus Armbruster
2016-11-07 12:38             ` Eduardo Habkost
2016-11-07 14:40               ` Markus Armbruster
2016-11-07 17:11                 ` Eduardo Habkost
2016-11-08  7:29                   ` Markus Armbruster
2016-11-11 12:17                     ` Jiri Denemark
2016-11-11 12:34                       ` Eduardo Habkost
2016-11-11 14:29                       ` Markus Armbruster
2016-11-07 12:45   ` Halil Pasic
2016-11-07 13:05     ` Eduardo Habkost
2016-11-07 14:48       ` Halil Pasic
2016-11-07 15:01         ` Daniel P. Berrange
2016-11-07 15:51           ` Markus Armbruster
2016-11-07 17:27             ` Eduardo Habkost
2016-11-07 17:41               ` Daniel P. Berrange
2016-11-07 18:03                 ` Eduardo Habkost
2016-11-07 18:08                   ` Daniel P. Berrange
2016-11-07 18:28                     ` Eduardo Habkost
2016-11-08  7:37                       ` Markus Armbruster
2016-11-08 10:09                         ` Daniel P. Berrange
2016-11-08 14:35                           ` Markus Armbruster
2016-11-08 16:16                             ` Eduardo Habkost
2016-11-08 10:11                         ` Halil Pasic
2016-10-29  1:48 ` [Qemu-devel] [PATCH v4 8/8] qdev: Warning about using qdev_property_add_static() in new code Eduardo Habkost
2016-10-31 14:05   ` Igor Mammedov
2016-11-04 15:52 ` [Qemu-devel] [PATCH v4 0/8] qdev class properties + abstract class support on device-list-properties Markus Armbruster

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.