summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--CODING_STYLE.rst37
-rw-r--r--Kconfig.host4
-rw-r--r--MAINTAINERS8
-rw-r--r--Makefile21
-rw-r--r--accel/tcg/tcg-all.c9
-rw-r--r--audio/trace-events3
-rw-r--r--backends/cryptodev-builtin.c8
-rw-r--r--backends/cryptodev-vhost-user.c11
-rw-r--r--backends/dbus-vmstate.c16
-rw-r--r--backends/hostmem-file.c7
-rw-r--r--backends/hostmem-memfd.c7
-rw-r--r--backends/rng-builtin.c9
-rw-r--r--backends/rng-egd.c10
-rw-r--r--backends/tpm/tpm_emulator.c10
-rw-r--r--backends/tpm/tpm_passthrough.c7
-rw-r--r--block.c492
-rw-r--r--block/backup-top.c4
-rw-r--r--block/backup.c9
-rw-r--r--block/blkdebug.c7
-rw-r--r--block/blklogwrites.c1
-rw-r--r--block/block-backend.c7
-rw-r--r--block/block-copy.c4
-rw-r--r--block/commit.c95
-rw-r--r--block/copy-on-read.c13
-rw-r--r--block/file-win32.c22
-rw-r--r--block/filter-compress.c2
-rw-r--r--block/io.c142
-rw-r--r--block/mirror.c119
-rw-r--r--block/monitor/block-hmp-cmds.c2
-rw-r--r--block/null.c7
-rw-r--r--block/nvme.c248
-rw-r--r--block/qapi.c74
-rw-r--r--block/qcow2-cluster.c1
-rw-r--r--block/snapshot.c104
-rw-r--r--block/stream.c63
-rw-r--r--block/throttle.c11
-rw-r--r--block/trace-events8
-rw-r--r--block/vmdk.c16
-rw-r--r--blockdev.c101
-rw-r--r--chardev/baum.c9
-rw-r--r--chardev/char-pty.c9
-rw-r--r--chardev/char-ringbuf.c10
-rw-r--r--chardev/char-socket.c10
-rw-r--r--chardev/char-udp.c9
-rw-r--r--chardev/char-win-stdio.c10
-rw-r--r--chardev/chardev-internal.h8
-rw-r--r--chardev/msmouse.c10
-rw-r--r--chardev/testdev.c10
-rw-r--r--chardev/wctablet.c10
-rwxr-xr-xconfigure48
-rw-r--r--contrib/plugins/Makefile42
-rw-r--r--contrib/plugins/hotblocks.c (renamed from tests/plugin/hotblocks.c)0
-rw-r--r--contrib/plugins/hotpages.c (renamed from tests/plugin/hotpages.c)0
-rw-r--r--contrib/plugins/howvec.c (renamed from tests/plugin/howvec.c)0
-rw-r--r--contrib/plugins/lockstep.c (renamed from tests/plugin/lockstep.c)0
-rw-r--r--crypto/aes.c51
-rw-r--r--crypto/afalgpriv.h3
-rw-r--r--crypto/cipher-afalg.c25
-rw-r--r--crypto/cipher-builtin.c532
-rw-r--r--crypto/cipher-builtin.c.inc435
-rw-r--r--crypto/cipher-gcrypt.c.inc (renamed from crypto/cipher-gcrypt.c)503
-rw-r--r--crypto/cipher-nettle.c733
-rw-r--r--crypto/cipher-nettle.c.inc760
-rw-r--r--crypto/cipher.c44
-rw-r--r--crypto/cipherpriv.h6
-rw-r--r--docs/devel/tcg-plugins.rst146
-rw-r--r--docs/system/deprecated.rst7
-rw-r--r--hw/9pfs/virtio-9p.h11
-rw-r--r--hw/acpi/piix4.c10
-rw-r--r--hw/acpi/tco.c11
-rw-r--r--hw/acpi/vmgenid.c6
-rw-r--r--hw/alpha/typhoon.c10
-rw-r--r--hw/arm/collie.c10
-rw-r--r--hw/arm/highbank.c10
-rw-r--r--hw/arm/integratorcp.c28
-rw-r--r--hw/arm/microbit.c10
-rw-r--r--hw/arm/mps2-tz.c19
-rw-r--r--hw/arm/mps2.c19
-rw-r--r--hw/arm/musca.c19
-rw-r--r--hw/arm/musicpal.c73
-rw-r--r--hw/arm/palm.c10
-rw-r--r--hw/arm/pxa2xx.c30
-rw-r--r--hw/arm/pxa2xx_gpio.c7
-rw-r--r--hw/arm/pxa2xx_pic.c10
-rw-r--r--hw/arm/raspi.c19
-rw-r--r--hw/arm/sbsa-ref.c10
-rw-r--r--hw/arm/spitz.c61
-rw-r--r--hw/arm/stellaris.c28
-rw-r--r--hw/arm/strongarm.c49
-rw-r--r--hw/arm/tosa.c18
-rw-r--r--hw/arm/versatilepb.c10
-rw-r--r--hw/arm/vexpress.c19
-rw-r--r--hw/arm/xilinx_zynq.c10
-rw-r--r--hw/arm/xlnx-versal-virt.c10
-rw-r--r--hw/arm/xlnx-zcu102.c10
-rw-r--r--hw/arm/z2.c17
-rw-r--r--hw/audio/ac97.c10
-rw-r--r--hw/audio/adlib.c9
-rw-r--r--hw/audio/cs4231.c10
-rw-r--r--hw/audio/cs4231a.c9
-rw-r--r--hw/audio/es1370.c10
-rw-r--r--hw/audio/gus.c9
-rw-r--r--hw/audio/hda-codec.c4
-rw-r--r--hw/audio/intel-hda.c5
-rw-r--r--hw/audio/intel-hda.h20
-rw-r--r--hw/audio/marvell_88w8618.c10
-rw-r--r--hw/audio/milkymist-ac97.c7
-rw-r--r--hw/audio/pcspk.c9
-rw-r--r--hw/audio/pl041.c9
-rw-r--r--hw/audio/sb16.c9
-rw-r--r--hw/audio/wm8750.c9
-rw-r--r--hw/avr/arduino.c19
-rw-r--r--hw/avr/atmega.c12
-rw-r--r--hw/avr/atmega.h9
-rw-r--r--hw/block/fdc.c34
-rw-r--r--hw/block/m25p80.c19
-rw-r--r--hw/block/nand.c5
-rw-r--r--hw/block/onenand.c9
-rw-r--r--hw/block/trace-events2
-rw-r--r--hw/char/debugcon.c10
-rw-r--r--hw/char/etraxfs_ser.c10
-rw-r--r--hw/char/exynos4210_uart.c10
-rw-r--r--hw/char/grlib_apbuart.c10
-rw-r--r--hw/char/ipoctal232.c5
-rw-r--r--hw/char/lm32_juart.c6
-rw-r--r--hw/char/lm32_uart.c6
-rw-r--r--hw/char/mcf_uart.c9
-rw-r--r--hw/char/milkymist-uart.c7
-rw-r--r--hw/char/parallel.c10
-rw-r--r--hw/char/sclpconsole-lm.c10
-rw-r--r--hw/char/sclpconsole.c10
-rw-r--r--hw/char/serial-isa.c9
-rw-r--r--hw/char/serial-pci.c9
-rw-r--r--hw/char/spapr_vty.c10
-rw-r--r--hw/char/terminal3270.c10
-rw-r--r--hw/char/trace-events2
-rw-r--r--hw/char/virtio-console.c10
-rw-r--r--hw/char/xilinx_uartlite.c10
-rw-r--r--hw/core/irq.c3
-rw-r--r--hw/cpu/realview_mpcore.c10
-rw-r--r--hw/display/ads7846.c9
-rw-r--r--hw/display/artist.c9
-rw-r--r--hw/display/ati_int.h9
-rw-r--r--hw/display/bochs-display.c10
-rw-r--r--hw/display/cg3.c9
-rw-r--r--hw/display/cirrus_vga.c10
-rw-r--r--hw/display/cirrus_vga_isa.c10
-rw-r--r--hw/display/exynos4210_fimd.c10
-rw-r--r--hw/display/g364fb.c9
-rw-r--r--hw/display/jazz_led.c9
-rw-r--r--hw/display/milkymist-tmu2.c7
-rw-r--r--hw/display/milkymist-vgafb.c7
-rw-r--r--hw/display/next-fb.c6
-rw-r--r--hw/display/pl110.c9
-rw-r--r--hw/display/qxl.h9
-rw-r--r--hw/display/ramfb-standalone.c9
-rw-r--r--hw/display/sii9022.c9
-rw-r--r--hw/display/sm501.c18
-rw-r--r--hw/display/ssd0303.c9
-rw-r--r--hw/display/ssd0323.c9
-rw-r--r--hw/display/tcx.c9
-rw-r--r--hw/display/trace-events4
-rw-r--r--hw/display/vga-isa.c9
-rw-r--r--hw/display/vga-pci.c9
-rw-r--r--hw/display/vhost-user-gpu-pci.c10
-rw-r--r--hw/display/vhost-user-vga.c12
-rw-r--r--hw/display/virtio-gpu-pci.c10
-rw-r--r--hw/display/virtio-vga.c16
-rw-r--r--hw/display/virtio-vga.h17
-rw-r--r--hw/display/vmware_vga.c5
-rw-r--r--hw/dma/i82374.c9
-rw-r--r--hw/dma/pl330.c4
-rw-r--r--hw/dma/puv3_dma.c9
-rw-r--r--hw/dma/pxa2xx_dma.c9
-rw-r--r--hw/dma/rc4030.c10
-rw-r--r--hw/dma/sparc32_dma.c2
-rw-r--r--hw/dma/xilinx_axidma.c23
-rw-r--r--hw/dma/xlnx_dpdma.c2
-rw-r--r--hw/gpio/gpio_key.c9
-rw-r--r--hw/gpio/max7310.c20
-rw-r--r--hw/gpio/mpc8xxx.c9
-rw-r--r--hw/gpio/omap_gpio.c6
-rw-r--r--hw/gpio/pl061.c9
-rw-r--r--hw/gpio/puv3_gpio.c9
-rw-r--r--hw/gpio/zaurus.c6
-rw-r--r--hw/hppa/dino.c10
-rw-r--r--hw/hppa/lasi.c10
-rw-r--r--hw/hyperv/hyperv.c9
-rw-r--r--hw/hyperv/hyperv_testdev.c5
-rw-r--r--hw/hyperv/trace-events2
-rw-r--r--hw/hyperv/vmbus.c3
-rw-r--r--hw/i2c/bitbang_i2c.c9
-rw-r--r--hw/i2c/exynos4210_i2c.c10
-rw-r--r--hw/i2c/mpc_i2c.c10
-rw-r--r--hw/i2c/smbus_eeprom.c10
-rw-r--r--hw/i2c/smbus_ich9.c10
-rw-r--r--hw/i2c/versatile_i2c.c7
-rw-r--r--hw/i386/amd_iommu.h10
-rw-r--r--hw/i386/kvm/clock.c9
-rw-r--r--hw/i386/kvm/i8254.c18
-rw-r--r--hw/i386/kvm/i8259.c12
-rw-r--r--hw/i386/kvmvapic.c9
-rw-r--r--hw/i386/pc_piix.c2
-rw-r--r--hw/i386/port92.c9
-rw-r--r--hw/i386/vmmouse.c10
-rw-r--r--hw/i386/vmport.c9
-rw-r--r--hw/i386/xen/xen_platform.c10
-rw-r--r--hw/i386/xen/xen_pvdevice.c10
-rw-r--r--hw/ide/ahci.c4
-rw-r--r--hw/ide/ich.c8
-rw-r--r--hw/ide/isa.c9
-rw-r--r--hw/ide/microdrive.c9
-rw-r--r--hw/ide/mmio.c9
-rw-r--r--hw/ide/sii3112.c8
-rw-r--r--hw/input/adb-kbd.c18
-rw-r--r--hw/input/adb-mouse.c18
-rw-r--r--hw/input/lm832x.c9
-rw-r--r--hw/input/milkymist-softusb.c7
-rw-r--r--hw/input/pl050.c9
-rw-r--r--hw/intc/apic.c6
-rw-r--r--hw/intc/arm_gic_kvm.c17
-rw-r--r--hw/intc/arm_gicv2m.c9
-rw-r--r--hw/intc/arm_gicv3_its_kvm.c14
-rw-r--r--hw/intc/arm_gicv3_kvm.c15
-rw-r--r--hw/intc/etraxfs_pic.c5
-rw-r--r--hw/intc/exynos4210_combiner.c10
-rw-r--r--hw/intc/exynos4210_gic.c19
-rw-r--r--hw/intc/grlib_irqmp.c9
-rw-r--r--hw/intc/i8259.c10
-rw-r--r--hw/intc/lm32_pic.c6
-rw-r--r--hw/intc/loongson_liointc.c5
-rw-r--r--hw/intc/nios2_iic.c10
-rw-r--r--hw/intc/omap_intc.c2
-rw-r--r--hw/intc/ompic.c6
-rw-r--r--hw/intc/openpic_kvm.c10
-rw-r--r--hw/intc/pl190.c9
-rw-r--r--hw/intc/puv3_intc.c9
-rw-r--r--hw/intc/s390_flic_kvm.c12
-rw-r--r--hw/intc/slavio_intctl.c10
-rw-r--r--hw/intc/xilinx_intc.c4
-rw-r--r--hw/ipack/tpci200.c10
-rw-r--r--hw/ipmi/ipmi_bmc_extern.c10
-rw-r--r--hw/ipmi/isa_ipmi_bt.c10
-rw-r--r--hw/ipmi/isa_ipmi_kcs.c10
-rw-r--r--hw/ipmi/pci_ipmi_bt.c10
-rw-r--r--hw/ipmi/pci_ipmi_kcs.c10
-rw-r--r--hw/ipmi/smbus_ipmi.c9
-rw-r--r--hw/isa/i82378.c10
-rw-r--r--hw/isa/isa-bus.c9
-rw-r--r--hw/isa/lpc_ich9.c2
-rw-r--r--hw/isa/pc87312.c2
-rw-r--r--hw/isa/piix4.c10
-rw-r--r--hw/isa/vt82c686.c37
-rw-r--r--hw/m68k/mcf_intc.c9
-rw-r--r--hw/m68k/next-cube.c9
-rw-r--r--hw/m68k/next-kbd.c9
-rw-r--r--hw/m68k/q800.c2
-rw-r--r--hw/microblaze/xlnx-zynqmp-pmu.c10
-rw-r--r--hw/mips/boston.c9
-rw-r--r--hw/mips/fuloong2e.c5
-rw-r--r--hw/mips/gt64xxx_pci.c10
-rw-r--r--hw/mips/jazz.c2
-rw-r--r--hw/mips/malta.c9
-rw-r--r--hw/mips/trace-events2
-rw-r--r--hw/misc/applesmc.c6
-rw-r--r--hw/misc/arm_integrator_debug.c10
-rw-r--r--hw/misc/arm_l2x0.c9
-rw-r--r--hw/misc/arm_sysctl.c10
-rw-r--r--hw/misc/debugexit.c10
-rw-r--r--hw/misc/eccmemctl.c9
-rw-r--r--hw/misc/edu.c9
-rw-r--r--hw/misc/empty_slot.c9
-rw-r--r--hw/misc/exynos4210_clk.c10
-rw-r--r--hw/misc/exynos4210_pmu.c10
-rw-r--r--hw/misc/exynos4210_rng.c10
-rw-r--r--hw/misc/ivshmem.c22
-rw-r--r--hw/misc/milkymist-hpdmc.c7
-rw-r--r--hw/misc/milkymist-pfpu.c7
-rw-r--r--hw/misc/mst_fpga.c10
-rw-r--r--hw/misc/pc-testdev.c10
-rw-r--r--hw/misc/pca9552.c12
-rw-r--r--hw/misc/pci-testdev.c10
-rw-r--r--hw/misc/puv3_pm.c9
-rw-r--r--hw/misc/pvpanic.c10
-rw-r--r--hw/misc/sga.c9
-rw-r--r--hw/misc/slavio_misc.c17
-rw-r--r--hw/misc/tmp105.h9
-rw-r--r--hw/misc/tmp421.c18
-rw-r--r--hw/misc/trace-events9
-rw-r--r--hw/misc/zynq_slcr.c9
-rw-r--r--hw/net/can/can_kvaser_pci.c10
-rw-r--r--hw/net/can/can_mioe3680_pci.c10
-rw-r--r--hw/net/can/can_pcm3680_pci.c10
-rw-r--r--hw/net/dp8393x.c9
-rw-r--r--hw/net/e1000.c19
-rw-r--r--hw/net/e1000e.c9
-rw-r--r--hw/net/e1000e_core.c2
-rw-r--r--hw/net/etraxfs_eth.c11
-rw-r--r--hw/net/fsl_etsec/etsec.c2
-rw-r--r--hw/net/fsl_etsec/etsec.h10
-rw-r--r--hw/net/fsl_etsec/rings.c2
-rw-r--r--hw/net/lan9118.c9
-rw-r--r--hw/net/milkymist-minimac2.c7
-rw-r--r--hw/net/mipsnet.c9
-rw-r--r--hw/net/ne2000-isa.c9
-rw-r--r--hw/net/opencores_eth.c9
-rw-r--r--hw/net/pcnet-pci.c10
-rw-r--r--hw/net/rocker/rocker.h5
-rw-r--r--hw/net/rtl8139.c10
-rw-r--r--hw/net/smc91c111.c9
-rw-r--r--hw/net/spapr_llan.c10
-rw-r--r--hw/net/stellaris_enet.c10
-rw-r--r--hw/net/sungem.c9
-rw-r--r--hw/net/sunhme.c9
-rw-r--r--hw/net/tulip.h4
-rw-r--r--hw/net/vmxnet3.c12
-rw-r--r--hw/net/vmxnet3_defs.h9
-rw-r--r--hw/net/xgmac.c9
-rw-r--r--hw/net/xilinx_axienet.c23
-rw-r--r--hw/net/xilinx_ethlite.c5
-rw-r--r--hw/nvram/ds1225y.c9
-rw-r--r--hw/nvram/eeprom_at24c.c9
-rw-r--r--hw/nvram/spapr_nvram.c10
-rw-r--r--hw/pci-bridge/dec.c9
-rw-r--r--hw/pci-bridge/gen_pcie_root_port.c10
-rw-r--r--hw/pci-bridge/pci_bridge_dev.c7
-rw-r--r--hw/pci-bridge/pci_expander_bridge.c23
-rw-r--r--hw/pci-bridge/pcie_pci_bridge.c10
-rw-r--r--hw/pci-host/bonito.c14
-rw-r--r--hw/pci-host/grackle.c10
-rw-r--r--hw/pci-host/i440fx.c10
-rw-r--r--hw/pci-host/pnv_phb3.c5
-rw-r--r--hw/pci-host/pnv_phb4.c5
-rw-r--r--hw/pci-host/ppce500.c13
-rw-r--r--hw/pci-host/prep.c19
-rw-r--r--hw/pci-host/sabre.c8
-rw-r--r--hw/pci-host/versatile.c14
-rw-r--r--hw/ppc/e500-ccsr.h9
-rw-r--r--hw/ppc/e500.h19
-rw-r--r--hw/ppc/mac.h19
-rw-r--r--hw/ppc/mpc8544_guts.c6
-rw-r--r--hw/ppc/ppc440_pcix.c10
-rw-r--r--hw/ppc/ppc440_uc.c10
-rw-r--r--hw/ppc/ppc4xx_pci.c7
-rw-r--r--hw/ppc/ppce500_spin.c9
-rw-r--r--hw/ppc/prep_systemio.c10
-rw-r--r--hw/ppc/rs6000_mc.c12
-rw-r--r--hw/ppc/spapr_rng.c7
-rw-r--r--hw/ppc/trace-events10
-rw-r--r--hw/rdma/vmw/pvrdma.h9
-rw-r--r--hw/rtc/ds1338.c9
-rw-r--r--hw/rtc/exynos4210_rtc.c10
-rw-r--r--hw/rtc/m41t80.c9
-rw-r--r--hw/rtc/m48t59-isa.c21
-rw-r--r--hw/rtc/m48t59.c19
-rw-r--r--hw/rtc/sun4v-rtc.c9
-rw-r--r--hw/rtc/trace-events2
-rw-r--r--hw/rtc/twl92230.c9
-rw-r--r--hw/rx/rx-gdbsim.c19
-rw-r--r--hw/rx/rx62n.c12
-rw-r--r--hw/s390x/ap-device.c2
-rw-r--r--hw/s390x/ccw-device.h17
-rw-r--r--hw/s390x/ipl.h6
-rw-r--r--hw/s390x/s390-pci-bus.h34
-rw-r--r--hw/s390x/virtio-ccw.h141
-rw-r--r--hw/scsi/esp-pci.c19
-rw-r--r--hw/scsi/esp.c6
-rw-r--r--hw/scsi/lsi53c895a.c10
-rw-r--r--hw/scsi/megasas.c19
-rw-r--r--hw/scsi/mptsas.h5
-rw-r--r--hw/scsi/scsi-disk.c20
-rw-r--r--hw/scsi/spapr_vscsi.c10
-rw-r--r--hw/scsi/vmw_pvscsi.c18
-rw-r--r--hw/sd/allwinner-sdhost.c6
-rw-r--r--hw/sd/bcm2835_sdhost.c6
-rw-r--r--hw/sd/milkymist-memcard.c7
-rw-r--r--hw/sd/pl181.c9
-rw-r--r--hw/sd/pxa2xx_mmci.c5
-rw-r--r--hw/sd/sd.c2
-rw-r--r--hw/sd/sdhci.c5
-rw-r--r--hw/sd/ssi-sd.c9
-rw-r--r--hw/sh4/sh_pci.c10
-rw-r--r--hw/sparc/sun4m.c36
-rw-r--r--hw/sparc64/sun4u.c35
-rw-r--r--hw/ssi/ssi.c4
-rw-r--r--hw/ssi/xilinx_spi.c9
-rw-r--r--hw/timer/altera_timer.c10
-rw-r--r--hw/timer/arm_timer.c18
-rw-r--r--hw/timer/cadence_ttc.c10
-rw-r--r--hw/timer/etraxfs_timer.c10
-rw-r--r--hw/timer/exynos4210_mct.c10
-rw-r--r--hw/timer/exynos4210_pwm.c10
-rw-r--r--hw/timer/grlib_gptimer.c7
-rw-r--r--hw/timer/hpet.c9
-rw-r--r--hw/timer/i8254.c10
-rw-r--r--hw/timer/lm32_timer.c6
-rw-r--r--hw/timer/milkymist-sysctl.c7
-rw-r--r--hw/timer/puv3_ost.c9
-rw-r--r--hw/timer/pxa2xx_timer.c7
-rw-r--r--hw/timer/slavio_timer.c10
-rw-r--r--hw/timer/trace-events1
-rw-r--r--hw/timer/xilinx_timer.c5
-rw-r--r--hw/tpm/tpm_crb.c9
-rw-r--r--hw/tpm/tpm_spapr.c10
-rw-r--r--hw/tpm/tpm_tis_isa.c9
-rw-r--r--hw/tpm/tpm_tis_sysbus.c9
-rw-r--r--hw/tpm/trace-events2
-rw-r--r--hw/usb/ccid-card-emulated.c7
-rw-r--r--hw/usb/ccid-card-passthru.c5
-rw-r--r--hw/usb/ccid.h14
-rw-r--r--hw/usb/dev-audio.c9
-rw-r--r--hw/usb/dev-hid.c9
-rw-r--r--hw/usb/dev-hub.c9
-rw-r--r--hw/usb/dev-mtp.c4
-rw-r--r--hw/usb/dev-network.c9
-rw-r--r--hw/usb/dev-serial.c11
-rw-r--r--hw/usb/dev-smartcard-reader.c23
-rw-r--r--hw/usb/dev-storage.c9
-rw-r--r--hw/usb/dev-uas.c4
-rw-r--r--hw/usb/dev-wacom.c9
-rw-r--r--hw/usb/hcd-dwc2.h9
-rw-r--r--hw/usb/hcd-ehci.h36
-rw-r--r--hw/usb/hcd-ohci-pci.c9
-rw-r--r--hw/usb/hcd-ohci.h9
-rw-r--r--hw/usb/hcd-uhci.c4
-rw-r--r--hw/usb/hcd-xhci.h7
-rw-r--r--hw/usb/host-libusb.c9
-rw-r--r--hw/usb/redirect.c6
-rw-r--r--hw/usb/trace-events4
-rw-r--r--hw/usb/tusb6010.c13
-rw-r--r--hw/vfio/ap.c18
-rw-r--r--hw/vfio/pci.c22
-rw-r--r--hw/vfio/pci.h9
-rw-r--r--hw/vfio/trace-events10
-rw-r--r--hw/virtio/trace-events2
-rw-r--r--hw/virtio/vhost-scsi-pci.c5
-rw-r--r--hw/virtio/vhost-user-blk-pci.c5
-rw-r--r--hw/virtio/vhost-user-fs-pci.c5
-rw-r--r--hw/virtio/vhost-user-input-pci.c5
-rw-r--r--hw/virtio/vhost-user-scsi-pci.c5
-rw-r--r--hw/virtio/vhost-user-vsock-pci.c5
-rw-r--r--hw/virtio/vhost-vsock-pci.c5
-rw-r--r--hw/virtio/virtio-9p-pci.c10
-rw-r--r--hw/virtio/virtio-balloon-pci.c5
-rw-r--r--hw/virtio/virtio-blk-pci.c5
-rw-r--r--hw/virtio/virtio-crypto-pci.c5
-rw-r--r--hw/virtio/virtio-input-host-pci.c5
-rw-r--r--hw/virtio/virtio-input-pci.c9
-rw-r--r--hw/virtio/virtio-iommu-pci.c5
-rw-r--r--hw/virtio/virtio-mem-pci.h5
-rw-r--r--hw/virtio/virtio-net-pci.c5
-rw-r--r--hw/virtio/virtio-pci.h24
-rw-r--r--hw/virtio/virtio-pmem-pci.h5
-rw-r--r--hw/virtio/virtio-rng-pci.c5
-rw-r--r--hw/virtio/virtio-scsi-pci.c5
-rw-r--r--hw/virtio/virtio-serial-pci.c5
-rw-r--r--hw/watchdog/wdt_i6300esb.c5
-rw-r--r--hw/watchdog/wdt_ib700.c9
-rw-r--r--hw/xen/xen_pt.h5
-rw-r--r--include/authz/base.h15
-rw-r--r--include/authz/list.h17
-rw-r--r--include/authz/listfile.h17
-rw-r--r--include/authz/pamacct.h17
-rw-r--r--include/authz/simple.h17
-rw-r--r--include/block/block.h2
-rw-r--r--include/block/block_int.h95
-rw-r--r--include/block/throttle-groups.h4
-rw-r--r--include/chardev/char-fd.h9
-rw-r--r--include/chardev/char-win.h9
-rw-r--r--include/chardev/char.h12
-rw-r--r--include/chardev/spice.h9
-rw-r--r--include/crypto/aes.h4
-rw-r--r--include/crypto/cipher.h4
-rw-r--r--include/crypto/secret.h6
-rw-r--r--include/crypto/secret_common.h12
-rw-r--r--include/crypto/secret_keyring.h24
-rw-r--r--include/crypto/tls-cipher-suites.h9
-rw-r--r--include/crypto/tlscreds.h6
-rw-r--r--include/crypto/tlscredsanon.h7
-rw-r--r--include/crypto/tlscredspsk.h7
-rw-r--r--include/crypto/tlscredsx509.h7
-rw-r--r--include/exec/memory.h21
-rw-r--r--include/hw/acpi/acpi_dev_interface.h13
-rw-r--r--include/hw/acpi/generic_event_device.h10
-rw-r--r--include/hw/acpi/vmgenid.h13
-rw-r--r--include/hw/adc/stm32f2xx_adc.h10
-rw-r--r--include/hw/arm/allwinner-a10.h9
-rw-r--r--include/hw/arm/allwinner-h3.h8
-rw-r--r--include/hw/arm/armsse.h16
-rw-r--r--include/hw/arm/armv7m.h17
-rw-r--r--include/hw/arm/aspeed.h14
-rw-r--r--include/hw/arm/aspeed_soc.h18
-rw-r--r--include/hw/arm/bcm2835_peripherals.h10
-rw-r--r--include/hw/arm/bcm2836.h18
-rw-r--r--include/hw/arm/digic.h9
-rw-r--r--include/hw/arm/exynos4210.h10
-rw-r--r--include/hw/arm/fsl-imx25.h9
-rw-r--r--include/hw/arm/fsl-imx31.h9
-rw-r--r--include/hw/arm/fsl-imx6.h9
-rw-r--r--include/hw/arm/fsl-imx6ul.h9
-rw-r--r--include/hw/arm/fsl-imx7.h9
-rw-r--r--include/hw/arm/linux-boot-if.h11
-rw-r--r--include/hw/arm/msf2-soc.h9
-rw-r--r--include/hw/arm/nrf51_soc.h10
-rw-r--r--include/hw/arm/omap.h20
-rw-r--r--include/hw/arm/pxa.h15
-rw-r--r--include/hw/arm/smmu-common.h18
-rw-r--r--include/hw/arm/smmuv3.h18
-rw-r--r--include/hw/arm/stm32f205_soc.h10
-rw-r--r--include/hw/arm/stm32f405_soc.h10
-rw-r--r--include/hw/arm/virt.h19
-rw-r--r--include/hw/arm/xlnx-versal.h9
-rw-r--r--include/hw/arm/xlnx-zynqmp.h10
-rw-r--r--include/hw/block/flash.h13
-rw-r--r--include/hw/block/swim.h15
-rw-r--r--include/hw/boards.h8
-rw-r--r--include/hw/char/avr_usart.h10
-rw-r--r--include/hw/char/bcm2835_aux.h9
-rw-r--r--include/hw/char/cadence_uart.h10
-rw-r--r--include/hw/char/cmsdk-apb-uart.h10
-rw-r--r--include/hw/char/digic-uart.h10
-rw-r--r--include/hw/char/escc.h9
-rw-r--r--include/hw/char/ibex_uart.h10
-rw-r--r--include/hw/char/imx_serial.h9
-rw-r--r--include/hw/char/nrf51_uart.h9
-rw-r--r--include/hw/char/pl011.h9
-rw-r--r--include/hw/char/renesas_sci.h9
-rw-r--r--include/hw/char/serial.h25
-rw-r--r--include/hw/char/stm32f2xx_usart.h10
-rw-r--r--include/hw/clock.h5
-rw-r--r--include/hw/core/cpu.h10
-rw-r--r--include/hw/core/generic-loader.h10
-rw-r--r--include/hw/core/split-irq.h3
-rw-r--r--include/hw/cpu/a15mpcore.h10
-rw-r--r--include/hw/cpu/a9mpcore.h10
-rw-r--r--include/hw/cpu/arm11mpcore.h10
-rw-r--r--include/hw/cpu/cluster.h10
-rw-r--r--include/hw/cpu/core.h10
-rw-r--r--include/hw/display/bcm2835_fb.h9
-rw-r--r--include/hw/display/dpcd.h4
-rw-r--r--include/hw/display/i2c-ddc.h4
-rw-r--r--include/hw/display/macfb.h30
-rw-r--r--include/hw/display/xlnx_dp.h9
-rw-r--r--include/hw/dma/bcm2835_dma.h10
-rw-r--r--include/hw/dma/i8257.h10
-rw-r--r--include/hw/dma/pl080.h9
-rw-r--r--include/hw/dma/xlnx-zdma.h10
-rw-r--r--include/hw/dma/xlnx-zynq-devcfg.h10
-rw-r--r--include/hw/dma/xlnx_dpdma.h4
-rw-r--r--include/hw/fw-path-provider.h11
-rw-r--r--include/hw/gpio/aspeed_gpio.h18
-rw-r--r--include/hw/gpio/bcm2835_gpio.h10
-rw-r--r--include/hw/gpio/imx_gpio.h9
-rw-r--r--include/hw/gpio/nrf51_gpio.h9
-rw-r--r--include/hw/hotplug.h11
-rw-r--r--include/hw/hyperv/vmbus-bridge.h9
-rw-r--r--include/hw/hyperv/vmbus.h17
-rw-r--r--include/hw/i2c/arm_sbcon_i2c.h10
-rw-r--r--include/hw/i2c/aspeed_i2c.h19
-rw-r--r--include/hw/i2c/i2c.h19
-rw-r--r--include/hw/i2c/imx_i2c.h9
-rw-r--r--include/hw/i2c/microbit_i2c.h10
-rw-r--r--include/hw/i2c/ppc4xx_i2c.h9
-rw-r--r--include/hw/i2c/smbus_slave.h15
-rw-r--r--include/hw/i386/apic_internal.h17
-rw-r--r--include/hw/i386/ich9.h10
-rw-r--r--include/hw/i386/intel_iommu.h7
-rw-r--r--include/hw/i386/ioapic_internal.h16
-rw-r--r--include/hw/i386/microvm.h19
-rw-r--r--include/hw/i386/pc.h14
-rw-r--r--include/hw/i386/x86-iommu.h13
-rw-r--r--include/hw/i386/x86.h19
-rw-r--r--include/hw/ide/ahci.h22
-rw-r--r--include/hw/ide/internal.h19
-rw-r--r--include/hw/ide/pci.h9
-rw-r--r--include/hw/input/adb.h16
-rw-r--r--include/hw/input/i8042.h6
-rw-r--r--include/hw/intc/allwinner-a10-pic.h9
-rw-r--r--include/hw/intc/arm_gic.h15
-rw-r--r--include/hw/intc/arm_gic_common.h21
-rw-r--r--include/hw/intc/arm_gicv3.h14
-rw-r--r--include/hw/intc/arm_gicv3_common.h16
-rw-r--r--include/hw/intc/arm_gicv3_its_common.h11
-rw-r--r--include/hw/intc/armv7m_nvic.h10
-rw-r--r--include/hw/intc/aspeed_vic.h9
-rw-r--r--include/hw/intc/bcm2835_ic.h9
-rw-r--r--include/hw/intc/bcm2836_control.h10
-rw-r--r--include/hw/intc/heathrow_pic.h9
-rw-r--r--include/hw/intc/ibex_plic.h10
-rw-r--r--include/hw/intc/imx_avic.h9
-rw-r--r--include/hw/intc/imx_gpcv2.h9
-rw-r--r--include/hw/intc/intc.h11
-rw-r--r--include/hw/intc/mips_gic.h6
-rw-r--r--include/hw/intc/realview_gic.h10
-rw-r--r--include/hw/intc/rx_icu.h4
-rw-r--r--include/hw/intc/xlnx-pmu-iomod-intc.h10
-rw-r--r--include/hw/intc/xlnx-zynqmp-ipi.h10
-rw-r--r--include/hw/ipack/ipack.h14
-rw-r--r--include/hw/ipmi/ipmi.h36
-rw-r--r--include/hw/isa/i8259_internal.h15
-rw-r--r--include/hw/isa/isa.h28
-rw-r--r--include/hw/isa/pc87312.h11
-rw-r--r--include/hw/isa/superio.h19
-rw-r--r--include/hw/m68k/mcf_fec.h4
-rw-r--r--include/hw/mem/memory-device.h11
-rw-r--r--include/hw/mem/nvdimm.h11
-rw-r--r--include/hw/mem/pc-dimm.h17
-rw-r--r--include/hw/mips/cps.h9
-rw-r--r--include/hw/misc/a9scu.h9
-rw-r--r--include/hw/misc/allwinner-cpucfg.h9
-rw-r--r--include/hw/misc/allwinner-h3-ccu.h9
-rw-r--r--include/hw/misc/allwinner-h3-dramc.h9
-rw-r--r--include/hw/misc/allwinner-h3-sysctrl.h9
-rw-r--r--include/hw/misc/allwinner-sid.h9
-rw-r--r--include/hw/misc/arm11scu.h9
-rw-r--r--include/hw/misc/armsse-cpuid.h9
-rw-r--r--include/hw/misc/armsse-mhu.h9
-rw-r--r--include/hw/misc/aspeed_scu.h18
-rw-r--r--include/hw/misc/aspeed_sdmc.h18
-rw-r--r--include/hw/misc/aspeed_xdma.h9
-rw-r--r--include/hw/misc/auxbus.h11
-rw-r--r--include/hw/misc/avr_power.h9
-rw-r--r--include/hw/misc/bcm2835_mbox.h10
-rw-r--r--include/hw/misc/bcm2835_mphi.h5
-rw-r--r--include/hw/misc/bcm2835_property.h10
-rw-r--r--include/hw/misc/bcm2835_rng.h10
-rw-r--r--include/hw/misc/bcm2835_thermal.h10
-rw-r--r--include/hw/misc/grlib_ahb_apb_pnp.h9
-rw-r--r--include/hw/misc/imx25_ccm.h9
-rw-r--r--include/hw/misc/imx31_ccm.h9
-rw-r--r--include/hw/misc/imx6_ccm.h9
-rw-r--r--include/hw/misc/imx6_src.h9
-rw-r--r--include/hw/misc/imx6ul_ccm.h9
-rw-r--r--include/hw/misc/imx7_ccm.h17
-rw-r--r--include/hw/misc/imx7_gpr.h9
-rw-r--r--include/hw/misc/imx7_snvs.h9
-rw-r--r--include/hw/misc/imx_ccm.h19
-rw-r--r--include/hw/misc/imx_rngc.h9
-rw-r--r--include/hw/misc/iotkit-secctl.h6
-rw-r--r--include/hw/misc/iotkit-sysctl.h10
-rw-r--r--include/hw/misc/iotkit-sysinfo.h10
-rw-r--r--include/hw/misc/mac_via.h27
-rw-r--r--include/hw/misc/macio/cuda.h18
-rw-r--r--include/hw/misc/macio/gpio.h9
-rw-r--r--include/hw/misc/macio/macio.h43
-rw-r--r--include/hw/misc/macio/pmu.h18
-rw-r--r--include/hw/misc/max111x.h10
-rw-r--r--include/hw/misc/mips_cmgcr.h6
-rw-r--r--include/hw/misc/mips_cpc.h9
-rw-r--r--include/hw/misc/mips_itu.h9
-rw-r--r--include/hw/misc/mos6522.h18
-rw-r--r--include/hw/misc/mps2-fpgaio.h9
-rw-r--r--include/hw/misc/mps2-scc.h9
-rw-r--r--include/hw/misc/msf2-sysreg.h9
-rw-r--r--include/hw/misc/nrf51_rng.h9
-rw-r--r--include/hw/misc/pca9552.h9
-rw-r--r--include/hw/misc/stm32f2xx_syscfg.h10
-rw-r--r--include/hw/misc/stm32f4xx_exti.h10
-rw-r--r--include/hw/misc/stm32f4xx_syscfg.h10
-rw-r--r--include/hw/misc/tz-mpc.h6
-rw-r--r--include/hw/misc/tz-msc.h9
-rw-r--r--include/hw/misc/tz-ppc.h6
-rw-r--r--include/hw/misc/unimp.h10
-rw-r--r--include/hw/misc/vmcoreinfo.h9
-rw-r--r--include/hw/misc/zynq-xadc.h10
-rw-r--r--include/hw/net/allwinner-sun8i-emac.h9
-rw-r--r--include/hw/net/allwinner_emac.h9
-rw-r--r--include/hw/net/cadence_gem.h9
-rw-r--r--include/hw/net/ftgmac100.h17
-rw-r--r--include/hw/net/imx_fec.h9
-rw-r--r--include/hw/net/lance.h10
-rw-r--r--include/hw/net/lasi_82596.h10
-rw-r--r--include/hw/net/msf2-emac.h10
-rw-r--r--include/hw/nmi.h11
-rw-r--r--include/hw/nubus/mac-nubus-bridge.h10
-rw-r--r--include/hw/nubus/nubus.h18
-rw-r--r--include/hw/nvram/fw_cfg.h21
-rw-r--r--include/hw/nvram/nrf51_nvm.h9
-rw-r--r--include/hw/or-irq.h3
-rw-r--r--include/hw/pci-bridge/simba.h10
-rw-r--r--include/hw/pci-host/designware.h16
-rw-r--r--include/hw/pci-host/gpex.h19
-rw-r--r--include/hw/pci-host/i440fx.h10
-rw-r--r--include/hw/pci-host/pnv_phb3.h20
-rw-r--r--include/hw/pci-host/pnv_phb4.h21
-rw-r--r--include/hw/pci-host/q35.h19
-rw-r--r--include/hw/pci-host/sabre.h19
-rw-r--r--include/hw/pci-host/spapr.h7
-rw-r--r--include/hw/pci-host/uninorth.h31
-rw-r--r--include/hw/pci-host/xilinx-pcie.h19
-rw-r--r--include/hw/pci/pci.h19
-rw-r--r--include/hw/pci/pci_bridge.h4
-rw-r--r--include/hw/pci/pci_host.h14
-rw-r--r--include/hw/pci/pcie_host.h5
-rw-r--r--include/hw/pci/pcie_port.h18
-rw-r--r--include/hw/pcmcia.h19
-rw-r--r--include/hw/platform-bus.h5
-rw-r--r--include/hw/ppc/mac_dbdma.h9
-rw-r--r--include/hw/ppc/openpic.h9
-rw-r--r--include/hw/ppc/pnv.h75
-rw-r--r--include/hw/ppc/pnv_core.h26
-rw-r--r--include/hw/ppc/pnv_homer.h22
-rw-r--r--include/hw/ppc/pnv_lpc.h28
-rw-r--r--include/hw/ppc/pnv_occ.h22
-rw-r--r--include/hw/ppc/pnv_pnor.h9
-rw-r--r--include/hw/ppc/pnv_psi.h35
-rw-r--r--include/hw/ppc/pnv_xive.h16
-rw-r--r--include/hw/ppc/pnv_xscom.h10
-rw-r--r--include/hw/ppc/spapr.h23
-rw-r--r--include/hw/ppc/spapr_cpu_core.h17
-rw-r--r--include/hw/ppc/spapr_irq.h12
-rw-r--r--include/hw/ppc/spapr_tpm_proxy.h9
-rw-r--r--include/hw/ppc/spapr_vio.h19
-rw-r--r--include/hw/ppc/xics.h31
-rw-r--r--include/hw/ppc/xics_spapr.h5
-rw-r--r--include/hw/ppc/xive.h77
-rw-r--r--include/hw/qdev-core.h15
-rw-r--r--include/hw/rdma/rdma.h11
-rw-r--r--include/hw/register.h4
-rw-r--r--include/hw/resettable.h11
-rw-r--r--include/hw/riscv/opentitan.h10
-rw-r--r--include/hw/riscv/riscv_hart.h10
-rw-r--r--include/hw/riscv/spike.h10
-rw-r--r--include/hw/riscv/virt.h10
-rw-r--r--include/hw/rtc/allwinner-rtc.h18
-rw-r--r--include/hw/rtc/aspeed_rtc.h9
-rw-r--r--include/hw/rtc/goldfish_rtc.h10
-rw-r--r--include/hw/rtc/m48t59.h11
-rw-r--r--include/hw/rtc/mc146818rtc.h9
-rw-r--r--include/hw/rtc/pl031.h9
-rw-r--r--include/hw/rtc/xlnx-zynqmp-rtc.h10
-rw-r--r--include/hw/rx/rx62n.h9
-rw-r--r--include/hw/s390x/3270-ccw.h19
-rw-r--r--include/hw/s390x/ap-device.h12
-rw-r--r--include/hw/s390x/css-bridge.h18
-rw-r--r--include/hw/s390x/event-facility.h34
-rw-r--r--include/hw/s390x/s390-ccw.h19
-rw-r--r--include/hw/s390x/s390-virtio-ccw.h17
-rw-r--r--include/hw/s390x/s390_flic.h30
-rw-r--r--include/hw/s390x/sclp.h14
-rw-r--r--include/hw/s390x/storage-attributes.h37
-rw-r--r--include/hw/s390x/storage-keys.h28
-rw-r--r--include/hw/s390x/tod.h18
-rw-r--r--include/hw/s390x/vfio-ccw.h7
-rw-r--r--include/hw/scsi/esp.h9
-rw-r--r--include/hw/scsi/scsi.h19
-rw-r--r--include/hw/sd/allwinner-sdhost.h18
-rw-r--r--include/hw/sd/aspeed_sdhci.h10
-rw-r--r--include/hw/sd/bcm2835_sdhost.h10
-rw-r--r--include/hw/sd/sd.h23
-rw-r--r--include/hw/sd/sdhci.h13
-rw-r--r--include/hw/southbridge/piix.h10
-rw-r--r--include/hw/sparc/sparc32_dma.h34
-rw-r--r--include/hw/sparc/sun4m_iommu.h9
-rw-r--r--include/hw/sparc/sun4u_iommu.h9
-rw-r--r--include/hw/ssi/aspeed_smc.h18
-rw-r--r--include/hw/ssi/imx_spi.h9
-rw-r--r--include/hw/ssi/mss-spi.h9
-rw-r--r--include/hw/ssi/pl022.h9
-rw-r--r--include/hw/ssi/ssi.h11
-rw-r--r--include/hw/ssi/stm32f2xx_spi.h10
-rw-r--r--include/hw/ssi/xilinx_spips.h32
-rw-r--r--include/hw/stream.h11
-rw-r--r--include/hw/sysbus.h17
-rw-r--r--include/hw/timer/a9gtimer.h6
-rw-r--r--include/hw/timer/allwinner-a10-pit.h6
-rw-r--r--include/hw/timer/arm_mptimer.h10
-rw-r--r--include/hw/timer/armv7m_systick.h9
-rw-r--r--include/hw/timer/aspeed_timer.h19
-rw-r--r--include/hw/timer/avr_timer16.h10
-rw-r--r--include/hw/timer/bcm2835_systmr.h10
-rw-r--r--include/hw/timer/cmsdk-apb-dualtimer.h7
-rw-r--r--include/hw/timer/cmsdk-apb-timer.h10
-rw-r--r--include/hw/timer/digic-timer.h9
-rw-r--r--include/hw/timer/i8254.h9
-rw-r--r--include/hw/timer/imx_epit.h9
-rw-r--r--include/hw/timer/imx_gpt.h9
-rw-r--r--include/hw/timer/mss-timer.h10
-rw-r--r--include/hw/timer/nrf51_timer.h9
-rw-r--r--include/hw/timer/renesas_cmt.h9
-rw-r--r--include/hw/timer/renesas_tmr.h9
-rw-r--r--include/hw/timer/stm32f2xx_timer.h10
-rw-r--r--include/hw/usb.h17
-rw-r--r--include/hw/usb/chipidea.h9
-rw-r--r--include/hw/usb/imx-usb-phy.h9
-rw-r--r--include/hw/vfio/vfio-amd-xgbe.h11
-rw-r--r--include/hw/vfio/vfio-calxeda-xgmac.h21
-rw-r--r--include/hw/vfio/vfio-platform.h19
-rw-r--r--include/hw/virtio/vhost-scsi-common.h10
-rw-r--r--include/hw/virtio/vhost-scsi.h10
-rw-r--r--include/hw/virtio/vhost-user-blk.h10
-rw-r--r--include/hw/virtio/vhost-user-fs.h10
-rw-r--r--include/hw/virtio/vhost-user-scsi.h10
-rw-r--r--include/hw/virtio/vhost-user-vsock.h10
-rw-r--r--include/hw/virtio/vhost-vsock-common.h10
-rw-r--r--include/hw/virtio/vhost-vsock.h10
-rw-r--r--include/hw/virtio/virtio-balloon.h10
-rw-r--r--include/hw/virtio/virtio-blk.h10
-rw-r--r--include/hw/virtio/virtio-bus.h15
-rw-r--r--include/hw/virtio/virtio-crypto.h10
-rw-r--r--include/hw/virtio/virtio-gpu-pci.h5
-rw-r--r--include/hw/virtio/virtio-gpu.h35
-rw-r--r--include/hw/virtio/virtio-input.h29
-rw-r--r--include/hw/virtio/virtio-iommu.h10
-rw-r--r--include/hw/virtio/virtio-mem.h17
-rw-r--r--include/hw/virtio/virtio-mmio.h19
-rw-r--r--include/hw/virtio/virtio-net.h7
-rw-r--r--include/hw/virtio/virtio-pmem.h17
-rw-r--r--include/hw/virtio/virtio-rng.h10
-rw-r--r--include/hw/virtio/virtio-scsi.h19
-rw-r--r--include/hw/virtio/virtio-serial.h22
-rw-r--r--include/hw/virtio/virtio.h14
-rw-r--r--include/hw/vmstate-if.h11
-rw-r--r--include/hw/watchdog/cmsdk-apb-watchdog.h10
-rw-r--r--include/hw/watchdog/wdt_aspeed.h19
-rw-r--r--include/hw/watchdog/wdt_diag288.h19
-rw-r--r--include/hw/watchdog/wdt_imx2.h9
-rw-r--r--include/hw/xen/xen-block.h39
-rw-r--r--include/hw/xen/xen-bus.h37
-rw-r--r--include/hw/xen/xen-legacy-backend.h5
-rw-r--r--include/io/channel-buffer.h7
-rw-r--r--include/io/channel-command.h7
-rw-r--r--include/io/channel-file.h7
-rw-r--r--include/io/channel-socket.h7
-rw-r--r--include/io/channel-tls.h7
-rw-r--r--include/io/channel-websock.h7
-rw-r--r--include/io/channel.h12
-rw-r--r--include/io/dns-resolver.h13
-rw-r--r--include/io/net-listener.h14
-rw-r--r--include/net/can_emu.h4
-rw-r--r--include/net/can_host.h21
-rw-r--r--include/net/filter.h13
-rw-r--r--include/qemu-common.h3
-rw-r--r--include/qom/object.h327
-rw-r--r--include/qom/object_interfaces.h13
-rw-r--r--include/scsi/pr-manager.h16
-rw-r--r--include/sysemu/cryptodev.h16
-rw-r--r--include/sysemu/hostmem.h10
-rw-r--r--include/sysemu/hvf.h5
-rw-r--r--include/sysemu/iothread.h9
-rw-r--r--include/sysemu/kvm.h5
-rw-r--r--include/sysemu/rng-random.h5
-rw-r--r--include/sysemu/rng.h10
-rw-r--r--include/sysemu/tpm.h11
-rw-r--r--include/sysemu/tpm_backend.h12
-rw-r--r--include/sysemu/vhost-user-backend.h17
-rw-r--r--include/ui/console.h10
-rw-r--r--iothread.c6
-rw-r--r--meson.build5
-rw-r--r--migration/block-dirty-bitmap.c8
-rw-r--r--migration/migration.h14
-rw-r--r--migration/rdma.c7
-rw-r--r--migration/trace-events37
-rw-r--r--nbd/server.c6
-rw-r--r--net/can/can_socketcan.c10
-rw-r--r--net/colo-compare.c45
-rw-r--r--net/dump.c7
-rw-r--r--net/filter-buffer.c9
-rw-r--r--net/filter-mirror.c17
-rw-r--r--net/filter-replay.c7
-rw-r--r--net/filter-rewriter.c37
-rw-r--r--net/net.c2
-rw-r--r--net/trace-events2
-rw-r--r--qapi/block-core.json58
-rw-r--r--qemu-img.c43
-rw-r--r--qom/object.c6
-rwxr-xr-xscripts/cleanup-trace-events.pl23
-rw-r--r--scripts/codeconverter/codeconverter/__init__.py0
-rw-r--r--scripts/codeconverter/codeconverter/patching.py397
-rw-r--r--scripts/codeconverter/codeconverter/qom_macros.py652
-rw-r--r--scripts/codeconverter/codeconverter/qom_type_info.py434
-rw-r--r--scripts/codeconverter/codeconverter/regexps.py118
-rw-r--r--scripts/codeconverter/codeconverter/test_patching.py105
-rw-r--r--scripts/codeconverter/codeconverter/test_regexps.py282
-rw-r--r--scripts/codeconverter/codeconverter/utils.py72
-rwxr-xr-xscripts/codeconverter/converter.py123
-rw-r--r--scripts/tracetool/format/d.py15
-rw-r--r--scripts/tracetool/vcpu.py2
-rw-r--r--scsi/pr-manager-helper.c11
-rw-r--r--softmmu/balloon.c2
-rw-r--r--softmmu/ioport.c2
-rw-r--r--softmmu/memory.c2
-rw-r--r--softmmu/trace-events28
-rw-r--r--softmmu/trace.h1
-rw-r--r--softmmu/vl.c2
-rw-r--r--target/alpha/cpu-qom.h14
-rw-r--r--target/arm/cpu-qom.h25
-rw-r--r--target/arm/idau.h11
-rw-r--r--target/avr/cpu-qom.h14
-rw-r--r--target/cris/cpu-qom.h14
-rw-r--r--target/hppa/cpu-qom.h14
-rw-r--r--target/i386/cpu-qom.h14
-rw-r--r--target/i386/kvm.c5
-rw-r--r--target/i386/sev.c7
-rw-r--r--target/lm32/cpu-qom.h14
-rw-r--r--target/m68k/cpu-qom.h14
-rw-r--r--target/microblaze/cpu-qom.h14
-rw-r--r--target/mips/cpu-qom.h14
-rw-r--r--target/mips/translate.c12
-rw-r--r--target/moxie/cpu.h17
-rw-r--r--target/nios2/cpu.h17
-rw-r--r--target/openrisc/cpu.h17
-rw-r--r--target/ppc/cpu-qom.h14
-rw-r--r--target/ppc/cpu.h11
-rw-r--r--target/ppc/trace-events1
-rw-r--r--target/riscv/cpu.h17
-rw-r--r--target/riscv/trace-events2
-rw-r--r--target/rx/cpu-qom.h14
-rw-r--r--target/s390x/cpu-qom.h14
-rw-r--r--target/sh4/cpu-qom.h14
-rw-r--r--target/sparc/cpu-qom.h14
-rw-r--r--target/tilegx/cpu.h17
-rw-r--r--target/tricore/cpu-qom.h14
-rw-r--r--target/unicore32/cpu-qom.h14
-rw-r--r--target/xtensa/cpu-qom.h14
-rw-r--r--tests/Makefile.include4
-rw-r--r--tests/acceptance/avocado_qemu/__init__.py12
-rw-r--r--tests/benchmark-crypto-cipher.c12
-rw-r--r--tests/benchmark-crypto-hash.c4
-rw-r--r--tests/benchmark-crypto-hmac.c7
-rw-r--r--tests/check-qom-interface.c11
-rw-r--r--tests/check-qom-proplist.c16
-rw-r--r--tests/meson.build3
-rw-r--r--tests/plugin/meson.build4
-rwxr-xr-xtests/qemu-iotests/02044
-rw-r--r--tests/qemu-iotests/020.out10
-rwxr-xr-xtests/qemu-iotests/040238
-rw-r--r--tests/qemu-iotests/040.out4
-rwxr-xr-xtests/qemu-iotests/041146
-rw-r--r--tests/qemu-iotests/041.out4
-rwxr-xr-xtests/qemu-iotests/0494
-rw-r--r--tests/qemu-iotests/049.out5
-rw-r--r--tests/qemu-iotests/153.out2
-rwxr-xr-xtests/qemu-iotests/1843
-rw-r--r--tests/qemu-iotests/184.out14
-rw-r--r--tests/qemu-iotests/204.out1
-rwxr-xr-xtests/qemu-iotests/2286
-rw-r--r--tests/qemu-iotests/228.out6
-rwxr-xr-xtests/qemu-iotests/24449
-rw-r--r--tests/qemu-iotests/244.out7
-rwxr-xr-xtests/qemu-iotests/2454
-rw-r--r--tests/qemu-iotests/273.out4
-rwxr-xr-xtests/qemu-iotests/check2
-rw-r--r--tests/qemu-iotests/iotests.py10
-rw-r--r--tests/requirements.txt2
-rw-r--r--tests/tcg/Makefile.target3
-rw-r--r--tests/test-qdev-global-props.c13
-rw-r--r--tests/test-vmstate.c3
-rw-r--r--trace-events32
-rw-r--r--ui/console.c9
-rw-r--r--ui/gtk.c8
-rw-r--r--ui/input-barrier.c14
-rw-r--r--ui/input-linux.c14
-rw-r--r--ui/spice-app.c9
-rw-r--r--ui/trace-events6
-rw-r--r--util/hexdump.c4
-rw-r--r--util/iov.c2
-rw-r--r--util/trace-events4
959 files changed, 11610 insertions, 6840 deletions
diff --git a/.travis.yml b/.travis.yml
index 1d0ade0a13..65341634d0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -138,7 +138,7 @@ jobs:
 
 
     # Just build tools and run minimal unit and softfloat checks
-    - name: "GCC check-softfloat (user)"
+    - name: "GCC check-unit and check-softfloat"
       env:
         - BASE_CONFIG="--enable-tools"
         - CONFIG="--disable-user --disable-system"
diff --git a/CODING_STYLE.rst b/CODING_STYLE.rst
index 427699e0e4..8b13ef0669 100644
--- a/CODING_STYLE.rst
+++ b/CODING_STYLE.rst
@@ -109,8 +109,41 @@ names are lower_case_with_underscores_ending_with_a_t, like the POSIX
 uint64_t and family.  Note that this last convention contradicts POSIX
 and is therefore likely to be changed.
 
-When wrapping standard library functions, use the prefix ``qemu_`` to alert
-readers that they are seeing a wrapped version; otherwise avoid this prefix.
+Variable Naming Conventions
+---------------------------
+
+A number of short naming conventions exist for variables that use
+common QEMU types. For example, the architecture independent CPUState
+is often held as a ``cs`` pointer variable, whereas the concrete
+CPUArchState is usually held in a pointer called ``env``.
+
+Likewise, in device emulation code the common DeviceState is usually
+called ``dev``.
+
+Function Naming Conventions
+---------------------------
+
+Wrapped version of standard library or GLib functions use a ``qemu_``
+prefix to alert readers that they are seeing a wrapped version, for
+example ``qemu_strtol`` or ``qemu_mutex_lock``.  Other utility functions
+that are widely called from across the codebase should not have any
+prefix, for example ``pstrcpy`` or bit manipulation functions such as
+``find_first_bit``.
+
+The ``qemu_`` prefix is also used for functions that modify global
+emulator state, for example ``qemu_add_vm_change_state_handler``.
+However, if there is an obvious subsystem-specific prefix it should be
+used instead.
+
+Public functions from a file or subsystem (declared in headers) tend
+to have a consistent prefix to show where they came from. For example,
+``tlb_`` for functions from ``cputlb.c`` or ``cpu_`` for functions
+from cpus.c.
+
+If there are two versions of a function to be called with or without a
+lock held, the function that expects the lock to be already held
+usually uses the suffix ``_locked``.
+
 
 Block structure
 ===============
diff --git a/Kconfig.host b/Kconfig.host
index a6d871c399..4af19bf70e 100644
--- a/Kconfig.host
+++ b/Kconfig.host
@@ -1,6 +1,6 @@
 # These are "proxy" symbols used to pass config-host.mak values
-# down to Kconfig.  See also MINIKCONF_ARGS in the Makefile:
-# these two need to be kept in sync.
+# down to Kconfig.  See also kconfig_external_symbols in
+# meson.build: these two need to be kept in sync.
 
 config LINUX
     bool
diff --git a/MAINTAINERS b/MAINTAINERS
index d17b08fad9..d817ee6c6f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2432,6 +2432,11 @@ F: tests/check-qom-interface.c
 F: tests/check-qom-proplist.c
 F: tests/test-qdev-global-props.c
 
+QOM boilerplate conversion script
+M: Eduardo Habkost <ehabkost@redhat.com>
+S: Maintained
+F: scripts/codeconverter/
+
 QMP
 M: Markus Armbruster <armbru@redhat.com>
 S: Supported
@@ -2754,7 +2759,8 @@ M: Alex Bennée <alex.bennee@linaro.org>
 S: Maintained
 F: docs/devel/tcg-plugins.rst
 F: plugins/
-F: tests/plugin
+F: tests/plugin/
+F: contrib/plugins/
 
 AArch64 TCG target
 M: Richard Henderson <richard.henderson@linaro.org>
diff --git a/Makefile b/Makefile
index d6c5c9fdef..57f72f56c6 100644
--- a/Makefile
+++ b/Makefile
@@ -106,6 +106,12 @@ config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/pc-bios $(SRC_PATH)/VERSION
 # Force configure to re-run if the API symbols are updated
 ifeq ($(CONFIG_PLUGIN),y)
 config-host.mak: $(SRC_PATH)/plugins/qemu-plugins.symbols
+
+.PHONY: plugins
+plugins:
+	$(call quiet-command,\
+		$(MAKE) $(SUBDIR_MAKEFLAGS) -C contrib/plugins V="$(V)", \
+		"BUILD", "example plugins")
 endif
 
 else
@@ -128,7 +134,7 @@ build.ninja: config-host.mak
 Makefile: ;
 configure: ;
 
-.PHONY: all clean cscope distclean install \
+.PHONY: all clean distclean install \
 	recurse-all dist msi FORCE
 
 SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory --quiet)
@@ -221,20 +227,22 @@ distclean: clean ninja-distclean
 	rm -f linux-headers/asm
 	rm -Rf .sdk
 
+find-src-path = find "$(SRC_PATH)/" -path "$(SRC_PATH)/meson" -prune -o -name "*.[chsS]"
+
 .PHONY: ctags
 ctags:
 	rm -f tags
-	find "$(SRC_PATH)" -name '*.[hc]' -exec ctags --append {} +
+	$(find-src-path) -exec ctags --append {} +
 
 .PHONY: TAGS
 TAGS:
 	rm -f TAGS
-	find "$(SRC_PATH)" -name '*.[hc]' -exec etags --append {} +
+	$(find-src-path) -exec etags --append {} +
 
 .PHONY: cscope
 cscope:
 	rm -f "$(SRC_PATH)"/cscope.*
-	find "$(SRC_PATH)/" -name "*.[chsS]" -print | sed -e 's,^\./,,' > "$(SRC_PATH)/cscope.files"
+	$(find-src-path) -print | sed -e 's,^\./,,' > "$(SRC_PATH)/cscope.files"
 	cscope -b -i"$(SRC_PATH)/cscope.files"
 
 # Needed by "meson install"
@@ -256,6 +264,11 @@ help:
 	$(call print-help,cscope,Generate cscope index)
 	$(call print-help,sparse,Run sparse on the QEMU source)
 	@echo  ''
+ifeq ($(CONFIG_PLUGIN),y)
+	@echo  'Plugin targets:'
+	$(call print-help,plugins,Build the example TCG plugins)
+	@echo  ''
+endif
 	@echo  'Cleaning targets:'
 	$(call print-help,clean,Remove most generated files but keep the config)
 	$(call print-help,distclean,Remove all generated files)
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c
index eace2c113b..7098ad96c3 100644
--- a/accel/tcg/tcg-all.c
+++ b/accel/tcg/tcg-all.c
@@ -36,17 +36,18 @@
 #include "hw/boards.h"
 #include "qapi/qapi-builtin-visit.h"
 
-typedef struct TCGState {
+struct TCGState {
     AccelState parent_obj;
 
     bool mttcg_enabled;
     unsigned long tb_size;
-} TCGState;
+};
+typedef struct TCGState TCGState;
 
 #define TYPE_TCG_ACCEL ACCEL_CLASS_NAME("tcg")
 
-#define TCG_STATE(obj) \
-        OBJECT_CHECK(TCGState, (obj), TYPE_TCG_ACCEL)
+DECLARE_INSTANCE_CHECKER(TCGState, TCG_STATE,
+                         TYPE_TCG_ACCEL)
 
 /* mask must never be zero, except for A20 change call */
 static void tcg_handle_interrupt(CPUState *cpu, int mask)
diff --git a/audio/trace-events b/audio/trace-events
index a1d1eccb8a..6aec535763 100644
--- a/audio/trace-events
+++ b/audio/trace-events
@@ -9,12 +9,9 @@ alsa_read_zero(long len) "Failed to read %ld frames (read zero)"
 alsa_xrun_out(void) "Recovering from playback xrun"
 alsa_xrun_in(void) "Recovering from capture xrun"
 alsa_resume_out(void) "Resuming suspended output stream"
-alsa_resume_in(void) "Resuming suspended input stream"
-alsa_no_frames(int state) "No frames available and ALSA state is %d"
 
 # ossaudio.c
 oss_version(int version) "OSS version = 0x%x"
-oss_invalid_available_size(int size, int bufsize) "Invalid available size, size=%d bufsize=%d"
 
 # audio.c
 audio_timer_start(int interval) "interval %d ms"
diff --git a/backends/cryptodev-builtin.c b/backends/cryptodev-builtin.c
index 14316333fe..f047ad0362 100644
--- a/backends/cryptodev-builtin.c
+++ b/backends/cryptodev-builtin.c
@@ -26,6 +26,7 @@
 #include "qapi/error.h"
 #include "standard-headers/linux/virtio_crypto.h"
 #include "crypto/cipher.h"
+#include "qom/object.h"
 
 
 /**
@@ -34,12 +35,11 @@
  */
 #define TYPE_CRYPTODEV_BACKEND_BUILTIN "cryptodev-backend-builtin"
 
-#define CRYPTODEV_BACKEND_BUILTIN(obj) \
-    OBJECT_CHECK(CryptoDevBackendBuiltin, \
-                 (obj), TYPE_CRYPTODEV_BACKEND_BUILTIN)
-
 typedef struct CryptoDevBackendBuiltin
                          CryptoDevBackendBuiltin;
+DECLARE_INSTANCE_CHECKER(CryptoDevBackendBuiltin, CRYPTODEV_BACKEND_BUILTIN,
+                         TYPE_CRYPTODEV_BACKEND_BUILTIN)
+
 
 typedef struct CryptoDevBackendBuiltinSession {
     QCryptoCipher *cipher;
diff --git a/backends/cryptodev-vhost-user.c b/backends/cryptodev-vhost-user.c
index dbe5a8aae6..41089dede1 100644
--- a/backends/cryptodev-vhost-user.c
+++ b/backends/cryptodev-vhost-user.c
@@ -30,6 +30,7 @@
 #include "sysemu/cryptodev-vhost.h"
 #include "chardev/char-fe.h"
 #include "sysemu/cryptodev-vhost-user.h"
+#include "qom/object.h"
 
 
 /**
@@ -38,12 +39,12 @@
  */
 #define TYPE_CRYPTODEV_BACKEND_VHOST_USER "cryptodev-vhost-user"
 
-#define CRYPTODEV_BACKEND_VHOST_USER(obj) \
-    OBJECT_CHECK(CryptoDevBackendVhostUser, \
-                 (obj), TYPE_CRYPTODEV_BACKEND_VHOST_USER)
+typedef struct CryptoDevBackendVhostUser CryptoDevBackendVhostUser;
+DECLARE_INSTANCE_CHECKER(CryptoDevBackendVhostUser, CRYPTODEV_BACKEND_VHOST_USER,
+                         TYPE_CRYPTODEV_BACKEND_VHOST_USER)
 
 
-typedef struct CryptoDevBackendVhostUser {
+struct CryptoDevBackendVhostUser {
     CryptoDevBackend parent_obj;
 
     VhostUserState vhost_user;
@@ -51,7 +52,7 @@ typedef struct CryptoDevBackendVhostUser {
     char *chr_name;
     bool opened;
     CryptoDevBackendVhost *vhost_crypto[MAX_CRYPTO_QUEUE_NUM];
-} CryptoDevBackendVhostUser;
+};
 
 static int
 cryptodev_vhost_user_running(
diff --git a/backends/dbus-vmstate.c b/backends/dbus-vmstate.c
index 56361a6272..a13461edea 100644
--- a/backends/dbus-vmstate.c
+++ b/backends/dbus-vmstate.c
@@ -19,21 +19,13 @@
 #include "qapi/qmp/qerror.h"
 #include "migration/vmstate.h"
 #include "trace.h"
+#include "qom/object.h"
 
-typedef struct DBusVMState DBusVMState;
-typedef struct DBusVMStateClass DBusVMStateClass;
 
 #define TYPE_DBUS_VMSTATE "dbus-vmstate"
-#define DBUS_VMSTATE(obj)                                \
-    OBJECT_CHECK(DBusVMState, (obj), TYPE_DBUS_VMSTATE)
-#define DBUS_VMSTATE_GET_CLASS(obj)                              \
-    OBJECT_GET_CLASS(DBusVMStateClass, (obj), TYPE_DBUS_VMSTATE)
-#define DBUS_VMSTATE_CLASS(klass)                                    \
-    OBJECT_CLASS_CHECK(DBusVMStateClass, (klass), TYPE_DBUS_VMSTATE)
-
-struct DBusVMStateClass {
-    ObjectClass parent_class;
-};
+OBJECT_DECLARE_SIMPLE_TYPE(DBusVMState, dbus_vmstate,
+                           DBUS_VMSTATE, ObjectClass)
+
 
 struct DBusVMState {
     Object parent;
diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index 5b819020b4..a3b2e8209e 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -17,11 +17,12 @@
 #include "sysemu/hostmem.h"
 #include "sysemu/sysemu.h"
 #include "qom/object_interfaces.h"
-
-#define MEMORY_BACKEND_FILE(obj) \
-    OBJECT_CHECK(HostMemoryBackendFile, (obj), TYPE_MEMORY_BACKEND_FILE)
+#include "qom/object.h"
 
 typedef struct HostMemoryBackendFile HostMemoryBackendFile;
+DECLARE_INSTANCE_CHECKER(HostMemoryBackendFile, MEMORY_BACKEND_FILE,
+                         TYPE_MEMORY_BACKEND_FILE)
+
 
 struct HostMemoryBackendFile {
     HostMemoryBackend parent_obj;
diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
index 4c040a7541..8cf6bcbda2 100644
--- a/backends/hostmem-memfd.c
+++ b/backends/hostmem-memfd.c
@@ -17,13 +17,14 @@
 #include "qemu/memfd.h"
 #include "qemu/module.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 #define TYPE_MEMORY_BACKEND_MEMFD "memory-backend-memfd"
 
-#define MEMORY_BACKEND_MEMFD(obj)                                        \
-    OBJECT_CHECK(HostMemoryBackendMemfd, (obj), TYPE_MEMORY_BACKEND_MEMFD)
-
 typedef struct HostMemoryBackendMemfd HostMemoryBackendMemfd;
+DECLARE_INSTANCE_CHECKER(HostMemoryBackendMemfd, MEMORY_BACKEND_MEMFD,
+                         TYPE_MEMORY_BACKEND_MEMFD)
+
 
 struct HostMemoryBackendMemfd {
     HostMemoryBackend parent_obj;
diff --git a/backends/rng-builtin.c b/backends/rng-builtin.c
index ba1b8d66b8..459be97a5a 100644
--- a/backends/rng-builtin.c
+++ b/backends/rng-builtin.c
@@ -9,13 +9,16 @@
 #include "sysemu/rng.h"
 #include "qemu/main-loop.h"
 #include "qemu/guest-random.h"
+#include "qom/object.h"
 
-#define RNG_BUILTIN(obj) OBJECT_CHECK(RngBuiltin, (obj), TYPE_RNG_BUILTIN)
+typedef struct RngBuiltin RngBuiltin;
+DECLARE_INSTANCE_CHECKER(RngBuiltin, RNG_BUILTIN,
+                         TYPE_RNG_BUILTIN)
 
-typedef struct RngBuiltin {
+struct RngBuiltin {
     RngBackend parent;
     QEMUBH *bh;
-} RngBuiltin;
+};
 
 static void rng_builtin_receive_entropy_bh(void *opaque)
 {
diff --git a/backends/rng-egd.c b/backends/rng-egd.c
index 7aaa6ee239..d905fe657c 100644
--- a/backends/rng-egd.c
+++ b/backends/rng-egd.c
@@ -16,17 +16,19 @@
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define TYPE_RNG_EGD "rng-egd"
-#define RNG_EGD(obj) OBJECT_CHECK(RngEgd, (obj), TYPE_RNG_EGD)
+typedef struct RngEgd RngEgd;
+DECLARE_INSTANCE_CHECKER(RngEgd, RNG_EGD,
+                         TYPE_RNG_EGD)
 
-typedef struct RngEgd
-{
+struct RngEgd {
     RngBackend parent;
 
     CharBackend chr;
     char *chr_name;
-} RngEgd;
+};
 
 static void rng_egd_request_entropy(RngBackend *b, RngRequest *req)
 {
diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
index a9b0f55e67..13657d9aba 100644
--- a/backends/tpm/tpm_emulator.c
+++ b/backends/tpm/tpm_emulator.c
@@ -42,10 +42,12 @@
 #include "qapi/qapi-visit-tpm.h"
 #include "chardev/char-fe.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define TYPE_TPM_EMULATOR "tpm-emulator"
-#define TPM_EMULATOR(obj) \
-    OBJECT_CHECK(TPMEmulator, (obj), TYPE_TPM_EMULATOR)
+typedef struct TPMEmulator TPMEmulator;
+DECLARE_INSTANCE_CHECKER(TPMEmulator, TPM_EMULATOR,
+                         TYPE_TPM_EMULATOR)
 
 #define TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(S, cap) (((S)->caps & (cap)) == (cap))
 
@@ -63,7 +65,7 @@ typedef struct TPMBlobBuffers {
     TPMSizedBuffer savestate;
 } TPMBlobBuffers;
 
-typedef struct TPMEmulator {
+struct TPMEmulator {
     TPMBackend parent;
 
     TPMEmulatorOptions *options;
@@ -80,7 +82,7 @@ typedef struct TPMEmulator {
     unsigned int established_flag_cached:1;
 
     TPMBlobBuffers state_blobs;
-} TPMEmulator;
+};
 
 struct tpm_error {
     uint32_t tpm_result;
diff --git a/backends/tpm/tpm_passthrough.c b/backends/tpm/tpm_passthrough.c
index 7403807ec4..10722e0a41 100644
--- a/backends/tpm/tpm_passthrough.c
+++ b/backends/tpm/tpm_passthrough.c
@@ -33,10 +33,12 @@
 #include "qapi/clone-visitor.h"
 #include "qapi/qapi-visit-tpm.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define TYPE_TPM_PASSTHROUGH "tpm-passthrough"
-#define TPM_PASSTHROUGH(obj) \
-    OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH)
+typedef struct TPMPassthruState TPMPassthruState;
+DECLARE_INSTANCE_CHECKER(TPMPassthruState, TPM_PASSTHROUGH,
+                         TYPE_TPM_PASSTHROUGH)
 
 /* data structures */
 struct TPMPassthruState {
@@ -53,7 +55,6 @@ struct TPMPassthruState {
     size_t tpm_buffersize;
 };
 
-typedef struct TPMPassthruState TPMPassthruState;
 
 #define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0"
 
diff --git a/block.c b/block.c
index 2ba76b2c36..9538af4884 100644
--- a/block.c
+++ b/block.c
@@ -712,11 +712,12 @@ int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp)
 int bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
 {
     BlockDriver *drv = bs->drv;
+    BlockDriverState *filtered = bdrv_filter_bs(bs);
 
     if (drv && drv->bdrv_probe_blocksizes) {
         return drv->bdrv_probe_blocksizes(bs, bsz);
-    } else if (drv && drv->is_filter && bs->file) {
-        return bdrv_probe_blocksizes(bs->file->bs, bsz);
+    } else if (filtered) {
+        return bdrv_probe_blocksizes(filtered, bsz);
     }
 
     return -ENOTSUP;
@@ -731,11 +732,12 @@ int bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
 int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
 {
     BlockDriver *drv = bs->drv;
+    BlockDriverState *filtered = bdrv_filter_bs(bs);
 
     if (drv && drv->bdrv_probe_geometry) {
         return drv->bdrv_probe_geometry(bs, geo);
-    } else if (drv && drv->is_filter && bs->file) {
-        return bdrv_probe_geometry(bs->file->bs, geo);
+    } else if (filtered) {
+        return bdrv_probe_geometry(filtered, geo);
     }
 
     return -ENOTSUP;
@@ -1153,10 +1155,6 @@ static void bdrv_backing_attach(BdrvChild *c)
     bdrv_refresh_filename(backing_hd);
 
     parent->open_flags &= ~BDRV_O_NO_BACKING;
-    pstrcpy(parent->backing_file, sizeof(parent->backing_file),
-            backing_hd->filename);
-    pstrcpy(parent->backing_format, sizeof(parent->backing_format),
-            backing_hd->drv ? backing_hd->drv->format_name : "");
 
     bdrv_op_block_all(backing_hd, parent->backing_blocker);
     /* Otherwise we won't be able to commit or stream */
@@ -2612,12 +2610,15 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
  * If @new_bs is not NULL, bdrv_check_perm() must be called beforehand, as this
  * function uses bdrv_set_perm() to update the permissions according to the new
  * reference that @new_bs gets.
+ *
+ * Callers must ensure that child->frozen is false.
  */
 static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
 {
     BlockDriverState *old_bs = child->bs;
     uint64_t perm, shared_perm;
 
+    /* Asserts that child->frozen == false */
     bdrv_replace_child_noperm(child, new_bs);
 
     /*
@@ -2778,6 +2779,7 @@ static void bdrv_detach_child(BdrvChild *child)
     g_free(child);
 }
 
+/* Callers must ensure that child->frozen is false. */
 void bdrv_root_unref_child(BdrvChild *child)
 {
     BlockDriverState *child_bs;
@@ -2815,6 +2817,7 @@ static void bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child)
     }
 }
 
+/* Callers must ensure that child->frozen is false. */
 void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child)
 {
     if (child == NULL) {
@@ -2863,7 +2866,7 @@ static BdrvChildRole bdrv_backing_role(BlockDriverState *bs)
 }
 
 /*
- * Sets the backing file link of a BDS. A new reference is created; callers
+ * Sets the bs->backing link of a BDS. A new reference is created; callers
  * which don't need their own reference any more must call bdrv_unref().
  */
 void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
@@ -2872,7 +2875,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
     bool update_inherits_from = bdrv_chain_contains(bs, backing_hd) &&
         bdrv_inherits_from_recursive(backing_hd, bs);
 
-    if (bdrv_is_backing_chain_frozen(bs, backing_bs(bs), errp)) {
+    if (bdrv_is_backing_chain_frozen(bs, child_bs(bs->backing), errp)) {
         return;
     }
 
@@ -2881,6 +2884,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
     }
 
     if (bs->backing) {
+        /* Cannot be frozen, we checked that above */
         bdrv_unref_child(bs, bs->backing);
         bs->backing = NULL;
     }
@@ -3996,7 +4000,7 @@ static int bdrv_reopen_parse_backing(BDRVReopenState *reopen_state,
                                      Error **errp)
 {
     BlockDriverState *bs = reopen_state->bs;
-    BlockDriverState *overlay_bs, *new_backing_bs;
+    BlockDriverState *overlay_bs, *below_bs, *new_backing_bs;
     QObject *value;
     const char *str;
 
@@ -4036,25 +4040,56 @@ static int bdrv_reopen_parse_backing(BDRVReopenState *reopen_state,
     }
 
     /*
+     * Ensure that @bs can really handle backing files, because we are
+     * about to give it one (or swap the existing one)
+     */
+    if (bs->drv->is_filter) {
+        /* Filters always have a file or a backing child */
+        if (!bs->backing) {
+            error_setg(errp, "'%s' is a %s filter node that does not support a "
+                       "backing child", bs->node_name, bs->drv->format_name);
+            return -EINVAL;
+        }
+    } else if (!bs->drv->supports_backing) {
+        error_setg(errp, "Driver '%s' of node '%s' does not support backing "
+                   "files", bs->drv->format_name, bs->node_name);
+        return -EINVAL;
+    }
+
+    /*
      * Find the "actual" backing file by skipping all links that point
      * to an implicit node, if any (e.g. a commit filter node).
+     * We cannot use any of the bdrv_skip_*() functions here because
+     * those return the first explicit node, while we are looking for
+     * its overlay here.
      */
     overlay_bs = bs;
-    while (backing_bs(overlay_bs) && backing_bs(overlay_bs)->implicit) {
-        overlay_bs = backing_bs(overlay_bs);
+    for (below_bs = bdrv_filter_or_cow_bs(overlay_bs);
+         below_bs && below_bs->implicit;
+         below_bs = bdrv_filter_or_cow_bs(overlay_bs))
+    {
+        overlay_bs = below_bs;
     }
 
     /* If we want to replace the backing file we need some extra checks */
-    if (new_backing_bs != backing_bs(overlay_bs)) {
+    if (new_backing_bs != bdrv_filter_or_cow_bs(overlay_bs)) {
         /* Check for implicit nodes between bs and its backing file */
         if (bs != overlay_bs) {
             error_setg(errp, "Cannot change backing link if '%s' has "
                        "an implicit backing file", bs->node_name);
             return -EPERM;
         }
-        /* Check if the backing link that we want to replace is frozen */
-        if (bdrv_is_backing_chain_frozen(overlay_bs, backing_bs(overlay_bs),
-                                         errp)) {
+        /*
+         * Check if the backing link that we want to replace is frozen.
+         * Note that
+         * bdrv_filter_or_cow_child(overlay_bs) == overlay_bs->backing,
+         * because we know that overlay_bs == bs, and that @bs
+         * either is a filter that uses ->backing or a COW format BDS
+         * with bs->drv->supports_backing == true.
+         */
+        if (bdrv_is_backing_chain_frozen(overlay_bs,
+                                         child_bs(overlay_bs->backing), errp))
+        {
             return -EPERM;
         }
         reopen_state->replace_backing_bs = true;
@@ -4203,7 +4238,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
      * its metadata. Otherwise the 'backing' option can be omitted.
      */
     if (drv->supports_backing && reopen_state->backing_missing &&
-        (backing_bs(reopen_state->bs) || reopen_state->bs->backing_file[0])) {
+        (reopen_state->bs->backing || reopen_state->bs->backing_file[0])) {
         error_setg(errp, "backing is missing for '%s'",
                    reopen_state->bs->node_name);
         ret = -EINVAL;
@@ -4344,7 +4379,7 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
      * from bdrv_set_backing_hd()) has the new values.
      */
     if (reopen_state->replace_backing_bs) {
-        BlockDriverState *old_backing_bs = backing_bs(bs);
+        BlockDriverState *old_backing_bs = child_bs(bs->backing);
         assert(!old_backing_bs || !old_backing_bs->implicit);
         /* Abort the permission update on the backing bs we're detaching */
         if (old_backing_bs) {
@@ -4387,6 +4422,7 @@ static void bdrv_close(BlockDriverState *bs)
 
     if (bs->drv) {
         if (bs->drv->bdrv_close) {
+            /* Must unfreeze all children, so bdrv_unref_child() works */
             bs->drv->bdrv_close(bs);
         }
         bs->drv = NULL;
@@ -4736,9 +4772,9 @@ int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
 }
 
 /*
- * Finds the image layer in the chain that has 'bs' as its backing file.
- *
- * active is the current topmost image.
+ * Finds the first non-filter node above bs in the chain between
+ * active and bs.  The returned node is either an immediate parent of
+ * bs, or there are only filter nodes between the two.
  *
  * Returns NULL if bs is not found in active's image chain,
  * or if active == bs.
@@ -4748,11 +4784,18 @@ int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
 BlockDriverState *bdrv_find_overlay(BlockDriverState *active,
                                     BlockDriverState *bs)
 {
-    while (active && bs != backing_bs(active)) {
-        active = backing_bs(active);
+    bs = bdrv_skip_filters(bs);
+    active = bdrv_skip_filters(active);
+
+    while (active) {
+        BlockDriverState *next = bdrv_backing_chain_next(active);
+        if (bs == next) {
+            return active;
+        }
+        active = next;
     }
 
-    return active;
+    return NULL;
 }
 
 /* Given a BDS, searches for the base layer. */
@@ -4762,20 +4805,22 @@ BlockDriverState *bdrv_find_base(BlockDriverState *bs)
 }
 
 /*
- * Return true if at least one of the backing links between @bs and
- * @base is frozen. @errp is set if that's the case.
+ * Return true if at least one of the COW (backing) and filter links
+ * between @bs and @base is frozen. @errp is set if that's the case.
  * @base must be reachable from @bs, or NULL.
  */
 bool bdrv_is_backing_chain_frozen(BlockDriverState *bs, BlockDriverState *base,
                                   Error **errp)
 {
     BlockDriverState *i;
+    BdrvChild *child;
+
+    for (i = bs; i != base; i = child_bs(child)) {
+        child = bdrv_filter_or_cow_child(i);
 
-    for (i = bs; i != base; i = backing_bs(i)) {
-        if (i->backing && i->backing->frozen) {
+        if (child && child->frozen) {
             error_setg(errp, "Cannot change '%s' link from '%s' to '%s'",
-                       i->backing->name, i->node_name,
-                       backing_bs(i)->node_name);
+                       child->name, i->node_name, child->bs->node_name);
             return true;
         }
     }
@@ -4784,7 +4829,7 @@ bool bdrv_is_backing_chain_frozen(BlockDriverState *bs, BlockDriverState *base,
 }
 
 /*
- * Freeze all backing links between @bs and @base.
+ * Freeze all COW (backing) and filter links between @bs and @base.
  * If any of the links is already frozen the operation is aborted and
  * none of the links are modified.
  * @base must be reachable from @bs, or NULL.
@@ -4794,22 +4839,25 @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
                               Error **errp)
 {
     BlockDriverState *i;
+    BdrvChild *child;
 
     if (bdrv_is_backing_chain_frozen(bs, base, errp)) {
         return -EPERM;
     }
 
-    for (i = bs; i != base; i = backing_bs(i)) {
-        if (i->backing && backing_bs(i)->never_freeze) {
+    for (i = bs; i != base; i = child_bs(child)) {
+        child = bdrv_filter_or_cow_child(i);
+        if (child && child->bs->never_freeze) {
             error_setg(errp, "Cannot freeze '%s' link to '%s'",
-                       i->backing->name, backing_bs(i)->node_name);
+                       child->name, child->bs->node_name);
             return -EPERM;
         }
     }
 
-    for (i = bs; i != base; i = backing_bs(i)) {
-        if (i->backing) {
-            i->backing->frozen = true;
+    for (i = bs; i != base; i = child_bs(child)) {
+        child = bdrv_filter_or_cow_child(i);
+        if (child) {
+            child->frozen = true;
         }
     }
 
@@ -4817,18 +4865,21 @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
 }
 
 /*
- * Unfreeze all backing links between @bs and @base. The caller must
- * ensure that all links are frozen before using this function.
+ * Unfreeze all COW (backing) and filter links between @bs and @base.
+ * The caller must ensure that all links are frozen before using this
+ * function.
  * @base must be reachable from @bs, or NULL.
  */
 void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base)
 {
     BlockDriverState *i;
+    BdrvChild *child;
 
-    for (i = bs; i != base; i = backing_bs(i)) {
-        if (i->backing) {
-            assert(i->backing->frozen);
-            i->backing->frozen = false;
+    for (i = bs; i != base; i = child_bs(child)) {
+        child = bdrv_filter_or_cow_child(i);
+        if (child) {
+            assert(child->frozen);
+            child->frozen = false;
         }
     }
 }
@@ -4896,9 +4947,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
      * other intermediate nodes have been dropped.
      * If 'top' is an implicit node (e.g. "commit_top") we should skip
      * it because no one inherits from it. We use explicit_top for that. */
-    while (explicit_top && explicit_top->implicit) {
-        explicit_top = backing_bs(explicit_top);
-    }
+    explicit_top = bdrv_skip_implicit_filters(explicit_top);
     update_inherits_from = bdrv_inherits_from_recursive(base, explicit_top);
 
     /* success - we can delete the intermediate states, and link top->base */
@@ -4931,8 +4980,11 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
             }
         }
 
-        /* Do the actual switch in the in-memory graph.
-         * Completes bdrv_check_update_perm() transaction internally. */
+        /*
+         * Do the actual switch in the in-memory graph.
+         * Completes bdrv_check_update_perm() transaction internally.
+         * c->frozen is false, we have checked that above.
+         */
         bdrv_ref(base);
         bdrv_replace_child(c, base);
         bdrv_unref(top);
@@ -4950,6 +5002,31 @@ exit:
 }
 
 /**
+ * Implementation of BlockDriver.bdrv_get_allocated_file_size() that
+ * sums the size of all data-bearing children.  (This excludes backing
+ * children.)
+ */
+static int64_t bdrv_sum_allocated_file_size(BlockDriverState *bs)
+{
+    BdrvChild *child;
+    int64_t child_size, sum = 0;
+
+    QLIST_FOREACH(child, &bs->children, next) {
+        if (child->role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
+                           BDRV_CHILD_FILTERED))
+        {
+            child_size = bdrv_get_allocated_file_size(child->bs);
+            if (child_size < 0) {
+                return child_size;
+            }
+            sum += child_size;
+        }
+    }
+
+    return sum;
+}
+
+/**
  * Length of a allocated file in bytes. Sparse files are counted by actual
  * allocated space. Return < 0 if error or unknown.
  */
@@ -4962,10 +5039,21 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
     if (drv->bdrv_get_allocated_file_size) {
         return drv->bdrv_get_allocated_file_size(bs);
     }
-    if (bs->file) {
-        return bdrv_get_allocated_file_size(bs->file->bs);
+
+    if (drv->bdrv_file_open) {
+        /*
+         * Protocol drivers default to -ENOTSUP (most of their data is
+         * not stored in any of their children (if they even have any),
+         * so there is no generic way to figure it out).
+         */
+        return -ENOTSUP;
+    } else if (drv->is_filter) {
+        /* Filter drivers default to the size of their filtered child */
+        return bdrv_get_allocated_file_size(bdrv_filter_bs(bs));
+    } else {
+        /* Other drivers default to summing their children's sizes */
+        return bdrv_sum_allocated_file_size(bs);
     }
-    return -ENOTSUP;
 }
 
 /*
@@ -5047,12 +5135,27 @@ bool bdrv_is_sg(BlockDriverState *bs)
     return bs->sg;
 }
 
-bool bdrv_is_encrypted(BlockDriverState *bs)
+/**
+ * Return whether the given node supports compressed writes.
+ */
+bool bdrv_supports_compressed_writes(BlockDriverState *bs)
 {
-    if (bs->backing && bs->backing->bs->encrypted) {
-        return true;
+    BlockDriverState *filtered;
+
+    if (!bs->drv || !block_driver_can_compress(bs->drv)) {
+        return false;
     }
-    return bs->encrypted;
+
+    filtered = bdrv_filter_bs(bs);
+    if (filtered) {
+        /*
+         * Filters can only forward compressed writes, so we have to
+         * check the child.
+         */
+        return bdrv_supports_compressed_writes(filtered);
+    }
+
+    return true;
 }
 
 const char *bdrv_get_format_name(BlockDriverState *bs)
@@ -5337,7 +5440,7 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
 bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base)
 {
     while (top && top != base) {
-        top = backing_bs(top);
+        top = bdrv_filter_or_cow_bs(top);
     }
 
     return top != NULL;
@@ -5409,20 +5512,24 @@ int bdrv_has_zero_init_1(BlockDriverState *bs)
 
 int bdrv_has_zero_init(BlockDriverState *bs)
 {
+    BlockDriverState *filtered;
+
     if (!bs->drv) {
         return 0;
     }
 
     /* If BS is a copy on write image, it is initialized to
        the contents of the base image, which may not be zeroes.  */
-    if (bs->backing) {
+    if (bdrv_cow_child(bs)) {
         return 0;
     }
     if (bs->drv->bdrv_has_zero_init) {
         return bs->drv->bdrv_has_zero_init(bs);
     }
-    if (bs->file && bs->drv->is_filter) {
-        return bdrv_has_zero_init(bs->file->bs);
+
+    filtered = bdrv_filter_bs(bs);
+    if (filtered) {
+        return bdrv_has_zero_init(filtered);
     }
 
     /* safe default */
@@ -5452,8 +5559,9 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
         return -ENOMEDIUM;
     }
     if (!drv->bdrv_get_info) {
-        if (bs->file && drv->is_filter) {
-            return bdrv_get_info(bs->file->bs, bdi);
+        BlockDriverState *filtered = bdrv_filter_bs(bs);
+        if (filtered) {
+            return bdrv_get_info(filtered, bdi);
         }
         return -ENOTSUP;
     }
@@ -5492,17 +5600,7 @@ void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event)
 static BlockDriverState *bdrv_find_debug_node(BlockDriverState *bs)
 {
     while (bs && bs->drv && !bs->drv->bdrv_debug_breakpoint) {
-        if (bs->file) {
-            bs = bs->file->bs;
-            continue;
-        }
-
-        if (bs->drv->is_filter && bs->backing) {
-            bs = bs->backing->bs;
-            continue;
-        }
-
-        break;
+        bs = bdrv_primary_bs(bs);
     }
 
     if (bs && bs->drv && bs->drv->bdrv_debug_breakpoint) {
@@ -5537,7 +5635,7 @@ int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag)
 int bdrv_debug_resume(BlockDriverState *bs, const char *tag)
 {
     while (bs && (!bs->drv || !bs->drv->bdrv_debug_resume)) {
-        bs = bs->file ? bs->file->bs : NULL;
+        bs = bdrv_primary_bs(bs);
     }
 
     if (bs && bs->drv && bs->drv->bdrv_debug_resume) {
@@ -5550,7 +5648,7 @@ int bdrv_debug_resume(BlockDriverState *bs, const char *tag)
 bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag)
 {
     while (bs && bs->drv && !bs->drv->bdrv_debug_is_suspended) {
-        bs = bs->file ? bs->file->bs : NULL;
+        bs = bdrv_primary_bs(bs);
     }
 
     if (bs && bs->drv && bs->drv->bdrv_debug_is_suspended) {
@@ -5571,8 +5669,10 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
     char *backing_file_full = NULL;
     char *filename_tmp = NULL;
     int is_protocol = 0;
+    bool filenames_refreshed = false;
     BlockDriverState *curr_bs = NULL;
     BlockDriverState *retval = NULL;
+    BlockDriverState *bs_below;
 
     if (!bs || !bs->drv || !backing_file) {
         return NULL;
@@ -5583,15 +5683,47 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
 
     is_protocol = path_has_protocol(backing_file);
 
-    for (curr_bs = bs; curr_bs->backing; curr_bs = curr_bs->backing->bs) {
+    /*
+     * Being largely a legacy function, skip any filters here
+     * (because filters do not have normal filenames, so they cannot
+     * match anyway; and allowing json:{} filenames is a bit out of
+     * scope).
+     */
+    for (curr_bs = bdrv_skip_filters(bs);
+         bdrv_cow_child(curr_bs) != NULL;
+         curr_bs = bs_below)
+    {
+        bs_below = bdrv_backing_chain_next(curr_bs);
+
+        if (bdrv_backing_overridden(curr_bs)) {
+            /*
+             * If the backing file was overridden, we can only compare
+             * directly against the backing node's filename.
+             */
 
-        /* If either of the filename paths is actually a protocol, then
-         * compare unmodified paths; otherwise make paths relative */
-        if (is_protocol || path_has_protocol(curr_bs->backing_file)) {
+            if (!filenames_refreshed) {
+                /*
+                 * This will automatically refresh all of the
+                 * filenames in the rest of the backing chain, so we
+                 * only need to do this once.
+                 */
+                bdrv_refresh_filename(bs_below);
+                filenames_refreshed = true;
+            }
+
+            if (strcmp(backing_file, bs_below->filename) == 0) {
+                retval = bs_below;
+                break;
+            }
+        } else if (is_protocol || path_has_protocol(curr_bs->backing_file)) {
+            /*
+             * If either of the filename paths is actually a protocol, then
+             * compare unmodified paths; otherwise make paths relative.
+             */
             char *backing_file_full_ret;
 
             if (strcmp(backing_file, curr_bs->backing_file) == 0) {
-                retval = curr_bs->backing->bs;
+                retval = bs_below;
                 break;
             }
             /* Also check against the full backing filename for the image */
@@ -5601,7 +5733,7 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
                 bool equal = strcmp(backing_file, backing_file_full_ret) == 0;
                 g_free(backing_file_full_ret);
                 if (equal) {
-                    retval = curr_bs->backing->bs;
+                    retval = bs_below;
                     break;
                 }
             }
@@ -5627,7 +5759,7 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
             g_free(filename_tmp);
 
             if (strcmp(backing_file_full, filename_full) == 0) {
-                retval = curr_bs->backing->bs;
+                retval = bs_below;
                 break;
             }
         }
@@ -6119,6 +6251,10 @@ void bdrv_img_create(const char *filename, const char *fmt,
                              "same filename as the backing file");
             goto out;
         }
+        if (backing_file[0] == '\0') {
+            error_setg(errp, "Expected backing file name, got empty string");
+            goto out;
+        }
     }
 
     backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
@@ -6534,6 +6670,8 @@ int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts,
 bool bdrv_recurse_can_replace(BlockDriverState *bs,
                               BlockDriverState *to_replace)
 {
+    BlockDriverState *filtered;
+
     if (!bs || !bs->drv) {
         return false;
     }
@@ -6548,9 +6686,9 @@ bool bdrv_recurse_can_replace(BlockDriverState *bs,
     }
 
     /* For filters without an own implementation, we can recurse on our own */
-    if (bs->drv->is_filter) {
-        BdrvChild *child = bs->file ?: bs->backing;
-        return bdrv_recurse_can_replace(child->bs, to_replace);
+    filtered = bdrv_filter_bs(bs);
+    if (filtered) {
+        return bdrv_recurse_can_replace(filtered, to_replace);
     }
 
     /* Safe default */
@@ -6701,7 +6839,7 @@ static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
 /* Note: This function may return false positives; it may return true
  * even if opening the backing file specified by bs's image header
  * would result in exactly bs->backing. */
-static bool bdrv_backing_overridden(BlockDriverState *bs)
+bool bdrv_backing_overridden(BlockDriverState *bs)
 {
     if (bs->backing) {
         return strcmp(bs->auto_backing_file,
@@ -6729,6 +6867,7 @@ void bdrv_refresh_filename(BlockDriverState *bs)
 {
     BlockDriver *drv = bs->drv;
     BdrvChild *child;
+    BlockDriverState *primary_child_bs;
     QDict *opts;
     bool backing_overridden;
     bool generate_json_filename; /* Whether our default implementation should
@@ -6798,20 +6937,30 @@ void bdrv_refresh_filename(BlockDriverState *bs)
     qobject_unref(bs->full_open_options);
     bs->full_open_options = opts;
 
+    primary_child_bs = bdrv_primary_bs(bs);
+
     if (drv->bdrv_refresh_filename) {
         /* Obsolete information is of no use here, so drop the old file name
          * information before refreshing it */
         bs->exact_filename[0] = '\0';
 
         drv->bdrv_refresh_filename(bs);
-    } else if (bs->file) {
-        /* Try to reconstruct valid information from the underlying file */
+    } else if (primary_child_bs) {
+        /*
+         * Try to reconstruct valid information from the underlying
+         * file -- this only works for format nodes (filter nodes
+         * cannot be probed and as such must be selected by the user
+         * either through an options dict, or through a special
+         * filename which the filter driver must construct in its
+         * .bdrv_refresh_filename() implementation).
+         */
 
         bs->exact_filename[0] = '\0';
 
         /*
          * We can use the underlying file's filename if:
          * - it has a filename,
+         * - the current BDS is not a filter,
          * - the file is a protocol BDS, and
          * - opening that file (as this BDS's format) will automatically create
          *   the BDS tree we have right now, that is:
@@ -6820,11 +6969,11 @@ void bdrv_refresh_filename(BlockDriverState *bs)
          *   - no non-file child of this BDS has been overridden by the user
          *   Both of these conditions are represented by generate_json_filename.
          */
-        if (bs->file->bs->exact_filename[0] &&
-            bs->file->bs->drv->bdrv_file_open &&
-            !generate_json_filename)
+        if (primary_child_bs->exact_filename[0] &&
+            primary_child_bs->drv->bdrv_file_open &&
+            !drv->is_filter && !generate_json_filename)
         {
-            strcpy(bs->exact_filename, bs->file->bs->exact_filename);
+            strcpy(bs->exact_filename, primary_child_bs->exact_filename);
         }
     }
 
@@ -6844,6 +6993,7 @@ void bdrv_refresh_filename(BlockDriverState *bs)
 char *bdrv_dirname(BlockDriverState *bs, Error **errp)
 {
     BlockDriver *drv = bs->drv;
+    BlockDriverState *child_bs;
 
     if (!drv) {
         error_setg(errp, "Node '%s' is ejected", bs->node_name);
@@ -6854,8 +7004,9 @@ char *bdrv_dirname(BlockDriverState *bs, Error **errp)
         return drv->bdrv_dirname(bs, errp);
     }
 
-    if (bs->file) {
-        return bdrv_dirname(bs->file->bs, errp);
+    child_bs = bdrv_primary_bs(bs);
+    if (child_bs) {
+        return bdrv_dirname(child_bs, errp);
     }
 
     bdrv_refresh_filename(bs);
@@ -6939,3 +7090,156 @@ int bdrv_make_empty(BdrvChild *c, Error **errp)
 
     return 0;
 }
+
+/*
+ * Return the child that @bs acts as an overlay for, and from which data may be
+ * copied in COW or COR operations.  Usually this is the backing file.
+ */
+BdrvChild *bdrv_cow_child(BlockDriverState *bs)
+{
+    if (!bs || !bs->drv) {
+        return NULL;
+    }
+
+    if (bs->drv->is_filter) {
+        return NULL;
+    }
+
+    if (!bs->backing) {
+        return NULL;
+    }
+
+    assert(bs->backing->role & BDRV_CHILD_COW);
+    return bs->backing;
+}
+
+/*
+ * If @bs acts as a filter for exactly one of its children, return
+ * that child.
+ */
+BdrvChild *bdrv_filter_child(BlockDriverState *bs)
+{
+    BdrvChild *c;
+
+    if (!bs || !bs->drv) {
+        return NULL;
+    }
+
+    if (!bs->drv->is_filter) {
+        return NULL;
+    }
+
+    /* Only one of @backing or @file may be used */
+    assert(!(bs->backing && bs->file));
+
+    c = bs->backing ?: bs->file;
+    if (!c) {
+        return NULL;
+    }
+
+    assert(c->role & BDRV_CHILD_FILTERED);
+    return c;
+}
+
+/*
+ * Return either the result of bdrv_cow_child() or bdrv_filter_child(),
+ * whichever is non-NULL.
+ *
+ * Return NULL if both are NULL.
+ */
+BdrvChild *bdrv_filter_or_cow_child(BlockDriverState *bs)
+{
+    BdrvChild *cow_child = bdrv_cow_child(bs);
+    BdrvChild *filter_child = bdrv_filter_child(bs);
+
+    /* Filter nodes cannot have COW backing files */
+    assert(!(cow_child && filter_child));
+
+    return cow_child ?: filter_child;
+}
+
+/*
+ * Return the primary child of this node: For filters, that is the
+ * filtered child.  For other nodes, that is usually the child storing
+ * metadata.
+ * (A generally more helpful description is that this is (usually) the
+ * child that has the same filename as @bs.)
+ *
+ * Drivers do not necessarily have a primary child; for example quorum
+ * does not.
+ */
+BdrvChild *bdrv_primary_child(BlockDriverState *bs)
+{
+    BdrvChild *c, *found = NULL;
+
+    QLIST_FOREACH(c, &bs->children, next) {
+        if (c->role & BDRV_CHILD_PRIMARY) {
+            assert(!found);
+            found = c;
+        }
+    }
+
+    return found;
+}
+
+static BlockDriverState *bdrv_do_skip_filters(BlockDriverState *bs,
+                                              bool stop_on_explicit_filter)
+{
+    BdrvChild *c;
+
+    if (!bs) {
+        return NULL;
+    }
+
+    while (!(stop_on_explicit_filter && !bs->implicit)) {
+        c = bdrv_filter_child(bs);
+        if (!c) {
+            /*
+             * A filter that is embedded in a working block graph must
+             * have a child.  Assert this here so this function does
+             * not return a filter node that is not expected by the
+             * caller.
+             */
+            assert(!bs->drv || !bs->drv->is_filter);
+            break;
+        }
+        bs = c->bs;
+    }
+    /*
+     * Note that this treats nodes with bs->drv == NULL as not being
+     * filters (bs->drv == NULL should be replaced by something else
+     * anyway).
+     * The advantage of this behavior is that this function will thus
+     * always return a non-NULL value (given a non-NULL @bs).
+     */
+
+    return bs;
+}
+
+/*
+ * Return the first BDS that has not been added implicitly or that
+ * does not have a filtered child down the chain starting from @bs
+ * (including @bs itself).
+ */
+BlockDriverState *bdrv_skip_implicit_filters(BlockDriverState *bs)
+{
+    return bdrv_do_skip_filters(bs, true);
+}
+
+/*
+ * Return the first BDS that does not have a filtered child down the
+ * chain starting from @bs (including @bs itself).
+ */
+BlockDriverState *bdrv_skip_filters(BlockDriverState *bs)
+{
+    return bdrv_do_skip_filters(bs, false);
+}
+
+/*
+ * For a backing chain, return the first non-filter backing image of
+ * the first non-filter image.
+ */
+BlockDriverState *bdrv_backing_chain_next(BlockDriverState *bs)
+{
+    return bdrv_skip_filters(bdrv_cow_bs(bdrv_skip_filters(bs)));
+}
diff --git a/block/backup-top.c b/block/backup-top.c
index af2f20f346..fe6883cc97 100644
--- a/block/backup-top.c
+++ b/block/backup-top.c
@@ -175,8 +175,6 @@ BlockDriver bdrv_backup_top_filter = {
     .bdrv_co_pdiscard           = backup_top_co_pdiscard,
     .bdrv_co_flush              = backup_top_co_flush,
 
-    .bdrv_co_block_status       = bdrv_co_block_status_from_backing,
-
     .bdrv_refresh_filename      = backup_top_refresh_filename,
 
     .bdrv_child_perm            = backup_top_child_perm,
@@ -281,7 +279,7 @@ void bdrv_backup_top_drop(BlockDriverState *bs)
 
     s->active = false;
     bdrv_child_refresh_perms(bs, bs->backing, &error_abort);
-    bdrv_replace_node(bs, backing_bs(bs), &error_abort);
+    bdrv_replace_node(bs, bs->backing->bs, &error_abort);
     bdrv_set_backing_hd(bs, NULL, &error_abort);
 
     bdrv_drained_end(bs);
diff --git a/block/backup.c b/block/backup.c
index 4f13bb20a5..9afa0bf3b4 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -297,6 +297,7 @@ static int64_t backup_calculate_cluster_size(BlockDriverState *target,
 {
     int ret;
     BlockDriverInfo bdi;
+    bool target_does_cow = bdrv_backing_chain_next(target);
 
     /*
      * If there is no backing file on the target, we cannot rely on COW if our
@@ -304,7 +305,7 @@ static int64_t backup_calculate_cluster_size(BlockDriverState *target,
      * targets with a backing file, try to avoid COW if possible.
      */
     ret = bdrv_get_info(target, &bdi);
-    if (ret == -ENOTSUP && !target->backing) {
+    if (ret == -ENOTSUP && !target_does_cow) {
         /* Cluster size is not defined */
         warn_report("The target block device doesn't provide "
                     "information about the block size and it doesn't have a "
@@ -313,14 +314,14 @@ static int64_t backup_calculate_cluster_size(BlockDriverState *target,
                     "this default, the backup may be unusable",
                     BACKUP_CLUSTER_SIZE_DEFAULT);
         return BACKUP_CLUSTER_SIZE_DEFAULT;
-    } else if (ret < 0 && !target->backing) {
+    } else if (ret < 0 && !target_does_cow) {
         error_setg_errno(errp, -ret,
             "Couldn't determine the cluster size of the target image, "
             "which has no backing file");
         error_append_hint(errp,
             "Aborting, since this may create an unusable destination image\n");
         return ret;
-    } else if (ret < 0 && target->backing) {
+    } else if (ret < 0 && target_does_cow) {
         /* Not fatal; just trudge on ahead. */
         return BACKUP_CLUSTER_SIZE_DEFAULT;
     }
@@ -371,7 +372,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
         return NULL;
     }
 
-    if (compress && !block_driver_can_compress(target->drv)) {
+    if (compress && !bdrv_supports_compressed_writes(target)) {
         error_setg(errp, "Compression is not supported for this drive %s",
                    bdrv_get_device_name(target));
         return NULL;
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 9c08d8a005..eecbf3e5c4 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -752,8 +752,11 @@ static int coroutine_fn blkdebug_co_block_status(BlockDriverState *bs,
         return err;
     }
 
-    return bdrv_co_block_status_from_file(bs, want_zero, offset, bytes,
-                                          pnum, map, file);
+    assert(bs->file && bs->file->bs);
+    *pnum = bytes;
+    *map = offset;
+    *file = bs->file->bs;
+    return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
 }
 
 static void blkdebug_close(BlockDriverState *bs)
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
index 57315f56b4..13ae63983b 100644
--- a/block/blklogwrites.c
+++ b/block/blklogwrites.c
@@ -515,7 +515,6 @@ static BlockDriver bdrv_blk_log_writes = {
     .bdrv_co_pwrite_zeroes  = blk_log_writes_co_pwrite_zeroes,
     .bdrv_co_flush_to_disk  = blk_log_writes_co_flush_to_disk,
     .bdrv_co_pdiscard       = blk_log_writes_co_pdiscard,
-    .bdrv_co_block_status   = bdrv_co_block_status_from_file,
 
     .is_filter              = true,
     .strong_runtime_opts    = blk_log_writes_strong_runtime_opts,
diff --git a/block/block-backend.c b/block/block-backend.c
index 3a13cb5f0b..24dd0670d1 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -2279,10 +2279,13 @@ int blk_commit_all(void)
 
     while ((blk = blk_all_next(blk)) != NULL) {
         AioContext *aio_context = blk_get_aio_context(blk);
+        BlockDriverState *unfiltered_bs = bdrv_skip_filters(blk_bs(blk));
 
         aio_context_acquire(aio_context);
-        if (blk_is_inserted(blk) && blk->root->bs->backing) {
-            int ret = bdrv_commit(blk->root->bs);
+        if (blk_is_inserted(blk) && bdrv_cow_child(unfiltered_bs)) {
+            int ret;
+
+            ret = bdrv_commit(unfiltered_bs);
             if (ret < 0) {
                 aio_context_release(aio_context);
                 return ret;
diff --git a/block/block-copy.c b/block/block-copy.c
index a30b9097ef..cd9bc47c8f 100644
--- a/block/block-copy.c
+++ b/block/block-copy.c
@@ -440,8 +440,8 @@ static int block_copy_block_status(BlockCopyState *s, int64_t offset,
     BlockDriverState *base;
     int ret;
 
-    if (s->skip_unallocated && s->source->bs->backing) {
-        base = s->source->bs->backing->bs;
+    if (s->skip_unallocated) {
+        base = bdrv_backing_chain_next(s->source->bs);
     } else {
         base = NULL;
     }
diff --git a/block/commit.c b/block/commit.c
index 7732d02dfe..1e85c306cc 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -37,6 +37,7 @@ typedef struct CommitBlockJob {
     BlockBackend *top;
     BlockBackend *base;
     BlockDriverState *base_bs;
+    BlockDriverState *base_overlay;
     BlockdevOnError on_error;
     bool base_read_only;
     bool chain_frozen;
@@ -89,7 +90,7 @@ static void commit_abort(Job *job)
      * XXX Can (or should) we somehow keep 'consistent read' blocked even
      * after the failed/cancelled commit job is gone? If we already wrote
      * something to base, the intermediate images aren't valid any more. */
-    bdrv_replace_node(s->commit_top_bs, backing_bs(s->commit_top_bs),
+    bdrv_replace_node(s->commit_top_bs, s->commit_top_bs->backing->bs,
                       &error_abort);
 
     bdrv_unref(s->commit_top_bs);
@@ -153,7 +154,7 @@ static int coroutine_fn commit_run(Job *job, Error **errp)
             break;
         }
         /* Copy if allocated above the base */
-        ret = bdrv_is_allocated_above(blk_bs(s->top), blk_bs(s->base), false,
+        ret = bdrv_is_allocated_above(blk_bs(s->top), s->base_overlay, true,
                                       offset, COMMIT_BUFFER_SIZE, &n);
         copy = (ret == 1);
         trace_commit_one_iteration(s, offset, n, ret);
@@ -237,7 +238,6 @@ static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
 static BlockDriver bdrv_commit_top = {
     .format_name                = "commit_top",
     .bdrv_co_preadv             = bdrv_commit_top_preadv,
-    .bdrv_co_block_status       = bdrv_co_block_status_from_backing,
     .bdrv_refresh_filename      = bdrv_commit_top_refresh_filename,
     .bdrv_child_perm            = bdrv_commit_top_child_perm,
 
@@ -253,15 +253,35 @@ void commit_start(const char *job_id, BlockDriverState *bs,
     CommitBlockJob *s;
     BlockDriverState *iter;
     BlockDriverState *commit_top_bs = NULL;
+    BlockDriverState *filtered_base;
     Error *local_err = NULL;
+    int64_t base_size, top_size;
+    uint64_t base_perms, iter_shared_perms;
     int ret;
 
     assert(top != bs);
-    if (top == base) {
+    if (bdrv_skip_filters(top) == bdrv_skip_filters(base)) {
         error_setg(errp, "Invalid files for merge: top and base are the same");
         return;
     }
 
+    base_size = bdrv_getlength(base);
+    if (base_size < 0) {
+        error_setg_errno(errp, -base_size, "Could not inquire base image size");
+        return;
+    }
+
+    top_size = bdrv_getlength(top);
+    if (top_size < 0) {
+        error_setg_errno(errp, -top_size, "Could not inquire top image size");
+        return;
+    }
+
+    base_perms = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE;
+    if (base_size < top_size) {
+        base_perms |= BLK_PERM_RESIZE;
+    }
+
     s = block_job_create(job_id, &commit_job_driver, NULL, bs, 0, BLK_PERM_ALL,
                          speed, creation_flags, NULL, NULL, errp);
     if (!s) {
@@ -301,17 +321,43 @@ void commit_start(const char *job_id, BlockDriverState *bs,
 
     s->commit_top_bs = commit_top_bs;
 
-    /* Block all nodes between top and base, because they will
-     * disappear from the chain after this operation. */
-    assert(bdrv_chain_contains(top, base));
-    for (iter = top; iter != base; iter = backing_bs(iter)) {
-        /* XXX BLK_PERM_WRITE needs to be allowed so we don't block ourselves
-         * at s->base (if writes are blocked for a node, they are also blocked
-         * for its backing file). The other options would be a second filter
-         * driver above s->base. */
+    /*
+     * Block all nodes between top and base, because they will
+     * disappear from the chain after this operation.
+     * Note that this assumes that the user is fine with removing all
+     * nodes (including R/W filters) between top and base.  Assuring
+     * this is the responsibility of the interface (i.e. whoever calls
+     * commit_start()).
+     */
+    s->base_overlay = bdrv_find_overlay(top, base);
+    assert(s->base_overlay);
+
+    /*
+     * The topmost node with
+     * bdrv_skip_filters(filtered_base) == bdrv_skip_filters(base)
+     */
+    filtered_base = bdrv_cow_bs(s->base_overlay);
+    assert(bdrv_skip_filters(filtered_base) == bdrv_skip_filters(base));
+
+    /*
+     * XXX BLK_PERM_WRITE needs to be allowed so we don't block ourselves
+     * at s->base (if writes are blocked for a node, they are also blocked
+     * for its backing file). The other options would be a second filter
+     * driver above s->base.
+     */
+    iter_shared_perms = BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE;
+
+    for (iter = top; iter != base; iter = bdrv_filter_or_cow_bs(iter)) {
+        if (iter == filtered_base) {
+            /*
+             * From here on, all nodes are filters on the base.  This
+             * allows us to share BLK_PERM_CONSISTENT_READ.
+             */
+            iter_shared_perms |= BLK_PERM_CONSISTENT_READ;
+        }
+
         ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
-                                 BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE,
-                                 errp);
+                                 iter_shared_perms, errp);
         if (ret < 0) {
             goto fail;
         }
@@ -328,9 +374,7 @@ void commit_start(const char *job_id, BlockDriverState *bs,
     }
 
     s->base = blk_new(s->common.job.aio_context,
-                      BLK_PERM_CONSISTENT_READ
-                      | BLK_PERM_WRITE
-                      | BLK_PERM_RESIZE,
+                      base_perms,
                       BLK_PERM_CONSISTENT_READ
                       | BLK_PERM_GRAPH_MOD
                       | BLK_PERM_WRITE_UNCHANGED);
@@ -398,19 +442,22 @@ int bdrv_commit(BlockDriverState *bs)
     if (!drv)
         return -ENOMEDIUM;
 
-    if (!bs->backing) {
+    backing_file_bs = bdrv_cow_bs(bs);
+
+    if (!backing_file_bs) {
         return -ENOTSUP;
     }
 
     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT_SOURCE, NULL) ||
-        bdrv_op_is_blocked(bs->backing->bs, BLOCK_OP_TYPE_COMMIT_TARGET, NULL)) {
+        bdrv_op_is_blocked(backing_file_bs, BLOCK_OP_TYPE_COMMIT_TARGET, NULL))
+    {
         return -EBUSY;
     }
 
-    ro = bs->backing->bs->read_only;
+    ro = backing_file_bs->read_only;
 
     if (ro) {
-        if (bdrv_reopen_set_read_only(bs->backing->bs, false, NULL)) {
+        if (bdrv_reopen_set_read_only(backing_file_bs, false, NULL)) {
             return -EACCES;
         }
     }
@@ -428,8 +475,6 @@ int bdrv_commit(BlockDriverState *bs)
     }
 
     /* Insert commit_top block node above backing, so we can write to it */
-    backing_file_bs = backing_bs(bs);
-
     commit_top_bs = bdrv_new_open_driver(&bdrv_commit_top, NULL, BDRV_O_RDWR,
                                          &local_err);
     if (commit_top_bs == NULL) {
@@ -515,7 +560,7 @@ ro_cleanup:
     qemu_vfree(buf);
 
     blk_unref(backing);
-    if (backing_file_bs) {
+    if (bdrv_cow_bs(bs) != backing_file_bs) {
         bdrv_set_backing_hd(bs, backing_file_bs, &error_abort);
     }
     bdrv_unref(commit_top_bs);
@@ -523,7 +568,7 @@ ro_cleanup:
 
     if (ro) {
         /* ignoring error return here */
-        bdrv_reopen_set_read_only(bs->backing->bs, true, NULL);
+        bdrv_reopen_set_read_only(backing_file_bs, true, NULL);
     }
 
     return ret;
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
index a6e3c74a68..2816e61afe 100644
--- a/block/copy-on-read.c
+++ b/block/copy-on-read.c
@@ -107,6 +107,16 @@ static int coroutine_fn cor_co_pdiscard(BlockDriverState *bs,
 }
 
 
+static int coroutine_fn cor_co_pwritev_compressed(BlockDriverState *bs,
+                                                  uint64_t offset,
+                                                  uint64_t bytes,
+                                                  QEMUIOVector *qiov)
+{
+    return bdrv_co_pwritev(bs->file, offset, bytes, qiov,
+                           BDRV_REQ_WRITE_COMPRESSED);
+}
+
+
 static void cor_eject(BlockDriverState *bs, bool eject_flag)
 {
     bdrv_eject(bs->file->bs, eject_flag);
@@ -131,12 +141,11 @@ static BlockDriver bdrv_copy_on_read = {
     .bdrv_co_pwritev                    = cor_co_pwritev,
     .bdrv_co_pwrite_zeroes              = cor_co_pwrite_zeroes,
     .bdrv_co_pdiscard                   = cor_co_pdiscard,
+    .bdrv_co_pwritev_compressed         = cor_co_pwritev_compressed,
 
     .bdrv_eject                         = cor_eject,
     .bdrv_lock_medium                   = cor_lock_medium,
 
-    .bdrv_co_block_status               = bdrv_co_block_status_from_file,
-
     .has_variable_length                = true,
     .is_filter                          = true,
 };
diff --git a/block/file-win32.c b/block/file-win32.c
index ab69bd811a..e2900c3a51 100644
--- a/block/file-win32.c
+++ b/block/file-win32.c
@@ -299,6 +299,11 @@ static QemuOptsList raw_runtime_opts = {
             .type = QEMU_OPT_STRING,
             .help = "host AIO implementation (threads, native)",
         },
+        {
+            .name = "locking",
+            .type = QEMU_OPT_STRING,
+            .help = "file locking mode (on/off/auto, default: auto)",
+        },
         { /* end of list */ }
     },
 };
@@ -333,6 +338,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
     Error *local_err = NULL;
     const char *filename;
     bool use_aio;
+    OnOffAuto locking;
     int ret;
 
     s->type = FTYPE_FILE;
@@ -343,10 +349,24 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
         goto fail;
     }
 
-    if (qdict_get_try_bool(options, "locking", false)) {
+    locking = qapi_enum_parse(&OnOffAuto_lookup,
+                              qemu_opt_get(opts, "locking"),
+                              ON_OFF_AUTO_AUTO, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        ret = -EINVAL;
+        goto fail;
+    }
+    switch (locking) {
+    case ON_OFF_AUTO_ON:
         error_setg(errp, "locking=on is not supported on Windows");
         ret = -EINVAL;
         goto fail;
+    case ON_OFF_AUTO_OFF:
+    case ON_OFF_AUTO_AUTO:
+        break;
+    default:
+        g_assert_not_reached();
     }
 
     filename = qemu_opt_get(opts, "filename");
diff --git a/block/filter-compress.c b/block/filter-compress.c
index 8ec1991c1f..5136371bf8 100644
--- a/block/filter-compress.c
+++ b/block/filter-compress.c
@@ -146,8 +146,6 @@ static BlockDriver bdrv_compress = {
     .bdrv_eject                         = compress_eject,
     .bdrv_lock_medium                   = compress_lock_medium,
 
-    .bdrv_co_block_status               = bdrv_co_block_status_from_file,
-
     .has_variable_length                = true,
     .is_filter                          = true,
 };
diff --git a/block/io.c b/block/io.c
index ad3a51ed53..a2389bb38c 100644
--- a/block/io.c
+++ b/block/io.c
@@ -135,6 +135,8 @@ static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src)
 void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
 {
     BlockDriver *drv = bs->drv;
+    BdrvChild *c;
+    bool have_limits;
     Error *local_err = NULL;
 
     memset(&bs->bl, 0, sizeof(bs->bl));
@@ -149,14 +151,21 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
                                 drv->bdrv_co_preadv_part) ? 1 : 512;
 
     /* Take some limits from the children as a default */
-    if (bs->file) {
-        bdrv_refresh_limits(bs->file->bs, &local_err);
-        if (local_err) {
-            error_propagate(errp, local_err);
-            return;
+    have_limits = false;
+    QLIST_FOREACH(c, &bs->children, next) {
+        if (c->role & (BDRV_CHILD_DATA | BDRV_CHILD_FILTERED | BDRV_CHILD_COW))
+        {
+            bdrv_refresh_limits(c->bs, &local_err);
+            if (local_err) {
+                error_propagate(errp, local_err);
+                return;
+            }
+            bdrv_merge_limits(&bs->bl, &c->bs->bl);
+            have_limits = true;
         }
-        bdrv_merge_limits(&bs->bl, &bs->file->bs->bl);
-    } else {
+    }
+
+    if (!have_limits) {
         bs->bl.min_mem_alignment = 512;
         bs->bl.opt_mem_alignment = qemu_real_host_page_size;
 
@@ -164,15 +173,6 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
         bs->bl.max_iov = IOV_MAX;
     }
 
-    if (bs->backing) {
-        bdrv_refresh_limits(bs->backing->bs, &local_err);
-        if (local_err) {
-            error_propagate(errp, local_err);
-            return;
-        }
-        bdrv_merge_limits(&bs->bl, &bs->backing->bs->bl);
-    }
-
     /* Then let the driver override it */
     if (drv->bdrv_refresh_limits) {
         drv->bdrv_refresh_limits(bs, errp);
@@ -2255,36 +2255,6 @@ typedef struct BdrvCoBlockStatusData {
     BlockDriverState **file;
 } BdrvCoBlockStatusData;
 
-int coroutine_fn bdrv_co_block_status_from_file(BlockDriverState *bs,
-                                                bool want_zero,
-                                                int64_t offset,
-                                                int64_t bytes,
-                                                int64_t *pnum,
-                                                int64_t *map,
-                                                BlockDriverState **file)
-{
-    assert(bs->file && bs->file->bs);
-    *pnum = bytes;
-    *map = offset;
-    *file = bs->file->bs;
-    return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
-}
-
-int coroutine_fn bdrv_co_block_status_from_backing(BlockDriverState *bs,
-                                                   bool want_zero,
-                                                   int64_t offset,
-                                                   int64_t bytes,
-                                                   int64_t *pnum,
-                                                   int64_t *map,
-                                                   BlockDriverState **file)
-{
-    assert(bs->backing && bs->backing->bs);
-    *pnum = bytes;
-    *map = offset;
-    *file = bs->backing->bs;
-    return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
-}
-
 /*
  * Returns the allocation status of the specified sectors.
  * Drivers not implementing the functionality are assumed to not support
@@ -2325,6 +2295,7 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
     BlockDriverState *local_file = NULL;
     int64_t aligned_offset, aligned_bytes;
     uint32_t align;
+    bool has_filtered_child;
 
     assert(pnum);
     *pnum = 0;
@@ -2350,7 +2321,8 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
 
     /* Must be non-NULL or bdrv_getlength() would have failed */
     assert(bs->drv);
-    if (!bs->drv->bdrv_co_block_status) {
+    has_filtered_child = bdrv_filter_child(bs);
+    if (!bs->drv->bdrv_co_block_status && !has_filtered_child) {
         *pnum = bytes;
         ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED;
         if (offset + bytes == total_size) {
@@ -2371,9 +2343,20 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
     aligned_offset = QEMU_ALIGN_DOWN(offset, align);
     aligned_bytes = ROUND_UP(offset + bytes, align) - aligned_offset;
 
-    ret = bs->drv->bdrv_co_block_status(bs, want_zero, aligned_offset,
-                                        aligned_bytes, pnum, &local_map,
-                                        &local_file);
+    if (bs->drv->bdrv_co_block_status) {
+        ret = bs->drv->bdrv_co_block_status(bs, want_zero, aligned_offset,
+                                            aligned_bytes, pnum, &local_map,
+                                            &local_file);
+    } else {
+        /* Default code for filters */
+
+        local_file = bdrv_filter_bs(bs);
+        assert(local_file);
+
+        *pnum = aligned_bytes;
+        local_map = aligned_offset;
+        ret = BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
+    }
     if (ret < 0) {
         *pnum = 0;
         goto out;
@@ -2409,9 +2392,10 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
     if (ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ZERO)) {
         ret |= BDRV_BLOCK_ALLOCATED;
     } else if (want_zero && bs->drv->supports_backing) {
-        if (bs->backing) {
-            BlockDriverState *bs2 = bs->backing->bs;
-            int64_t size2 = bdrv_getlength(bs2);
+        BlockDriverState *cow_bs = bdrv_cow_bs(bs);
+
+        if (cow_bs) {
+            int64_t size2 = bdrv_getlength(cow_bs);
 
             if (size2 >= 0 && offset >= size2) {
                 ret |= BDRV_BLOCK_ZERO;
@@ -2479,7 +2463,7 @@ static int coroutine_fn bdrv_co_block_status_above(BlockDriverState *bs,
     bool first = true;
 
     assert(bs != base);
-    for (p = bs; p != base; p = backing_bs(p)) {
+    for (p = bs; p != base; p = bdrv_filter_or_cow_bs(p)) {
         ret = bdrv_co_block_status(p, want_zero, offset, bytes, pnum, map,
                                    file);
         if (ret < 0) {
@@ -2553,7 +2537,7 @@ int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
 int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes,
                       int64_t *pnum, int64_t *map, BlockDriverState **file)
 {
-    return bdrv_block_status_above(bs, backing_bs(bs),
+    return bdrv_block_status_above(bs, bdrv_filter_or_cow_bs(bs),
                                    offset, bytes, pnum, map, file);
 }
 
@@ -2563,9 +2547,9 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
     int ret;
     int64_t dummy;
 
-    ret = bdrv_common_block_status_above(bs, backing_bs(bs), false, offset,
-                                         bytes, pnum ? pnum : &dummy, NULL,
-                                         NULL);
+    ret = bdrv_common_block_status_above(bs, bdrv_filter_or_cow_bs(bs), false,
+                                         offset, bytes, pnum ? pnum : &dummy,
+                                         NULL, NULL);
     if (ret < 0) {
         return ret;
     }
@@ -2628,7 +2612,7 @@ int bdrv_is_allocated_above(BlockDriverState *top,
             break;
         }
 
-        intermediate = backing_bs(intermediate);
+        intermediate = bdrv_filter_or_cow_bs(intermediate);
     }
 
     *pnum = n;
@@ -2647,6 +2631,7 @@ bdrv_co_rw_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos,
                    bool is_read)
 {
     BlockDriver *drv = bs->drv;
+    BlockDriverState *child_bs = bdrv_primary_bs(bs);
     int ret = -ENOTSUP;
 
     bdrv_inc_in_flight(bs);
@@ -2659,8 +2644,8 @@ bdrv_co_rw_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos,
         } else {
             ret = drv->bdrv_save_vmstate(bs, qiov, pos);
         }
-    } else if (bs->file) {
-        ret = bdrv_co_rw_vmstate(bs->file->bs, qiov, pos, is_read);
+    } else if (child_bs) {
+        ret = bdrv_co_rw_vmstate(child_bs, qiov, pos, is_read);
     }
 
     bdrv_dec_in_flight(bs);
@@ -2770,6 +2755,8 @@ static int coroutine_fn bdrv_flush_co_entry(void *opaque)
 
 int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
 {
+    BdrvChild *primary_child = bdrv_primary_child(bs);
+    BdrvChild *child;
     int current_gen;
     int ret = 0;
 
@@ -2799,7 +2786,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
     }
 
     /* Write back cached data to the OS even with cache=unsafe */
-    BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_OS);
+    BLKDBG_EVENT(primary_child, BLKDBG_FLUSH_TO_OS);
     if (bs->drv->bdrv_co_flush_to_os) {
         ret = bs->drv->bdrv_co_flush_to_os(bs);
         if (ret < 0) {
@@ -2809,15 +2796,15 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
 
     /* But don't actually force it to the disk with cache=unsafe */
     if (bs->open_flags & BDRV_O_NO_FLUSH) {
-        goto flush_parent;
+        goto flush_children;
     }
 
     /* Check if we really need to flush anything */
     if (bs->flushed_gen == current_gen) {
-        goto flush_parent;
+        goto flush_children;
     }
 
-    BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_DISK);
+    BLKDBG_EVENT(primary_child, BLKDBG_FLUSH_TO_DISK);
     if (!bs->drv) {
         /* bs->drv->bdrv_co_flush() might have ejected the BDS
          * (even in case of apparent success) */
@@ -2861,8 +2848,17 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
     /* Now flush the underlying protocol.  It will also have BDRV_O_NO_FLUSH
      * in the case of cache=unsafe, so there are no useless flushes.
      */
-flush_parent:
-    ret = bs->file ? bdrv_co_flush(bs->file->bs) : 0;
+flush_children:
+    ret = 0;
+    QLIST_FOREACH(child, &bs->children, next) {
+        if (child->perm & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) {
+            int this_child_ret = bdrv_co_flush(child->bs);
+            if (!ret) {
+                ret = this_child_ret;
+            }
+        }
+    }
+
 out:
     /* Notify any pending flushes that we have completed */
     if (ret == 0) {
@@ -3309,6 +3305,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
                                   Error **errp)
 {
     BlockDriverState *bs = child->bs;
+    BdrvChild *filtered, *backing;
     BlockDriver *drv = bs->drv;
     BdrvTrackedRequest req;
     int64_t old_size, new_bytes;
@@ -3360,6 +3357,9 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
         goto out;
     }
 
+    filtered = bdrv_filter_child(bs);
+    backing = bdrv_cow_child(bs);
+
     /*
      * If the image has a backing file that is large enough that it would
      * provide data for the new area, we cannot leave it unallocated because
@@ -3370,10 +3370,10 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
      * backing file, taking care of keeping things consistent with that backing
      * file is the user's responsibility.
      */
-    if (new_bytes && bs->backing) {
+    if (new_bytes && backing) {
         int64_t backing_len;
 
-        backing_len = bdrv_getlength(backing_bs(bs));
+        backing_len = bdrv_getlength(backing->bs);
         if (backing_len < 0) {
             ret = backing_len;
             error_setg_errno(errp, -ret, "Could not get backing file size");
@@ -3392,8 +3392,8 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
             goto out;
         }
         ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
-    } else if (bs->file && drv->is_filter) {
-        ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
+    } else if (filtered) {
+        ret = bdrv_co_truncate(filtered, offset, exact, prealloc, flags, errp);
     } else {
         error_setg(errp, "Image format driver does not support resize");
         ret = -ENOTSUP;
diff --git a/block/mirror.c b/block/mirror.c
index e8e8844afc..26acf4af6f 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -42,6 +42,7 @@ typedef struct MirrorBlockJob {
     BlockBackend *target;
     BlockDriverState *mirror_top_bs;
     BlockDriverState *base;
+    BlockDriverState *base_overlay;
 
     /* The name of the graph node to replace */
     char *replaces;
@@ -677,8 +678,10 @@ static int mirror_exit_common(Job *job)
                              &error_abort);
     if (!abort && s->backing_mode == MIRROR_SOURCE_BACKING_CHAIN) {
         BlockDriverState *backing = s->is_none_mode ? src : s->base;
-        if (backing_bs(target_bs) != backing) {
-            bdrv_set_backing_hd(target_bs, backing, &local_err);
+        BlockDriverState *unfiltered_target = bdrv_skip_filters(target_bs);
+
+        if (bdrv_cow_bs(unfiltered_target) != backing) {
+            bdrv_set_backing_hd(unfiltered_target, backing, &local_err);
             if (local_err) {
                 error_report_err(local_err);
                 local_err = NULL;
@@ -740,7 +743,7 @@ static int mirror_exit_common(Job *job)
      * valid.
      */
     block_job_remove_all_bdrv(bjob);
-    bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort);
+    bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort);
 
     /* We just changed the BDS the job BB refers to (with either or both of the
      * bdrv_replace_node() calls), so switch the BB back so the cleanup does
@@ -786,7 +789,6 @@ static void coroutine_fn mirror_throttle(MirrorBlockJob *s)
 static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
 {
     int64_t offset;
-    BlockDriverState *base = s->base;
     BlockDriverState *bs = s->mirror_top_bs->backing->bs;
     BlockDriverState *target_bs = blk_bs(s->target);
     int ret;
@@ -837,7 +839,8 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
             return 0;
         }
 
-        ret = bdrv_is_allocated_above(bs, base, false, offset, bytes, &count);
+        ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset, bytes,
+                                      &count);
         if (ret < 0) {
             return ret;
         }
@@ -936,7 +939,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
     } else {
         s->target_cluster_size = BDRV_SECTOR_SIZE;
     }
-    if (backing_filename[0] && !target_bs->backing &&
+    if (backing_filename[0] && !bdrv_backing_chain_next(target_bs) &&
         s->granularity < s->target_cluster_size) {
         s->buf_size = MAX(s->buf_size, s->target_cluster_size);
         s->cow_bitmap = bitmap_new(length);
@@ -1116,8 +1119,9 @@ static void mirror_complete(Job *job, Error **errp)
     if (s->backing_mode == MIRROR_OPEN_BACKING_CHAIN) {
         int ret;
 
-        assert(!target->backing);
-        ret = bdrv_open_backing_file(target, NULL, "backing", errp);
+        assert(!bdrv_backing_chain_next(target));
+        ret = bdrv_open_backing_file(bdrv_skip_filters(target), NULL,
+                                     "backing", errp);
         if (ret < 0) {
             return;
         }
@@ -1527,7 +1531,6 @@ static BlockDriver bdrv_mirror_top = {
     .bdrv_co_pwrite_zeroes      = bdrv_mirror_top_pwrite_zeroes,
     .bdrv_co_pdiscard           = bdrv_mirror_top_pdiscard,
     .bdrv_co_flush              = bdrv_mirror_top_flush,
-    .bdrv_co_block_status       = bdrv_co_block_status_from_backing,
     .bdrv_refresh_filename      = bdrv_mirror_top_refresh_filename,
     .bdrv_child_perm            = bdrv_mirror_top_child_perm,
 
@@ -1555,8 +1558,8 @@ static BlockJob *mirror_start_job(
     MirrorBlockJob *s;
     MirrorBDSOpaque *bs_opaque;
     BlockDriverState *mirror_top_bs;
-    bool target_graph_mod;
     bool target_is_backing;
+    uint64_t target_perms, target_shared_perms;
     Error *local_err = NULL;
     int ret;
 
@@ -1575,7 +1578,7 @@ static BlockJob *mirror_start_job(
         buf_size = DEFAULT_MIRROR_BUF_SIZE;
     }
 
-    if (bs == target) {
+    if (bdrv_skip_filters(bs) == bdrv_skip_filters(target)) {
         error_setg(errp, "Can't mirror node into itself");
         return NULL;
     }
@@ -1639,15 +1642,50 @@ static BlockJob *mirror_start_job(
      * In the case of active commit, things look a bit different, though,
      * because the target is an already populated backing file in active use.
      * We can allow anything except resize there.*/
+
+    target_perms = BLK_PERM_WRITE;
+    target_shared_perms = BLK_PERM_WRITE_UNCHANGED;
+
     target_is_backing = bdrv_chain_contains(bs, target);
-    target_graph_mod = (backing_mode != MIRROR_LEAVE_BACKING_CHAIN);
+    if (target_is_backing) {
+        int64_t bs_size, target_size;
+        bs_size = bdrv_getlength(bs);
+        if (bs_size < 0) {
+            error_setg_errno(errp, -bs_size,
+                             "Could not inquire top image size");
+            goto fail;
+        }
+
+        target_size = bdrv_getlength(target);
+        if (target_size < 0) {
+            error_setg_errno(errp, -target_size,
+                             "Could not inquire base image size");
+            goto fail;
+        }
+
+        if (target_size < bs_size) {
+            target_perms |= BLK_PERM_RESIZE;
+        }
+
+        target_shared_perms |= BLK_PERM_CONSISTENT_READ
+                            |  BLK_PERM_WRITE
+                            |  BLK_PERM_GRAPH_MOD;
+    } else if (bdrv_chain_contains(bs, bdrv_skip_filters(target))) {
+        /*
+         * We may want to allow this in the future, but it would
+         * require taking some extra care.
+         */
+        error_setg(errp, "Cannot mirror to a filter on top of a node in the "
+                   "source's backing chain");
+        goto fail;
+    }
+
+    if (backing_mode != MIRROR_LEAVE_BACKING_CHAIN) {
+        target_perms |= BLK_PERM_GRAPH_MOD;
+    }
+
     s->target = blk_new(s->common.job.aio_context,
-                        BLK_PERM_WRITE | BLK_PERM_RESIZE |
-                        (target_graph_mod ? BLK_PERM_GRAPH_MOD : 0),
-                        BLK_PERM_WRITE_UNCHANGED |
-                        (target_is_backing ? BLK_PERM_CONSISTENT_READ |
-                                             BLK_PERM_WRITE |
-                                             BLK_PERM_GRAPH_MOD : 0));
+                        target_perms, target_shared_perms);
     ret = blk_insert_bs(s->target, target, errp);
     if (ret < 0) {
         goto fail;
@@ -1672,6 +1710,7 @@ static BlockJob *mirror_start_job(
     s->zero_target = zero_target;
     s->copy_mode = copy_mode;
     s->base = base;
+    s->base_overlay = bdrv_find_overlay(bs, base);
     s->granularity = granularity;
     s->buf_size = ROUND_UP(buf_size, granularity);
     s->unmap = unmap;
@@ -1702,15 +1741,39 @@ static BlockJob *mirror_start_job(
     /* In commit_active_start() all intermediate nodes disappear, so
      * any jobs in them must be blocked */
     if (target_is_backing) {
-        BlockDriverState *iter;
-        for (iter = backing_bs(bs); iter != target; iter = backing_bs(iter)) {
-            /* XXX BLK_PERM_WRITE needs to be allowed so we don't block
-             * ourselves at s->base (if writes are blocked for a node, they are
-             * also blocked for its backing file). The other options would be a
-             * second filter driver above s->base (== target). */
+        BlockDriverState *iter, *filtered_target;
+        uint64_t iter_shared_perms;
+
+        /*
+         * The topmost node with
+         * bdrv_skip_filters(filtered_target) == bdrv_skip_filters(target)
+         */
+        filtered_target = bdrv_cow_bs(bdrv_find_overlay(bs, target));
+
+        assert(bdrv_skip_filters(filtered_target) ==
+               bdrv_skip_filters(target));
+
+        /*
+         * XXX BLK_PERM_WRITE needs to be allowed so we don't block
+         * ourselves at s->base (if writes are blocked for a node, they are
+         * also blocked for its backing file). The other options would be a
+         * second filter driver above s->base (== target).
+         */
+        iter_shared_perms = BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE;
+
+        for (iter = bdrv_filter_or_cow_bs(bs); iter != target;
+             iter = bdrv_filter_or_cow_bs(iter))
+        {
+            if (iter == filtered_target) {
+                /*
+                 * From here on, all nodes are filters on the base.
+                 * This allows us to share BLK_PERM_CONSISTENT_READ.
+                 */
+                iter_shared_perms |= BLK_PERM_CONSISTENT_READ;
+            }
+
             ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
-                                     BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE,
-                                     errp);
+                                     iter_shared_perms, errp);
             if (ret < 0) {
                 goto fail;
             }
@@ -1746,7 +1809,7 @@ fail:
     bs_opaque->stop = true;
     bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing,
                              &error_abort);
-    bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort);
+    bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort);
 
     bdrv_unref(mirror_top_bs);
 
@@ -1774,7 +1837,7 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
         return;
     }
     is_none_mode = mode == MIRROR_SYNC_MODE_NONE;
-    base = mode == MIRROR_SYNC_MODE_TOP ? backing_bs(bs) : NULL;
+    base = mode == MIRROR_SYNC_MODE_TOP ? bdrv_backing_chain_next(bs) : NULL;
     mirror_start_job(job_id, bs, creation_flags, target, replaces,
                      speed, granularity, buf_size, backing_mode, zero_target,
                      on_source_error, on_target_error, unmap, NULL, NULL,
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index 4c8c375172..4d3db5ed3c 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -217,7 +217,7 @@ void hmp_commit(Monitor *mon, const QDict *qdict)
             return;
         }
 
-        bs = blk_bs(blk);
+        bs = bdrv_skip_implicit_filters(blk_bs(blk));
         aio_context = bdrv_get_aio_context(bs);
         aio_context_acquire(aio_context);
 
diff --git a/block/null.c b/block/null.c
index 15e1d56746..cc9b1d4ea7 100644
--- a/block/null.c
+++ b/block/null.c
@@ -262,6 +262,11 @@ static void null_refresh_filename(BlockDriverState *bs)
              bs->drv->format_name);
 }
 
+static int64_t null_allocated_file_size(BlockDriverState *bs)
+{
+    return 0;
+}
+
 static const char *const null_strong_runtime_opts[] = {
     BLOCK_OPT_SIZE,
     NULL_OPT_ZEROES,
@@ -277,6 +282,7 @@ static BlockDriver bdrv_null_co = {
     .bdrv_file_open         = null_file_open,
     .bdrv_parse_filename    = null_co_parse_filename,
     .bdrv_getlength         = null_getlength,
+    .bdrv_get_allocated_file_size = null_allocated_file_size,
 
     .bdrv_co_preadv         = null_co_preadv,
     .bdrv_co_pwritev        = null_co_pwritev,
@@ -297,6 +303,7 @@ static BlockDriver bdrv_null_aio = {
     .bdrv_file_open         = null_file_open,
     .bdrv_parse_filename    = null_aio_parse_filename,
     .bdrv_getlength         = null_getlength,
+    .bdrv_get_allocated_file_size = null_allocated_file_size,
 
     .bdrv_aio_preadv        = null_aio_preadv,
     .bdrv_aio_pwritev       = null_aio_pwritev,
diff --git a/block/nvme.c b/block/nvme.c
index 05485fdd11..f4f27b6da7 100644
--- a/block/nvme.c
+++ b/block/nvme.c
@@ -83,25 +83,21 @@ typedef struct {
 
 /* Memory mapped registers */
 typedef volatile struct {
-    uint64_t cap;
-    uint32_t vs;
-    uint32_t intms;
-    uint32_t intmc;
-    uint32_t cc;
-    uint32_t reserved0;
-    uint32_t csts;
-    uint32_t nssr;
-    uint32_t aqa;
-    uint64_t asq;
-    uint64_t acq;
-    uint32_t cmbloc;
-    uint32_t cmbsz;
-    uint8_t  reserved1[0xec0];
-    uint8_t  cmd_set_specfic[0x100];
-    uint32_t doorbells[];
+    NvmeBar ctrl;
+    struct {
+        uint32_t sq_tail;
+        uint32_t cq_head;
+    } doorbells[];
 } NVMeRegs;
 
-QEMU_BUILD_BUG_ON(offsetof(NVMeRegs, doorbells) != 0x1000);
+#define INDEX_ADMIN     0
+#define INDEX_IO(n)     (1 + n)
+
+/* This driver shares a single MSIX IRQ for the admin and I/O queues */
+enum {
+    MSIX_SHARED_IRQ_IDX = 0,
+    MSIX_IRQ_COUNT = 1
+};
 
 struct BDRVNVMeState {
     AioContext *aio_context;
@@ -117,7 +113,7 @@ struct BDRVNVMeState {
     /* How many uint32_t elements does each doorbell entry take. */
     size_t doorbell_scale;
     bool write_cache_supported;
-    EventNotifier irq_notifier;
+    EventNotifier irq_notifier[MSIX_IRQ_COUNT];
 
     uint64_t nsze; /* Namespace size reported by identify command */
     int nsid;      /* The namespace id to read/write data. */
@@ -162,21 +158,20 @@ static QemuOptsList runtime_opts = {
     },
 };
 
-static void nvme_init_queue(BlockDriverState *bs, NVMeQueue *q,
+static void nvme_init_queue(BDRVNVMeState *s, NVMeQueue *q,
                             int nentries, int entry_bytes, Error **errp)
 {
-    BDRVNVMeState *s = bs->opaque;
     size_t bytes;
     int r;
 
     bytes = ROUND_UP(nentries * entry_bytes, s->page_size);
     q->head = q->tail = 0;
-    q->queue = qemu_try_blockalign0(bs, bytes);
-
+    q->queue = qemu_try_memalign(s->page_size, bytes);
     if (!q->queue) {
         error_setg(errp, "Cannot allocate queue");
         return;
     }
+    memset(q->queue, 0, bytes);
     r = qemu_vfio_dma_map(s->vfio, q->queue, bytes, false, &q->iova);
     if (r) {
         error_setg(errp, "Cannot map queue");
@@ -206,23 +201,31 @@ static void nvme_free_req_queue_cb(void *opaque)
     qemu_mutex_unlock(&q->lock);
 }
 
-static NVMeQueuePair *nvme_create_queue_pair(BlockDriverState *bs,
+static NVMeQueuePair *nvme_create_queue_pair(BDRVNVMeState *s,
+                                             AioContext *aio_context,
                                              int idx, int size,
                                              Error **errp)
 {
     int i, r;
-    BDRVNVMeState *s = bs->opaque;
     Error *local_err = NULL;
-    NVMeQueuePair *q = g_new0(NVMeQueuePair, 1);
+    NVMeQueuePair *q;
     uint64_t prp_list_iova;
 
+    q = g_try_new0(NVMeQueuePair, 1);
+    if (!q) {
+        return NULL;
+    }
+    q->prp_list_pages = qemu_try_memalign(s->page_size,
+                                          s->page_size * NVME_NUM_REQS);
+    if (!q->prp_list_pages) {
+        goto fail;
+    }
+    memset(q->prp_list_pages, 0, s->page_size * NVME_NUM_REQS);
     qemu_mutex_init(&q->lock);
     q->s = s;
     q->index = idx;
     qemu_co_queue_init(&q->free_req_queue);
-    q->prp_list_pages = qemu_blockalign0(bs, s->page_size * NVME_NUM_REQS);
-    q->completion_bh = aio_bh_new(bdrv_get_aio_context(bs),
-                                  nvme_process_completion_bh, q);
+    q->completion_bh = aio_bh_new(aio_context, nvme_process_completion_bh, q);
     r = qemu_vfio_dma_map(s->vfio, q->prp_list_pages,
                           s->page_size * NVME_NUM_REQS,
                           false, &prp_list_iova);
@@ -239,19 +242,19 @@ static NVMeQueuePair *nvme_create_queue_pair(BlockDriverState *bs,
         req->prp_list_iova = prp_list_iova + i * s->page_size;
     }
 
-    nvme_init_queue(bs, &q->sq, size, NVME_SQ_ENTRY_BYTES, &local_err);
+    nvme_init_queue(s, &q->sq, size, NVME_SQ_ENTRY_BYTES, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         goto fail;
     }
-    q->sq.doorbell = &s->regs->doorbells[idx * 2 * s->doorbell_scale];
+    q->sq.doorbell = &s->regs->doorbells[idx * s->doorbell_scale].sq_tail;
 
-    nvme_init_queue(bs, &q->cq, size, NVME_CQ_ENTRY_BYTES, &local_err);
+    nvme_init_queue(s, &q->cq, size, NVME_CQ_ENTRY_BYTES, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         goto fail;
     }
-    q->cq.doorbell = &s->regs->doorbells[(idx * 2 + 1) * s->doorbell_scale];
+    q->cq.doorbell = &s->regs->doorbells[idx * s->doorbell_scale].cq_head;
 
     return q;
 fail:
@@ -441,6 +444,9 @@ static void nvme_trace_command(const NvmeCmd *cmd)
 {
     int i;
 
+    if (!trace_event_get_state_backends(TRACE_NVME_SUBMIT_COMMAND_RAW)) {
+        return;
+    }
     for (i = 0; i < 8; ++i) {
         uint8_t *cmdp = (uint8_t *)cmd + i * 8;
         trace_nvme_submit_command_raw(cmdp[0], cmdp[1], cmdp[2], cmdp[3],
@@ -479,6 +485,7 @@ static void nvme_cmd_sync_cb(void *opaque, int ret)
 static int nvme_cmd_sync(BlockDriverState *bs, NVMeQueuePair *q,
                          NvmeCmd *cmd)
 {
+    AioContext *aio_context = bdrv_get_aio_context(bs);
     NVMeRequest *req;
     int ret = -EINPROGRESS;
     req = nvme_get_free_req(q);
@@ -487,17 +494,18 @@ static int nvme_cmd_sync(BlockDriverState *bs, NVMeQueuePair *q,
     }
     nvme_submit_command(q, req, cmd, nvme_cmd_sync_cb, &ret);
 
-    BDRV_POLL_WHILE(bs, ret == -EINPROGRESS);
+    AIO_WAIT_WHILE(aio_context, ret == -EINPROGRESS);
     return ret;
 }
 
 static void nvme_identify(BlockDriverState *bs, int namespace, Error **errp)
 {
     BDRVNVMeState *s = bs->opaque;
-    NvmeIdCtrl *idctrl;
-    NvmeIdNs *idns;
+    union {
+        NvmeIdCtrl ctrl;
+        NvmeIdNs ns;
+    } *id;
     NvmeLBAF *lbaf;
-    uint8_t *resp;
     uint16_t oncs;
     int r;
     uint64_t iova;
@@ -506,54 +514,52 @@ static void nvme_identify(BlockDriverState *bs, int namespace, Error **errp)
         .cdw10 = cpu_to_le32(0x1),
     };
 
-    resp = qemu_try_blockalign0(bs, sizeof(NvmeIdCtrl));
-    if (!resp) {
+    id = qemu_try_memalign(s->page_size, sizeof(*id));
+    if (!id) {
         error_setg(errp, "Cannot allocate buffer for identify response");
         goto out;
     }
-    idctrl = (NvmeIdCtrl *)resp;
-    idns = (NvmeIdNs *)resp;
-    r = qemu_vfio_dma_map(s->vfio, resp, sizeof(NvmeIdCtrl), true, &iova);
+    r = qemu_vfio_dma_map(s->vfio, id, sizeof(*id), true, &iova);
     if (r) {
         error_setg(errp, "Cannot map buffer for DMA");
         goto out;
     }
-    cmd.dptr.prp1 = cpu_to_le64(iova);
 
-    if (nvme_cmd_sync(bs, s->queues[0], &cmd)) {
+    memset(id, 0, sizeof(*id));
+    cmd.dptr.prp1 = cpu_to_le64(iova);
+    if (nvme_cmd_sync(bs, s->queues[INDEX_ADMIN], &cmd)) {
         error_setg(errp, "Failed to identify controller");
         goto out;
     }
 
-    if (le32_to_cpu(idctrl->nn) < namespace) {
+    if (le32_to_cpu(id->ctrl.nn) < namespace) {
         error_setg(errp, "Invalid namespace");
         goto out;
     }
-    s->write_cache_supported = le32_to_cpu(idctrl->vwc) & 0x1;
-    s->max_transfer = (idctrl->mdts ? 1 << idctrl->mdts : 0) * s->page_size;
+    s->write_cache_supported = le32_to_cpu(id->ctrl.vwc) & 0x1;
+    s->max_transfer = (id->ctrl.mdts ? 1 << id->ctrl.mdts : 0) * s->page_size;
     /* For now the page list buffer per command is one page, to hold at most
      * s->page_size / sizeof(uint64_t) entries. */
     s->max_transfer = MIN_NON_ZERO(s->max_transfer,
                           s->page_size / sizeof(uint64_t) * s->page_size);
 
-    oncs = le16_to_cpu(idctrl->oncs);
+    oncs = le16_to_cpu(id->ctrl.oncs);
     s->supports_write_zeroes = !!(oncs & NVME_ONCS_WRITE_ZEROES);
     s->supports_discard = !!(oncs & NVME_ONCS_DSM);
 
-    memset(resp, 0, 4096);
-
+    memset(id, 0, sizeof(*id));
     cmd.cdw10 = 0;
     cmd.nsid = cpu_to_le32(namespace);
-    if (nvme_cmd_sync(bs, s->queues[0], &cmd)) {
+    if (nvme_cmd_sync(bs, s->queues[INDEX_ADMIN], &cmd)) {
         error_setg(errp, "Failed to identify namespace");
         goto out;
     }
 
-    s->nsze = le64_to_cpu(idns->nsze);
-    lbaf = &idns->lbaf[NVME_ID_NS_FLBAS_INDEX(idns->flbas)];
+    s->nsze = le64_to_cpu(id->ns.nsze);
+    lbaf = &id->ns.lbaf[NVME_ID_NS_FLBAS_INDEX(id->ns.flbas)];
 
-    if (NVME_ID_NS_DLFEAT_WRITE_ZEROES(idns->dlfeat) &&
-            NVME_ID_NS_DLFEAT_READ_BEHAVIOR(idns->dlfeat) ==
+    if (NVME_ID_NS_DLFEAT_WRITE_ZEROES(id->ns.dlfeat) &&
+            NVME_ID_NS_DLFEAT_READ_BEHAVIOR(id->ns.dlfeat) ==
                     NVME_ID_NS_DLFEAT_READ_BEHAVIOR_ZEROES) {
         bs->supported_write_flags |= BDRV_REQ_MAY_UNMAP;
     }
@@ -573,8 +579,34 @@ static void nvme_identify(BlockDriverState *bs, int namespace, Error **errp)
 
     s->blkshift = lbaf->ds;
 out:
-    qemu_vfio_dma_unmap(s->vfio, resp);
-    qemu_vfree(resp);
+    qemu_vfio_dma_unmap(s->vfio, id);
+    qemu_vfree(id);
+}
+
+static bool nvme_poll_queue(NVMeQueuePair *q)
+{
+    bool progress = false;
+
+    const size_t cqe_offset = q->cq.head * NVME_CQ_ENTRY_BYTES;
+    NvmeCqe *cqe = (NvmeCqe *)&q->cq.queue[cqe_offset];
+
+    /*
+     * Do an early check for completions. q->lock isn't needed because
+     * nvme_process_completion() only runs in the event loop thread and
+     * cannot race with itself.
+     */
+    if ((le16_to_cpu(cqe->status) & 0x1) == q->cq_phase) {
+        return false;
+    }
+
+    qemu_mutex_lock(&q->lock);
+    while (nvme_process_completion(q)) {
+        /* Keep polling */
+        progress = true;
+    }
+    qemu_mutex_unlock(&q->lock);
+
+    return progress;
 }
 
 static bool nvme_poll_queues(BDRVNVMeState *s)
@@ -583,32 +615,17 @@ static bool nvme_poll_queues(BDRVNVMeState *s)
     int i;
 
     for (i = 0; i < s->nr_queues; i++) {
-        NVMeQueuePair *q = s->queues[i];
-        const size_t cqe_offset = q->cq.head * NVME_CQ_ENTRY_BYTES;
-        NvmeCqe *cqe = (NvmeCqe *)&q->cq.queue[cqe_offset];
-
-        /*
-         * Do an early check for completions. q->lock isn't needed because
-         * nvme_process_completion() only runs in the event loop thread and
-         * cannot race with itself.
-         */
-        if ((le16_to_cpu(cqe->status) & 0x1) == q->cq_phase) {
-            continue;
-        }
-
-        qemu_mutex_lock(&q->lock);
-        while (nvme_process_completion(q)) {
-            /* Keep polling */
+        if (nvme_poll_queue(s->queues[i])) {
             progress = true;
         }
-        qemu_mutex_unlock(&q->lock);
     }
     return progress;
 }
 
 static void nvme_handle_event(EventNotifier *n)
 {
-    BDRVNVMeState *s = container_of(n, BDRVNVMeState, irq_notifier);
+    BDRVNVMeState *s = container_of(n, BDRVNVMeState,
+                                    irq_notifier[MSIX_SHARED_IRQ_IDX]);
 
     trace_nvme_handle_event(s);
     event_notifier_test_and_clear(n);
@@ -623,7 +640,8 @@ static bool nvme_add_io_queue(BlockDriverState *bs, Error **errp)
     NvmeCmd cmd;
     int queue_size = NVME_QUEUE_SIZE;
 
-    q = nvme_create_queue_pair(bs, n, queue_size, errp);
+    q = nvme_create_queue_pair(s, bdrv_get_aio_context(bs),
+                               n, queue_size, errp);
     if (!q) {
         return false;
     }
@@ -633,10 +651,9 @@ static bool nvme_add_io_queue(BlockDriverState *bs, Error **errp)
         .cdw10 = cpu_to_le32(((queue_size - 1) << 16) | (n & 0xFFFF)),
         .cdw11 = cpu_to_le32(0x3),
     };
-    if (nvme_cmd_sync(bs, s->queues[0], &cmd)) {
-        error_setg(errp, "Failed to create io queue [%d]", n);
-        nvme_free_queue_pair(q);
-        return false;
+    if (nvme_cmd_sync(bs, s->queues[INDEX_ADMIN], &cmd)) {
+        error_setg(errp, "Failed to create CQ io queue [%d]", n);
+        goto out_error;
     }
     cmd = (NvmeCmd) {
         .opcode = NVME_ADM_CMD_CREATE_SQ,
@@ -644,21 +661,24 @@ static bool nvme_add_io_queue(BlockDriverState *bs, Error **errp)
         .cdw10 = cpu_to_le32(((queue_size - 1) << 16) | (n & 0xFFFF)),
         .cdw11 = cpu_to_le32(0x1 | (n << 16)),
     };
-    if (nvme_cmd_sync(bs, s->queues[0], &cmd)) {
-        error_setg(errp, "Failed to create io queue [%d]", n);
-        nvme_free_queue_pair(q);
-        return false;
+    if (nvme_cmd_sync(bs, s->queues[INDEX_ADMIN], &cmd)) {
+        error_setg(errp, "Failed to create SQ io queue [%d]", n);
+        goto out_error;
     }
     s->queues = g_renew(NVMeQueuePair *, s->queues, n + 1);
     s->queues[n] = q;
     s->nr_queues++;
     return true;
+out_error:
+    nvme_free_queue_pair(q);
+    return false;
 }
 
 static bool nvme_poll_cb(void *opaque)
 {
     EventNotifier *e = opaque;
-    BDRVNVMeState *s = container_of(e, BDRVNVMeState, irq_notifier);
+    BDRVNVMeState *s = container_of(e, BDRVNVMeState,
+                                    irq_notifier[MSIX_SHARED_IRQ_IDX]);
 
     trace_nvme_poll_cb(s);
     return nvme_poll_queues(s);
@@ -668,6 +688,7 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
                      Error **errp)
 {
     BDRVNVMeState *s = bs->opaque;
+    AioContext *aio_context = bdrv_get_aio_context(bs);
     int ret;
     uint64_t cap;
     uint64_t timeout_ms;
@@ -679,7 +700,7 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
     s->device = g_strdup(device);
     s->nsid = namespace;
     s->aio_context = bdrv_get_aio_context(bs);
-    ret = event_notifier_init(&s->irq_notifier, 0);
+    ret = event_notifier_init(&s->irq_notifier[MSIX_SHARED_IRQ_IDX], 0);
     if (ret) {
         error_setg(errp, "Failed to init event notifier");
         return ret;
@@ -700,7 +721,7 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
     /* Perform initialize sequence as described in NVMe spec "7.6.1
      * Initialization". */
 
-    cap = le64_to_cpu(s->regs->cap);
+    cap = le64_to_cpu(s->regs->ctrl.cap);
     if (!(cap & (1ULL << 37))) {
         error_setg(errp, "Device doesn't support NVMe command set");
         ret = -EINVAL;
@@ -713,10 +734,10 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
     timeout_ms = MIN(500 * ((cap >> 24) & 0xFF), 30000);
 
     /* Reset device to get a clean state. */
-    s->regs->cc = cpu_to_le32(le32_to_cpu(s->regs->cc) & 0xFE);
+    s->regs->ctrl.cc = cpu_to_le32(le32_to_cpu(s->regs->ctrl.cc) & 0xFE);
     /* Wait for CSTS.RDY = 0. */
-    deadline = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + timeout_ms * 1000000ULL;
-    while (le32_to_cpu(s->regs->csts) & 0x1) {
+    deadline = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + timeout_ms * SCALE_MS;
+    while (le32_to_cpu(s->regs->ctrl.csts) & 0x1) {
         if (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) > deadline) {
             error_setg(errp, "Timeout while waiting for device to reset (%"
                              PRId64 " ms)",
@@ -728,25 +749,27 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
 
     /* Set up admin queue. */
     s->queues = g_new(NVMeQueuePair *, 1);
-    s->queues[0] = nvme_create_queue_pair(bs, 0, NVME_QUEUE_SIZE, errp);
-    if (!s->queues[0]) {
+    s->queues[INDEX_ADMIN] = nvme_create_queue_pair(s, aio_context, 0,
+                                                          NVME_QUEUE_SIZE,
+                                                          errp);
+    if (!s->queues[INDEX_ADMIN]) {
         ret = -EINVAL;
         goto out;
     }
     s->nr_queues = 1;
     QEMU_BUILD_BUG_ON(NVME_QUEUE_SIZE & 0xF000);
-    s->regs->aqa = cpu_to_le32((NVME_QUEUE_SIZE << 16) | NVME_QUEUE_SIZE);
-    s->regs->asq = cpu_to_le64(s->queues[0]->sq.iova);
-    s->regs->acq = cpu_to_le64(s->queues[0]->cq.iova);
+    s->regs->ctrl.aqa = cpu_to_le32((NVME_QUEUE_SIZE << 16) | NVME_QUEUE_SIZE);
+    s->regs->ctrl.asq = cpu_to_le64(s->queues[INDEX_ADMIN]->sq.iova);
+    s->regs->ctrl.acq = cpu_to_le64(s->queues[INDEX_ADMIN]->cq.iova);
 
     /* After setting up all control registers we can enable device now. */
-    s->regs->cc = cpu_to_le32((ctz32(NVME_CQ_ENTRY_BYTES) << 20) |
+    s->regs->ctrl.cc = cpu_to_le32((ctz32(NVME_CQ_ENTRY_BYTES) << 20) |
                               (ctz32(NVME_SQ_ENTRY_BYTES) << 16) |
                               0x1);
     /* Wait for CSTS.RDY = 1. */
     now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
     deadline = now + timeout_ms * 1000000;
-    while (!(le32_to_cpu(s->regs->csts) & 0x1)) {
+    while (!(le32_to_cpu(s->regs->ctrl.csts) & 0x1)) {
         if (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) > deadline) {
             error_setg(errp, "Timeout while waiting for device to start (%"
                              PRId64 " ms)",
@@ -756,12 +779,13 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
         }
     }
 
-    ret = qemu_vfio_pci_init_irq(s->vfio, &s->irq_notifier,
+    ret = qemu_vfio_pci_init_irq(s->vfio, s->irq_notifier,
                                  VFIO_PCI_MSIX_IRQ_INDEX, errp);
     if (ret) {
         goto out;
     }
-    aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier,
+    aio_set_event_notifier(bdrv_get_aio_context(bs),
+                           &s->irq_notifier[MSIX_SHARED_IRQ_IDX],
                            false, nvme_handle_event, nvme_poll_cb);
 
     nvme_identify(bs, namespace, &local_err);
@@ -828,7 +852,7 @@ static int nvme_enable_disable_write_cache(BlockDriverState *bs, bool enable,
         .cdw11 = cpu_to_le32(enable ? 0x01 : 0x00),
     };
 
-    ret = nvme_cmd_sync(bs, s->queues[0], &cmd);
+    ret = nvme_cmd_sync(bs, s->queues[INDEX_ADMIN], &cmd);
     if (ret) {
         error_setg(errp, "Failed to configure NVMe write cache");
     }
@@ -844,9 +868,10 @@ static void nvme_close(BlockDriverState *bs)
         nvme_free_queue_pair(s->queues[i]);
     }
     g_free(s->queues);
-    aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier,
+    aio_set_event_notifier(bdrv_get_aio_context(bs),
+                           &s->irq_notifier[MSIX_SHARED_IRQ_IDX],
                            false, NULL, NULL);
-    event_notifier_cleanup(&s->irq_notifier);
+    event_notifier_cleanup(&s->irq_notifier[MSIX_SHARED_IRQ_IDX]);
     qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->regs, 0, NVME_BAR_SIZE);
     qemu_vfio_close(s->vfio);
 
@@ -1045,7 +1070,7 @@ static coroutine_fn int nvme_co_prw_aligned(BlockDriverState *bs,
 {
     int r;
     BDRVNVMeState *s = bs->opaque;
-    NVMeQueuePair *ioq = s->queues[1];
+    NVMeQueuePair *ioq = s->queues[INDEX_IO(0)];
     NVMeRequest *req;
 
     uint32_t cdw12 = (((bytes >> s->blkshift) - 1) & 0xFFFF) |
@@ -1124,7 +1149,7 @@ static int nvme_co_prw(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
         return nvme_co_prw_aligned(bs, offset, bytes, qiov, is_write, flags);
     }
     trace_nvme_prw_buffered(s, offset, bytes, qiov->niov, is_write);
-    buf = qemu_try_blockalign(bs, bytes);
+    buf = qemu_try_memalign(s->page_size, bytes);
 
     if (!buf) {
         return -ENOMEM;
@@ -1160,7 +1185,7 @@ static coroutine_fn int nvme_co_pwritev(BlockDriverState *bs,
 static coroutine_fn int nvme_co_flush(BlockDriverState *bs)
 {
     BDRVNVMeState *s = bs->opaque;
-    NVMeQueuePair *ioq = s->queues[1];
+    NVMeQueuePair *ioq = s->queues[INDEX_IO(0)];
     NVMeRequest *req;
     NvmeCmd cmd = {
         .opcode = NVME_CMD_FLUSH,
@@ -1191,7 +1216,7 @@ static coroutine_fn int nvme_co_pwrite_zeroes(BlockDriverState *bs,
                                               BdrvRequestFlags flags)
 {
     BDRVNVMeState *s = bs->opaque;
-    NVMeQueuePair *ioq = s->queues[1];
+    NVMeQueuePair *ioq = s->queues[INDEX_IO(0)];
     NVMeRequest *req;
 
     uint32_t cdw12 = ((bytes >> s->blkshift) - 1) & 0xFFFF;
@@ -1244,7 +1269,7 @@ static int coroutine_fn nvme_co_pdiscard(BlockDriverState *bs,
                                          int bytes)
 {
     BDRVNVMeState *s = bs->opaque;
-    NVMeQueuePair *ioq = s->queues[1];
+    NVMeQueuePair *ioq = s->queues[INDEX_IO(0)];
     NVMeRequest *req;
     NvmeDsmRange *buf;
     QEMUIOVector local_qiov;
@@ -1268,11 +1293,11 @@ static int coroutine_fn nvme_co_pdiscard(BlockDriverState *bs,
 
     assert(s->nr_queues > 1);
 
-    buf = qemu_try_blockalign0(bs, s->page_size);
+    buf = qemu_try_memalign(s->page_size, s->page_size);
     if (!buf) {
         return -ENOMEM;
     }
-
+    memset(buf, 0, s->page_size);
     buf->nlb = cpu_to_le32(bytes >> s->blkshift);
     buf->slba = cpu_to_le64(offset >> s->blkshift);
     buf->cattr = 0;
@@ -1353,7 +1378,8 @@ static void nvme_detach_aio_context(BlockDriverState *bs)
         q->completion_bh = NULL;
     }
 
-    aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier,
+    aio_set_event_notifier(bdrv_get_aio_context(bs),
+                           &s->irq_notifier[MSIX_SHARED_IRQ_IDX],
                            false, NULL, NULL);
 }
 
@@ -1363,7 +1389,7 @@ static void nvme_attach_aio_context(BlockDriverState *bs,
     BDRVNVMeState *s = bs->opaque;
 
     s->aio_context = new_context;
-    aio_set_event_notifier(new_context, &s->irq_notifier,
+    aio_set_event_notifier(new_context, &s->irq_notifier[MSIX_SHARED_IRQ_IDX],
                            false, nvme_handle_event, nvme_poll_cb);
 
     for (int i = 0; i < s->nr_queues; i++) {
@@ -1387,7 +1413,7 @@ static void nvme_aio_unplug(BlockDriverState *bs)
     BDRVNVMeState *s = bs->opaque;
     assert(s->plugged);
     s->plugged = false;
-    for (i = 1; i < s->nr_queues; i++) {
+    for (i = INDEX_IO(0); i < s->nr_queues; i++) {
         NVMeQueuePair *q = s->queues[i];
         qemu_mutex_lock(&q->lock);
         nvme_kick(q);
diff --git a/block/qapi.c b/block/qapi.c
index afd9f3b4a7..f423ece98c 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -47,7 +47,7 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
                                         Error **errp)
 {
     ImageInfo **p_image_info;
-    BlockDriverState *bs0;
+    BlockDriverState *bs0, *backing;
     BlockDeviceInfo *info;
 
     if (!bs->drv) {
@@ -76,9 +76,10 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
         info->node_name = g_strdup(bs->node_name);
     }
 
-    if (bs->backing_file[0]) {
+    backing = bdrv_cow_bs(bs);
+    if (backing) {
         info->has_backing_file = true;
-        info->backing_file = g_strdup(bs->backing_file);
+        info->backing_file = g_strdup(backing->filename);
     }
 
     if (!QLIST_EMPTY(&bs->dirty_bitmaps)) {
@@ -163,9 +164,13 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
             break;
         }
 
-        if (bs0->drv && bs0->backing) {
+        if (bs0->drv && bdrv_filter_or_cow_child(bs0)) {
+            /*
+             * Put any filtered child here (for backwards compatibility to when
+             * we put bs0->backing here, which might be any filtered child).
+             */
             info->backing_file_depth++;
-            bs0 = bs0->backing->bs;
+            bs0 = bdrv_filter_or_cow_bs(bs0);
             (*p_image_info)->has_backing_image = true;
             p_image_info = &((*p_image_info)->backing_image);
         } else {
@@ -174,9 +179,8 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
 
         /* Skip automatically inserted nodes that the user isn't aware of for
          * query-block (blk != NULL), but not for query-named-block-nodes */
-        while (blk && bs0->drv && bs0->implicit) {
-            bs0 = backing_bs(bs0);
-            assert(bs0);
+        if (blk) {
+            bs0 = bdrv_skip_implicit_filters(bs0);
         }
     }
 
@@ -288,7 +292,7 @@ void bdrv_query_image_info(BlockDriverState *bs,
     info->virtual_size    = size;
     info->actual_size     = bdrv_get_allocated_file_size(bs);
     info->has_actual_size = info->actual_size >= 0;
-    if (bdrv_is_encrypted(bs)) {
+    if (bs->encrypted) {
         info->encrypted = true;
         info->has_encrypted = true;
     }
@@ -311,6 +315,7 @@ void bdrv_query_image_info(BlockDriverState *bs,
     backing_filename = bs->backing_file;
     if (backing_filename[0] != '\0') {
         char *backing_filename2;
+
         info->backing_filename = g_strdup(backing_filename);
         info->has_backing_filename = true;
         backing_filename2 = bdrv_get_full_backing_filename(bs, NULL);
@@ -362,9 +367,7 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
     char *qdev;
 
     /* Skip automatically inserted nodes that the user isn't aware of */
-    while (bs && bs->drv && bs->implicit) {
-        bs = backing_bs(bs);
-    }
+    bs = bdrv_skip_implicit_filters(bs);
 
     info->device = g_strdup(blk_name(blk));
     info->type = g_strdup("unknown");
@@ -526,6 +529,8 @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
 static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs,
                                         bool blk_level)
 {
+    BdrvChild *parent_child;
+    BlockDriverState *filter_or_cow_bs;
     BlockStats *s = NULL;
 
     s = g_malloc0(sizeof(*s));
@@ -538,9 +543,8 @@ static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs,
     /* Skip automatically inserted nodes that the user isn't aware of in
      * a BlockBackend-level command. Stay at the exact node for a node-level
      * command. */
-    while (blk_level && bs->drv && bs->implicit) {
-        bs = backing_bs(bs);
-        assert(bs);
+    if (blk_level) {
+        bs = bdrv_skip_implicit_filters(bs);
     }
 
     if (bdrv_get_node_name(bs)[0]) {
@@ -555,14 +559,46 @@ static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs,
         s->has_driver_specific = true;
     }
 
-    if (bs->file) {
+    parent_child = bdrv_primary_child(bs);
+    if (!parent_child ||
+        !(parent_child->role & (BDRV_CHILD_DATA | BDRV_CHILD_FILTERED)))
+    {
+        BdrvChild *c;
+
+        /*
+         * Look for a unique data-storing child.  We do not need to look for
+         * filtered children, as there would be only one and it would have been
+         * the primary child.
+         */
+        parent_child = NULL;
+        QLIST_FOREACH(c, &bs->children, next) {
+            if (c->role & BDRV_CHILD_DATA) {
+                if (parent_child) {
+                    /*
+                     * There are multiple data-storing children and we cannot
+                     * choose between them.
+                     */
+                    parent_child = NULL;
+                    break;
+                }
+                parent_child = c;
+            }
+        }
+    }
+    if (parent_child) {
         s->has_parent = true;
-        s->parent = bdrv_query_bds_stats(bs->file->bs, blk_level);
+        s->parent = bdrv_query_bds_stats(parent_child->bs, blk_level);
     }
 
-    if (blk_level && bs->backing) {
+    filter_or_cow_bs = bdrv_filter_or_cow_bs(bs);
+    if (blk_level && filter_or_cow_bs) {
+        /*
+         * Put any filtered or COW child here (for backwards
+         * compatibility to when we put bs0->backing here, which might
+         * be either)
+         */
         s->has_backing = true;
-        s->backing = bdrv_query_bds_stats(bs->backing->bs, blk_level);
+        s->backing = bdrv_query_bds_stats(filter_or_cow_bs, blk_level);
     }
 
     return s;
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 996b3314f4..fcdf7af8e6 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1320,6 +1320,7 @@ static bool cluster_needs_new_alloc(BlockDriverState *bs, uint64_t l2_entry)
         if (l2_entry & QCOW_OFLAG_COPIED) {
             return false;
         }
+        /* fallthrough */
     case QCOW2_CLUSTER_UNALLOCATED:
     case QCOW2_CLUSTER_COMPRESSED:
     case QCOW2_CLUSTER_ZERO_PLAIN:
diff --git a/block/snapshot.c b/block/snapshot.c
index bd9fb01817..a2bf3a54eb 100644
--- a/block/snapshot.c
+++ b/block/snapshot.c
@@ -147,6 +147,56 @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
     return ret;
 }
 
+/**
+ * Return a pointer to the child BDS pointer to which we can fall
+ * back if the given BDS does not support snapshots.
+ * Return NULL if there is no BDS to (safely) fall back to.
+ *
+ * We need to return an indirect pointer because bdrv_snapshot_goto()
+ * has to modify the BdrvChild pointer.
+ */
+static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs)
+{
+    BdrvChild **fallback;
+    BdrvChild *child;
+
+    /*
+     * The only BdrvChild pointers that are safe to modify (and which
+     * we can thus return a reference to) are bs->file and
+     * bs->backing.
+     */
+    fallback = &bs->file;
+    if (!*fallback && bs->drv && bs->drv->is_filter) {
+        fallback = &bs->backing;
+    }
+
+    if (!*fallback) {
+        return NULL;
+    }
+
+    /*
+     * Check that there are no other children that would need to be
+     * snapshotted.  If there are, it is not safe to fall back to
+     * *fallback.
+     */
+    QLIST_FOREACH(child, &bs->children, next) {
+        if (child->role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
+                           BDRV_CHILD_FILTERED) &&
+            child != *fallback)
+        {
+            return NULL;
+        }
+    }
+
+    return fallback;
+}
+
+static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs)
+{
+    BdrvChild **child_ptr = bdrv_snapshot_fallback_ptr(bs);
+    return child_ptr ? (*child_ptr)->bs : NULL;
+}
+
 int bdrv_can_snapshot(BlockDriverState *bs)
 {
     BlockDriver *drv = bs->drv;
@@ -155,8 +205,9 @@ int bdrv_can_snapshot(BlockDriverState *bs)
     }
 
     if (!drv->bdrv_snapshot_create) {
-        if (bs->file != NULL) {
-            return bdrv_can_snapshot(bs->file->bs);
+        BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs);
+        if (fallback_bs) {
+            return bdrv_can_snapshot(fallback_bs);
         }
         return 0;
     }
@@ -168,14 +219,15 @@ int bdrv_snapshot_create(BlockDriverState *bs,
                          QEMUSnapshotInfo *sn_info)
 {
     BlockDriver *drv = bs->drv;
+    BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs);
     if (!drv) {
         return -ENOMEDIUM;
     }
     if (drv->bdrv_snapshot_create) {
         return drv->bdrv_snapshot_create(bs, sn_info);
     }
-    if (bs->file) {
-        return bdrv_snapshot_create(bs->file->bs, sn_info);
+    if (fallback_bs) {
+        return bdrv_snapshot_create(fallback_bs, sn_info);
     }
     return -ENOTSUP;
 }
@@ -185,6 +237,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
                        Error **errp)
 {
     BlockDriver *drv = bs->drv;
+    BdrvChild **fallback_ptr;
     int ret, open_ret;
 
     if (!drv) {
@@ -205,39 +258,46 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
         return ret;
     }
 
-    if (bs->file) {
-        BlockDriverState *file;
-        QDict *options = qdict_clone_shallow(bs->options);
+    fallback_ptr = bdrv_snapshot_fallback_ptr(bs);
+    if (fallback_ptr) {
+        QDict *options;
         QDict *file_options;
         Error *local_err = NULL;
+        BlockDriverState *fallback_bs = (*fallback_ptr)->bs;
+        char *subqdict_prefix = g_strdup_printf("%s.", (*fallback_ptr)->name);
+
+        options = qdict_clone_shallow(bs->options);
 
-        file = bs->file->bs;
         /* Prevent it from getting deleted when detached from bs */
-        bdrv_ref(file);
+        bdrv_ref(fallback_bs);
 
-        qdict_extract_subqdict(options, &file_options, "file.");
+        qdict_extract_subqdict(options, &file_options, subqdict_prefix);
         qobject_unref(file_options);
-        qdict_put_str(options, "file", bdrv_get_node_name(file));
+        g_free(subqdict_prefix);
+
+        qdict_put_str(options, (*fallback_ptr)->name,
+                      bdrv_get_node_name(fallback_bs));
 
         if (drv->bdrv_close) {
             drv->bdrv_close(bs);
         }
-        bdrv_unref_child(bs, bs->file);
-        bs->file = NULL;
 
-        ret = bdrv_snapshot_goto(file, snapshot_id, errp);
+        bdrv_unref_child(bs, *fallback_ptr);
+        *fallback_ptr = NULL;
+
+        ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
         open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
         qobject_unref(options);
         if (open_ret < 0) {
-            bdrv_unref(file);
+            bdrv_unref(fallback_bs);
             bs->drv = NULL;
             /* A bdrv_snapshot_goto() error takes precedence */
             error_propagate(errp, local_err);
             return ret < 0 ? ret : open_ret;
         }
 
-        assert(bs->file->bs == file);
-        bdrv_unref(file);
+        assert(fallback_bs == (*fallback_ptr)->bs);
+        bdrv_unref(fallback_bs);
         return ret;
     }
 
@@ -273,6 +333,7 @@ int bdrv_snapshot_delete(BlockDriverState *bs,
                          Error **errp)
 {
     BlockDriver *drv = bs->drv;
+    BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs);
     int ret;
 
     if (!drv) {
@@ -289,8 +350,8 @@ int bdrv_snapshot_delete(BlockDriverState *bs,
 
     if (drv->bdrv_snapshot_delete) {
         ret = drv->bdrv_snapshot_delete(bs, snapshot_id, name, errp);
-    } else if (bs->file) {
-        ret = bdrv_snapshot_delete(bs->file->bs, snapshot_id, name, errp);
+    } else if (fallback_bs) {
+        ret = bdrv_snapshot_delete(fallback_bs, snapshot_id, name, errp);
     } else {
         error_setg(errp, "Block format '%s' used by device '%s' "
                    "does not support internal snapshot deletion",
@@ -306,14 +367,15 @@ int bdrv_snapshot_list(BlockDriverState *bs,
                        QEMUSnapshotInfo **psn_info)
 {
     BlockDriver *drv = bs->drv;
+    BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs);
     if (!drv) {
         return -ENOMEDIUM;
     }
     if (drv->bdrv_snapshot_list) {
         return drv->bdrv_snapshot_list(bs, psn_info);
     }
-    if (bs->file) {
-        return bdrv_snapshot_list(bs->file->bs, psn_info);
+    if (fallback_bs) {
+        return bdrv_snapshot_list(fallback_bs, psn_info);
     }
     return -ENOTSUP;
 }
diff --git a/block/stream.c b/block/stream.c
index 310ccbaa4c..8ce6729a33 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -31,7 +31,8 @@ enum {
 
 typedef struct StreamBlockJob {
     BlockJob common;
-    BlockDriverState *bottom;
+    BlockDriverState *base_overlay; /* COW overlay (stream from this) */
+    BlockDriverState *above_base;   /* Node directly above the base */
     BlockdevOnError on_error;
     char *backing_file_str;
     bool bs_read_only;
@@ -53,7 +54,7 @@ static void stream_abort(Job *job)
 
     if (s->chain_frozen) {
         BlockJob *bjob = &s->common;
-        bdrv_unfreeze_backing_chain(blk_bs(bjob->blk), s->bottom);
+        bdrv_unfreeze_backing_chain(blk_bs(bjob->blk), s->above_base);
     }
 }
 
@@ -62,14 +63,15 @@ static int stream_prepare(Job *job)
     StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
     BlockJob *bjob = &s->common;
     BlockDriverState *bs = blk_bs(bjob->blk);
-    BlockDriverState *base = backing_bs(s->bottom);
+    BlockDriverState *unfiltered_bs = bdrv_skip_filters(bs);
+    BlockDriverState *base = bdrv_filter_or_cow_bs(s->above_base);
     Error *local_err = NULL;
     int ret = 0;
 
-    bdrv_unfreeze_backing_chain(bs, s->bottom);
+    bdrv_unfreeze_backing_chain(bs, s->above_base);
     s->chain_frozen = false;
 
-    if (bs->backing) {
+    if (bdrv_cow_child(unfiltered_bs)) {
         const char *base_id = NULL, *base_fmt = NULL;
         if (base) {
             base_id = s->backing_file_str;
@@ -77,8 +79,8 @@ static int stream_prepare(Job *job)
                 base_fmt = base->drv->format_name;
             }
         }
-        bdrv_set_backing_hd(bs, base, &local_err);
-        ret = bdrv_change_backing_file(bs, base_id, base_fmt, false);
+        bdrv_set_backing_hd(unfiltered_bs, base, &local_err);
+        ret = bdrv_change_backing_file(unfiltered_bs, base_id, base_fmt, false);
         if (local_err) {
             error_report_err(local_err);
             return -EPERM;
@@ -109,14 +111,15 @@ static int coroutine_fn stream_run(Job *job, Error **errp)
     StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
     BlockBackend *blk = s->common.blk;
     BlockDriverState *bs = blk_bs(blk);
-    bool enable_cor = !backing_bs(s->bottom);
+    BlockDriverState *unfiltered_bs = bdrv_skip_filters(bs);
+    bool enable_cor = !bdrv_cow_child(s->base_overlay);
     int64_t len;
     int64_t offset = 0;
     uint64_t delay_ns = 0;
     int error = 0;
     int64_t n = 0; /* bytes */
 
-    if (bs == s->bottom) {
+    if (unfiltered_bs == s->base_overlay) {
         /* Nothing to stream */
         return 0;
     }
@@ -150,13 +153,14 @@ static int coroutine_fn stream_run(Job *job, Error **errp)
 
         copy = false;
 
-        ret = bdrv_is_allocated(bs, offset, STREAM_CHUNK, &n);
+        ret = bdrv_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n);
         if (ret == 1) {
             /* Allocated in the top, no need to copy.  */
         } else if (ret >= 0) {
             /* Copy if allocated in the intermediate images.  Limit to the
              * known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE).  */
-            ret = bdrv_is_allocated_above(backing_bs(bs), s->bottom, true,
+            ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs),
+                                          s->base_overlay, true,
                                           offset, n, &n);
             /* Finish early if end of backing file has been reached */
             if (ret == 0 && n == 0) {
@@ -223,9 +227,29 @@ void stream_start(const char *job_id, BlockDriverState *bs,
     BlockDriverState *iter;
     bool bs_read_only;
     int basic_flags = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED;
-    BlockDriverState *bottom = bdrv_find_overlay(bs, base);
+    BlockDriverState *base_overlay = bdrv_find_overlay(bs, base);
+    BlockDriverState *above_base;
 
-    if (bdrv_freeze_backing_chain(bs, bottom, errp) < 0) {
+    if (!base_overlay) {
+        error_setg(errp, "'%s' is not in the backing chain of '%s'",
+                   base->node_name, bs->node_name);
+        return;
+    }
+
+    /*
+     * Find the node directly above @base.  @base_overlay is a COW overlay, so
+     * it must have a bdrv_cow_child(), but it is the immediate overlay of
+     * @base, so between the two there can only be filters.
+     */
+    above_base = base_overlay;
+    if (bdrv_cow_bs(above_base) != base) {
+        above_base = bdrv_cow_bs(above_base);
+        while (bdrv_filter_bs(above_base) != base) {
+            above_base = bdrv_filter_bs(above_base);
+        }
+    }
+
+    if (bdrv_freeze_backing_chain(bs, above_base, errp) < 0) {
         return;
     }
 
@@ -255,14 +279,19 @@ void stream_start(const char *job_id, BlockDriverState *bs,
      * and resizes. Reassign the base node pointer because the backing BS of the
      * bottom node might change after the call to bdrv_reopen_set_read_only()
      * due to parallel block jobs running.
+     * above_base node might change after the call to
+     * bdrv_reopen_set_read_only() due to parallel block jobs running.
      */
-    base = backing_bs(bottom);
-    for (iter = backing_bs(bs); iter && iter != base; iter = backing_bs(iter)) {
+    base = bdrv_filter_or_cow_bs(above_base);
+    for (iter = bdrv_filter_or_cow_bs(bs); iter != base;
+         iter = bdrv_filter_or_cow_bs(iter))
+    {
         block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
                            basic_flags, &error_abort);
     }
 
-    s->bottom = bottom;
+    s->base_overlay = base_overlay;
+    s->above_base = above_base;
     s->backing_file_str = g_strdup(backing_file_str);
     s->bs_read_only = bs_read_only;
     s->chain_frozen = true;
@@ -276,5 +305,5 @@ fail:
     if (bs_read_only) {
         bdrv_reopen_set_read_only(bs, true, NULL);
     }
-    bdrv_unfreeze_backing_chain(bs, bottom);
+    bdrv_unfreeze_backing_chain(bs, above_base);
 }
diff --git a/block/throttle.c b/block/throttle.c
index 1c1ac57bee..9a0f38149a 100644
--- a/block/throttle.c
+++ b/block/throttle.c
@@ -151,6 +151,15 @@ static int coroutine_fn throttle_co_pdiscard(BlockDriverState *bs,
     return bdrv_co_pdiscard(bs->file, offset, bytes);
 }
 
+static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs,
+                                                       uint64_t offset,
+                                                       uint64_t bytes,
+                                                       QEMUIOVector *qiov)
+{
+    return throttle_co_pwritev(bs, offset, bytes, qiov,
+                               BDRV_REQ_WRITE_COMPRESSED);
+}
+
 static int throttle_co_flush(BlockDriverState *bs)
 {
     return bdrv_co_flush(bs->file->bs);
@@ -243,6 +252,7 @@ static BlockDriver bdrv_throttle = {
 
     .bdrv_co_pwrite_zeroes              =   throttle_co_pwrite_zeroes,
     .bdrv_co_pdiscard                   =   throttle_co_pdiscard,
+    .bdrv_co_pwritev_compressed         =   throttle_co_pwritev_compressed,
 
     .bdrv_attach_aio_context            =   throttle_attach_aio_context,
     .bdrv_detach_aio_context            =   throttle_detach_aio_context,
@@ -250,7 +260,6 @@ static BlockDriver bdrv_throttle = {
     .bdrv_reopen_prepare                =   throttle_reopen_prepare,
     .bdrv_reopen_commit                 =   throttle_reopen_commit,
     .bdrv_reopen_abort                  =   throttle_reopen_abort,
-    .bdrv_co_block_status               =   bdrv_co_block_status_from_file,
 
     .bdrv_co_drain_begin                =   throttle_co_drain_begin,
     .bdrv_co_drain_end                  =   throttle_co_drain_end,
diff --git a/block/trace-events b/block/trace-events
index e1c79a910d..0e351c3fa3 100644
--- a/block/trace-events
+++ b/block/trace-events
@@ -42,7 +42,6 @@ backup_do_cow_enter(void *job, int64_t start, int64_t offset, uint64_t bytes) "j
 backup_do_cow_return(void *job, int64_t offset, uint64_t bytes, int ret) "job %p offset %" PRId64 " bytes %" PRIu64 " ret %d"
 
 # block-copy.c
-block_copy_skip(void *bcs, int64_t start) "bcs %p start %"PRId64
 block_copy_skip_range(void *bcs, int64_t start, uint64_t bytes) "bcs %p start %"PRId64" bytes %"PRId64
 block_copy_process(void *bcs, int64_t start) "bcs %p start %"PRId64
 block_copy_copy_range_fail(void *bcs, int64_t start, int ret) "bcs %p start %"PRId64" ret %d"
@@ -59,12 +58,10 @@ qmp_block_job_finalize(void *job) "job %p"
 qmp_block_job_dismiss(void *job) "job %p"
 qmp_block_stream(void *bs) "bs %p"
 
-# file-posix.c
 # file-win32.c
 file_paio_submit(void *acb, void *opaque, int64_t offset, int count, int type) "acb %p opaque %p offset %"PRId64" count %d type %d"
-file_copy_file_range(void *bs, int src, int64_t src_off, int dst, int64_t dst_off, int64_t bytes, int flags, int64_t ret) "bs %p src_fd %d offset %"PRIu64" dst_fd %d offset %"PRIu64" bytes %"PRIu64" flags %d ret %"PRId64
 
-#io_uring.c
+# io_uring.c
 luring_init_state(void *s, size_t size) "s %p size %zu"
 luring_cleanup_state(void *s) "%p freed"
 luring_io_plug(void *s) "LuringState %p plug"
@@ -200,8 +197,7 @@ curl_setup_preadv(uint64_t bytes, uint64_t start, const char *range) "reading %"
 curl_close(void) "close"
 
 # file-posix.c
-file_xfs_write_zeroes(const char *error) "cannot write zero range (%s)"
-file_xfs_discard(const char *error) "cannot punch hole (%s)"
+file_copy_file_range(void *bs, int src, int64_t src_off, int dst, int64_t dst_off, int64_t bytes, int flags, int64_t ret) "bs %p src_fd %d offset %"PRIu64" dst_fd %d offset %"PRIu64" bytes %"PRIu64" flags %d ret %"PRId64
 file_FindEjectableOpticalMedia(const char *media) "Matching using %s"
 file_setup_cdrom(const char *partition) "Using %s as optical disc"
 file_hdev_is_sg(int type, int version) "SG device found: type=%d, version=%d"
diff --git a/block/vmdk.c b/block/vmdk.c
index d90855446a..8ec62c7ab7 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -2803,21 +2803,6 @@ static void vmdk_close(BlockDriverState *bs)
     error_free(s->migration_blocker);
 }
 
-static coroutine_fn int vmdk_co_flush(BlockDriverState *bs)
-{
-    BDRVVmdkState *s = bs->opaque;
-    int i, err;
-    int ret = 0;
-
-    for (i = 0; i < s->num_extents; i++) {
-        err = bdrv_co_flush(s->extents[i].file->bs);
-        if (err < 0) {
-            ret = err;
-        }
-    }
-    return ret;
-}
-
 static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs)
 {
     int i;
@@ -3081,7 +3066,6 @@ static BlockDriver bdrv_vmdk = {
     .bdrv_close                   = vmdk_close,
     .bdrv_co_create_opts          = vmdk_co_create_opts,
     .bdrv_co_create               = vmdk_co_create,
-    .bdrv_co_flush_to_disk        = vmdk_co_flush,
     .bdrv_co_block_status         = vmdk_co_block_status,
     .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
     .bdrv_has_zero_init           = vmdk_has_zero_init,
diff --git a/blockdev.c b/blockdev.c
index 3848a9c8ab..7f2561081e 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1562,7 +1562,12 @@ static void external_snapshot_prepare(BlkActionState *common,
         goto out;
     }
 
-    if (state->new_bs->backing != NULL) {
+    if (state->new_bs->drv->is_filter) {
+        error_setg(errp, "Filters cannot be used as overlays");
+        goto out;
+    }
+
+    if (bdrv_cow_child(state->new_bs)) {
         error_setg(errp, "The overlay already has a backing image");
         goto out;
     }
@@ -1736,7 +1741,13 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
      * on top of.
      */
     if (backup->sync == MIRROR_SYNC_MODE_TOP) {
-        source = backing_bs(bs);
+        /*
+         * Backup will not replace the source by the target, so none
+         * of the filters skipped here will be removed (in contrast to
+         * mirror).  Therefore, we can skip all of them when looking
+         * for the first COW relationship.
+         */
+        source = bdrv_cow_bs(bdrv_skip_filters(bs));
         if (!source) {
             backup->sync = MIRROR_SYNC_MODE_FULL;
         }
@@ -1756,9 +1767,14 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
     if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
         assert(backup->format);
         if (source) {
-            bdrv_refresh_filename(source);
-            bdrv_img_create(backup->target, backup->format, source->filename,
-                            source->drv->format_name, NULL,
+            /* Implicit filters should not appear in the filename */
+            BlockDriverState *explicit_backing =
+                bdrv_skip_implicit_filters(source);
+
+            bdrv_refresh_filename(explicit_backing);
+            bdrv_img_create(backup->target, backup->format,
+                            explicit_backing->filename,
+                            explicit_backing->drv->format_name, NULL,
                             size, flags, false, &local_err);
         } else {
             bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL,
@@ -2528,7 +2544,9 @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
     }
 
     /* Check for op blockers in the whole chain between bs and base */
-    for (iter = bs; iter && iter != base_bs; iter = backing_bs(iter)) {
+    for (iter = bs; iter && iter != base_bs;
+         iter = bdrv_filter_or_cow_bs(iter))
+    {
         if (bdrv_op_is_blocked(iter, BLOCK_OP_TYPE_STREAM, errp)) {
             goto out;
         }
@@ -2584,6 +2602,7 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
     AioContext *aio_context;
     Error *local_err = NULL;
     int job_flags = JOB_DEFAULT;
+    uint64_t top_perm, top_shared;
 
     if (!has_speed) {
         speed = 0;
@@ -2685,7 +2704,9 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
 
     assert(bdrv_get_aio_context(base_bs) == aio_context);
 
-    for (iter = top_bs; iter != backing_bs(base_bs); iter = backing_bs(iter)) {
+    for (iter = top_bs; iter != bdrv_filter_or_cow_bs(base_bs);
+         iter = bdrv_filter_or_cow_bs(iter))
+    {
         if (bdrv_op_is_blocked(iter, BLOCK_OP_TYPE_COMMIT_TARGET, errp)) {
             goto out;
         }
@@ -2697,14 +2718,38 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
         goto out;
     }
 
-    if (top_bs == bs) {
+    /*
+     * Active commit is required if and only if someone has taken a
+     * WRITE permission on the top node.  Historically, we have always
+     * used active commit for top nodes, so continue that practice
+     * lest we possibly break clients that rely on this behavior, e.g.
+     * to later attach this node to a writing parent.
+     * (Active commit is never really wrong.)
+     */
+    bdrv_get_cumulative_perm(top_bs, &top_perm, &top_shared);
+    if (top_perm & BLK_PERM_WRITE ||
+        bdrv_skip_filters(top_bs) == bdrv_skip_filters(bs))
+    {
         if (has_backing_file) {
-            error_setg(errp, "'backing-file' specified,"
-                             " but 'top' is the active layer");
+            if (bdrv_skip_filters(top_bs) == bdrv_skip_filters(bs)) {
+                error_setg(errp, "'backing-file' specified,"
+                                 " but 'top' is the active layer");
+            } else {
+                error_setg(errp, "'backing-file' specified, but 'top' has a "
+                                 "writer on it");
+            }
             goto out;
         }
-        commit_active_start(has_job_id ? job_id : NULL, bs, base_bs,
-                            job_flags, speed, on_error,
+        if (!has_job_id) {
+            /*
+             * Emulate here what block_job_create() does, because it
+             * is possible that @bs != @top_bs (the block job should
+             * be named after @bs, even if @top_bs is the actual
+             * source)
+             */
+            job_id = bdrv_get_device_name(bs);
+        }
+        commit_active_start(job_id, top_bs, base_bs, job_flags, speed, on_error,
                             filter_node_name, NULL, NULL, false, &local_err);
     } else {
         BlockDriverState *overlay_bs = bdrv_find_overlay(bs, top_bs);
@@ -2892,6 +2937,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
                                    bool has_auto_dismiss, bool auto_dismiss,
                                    Error **errp)
 {
+    BlockDriverState *unfiltered_bs;
     int job_flags = JOB_DEFAULT;
 
     if (!has_speed) {
@@ -2943,10 +2989,19 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
         return;
     }
 
-    if (!bs->backing && sync == MIRROR_SYNC_MODE_TOP) {
+    if (!bdrv_backing_chain_next(bs) && sync == MIRROR_SYNC_MODE_TOP) {
         sync = MIRROR_SYNC_MODE_FULL;
     }
 
+    if (!has_replaces) {
+        /* We want to mirror from @bs, but keep implicit filters on top */
+        unfiltered_bs = bdrv_skip_implicit_filters(bs);
+        if (unfiltered_bs != bs) {
+            replaces = unfiltered_bs->node_name;
+            has_replaces = true;
+        }
+    }
+
     if (has_replaces) {
         BlockDriverState *to_replace_bs;
         AioContext *replace_aio_context;
@@ -2993,7 +3048,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
 void qmp_drive_mirror(DriveMirror *arg, Error **errp)
 {
     BlockDriverState *bs;
-    BlockDriverState *source, *target_bs;
+    BlockDriverState *target_backing_bs, *target_bs;
     AioContext *aio_context;
     AioContext *old_context;
     BlockMirrorBackingMode backing_mode;
@@ -3028,12 +3083,12 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
     }
 
     flags = bs->open_flags | BDRV_O_RDWR;
-    source = backing_bs(bs);
-    if (!source && arg->sync == MIRROR_SYNC_MODE_TOP) {
+    target_backing_bs = bdrv_cow_bs(bdrv_skip_filters(bs));
+    if (!target_backing_bs && arg->sync == MIRROR_SYNC_MODE_TOP) {
         arg->sync = MIRROR_SYNC_MODE_FULL;
     }
     if (arg->sync == MIRROR_SYNC_MODE_NONE) {
-        source = bs;
+        target_backing_bs = bs;
     }
 
     size = bdrv_getlength(bs);
@@ -3059,7 +3114,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
     /* Don't open backing image in create() */
     flags |= BDRV_O_NO_BACKING;
 
-    if ((arg->sync == MIRROR_SYNC_MODE_FULL || !source)
+    if ((arg->sync == MIRROR_SYNC_MODE_FULL || !target_backing_bs)
         && arg->mode != NEW_IMAGE_MODE_EXISTING)
     {
         /* create new image w/o backing file */
@@ -3067,15 +3122,19 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
         bdrv_img_create(arg->target, format,
                         NULL, NULL, NULL, size, flags, false, &local_err);
     } else {
+        /* Implicit filters should not appear in the filename */
+        BlockDriverState *explicit_backing =
+            bdrv_skip_implicit_filters(target_backing_bs);
+
         switch (arg->mode) {
         case NEW_IMAGE_MODE_EXISTING:
             break;
         case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
             /* create new image with backing file */
-            bdrv_refresh_filename(source);
+            bdrv_refresh_filename(explicit_backing);
             bdrv_img_create(arg->target, format,
-                            source->filename,
-                            source->drv->format_name,
+                            explicit_backing->filename,
+                            explicit_backing->drv->format_name,
                             NULL, size, flags, false, &local_err);
             break;
         default:
diff --git a/chardev/baum.c b/chardev/baum.c
index 9c95e7bc79..5deca778bc 100644
--- a/chardev/baum.c
+++ b/chardev/baum.c
@@ -33,6 +33,7 @@
 #include <brlapi.h>
 #include <brlapi_constants.h>
 #include <brlapi_keycodes.h>
+#include "qom/object.h"
 
 #if 0
 #define DPRINTF(fmt, ...) \
@@ -86,7 +87,7 @@
 
 #define BUF_SIZE 256
 
-typedef struct {
+struct BaumChardev {
     Chardev parent;
 
     brlapi_handle_t *brlapi;
@@ -100,10 +101,12 @@ typedef struct {
     uint8_t out_buf_used, out_buf_ptr;
 
     QEMUTimer *cellCount_timer;
-} BaumChardev;
+};
+typedef struct BaumChardev BaumChardev;
 
 #define TYPE_CHARDEV_BRAILLE "chardev-braille"
-#define BAUM_CHARDEV(obj) OBJECT_CHECK(BaumChardev, (obj), TYPE_CHARDEV_BRAILLE)
+DECLARE_INSTANCE_CHECKER(BaumChardev, BAUM_CHARDEV,
+                         TYPE_CHARDEV_BRAILLE)
 
 /* Let's assume NABCC by default */
 enum way {
diff --git a/chardev/char-pty.c b/chardev/char-pty.c
index 1cc501a481..a2d1e7c985 100644
--- a/chardev/char-pty.c
+++ b/chardev/char-pty.c
@@ -33,17 +33,20 @@
 #include "qemu/qemu-print.h"
 
 #include "chardev/char-io.h"
+#include "qom/object.h"
 
-typedef struct {
+struct PtyChardev {
     Chardev parent;
     QIOChannel *ioc;
     int read_bytes;
 
     int connected;
     GSource *timer_src;
-} PtyChardev;
+};
+typedef struct PtyChardev PtyChardev;
 
-#define PTY_CHARDEV(obj) OBJECT_CHECK(PtyChardev, (obj), TYPE_CHARDEV_PTY)
+DECLARE_INSTANCE_CHECKER(PtyChardev, PTY_CHARDEV,
+                         TYPE_CHARDEV_PTY)
 
 static void pty_chr_state(Chardev *chr, int connected);
 
diff --git a/chardev/char-ringbuf.c b/chardev/char-ringbuf.c
index 67397a8ce9..d40d21d3cf 100644
--- a/chardev/char-ringbuf.c
+++ b/chardev/char-ringbuf.c
@@ -29,19 +29,21 @@
 #include "qemu/base64.h"
 #include "qemu/module.h"
 #include "qemu/option.h"
+#include "qom/object.h"
 
 /* Ring buffer chardev */
 
-typedef struct {
+struct RingBufChardev {
     Chardev parent;
     size_t size;
     size_t prod;
     size_t cons;
     uint8_t *cbuf;
-} RingBufChardev;
+};
+typedef struct RingBufChardev RingBufChardev;
 
-#define RINGBUF_CHARDEV(obj)                                    \
-    OBJECT_CHECK(RingBufChardev, (obj), TYPE_CHARDEV_RINGBUF)
+DECLARE_INSTANCE_CHECKER(RingBufChardev, RINGBUF_CHARDEV,
+                         TYPE_CHARDEV_RINGBUF)
 
 static size_t ringbuf_count(const Chardev *chr)
 {
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index ef62dbf3d7..95e45812d5 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -36,6 +36,7 @@
 #include "qapi/qapi-visit-sockets.h"
 
 #include "chardev/char-io.h"
+#include "qom/object.h"
 
 /***********************************************************/
 /* TCP Net console */
@@ -53,7 +54,7 @@ typedef enum {
     TCP_CHARDEV_STATE_CONNECTED,
 } TCPChardevState;
 
-typedef struct {
+struct SocketChardev {
     Chardev parent;
     QIOChannel *ioc; /* Client I/O channel */
     QIOChannelSocket *sioc; /* Client master channel */
@@ -84,10 +85,11 @@ typedef struct {
     bool connect_err_reported;
 
     QIOTask *connect_task;
-} SocketChardev;
+};
+typedef struct SocketChardev SocketChardev;
 
-#define SOCKET_CHARDEV(obj)                                     \
-    OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET)
+DECLARE_INSTANCE_CHECKER(SocketChardev, SOCKET_CHARDEV,
+                         TYPE_CHARDEV_SOCKET)
 
 static gboolean socket_reconnect_timeout(gpointer opaque);
 static void tcp_chr_telnet_init(Chardev *chr);
diff --git a/chardev/char-udp.c b/chardev/char-udp.c
index bba4145f96..16b5dbce58 100644
--- a/chardev/char-udp.c
+++ b/chardev/char-udp.c
@@ -30,20 +30,23 @@
 #include "qemu/option.h"
 
 #include "chardev/char-io.h"
+#include "qom/object.h"
 
 /***********************************************************/
 /* UDP Net console */
 
-typedef struct {
+struct UdpChardev {
     Chardev parent;
     QIOChannel *ioc;
     uint8_t buf[CHR_READ_BUF_LEN];
     int bufcnt;
     int bufptr;
     int max_size;
-} UdpChardev;
+};
+typedef struct UdpChardev UdpChardev;
 
-#define UDP_CHARDEV(obj) OBJECT_CHECK(UdpChardev, (obj), TYPE_CHARDEV_UDP)
+DECLARE_INSTANCE_CHECKER(UdpChardev, UDP_CHARDEV,
+                         TYPE_CHARDEV_UDP)
 
 /* Called with chr_write_lock held.  */
 static int udp_chr_write(Chardev *chr, const uint8_t *buf, int len)
diff --git a/chardev/char-win-stdio.c b/chardev/char-win-stdio.c
index 99afda353c..a4771ab82e 100644
--- a/chardev/char-win-stdio.c
+++ b/chardev/char-win-stdio.c
@@ -28,18 +28,20 @@
 #include "qemu/module.h"
 #include "chardev/char-win.h"
 #include "chardev/char-win-stdio.h"
+#include "qom/object.h"
 
-typedef struct {
+struct WinStdioChardev {
     Chardev parent;
     HANDLE  hStdIn;
     HANDLE  hInputReadyEvent;
     HANDLE  hInputDoneEvent;
     HANDLE  hInputThread;
     uint8_t win_stdio_buf;
-} WinStdioChardev;
+};
+typedef struct WinStdioChardev WinStdioChardev;
 
-#define WIN_STDIO_CHARDEV(obj)                                          \
-    OBJECT_CHECK(WinStdioChardev, (obj), TYPE_CHARDEV_WIN_STDIO)
+DECLARE_INSTANCE_CHECKER(WinStdioChardev, WIN_STDIO_CHARDEV,
+                         TYPE_CHARDEV_WIN_STDIO)
 
 static void win_stdio_wait_func(void *opaque)
 {
diff --git a/chardev/chardev-internal.h b/chardev/chardev-internal.h
index f4d0429763..aba0240759 100644
--- a/chardev/chardev-internal.h
+++ b/chardev/chardev-internal.h
@@ -32,7 +32,7 @@
 #define MUX_BUFFER_SIZE 32 /* Must be a power of 2.  */
 #define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1)
 
-typedef struct MuxChardev {
+struct MuxChardev {
     Chardev parent;
     CharBackend *backends[MAX_MUX];
     CharBackend chr;
@@ -51,9 +51,11 @@ typedef struct MuxChardev {
     /* Protected by the Chardev chr_write_lock.  */
     int linestart;
     int64_t timestamps_start;
-} MuxChardev;
+};
+typedef struct MuxChardev MuxChardev;
 
-#define MUX_CHARDEV(obj) OBJECT_CHECK(MuxChardev, (obj), TYPE_CHARDEV_MUX)
+DECLARE_INSTANCE_CHECKER(MuxChardev, MUX_CHARDEV,
+                         TYPE_CHARDEV_MUX)
 #define CHARDEV_IS_MUX(chr)                             \
     object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX)
 
diff --git a/chardev/msmouse.c b/chardev/msmouse.c
index 6d8f06fed4..eb9231dcdb 100644
--- a/chardev/msmouse.c
+++ b/chardev/msmouse.c
@@ -27,11 +27,12 @@
 #include "chardev/char.h"
 #include "ui/console.h"
 #include "ui/input.h"
+#include "qom/object.h"
 
 #define MSMOUSE_LO6(n) ((n) & 0x3f)
 #define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
 
-typedef struct {
+struct MouseChardev {
     Chardev parent;
 
     QemuInputHandlerState *hs;
@@ -40,11 +41,12 @@ typedef struct {
     bool btnc[INPUT_BUTTON__MAX];
     uint8_t outbuf[32];
     int outlen;
-} MouseChardev;
+};
+typedef struct MouseChardev MouseChardev;
 
 #define TYPE_CHARDEV_MSMOUSE "chardev-msmouse"
-#define MOUSE_CHARDEV(obj)                                      \
-    OBJECT_CHECK(MouseChardev, (obj), TYPE_CHARDEV_MSMOUSE)
+DECLARE_INSTANCE_CHECKER(MouseChardev, MOUSE_CHARDEV,
+                         TYPE_CHARDEV_MSMOUSE)
 
 static void msmouse_chr_accept_input(Chardev *chr)
 {
diff --git a/chardev/testdev.c b/chardev/testdev.c
index 368a8c041e..a92caca3c3 100644
--- a/chardev/testdev.c
+++ b/chardev/testdev.c
@@ -27,19 +27,21 @@
 #include "qemu/osdep.h"
 #include "qemu/module.h"
 #include "chardev/char.h"
+#include "qom/object.h"
 
 #define BUF_SIZE 32
 
-typedef struct {
+struct TestdevChardev {
     Chardev parent;
 
     uint8_t in_buf[32];
     int in_buf_used;
-} TestdevChardev;
+};
+typedef struct TestdevChardev TestdevChardev;
 
 #define TYPE_CHARDEV_TESTDEV "chardev-testdev"
-#define TESTDEV_CHARDEV(obj)                                    \
-    OBJECT_CHECK(TestdevChardev, (obj), TYPE_CHARDEV_TESTDEV)
+DECLARE_INSTANCE_CHECKER(TestdevChardev, TESTDEV_CHARDEV,
+                         TYPE_CHARDEV_TESTDEV)
 
 /* Try to interpret a whole incoming packet */
 static int testdev_eat_packet(TestdevChardev *testdev)
diff --git a/chardev/wctablet.c b/chardev/wctablet.c
index e9cb7ca710..95e005f5a5 100644
--- a/chardev/wctablet.c
+++ b/chardev/wctablet.c
@@ -32,6 +32,7 @@
 #include "ui/console.h"
 #include "ui/input.h"
 #include "trace.h"
+#include "qom/object.h"
 
 
 #define WC_OUTPUT_BUF_MAX_LEN 512
@@ -64,7 +65,7 @@ uint8_t WC_FULL_CONFIG_STRING[WC_FULL_CONFIG_STRING_LENGTH + 1] = {
 };
 
 /* This structure is used to save private info for Wacom Tablet. */
-typedef struct {
+struct TabletChardev {
     Chardev parent;
     QemuInputHandlerState *hs;
 
@@ -81,11 +82,12 @@ typedef struct {
     int axis[INPUT_AXIS__MAX];
     bool btns[INPUT_BUTTON__MAX];
 
-} TabletChardev;
+};
+typedef struct TabletChardev TabletChardev;
 
 #define TYPE_CHARDEV_WCTABLET "chardev-wctablet"
-#define WCTABLET_CHARDEV(obj)                                      \
-    OBJECT_CHECK(TabletChardev, (obj), TYPE_CHARDEV_WCTABLET)
+DECLARE_INSTANCE_CHECKER(TabletChardev, WCTABLET_CHARDEV,
+                         TYPE_CHARDEV_WCTABLET)
 
 
 static void wctablet_chr_accept_input(Chardev *chr);
diff --git a/configure b/configure
index 4231d56bcc..2b6a1196da 100755
--- a/configure
+++ b/configure
@@ -542,6 +542,8 @@ gettext=""
 bogus_os="no"
 malloc_trim=""
 
+deprecated_features=""
+
 # parse CC options first
 for opt do
   optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
@@ -1720,26 +1722,25 @@ if [ "$bsd_user" = "yes" ]; then
     mak_wilds="${mak_wilds} $source_path/default-configs/*-bsd-user.mak"
 fi
 
-if test -z "$target_list_exclude"; then
-    for config in $mak_wilds; do
-        default_target_list="${default_target_list} $(basename "$config" .mak)"
-    done
-else
-    exclude_list=$(echo "$target_list_exclude" | sed -e 's/,/ /g')
-    for config in $mak_wilds; do
-        target="$(basename "$config" .mak)"
-        exclude="no"
-        for excl in $exclude_list; do
-            if test "$excl" = "$target"; then
-                exclude="yes"
-                break;
-            fi
-        done
-        if test "$exclude" = "no"; then
-            default_target_list="${default_target_list} $target"
+if test -z "$target_list_exclude" -a -z "$target_list"; then
+    # if the user doesn't specify anything lets skip deprecating stuff
+    target_list_exclude=ppc64abi32-linux-user
+fi
+
+exclude_list=$(echo "$target_list_exclude" | sed -e 's/,/ /g')
+for config in $mak_wilds; do
+    target="$(basename "$config" .mak)"
+    exclude="no"
+    for excl in $exclude_list; do
+        if test "$excl" = "$target"; then
+            exclude="yes"
+            break;
         fi
     done
-fi
+    if test "$exclude" = "no"; then
+        default_target_list="${default_target_list} $target"
+    fi
+done
 
 # Enumerate public trace backends for --help output
 trace_backend_list=$(echo $(grep -le '^PUBLIC = True$' "$source_path"/scripts/tracetool/backend/*.py | sed -e 's/^.*\/\(.*\)\.py$/\1/'))
@@ -7557,7 +7558,7 @@ TARGET_SYSTBL=""
 case "$target_name" in
   i386)
     mttcg="yes"
-	gdb_xml_files="i386-32bit.xml"
+    gdb_xml_files="i386-32bit.xml"
     TARGET_SYSTBL_ABI=i386
     TARGET_SYSTBL=syscall_32.tbl
   ;;
@@ -7667,6 +7668,7 @@ case "$target_name" in
     TARGET_SYSTBL_ABI=common,nospu,32
     echo "TARGET_ABI32=y" >> $config_target_mak
     gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml"
+    deprecated_features="ppc64abi32 ${deprecated_features}"
   ;;
   riscv32)
     TARGET_BASE_ARCH=riscv
@@ -7853,6 +7855,7 @@ DIRS="$DIRS tests/qtest tests/qemu-iotests tests/vm tests/fp tests/qgraph"
 DIRS="$DIRS docs docs/interop fsdev scsi"
 DIRS="$DIRS pc-bios/optionrom pc-bios/s390-ccw"
 DIRS="$DIRS roms/seabios"
+DIRS="$DIRS contrib/plugins/"
 LINKS="Makefile"
 LINKS="$LINKS tests/tcg/lm32/Makefile"
 LINKS="$LINKS tests/tcg/Makefile.target"
@@ -7864,6 +7867,7 @@ LINKS="$LINKS .gdbinit scripts" # scripts needed by relative path in .gdbinit
 LINKS="$LINKS tests/acceptance tests/data"
 LINKS="$LINKS tests/qemu-iotests/check"
 LINKS="$LINKS python"
+LINKS="$LINKS contrib/plugins/Makefile "
 UNLINK="pc-bios/keymaps"
 for bios_file in \
     $source_path/pc-bios/*.bin \
@@ -8011,6 +8015,12 @@ fi
 touch ninjatool.stamp
 fi
 
+if test -n "${deprecated_features}"; then
+    echo "Warning, deprecated features enabled."
+    echo "Please see docs/system/deprecated.rst"
+    echo "  features: ${deprecated_features}"
+fi
+
 # Save the configure command line for later reuse.
 cat <<EOD >config.status
 #!/bin/sh
diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile
new file mode 100644
index 0000000000..7801b08b0d
--- /dev/null
+++ b/contrib/plugins/Makefile
@@ -0,0 +1,42 @@
+# -*- Mode: makefile -*-
+#
+# This Makefile example is fairly independent from the main makefile
+# so users can take and adapt it for their build. We only really
+# include config-host.mak so we don't have to repeat probing for
+# cflags that the main configure has already done for us.
+#
+
+BUILD_DIR := $(CURDIR)/../..
+
+include $(BUILD_DIR)/config-host.mak
+
+VPATH += $(SRC_PATH)/contrib/plugins
+
+NAMES :=
+NAMES += hotblocks
+NAMES += hotpages
+NAMES += howvec
+NAMES += lockstep
+
+SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES)))
+
+# The main QEMU uses Glib extensively so it's perfectly fine to use it
+# in plugins (which many example do).
+CFLAGS = $(GLIB_CFLAGS)
+CFLAGS += -fPIC
+CFLAGS += $(if $(findstring no-psabi,$(QEMU_CFLAGS)),-Wpsabi)
+CFLAGS += -I$(SRC_PATH)/include/qemu
+
+all: $(SONAMES)
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+lib%.so: %.o
+	$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDLIBS)
+
+clean:
+	rm -f *.o *.so *.d
+	rm -Rf .libs
+
+.PHONY: all clean
diff --git a/tests/plugin/hotblocks.c b/contrib/plugins/hotblocks.c
index 3942a2ca54..3942a2ca54 100644
--- a/tests/plugin/hotblocks.c
+++ b/contrib/plugins/hotblocks.c
diff --git a/tests/plugin/hotpages.c b/contrib/plugins/hotpages.c
index ecd6c18732..ecd6c18732 100644
--- a/tests/plugin/hotpages.c
+++ b/contrib/plugins/hotpages.c
diff --git a/tests/plugin/howvec.c b/contrib/plugins/howvec.c
index 3b9a6939f2..3b9a6939f2 100644
--- a/tests/plugin/howvec.c
+++ b/contrib/plugins/howvec.c
diff --git a/tests/plugin/lockstep.c b/contrib/plugins/lockstep.c
index a696673dff..a696673dff 100644
--- a/tests/plugin/lockstep.c
+++ b/contrib/plugins/lockstep.c
diff --git a/crypto/aes.c b/crypto/aes.c
index 0f6a195af8..159800df65 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -1599,54 +1599,3 @@ void AES_decrypt(const unsigned char *in, unsigned char *out,
 }
 
 #endif /* AES_ASM */
-
-void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
-                     const unsigned long length, const AES_KEY *key,
-                     unsigned char *ivec, const int enc)
-{
-
-        unsigned long n;
-        unsigned long len = length;
-        unsigned char tmp[AES_BLOCK_SIZE];
-
-        assert(in && out && key && ivec);
-
-        if (enc) {
-                while (len >= AES_BLOCK_SIZE) {
-                        for(n=0; n < AES_BLOCK_SIZE; ++n)
-                                tmp[n] = in[n] ^ ivec[n];
-                        AES_encrypt(tmp, out, key);
-                        memcpy(ivec, out, AES_BLOCK_SIZE);
-                        len -= AES_BLOCK_SIZE;
-                        in += AES_BLOCK_SIZE;
-                        out += AES_BLOCK_SIZE;
-                }
-                if (len) {
-                        for(n=0; n < len; ++n)
-                                tmp[n] = in[n] ^ ivec[n];
-                        for(n=len; n < AES_BLOCK_SIZE; ++n)
-                                tmp[n] = ivec[n];
-                        AES_encrypt(tmp, tmp, key);
-                        memcpy(out, tmp, AES_BLOCK_SIZE);
-                        memcpy(ivec, tmp, AES_BLOCK_SIZE);
-                }
-        } else {
-                while (len >= AES_BLOCK_SIZE) {
-                        memcpy(tmp, in, AES_BLOCK_SIZE);
-                        AES_decrypt(in, out, key);
-                        for(n=0; n < AES_BLOCK_SIZE; ++n)
-                                out[n] ^= ivec[n];
-                        memcpy(ivec, tmp, AES_BLOCK_SIZE);
-                        len -= AES_BLOCK_SIZE;
-                        in += AES_BLOCK_SIZE;
-                        out += AES_BLOCK_SIZE;
-                }
-                if (len) {
-                        memcpy(tmp, in, AES_BLOCK_SIZE);
-                        AES_decrypt(tmp, tmp, key);
-                        for(n=0; n < len; ++n)
-                                out[n] = tmp[n] ^ ivec[n];
-                        memcpy(ivec, tmp, AES_BLOCK_SIZE);
-                }
-        }
-}
diff --git a/crypto/afalgpriv.h b/crypto/afalgpriv.h
index f6550b5c51..5a2393f1b7 100644
--- a/crypto/afalgpriv.h
+++ b/crypto/afalgpriv.h
@@ -15,6 +15,7 @@
 #define QCRYPTO_AFALGPRIV_H
 
 #include <linux/if_alg.h>
+#include "crypto/cipher.h"
 
 #define SALG_TYPE_LEN_MAX 14
 #define SALG_NAME_LEN_MAX 64
@@ -32,6 +33,8 @@
 typedef struct QCryptoAFAlg QCryptoAFAlg;
 
 struct QCryptoAFAlg {
+    QCryptoCipher base;
+
     int tfmfd;
     int opfd;
     struct msghdr *msg;
diff --git a/crypto/cipher-afalg.c b/crypto/cipher-afalg.c
index cd72284690..052355a8a9 100644
--- a/crypto/cipher-afalg.c
+++ b/crypto/cipher-afalg.c
@@ -58,7 +58,9 @@ qcrypto_afalg_cipher_format_name(QCryptoCipherAlgorithm alg,
     return name;
 }
 
-QCryptoAFAlg *
+static const struct QCryptoCipherDriver qcrypto_cipher_afalg_driver;
+
+QCryptoCipher *
 qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg,
                              QCryptoCipherMode mode,
                              const uint8_t *key,
@@ -109,7 +111,8 @@ qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg,
     }
     afalg->cmsg = CMSG_FIRSTHDR(afalg->msg);
 
-    return afalg;
+    afalg->base.driver = &qcrypto_cipher_afalg_driver;
+    return &afalg->base;
 }
 
 static int
@@ -117,9 +120,9 @@ qcrypto_afalg_cipher_setiv(QCryptoCipher *cipher,
                            const uint8_t *iv,
                            size_t niv, Error **errp)
 {
+    QCryptoAFAlg *afalg = container_of(cipher, QCryptoAFAlg, base);
     struct af_alg_iv *alg_iv;
     size_t expect_niv;
-    QCryptoAFAlg *afalg = cipher->opaque;
 
     expect_niv = qcrypto_cipher_get_iv_len(cipher->alg, cipher->mode);
     if (niv != expect_niv) {
@@ -200,8 +203,9 @@ qcrypto_afalg_cipher_encrypt(QCryptoCipher *cipher,
                              const void *in, void *out,
                              size_t len, Error **errp)
 {
-    return qcrypto_afalg_cipher_op(cipher->opaque, in, out,
-                                   len, true, errp);
+    QCryptoAFAlg *afalg = container_of(cipher, QCryptoAFAlg, base);
+
+    return qcrypto_afalg_cipher_op(afalg, in, out, len, true, errp);
 }
 
 static int
@@ -209,16 +213,19 @@ qcrypto_afalg_cipher_decrypt(QCryptoCipher *cipher,
                              const void *in, void *out,
                              size_t len, Error **errp)
 {
-    return qcrypto_afalg_cipher_op(cipher->opaque, in, out,
-                                   len, false, errp);
+    QCryptoAFAlg *afalg = container_of(cipher, QCryptoAFAlg, base);
+
+    return qcrypto_afalg_cipher_op(afalg, in, out, len, false, errp);
 }
 
 static void qcrypto_afalg_comm_ctx_free(QCryptoCipher *cipher)
 {
-    qcrypto_afalg_comm_free(cipher->opaque);
+    QCryptoAFAlg *afalg = container_of(cipher, QCryptoAFAlg, base);
+
+    qcrypto_afalg_comm_free(afalg);
 }
 
-struct QCryptoCipherDriver qcrypto_cipher_afalg_driver = {
+static const struct QCryptoCipherDriver qcrypto_cipher_afalg_driver = {
     .cipher_encrypt = qcrypto_afalg_cipher_encrypt,
     .cipher_decrypt = qcrypto_afalg_cipher_decrypt,
     .cipher_setiv = qcrypto_afalg_cipher_setiv,
diff --git a/crypto/cipher-builtin.c b/crypto/cipher-builtin.c
deleted file mode 100644
index 35cf7820d9..0000000000
--- a/crypto/cipher-builtin.c
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * QEMU Crypto cipher built-in algorithms
- *
- * Copyright (c) 2015 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "qemu/osdep.h"
-#include "crypto/aes.h"
-#include "crypto/desrfb.h"
-#include "crypto/xts.h"
-#include "cipherpriv.h"
-
-typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext;
-struct QCryptoCipherBuiltinAESContext {
-    AES_KEY enc;
-    AES_KEY dec;
-};
-typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES;
-struct QCryptoCipherBuiltinAES {
-    QCryptoCipherBuiltinAESContext key;
-    QCryptoCipherBuiltinAESContext key_tweak;
-    uint8_t iv[AES_BLOCK_SIZE];
-};
-typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB;
-struct QCryptoCipherBuiltinDESRFB {
-    uint8_t *key;
-    size_t nkey;
-};
-
-typedef struct QCryptoCipherBuiltin QCryptoCipherBuiltin;
-struct QCryptoCipherBuiltin {
-    union {
-        QCryptoCipherBuiltinAES aes;
-        QCryptoCipherBuiltinDESRFB desrfb;
-    } state;
-    size_t blocksize;
-    void (*free)(QCryptoCipher *cipher);
-    int (*setiv)(QCryptoCipher *cipher,
-                 const uint8_t *iv, size_t niv,
-                 Error **errp);
-    int (*encrypt)(QCryptoCipher *cipher,
-                   const void *in,
-                   void *out,
-                   size_t len,
-                   Error **errp);
-    int (*decrypt)(QCryptoCipher *cipher,
-                   const void *in,
-                   void *out,
-                   size_t len,
-                   Error **errp);
-};
-
-
-static void qcrypto_cipher_free_aes(QCryptoCipher *cipher)
-{
-    QCryptoCipherBuiltin *ctxt = cipher->opaque;
-
-    g_free(ctxt);
-    cipher->opaque = NULL;
-}
-
-
-static void qcrypto_cipher_aes_ecb_encrypt(const AES_KEY *key,
-                                           const void *in,
-                                           void *out,
-                                           size_t len)
-{
-    const uint8_t *inptr = in;
-    uint8_t *outptr = out;
-    while (len) {
-        if (len > AES_BLOCK_SIZE) {
-            AES_encrypt(inptr, outptr, key);
-            inptr += AES_BLOCK_SIZE;
-            outptr += AES_BLOCK_SIZE;
-            len -= AES_BLOCK_SIZE;
-        } else {
-            uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
-            memcpy(tmp1, inptr, len);
-            /* Fill with 0 to avoid valgrind uninitialized reads */
-            memset(tmp1 + len, 0, sizeof(tmp1) - len);
-            AES_encrypt(tmp1, tmp2, key);
-            memcpy(outptr, tmp2, len);
-            len = 0;
-        }
-    }
-}
-
-
-static void qcrypto_cipher_aes_ecb_decrypt(const AES_KEY *key,
-                                           const void *in,
-                                           void *out,
-                                           size_t len)
-{
-    const uint8_t *inptr = in;
-    uint8_t *outptr = out;
-    while (len) {
-        if (len > AES_BLOCK_SIZE) {
-            AES_decrypt(inptr, outptr, key);
-            inptr += AES_BLOCK_SIZE;
-            outptr += AES_BLOCK_SIZE;
-            len -= AES_BLOCK_SIZE;
-        } else {
-            uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
-            memcpy(tmp1, inptr, len);
-            /* Fill with 0 to avoid valgrind uninitialized reads */
-            memset(tmp1 + len, 0, sizeof(tmp1) - len);
-            AES_decrypt(tmp1, tmp2, key);
-            memcpy(outptr, tmp2, len);
-            len = 0;
-        }
-    }
-}
-
-
-static void qcrypto_cipher_aes_xts_encrypt(const void *ctx,
-                                           size_t length,
-                                           uint8_t *dst,
-                                           const uint8_t *src)
-{
-    const QCryptoCipherBuiltinAESContext *aesctx = ctx;
-
-    qcrypto_cipher_aes_ecb_encrypt(&aesctx->enc, src, dst, length);
-}
-
-
-static void qcrypto_cipher_aes_xts_decrypt(const void *ctx,
-                                           size_t length,
-                                           uint8_t *dst,
-                                           const uint8_t *src)
-{
-    const QCryptoCipherBuiltinAESContext *aesctx = ctx;
-
-    qcrypto_cipher_aes_ecb_decrypt(&aesctx->dec, src, dst, length);
-}
-
-
-static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher,
-                                      const void *in,
-                                      void *out,
-                                      size_t len,
-                                      Error **errp)
-{
-    QCryptoCipherBuiltin *ctxt = cipher->opaque;
-
-    switch (cipher->mode) {
-    case QCRYPTO_CIPHER_MODE_ECB:
-        qcrypto_cipher_aes_ecb_encrypt(&ctxt->state.aes.key.enc,
-                                       in, out, len);
-        break;
-    case QCRYPTO_CIPHER_MODE_CBC:
-        AES_cbc_encrypt(in, out, len,
-                        &ctxt->state.aes.key.enc,
-                        ctxt->state.aes.iv, 1);
-        break;
-    case QCRYPTO_CIPHER_MODE_XTS:
-        xts_encrypt(&ctxt->state.aes.key,
-                    &ctxt->state.aes.key_tweak,
-                    qcrypto_cipher_aes_xts_encrypt,
-                    qcrypto_cipher_aes_xts_decrypt,
-                    ctxt->state.aes.iv,
-                    len, out, in);
-        break;
-    default:
-        g_assert_not_reached();
-    }
-
-    return 0;
-}
-
-
-static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher,
-                                      const void *in,
-                                      void *out,
-                                      size_t len,
-                                      Error **errp)
-{
-    QCryptoCipherBuiltin *ctxt = cipher->opaque;
-
-    switch (cipher->mode) {
-    case QCRYPTO_CIPHER_MODE_ECB:
-        qcrypto_cipher_aes_ecb_decrypt(&ctxt->state.aes.key.dec,
-                                       in, out, len);
-        break;
-    case QCRYPTO_CIPHER_MODE_CBC:
-        AES_cbc_encrypt(in, out, len,
-                        &ctxt->state.aes.key.dec,
-                        ctxt->state.aes.iv, 0);
-        break;
-    case QCRYPTO_CIPHER_MODE_XTS:
-        xts_decrypt(&ctxt->state.aes.key,
-                    &ctxt->state.aes.key_tweak,
-                    qcrypto_cipher_aes_xts_encrypt,
-                    qcrypto_cipher_aes_xts_decrypt,
-                    ctxt->state.aes.iv,
-                    len, out, in);
-        break;
-    default:
-        g_assert_not_reached();
-    }
-
-    return 0;
-}
-
-static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher,
-                                     const uint8_t *iv, size_t niv,
-                                     Error **errp)
-{
-    QCryptoCipherBuiltin *ctxt = cipher->opaque;
-    if (niv != AES_BLOCK_SIZE) {
-        error_setg(errp, "IV must be %d bytes not %zu",
-                   AES_BLOCK_SIZE, niv);
-        return -1;
-    }
-
-    memcpy(ctxt->state.aes.iv, iv, AES_BLOCK_SIZE);
-
-    return 0;
-}
-
-
-
-
-static QCryptoCipherBuiltin *
-qcrypto_cipher_init_aes(QCryptoCipherMode mode,
-                        const uint8_t *key, size_t nkey,
-                        Error **errp)
-{
-    QCryptoCipherBuiltin *ctxt;
-
-    if (mode != QCRYPTO_CIPHER_MODE_CBC &&
-        mode != QCRYPTO_CIPHER_MODE_ECB &&
-        mode != QCRYPTO_CIPHER_MODE_XTS) {
-        error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_str(mode));
-        return NULL;
-    }
-
-    ctxt = g_new0(QCryptoCipherBuiltin, 1);
-
-    if (mode == QCRYPTO_CIPHER_MODE_XTS) {
-        if (AES_set_encrypt_key(key, nkey * 4, &ctxt->state.aes.key.enc) != 0) {
-            error_setg(errp, "Failed to set encryption key");
-            goto error;
-        }
-
-        if (AES_set_decrypt_key(key, nkey * 4, &ctxt->state.aes.key.dec) != 0) {
-            error_setg(errp, "Failed to set decryption key");
-            goto error;
-        }
-
-        if (AES_set_encrypt_key(key + (nkey / 2), nkey * 4,
-                                &ctxt->state.aes.key_tweak.enc) != 0) {
-            error_setg(errp, "Failed to set encryption key");
-            goto error;
-        }
-
-        if (AES_set_decrypt_key(key + (nkey / 2), nkey * 4,
-                                &ctxt->state.aes.key_tweak.dec) != 0) {
-            error_setg(errp, "Failed to set decryption key");
-            goto error;
-        }
-    } else {
-        if (AES_set_encrypt_key(key, nkey * 8, &ctxt->state.aes.key.enc) != 0) {
-            error_setg(errp, "Failed to set encryption key");
-            goto error;
-        }
-
-        if (AES_set_decrypt_key(key, nkey * 8, &ctxt->state.aes.key.dec) != 0) {
-            error_setg(errp, "Failed to set decryption key");
-            goto error;
-        }
-    }
-
-    ctxt->blocksize = AES_BLOCK_SIZE;
-    ctxt->free = qcrypto_cipher_free_aes;
-    ctxt->setiv = qcrypto_cipher_setiv_aes;
-    ctxt->encrypt = qcrypto_cipher_encrypt_aes;
-    ctxt->decrypt = qcrypto_cipher_decrypt_aes;
-
-    return ctxt;
-
- error:
-    g_free(ctxt);
-    return NULL;
-}
-
-
-static void qcrypto_cipher_free_des_rfb(QCryptoCipher *cipher)
-{
-    QCryptoCipherBuiltin *ctxt = cipher->opaque;
-
-    g_free(ctxt->state.desrfb.key);
-    g_free(ctxt);
-    cipher->opaque = NULL;
-}
-
-
-static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher,
-                                          const void *in,
-                                          void *out,
-                                          size_t len,
-                                          Error **errp)
-{
-    QCryptoCipherBuiltin *ctxt = cipher->opaque;
-    size_t i;
-
-    if (len % 8) {
-        error_setg(errp, "Buffer size must be multiple of 8 not %zu",
-                   len);
-        return -1;
-    }
-
-    deskey(ctxt->state.desrfb.key, EN0);
-
-    for (i = 0; i < len; i += 8) {
-        des((void *)in + i, out + i);
-    }
-
-    return 0;
-}
-
-
-static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher,
-                                          const void *in,
-                                          void *out,
-                                          size_t len,
-                                          Error **errp)
-{
-    QCryptoCipherBuiltin *ctxt = cipher->opaque;
-    size_t i;
-
-    if (len % 8) {
-        error_setg(errp, "Buffer size must be multiple of 8 not %zu",
-                   len);
-        return -1;
-    }
-
-    deskey(ctxt->state.desrfb.key, DE1);
-
-    for (i = 0; i < len; i += 8) {
-        des((void *)in + i, out + i);
-    }
-
-    return 0;
-}
-
-
-static int qcrypto_cipher_setiv_des_rfb(QCryptoCipher *cipher,
-                                        const uint8_t *iv, size_t niv,
-                                        Error **errp)
-{
-    error_setg(errp, "Setting IV is not supported");
-    return -1;
-}
-
-
-static QCryptoCipherBuiltin *
-qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode,
-                            const uint8_t *key, size_t nkey,
-                            Error **errp)
-{
-    QCryptoCipherBuiltin *ctxt;
-
-    if (mode != QCRYPTO_CIPHER_MODE_ECB) {
-        error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_str(mode));
-        return NULL;
-    }
-
-    ctxt = g_new0(QCryptoCipherBuiltin, 1);
-
-    ctxt->state.desrfb.key = g_new0(uint8_t, nkey);
-    memcpy(ctxt->state.desrfb.key, key, nkey);
-    ctxt->state.desrfb.nkey = nkey;
-
-    ctxt->blocksize = 8;
-    ctxt->free = qcrypto_cipher_free_des_rfb;
-    ctxt->setiv = qcrypto_cipher_setiv_des_rfb;
-    ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb;
-    ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb;
-
-    return ctxt;
-}
-
-
-bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
-                             QCryptoCipherMode mode)
-{
-    switch (alg) {
-    case QCRYPTO_CIPHER_ALG_DES_RFB:
-    case QCRYPTO_CIPHER_ALG_AES_128:
-    case QCRYPTO_CIPHER_ALG_AES_192:
-    case QCRYPTO_CIPHER_ALG_AES_256:
-        break;
-    default:
-        return false;
-    }
-
-    switch (mode) {
-    case QCRYPTO_CIPHER_MODE_ECB:
-    case QCRYPTO_CIPHER_MODE_CBC:
-    case QCRYPTO_CIPHER_MODE_XTS:
-        return true;
-    case QCRYPTO_CIPHER_MODE_CTR:
-        return false;
-    default:
-        return false;
-    }
-}
-
-
-static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
-                                                    QCryptoCipherMode mode,
-                                                    const uint8_t *key,
-                                                    size_t nkey,
-                                                    Error **errp)
-{
-    QCryptoCipherBuiltin *ctxt;
-
-    switch (mode) {
-    case QCRYPTO_CIPHER_MODE_ECB:
-    case QCRYPTO_CIPHER_MODE_CBC:
-    case QCRYPTO_CIPHER_MODE_XTS:
-        break;
-    default:
-        error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_str(mode));
-        return NULL;
-    }
-
-    if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
-        return NULL;
-    }
-
-    switch (alg) {
-    case QCRYPTO_CIPHER_ALG_DES_RFB:
-        ctxt = qcrypto_cipher_init_des_rfb(mode, key, nkey, errp);
-        break;
-    case QCRYPTO_CIPHER_ALG_AES_128:
-    case QCRYPTO_CIPHER_ALG_AES_192:
-    case QCRYPTO_CIPHER_ALG_AES_256:
-        ctxt = qcrypto_cipher_init_aes(mode, key, nkey, errp);
-        break;
-    default:
-        error_setg(errp,
-                   "Unsupported cipher algorithm %s",
-                   QCryptoCipherAlgorithm_str(alg));
-        return NULL;
-    }
-
-    return ctxt;
-}
-
-static void
-qcrypto_builtin_cipher_ctx_free(QCryptoCipher *cipher)
-{
-    QCryptoCipherBuiltin *ctxt;
-
-    ctxt = cipher->opaque;
-    ctxt->free(cipher);
-}
-
-
-static int
-qcrypto_builtin_cipher_encrypt(QCryptoCipher *cipher,
-                               const void *in,
-                               void *out,
-                               size_t len,
-                               Error **errp)
-{
-    QCryptoCipherBuiltin *ctxt = cipher->opaque;
-
-    if (len % ctxt->blocksize) {
-        error_setg(errp, "Length %zu must be a multiple of block size %zu",
-                   len, ctxt->blocksize);
-        return -1;
-    }
-
-    return ctxt->encrypt(cipher, in, out, len, errp);
-}
-
-
-static int
-qcrypto_builtin_cipher_decrypt(QCryptoCipher *cipher,
-                               const void *in,
-                               void *out,
-                               size_t len,
-                               Error **errp)
-{
-    QCryptoCipherBuiltin *ctxt = cipher->opaque;
-
-    if (len % ctxt->blocksize) {
-        error_setg(errp, "Length %zu must be a multiple of block size %zu",
-                   len, ctxt->blocksize);
-        return -1;
-    }
-
-    return ctxt->decrypt(cipher, in, out, len, errp);
-}
-
-
-static int
-qcrypto_builtin_cipher_setiv(QCryptoCipher *cipher,
-                             const uint8_t *iv, size_t niv,
-                             Error **errp)
-{
-    QCryptoCipherBuiltin *ctxt = cipher->opaque;
-
-    return ctxt->setiv(cipher, iv, niv, errp);
-}
-
-
-static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = {
-    .cipher_encrypt = qcrypto_builtin_cipher_encrypt,
-    .cipher_decrypt = qcrypto_builtin_cipher_decrypt,
-    .cipher_setiv = qcrypto_builtin_cipher_setiv,
-    .cipher_free = qcrypto_builtin_cipher_ctx_free,
-};
diff --git a/crypto/cipher-builtin.c.inc b/crypto/cipher-builtin.c.inc
new file mode 100644
index 0000000000..7597cf4a10
--- /dev/null
+++ b/crypto/cipher-builtin.c.inc
@@ -0,0 +1,435 @@
+/*
+ * QEMU Crypto cipher built-in algorithms
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "crypto/aes.h"
+#include "crypto/desrfb.h"
+#include "crypto/xts.h"
+
+typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext;
+struct QCryptoCipherBuiltinAESContext {
+    AES_KEY enc;
+    AES_KEY dec;
+};
+
+typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES;
+struct QCryptoCipherBuiltinAES {
+    QCryptoCipher base;
+    QCryptoCipherBuiltinAESContext key;
+    QCryptoCipherBuiltinAESContext key_tweak;
+    uint8_t iv[AES_BLOCK_SIZE];
+};
+
+
+static inline bool qcrypto_length_check(size_t len, size_t blocksize,
+                                        Error **errp)
+{
+    if (unlikely(len & (blocksize - 1))) {
+        error_setg(errp, "Length %zu must be a multiple of block size %zu",
+                   len, blocksize);
+        return false;
+    }
+    return true;
+}
+
+static void qcrypto_cipher_ctx_free(QCryptoCipher *cipher)
+{
+    g_free(cipher);
+}
+
+static int qcrypto_cipher_no_setiv(QCryptoCipher *cipher,
+                                   const uint8_t *iv, size_t niv,
+                                   Error **errp)
+{
+    error_setg(errp, "Setting IV is not supported");
+    return -1;
+}
+
+static void do_aes_encrypt_ecb(const void *vctx,
+                               size_t len,
+                               uint8_t *out,
+                               const uint8_t *in)
+{
+    const QCryptoCipherBuiltinAESContext *ctx = vctx;
+
+    /* We have already verified that len % AES_BLOCK_SIZE == 0. */
+    while (len) {
+        AES_encrypt(in, out, &ctx->enc);
+        in += AES_BLOCK_SIZE;
+        out += AES_BLOCK_SIZE;
+        len -= AES_BLOCK_SIZE;
+    }
+}
+
+static void do_aes_decrypt_ecb(const void *vctx,
+                               size_t len,
+                               uint8_t *out,
+                               const uint8_t *in)
+{
+    const QCryptoCipherBuiltinAESContext *ctx = vctx;
+
+    /* We have already verified that len % AES_BLOCK_SIZE == 0. */
+    while (len) {
+        AES_decrypt(in, out, &ctx->dec);
+        in += AES_BLOCK_SIZE;
+        out += AES_BLOCK_SIZE;
+        len -= AES_BLOCK_SIZE;
+    }
+}
+
+static void do_aes_encrypt_cbc(const AES_KEY *key,
+                               size_t len,
+                               uint8_t *out,
+                               const uint8_t *in,
+                               uint8_t *ivec)
+{
+    uint8_t tmp[AES_BLOCK_SIZE];
+    size_t n;
+
+    /* We have already verified that len % AES_BLOCK_SIZE == 0. */
+    while (len) {
+        for (n = 0; n < AES_BLOCK_SIZE; ++n) {
+            tmp[n] = in[n] ^ ivec[n];
+        }
+        AES_encrypt(tmp, out, key);
+        memcpy(ivec, out, AES_BLOCK_SIZE);
+        len -= AES_BLOCK_SIZE;
+        in += AES_BLOCK_SIZE;
+        out += AES_BLOCK_SIZE;
+    }
+}
+
+static void do_aes_decrypt_cbc(const AES_KEY *key,
+                               size_t len,
+                               uint8_t *out,
+                               const uint8_t *in,
+                               uint8_t *ivec)
+{
+    uint8_t tmp[AES_BLOCK_SIZE];
+    size_t n;
+
+    /* We have already verified that len % AES_BLOCK_SIZE == 0. */
+    while (len) {
+        memcpy(tmp, in, AES_BLOCK_SIZE);
+        AES_decrypt(in, out, key);
+        for (n = 0; n < AES_BLOCK_SIZE; ++n) {
+            out[n] ^= ivec[n];
+        }
+        memcpy(ivec, tmp, AES_BLOCK_SIZE);
+        len -= AES_BLOCK_SIZE;
+        in += AES_BLOCK_SIZE;
+        out += AES_BLOCK_SIZE;
+    }
+}
+
+static int qcrypto_cipher_aes_encrypt_ecb(QCryptoCipher *cipher,
+                                          const void *in, void *out,
+                                          size_t len, Error **errp)
+{
+    QCryptoCipherBuiltinAES *ctx
+        = container_of(cipher, QCryptoCipherBuiltinAES, base);
+
+    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
+        return -1;
+    }
+    do_aes_encrypt_ecb(&ctx->key, len, out, in);
+    return 0;
+}
+
+static int qcrypto_cipher_aes_decrypt_ecb(QCryptoCipher *cipher,
+                                          const void *in, void *out,
+                                          size_t len, Error **errp)
+{
+    QCryptoCipherBuiltinAES *ctx
+        = container_of(cipher, QCryptoCipherBuiltinAES, base);
+
+    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
+        return -1;
+    }
+    do_aes_decrypt_ecb(&ctx->key, len, out, in);
+    return 0;
+}
+
+static int qcrypto_cipher_aes_encrypt_cbc(QCryptoCipher *cipher,
+                                          const void *in, void *out,
+                                          size_t len, Error **errp)
+{
+    QCryptoCipherBuiltinAES *ctx
+        = container_of(cipher, QCryptoCipherBuiltinAES, base);
+
+    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
+        return -1;
+    }
+    do_aes_encrypt_cbc(&ctx->key.enc, len, out, in, ctx->iv);
+    return 0;
+}
+
+static int qcrypto_cipher_aes_decrypt_cbc(QCryptoCipher *cipher,
+                                          const void *in, void *out,
+                                          size_t len, Error **errp)
+{
+    QCryptoCipherBuiltinAES *ctx
+        = container_of(cipher, QCryptoCipherBuiltinAES, base);
+
+    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
+        return -1;
+    }
+    do_aes_decrypt_cbc(&ctx->key.dec, len, out, in, ctx->iv);
+    return 0;
+}
+
+static int qcrypto_cipher_aes_encrypt_xts(QCryptoCipher *cipher,
+                                          const void *in, void *out,
+                                          size_t len, Error **errp)
+{
+    QCryptoCipherBuiltinAES *ctx
+        = container_of(cipher, QCryptoCipherBuiltinAES, base);
+
+    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
+        return -1;
+    }
+    xts_encrypt(&ctx->key, &ctx->key_tweak,
+                do_aes_encrypt_ecb, do_aes_decrypt_ecb,
+                ctx->iv, len, out, in);
+    return 0;
+}
+
+static int qcrypto_cipher_aes_decrypt_xts(QCryptoCipher *cipher,
+                                          const void *in, void *out,
+                                          size_t len, Error **errp)
+{
+    QCryptoCipherBuiltinAES *ctx
+        = container_of(cipher, QCryptoCipherBuiltinAES, base);
+
+    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
+        return -1;
+    }
+    xts_decrypt(&ctx->key, &ctx->key_tweak,
+                do_aes_encrypt_ecb, do_aes_decrypt_ecb,
+                ctx->iv, len, out, in);
+    return 0;
+}
+
+
+static int qcrypto_cipher_aes_setiv(QCryptoCipher *cipher, const uint8_t *iv,
+                             size_t niv, Error **errp)
+{
+    QCryptoCipherBuiltinAES *ctx
+        = container_of(cipher, QCryptoCipherBuiltinAES, base);
+
+    if (niv != AES_BLOCK_SIZE) {
+        error_setg(errp, "IV must be %d bytes not %zu",
+                   AES_BLOCK_SIZE, niv);
+        return -1;
+    }
+
+    memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
+    return 0;
+}
+
+static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_ecb = {
+    .cipher_encrypt = qcrypto_cipher_aes_encrypt_ecb,
+    .cipher_decrypt = qcrypto_cipher_aes_decrypt_ecb,
+    .cipher_setiv = qcrypto_cipher_no_setiv,
+    .cipher_free = qcrypto_cipher_ctx_free,
+};
+
+static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_cbc = {
+    .cipher_encrypt = qcrypto_cipher_aes_encrypt_cbc,
+    .cipher_decrypt = qcrypto_cipher_aes_decrypt_cbc,
+    .cipher_setiv = qcrypto_cipher_aes_setiv,
+    .cipher_free = qcrypto_cipher_ctx_free,
+};
+
+static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_xts = {
+    .cipher_encrypt = qcrypto_cipher_aes_encrypt_xts,
+    .cipher_decrypt = qcrypto_cipher_aes_decrypt_xts,
+    .cipher_setiv = qcrypto_cipher_aes_setiv,
+    .cipher_free = qcrypto_cipher_ctx_free,
+};
+
+
+typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB;
+struct QCryptoCipherBuiltinDESRFB {
+    QCryptoCipher base;
+
+    /* C.f. alg_key_len[QCRYPTO_CIPHER_ALG_DES_RFB] */
+    uint8_t key[8];
+};
+
+static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher,
+                                          const void *in, void *out,
+                                          size_t len, Error **errp)
+{
+    QCryptoCipherBuiltinDESRFB *ctx
+        = container_of(cipher, QCryptoCipherBuiltinDESRFB, base);
+    size_t i;
+
+    if (!qcrypto_length_check(len, 8, errp)) {
+        return -1;
+    }
+
+    deskey(ctx->key, EN0);
+
+    for (i = 0; i < len; i += 8) {
+        des((void *)in + i, out + i);
+    }
+
+    return 0;
+}
+
+static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher,
+                                          const void *in, void *out,
+                                          size_t len, Error **errp)
+{
+    QCryptoCipherBuiltinDESRFB *ctx
+        = container_of(cipher, QCryptoCipherBuiltinDESRFB, base);
+    size_t i;
+
+    if (!qcrypto_length_check(len, 8, errp)) {
+        return -1;
+    }
+
+    deskey(ctx->key, DE1);
+
+    for (i = 0; i < len; i += 8) {
+        des((void *)in + i, out + i);
+    }
+
+    return 0;
+}
+
+static const struct QCryptoCipherDriver qcrypto_cipher_des_rfb_driver = {
+    .cipher_encrypt = qcrypto_cipher_encrypt_des_rfb,
+    .cipher_decrypt = qcrypto_cipher_decrypt_des_rfb,
+    .cipher_setiv = qcrypto_cipher_no_setiv,
+    .cipher_free = qcrypto_cipher_ctx_free,
+};
+
+bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
+                             QCryptoCipherMode mode)
+{
+    switch (alg) {
+    case QCRYPTO_CIPHER_ALG_DES_RFB:
+        return mode == QCRYPTO_CIPHER_MODE_ECB;
+    case QCRYPTO_CIPHER_ALG_AES_128:
+    case QCRYPTO_CIPHER_ALG_AES_192:
+    case QCRYPTO_CIPHER_ALG_AES_256:
+        switch (mode) {
+        case QCRYPTO_CIPHER_MODE_ECB:
+        case QCRYPTO_CIPHER_MODE_CBC:
+        case QCRYPTO_CIPHER_MODE_XTS:
+            return true;
+        default:
+            return false;
+        }
+        break;
+    default:
+        return false;
+    }
+}
+
+static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
+                                             QCryptoCipherMode mode,
+                                             const uint8_t *key,
+                                             size_t nkey,
+                                             Error **errp)
+{
+    if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
+        return NULL;
+    }
+
+    switch (alg) {
+    case QCRYPTO_CIPHER_ALG_DES_RFB:
+        if (mode == QCRYPTO_CIPHER_MODE_ECB) {
+            QCryptoCipherBuiltinDESRFB *ctx;
+
+            ctx = g_new0(QCryptoCipherBuiltinDESRFB, 1);
+            ctx->base.driver = &qcrypto_cipher_des_rfb_driver;
+            memcpy(ctx->key, key, sizeof(ctx->key));
+
+            return &ctx->base;
+        }
+        goto bad_mode;
+
+    case QCRYPTO_CIPHER_ALG_AES_128:
+    case QCRYPTO_CIPHER_ALG_AES_192:
+    case QCRYPTO_CIPHER_ALG_AES_256:
+        {
+            QCryptoCipherBuiltinAES *ctx;
+            const QCryptoCipherDriver *drv;
+
+            switch (mode) {
+            case QCRYPTO_CIPHER_MODE_ECB:
+                drv = &qcrypto_cipher_aes_driver_ecb;
+                break;
+            case QCRYPTO_CIPHER_MODE_CBC:
+                drv = &qcrypto_cipher_aes_driver_cbc;
+                break;
+            case QCRYPTO_CIPHER_MODE_XTS:
+                drv = &qcrypto_cipher_aes_driver_xts;
+                break;
+            default:
+                goto bad_mode;
+            }
+
+            ctx = g_new0(QCryptoCipherBuiltinAES, 1);
+            ctx->base.driver = drv;
+
+            if (mode == QCRYPTO_CIPHER_MODE_XTS) {
+                nkey /= 2;
+                if (AES_set_encrypt_key(key + nkey, nkey * 8,
+                                        &ctx->key_tweak.enc)) {
+                    error_setg(errp, "Failed to set encryption key");
+                    goto error;
+                }
+                if (AES_set_decrypt_key(key + nkey, nkey * 8,
+                                        &ctx->key_tweak.dec)) {
+                    error_setg(errp, "Failed to set decryption key");
+                    goto error;
+                }
+            }
+            if (AES_set_encrypt_key(key, nkey * 8, &ctx->key.enc)) {
+                error_setg(errp, "Failed to set encryption key");
+                goto error;
+            }
+            if (AES_set_decrypt_key(key, nkey * 8, &ctx->key.dec)) {
+                error_setg(errp, "Failed to set decryption key");
+                goto error;
+            }
+
+            return &ctx->base;
+
+        error:
+            g_free(ctx);
+            return NULL;
+        }
+
+    default:
+        error_setg(errp,
+                   "Unsupported cipher algorithm %s",
+                   QCryptoCipherAlgorithm_str(alg));
+        return NULL;
+    }
+
+ bad_mode:
+    error_setg(errp, "Unsupported cipher mode %s",
+               QCryptoCipherMode_str(mode));
+    return NULL;
+}
diff --git a/crypto/cipher-gcrypt.c b/crypto/cipher-gcrypt.c.inc
index 2864099527..42d4137534 100644
--- a/crypto/cipher-gcrypt.c
+++ b/crypto/cipher-gcrypt.c.inc
@@ -18,15 +18,12 @@
  *
  */
 
-#include "qemu/osdep.h"
 #ifdef CONFIG_QEMU_PRIVATE_XTS
 #include "crypto/xts.h"
 #endif
-#include "cipherpriv.h"
 
 #include <gcrypt.h>
 
-
 bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
                              QCryptoCipherMode mode)
 {
@@ -58,69 +55,224 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
     }
 }
 
-typedef struct QCryptoCipherGcrypt QCryptoCipherGcrypt;
-struct QCryptoCipherGcrypt {
+typedef struct QCryptoCipherGcrypt {
+    QCryptoCipher base;
     gcry_cipher_hd_t handle;
     size_t blocksize;
 #ifdef CONFIG_QEMU_PRIVATE_XTS
     gcry_cipher_hd_t tweakhandle;
-    /* Initialization vector or Counter */
-    uint8_t *iv;
+    uint8_t iv[XTS_BLOCK_SIZE];
 #endif
-};
+} QCryptoCipherGcrypt;
+
 
-static void
-qcrypto_gcrypt_cipher_free_ctx(QCryptoCipherGcrypt *ctx,
-                               QCryptoCipherMode mode)
+static void qcrypto_gcrypt_ctx_free(QCryptoCipher *cipher)
 {
-    if (!ctx) {
-        return;
-    }
+    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
 
     gcry_cipher_close(ctx->handle);
-#ifdef CONFIG_QEMU_PRIVATE_XTS
-    if (mode == QCRYPTO_CIPHER_MODE_XTS) {
-        gcry_cipher_close(ctx->tweakhandle);
-    }
-    g_free(ctx->iv);
-#endif
     g_free(ctx);
 }
 
+static int qcrypto_gcrypt_encrypt(QCryptoCipher *cipher, const void *in,
+                                  void *out, size_t len, Error **errp)
+{
+    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
+    gcry_error_t err;
+
+    if (len & (ctx->blocksize - 1)) {
+        error_setg(errp, "Length %zu must be a multiple of block size %zu",
+                   len, ctx->blocksize);
+        return -1;
+    }
+
+    err = gcry_cipher_encrypt(ctx->handle, out, len, in, len);
+    if (err != 0) {
+        error_setg(errp, "Cannot encrypt data: %s", gcry_strerror(err));
+        return -1;
+    }
+
+    return 0;
+}
+
 
-static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
-                                                   QCryptoCipherMode mode,
-                                                   const uint8_t *key,
-                                                   size_t nkey,
-                                                   Error **errp)
+static int qcrypto_gcrypt_decrypt(QCryptoCipher *cipher, const void *in,
+                                  void *out, size_t len, Error **errp)
 {
-    QCryptoCipherGcrypt *ctx;
+    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
     gcry_error_t err;
-    int gcryalg, gcrymode;
 
-    switch (mode) {
-    case QCRYPTO_CIPHER_MODE_ECB:
-        gcrymode = GCRY_CIPHER_MODE_ECB;
-        break;
-    case QCRYPTO_CIPHER_MODE_XTS:
+    if (len & (ctx->blocksize - 1)) {
+        error_setg(errp, "Length %zu must be a multiple of block size %zu",
+                   len, ctx->blocksize);
+        return -1;
+    }
+
+    err = gcry_cipher_decrypt(ctx->handle, out, len, in, len);
+    if (err != 0) {
+        error_setg(errp, "Cannot decrypt data: %s",
+                   gcry_strerror(err));
+        return -1;
+    }
+
+    return 0;
+}
+
+static int qcrypto_gcrypt_setiv(QCryptoCipher *cipher,
+                                const uint8_t *iv, size_t niv,
+                                Error **errp)
+{
+    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
+    gcry_error_t err;
+
+    if (niv != ctx->blocksize) {
+        error_setg(errp, "Expected IV size %zu not %zu",
+                   ctx->blocksize, niv);
+        return -1;
+    }
+
+    gcry_cipher_reset(ctx->handle);
+    err = gcry_cipher_setiv(ctx->handle, iv, niv);
+    if (err != 0) {
+        error_setg(errp, "Cannot set IV: %s", gcry_strerror(err));
+        return -1;
+    }
+
+    return 0;
+}
+
+static int qcrypto_gcrypt_ctr_setiv(QCryptoCipher *cipher,
+                                    const uint8_t *iv, size_t niv,
+                                    Error **errp)
+{
+    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
+    gcry_error_t err;
+
+    if (niv != ctx->blocksize) {
+        error_setg(errp, "Expected IV size %zu not %zu",
+                   ctx->blocksize, niv);
+        return -1;
+    }
+
+    err = gcry_cipher_setctr(ctx->handle, iv, niv);
+    if (err != 0) {
+        error_setg(errp, "Cannot set Counter: %s", gcry_strerror(err));
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static const struct QCryptoCipherDriver qcrypto_gcrypt_driver = {
+    .cipher_encrypt = qcrypto_gcrypt_encrypt,
+    .cipher_decrypt = qcrypto_gcrypt_decrypt,
+    .cipher_setiv = qcrypto_gcrypt_setiv,
+    .cipher_free = qcrypto_gcrypt_ctx_free,
+};
+
+static const struct QCryptoCipherDriver qcrypto_gcrypt_ctr_driver = {
+    .cipher_encrypt = qcrypto_gcrypt_encrypt,
+    .cipher_decrypt = qcrypto_gcrypt_decrypt,
+    .cipher_setiv = qcrypto_gcrypt_ctr_setiv,
+    .cipher_free = qcrypto_gcrypt_ctx_free,
+};
+
 #ifdef CONFIG_QEMU_PRIVATE_XTS
-        gcrymode = GCRY_CIPHER_MODE_ECB;
-#else
-        gcrymode = GCRY_CIPHER_MODE_XTS;
-#endif
-        break;
-    case QCRYPTO_CIPHER_MODE_CBC:
-        gcrymode = GCRY_CIPHER_MODE_CBC;
-        break;
-    case QCRYPTO_CIPHER_MODE_CTR:
-        gcrymode = GCRY_CIPHER_MODE_CTR;
-        break;
-    default:
-        error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_str(mode));
-        return NULL;
+static void qcrypto_gcrypt_xts_ctx_free(QCryptoCipher *cipher)
+{
+    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
+
+    gcry_cipher_close(ctx->tweakhandle);
+    qcrypto_gcrypt_ctx_free(cipher);
+}
+
+static void qcrypto_gcrypt_xts_wrape(const void *ctx, size_t length,
+                                     uint8_t *dst, const uint8_t *src)
+{
+    gcry_error_t err;
+    err = gcry_cipher_encrypt((gcry_cipher_hd_t)ctx, dst, length, src, length);
+    g_assert(err == 0);
+}
+
+static void qcrypto_gcrypt_xts_wrapd(const void *ctx, size_t length,
+                                     uint8_t *dst, const uint8_t *src)
+{
+    gcry_error_t err;
+    err = gcry_cipher_decrypt((gcry_cipher_hd_t)ctx, dst, length, src, length);
+    g_assert(err == 0);
+}
+
+static int qcrypto_gcrypt_xts_encrypt(QCryptoCipher *cipher, const void *in,
+                                      void *out, size_t len, Error **errp)
+{
+    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
+
+    if (len & (ctx->blocksize - 1)) {
+        error_setg(errp, "Length %zu must be a multiple of block size %zu",
+                   len, ctx->blocksize);
+        return -1;
     }
 
+    xts_encrypt(ctx->handle, ctx->tweakhandle,
+                qcrypto_gcrypt_xts_wrape, qcrypto_gcrypt_xts_wrapd,
+                ctx->iv, len, out, in);
+    return 0;
+}
+
+static int qcrypto_gcrypt_xts_decrypt(QCryptoCipher *cipher, const void *in,
+                                      void *out, size_t len, Error **errp)
+{
+    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
+
+    if (len & (ctx->blocksize - 1)) {
+        error_setg(errp, "Length %zu must be a multiple of block size %zu",
+                   len, ctx->blocksize);
+        return -1;
+    }
+
+    xts_decrypt(ctx->handle, ctx->tweakhandle,
+                qcrypto_gcrypt_xts_wrape, qcrypto_gcrypt_xts_wrapd,
+                ctx->iv, len, out, in);
+    return 0;
+}
+
+static int qcrypto_gcrypt_xts_setiv(QCryptoCipher *cipher,
+                                    const uint8_t *iv, size_t niv,
+                                    Error **errp)
+{
+    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
+
+    if (niv != ctx->blocksize) {
+        error_setg(errp, "Expected IV size %zu not %zu",
+                   ctx->blocksize, niv);
+        return -1;
+    }
+
+    memcpy(ctx->iv, iv, niv);
+    return 0;
+}
+
+static const struct QCryptoCipherDriver qcrypto_gcrypt_xts_driver = {
+    .cipher_encrypt = qcrypto_gcrypt_xts_encrypt,
+    .cipher_decrypt = qcrypto_gcrypt_xts_decrypt,
+    .cipher_setiv = qcrypto_gcrypt_xts_setiv,
+    .cipher_free = qcrypto_gcrypt_xts_ctx_free,
+};
+#endif /* CONFIG_QEMU_PRIVATE_XTS */
+
+
+static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
+                                             QCryptoCipherMode mode,
+                                             const uint8_t *key,
+                                             size_t nkey,
+                                             Error **errp)
+{
+    QCryptoCipherGcrypt *ctx;
+    const QCryptoCipherDriver *drv;
+    gcry_error_t err;
+    int gcryalg, gcrymode;
+
     if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
         return NULL;
     }
@@ -129,54 +281,70 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
     case QCRYPTO_CIPHER_ALG_DES_RFB:
         gcryalg = GCRY_CIPHER_DES;
         break;
-
     case QCRYPTO_CIPHER_ALG_3DES:
         gcryalg = GCRY_CIPHER_3DES;
         break;
-
     case QCRYPTO_CIPHER_ALG_AES_128:
         gcryalg = GCRY_CIPHER_AES128;
         break;
-
     case QCRYPTO_CIPHER_ALG_AES_192:
         gcryalg = GCRY_CIPHER_AES192;
         break;
-
     case QCRYPTO_CIPHER_ALG_AES_256:
         gcryalg = GCRY_CIPHER_AES256;
         break;
-
     case QCRYPTO_CIPHER_ALG_CAST5_128:
         gcryalg = GCRY_CIPHER_CAST5;
         break;
-
     case QCRYPTO_CIPHER_ALG_SERPENT_128:
         gcryalg = GCRY_CIPHER_SERPENT128;
         break;
-
     case QCRYPTO_CIPHER_ALG_SERPENT_192:
         gcryalg = GCRY_CIPHER_SERPENT192;
         break;
-
     case QCRYPTO_CIPHER_ALG_SERPENT_256:
         gcryalg = GCRY_CIPHER_SERPENT256;
         break;
-
     case QCRYPTO_CIPHER_ALG_TWOFISH_128:
         gcryalg = GCRY_CIPHER_TWOFISH128;
         break;
-
     case QCRYPTO_CIPHER_ALG_TWOFISH_256:
         gcryalg = GCRY_CIPHER_TWOFISH;
         break;
-
     default:
         error_setg(errp, "Unsupported cipher algorithm %s",
                    QCryptoCipherAlgorithm_str(alg));
         return NULL;
     }
 
+    drv = &qcrypto_gcrypt_driver;
+    switch (mode) {
+    case QCRYPTO_CIPHER_MODE_ECB:
+        gcrymode = GCRY_CIPHER_MODE_ECB;
+        break;
+    case QCRYPTO_CIPHER_MODE_XTS:
+#ifdef CONFIG_QEMU_PRIVATE_XTS
+        drv = &qcrypto_gcrypt_xts_driver;
+        gcrymode = GCRY_CIPHER_MODE_ECB;
+#else
+        gcrymode = GCRY_CIPHER_MODE_XTS;
+#endif
+        break;
+    case QCRYPTO_CIPHER_MODE_CBC:
+        gcrymode = GCRY_CIPHER_MODE_CBC;
+        break;
+    case QCRYPTO_CIPHER_MODE_CTR:
+        drv = &qcrypto_gcrypt_ctr_driver;
+        gcrymode = GCRY_CIPHER_MODE_CTR;
+        break;
+    default:
+        error_setg(errp, "Unsupported cipher mode %s",
+                   QCryptoCipherMode_str(mode));
+        return NULL;
+    }
+
     ctx = g_new0(QCryptoCipherGcrypt, 1);
+    ctx->base.driver = drv;
 
     err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
     if (err != 0) {
@@ -184,8 +352,16 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
                    gcry_strerror(err));
         goto error;
     }
+    ctx->blocksize = gcry_cipher_get_algo_blklen(gcryalg);
+
 #ifdef CONFIG_QEMU_PRIVATE_XTS
     if (mode == QCRYPTO_CIPHER_MODE_XTS) {
+        if (ctx->blocksize != XTS_BLOCK_SIZE) {
+            error_setg(errp,
+                       "Cipher block size %zu must equal XTS block size %d",
+		       ctx->blocksize, XTS_BLOCK_SIZE);
+            goto error;
+        }
         err = gcry_cipher_open(&ctx->tweakhandle, gcryalg, gcrymode, 0);
         if (err != 0) {
             error_setg(errp, "Cannot initialize cipher: %s",
@@ -203,220 +379,31 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
         uint8_t *rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
         err = gcry_cipher_setkey(ctx->handle, rfbkey, nkey);
         g_free(rfbkey);
-        ctx->blocksize = 8;
     } else {
 #ifdef CONFIG_QEMU_PRIVATE_XTS
         if (mode == QCRYPTO_CIPHER_MODE_XTS) {
             nkey /= 2;
-            err = gcry_cipher_setkey(ctx->handle, key, nkey);
+            err = gcry_cipher_setkey(ctx->tweakhandle, key + nkey, nkey);
             if (err != 0) {
-                error_setg(errp, "Cannot set key: %s",
-                           gcry_strerror(err));
+                error_setg(errp, "Cannot set key: %s", gcry_strerror(err));
                 goto error;
             }
-            err = gcry_cipher_setkey(ctx->tweakhandle, key + nkey, nkey);
-        } else {
-#endif
-            err = gcry_cipher_setkey(ctx->handle, key, nkey);
-#ifdef CONFIG_QEMU_PRIVATE_XTS
-        }
-#endif
-        if (err != 0) {
-            error_setg(errp, "Cannot set key: %s",
-                       gcry_strerror(err));
-            goto error;
         }
-        switch (alg) {
-        case QCRYPTO_CIPHER_ALG_AES_128:
-        case QCRYPTO_CIPHER_ALG_AES_192:
-        case QCRYPTO_CIPHER_ALG_AES_256:
-        case QCRYPTO_CIPHER_ALG_SERPENT_128:
-        case QCRYPTO_CIPHER_ALG_SERPENT_192:
-        case QCRYPTO_CIPHER_ALG_SERPENT_256:
-        case QCRYPTO_CIPHER_ALG_TWOFISH_128:
-        case QCRYPTO_CIPHER_ALG_TWOFISH_256:
-            ctx->blocksize = 16;
-            break;
-        case QCRYPTO_CIPHER_ALG_3DES:
-        case QCRYPTO_CIPHER_ALG_CAST5_128:
-            ctx->blocksize = 8;
-            break;
-        default:
-            g_assert_not_reached();
-        }
-    }
-
-#ifdef CONFIG_QEMU_PRIVATE_XTS
-    if (mode == QCRYPTO_CIPHER_MODE_XTS) {
-        if (ctx->blocksize != XTS_BLOCK_SIZE) {
-            error_setg(errp,
-                       "Cipher block size %zu must equal XTS block size %d",
-                       ctx->blocksize, XTS_BLOCK_SIZE);
-            goto error;
-        }
-        ctx->iv = g_new0(uint8_t, ctx->blocksize);
-    }
-#endif
-
-    return ctx;
-
- error:
-    qcrypto_gcrypt_cipher_free_ctx(ctx, mode);
-    return NULL;
-}
-
-
-static void
-qcrypto_gcrypt_cipher_ctx_free(QCryptoCipher *cipher)
-{
-    qcrypto_gcrypt_cipher_free_ctx(cipher->opaque, cipher->mode);
-}
-
-
-#ifdef CONFIG_QEMU_PRIVATE_XTS
-static void qcrypto_gcrypt_xts_encrypt(const void *ctx,
-                                       size_t length,
-                                       uint8_t *dst,
-                                       const uint8_t *src)
-{
-    gcry_error_t err;
-    err = gcry_cipher_encrypt((gcry_cipher_hd_t)ctx, dst, length, src, length);
-    g_assert(err == 0);
-}
-
-static void qcrypto_gcrypt_xts_decrypt(const void *ctx,
-                                       size_t length,
-                                       uint8_t *dst,
-                                       const uint8_t *src)
-{
-    gcry_error_t err;
-    err = gcry_cipher_decrypt((gcry_cipher_hd_t)ctx, dst, length, src, length);
-    g_assert(err == 0);
-}
 #endif
-
-static int
-qcrypto_gcrypt_cipher_encrypt(QCryptoCipher *cipher,
-                              const void *in,
-                              void *out,
-                              size_t len,
-                              Error **errp)
-{
-    QCryptoCipherGcrypt *ctx = cipher->opaque;
-    gcry_error_t err;
-
-    if (len % ctx->blocksize) {
-        error_setg(errp, "Length %zu must be a multiple of block size %zu",
-                   len, ctx->blocksize);
-        return -1;
+        err = gcry_cipher_setkey(ctx->handle, key, nkey);
     }
-
-#ifdef CONFIG_QEMU_PRIVATE_XTS
-    if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
-        xts_encrypt(ctx->handle, ctx->tweakhandle,
-                    qcrypto_gcrypt_xts_encrypt,
-                    qcrypto_gcrypt_xts_decrypt,
-                    ctx->iv, len, out, in);
-        return 0;
-    }
-#endif
-
-    err = gcry_cipher_encrypt(ctx->handle,
-                              out, len,
-                              in, len);
     if (err != 0) {
-        error_setg(errp, "Cannot encrypt data: %s",
-                   gcry_strerror(err));
-        return -1;
-    }
-
-    return 0;
-}
-
-
-static int
-qcrypto_gcrypt_cipher_decrypt(QCryptoCipher *cipher,
-                              const void *in,
-                              void *out,
-                              size_t len,
-                              Error **errp)
-{
-    QCryptoCipherGcrypt *ctx = cipher->opaque;
-    gcry_error_t err;
-
-    if (len % ctx->blocksize) {
-        error_setg(errp, "Length %zu must be a multiple of block size %zu",
-                   len, ctx->blocksize);
-        return -1;
-    }
-
-#ifdef CONFIG_QEMU_PRIVATE_XTS
-    if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
-        xts_decrypt(ctx->handle, ctx->tweakhandle,
-                    qcrypto_gcrypt_xts_encrypt,
-                    qcrypto_gcrypt_xts_decrypt,
-                    ctx->iv, len, out, in);
-        return 0;
-    }
-#endif
-
-    err = gcry_cipher_decrypt(ctx->handle,
-                              out, len,
-                              in, len);
-    if (err != 0) {
-        error_setg(errp, "Cannot decrypt data: %s",
-                   gcry_strerror(err));
-        return -1;
+        error_setg(errp, "Cannot set key: %s", gcry_strerror(err));
+        goto error;
     }
 
-    return 0;
-}
-
-static int
-qcrypto_gcrypt_cipher_setiv(QCryptoCipher *cipher,
-                            const uint8_t *iv, size_t niv,
-                            Error **errp)
-{
-    QCryptoCipherGcrypt *ctx = cipher->opaque;
-    gcry_error_t err;
-
-    if (niv != ctx->blocksize) {
-        error_setg(errp, "Expected IV size %zu not %zu",
-                   ctx->blocksize, niv);
-        return -1;
-    }
+    return &ctx->base;
 
+ error:
 #ifdef CONFIG_QEMU_PRIVATE_XTS
-    if (ctx->iv) {
-        memcpy(ctx->iv, iv, niv);
-        return 0;
-    }
+    gcry_cipher_close(ctx->tweakhandle);
 #endif
-
-    if (cipher->mode == QCRYPTO_CIPHER_MODE_CTR) {
-        err = gcry_cipher_setctr(ctx->handle, iv, niv);
-        if (err != 0) {
-            error_setg(errp, "Cannot set Counter: %s",
-                       gcry_strerror(err));
-            return -1;
-        }
-    } else {
-        gcry_cipher_reset(ctx->handle);
-        err = gcry_cipher_setiv(ctx->handle, iv, niv);
-        if (err != 0) {
-            error_setg(errp, "Cannot set IV: %s",
-                       gcry_strerror(err));
-            return -1;
-        }
-    }
-
-    return 0;
+    gcry_cipher_close(ctx->handle);
+    g_free(ctx);
+    return NULL;
 }
-
-
-static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = {
-    .cipher_encrypt = qcrypto_gcrypt_cipher_encrypt,
-    .cipher_decrypt = qcrypto_gcrypt_cipher_decrypt,
-    .cipher_setiv = qcrypto_gcrypt_cipher_setiv,
-    .cipher_free = qcrypto_gcrypt_cipher_ctx_free,
-};
diff --git a/crypto/cipher-nettle.c b/crypto/cipher-nettle.c
deleted file mode 100644
index 7e9a4cc199..0000000000
--- a/crypto/cipher-nettle.c
+++ /dev/null
@@ -1,733 +0,0 @@
-/*
- * QEMU Crypto cipher nettle algorithms
- *
- * Copyright (c) 2015 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "qemu/osdep.h"
-#ifdef CONFIG_QEMU_PRIVATE_XTS
-#include "crypto/xts.h"
-#endif
-#include "cipherpriv.h"
-
-#include <nettle/nettle-types.h>
-#include <nettle/aes.h>
-#include <nettle/des.h>
-#include <nettle/cbc.h>
-#include <nettle/cast128.h>
-#include <nettle/serpent.h>
-#include <nettle/twofish.h>
-#include <nettle/ctr.h>
-#ifndef CONFIG_QEMU_PRIVATE_XTS
-#include <nettle/xts.h>
-#endif
-
-typedef void (*QCryptoCipherNettleFuncWrapper)(const void *ctx,
-                                               size_t length,
-                                               uint8_t *dst,
-                                               const uint8_t *src);
-
-#if CONFIG_NETTLE_VERSION_MAJOR < 3
-typedef nettle_crypt_func * QCryptoCipherNettleFuncNative;
-typedef void *       cipher_ctx_t;
-typedef unsigned     cipher_length_t;
-
-#define cast5_set_key cast128_set_key
-
-#define aes128_ctx aes_ctx
-#define aes192_ctx aes_ctx
-#define aes256_ctx aes_ctx
-#define aes128_set_encrypt_key(c, k) \
-    aes_set_encrypt_key(c, 16, k)
-#define aes192_set_encrypt_key(c, k) \
-    aes_set_encrypt_key(c, 24, k)
-#define aes256_set_encrypt_key(c, k) \
-    aes_set_encrypt_key(c, 32, k)
-#define aes128_set_decrypt_key(c, k) \
-    aes_set_decrypt_key(c, 16, k)
-#define aes192_set_decrypt_key(c, k) \
-    aes_set_decrypt_key(c, 24, k)
-#define aes256_set_decrypt_key(c, k) \
-    aes_set_decrypt_key(c, 32, k)
-#define aes128_encrypt aes_encrypt
-#define aes192_encrypt aes_encrypt
-#define aes256_encrypt aes_encrypt
-#define aes128_decrypt aes_decrypt
-#define aes192_decrypt aes_decrypt
-#define aes256_decrypt aes_decrypt
-#else
-typedef nettle_cipher_func * QCryptoCipherNettleFuncNative;
-typedef const void * cipher_ctx_t;
-typedef size_t       cipher_length_t;
-#endif
-
-typedef struct QCryptoNettleAES128 {
-    struct aes128_ctx enc;
-    struct aes128_ctx dec;
-} QCryptoNettleAES128;
-
-typedef struct QCryptoNettleAES192 {
-    struct aes192_ctx enc;
-    struct aes192_ctx dec;
-} QCryptoNettleAES192;
-
-typedef struct QCryptoNettleAES256 {
-    struct aes256_ctx enc;
-    struct aes256_ctx dec;
-} QCryptoNettleAES256;
-
-static void aes128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                                  uint8_t *dst, const uint8_t *src)
-{
-    const QCryptoNettleAES128 *aesctx = ctx;
-    aes128_encrypt(&aesctx->enc, length, dst, src);
-}
-
-static void aes128_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                                  uint8_t *dst, const uint8_t *src)
-{
-    const QCryptoNettleAES128 *aesctx = ctx;
-    aes128_decrypt(&aesctx->dec, length, dst, src);
-}
-
-static void aes192_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                               uint8_t *dst, const uint8_t *src)
-{
-    const QCryptoNettleAES192 *aesctx = ctx;
-    aes192_encrypt(&aesctx->enc, length, dst, src);
-}
-
-static void aes192_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                               uint8_t *dst, const uint8_t *src)
-{
-    const QCryptoNettleAES192 *aesctx = ctx;
-    aes192_decrypt(&aesctx->dec, length, dst, src);
-}
-
-static void aes256_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                               uint8_t *dst, const uint8_t *src)
-{
-    const QCryptoNettleAES256 *aesctx = ctx;
-    aes256_encrypt(&aesctx->enc, length, dst, src);
-}
-
-static void aes256_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                               uint8_t *dst, const uint8_t *src)
-{
-    const QCryptoNettleAES256 *aesctx = ctx;
-    aes256_decrypt(&aesctx->dec, length, dst, src);
-}
-
-static void des_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                               uint8_t *dst, const uint8_t *src)
-{
-    des_encrypt(ctx, length, dst, src);
-}
-
-static void des_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                               uint8_t *dst, const uint8_t *src)
-{
-    des_decrypt(ctx, length, dst, src);
-}
-
-static void des3_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                                uint8_t *dst, const uint8_t *src)
-{
-    des3_encrypt(ctx, length, dst, src);
-}
-
-static void des3_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                                uint8_t *dst, const uint8_t *src)
-{
-    des3_decrypt(ctx, length, dst, src);
-}
-
-static void cast128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                                   uint8_t *dst, const uint8_t *src)
-{
-    cast128_encrypt(ctx, length, dst, src);
-}
-
-static void cast128_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                                   uint8_t *dst, const uint8_t *src)
-{
-    cast128_decrypt(ctx, length, dst, src);
-}
-
-static void serpent_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                                   uint8_t *dst, const uint8_t *src)
-{
-    serpent_encrypt(ctx, length, dst, src);
-}
-
-static void serpent_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                                   uint8_t *dst, const uint8_t *src)
-{
-    serpent_decrypt(ctx, length, dst, src);
-}
-
-static void twofish_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                                   uint8_t *dst, const uint8_t *src)
-{
-    twofish_encrypt(ctx, length, dst, src);
-}
-
-static void twofish_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
-                                   uint8_t *dst, const uint8_t *src)
-{
-    twofish_decrypt(ctx, length, dst, src);
-}
-
-static void aes128_encrypt_wrapper(const void *ctx, size_t length,
-                                uint8_t *dst, const uint8_t *src)
-{
-    const QCryptoNettleAES128 *aesctx = ctx;
-    aes128_encrypt(&aesctx->enc, length, dst, src);
-}
-
-static void aes128_decrypt_wrapper(const void *ctx, size_t length,
-                                uint8_t *dst, const uint8_t *src)
-{
-    const QCryptoNettleAES128 *aesctx = ctx;
-    aes128_decrypt(&aesctx->dec, length, dst, src);
-}
-
-static void aes192_encrypt_wrapper(const void *ctx, size_t length,
-                                uint8_t *dst, const uint8_t *src)
-{
-    const QCryptoNettleAES192 *aesctx = ctx;
-    aes192_encrypt(&aesctx->enc, length, dst, src);
-}
-
-static void aes192_decrypt_wrapper(const void *ctx, size_t length,
-                                uint8_t *dst, const uint8_t *src)
-{
-    const QCryptoNettleAES192 *aesctx = ctx;
-    aes192_decrypt(&aesctx->dec, length, dst, src);
-}
-
-static void aes256_encrypt_wrapper(const void *ctx, size_t length,
-                                uint8_t *dst, const uint8_t *src)
-{
-    const QCryptoNettleAES256 *aesctx = ctx;
-    aes256_encrypt(&aesctx->enc, length, dst, src);
-}
-
-static void aes256_decrypt_wrapper(const void *ctx, size_t length,
-                                uint8_t *dst, const uint8_t *src)
-{
-    const QCryptoNettleAES256 *aesctx = ctx;
-    aes256_decrypt(&aesctx->dec, length, dst, src);
-}
-
-static void des_encrypt_wrapper(const void *ctx, size_t length,
-                                uint8_t *dst, const uint8_t *src)
-{
-    des_encrypt(ctx, length, dst, src);
-}
-
-static void des_decrypt_wrapper(const void *ctx, size_t length,
-                                uint8_t *dst, const uint8_t *src)
-{
-    des_decrypt(ctx, length, dst, src);
-}
-
-static void des3_encrypt_wrapper(const void *ctx, size_t length,
-                                uint8_t *dst, const uint8_t *src)
-{
-    des3_encrypt(ctx, length, dst, src);
-}
-
-static void des3_decrypt_wrapper(const void *ctx, size_t length,
-                                uint8_t *dst, const uint8_t *src)
-{
-    des3_decrypt(ctx, length, dst, src);
-}
-
-static void cast128_encrypt_wrapper(const void *ctx, size_t length,
-                                    uint8_t *dst, const uint8_t *src)
-{
-    cast128_encrypt(ctx, length, dst, src);
-}
-
-static void cast128_decrypt_wrapper(const void *ctx, size_t length,
-                                    uint8_t *dst, const uint8_t *src)
-{
-    cast128_decrypt(ctx, length, dst, src);
-}
-
-static void serpent_encrypt_wrapper(const void *ctx, size_t length,
-                                    uint8_t *dst, const uint8_t *src)
-{
-    serpent_encrypt(ctx, length, dst, src);
-}
-
-static void serpent_decrypt_wrapper(const void *ctx, size_t length,
-                                    uint8_t *dst, const uint8_t *src)
-{
-    serpent_decrypt(ctx, length, dst, src);
-}
-
-static void twofish_encrypt_wrapper(const void *ctx, size_t length,
-                                    uint8_t *dst, const uint8_t *src)
-{
-    twofish_encrypt(ctx, length, dst, src);
-}
-
-static void twofish_decrypt_wrapper(const void *ctx, size_t length,
-                                    uint8_t *dst, const uint8_t *src)
-{
-    twofish_decrypt(ctx, length, dst, src);
-}
-
-typedef struct QCryptoCipherNettle QCryptoCipherNettle;
-struct QCryptoCipherNettle {
-    /* Primary cipher context for all modes */
-    void *ctx;
-    /* Second cipher context for XTS mode only */
-    void *ctx_tweak;
-    /* Cipher callbacks for both contexts */
-    QCryptoCipherNettleFuncNative alg_encrypt_native;
-    QCryptoCipherNettleFuncNative alg_decrypt_native;
-    QCryptoCipherNettleFuncWrapper alg_encrypt_wrapper;
-    QCryptoCipherNettleFuncWrapper alg_decrypt_wrapper;
-    /* Initialization vector or Counter */
-    uint8_t *iv;
-    size_t blocksize;
-};
-
-bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
-                             QCryptoCipherMode mode)
-{
-    switch (alg) {
-    case QCRYPTO_CIPHER_ALG_DES_RFB:
-    case QCRYPTO_CIPHER_ALG_3DES:
-    case QCRYPTO_CIPHER_ALG_AES_128:
-    case QCRYPTO_CIPHER_ALG_AES_192:
-    case QCRYPTO_CIPHER_ALG_AES_256:
-    case QCRYPTO_CIPHER_ALG_CAST5_128:
-    case QCRYPTO_CIPHER_ALG_SERPENT_128:
-    case QCRYPTO_CIPHER_ALG_SERPENT_192:
-    case QCRYPTO_CIPHER_ALG_SERPENT_256:
-    case QCRYPTO_CIPHER_ALG_TWOFISH_128:
-    case QCRYPTO_CIPHER_ALG_TWOFISH_192:
-    case QCRYPTO_CIPHER_ALG_TWOFISH_256:
-        break;
-    default:
-        return false;
-    }
-
-    switch (mode) {
-    case QCRYPTO_CIPHER_MODE_ECB:
-    case QCRYPTO_CIPHER_MODE_CBC:
-    case QCRYPTO_CIPHER_MODE_XTS:
-    case QCRYPTO_CIPHER_MODE_CTR:
-        return true;
-    default:
-        return false;
-    }
-}
-
-
-static void
-qcrypto_nettle_cipher_free_ctx(QCryptoCipherNettle *ctx)
-{
-    if (!ctx) {
-        return;
-    }
-
-    g_free(ctx->iv);
-    g_free(ctx->ctx);
-    g_free(ctx->ctx_tweak);
-    g_free(ctx);
-}
-
-
-static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
-                                                   QCryptoCipherMode mode,
-                                                   const uint8_t *key,
-                                                   size_t nkey,
-                                                   Error **errp)
-{
-    QCryptoCipherNettle *ctx;
-    uint8_t *rfbkey;
-
-    switch (mode) {
-    case QCRYPTO_CIPHER_MODE_ECB:
-    case QCRYPTO_CIPHER_MODE_CBC:
-    case QCRYPTO_CIPHER_MODE_XTS:
-    case QCRYPTO_CIPHER_MODE_CTR:
-        break;
-    default:
-        error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_str(mode));
-        return NULL;
-    }
-
-    if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
-        return NULL;
-    }
-
-    ctx = g_new0(QCryptoCipherNettle, 1);
-
-    switch (alg) {
-    case QCRYPTO_CIPHER_ALG_DES_RFB:
-        ctx->ctx = g_new0(struct des_ctx, 1);
-        rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
-        des_set_key(ctx->ctx, rfbkey);
-        g_free(rfbkey);
-
-        ctx->alg_encrypt_native = des_encrypt_native;
-        ctx->alg_decrypt_native = des_decrypt_native;
-        ctx->alg_encrypt_wrapper = des_encrypt_wrapper;
-        ctx->alg_decrypt_wrapper = des_decrypt_wrapper;
-
-        ctx->blocksize = DES_BLOCK_SIZE;
-        break;
-
-    case QCRYPTO_CIPHER_ALG_3DES:
-        ctx->ctx = g_new0(struct des3_ctx, 1);
-        des3_set_key(ctx->ctx, key);
-
-        ctx->alg_encrypt_native = des3_encrypt_native;
-        ctx->alg_decrypt_native = des3_decrypt_native;
-        ctx->alg_encrypt_wrapper = des3_encrypt_wrapper;
-        ctx->alg_decrypt_wrapper = des3_decrypt_wrapper;
-
-        ctx->blocksize = DES3_BLOCK_SIZE;
-        break;
-
-    case QCRYPTO_CIPHER_ALG_AES_128:
-        ctx->ctx = g_new0(QCryptoNettleAES128, 1);
-
-        if (mode == QCRYPTO_CIPHER_MODE_XTS) {
-            ctx->ctx_tweak = g_new0(QCryptoNettleAES128, 1);
-
-            nkey /= 2;
-            aes128_set_encrypt_key(&((QCryptoNettleAES128 *)ctx->ctx)->enc,
-                                   key);
-            aes128_set_decrypt_key(&((QCryptoNettleAES128 *)ctx->ctx)->dec,
-                                   key);
-
-            aes128_set_encrypt_key(&((QCryptoNettleAES128 *)ctx->ctx_tweak)->
-                                   enc, key + nkey);
-            aes128_set_decrypt_key(&((QCryptoNettleAES128 *)ctx->ctx_tweak)->
-                                   dec, key + nkey);
-        } else {
-            aes128_set_encrypt_key(&((QCryptoNettleAES128 *)ctx->ctx)->enc,
-                                   key);
-            aes128_set_decrypt_key(&((QCryptoNettleAES128 *)ctx->ctx)->dec,
-                                   key);
-        }
-
-        ctx->alg_encrypt_native = aes128_encrypt_native;
-        ctx->alg_decrypt_native = aes128_decrypt_native;
-        ctx->alg_encrypt_wrapper = aes128_encrypt_wrapper;
-        ctx->alg_decrypt_wrapper = aes128_decrypt_wrapper;
-
-        ctx->blocksize = AES_BLOCK_SIZE;
-        break;
-
-    case QCRYPTO_CIPHER_ALG_AES_192:
-        ctx->ctx = g_new0(QCryptoNettleAES192, 1);
-
-        if (mode == QCRYPTO_CIPHER_MODE_XTS) {
-            ctx->ctx_tweak = g_new0(QCryptoNettleAES192, 1);
-
-            nkey /= 2;
-            aes192_set_encrypt_key(&((QCryptoNettleAES192 *)ctx->ctx)->enc,
-                                   key);
-            aes192_set_decrypt_key(&((QCryptoNettleAES192 *)ctx->ctx)->dec,
-                                   key);
-
-            aes192_set_encrypt_key(&((QCryptoNettleAES192 *)ctx->ctx_tweak)->
-                                   enc, key + nkey);
-            aes192_set_decrypt_key(&((QCryptoNettleAES192 *)ctx->ctx_tweak)->
-                                   dec, key + nkey);
-        } else {
-            aes192_set_encrypt_key(&((QCryptoNettleAES192 *)ctx->ctx)->enc,
-                                   key);
-            aes192_set_decrypt_key(&((QCryptoNettleAES192 *)ctx->ctx)->dec,
-                                   key);
-        }
-
-        ctx->alg_encrypt_native = aes192_encrypt_native;
-        ctx->alg_decrypt_native = aes192_decrypt_native;
-        ctx->alg_encrypt_wrapper = aes192_encrypt_wrapper;
-        ctx->alg_decrypt_wrapper = aes192_decrypt_wrapper;
-
-        ctx->blocksize = AES_BLOCK_SIZE;
-        break;
-
-    case QCRYPTO_CIPHER_ALG_AES_256:
-        ctx->ctx = g_new0(QCryptoNettleAES256, 1);
-
-        if (mode == QCRYPTO_CIPHER_MODE_XTS) {
-            ctx->ctx_tweak = g_new0(QCryptoNettleAES256, 1);
-
-            nkey /= 2;
-            aes256_set_encrypt_key(&((QCryptoNettleAES256 *)ctx->ctx)->enc,
-                                   key);
-            aes256_set_decrypt_key(&((QCryptoNettleAES256 *)ctx->ctx)->dec,
-                                   key);
-
-            aes256_set_encrypt_key(&((QCryptoNettleAES256 *)ctx->ctx_tweak)->
-                                   enc, key + nkey);
-            aes256_set_decrypt_key(&((QCryptoNettleAES256 *)ctx->ctx_tweak)->
-                                   dec, key + nkey);
-        } else {
-            aes256_set_encrypt_key(&((QCryptoNettleAES256 *)ctx->ctx)->enc,
-                                   key);
-            aes256_set_decrypt_key(&((QCryptoNettleAES256 *)ctx->ctx)->dec,
-                                   key);
-        }
-
-        ctx->alg_encrypt_native = aes256_encrypt_native;
-        ctx->alg_decrypt_native = aes256_decrypt_native;
-        ctx->alg_encrypt_wrapper = aes256_encrypt_wrapper;
-        ctx->alg_decrypt_wrapper = aes256_decrypt_wrapper;
-
-        ctx->blocksize = AES_BLOCK_SIZE;
-        break;
-
-    case QCRYPTO_CIPHER_ALG_CAST5_128:
-        ctx->ctx = g_new0(struct cast128_ctx, 1);
-
-        if (mode == QCRYPTO_CIPHER_MODE_XTS) {
-            ctx->ctx_tweak = g_new0(struct cast128_ctx, 1);
-
-            nkey /= 2;
-            cast5_set_key(ctx->ctx, nkey, key);
-            cast5_set_key(ctx->ctx_tweak, nkey, key + nkey);
-        } else {
-            cast5_set_key(ctx->ctx, nkey, key);
-        }
-
-        ctx->alg_encrypt_native = cast128_encrypt_native;
-        ctx->alg_decrypt_native = cast128_decrypt_native;
-        ctx->alg_encrypt_wrapper = cast128_encrypt_wrapper;
-        ctx->alg_decrypt_wrapper = cast128_decrypt_wrapper;
-
-        ctx->blocksize = CAST128_BLOCK_SIZE;
-        break;
-
-    case QCRYPTO_CIPHER_ALG_SERPENT_128:
-    case QCRYPTO_CIPHER_ALG_SERPENT_192:
-    case QCRYPTO_CIPHER_ALG_SERPENT_256:
-        ctx->ctx = g_new0(struct serpent_ctx, 1);
-
-        if (mode == QCRYPTO_CIPHER_MODE_XTS) {
-            ctx->ctx_tweak = g_new0(struct serpent_ctx, 1);
-
-            nkey /= 2;
-            serpent_set_key(ctx->ctx, nkey, key);
-            serpent_set_key(ctx->ctx_tweak, nkey, key + nkey);
-        } else {
-            serpent_set_key(ctx->ctx, nkey, key);
-        }
-
-        ctx->alg_encrypt_native = serpent_encrypt_native;
-        ctx->alg_decrypt_native = serpent_decrypt_native;
-        ctx->alg_encrypt_wrapper = serpent_encrypt_wrapper;
-        ctx->alg_decrypt_wrapper = serpent_decrypt_wrapper;
-
-        ctx->blocksize = SERPENT_BLOCK_SIZE;
-        break;
-
-    case QCRYPTO_CIPHER_ALG_TWOFISH_128:
-    case QCRYPTO_CIPHER_ALG_TWOFISH_192:
-    case QCRYPTO_CIPHER_ALG_TWOFISH_256:
-        ctx->ctx = g_new0(struct twofish_ctx, 1);
-
-        if (mode == QCRYPTO_CIPHER_MODE_XTS) {
-            ctx->ctx_tweak = g_new0(struct twofish_ctx, 1);
-
-            nkey /= 2;
-            twofish_set_key(ctx->ctx, nkey, key);
-            twofish_set_key(ctx->ctx_tweak, nkey, key + nkey);
-        } else {
-            twofish_set_key(ctx->ctx, nkey, key);
-        }
-
-        ctx->alg_encrypt_native = twofish_encrypt_native;
-        ctx->alg_decrypt_native = twofish_decrypt_native;
-        ctx->alg_encrypt_wrapper = twofish_encrypt_wrapper;
-        ctx->alg_decrypt_wrapper = twofish_decrypt_wrapper;
-
-        ctx->blocksize = TWOFISH_BLOCK_SIZE;
-        break;
-
-    default:
-        error_setg(errp, "Unsupported cipher algorithm %s",
-                   QCryptoCipherAlgorithm_str(alg));
-        goto error;
-    }
-
-    if (mode == QCRYPTO_CIPHER_MODE_XTS &&
-        ctx->blocksize != XTS_BLOCK_SIZE) {
-        error_setg(errp, "Cipher block size %zu must equal XTS block size %d",
-                   ctx->blocksize, XTS_BLOCK_SIZE);
-        goto error;
-    }
-
-    ctx->iv = g_new0(uint8_t, ctx->blocksize);
-
-    return ctx;
-
- error:
-    qcrypto_nettle_cipher_free_ctx(ctx);
-    return NULL;
-}
-
-
-static void
-qcrypto_nettle_cipher_ctx_free(QCryptoCipher *cipher)
-{
-    QCryptoCipherNettle *ctx;
-
-    ctx = cipher->opaque;
-    qcrypto_nettle_cipher_free_ctx(ctx);
-}
-
-
-static int
-qcrypto_nettle_cipher_encrypt(QCryptoCipher *cipher,
-                              const void *in,
-                              void *out,
-                              size_t len,
-                              Error **errp)
-{
-    QCryptoCipherNettle *ctx = cipher->opaque;
-
-    if (len % ctx->blocksize) {
-        error_setg(errp, "Length %zu must be a multiple of block size %zu",
-                   len, ctx->blocksize);
-        return -1;
-    }
-
-    switch (cipher->mode) {
-    case QCRYPTO_CIPHER_MODE_ECB:
-        ctx->alg_encrypt_wrapper(ctx->ctx, len, out, in);
-        break;
-
-    case QCRYPTO_CIPHER_MODE_CBC:
-        cbc_encrypt(ctx->ctx, ctx->alg_encrypt_native,
-                    ctx->blocksize, ctx->iv,
-                    len, out, in);
-        break;
-
-    case QCRYPTO_CIPHER_MODE_XTS:
-#ifdef CONFIG_QEMU_PRIVATE_XTS
-        xts_encrypt(ctx->ctx, ctx->ctx_tweak,
-                    ctx->alg_encrypt_wrapper, ctx->alg_encrypt_wrapper,
-                    ctx->iv, len, out, in);
-#else
-        xts_encrypt_message(ctx->ctx, ctx->ctx_tweak,
-                            ctx->alg_encrypt_native,
-                            ctx->iv, len, out, in);
-#endif
-        break;
-
-    case QCRYPTO_CIPHER_MODE_CTR:
-        ctr_crypt(ctx->ctx, ctx->alg_encrypt_native,
-                    ctx->blocksize, ctx->iv,
-                    len, out, in);
-        break;
-
-    default:
-        error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_str(cipher->mode));
-        return -1;
-    }
-    return 0;
-}
-
-
-static int
-qcrypto_nettle_cipher_decrypt(QCryptoCipher *cipher,
-                              const void *in,
-                              void *out,
-                              size_t len,
-                              Error **errp)
-{
-    QCryptoCipherNettle *ctx = cipher->opaque;
-
-    if (len % ctx->blocksize) {
-        error_setg(errp, "Length %zu must be a multiple of block size %zu",
-                   len, ctx->blocksize);
-        return -1;
-    }
-
-    switch (cipher->mode) {
-    case QCRYPTO_CIPHER_MODE_ECB:
-        ctx->alg_decrypt_wrapper(ctx->ctx, len, out, in);
-        break;
-
-    case QCRYPTO_CIPHER_MODE_CBC:
-        cbc_decrypt(ctx->ctx, ctx->alg_decrypt_native,
-                    ctx->blocksize, ctx->iv,
-                    len, out, in);
-        break;
-
-    case QCRYPTO_CIPHER_MODE_XTS:
-#ifdef CONFIG_QEMU_PRIVATE_XTS
-        xts_decrypt(ctx->ctx, ctx->ctx_tweak,
-                    ctx->alg_encrypt_wrapper, ctx->alg_decrypt_wrapper,
-                    ctx->iv, len, out, in);
-#else
-        xts_decrypt_message(ctx->ctx, ctx->ctx_tweak,
-                            ctx->alg_decrypt_native,
-                            ctx->alg_encrypt_native,
-                            ctx->iv, len, out, in);
-#endif
-        break;
-    case QCRYPTO_CIPHER_MODE_CTR:
-        ctr_crypt(ctx->ctx, ctx->alg_encrypt_native,
-                    ctx->blocksize, ctx->iv,
-                    len, out, in);
-        break;
-
-    default:
-        error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_str(cipher->mode));
-        return -1;
-    }
-    return 0;
-}
-
-static int
-qcrypto_nettle_cipher_setiv(QCryptoCipher *cipher,
-                            const uint8_t *iv, size_t niv,
-                            Error **errp)
-{
-    QCryptoCipherNettle *ctx = cipher->opaque;
-    if (niv != ctx->blocksize) {
-        error_setg(errp, "Expected IV size %zu not %zu",
-                   ctx->blocksize, niv);
-        return -1;
-    }
-    memcpy(ctx->iv, iv, niv);
-    return 0;
-}
-
-
-static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = {
-    .cipher_encrypt = qcrypto_nettle_cipher_encrypt,
-    .cipher_decrypt = qcrypto_nettle_cipher_decrypt,
-    .cipher_setiv = qcrypto_nettle_cipher_setiv,
-    .cipher_free = qcrypto_nettle_cipher_ctx_free,
-};
diff --git a/crypto/cipher-nettle.c.inc b/crypto/cipher-nettle.c.inc
new file mode 100644
index 0000000000..cac771e4ff
--- /dev/null
+++ b/crypto/cipher-nettle.c.inc
@@ -0,0 +1,760 @@
+/*
+ * QEMU Crypto cipher nettle algorithms
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef CONFIG_QEMU_PRIVATE_XTS
+#include "crypto/xts.h"
+#endif
+
+#include <nettle/nettle-types.h>
+#include <nettle/aes.h>
+#include <nettle/des.h>
+#include <nettle/cbc.h>
+#include <nettle/cast128.h>
+#include <nettle/serpent.h>
+#include <nettle/twofish.h>
+#include <nettle/ctr.h>
+#ifndef CONFIG_QEMU_PRIVATE_XTS
+#include <nettle/xts.h>
+#endif
+
+typedef void (*QCryptoCipherNettleFuncWrapper)(const void *ctx,
+                                               size_t length,
+                                               uint8_t *dst,
+                                               const uint8_t *src);
+
+#if CONFIG_NETTLE_VERSION_MAJOR < 3
+typedef nettle_crypt_func * QCryptoCipherNettleFuncNative;
+typedef void *       cipher_ctx_t;
+typedef unsigned     cipher_length_t;
+#define CONST_CTX
+
+#define cast5_set_key cast128_set_key
+
+#define aes128_ctx aes_ctx
+#define aes192_ctx aes_ctx
+#define aes256_ctx aes_ctx
+#define aes128_set_encrypt_key(c, k) \
+    aes_set_encrypt_key(c, 16, k)
+#define aes192_set_encrypt_key(c, k) \
+    aes_set_encrypt_key(c, 24, k)
+#define aes256_set_encrypt_key(c, k) \
+    aes_set_encrypt_key(c, 32, k)
+#define aes128_set_decrypt_key(c, k) \
+    aes_set_decrypt_key(c, 16, k)
+#define aes192_set_decrypt_key(c, k) \
+    aes_set_decrypt_key(c, 24, k)
+#define aes256_set_decrypt_key(c, k) \
+    aes_set_decrypt_key(c, 32, k)
+#define aes128_encrypt aes_encrypt
+#define aes192_encrypt aes_encrypt
+#define aes256_encrypt aes_encrypt
+#define aes128_decrypt aes_decrypt
+#define aes192_decrypt aes_decrypt
+#define aes256_decrypt aes_decrypt
+#else
+typedef nettle_cipher_func * QCryptoCipherNettleFuncNative;
+typedef const void * cipher_ctx_t;
+typedef size_t       cipher_length_t;
+#define CONST_CTX    const
+#endif
+
+static inline bool qcrypto_length_check(size_t len, size_t blocksize,
+                                        Error **errp)
+{
+    if (unlikely(len & (blocksize - 1))) {
+        error_setg(errp, "Length %zu must be a multiple of block size %zu",
+                   len, blocksize);
+        return false;
+    }
+    return true;
+}
+
+
+static void qcrypto_cipher_ctx_free(QCryptoCipher *ctx)
+{
+    g_free(ctx);
+}
+
+static int qcrypto_cipher_no_setiv(QCryptoCipher *cipher,
+                                   const uint8_t *iv, size_t niv,
+                                   Error **errp)
+{
+    error_setg(errp, "Setting IV is not supported");
+    return -1;
+}
+
+
+#define DEFINE_SETIV(NAME, TYPE, BLEN)                                  \
+static int NAME##_setiv(QCryptoCipher *cipher, const uint8_t *iv,       \
+                        size_t niv, Error **errp)                       \
+{                                                                       \
+    TYPE *ctx = container_of(cipher, TYPE, base);                       \
+    if (niv != BLEN) {                                                  \
+        error_setg(errp, "Expected IV size %d not %zu", BLEN, niv);     \
+        return -1;                                                      \
+    }                                                                   \
+    memcpy(ctx->iv, iv, niv);                                           \
+    return 0;                                                           \
+}
+
+
+#define DEFINE_ECB(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)                  \
+static int NAME##_encrypt_ecb(QCryptoCipher *cipher, const void *in,    \
+                              void *out, size_t len, Error **errp)      \
+{                                                                       \
+    TYPE *ctx = container_of(cipher, TYPE, base);                       \
+    if (!qcrypto_length_check(len, BLEN, errp)) {                       \
+        return -1;                                                      \
+    }                                                                   \
+    ENCRYPT(&ctx->key, len, out, in);                                   \
+    return 0;                                                           \
+}                                                                       \
+static int NAME##_decrypt_ecb(QCryptoCipher *cipher, const void *in,    \
+                              void *out, size_t len, Error **errp)      \
+{                                                                       \
+    TYPE *ctx = container_of(cipher, TYPE, base);                       \
+    if (!qcrypto_length_check(len, BLEN, errp)) {                       \
+        return -1;                                                      \
+    }                                                                   \
+    DECRYPT(&ctx->key, len, out, in);                                   \
+    return 0;                                                           \
+}                                                                       \
+static const struct QCryptoCipherDriver NAME##_driver_ecb = {           \
+    .cipher_encrypt = NAME##_encrypt_ecb,                               \
+    .cipher_decrypt = NAME##_decrypt_ecb,                               \
+    .cipher_setiv = qcrypto_cipher_no_setiv,                            \
+    .cipher_free = qcrypto_cipher_ctx_free,                             \
+};
+
+
+#define DEFINE_CBC(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)                  \
+static int NAME##_encrypt_cbc(QCryptoCipher *cipher, const void *in,    \
+                              void *out, size_t len, Error **errp)      \
+{                                                                       \
+    TYPE *ctx = container_of(cipher, TYPE, base);                       \
+    if (!qcrypto_length_check(len, BLEN, errp)) {                       \
+        return -1;                                                      \
+    }                                                                   \
+    cbc_encrypt(&ctx->key, ENCRYPT, BLEN, ctx->iv, len, out, in);       \
+    return 0;                                                           \
+}                                                                       \
+static int NAME##_decrypt_cbc(QCryptoCipher *cipher, const void *in,    \
+                              void *out, size_t len, Error **errp)      \
+{                                                                       \
+    TYPE *ctx = container_of(cipher, TYPE, base);                       \
+    if (!qcrypto_length_check(len, BLEN, errp)) {                       \
+        return -1;                                                      \
+    }                                                                   \
+    cbc_decrypt(&ctx->key, DECRYPT, BLEN, ctx->iv, len, out, in);       \
+    return 0;                                                           \
+}                                                                       \
+static const struct QCryptoCipherDriver NAME##_driver_cbc = {           \
+    .cipher_encrypt = NAME##_encrypt_cbc,                               \
+    .cipher_decrypt = NAME##_decrypt_cbc,                               \
+    .cipher_setiv = NAME##_setiv,                                       \
+    .cipher_free = qcrypto_cipher_ctx_free,                             \
+};
+
+
+#define DEFINE_CTR(NAME, TYPE, BLEN, ENCRYPT)                           \
+static int NAME##_encrypt_ctr(QCryptoCipher *cipher, const void *in,    \
+                              void *out, size_t len, Error **errp)      \
+{                                                                       \
+    TYPE *ctx = container_of(cipher, TYPE, base);                       \
+    if (!qcrypto_length_check(len, BLEN, errp)) {                       \
+        return -1;                                                      \
+    }                                                                   \
+    ctr_crypt(&ctx->key, ENCRYPT, BLEN, ctx->iv, len, out, in);         \
+    return 0;                                                           \
+}                                                                       \
+static const struct QCryptoCipherDriver NAME##_driver_ctr = {           \
+    .cipher_encrypt = NAME##_encrypt_ctr,                               \
+    .cipher_decrypt = NAME##_encrypt_ctr,                               \
+    .cipher_setiv = NAME##_setiv,                                       \
+    .cipher_free = qcrypto_cipher_ctx_free,                             \
+};
+
+
+#ifdef CONFIG_QEMU_PRIVATE_XTS
+#define DEFINE__XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)                 \
+static void NAME##_xts_wrape(const void *ctx, size_t length,            \
+                             uint8_t *dst, const uint8_t *src)          \
+{                                                                       \
+    ENCRYPT((cipher_ctx_t)ctx, length, dst, src);                       \
+}                                                                       \
+static void NAME##_xts_wrapd(const void *ctx, size_t length,            \
+                             uint8_t *dst, const uint8_t *src)          \
+{                                                                       \
+    DECRYPT((cipher_ctx_t)ctx, length, dst, src);                       \
+}                                                                       \
+static int NAME##_encrypt_xts(QCryptoCipher *cipher, const void *in,    \
+                              void *out, size_t len, Error **errp)      \
+{                                                                       \
+    TYPE *ctx = container_of(cipher, TYPE, base);                       \
+    if (!qcrypto_length_check(len, BLEN, errp)) {                       \
+        return -1;                                                      \
+    }                                                                   \
+    xts_encrypt(&ctx->key, &ctx->key_xts,                               \
+                NAME##_xts_wrape, NAME##_xts_wrapd,                     \
+                ctx->iv, len, out, in);                                 \
+    return 0;                                                           \
+}                                                                       \
+static int NAME##_decrypt_xts(QCryptoCipher *cipher, const void *in,    \
+                              void *out, size_t len, Error **errp)      \
+{                                                                       \
+    TYPE *ctx = container_of(cipher, TYPE, base);                       \
+    if (!qcrypto_length_check(len, BLEN, errp)) {                       \
+        return -1;                                                      \
+    }                                                                   \
+    xts_decrypt(&ctx->key, &ctx->key_xts,                               \
+                NAME##_xts_wrape, NAME##_xts_wrapd,                     \
+                ctx->iv, len, out, in);                                 \
+    return 0;                                                           \
+}
+#else
+#define DEFINE__XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)                 \
+static int NAME##_encrypt_xts(QCryptoCipher *cipher, const void *in,    \
+                              void *out, size_t len, Error **errp)      \
+{                                                                       \
+    TYPE *ctx = container_of(cipher, TYPE, base);                       \
+    if (!qcrypto_length_check(len, BLEN, errp)) {                       \
+        return -1;                                                      \
+    }                                                                   \
+    xts_encrypt_message(&ctx->key, &ctx->key_xts, ENCRYPT,              \
+                        ctx->iv, len, out, in);                         \
+    return 0;                                                           \
+}                                                                       \
+static int NAME##_decrypt_xts(QCryptoCipher *cipher, const void *in,    \
+                              void *out, size_t len, Error **errp)      \
+{                                                                       \
+    TYPE *ctx = container_of(cipher, TYPE, base);                       \
+    if (!qcrypto_length_check(len, BLEN, errp)) {                       \
+        return -1;                                                      \
+    }                                                                   \
+    xts_decrypt_message(&ctx->key, &ctx->key_xts, DECRYPT, ENCRYPT,     \
+                        ctx->iv, len, out, in);                         \
+    return 0;                                                           \
+}
+#endif
+
+#define DEFINE_XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)          \
+    QEMU_BUILD_BUG_ON(BLEN != XTS_BLOCK_SIZE);                  \
+    DEFINE__XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)             \
+static const struct QCryptoCipherDriver NAME##_driver_xts = {   \
+    .cipher_encrypt = NAME##_encrypt_xts,                       \
+    .cipher_decrypt = NAME##_decrypt_xts,                       \
+    .cipher_setiv = NAME##_setiv,                               \
+    .cipher_free = qcrypto_cipher_ctx_free,                     \
+};
+
+
+#define DEFINE_ECB_CBC_CTR(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)  \
+    DEFINE_SETIV(NAME, TYPE, BLEN)                              \
+    DEFINE_ECB(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)              \
+    DEFINE_CBC(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)              \
+    DEFINE_CTR(NAME, TYPE, BLEN, ENCRYPT)
+
+#define DEFINE_ECB_CBC_CTR_XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)      \
+    DEFINE_ECB_CBC_CTR(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)              \
+    DEFINE_XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)
+
+
+typedef struct QCryptoNettleDESRFB {
+    QCryptoCipher base;
+    struct des_ctx key;
+    uint8_t iv[DES_BLOCK_SIZE];
+} QCryptoNettleDESRFB;
+
+static void des_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                               uint8_t *dst, const uint8_t *src)
+{
+    des_encrypt(ctx, length, dst, src);
+}
+
+static void des_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                               uint8_t *dst, const uint8_t *src)
+{
+    des_decrypt(ctx, length, dst, src);
+}
+
+DEFINE_ECB_CBC_CTR(qcrypto_nettle_des_rfb, QCryptoNettleDESRFB,
+                   DES_BLOCK_SIZE, des_encrypt_native, des_decrypt_native)
+
+
+typedef struct QCryptoNettleDES3 {
+    QCryptoCipher base;
+    struct des3_ctx key;
+    uint8_t iv[DES3_BLOCK_SIZE];
+} QCryptoNettleDES3;
+
+static void des3_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                uint8_t *dst, const uint8_t *src)
+{
+    des3_encrypt(ctx, length, dst, src);
+}
+
+static void des3_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                uint8_t *dst, const uint8_t *src)
+{
+    des3_decrypt(ctx, length, dst, src);
+}
+
+DEFINE_ECB_CBC_CTR(qcrypto_nettle_des3, QCryptoNettleDES3, DES3_BLOCK_SIZE,
+                   des3_encrypt_native, des3_decrypt_native)
+
+
+typedef struct QCryptoNettleAES128 {
+    QCryptoCipher base;
+    uint8_t iv[AES_BLOCK_SIZE];
+    /* First key from pair is encode, second key is decode. */
+    struct aes128_ctx key[2], key_xts[2];
+} QCryptoNettleAES128;
+
+static void aes128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                  uint8_t *dst, const uint8_t *src)
+{
+    CONST_CTX struct aes128_ctx *keys = ctx;
+    aes128_encrypt(&keys[0], length, dst, src);
+}
+
+static void aes128_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                  uint8_t *dst, const uint8_t *src)
+{
+    CONST_CTX struct aes128_ctx *keys = ctx;
+    aes128_decrypt(&keys[1], length, dst, src);
+}
+
+DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_aes128,
+                       QCryptoNettleAES128, AES_BLOCK_SIZE,
+                       aes128_encrypt_native, aes128_decrypt_native)
+
+
+typedef struct QCryptoNettleAES192 {
+    QCryptoCipher base;
+    uint8_t iv[AES_BLOCK_SIZE];
+    /* First key from pair is encode, second key is decode. */
+    struct aes192_ctx key[2], key_xts[2];
+} QCryptoNettleAES192;
+
+static void aes192_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                  uint8_t *dst, const uint8_t *src)
+{
+    CONST_CTX struct aes192_ctx *keys = ctx;
+    aes192_encrypt(&keys[0], length, dst, src);
+}
+
+static void aes192_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                  uint8_t *dst, const uint8_t *src)
+{
+    CONST_CTX struct aes192_ctx *keys = ctx;
+    aes192_decrypt(&keys[1], length, dst, src);
+}
+
+DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_aes192,
+                       QCryptoNettleAES192, AES_BLOCK_SIZE,
+                       aes192_encrypt_native, aes192_decrypt_native)
+
+
+typedef struct QCryptoNettleAES256 {
+    QCryptoCipher base;
+    uint8_t iv[AES_BLOCK_SIZE];
+    /* First key from pair is encode, second key is decode. */
+    struct aes256_ctx key[2], key_xts[2];
+} QCryptoNettleAES256;
+
+static void aes256_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                  uint8_t *dst, const uint8_t *src)
+{
+    CONST_CTX struct aes256_ctx *keys = ctx;
+    aes256_encrypt(&keys[0], length, dst, src);
+}
+
+static void aes256_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                               uint8_t *dst, const uint8_t *src)
+{
+    CONST_CTX struct aes256_ctx *keys = ctx;
+    aes256_decrypt(&keys[1], length, dst, src);
+}
+
+DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_aes256,
+                       QCryptoNettleAES256, AES_BLOCK_SIZE,
+                       aes256_encrypt_native, aes256_decrypt_native)
+
+
+typedef struct QCryptoNettleCAST128 {
+    QCryptoCipher base;
+    uint8_t iv[CAST128_BLOCK_SIZE];
+    struct cast128_ctx key, key_xts;
+} QCryptoNettleCAST128;
+
+static void cast128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                   uint8_t *dst, const uint8_t *src)
+{
+    cast128_encrypt(ctx, length, dst, src);
+}
+
+static void cast128_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                   uint8_t *dst, const uint8_t *src)
+{
+    cast128_decrypt(ctx, length, dst, src);
+}
+
+DEFINE_ECB_CBC_CTR(qcrypto_nettle_cast128,
+                   QCryptoNettleCAST128, CAST128_BLOCK_SIZE,
+                   cast128_encrypt_native, cast128_decrypt_native)
+
+
+typedef struct QCryptoNettleSerpent {
+    QCryptoCipher base;
+    uint8_t iv[SERPENT_BLOCK_SIZE];
+    struct serpent_ctx key, key_xts;
+} QCryptoNettleSerpent;
+
+
+static void serpent_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                   uint8_t *dst, const uint8_t *src)
+{
+    serpent_encrypt(ctx, length, dst, src);
+}
+
+static void serpent_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                   uint8_t *dst, const uint8_t *src)
+{
+    serpent_decrypt(ctx, length, dst, src);
+}
+
+DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_serpent,
+                       QCryptoNettleSerpent, SERPENT_BLOCK_SIZE,
+                       serpent_encrypt_native, serpent_decrypt_native)
+
+
+typedef struct QCryptoNettleTwofish {
+    QCryptoCipher base;
+    uint8_t iv[TWOFISH_BLOCK_SIZE];
+    struct twofish_ctx key, key_xts;
+} QCryptoNettleTwofish;
+
+static void twofish_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                   uint8_t *dst, const uint8_t *src)
+{
+    twofish_encrypt(ctx, length, dst, src);
+}
+
+static void twofish_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                   uint8_t *dst, const uint8_t *src)
+{
+    twofish_decrypt(ctx, length, dst, src);
+}
+
+DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_twofish,
+                       QCryptoNettleTwofish, TWOFISH_BLOCK_SIZE,
+                       twofish_encrypt_native, twofish_decrypt_native)
+
+
+bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
+                             QCryptoCipherMode mode)
+{
+    switch (alg) {
+    case QCRYPTO_CIPHER_ALG_DES_RFB:
+    case QCRYPTO_CIPHER_ALG_3DES:
+    case QCRYPTO_CIPHER_ALG_AES_128:
+    case QCRYPTO_CIPHER_ALG_AES_192:
+    case QCRYPTO_CIPHER_ALG_AES_256:
+    case QCRYPTO_CIPHER_ALG_CAST5_128:
+    case QCRYPTO_CIPHER_ALG_SERPENT_128:
+    case QCRYPTO_CIPHER_ALG_SERPENT_192:
+    case QCRYPTO_CIPHER_ALG_SERPENT_256:
+    case QCRYPTO_CIPHER_ALG_TWOFISH_128:
+    case QCRYPTO_CIPHER_ALG_TWOFISH_192:
+    case QCRYPTO_CIPHER_ALG_TWOFISH_256:
+        break;
+    default:
+        return false;
+    }
+
+    switch (mode) {
+    case QCRYPTO_CIPHER_MODE_ECB:
+    case QCRYPTO_CIPHER_MODE_CBC:
+    case QCRYPTO_CIPHER_MODE_XTS:
+    case QCRYPTO_CIPHER_MODE_CTR:
+        return true;
+    default:
+        return false;
+    }
+}
+
+static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
+                                             QCryptoCipherMode mode,
+                                             const uint8_t *key,
+                                             size_t nkey,
+                                             Error **errp)
+{
+    switch (mode) {
+    case QCRYPTO_CIPHER_MODE_ECB:
+    case QCRYPTO_CIPHER_MODE_CBC:
+    case QCRYPTO_CIPHER_MODE_XTS:
+    case QCRYPTO_CIPHER_MODE_CTR:
+        break;
+    default:
+        goto bad_cipher_mode;
+    }
+
+    if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
+        return NULL;
+    }
+
+    switch (alg) {
+    case QCRYPTO_CIPHER_ALG_DES_RFB:
+        {
+            QCryptoNettleDESRFB *ctx;
+            const QCryptoCipherDriver *drv;
+            uint8_t *rfbkey;
+
+            switch (mode) {
+            case QCRYPTO_CIPHER_MODE_ECB:
+                drv = &qcrypto_nettle_des_rfb_driver_ecb;
+                break;
+            case QCRYPTO_CIPHER_MODE_CBC:
+                drv = &qcrypto_nettle_des_rfb_driver_cbc;
+                break;
+            case QCRYPTO_CIPHER_MODE_CTR:
+                drv = &qcrypto_nettle_des_rfb_driver_ctr;
+                break;
+            default:
+                goto bad_cipher_mode;
+            }
+
+            ctx = g_new0(QCryptoNettleDESRFB, 1);
+            ctx->base.driver = drv;
+
+            rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
+            des_set_key(&ctx->key, rfbkey);
+            g_free(rfbkey);
+
+            return &ctx->base;
+        }
+
+    case QCRYPTO_CIPHER_ALG_3DES:
+        {
+            QCryptoNettleDES3 *ctx;
+            const QCryptoCipherDriver *drv;
+
+            switch (mode) {
+            case QCRYPTO_CIPHER_MODE_ECB:
+                drv = &qcrypto_nettle_des3_driver_ecb;
+                break;
+            case QCRYPTO_CIPHER_MODE_CBC:
+                drv = &qcrypto_nettle_des3_driver_cbc;
+                break;
+            case QCRYPTO_CIPHER_MODE_CTR:
+                drv = &qcrypto_nettle_des3_driver_ctr;
+                break;
+            default:
+                goto bad_cipher_mode;
+            }
+
+            ctx = g_new0(QCryptoNettleDES3, 1);
+            ctx->base.driver = drv;
+            des3_set_key(&ctx->key, key);
+            return &ctx->base;
+        }
+
+    case QCRYPTO_CIPHER_ALG_AES_128:
+        {
+            QCryptoNettleAES128 *ctx = g_new0(QCryptoNettleAES128, 1);
+
+            switch (mode) {
+            case QCRYPTO_CIPHER_MODE_ECB:
+                ctx->base.driver = &qcrypto_nettle_aes128_driver_ecb;
+                break;
+            case QCRYPTO_CIPHER_MODE_CBC:
+                ctx->base.driver = &qcrypto_nettle_aes128_driver_cbc;
+                break;
+            case QCRYPTO_CIPHER_MODE_CTR:
+                ctx->base.driver = &qcrypto_nettle_aes128_driver_ctr;
+                break;
+            case QCRYPTO_CIPHER_MODE_XTS:
+                ctx->base.driver = &qcrypto_nettle_aes128_driver_xts;
+                nkey /= 2;
+                aes128_set_encrypt_key(&ctx->key_xts[0], key + nkey);
+                aes128_set_decrypt_key(&ctx->key_xts[1], key + nkey);
+                break;
+            default:
+                g_assert_not_reached();
+            }
+            aes128_set_encrypt_key(&ctx->key[0], key);
+            aes128_set_decrypt_key(&ctx->key[1], key);
+
+            return &ctx->base;
+        }
+
+    case QCRYPTO_CIPHER_ALG_AES_192:
+        {
+            QCryptoNettleAES192 *ctx = g_new0(QCryptoNettleAES192, 1);
+
+            switch (mode) {
+            case QCRYPTO_CIPHER_MODE_ECB:
+                ctx->base.driver = &qcrypto_nettle_aes192_driver_ecb;
+                break;
+            case QCRYPTO_CIPHER_MODE_CBC:
+                ctx->base.driver = &qcrypto_nettle_aes192_driver_cbc;
+                break;
+            case QCRYPTO_CIPHER_MODE_CTR:
+                ctx->base.driver = &qcrypto_nettle_aes192_driver_ctr;
+                break;
+            case QCRYPTO_CIPHER_MODE_XTS:
+                ctx->base.driver = &qcrypto_nettle_aes192_driver_xts;
+                nkey /= 2;
+                aes192_set_encrypt_key(&ctx->key_xts[0], key + nkey);
+                aes192_set_decrypt_key(&ctx->key_xts[1], key + nkey);
+                break;
+            default:
+                g_assert_not_reached();
+            }
+            aes192_set_encrypt_key(&ctx->key[0], key);
+            aes192_set_decrypt_key(&ctx->key[1], key);
+
+            return &ctx->base;
+        }
+
+    case QCRYPTO_CIPHER_ALG_AES_256:
+        {
+            QCryptoNettleAES256 *ctx = g_new0(QCryptoNettleAES256, 1);
+
+            switch (mode) {
+            case QCRYPTO_CIPHER_MODE_ECB:
+                ctx->base.driver = &qcrypto_nettle_aes256_driver_ecb;
+                break;
+            case QCRYPTO_CIPHER_MODE_CBC:
+                ctx->base.driver = &qcrypto_nettle_aes256_driver_cbc;
+                break;
+            case QCRYPTO_CIPHER_MODE_CTR:
+                ctx->base.driver = &qcrypto_nettle_aes256_driver_ctr;
+                break;
+            case QCRYPTO_CIPHER_MODE_XTS:
+                ctx->base.driver = &qcrypto_nettle_aes256_driver_xts;
+                nkey /= 2;
+                aes256_set_encrypt_key(&ctx->key_xts[0], key + nkey);
+                aes256_set_decrypt_key(&ctx->key_xts[1], key + nkey);
+                break;
+            default:
+                g_assert_not_reached();
+            }
+            aes256_set_encrypt_key(&ctx->key[0], key);
+            aes256_set_decrypt_key(&ctx->key[1], key);
+
+            return &ctx->base;
+        }
+
+    case QCRYPTO_CIPHER_ALG_CAST5_128:
+        {
+            QCryptoNettleCAST128 *ctx;
+            const QCryptoCipherDriver *drv;
+
+            switch (mode) {
+            case QCRYPTO_CIPHER_MODE_ECB:
+                drv = &qcrypto_nettle_cast128_driver_ecb;
+                break;
+            case QCRYPTO_CIPHER_MODE_CBC:
+                drv = &qcrypto_nettle_cast128_driver_cbc;
+                break;
+            case QCRYPTO_CIPHER_MODE_CTR:
+                drv = &qcrypto_nettle_cast128_driver_ctr;
+                break;
+            default:
+                goto bad_cipher_mode;
+            }
+
+            ctx = g_new0(QCryptoNettleCAST128, 1);
+            ctx->base.driver = drv;
+            cast5_set_key(&ctx->key, nkey, key);
+
+            return &ctx->base;
+        }
+
+    case QCRYPTO_CIPHER_ALG_SERPENT_128:
+    case QCRYPTO_CIPHER_ALG_SERPENT_192:
+    case QCRYPTO_CIPHER_ALG_SERPENT_256:
+        {
+            QCryptoNettleSerpent *ctx = g_new0(QCryptoNettleSerpent, 1);
+
+            switch (mode) {
+            case QCRYPTO_CIPHER_MODE_ECB:
+                ctx->base.driver = &qcrypto_nettle_serpent_driver_ecb;
+                break;
+            case QCRYPTO_CIPHER_MODE_CBC:
+                ctx->base.driver = &qcrypto_nettle_serpent_driver_cbc;
+                break;
+            case QCRYPTO_CIPHER_MODE_CTR:
+                ctx->base.driver = &qcrypto_nettle_serpent_driver_ctr;
+                break;
+            case QCRYPTO_CIPHER_MODE_XTS:
+                ctx->base.driver = &qcrypto_nettle_serpent_driver_xts;
+                nkey /= 2;
+                serpent_set_key(&ctx->key_xts, nkey, key + nkey);
+                break;
+            default:
+                g_assert_not_reached();
+            }
+            serpent_set_key(&ctx->key, nkey, key);
+
+            return &ctx->base;
+        }
+
+    case QCRYPTO_CIPHER_ALG_TWOFISH_128:
+    case QCRYPTO_CIPHER_ALG_TWOFISH_192:
+    case QCRYPTO_CIPHER_ALG_TWOFISH_256:
+        {
+            QCryptoNettleTwofish *ctx = g_new0(QCryptoNettleTwofish, 1);
+
+            switch (mode) {
+            case QCRYPTO_CIPHER_MODE_ECB:
+                ctx->base.driver = &qcrypto_nettle_twofish_driver_ecb;
+                break;
+            case QCRYPTO_CIPHER_MODE_CBC:
+                ctx->base.driver = &qcrypto_nettle_twofish_driver_cbc;
+                break;
+            case QCRYPTO_CIPHER_MODE_CTR:
+                ctx->base.driver = &qcrypto_nettle_twofish_driver_ctr;
+                break;
+            case QCRYPTO_CIPHER_MODE_XTS:
+                ctx->base.driver = &qcrypto_nettle_twofish_driver_xts;
+                nkey /= 2;
+                twofish_set_key(&ctx->key_xts, nkey, key + nkey);
+                break;
+            default:
+                g_assert_not_reached();
+            }
+            twofish_set_key(&ctx->key, nkey, key);
+
+            return &ctx->base;
+        }
+
+    default:
+        error_setg(errp, "Unsupported cipher algorithm %s",
+                   QCryptoCipherAlgorithm_str(alg));
+        return NULL;
+    }
+
+ bad_cipher_mode:
+    error_setg(errp, "Unsupported cipher mode %s",
+               QCryptoCipherMode_str(mode));
+    return NULL;
+}
diff --git a/crypto/cipher.c b/crypto/cipher.c
index e5adb56271..068b2fb867 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -19,12 +19,13 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/host-utils.h"
 #include "qapi/error.h"
 #include "crypto/cipher.h"
 #include "cipherpriv.h"
 
 
-static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
+static const size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
     [QCRYPTO_CIPHER_ALG_AES_128] = 16,
     [QCRYPTO_CIPHER_ALG_AES_192] = 24,
     [QCRYPTO_CIPHER_ALG_AES_256] = 32,
@@ -39,7 +40,7 @@ static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
     [QCRYPTO_CIPHER_ALG_TWOFISH_256] = 32,
 };
 
-static size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
+static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
     [QCRYPTO_CIPHER_ALG_AES_128] = 16,
     [QCRYPTO_CIPHER_ALG_AES_192] = 16,
     [QCRYPTO_CIPHER_ALG_AES_256] = 16,
@@ -54,7 +55,7 @@ static size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
     [QCRYPTO_CIPHER_ALG_TWOFISH_256] = 16,
 };
 
-static bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = {
+static const bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = {
     [QCRYPTO_CIPHER_MODE_ECB] = false,
     [QCRYPTO_CIPHER_MODE_CBC] = true,
     [QCRYPTO_CIPHER_MODE_XTS] = true,
@@ -150,11 +151,11 @@ qcrypto_cipher_munge_des_rfb_key(const uint8_t *key,
 #endif /* CONFIG_GCRYPT || CONFIG_NETTLE */
 
 #ifdef CONFIG_GCRYPT
-#include "cipher-gcrypt.c"
+#include "cipher-gcrypt.c.inc"
 #elif defined CONFIG_NETTLE
-#include "cipher-nettle.c"
+#include "cipher-nettle.c.inc"
 #else
-#include "cipher-builtin.c"
+#include "cipher-builtin.c.inc"
 #endif
 
 QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
@@ -162,31 +163,21 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
                                   const uint8_t *key, size_t nkey,
                                   Error **errp)
 {
-    QCryptoCipher *cipher;
-    void *ctx = NULL;
-    QCryptoCipherDriver *drv = NULL;
+    QCryptoCipher *cipher = NULL;
 
 #ifdef CONFIG_AF_ALG
-    ctx = qcrypto_afalg_cipher_ctx_new(alg, mode, key, nkey, NULL);
-    if (ctx) {
-        drv = &qcrypto_cipher_afalg_driver;
-    }
+    cipher = qcrypto_afalg_cipher_ctx_new(alg, mode, key, nkey, NULL);
 #endif
 
-    if (!ctx) {
-        ctx = qcrypto_cipher_ctx_new(alg, mode, key, nkey, errp);
-        if (!ctx) {
+    if (!cipher) {
+        cipher = qcrypto_cipher_ctx_new(alg, mode, key, nkey, errp);
+        if (!cipher) {
             return NULL;
         }
-
-        drv = &qcrypto_cipher_lib_driver;
     }
 
-    cipher = g_new0(QCryptoCipher, 1);
     cipher->alg = alg;
     cipher->mode = mode;
-    cipher->opaque = ctx;
-    cipher->driver = (void *)drv;
 
     return cipher;
 }
@@ -198,7 +189,7 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
                            size_t len,
                            Error **errp)
 {
-    QCryptoCipherDriver *drv = cipher->driver;
+    const QCryptoCipherDriver *drv = cipher->driver;
     return drv->cipher_encrypt(cipher, in, out, len, errp);
 }
 
@@ -209,7 +200,7 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
                            size_t len,
                            Error **errp)
 {
-    QCryptoCipherDriver *drv = cipher->driver;
+    const QCryptoCipherDriver *drv = cipher->driver;
     return drv->cipher_decrypt(cipher, in, out, len, errp);
 }
 
@@ -218,17 +209,14 @@ int qcrypto_cipher_setiv(QCryptoCipher *cipher,
                          const uint8_t *iv, size_t niv,
                          Error **errp)
 {
-    QCryptoCipherDriver *drv = cipher->driver;
+    const QCryptoCipherDriver *drv = cipher->driver;
     return drv->cipher_setiv(cipher, iv, niv, errp);
 }
 
 
 void qcrypto_cipher_free(QCryptoCipher *cipher)
 {
-    QCryptoCipherDriver *drv;
     if (cipher) {
-        drv = cipher->driver;
-        drv->cipher_free(cipher);
-        g_free(cipher);
+        cipher->driver->cipher_free(cipher);
     }
 }
diff --git a/crypto/cipherpriv.h b/crypto/cipherpriv.h
index 0823239f41..396527857d 100644
--- a/crypto/cipherpriv.h
+++ b/crypto/cipherpriv.h
@@ -17,8 +17,6 @@
 
 #include "qapi/qapi-types-crypto.h"
 
-typedef struct QCryptoCipherDriver QCryptoCipherDriver;
-
 struct QCryptoCipherDriver {
     int (*cipher_encrypt)(QCryptoCipher *cipher,
                           const void *in,
@@ -43,14 +41,12 @@ struct QCryptoCipherDriver {
 
 #include "afalgpriv.h"
 
-extern QCryptoAFAlg *
+extern QCryptoCipher *
 qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg,
                              QCryptoCipherMode mode,
                              const uint8_t *key,
                              size_t nkey, Error **errp);
 
-extern struct QCryptoCipherDriver qcrypto_cipher_afalg_driver;
-
 #endif
 
 #endif
diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst
index a05990906c..0568dfa6a4 100644
--- a/docs/devel/tcg-plugins.rst
+++ b/docs/devel/tcg-plugins.rst
@@ -134,3 +134,149 @@ longer want to instrument the code. This operation is asynchronous
 which means callbacks may still occur after the uninstall operation is
 requested. The plugin isn't completely uninstalled until the safe work
 has executed while all vCPUs are quiescent.
+
+Example Plugins
+===============
+
+There are a number of plugins included with QEMU and you are
+encouraged to contribute your own plugins plugins upstream. There is a
+`contrib/plugins` directory where they can go.
+
+- tests/plugins
+
+These are some basic plugins that are used to test and exercise the
+API during the `make check-tcg` target.
+
+- contrib/plugins/hotblocks.c
+
+The hotblocks plugin allows you to examine the where hot paths of
+execution are in your program. Once the program has finished you will
+get a sorted list of blocks reporting the starting PC, translation
+count, number of instructions and execution count. This will work best
+with linux-user execution as system emulation tends to generate
+re-translations as blocks from different programs get swapped in and
+out of system memory.
+
+If your program is single-threaded you can use the `inline` option for
+slightly faster (but not thread safe) counters.
+
+Example::
+
+  ./aarch64-linux-user/qemu-aarch64 \
+    -plugin contrib/plugins/libhotblocks.so -d plugin \
+    ./tests/tcg/aarch64-linux-user/sha1
+  SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6
+  collected 903 entries in the hash table
+  pc, tcount, icount, ecount
+  0x0000000041ed10, 1, 5, 66087
+  0x000000004002b0, 1, 4, 66087
+  ...
+
+- contrib/plugins/hotpages.c
+
+Similar to hotblocks but this time tracks memory accesses::
+
+  ./aarch64-linux-user/qemu-aarch64 \
+    -plugin contrib/plugins/libhotpages.so -d plugin \
+    ./tests/tcg/aarch64-linux-user/sha1
+  SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6
+  Addr, RCPUs, Reads, WCPUs, Writes
+  0x000055007fe000, 0x0001, 31747952, 0x0001, 8835161
+  0x000055007ff000, 0x0001, 29001054, 0x0001, 8780625
+  0x00005500800000, 0x0001, 687465, 0x0001, 335857
+  0x0000000048b000, 0x0001, 130594, 0x0001, 355
+  0x0000000048a000, 0x0001, 1826, 0x0001, 11
+
+- contrib/plugins/howvec.c
+
+This is an instruction classifier so can be used to count different
+types of instructions. It has a number of options to refine which get
+counted. You can give an argument for a class of instructions to break
+it down fully, so for example to see all the system registers
+accesses::
+
+  ./aarch64-softmmu/qemu-system-aarch64 $(QEMU_ARGS) \
+    -append "root=/dev/sda2 systemd.unit=benchmark.service" \
+    -smp 4 -plugin ./contrib/plugins/libhowvec.so,arg=sreg -d plugin
+
+which will lead to a sorted list after the class breakdown::
+
+  Instruction Classes:
+  Class:   UDEF                   not counted
+  Class:   SVE                    (68 hits)
+  Class:   PCrel addr             (47789483 hits)
+  Class:   Add/Sub (imm)          (192817388 hits)
+  Class:   Logical (imm)          (93852565 hits)
+  Class:   Move Wide (imm)        (76398116 hits)
+  Class:   Bitfield               (44706084 hits)
+  Class:   Extract                (5499257 hits)
+  Class:   Cond Branch (imm)      (147202932 hits)
+  Class:   Exception Gen          (193581 hits)
+  Class:     NOP                  not counted
+  Class:   Hints                  (6652291 hits)
+  Class:   Barriers               (8001661 hits)
+  Class:   PSTATE                 (1801695 hits)
+  Class:   System Insn            (6385349 hits)
+  Class:   System Reg             counted individually
+  Class:   Branch (reg)           (69497127 hits)
+  Class:   Branch (imm)           (84393665 hits)
+  Class:   Cmp & Branch           (110929659 hits)
+  Class:   Tst & Branch           (44681442 hits)
+  Class:   AdvSimd ldstmult       (736 hits)
+  Class:   ldst excl              (9098783 hits)
+  Class:   Load Reg (lit)         (87189424 hits)
+  Class:   ldst noalloc pair      (3264433 hits)
+  Class:   ldst pair              (412526434 hits)
+  Class:   ldst reg (imm)         (314734576 hits)
+  Class: Loads & Stores           (2117774 hits)
+  Class: Data Proc Reg            (223519077 hits)
+  Class: Scalar FP                (31657954 hits)
+  Individual Instructions:
+  Instr: mrs x0, sp_el0           (2682661 hits)  (op=0xd5384100/  System Reg)
+  Instr: mrs x1, tpidr_el2        (1789339 hits)  (op=0xd53cd041/  System Reg)
+  Instr: mrs x2, tpidr_el2        (1513494 hits)  (op=0xd53cd042/  System Reg)
+  Instr: mrs x0, tpidr_el2        (1490823 hits)  (op=0xd53cd040/  System Reg)
+  Instr: mrs x1, sp_el0           (933793 hits)   (op=0xd5384101/  System Reg)
+  Instr: mrs x2, sp_el0           (699516 hits)   (op=0xd5384102/  System Reg)
+  Instr: mrs x4, tpidr_el2        (528437 hits)   (op=0xd53cd044/  System Reg)
+  Instr: mrs x30, ttbr1_el1       (480776 hits)   (op=0xd538203e/  System Reg)
+  Instr: msr ttbr1_el1, x30       (480713 hits)   (op=0xd518203e/  System Reg)
+  Instr: msr vbar_el1, x30        (480671 hits)   (op=0xd518c01e/  System Reg)
+  ...
+
+To find the argument shorthand for the class you need to examine the
+source code of the plugin at the moment, specifically the `*opt`
+argument in the InsnClassExecCount tables.
+
+- contrib/plugins/lockstep.c
+
+This is a debugging tool for developers who want to find out when and
+where execution diverges after a subtle change to TCG code generation.
+It is not an exact science and results are likely to be mixed once
+asynchronous events are introduced. While the use of -icount can
+introduce determinism to the execution flow it doesn't always follow
+the translation sequence will be exactly the same. Typically this is
+caused by a timer firing to service the GUI causing a block to end
+early. However in some cases it has proved to be useful in pointing
+people at roughly where execution diverges. The only argument you need
+for the plugin is a path for the socket the two instances will
+communicate over::
+
+
+  ./sparc-softmmu/qemu-system-sparc -monitor none -parallel none \
+    -net none -M SS-20 -m 256 -kernel day11/zImage.elf \
+    -plugin ./contrib/plugins/liblockstep.so,arg=lockstep-sparc.sock \
+  -d plugin,nochain
+
+which will eventually report::
+
+  qemu-system-sparc: warning: nic lance.0 has no peer
+  @ 0x000000ffd06678 vs 0x000000ffd001e0 (2/1 since last)
+  @ 0x000000ffd07d9c vs 0x000000ffd06678 (3/1 since last)
+  Δ insn_count @ 0x000000ffd07d9c (809900609) vs 0x000000ffd06678 (809900612)
+    previously @ 0x000000ffd06678/10 (809900609 insns)
+    previously @ 0x000000ffd001e0/4 (809900599 insns)
+    previously @ 0x000000ffd080ac/2 (809900595 insns)
+    previously @ 0x000000ffd08098/5 (809900593 insns)
+    previously @ 0x000000ffd080c0/1 (809900588 insns)
+
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
index 851dbdeb8a..a158e765c3 100644
--- a/docs/system/deprecated.rst
+++ b/docs/system/deprecated.rst
@@ -424,6 +424,13 @@ linux-user mode) is deprecated and will be removed in a future version
 of QEMU. Support for this CPU was removed from the upstream Linux
 kernel in 2018, and has also been dropped from glibc.
 
+``ppc64abi32`` CPUs (since 5.2.0)
+'''''''''''''''''''''''''''''''''
+
+The ``ppc64abi32`` architecture has a number of issues which regularly
+trip up our CI testing and is suspected to be quite broken. For that
+reason the maintainers strongly suspect no one actually uses it.
+
 Related binaries
 ----------------
 
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index e763da2c02..ff70c5a971 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -4,18 +4,19 @@
 #include "standard-headers/linux/virtio_9p.h"
 #include "hw/virtio/virtio.h"
 #include "9p.h"
+#include "qom/object.h"
 
-typedef struct V9fsVirtioState
-{
+struct V9fsVirtioState {
     VirtIODevice parent_obj;
     VirtQueue *vq;
     size_t config_size;
     VirtQueueElement *elems[MAX_REQ];
     V9fsState state;
-} V9fsVirtioState;
+};
+typedef struct V9fsVirtioState V9fsVirtioState;
 
 #define TYPE_VIRTIO_9P "virtio-9p-device"
-#define VIRTIO_9P(obj) \
-        OBJECT_CHECK(V9fsVirtioState, (obj), TYPE_VIRTIO_9P)
+DECLARE_INSTANCE_CHECKER(V9fsVirtioState, VIRTIO_9P,
+                         TYPE_VIRTIO_9P)
 
 #endif
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index e6163bb6ce..1574f7db3e 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -45,6 +45,7 @@
 #include "migration/vmstate.h"
 #include "hw/core/cpu.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define GPE_BASE 0xafe0
 #define GPE_LEN 4
@@ -54,7 +55,7 @@ struct pci_status {
     uint32_t down;
 };
 
-typedef struct PIIX4PMState {
+struct PIIX4PMState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
@@ -89,10 +90,11 @@ typedef struct PIIX4PMState {
     CPUHotplugState cpuhp_state;
 
     MemHotplugState acpi_memory_hotplug;
-} PIIX4PMState;
+};
+typedef struct PIIX4PMState PIIX4PMState;
 
-#define PIIX4_PM(obj) \
-    OBJECT_CHECK(PIIX4PMState, (obj), TYPE_PIIX4_PM)
+DECLARE_INSTANCE_CHECKER(PIIX4PMState, PIIX4_PM,
+                         TYPE_PIIX4_PM)
 
 static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
                                            PCIBus *bus, PIIX4PMState *s);
diff --git a/hw/acpi/tco.c b/hw/acpi/tco.c
index fb9052dbca..cf1e68a539 100644
--- a/hw/acpi/tco.c
+++ b/hw/acpi/tco.c
@@ -15,17 +15,6 @@
 #include "hw/acpi/tco.h"
 #include "trace.h"
 
-//#define DEBUG
-
-#ifdef DEBUG
-#define TCO_DEBUG(fmt, ...)                                     \
-    do {                                                        \
-        fprintf(stderr, "%s "fmt, __func__, ## __VA_ARGS__);    \
-    } while (0)
-#else
-#define TCO_DEBUG(fmt, ...) do { } while (0)
-#endif
-
 enum {
     TCO_RLD_DEFAULT         = 0x0000,
     TCO_DAT_IN_DEFAULT      = 0x00,
diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c
index 2df7623d74..53db6af75d 100644
--- a/hw/acpi/vmgenid.c
+++ b/hw/acpi/vmgenid.c
@@ -198,7 +198,7 @@ static void vmgenid_realize(DeviceState *dev, Error **errp)
 
     if (!bios_linker_loader_can_write_pointer()) {
         error_setg(errp, "%s requires DMA write support in fw_cfg, "
-                   "which this machine type does not provide", VMGENID_DEVICE);
+                   "which this machine type does not provide", TYPE_VMGENID);
         return;
     }
 
@@ -206,7 +206,7 @@ static void vmgenid_realize(DeviceState *dev, Error **errp)
      * device. Check if there are several.
      */
     if (!find_vmgenid_dev()) {
-        error_setg(errp, "at most one %s device is permitted", VMGENID_DEVICE);
+        error_setg(errp, "at most one %s device is permitted", TYPE_VMGENID);
         return;
     }
 
@@ -232,7 +232,7 @@ static void vmgenid_device_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo vmgenid_device_info = {
-    .name          = VMGENID_DEVICE,
+    .name          = TYPE_VMGENID,
     .parent        = TYPE_DEVICE,
     .instance_size = sizeof(VmGenIdState),
     .class_init    = vmgenid_device_class_init,
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index 29d44dfb06..d02b14d89f 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -15,6 +15,7 @@
 #include "hw/irq.h"
 #include "alpha_sys.h"
 #include "exec/address-spaces.h"
+#include "qom/object.h"
 
 
 #define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost"
@@ -49,16 +50,17 @@ typedef struct TyphoonPchip {
     TyphoonWindow win[4];
 } TyphoonPchip;
 
-#define TYPHOON_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(TyphoonState, (obj), TYPE_TYPHOON_PCI_HOST_BRIDGE)
+typedef struct TyphoonState TyphoonState;
+DECLARE_INSTANCE_CHECKER(TyphoonState, TYPHOON_PCI_HOST_BRIDGE,
+                         TYPE_TYPHOON_PCI_HOST_BRIDGE)
 
-typedef struct TyphoonState {
+struct TyphoonState {
     PCIHostState parent_obj;
 
     TyphoonCchip cchip;
     TyphoonPchip pchip;
     MemoryRegion dchip_region;
-} TyphoonState;
+};
 
 /* Called when one of DRIR or DIM changes.  */
 static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
index 4b35ef4bed..a49f4a1c7c 100644
--- a/hw/arm/collie.c
+++ b/hw/arm/collie.c
@@ -18,16 +18,18 @@
 #include "hw/block/flash.h"
 #include "exec/address-spaces.h"
 #include "cpu.h"
+#include "qom/object.h"
 
-typedef struct {
+struct CollieMachineState {
     MachineState parent;
 
     StrongARMState *sa1110;
-} CollieMachineState;
+};
+typedef struct CollieMachineState CollieMachineState;
 
 #define TYPE_COLLIE_MACHINE MACHINE_TYPE_NAME("collie")
-#define COLLIE_MACHINE(obj) \
-    OBJECT_CHECK(CollieMachineState, obj, TYPE_COLLIE_MACHINE)
+DECLARE_INSTANCE_CHECKER(CollieMachineState, COLLIE_MACHINE,
+                         TYPE_COLLIE_MACHINE)
 
 static struct arm_boot_info collie_binfo = {
     .loader_start = SA_SDCS0,
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index c96f2ab9cf..e2ace803ef 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -36,6 +36,7 @@
 #include "hw/cpu/a9mpcore.h"
 #include "hw/cpu/a15mpcore.h"
 #include "qemu/log.h"
+#include "qom/object.h"
 
 #define SMP_BOOT_ADDR           0x100
 #define SMP_BOOT_REG            0x40
@@ -155,17 +156,18 @@ static const MemoryRegionOps hb_mem_ops = {
 };
 
 #define TYPE_HIGHBANK_REGISTERS "highbank-regs"
-#define HIGHBANK_REGISTERS(obj) \
-    OBJECT_CHECK(HighbankRegsState, (obj), TYPE_HIGHBANK_REGISTERS)
+typedef struct HighbankRegsState HighbankRegsState;
+DECLARE_INSTANCE_CHECKER(HighbankRegsState, HIGHBANK_REGISTERS,
+                         TYPE_HIGHBANK_REGISTERS)
 
-typedef struct {
+struct HighbankRegsState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
 
     MemoryRegion iomem;
     uint32_t regs[NUM_REGS];
-} HighbankRegsState;
+};
 
 static VMStateDescription vmstate_highbank_regs = {
     .name = "highbank-regs",
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index fe7c2b9d4b..19989b61b9 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -26,12 +26,14 @@
 #include "hw/hw.h"
 #include "hw/irq.h"
 #include "hw/sd/sd.h"
+#include "qom/object.h"
 
 #define TYPE_INTEGRATOR_CM "integrator_core"
-#define INTEGRATOR_CM(obj) \
-    OBJECT_CHECK(IntegratorCMState, (obj), TYPE_INTEGRATOR_CM)
+typedef struct IntegratorCMState IntegratorCMState;
+DECLARE_INSTANCE_CHECKER(IntegratorCMState, INTEGRATOR_CM,
+                         TYPE_INTEGRATOR_CM)
 
-typedef struct IntegratorCMState {
+struct IntegratorCMState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -51,7 +53,7 @@ typedef struct IntegratorCMState {
     uint32_t int_level;
     uint32_t irq_enabled;
     uint32_t fiq_enabled;
-} IntegratorCMState;
+};
 
 static uint8_t integrator_spd[128] = {
    128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
@@ -326,10 +328,11 @@ static void integratorcm_realize(DeviceState *d, Error **errp)
 /* Primary interrupt controller.  */
 
 #define TYPE_INTEGRATOR_PIC "integrator_pic"
-#define INTEGRATOR_PIC(obj) \
-   OBJECT_CHECK(icp_pic_state, (obj), TYPE_INTEGRATOR_PIC)
+typedef struct icp_pic_state icp_pic_state;
+DECLARE_INSTANCE_CHECKER(icp_pic_state, INTEGRATOR_PIC,
+                         TYPE_INTEGRATOR_PIC)
 
-typedef struct icp_pic_state {
+struct icp_pic_state {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -340,7 +343,7 @@ typedef struct icp_pic_state {
     uint32_t fiq_enabled;
     qemu_irq parent_irq;
     qemu_irq parent_fiq;
-} icp_pic_state;
+};
 
 static const VMStateDescription vmstate_icp_pic = {
     .name = "icp_pic",
@@ -465,10 +468,11 @@ static void icp_pic_init(Object *obj)
 /* CP control registers.  */
 
 #define TYPE_ICP_CONTROL_REGS "icp-ctrl-regs"
-#define ICP_CONTROL_REGS(obj) \
-    OBJECT_CHECK(ICPCtrlRegsState, (obj), TYPE_ICP_CONTROL_REGS)
+typedef struct ICPCtrlRegsState ICPCtrlRegsState;
+DECLARE_INSTANCE_CHECKER(ICPCtrlRegsState, ICP_CONTROL_REGS,
+                         TYPE_ICP_CONTROL_REGS)
 
-typedef struct ICPCtrlRegsState {
+struct ICPCtrlRegsState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -477,7 +481,7 @@ typedef struct ICPCtrlRegsState {
 
     qemu_irq mmc_irq;
     uint32_t intreg_state;
-} ICPCtrlRegsState;
+};
 
 #define ICP_GPIO_MMC_WPROT      "mmc-wprot"
 #define ICP_GPIO_MMC_CARDIN     "mmc-cardin"
diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c
index a91acab1cb..9a4a3d357a 100644
--- a/hw/arm/microbit.c
+++ b/hw/arm/microbit.c
@@ -18,18 +18,20 @@
 #include "hw/arm/nrf51_soc.h"
 #include "hw/i2c/microbit_i2c.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
-typedef struct {
+struct MicrobitMachineState {
     MachineState parent;
 
     NRF51State nrf51;
     MicrobitI2CState i2c;
-} MicrobitMachineState;
+};
+typedef struct MicrobitMachineState MicrobitMachineState;
 
 #define TYPE_MICROBIT_MACHINE MACHINE_TYPE_NAME("microbit")
 
-#define MICROBIT_MACHINE(obj) \
-    OBJECT_CHECK(MicrobitMachineState, obj, TYPE_MICROBIT_MACHINE)
+DECLARE_INSTANCE_CHECKER(MicrobitMachineState, MICROBIT_MACHINE,
+                         TYPE_MICROBIT_MACHINE)
 
 static void microbit_init(MachineState *machine)
 {
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 28d9e8bfac..dbf7d63dc8 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -62,6 +62,7 @@
 #include "hw/net/lan9118.h"
 #include "net/net.h"
 #include "hw/core/split-irq.h"
+#include "qom/object.h"
 
 #define MPS2TZ_NUMIRQ 92
 
@@ -70,14 +71,15 @@ typedef enum MPS2TZFPGAType {
     FPGA_AN521,
 } MPS2TZFPGAType;
 
-typedef struct {
+struct MPS2TZMachineClass {
     MachineClass parent;
     MPS2TZFPGAType fpga_type;
     uint32_t scc_id;
     const char *armsse_type;
-} MPS2TZMachineClass;
+};
+typedef struct MPS2TZMachineClass MPS2TZMachineClass;
 
-typedef struct {
+struct MPS2TZMachineState {
     MachineState parent;
 
     ARMSSE iotkit;
@@ -99,18 +101,15 @@ typedef struct {
     qemu_or_irq uart_irq_orgate;
     DeviceState *lan9118;
     SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
-} MPS2TZMachineState;
+};
+typedef struct MPS2TZMachineState MPS2TZMachineState;
 
 #define TYPE_MPS2TZ_MACHINE "mps2tz"
 #define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
 #define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
 
-#define MPS2TZ_MACHINE(obj) \
-    OBJECT_CHECK(MPS2TZMachineState, obj, TYPE_MPS2TZ_MACHINE)
-#define MPS2TZ_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(MPS2TZMachineClass, obj, TYPE_MPS2TZ_MACHINE)
-#define MPS2TZ_MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(MPS2TZMachineClass, klass, TYPE_MPS2TZ_MACHINE)
+DECLARE_OBJ_CHECKERS(MPS2TZMachineState, MPS2TZMachineClass,
+                     MPS2TZ_MACHINE, TYPE_MPS2TZ_MACHINE)
 
 /* Main SYSCLK frequency in Hz */
 #define SYSCLK_FRQ 20000000
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
index 9f12934ca8..4ee5c38459 100644
--- a/hw/arm/mps2.c
+++ b/hw/arm/mps2.c
@@ -44,19 +44,21 @@
 #include "hw/net/lan9118.h"
 #include "net/net.h"
 #include "hw/watchdog/cmsdk-apb-watchdog.h"
+#include "qom/object.h"
 
 typedef enum MPS2FPGAType {
     FPGA_AN385,
     FPGA_AN511,
 } MPS2FPGAType;
 
-typedef struct {
+struct MPS2MachineClass {
     MachineClass parent;
     MPS2FPGAType fpga_type;
     uint32_t scc_id;
-} MPS2MachineClass;
+};
+typedef struct MPS2MachineClass MPS2MachineClass;
 
-typedef struct {
+struct MPS2MachineState {
     MachineState parent;
 
     ARMv7MState armv7m;
@@ -75,18 +77,15 @@ typedef struct {
     /* CMSDK APB subsystem */
     CMSDKAPBDualTimer dualtimer;
     CMSDKAPBWatchdog watchdog;
-} MPS2MachineState;
+};
+typedef struct MPS2MachineState MPS2MachineState;
 
 #define TYPE_MPS2_MACHINE "mps2"
 #define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385")
 #define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511")
 
-#define MPS2_MACHINE(obj)                                       \
-    OBJECT_CHECK(MPS2MachineState, obj, TYPE_MPS2_MACHINE)
-#define MPS2_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(MPS2MachineClass, obj, TYPE_MPS2_MACHINE)
-#define MPS2_MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(MPS2MachineClass, klass, TYPE_MPS2_MACHINE)
+DECLARE_OBJ_CHECKERS(MPS2MachineState, MPS2MachineClass,
+                     MPS2_MACHINE, TYPE_MPS2_MACHINE)
 
 /* Main SYSCLK frequency in Hz */
 #define SYSCLK_FRQ 25000000
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
index 4bc737f93b..16015255c8 100644
--- a/hw/arm/musca.c
+++ b/hw/arm/musca.c
@@ -33,6 +33,7 @@
 #include "hw/misc/tz-ppc.h"
 #include "hw/misc/unimp.h"
 #include "hw/rtc/pl031.h"
+#include "qom/object.h"
 
 #define MUSCA_NUMIRQ_MAX 96
 #define MUSCA_PPC_MAX 3
@@ -45,7 +46,7 @@ typedef enum MuscaType {
     MUSCA_B1,
 } MuscaType;
 
-typedef struct {
+struct MuscaMachineClass {
     MachineClass parent;
     MuscaType type;
     uint32_t init_svtor;
@@ -53,9 +54,10 @@ typedef struct {
     int num_irqs;
     const MPCInfo *mpc_info;
     int num_mpcs;
-} MuscaMachineClass;
+};
+typedef struct MuscaMachineClass MuscaMachineClass;
 
-typedef struct {
+struct MuscaMachineState {
     MachineState parent;
 
     ARMSSE sse;
@@ -81,18 +83,15 @@ typedef struct {
     UnimplementedDeviceState sdio;
     UnimplementedDeviceState gpio;
     UnimplementedDeviceState cryptoisland;
-} MuscaMachineState;
+};
+typedef struct MuscaMachineState MuscaMachineState;
 
 #define TYPE_MUSCA_MACHINE "musca"
 #define TYPE_MUSCA_A_MACHINE MACHINE_TYPE_NAME("musca-a")
 #define TYPE_MUSCA_B1_MACHINE MACHINE_TYPE_NAME("musca-b1")
 
-#define MUSCA_MACHINE(obj) \
-    OBJECT_CHECK(MuscaMachineState, obj, TYPE_MUSCA_MACHINE)
-#define MUSCA_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(MuscaMachineClass, obj, TYPE_MUSCA_MACHINE)
-#define MUSCA_MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(MuscaMachineClass, klass, TYPE_MUSCA_MACHINE)
+DECLARE_OBJ_CHECKERS(MuscaMachineState, MuscaMachineClass,
+                     MUSCA_MACHINE, TYPE_MUSCA_MACHINE)
 
 /*
  * Main SYSCLK frequency in Hz
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index f2f4fc0264..2117a04171 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -34,6 +34,7 @@
 #include "exec/address-spaces.h"
 #include "ui/pixel_ops.h"
 #include "qemu/cutils.h"
+#include "qom/object.h"
 
 #define MP_MISC_BASE            0x80002000
 #define MP_MISC_SIZE            0x00001000
@@ -154,10 +155,11 @@ typedef struct mv88w8618_rx_desc {
 } mv88w8618_rx_desc;
 
 #define TYPE_MV88W8618_ETH "mv88w8618_eth"
-#define MV88W8618_ETH(obj) \
-    OBJECT_CHECK(mv88w8618_eth_state, (obj), TYPE_MV88W8618_ETH)
+typedef struct mv88w8618_eth_state mv88w8618_eth_state;
+DECLARE_INSTANCE_CHECKER(mv88w8618_eth_state, MV88W8618_ETH,
+                         TYPE_MV88W8618_ETH)
 
-typedef struct mv88w8618_eth_state {
+struct mv88w8618_eth_state {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -177,7 +179,7 @@ typedef struct mv88w8618_eth_state {
     uint32_t cur_rx[4];
     NICState *nic;
     NICConf conf;
-} mv88w8618_eth_state;
+};
 
 static void eth_rx_desc_put(AddressSpace *dma_as, uint32_t addr,
                             mv88w8618_rx_desc *desc)
@@ -483,10 +485,11 @@ static const TypeInfo mv88w8618_eth_info = {
 #define MP_LCD_TEXTCOLOR        0xe0e0ff /* RRGGBB */
 
 #define TYPE_MUSICPAL_LCD "musicpal_lcd"
-#define MUSICPAL_LCD(obj) \
-    OBJECT_CHECK(musicpal_lcd_state, (obj), TYPE_MUSICPAL_LCD)
+typedef struct musicpal_lcd_state musicpal_lcd_state;
+DECLARE_INSTANCE_CHECKER(musicpal_lcd_state, MUSICPAL_LCD,
+                         TYPE_MUSICPAL_LCD)
 
-typedef struct musicpal_lcd_state {
+struct musicpal_lcd_state {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -499,7 +502,7 @@ typedef struct musicpal_lcd_state {
     uint32_t page_off;
     QemuConsole *con;
     uint8_t video_ram[128*64/8];
-} musicpal_lcd_state;
+};
 
 static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
 {
@@ -700,10 +703,11 @@ static const TypeInfo musicpal_lcd_info = {
 #define MP_PIC_ENABLE_CLR       0x0C
 
 #define TYPE_MV88W8618_PIC "mv88w8618_pic"
-#define MV88W8618_PIC(obj) \
-    OBJECT_CHECK(mv88w8618_pic_state, (obj), TYPE_MV88W8618_PIC)
+typedef struct mv88w8618_pic_state mv88w8618_pic_state;
+DECLARE_INSTANCE_CHECKER(mv88w8618_pic_state, MV88W8618_PIC,
+                         TYPE_MV88W8618_PIC)
 
-typedef struct mv88w8618_pic_state {
+struct mv88w8618_pic_state {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -712,7 +716,7 @@ typedef struct mv88w8618_pic_state {
     uint32_t level;
     uint32_t enabled;
     qemu_irq parent_irq;
-} mv88w8618_pic_state;
+};
 
 static void mv88w8618_pic_update(mv88w8618_pic_state *s)
 {
@@ -837,17 +841,18 @@ typedef struct mv88w8618_timer_state {
 } mv88w8618_timer_state;
 
 #define TYPE_MV88W8618_PIT "mv88w8618_pit"
-#define MV88W8618_PIT(obj) \
-    OBJECT_CHECK(mv88w8618_pit_state, (obj), TYPE_MV88W8618_PIT)
+typedef struct mv88w8618_pit_state mv88w8618_pit_state;
+DECLARE_INSTANCE_CHECKER(mv88w8618_pit_state, MV88W8618_PIT,
+                         TYPE_MV88W8618_PIT)
 
-typedef struct mv88w8618_pit_state {
+struct mv88w8618_pit_state {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
 
     MemoryRegion iomem;
     mv88w8618_timer_state timer[4];
-} mv88w8618_pit_state;
+};
 
 static void mv88w8618_timer_tick(void *opaque)
 {
@@ -1004,17 +1009,18 @@ static const TypeInfo mv88w8618_pit_info = {
 #define MP_FLASHCFG_CFGR0    0x04
 
 #define TYPE_MV88W8618_FLASHCFG "mv88w8618_flashcfg"
-#define MV88W8618_FLASHCFG(obj) \
-    OBJECT_CHECK(mv88w8618_flashcfg_state, (obj), TYPE_MV88W8618_FLASHCFG)
+typedef struct mv88w8618_flashcfg_state mv88w8618_flashcfg_state;
+DECLARE_INSTANCE_CHECKER(mv88w8618_flashcfg_state, MV88W8618_FLASHCFG,
+                         TYPE_MV88W8618_FLASHCFG)
 
-typedef struct mv88w8618_flashcfg_state {
+struct mv88w8618_flashcfg_state {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
 
     MemoryRegion iomem;
     uint32_t cfgr0;
-} mv88w8618_flashcfg_state;
+};
 
 static uint64_t mv88w8618_flashcfg_read(void *opaque,
                                         hwaddr offset,
@@ -1090,14 +1096,15 @@ static const TypeInfo mv88w8618_flashcfg_info = {
 
 #define MP_BOARD_REVISION       0x31
 
-typedef struct {
+struct MusicPalMiscState {
     SysBusDevice parent_obj;
     MemoryRegion iomem;
-} MusicPalMiscState;
+};
+typedef struct MusicPalMiscState MusicPalMiscState;
 
 #define TYPE_MUSICPAL_MISC "musicpal-misc"
-#define MUSICPAL_MISC(obj) \
-     OBJECT_CHECK(MusicPalMiscState, (obj), TYPE_MUSICPAL_MISC)
+DECLARE_INSTANCE_CHECKER(MusicPalMiscState, MUSICPAL_MISC,
+                         TYPE_MUSICPAL_MISC)
 
 static uint64_t musicpal_misc_read(void *opaque, hwaddr offset,
                                    unsigned size)
@@ -1202,10 +1209,11 @@ static void mv88w8618_wlan_realize(DeviceState *dev, Error **errp)
 #define MP_OE_LCD_BRIGHTNESS    0x0007
 
 #define TYPE_MUSICPAL_GPIO "musicpal_gpio"
-#define MUSICPAL_GPIO(obj) \
-    OBJECT_CHECK(musicpal_gpio_state, (obj), TYPE_MUSICPAL_GPIO)
+typedef struct musicpal_gpio_state musicpal_gpio_state;
+DECLARE_INSTANCE_CHECKER(musicpal_gpio_state, MUSICPAL_GPIO,
+                         TYPE_MUSICPAL_GPIO)
 
-typedef struct musicpal_gpio_state {
+struct musicpal_gpio_state {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -1219,7 +1227,7 @@ typedef struct musicpal_gpio_state {
     uint32_t isr;
     qemu_irq irq;
     qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
-} musicpal_gpio_state;
+};
 
 static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
     int i;
@@ -1452,10 +1460,11 @@ static const TypeInfo musicpal_gpio_info = {
 #define MP_KEY_BTN_NAVIGATION  (1 << 7)
 
 #define TYPE_MUSICPAL_KEY "musicpal_key"
-#define MUSICPAL_KEY(obj) \
-    OBJECT_CHECK(musicpal_key_state, (obj), TYPE_MUSICPAL_KEY)
+typedef struct musicpal_key_state musicpal_key_state;
+DECLARE_INSTANCE_CHECKER(musicpal_key_state, MUSICPAL_KEY,
+                         TYPE_MUSICPAL_KEY)
 
-typedef struct musicpal_key_state {
+struct musicpal_key_state {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -1464,7 +1473,7 @@ typedef struct musicpal_key_state {
     uint32_t kbd_extended;
     uint32_t pressed_keys;
     qemu_irq out[8];
-} musicpal_key_state;
+};
 
 static void musicpal_key_event(void *opaque, int keycode)
 {
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
index e7bc9ea4c6..abc6495489 100644
--- a/hw/arm/palm.c
+++ b/hw/arm/palm.c
@@ -32,6 +32,7 @@
 #include "exec/address-spaces.h"
 #include "cpu.h"
 #include "qemu/cutils.h"
+#include "qom/object.h"
 
 static uint64_t static_read(void *opaque, hwaddr offset, unsigned size)
 {
@@ -132,12 +133,13 @@ static void palmte_button_event(void *opaque, int keycode)
  */
 
 #define TYPE_PALM_MISC_GPIO "palm-misc-gpio"
-#define PALM_MISC_GPIO(obj) \
-    OBJECT_CHECK(PalmMiscGPIOState, (obj), TYPE_PALM_MISC_GPIO)
+typedef struct PalmMiscGPIOState PalmMiscGPIOState;
+DECLARE_INSTANCE_CHECKER(PalmMiscGPIOState, PALM_MISC_GPIO,
+                         TYPE_PALM_MISC_GPIO)
 
-typedef struct PalmMiscGPIOState {
+struct PalmMiscGPIOState {
     SysBusDevice parent_obj;
-} PalmMiscGPIOState;
+};
 
 static void palmte_onoff_gpios(void *opaque, int line, int level)
 {
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 76975d17a4..33074dbf82 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -28,6 +28,7 @@
 #include "sysemu/qtest.h"
 #include "qemu/cutils.h"
 #include "qemu/log.h"
+#include "qom/object.h"
 
 static struct {
     hwaddr io_base;
@@ -443,7 +444,7 @@ static void pxa2xx_mm_write(void *opaque, hwaddr addr,
             s->mm_regs[addr >> 2] = value;
             break;
         }
-
+        /* fallthrough */
     default:
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
@@ -469,11 +470,12 @@ static const VMStateDescription vmstate_pxa2xx_mm = {
 };
 
 #define TYPE_PXA2XX_SSP "pxa2xx-ssp"
-#define PXA2XX_SSP(obj) \
-    OBJECT_CHECK(PXA2xxSSPState, (obj), TYPE_PXA2XX_SSP)
+typedef struct PXA2xxSSPState PXA2xxSSPState;
+DECLARE_INSTANCE_CHECKER(PXA2xxSSPState, PXA2XX_SSP,
+                         TYPE_PXA2XX_SSP)
 
 /* Synchronous Serial Ports */
-typedef struct {
+struct PXA2xxSSPState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -495,7 +497,7 @@ typedef struct {
     uint32_t rx_fifo[16];
     uint32_t rx_level;
     uint32_t rx_start;
-} PXA2xxSSPState;
+};
 
 static bool pxa2xx_ssp_vmstate_validate(void *opaque, int version_id)
 {
@@ -809,10 +811,11 @@ static void pxa2xx_ssp_init(Object *obj)
 #define PIAR		0x38	/* RTC Periodic Interrupt Alarm register */
 
 #define TYPE_PXA2XX_RTC "pxa2xx_rtc"
-#define PXA2XX_RTC(obj) \
-    OBJECT_CHECK(PXA2xxRTCState, (obj), TYPE_PXA2XX_RTC)
+typedef struct PXA2xxRTCState PXA2xxRTCState;
+DECLARE_INSTANCE_CHECKER(PXA2xxRTCState, PXA2XX_RTC,
+                         TYPE_PXA2XX_RTC)
 
-typedef struct {
+struct PXA2xxRTCState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -843,7 +846,7 @@ typedef struct {
     QEMUTimer *rtc_swal2;
     QEMUTimer *rtc_pi;
     qemu_irq rtc_irq;
-} PXA2xxRTCState;
+};
 
 static inline void pxa2xx_rtc_int_update(PXA2xxRTCState *s)
 {
@@ -1242,14 +1245,15 @@ static const TypeInfo pxa2xx_rtc_sysbus_info = {
 /* I2C Interface */
 
 #define TYPE_PXA2XX_I2C_SLAVE "pxa2xx-i2c-slave"
-#define PXA2XX_I2C_SLAVE(obj) \
-    OBJECT_CHECK(PXA2xxI2CSlaveState, (obj), TYPE_PXA2XX_I2C_SLAVE)
+typedef struct PXA2xxI2CSlaveState PXA2xxI2CSlaveState;
+DECLARE_INSTANCE_CHECKER(PXA2xxI2CSlaveState, PXA2XX_I2C_SLAVE,
+                         TYPE_PXA2XX_I2C_SLAVE)
 
-typedef struct PXA2xxI2CSlaveState {
+struct PXA2xxI2CSlaveState {
     I2CSlave parent_obj;
 
     PXA2xxI2CState *host;
-} PXA2xxI2CSlaveState;
+};
 
 struct PXA2xxI2CState {
     /*< private >*/
diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c
index d6d0d0b08e..16bbe4fb70 100644
--- a/hw/arm/pxa2xx_gpio.c
+++ b/hw/arm/pxa2xx_gpio.c
@@ -17,14 +17,15 @@
 #include "qapi/error.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define PXA2XX_GPIO_BANKS	4
 
 #define TYPE_PXA2XX_GPIO "pxa2xx-gpio"
-#define PXA2XX_GPIO(obj) \
-    OBJECT_CHECK(PXA2xxGPIOInfo, (obj), TYPE_PXA2XX_GPIO)
-
 typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo;
+DECLARE_INSTANCE_CHECKER(PXA2xxGPIOInfo, PXA2XX_GPIO,
+                         TYPE_PXA2XX_GPIO)
+
 struct PXA2xxGPIOInfo {
     /*< private >*/
     SysBusDevice parent_obj;
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
index ceee6aa48d..cb52a9dff3 100644
--- a/hw/arm/pxa2xx_pic.c
+++ b/hw/arm/pxa2xx_pic.c
@@ -16,6 +16,7 @@
 #include "hw/arm/pxa.h"
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 #define ICIP	0x00	/* Interrupt Controller IRQ Pending register */
 #define ICMR	0x04	/* Interrupt Controller Mask register */
@@ -37,10 +38,11 @@
 #define PXA2XX_PIC_SRCS	40
 
 #define TYPE_PXA2XX_PIC "pxa2xx_pic"
-#define PXA2XX_PIC(obj) \
-    OBJECT_CHECK(PXA2xxPICState, (obj), TYPE_PXA2XX_PIC)
+typedef struct PXA2xxPICState PXA2xxPICState;
+DECLARE_INSTANCE_CHECKER(PXA2xxPICState, PXA2XX_PIC,
+                         TYPE_PXA2XX_PIC)
 
-typedef struct {
+struct PXA2xxPICState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -52,7 +54,7 @@ typedef struct {
     uint32_t is_fiq[2];
     uint32_t int_idle;
     uint32_t priority[PXA2XX_PIC_SRCS];
-} PXA2xxPICState;
+};
 
 static void pxa2xx_pic_update(void *opaque)
 {
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index b2d6c9688f..d2f674587d 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -24,6 +24,7 @@
 #include "hw/loader.h"
 #include "hw/arm/boot.h"
 #include "sysemu/sysemu.h"
+#include "qom/object.h"
 
 #define SMPBOOT_ADDR    0x300 /* this should leave enough space for ATAGS */
 #define MVBAR_ADDR      0x400 /* secure vectors */
@@ -35,28 +36,26 @@
 /* Registered machine type (matches RPi Foundation bootloader and U-Boot) */
 #define MACH_TYPE_BCM2708   3138
 
-typedef struct RaspiMachineState {
+struct RaspiMachineState {
     /*< private >*/
     MachineState parent_obj;
     /*< public >*/
     BCM283XState soc;
-} RaspiMachineState;
+};
+typedef struct RaspiMachineState RaspiMachineState;
 
-typedef struct RaspiMachineClass {
+struct RaspiMachineClass {
     /*< private >*/
     MachineClass parent_obj;
     /*< public >*/
     uint32_t board_rev;
-} RaspiMachineClass;
+};
+typedef struct RaspiMachineClass RaspiMachineClass;
 
 #define TYPE_RASPI_MACHINE       MACHINE_TYPE_NAME("raspi-common")
-#define RASPI_MACHINE(obj) \
-    OBJECT_CHECK(RaspiMachineState, (obj), TYPE_RASPI_MACHINE)
+DECLARE_OBJ_CHECKERS(RaspiMachineState, RaspiMachineClass,
+                     RASPI_MACHINE, TYPE_RASPI_MACHINE)
 
-#define RASPI_MACHINE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(RaspiMachineClass, (klass), TYPE_RASPI_MACHINE)
-#define RASPI_MACHINE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(RaspiMachineClass, (obj), TYPE_RASPI_MACHINE)
 
 /*
  * Board revision codes:
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
index 47b5286d46..ac68b4640d 100644
--- a/hw/arm/sbsa-ref.c
+++ b/hw/arm/sbsa-ref.c
@@ -41,6 +41,7 @@
 #include "hw/usb.h"
 #include "hw/char/pl011.h"
 #include "net/net.h"
+#include "qom/object.h"
 
 #define RAMLIMIT_GB 8192
 #define RAMLIMIT_BYTES (RAMLIMIT_GB * GiB)
@@ -84,7 +85,7 @@ typedef struct MemMapEntry {
     hwaddr size;
 } MemMapEntry;
 
-typedef struct {
+struct SBSAMachineState {
     MachineState parent;
     struct arm_boot_info bootinfo;
     int smp_cpus;
@@ -93,11 +94,12 @@ typedef struct {
     int psci_conduit;
     DeviceState *gic;
     PFlashCFI01 *flash[2];
-} SBSAMachineState;
+};
+typedef struct SBSAMachineState SBSAMachineState;
 
 #define TYPE_SBSA_MACHINE   MACHINE_TYPE_NAME("sbsa-ref")
-#define SBSA_MACHINE(obj) \
-    OBJECT_CHECK(SBSAMachineState, (obj), TYPE_SBSA_MACHINE)
+DECLARE_INSTANCE_CHECKER(SBSAMachineState, SBSA_MACHINE,
+                         TYPE_SBSA_MACHINE)
 
 static const MemMapEntry sbsa_ref_memmap[] = {
     /* 512M boot ROM */
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 7ac8254aa6..a7ad667f06 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -34,16 +34,18 @@
 #include "migration/vmstate.h"
 #include "exec/address-spaces.h"
 #include "cpu.h"
+#include "qom/object.h"
 
 enum spitz_model_e { spitz, akita, borzoi, terrier };
 
-typedef struct {
+struct SpitzMachineClass {
     MachineClass parent;
     enum spitz_model_e model;
     int arm_id;
-} SpitzMachineClass;
+};
+typedef struct SpitzMachineClass SpitzMachineClass;
 
-typedef struct {
+struct SpitzMachineState {
     MachineState parent;
     PXA2xxState *mpu;
     DeviceState *mux;
@@ -53,15 +55,12 @@ typedef struct {
     DeviceState *scp0;
     DeviceState *scp1;
     DeviceState *misc_gpio;
-} SpitzMachineState;
+};
+typedef struct SpitzMachineState SpitzMachineState;
 
 #define TYPE_SPITZ_MACHINE "spitz-common"
-#define SPITZ_MACHINE(obj) \
-    OBJECT_CHECK(SpitzMachineState, obj, TYPE_SPITZ_MACHINE)
-#define SPITZ_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(SpitzMachineClass, obj, TYPE_SPITZ_MACHINE)
-#define SPITZ_MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(SpitzMachineClass, klass, TYPE_SPITZ_MACHINE)
+DECLARE_OBJ_CHECKERS(SpitzMachineState, SpitzMachineClass,
+                     SPITZ_MACHINE, TYPE_SPITZ_MACHINE)
 
 #define zaurus_printf(format, ...)                              \
     fprintf(stderr, "%s: " format, __func__, ##__VA_ARGS__)
@@ -85,9 +84,11 @@ typedef struct {
 #define FLASHCTL_NCE            (FLASHCTL_CE0 | FLASHCTL_CE1)
 
 #define TYPE_SL_NAND "sl-nand"
-#define SL_NAND(obj) OBJECT_CHECK(SLNANDState, (obj), TYPE_SL_NAND)
+typedef struct SLNANDState SLNANDState;
+DECLARE_INSTANCE_CHECKER(SLNANDState, SL_NAND,
+                         TYPE_SL_NAND)
 
-typedef struct {
+struct SLNANDState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -96,7 +97,7 @@ typedef struct {
     uint8_t manf_id;
     uint8_t chip_id;
     ECCState ecc;
-} SLNANDState;
+};
 
 static uint64_t sl_read(void *opaque, hwaddr addr, unsigned size)
 {
@@ -261,10 +262,11 @@ static const int spitz_gpiomap[5] = {
 };
 
 #define TYPE_SPITZ_KEYBOARD "spitz-keyboard"
-#define SPITZ_KEYBOARD(obj) \
-    OBJECT_CHECK(SpitzKeyboardState, (obj), TYPE_SPITZ_KEYBOARD)
+typedef struct SpitzKeyboardState SpitzKeyboardState;
+DECLARE_INSTANCE_CHECKER(SpitzKeyboardState, SPITZ_KEYBOARD,
+                         TYPE_SPITZ_KEYBOARD)
 
-typedef struct {
+struct SpitzKeyboardState {
     SysBusDevice parent_obj;
 
     qemu_irq sense[SPITZ_KEY_SENSE_NUM];
@@ -280,7 +282,7 @@ typedef struct {
     uint8_t fifo[16];
     int fifopos, fifolen;
     QEMUTimer *kbdtimer;
-} SpitzKeyboardState;
+};
 
 static void spitz_keyboard_sense_update(SpitzKeyboardState *s)
 {
@@ -580,13 +582,15 @@ static void spitz_keyboard_realize(DeviceState *dev, Error **errp)
 #define LCDTG_POLCTRL   0x07
 
 #define TYPE_SPITZ_LCDTG "spitz-lcdtg"
-#define SPITZ_LCDTG(obj) OBJECT_CHECK(SpitzLCDTG, (obj), TYPE_SPITZ_LCDTG)
+typedef struct SpitzLCDTG SpitzLCDTG;
+DECLARE_INSTANCE_CHECKER(SpitzLCDTG, SPITZ_LCDTG,
+                         TYPE_SPITZ_LCDTG)
 
-typedef struct {
+struct SpitzLCDTG {
     SSISlave ssidev;
     uint32_t bl_intensity;
     uint32_t bl_power;
-} SpitzLCDTG;
+};
 
 static void spitz_bl_update(SpitzLCDTG *s)
 {
@@ -668,14 +672,16 @@ static void spitz_lcdtg_realize(SSISlave *ssi, Error **errp)
 #define SPITZ_GPIO_TP_INT       11
 
 #define TYPE_CORGI_SSP "corgi-ssp"
-#define CORGI_SSP(obj) OBJECT_CHECK(CorgiSSPState, (obj), TYPE_CORGI_SSP)
+typedef struct CorgiSSPState CorgiSSPState;
+DECLARE_INSTANCE_CHECKER(CorgiSSPState, CORGI_SSP,
+                         TYPE_CORGI_SSP)
 
 /* "Demux" the signal based on current chipselect */
-typedef struct {
+struct CorgiSSPState {
     SSISlave ssidev;
     SSIBus *bus[3];
     uint32_t enable[3];
-} CorgiSSPState;
+};
 
 static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value)
 {
@@ -819,14 +825,15 @@ static void spitz_akita_i2c_setup(PXA2xxState *cpu)
  *  + named GPIO output "adc-temp": the ADC value, to be wired up to the max111x
  */
 #define TYPE_SPITZ_MISC_GPIO "spitz-misc-gpio"
-#define SPITZ_MISC_GPIO(obj) \
-    OBJECT_CHECK(SpitzMiscGPIOState, (obj), TYPE_SPITZ_MISC_GPIO)
+typedef struct SpitzMiscGPIOState SpitzMiscGPIOState;
+DECLARE_INSTANCE_CHECKER(SpitzMiscGPIOState, SPITZ_MISC_GPIO,
+                         TYPE_SPITZ_MISC_GPIO)
 
-typedef struct SpitzMiscGPIOState {
+struct SpitzMiscGPIOState {
     SysBusDevice parent_obj;
 
     qemu_irq adc_value;
-} SpitzMiscGPIOState;
+};
 
 static void spitz_misc_charging(void *opaque, int n, int level)
 {
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index 5f9d080180..d6fc4a4681 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -27,6 +27,7 @@
 #include "migration/vmstate.h"
 #include "hw/misc/unimp.h"
 #include "cpu.h"
+#include "qom/object.h"
 
 #define GPIO_A 0
 #define GPIO_B 1
@@ -57,10 +58,11 @@ typedef const struct {
 /* General purpose timer module.  */
 
 #define TYPE_STELLARIS_GPTM "stellaris-gptm"
-#define STELLARIS_GPTM(obj) \
-    OBJECT_CHECK(gptm_state, (obj), TYPE_STELLARIS_GPTM)
+typedef struct gptm_state gptm_state;
+DECLARE_INSTANCE_CHECKER(gptm_state, STELLARIS_GPTM,
+                         TYPE_STELLARIS_GPTM)
 
-typedef struct gptm_state {
+struct gptm_state {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -80,7 +82,7 @@ typedef struct gptm_state {
     /* The timers have an alternate output used to trigger the ADC.  */
     qemu_irq trigger;
     qemu_irq irq;
-} gptm_state;
+};
 
 static void gptm_update_irq(gptm_state *s)
 {
@@ -719,10 +721,11 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
 /* I2C controller.  */
 
 #define TYPE_STELLARIS_I2C "stellaris-i2c"
-#define STELLARIS_I2C(obj) \
-    OBJECT_CHECK(stellaris_i2c_state, (obj), TYPE_STELLARIS_I2C)
+typedef struct stellaris_i2c_state stellaris_i2c_state;
+DECLARE_INSTANCE_CHECKER(stellaris_i2c_state, STELLARIS_I2C,
+                         TYPE_STELLARIS_I2C)
 
-typedef struct {
+struct stellaris_i2c_state {
     SysBusDevice parent_obj;
 
     I2CBus *bus;
@@ -735,7 +738,7 @@ typedef struct {
     uint32_t mimr;
     uint32_t mris;
     uint32_t mcr;
-} stellaris_i2c_state;
+};
 
 #define STELLARIS_I2C_MCS_BUSY    0x01
 #define STELLARIS_I2C_MCS_ERROR   0x02
@@ -932,10 +935,11 @@ static void stellaris_i2c_init(Object *obj)
 #define STELLARIS_ADC_FIFO_FULL     0x1000
 
 #define TYPE_STELLARIS_ADC "stellaris-adc"
-#define STELLARIS_ADC(obj) \
-    OBJECT_CHECK(stellaris_adc_state, (obj), TYPE_STELLARIS_ADC)
+typedef struct StellarisADCState stellaris_adc_state;
+DECLARE_INSTANCE_CHECKER(stellaris_adc_state, STELLARIS_ADC,
+                         TYPE_STELLARIS_ADC)
 
-typedef struct StellarisADCState {
+struct StellarisADCState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -955,7 +959,7 @@ typedef struct StellarisADCState {
     uint32_t ssctl[4];
     uint32_t noise;
     qemu_irq irq[4];
-} stellaris_adc_state;
+};
 
 static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
 {
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index 2639b9ae55..0fe829b868 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -45,6 +45,7 @@
 #include "qapi/error.h"
 #include "qemu/cutils.h"
 #include "qemu/log.h"
+#include "qom/object.h"
 
 //#define DEBUG
 
@@ -84,10 +85,11 @@ static struct {
 /* Interrupt Controller */
 
 #define TYPE_STRONGARM_PIC "strongarm_pic"
-#define STRONGARM_PIC(obj) \
-    OBJECT_CHECK(StrongARMPICState, (obj), TYPE_STRONGARM_PIC)
+typedef struct StrongARMPICState StrongARMPICState;
+DECLARE_INSTANCE_CHECKER(StrongARMPICState, STRONGARM_PIC,
+                         TYPE_STRONGARM_PIC)
 
-typedef struct StrongARMPICState {
+struct StrongARMPICState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -98,7 +100,7 @@ typedef struct StrongARMPICState {
     uint32_t enabled;
     uint32_t is_fiq;
     uint32_t int_idle;
-} StrongARMPICState;
+};
 
 #define ICIP    0x00
 #define ICMR    0x04
@@ -252,10 +254,11 @@ static const TypeInfo strongarm_pic_info = {
  * f = 32 768 / (RTTR_trim + 1) */
 
 #define TYPE_STRONGARM_RTC "strongarm-rtc"
-#define STRONGARM_RTC(obj) \
-    OBJECT_CHECK(StrongARMRTCState, (obj), TYPE_STRONGARM_RTC)
+typedef struct StrongARMRTCState StrongARMRTCState;
+DECLARE_INSTANCE_CHECKER(StrongARMRTCState, STRONGARM_RTC,
+                         TYPE_STRONGARM_RTC)
 
-typedef struct StrongARMRTCState {
+struct StrongARMRTCState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -268,7 +271,7 @@ typedef struct StrongARMRTCState {
     QEMUTimer *rtc_hz;
     qemu_irq rtc_irq;
     qemu_irq rtc_hz_irq;
-} StrongARMRTCState;
+};
 
 static inline void strongarm_rtc_int_update(StrongARMRTCState *s)
 {
@@ -478,10 +481,10 @@ static const TypeInfo strongarm_rtc_sysbus_info = {
 #define GAFR 0x1c
 
 #define TYPE_STRONGARM_GPIO "strongarm-gpio"
-#define STRONGARM_GPIO(obj) \
-    OBJECT_CHECK(StrongARMGPIOInfo, (obj), TYPE_STRONGARM_GPIO)
-
 typedef struct StrongARMGPIOInfo StrongARMGPIOInfo;
+DECLARE_INSTANCE_CHECKER(StrongARMGPIOInfo, STRONGARM_GPIO,
+                         TYPE_STRONGARM_GPIO)
+
 struct StrongARMGPIOInfo {
     SysBusDevice busdev;
     MemoryRegion iomem;
@@ -717,10 +720,10 @@ static const TypeInfo strongarm_gpio_info = {
 #define PPFR 0x10
 
 #define TYPE_STRONGARM_PPC "strongarm-ppc"
-#define STRONGARM_PPC(obj) \
-    OBJECT_CHECK(StrongARMPPCInfo, (obj), TYPE_STRONGARM_PPC)
-
 typedef struct StrongARMPPCInfo StrongARMPPCInfo;
+DECLARE_INSTANCE_CHECKER(StrongARMPPCInfo, STRONGARM_PPC,
+                         TYPE_STRONGARM_PPC)
+
 struct StrongARMPPCInfo {
     SysBusDevice parent_obj;
 
@@ -918,10 +921,11 @@ static const TypeInfo strongarm_ppc_info = {
 #define RX_FIFO_ROR (1 << 10)
 
 #define TYPE_STRONGARM_UART "strongarm-uart"
-#define STRONGARM_UART(obj) \
-    OBJECT_CHECK(StrongARMUARTState, (obj), TYPE_STRONGARM_UART)
+typedef struct StrongARMUARTState StrongARMUARTState;
+DECLARE_INSTANCE_CHECKER(StrongARMUARTState, STRONGARM_UART,
+                         TYPE_STRONGARM_UART)
 
-typedef struct StrongARMUARTState {
+struct StrongARMUARTState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -945,7 +949,7 @@ typedef struct StrongARMUARTState {
     bool wait_break_end;
     QEMUTimer *rx_timeout_timer;
     QEMUTimer *tx_timer;
-} StrongARMUARTState;
+};
 
 static void strongarm_uart_update_status(StrongARMUARTState *s)
 {
@@ -1349,10 +1353,11 @@ static const TypeInfo strongarm_uart_info = {
 /* Synchronous Serial Ports */
 
 #define TYPE_STRONGARM_SSP "strongarm-ssp"
-#define STRONGARM_SSP(obj) \
-    OBJECT_CHECK(StrongARMSSPState, (obj), TYPE_STRONGARM_SSP)
+typedef struct StrongARMSSPState StrongARMSSPState;
+DECLARE_INSTANCE_CHECKER(StrongARMSSPState, STRONGARM_SSP,
+                         TYPE_STRONGARM_SSP)
 
-typedef struct StrongARMSSPState {
+struct StrongARMSSPState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -1365,7 +1370,7 @@ typedef struct StrongARMSSPState {
     uint16_t rx_fifo[8];
     uint8_t rx_level;
     uint8_t rx_start;
-} StrongARMSSPState;
+};
 
 #define SSCR0 0x60 /* SSP Control register 0 */
 #define SSCR1 0x64 /* SSP Control register 1 */
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
index 90eef1f14d..2ef6c7b288 100644
--- a/hw/arm/tosa.c
+++ b/hw/arm/tosa.c
@@ -25,6 +25,7 @@
 #include "hw/ssi/ssi.h"
 #include "hw/sysbus.h"
 #include "exec/address-spaces.h"
+#include "qom/object.h"
 
 #define TOSA_RAM 0x04000000
 #define TOSA_ROM 0x00800000
@@ -74,12 +75,13 @@ static void tosa_microdrive_attach(PXA2xxState *cpu)
  */
 
 #define TYPE_TOSA_MISC_GPIO "tosa-misc-gpio"
-#define TOSA_MISC_GPIO(obj) \
-    OBJECT_CHECK(TosaMiscGPIOState, (obj), TYPE_TOSA_MISC_GPIO)
+typedef struct TosaMiscGPIOState TosaMiscGPIOState;
+DECLARE_INSTANCE_CHECKER(TosaMiscGPIOState, TOSA_MISC_GPIO,
+                         TYPE_TOSA_MISC_GPIO)
 
-typedef struct TosaMiscGPIOState {
+struct TosaMiscGPIOState {
     SysBusDevice parent_obj;
-} TosaMiscGPIOState;
+};
 
 static void tosa_gpio_leds(void *opaque, int line, int level)
 {
@@ -170,14 +172,16 @@ static void tosa_ssp_realize(SSISlave *dev, Error **errp)
 }
 
 #define TYPE_TOSA_DAC "tosa_dac"
-#define TOSA_DAC(obj) OBJECT_CHECK(TosaDACState, (obj), TYPE_TOSA_DAC)
+typedef struct TosaDACState TosaDACState;
+DECLARE_INSTANCE_CHECKER(TosaDACState, TOSA_DAC,
+                         TYPE_TOSA_DAC)
 
-typedef struct {
+struct TosaDACState {
     I2CSlave parent_obj;
 
     int len;
     char buf[3];
-} TosaDACState;
+};
 
 static int tosa_dac_send(I2CSlave *i2c, uint8_t data)
 {
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index 9127579984..2ba69f24b7 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -26,6 +26,7 @@
 #include "qemu/error-report.h"
 #include "hw/char/pl011.h"
 #include "hw/sd/sd.h"
+#include "qom/object.h"
 
 #define VERSATILE_FLASH_ADDR 0x34000000
 #define VERSATILE_FLASH_SIZE (64 * 1024 * 1024)
@@ -34,10 +35,11 @@
 /* Primary interrupt controller.  */
 
 #define TYPE_VERSATILE_PB_SIC "versatilepb_sic"
-#define VERSATILE_PB_SIC(obj) \
-    OBJECT_CHECK(vpb_sic_state, (obj), TYPE_VERSATILE_PB_SIC)
+typedef struct vpb_sic_state vpb_sic_state;
+DECLARE_INSTANCE_CHECKER(vpb_sic_state, VERSATILE_PB_SIC,
+                         TYPE_VERSATILE_PB_SIC)
 
-typedef struct vpb_sic_state {
+struct vpb_sic_state {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -46,7 +48,7 @@ typedef struct vpb_sic_state {
     uint32_t pic_enable;
     qemu_irq parent[32];
     int irq;
-} vpb_sic_state;
+};
 
 static const VMStateDescription vmstate_vpb_sic = {
     .name = "versatilepb_sic",
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 95405f5940..01bb4bba1e 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -44,6 +44,7 @@
 #include "hw/cpu/a15mpcore.h"
 #include "hw/i2c/arm_sbcon_i2c.h"
 #include "hw/sd/sd.h"
+#include "qom/object.h"
 
 #define VEXPRESS_BOARD_ID 0x8e0
 #define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
@@ -166,26 +167,24 @@ static hwaddr motherboard_aseries_map[] = {
 
 typedef struct VEDBoardInfo VEDBoardInfo;
 
-typedef struct {
+struct VexpressMachineClass {
     MachineClass parent;
     VEDBoardInfo *daughterboard;
-} VexpressMachineClass;
+};
+typedef struct VexpressMachineClass VexpressMachineClass;
 
-typedef struct {
+struct VexpressMachineState {
     MachineState parent;
     bool secure;
     bool virt;
-} VexpressMachineState;
+};
+typedef struct VexpressMachineState VexpressMachineState;
 
 #define TYPE_VEXPRESS_MACHINE   "vexpress"
 #define TYPE_VEXPRESS_A9_MACHINE   MACHINE_TYPE_NAME("vexpress-a9")
 #define TYPE_VEXPRESS_A15_MACHINE   MACHINE_TYPE_NAME("vexpress-a15")
-#define VEXPRESS_MACHINE(obj) \
-    OBJECT_CHECK(VexpressMachineState, (obj), TYPE_VEXPRESS_MACHINE)
-#define VEXPRESS_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(VexpressMachineClass, obj, TYPE_VEXPRESS_MACHINE)
-#define VEXPRESS_MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(VexpressMachineClass, klass, TYPE_VEXPRESS_MACHINE)
+DECLARE_OBJ_CHECKERS(VexpressMachineState, VexpressMachineClass,
+                     VEXPRESS_MACHINE, TYPE_VEXPRESS_MACHINE)
 
 typedef void DBoardInitFn(const VexpressMachineState *machine,
                           ram_addr_t ram_size,
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 9ffcc5606f..f45e71e89b 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -37,10 +37,12 @@
 #include "hw/cpu/a9mpcore.h"
 #include "hw/qdev-clock.h"
 #include "sysemu/reset.h"
+#include "qom/object.h"
 
 #define TYPE_ZYNQ_MACHINE MACHINE_TYPE_NAME("xilinx-zynq-a9")
-#define ZYNQ_MACHINE(obj) \
-    OBJECT_CHECK(ZynqMachineState, (obj), TYPE_ZYNQ_MACHINE)
+typedef struct ZynqMachineState ZynqMachineState;
+DECLARE_INSTANCE_CHECKER(ZynqMachineState, ZYNQ_MACHINE,
+                         TYPE_ZYNQ_MACHINE)
 
 /* board base frequency: 33.333333 MHz */
 #define PS_CLK_FREQUENCY (100 * 1000 * 1000 / 3)
@@ -84,10 +86,10 @@ static const int dma_irqs[8] = {
     0xe3401000 + ARMV7_IMM16(extract32((val), 16, 16)), /* movt r1 ... */ \
     0xe5801000 + (addr)
 
-typedef struct ZynqMachineState {
+struct ZynqMachineState {
     MachineState parent;
     Clock *ps_clk;
-} ZynqMachineState;
+};
 
 static void zynq_write_board_setup(ARMCPU *cpu,
                                    const struct arm_boot_info *info)
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 4b3152ee77..5a01e856fd 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -22,12 +22,14 @@
 #include "cpu.h"
 #include "hw/qdev-properties.h"
 #include "hw/arm/xlnx-versal.h"
+#include "qom/object.h"
 
 #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt")
-#define XLNX_VERSAL_VIRT_MACHINE(obj) \
-    OBJECT_CHECK(VersalVirt, (obj), TYPE_XLNX_VERSAL_VIRT_MACHINE)
+typedef struct VersalVirt VersalVirt;
+DECLARE_INSTANCE_CHECKER(VersalVirt, XLNX_VERSAL_VIRT_MACHINE,
+                         TYPE_XLNX_VERSAL_VIRT_MACHINE)
 
-typedef struct VersalVirt {
+struct VersalVirt {
     MachineState parent_obj;
 
     Versal soc;
@@ -45,7 +47,7 @@ typedef struct VersalVirt {
     struct {
         bool secure;
     } cfg;
-} VersalVirt;
+};
 
 static void fdt_create(VersalVirt *s)
 {
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
index 672d9d4bd1..19d5a4d4e0 100644
--- a/hw/arm/xlnx-zcu102.c
+++ b/hw/arm/xlnx-zcu102.c
@@ -24,8 +24,9 @@
 #include "qemu/log.h"
 #include "sysemu/qtest.h"
 #include "sysemu/device_tree.h"
+#include "qom/object.h"
 
-typedef struct XlnxZCU102 {
+struct XlnxZCU102 {
     MachineState parent_obj;
 
     XlnxZynqMPState soc;
@@ -34,11 +35,12 @@ typedef struct XlnxZCU102 {
     bool virt;
 
     struct arm_boot_info binfo;
-} XlnxZCU102;
+};
+typedef struct XlnxZCU102 XlnxZCU102;
 
 #define TYPE_ZCU102_MACHINE   MACHINE_TYPE_NAME("xlnx-zcu102")
-#define ZCU102_MACHINE(obj) \
-    OBJECT_CHECK(XlnxZCU102, (obj), TYPE_ZCU102_MACHINE)
+DECLARE_INSTANCE_CHECKER(XlnxZCU102, ZCU102_MACHINE,
+                         TYPE_ZCU102_MACHINE)
 
 
 static bool zcu102_get_secure(Object *obj, Error **errp)
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index 9a9bbc653b..72ecb6df29 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -26,6 +26,7 @@
 #include "exec/address-spaces.h"
 #include "sysemu/qtest.h"
 #include "cpu.h"
+#include "qom/object.h"
 
 #ifdef DEBUG_Z2
 #define DPRINTF(fmt, ...) \
@@ -102,17 +103,19 @@ static struct arm_boot_info z2_binfo = {
 #define Z2_GPIO_KEY_ON      1
 #define Z2_GPIO_LCD_CS      88
 
-typedef struct {
+struct ZipitLCD {
     SSISlave ssidev;
     int32_t selected;
     int32_t enabled;
     uint8_t buf[3];
     uint32_t cur_reg;
     int pos;
-} ZipitLCD;
+};
+typedef struct ZipitLCD ZipitLCD;
 
 #define TYPE_ZIPIT_LCD "zipit-lcd"
-#define ZIPIT_LCD(obj) OBJECT_CHECK(ZipitLCD, (obj), TYPE_ZIPIT_LCD)
+DECLARE_INSTANCE_CHECKER(ZipitLCD, ZIPIT_LCD,
+                         TYPE_ZIPIT_LCD)
 
 static uint32_t zipit_lcd_transfer(SSISlave *dev, uint32_t value)
 {
@@ -195,14 +198,16 @@ static const TypeInfo zipit_lcd_info = {
 };
 
 #define TYPE_AER915 "aer915"
-#define AER915(obj) OBJECT_CHECK(AER915State, (obj), TYPE_AER915)
+typedef struct AER915State AER915State;
+DECLARE_INSTANCE_CHECKER(AER915State, AER915,
+                         TYPE_AER915)
 
-typedef struct AER915State {
+struct AER915State {
     I2CSlave parent_obj;
 
     int len;
     uint8_t buf[3];
-} AER915State;
+};
 
 static int aer915_send(I2CSlave *i2c, uint8_t data)
 {
diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c
index 38522cf0ba..eb8a7f032d 100644
--- a/hw/audio/ac97.c
+++ b/hw/audio/ac97.c
@@ -25,6 +25,7 @@
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "sysemu/dma.h"
+#include "qom/object.h"
 
 enum {
     AC97_Reset                     = 0x00,
@@ -126,8 +127,9 @@ enum {
 #define MUTE_SHIFT 15
 
 #define TYPE_AC97 "AC97"
-#define AC97(obj) \
-    OBJECT_CHECK(AC97LinkState, (obj), TYPE_AC97)
+typedef struct AC97LinkState AC97LinkState;
+DECLARE_INSTANCE_CHECKER(AC97LinkState, AC97,
+                         TYPE_AC97)
 
 #define REC_MASK 7
 enum {
@@ -158,7 +160,7 @@ typedef struct AC97BusMasterRegs {
     BD bd;
 } AC97BusMasterRegs;
 
-typedef struct AC97LinkState {
+struct AC97LinkState {
     PCIDevice dev;
     QEMUSoundCard card;
     uint32_t glob_cnt;
@@ -175,7 +177,7 @@ typedef struct AC97LinkState {
     int bup_flag;
     MemoryRegion io_nam;
     MemoryRegion io_nabm;
-} AC97LinkState;
+};
 
 enum {
     BUP_SET = 1,
diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c
index 65dff5b6fc..870116e324 100644
--- a/hw/audio/adlib.c
+++ b/hw/audio/adlib.c
@@ -29,6 +29,7 @@
 #include "audio/audio.h"
 #include "hw/isa/isa.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 //#define DEBUG
 
@@ -51,9 +52,11 @@
 #define SHIFT 1
 
 #define TYPE_ADLIB "adlib"
-#define ADLIB(obj) OBJECT_CHECK(AdlibState, (obj), TYPE_ADLIB)
+typedef struct AdlibState AdlibState;
+DECLARE_INSTANCE_CHECKER(AdlibState, ADLIB,
+                         TYPE_ADLIB)
 
-typedef struct {
+struct AdlibState {
     ISADevice parent_obj;
 
     QEMUSoundCard card;
@@ -73,7 +76,7 @@ typedef struct {
     QEMUAudioTimeStamp ats;
     FM_OPL *opl;
     PortioList port_list;
-} AdlibState;
+};
 
 static void adlib_stop_opl_timer (AdlibState *s, size_t n)
 {
diff --git a/hw/audio/cs4231.c b/hw/audio/cs4231.c
index 11a6328fc2..8e9554ce9b 100644
--- a/hw/audio/cs4231.c
+++ b/hw/audio/cs4231.c
@@ -27,6 +27,7 @@
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "trace.h"
+#include "qom/object.h"
 
 /*
  * In addition to Crystal CS4231 there is a DMA controller on Sparc.
@@ -37,17 +38,18 @@
 #define CS_MAXDREG (CS_DREGS - 1)
 
 #define TYPE_CS4231 "SUNW,CS4231"
-#define CS4231(obj) \
-    OBJECT_CHECK(CSState, (obj), TYPE_CS4231)
+typedef struct CSState CSState;
+DECLARE_INSTANCE_CHECKER(CSState, CS4231,
+                         TYPE_CS4231)
 
-typedef struct CSState {
+struct CSState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
     qemu_irq irq;
     uint32_t regs[CS_REGS];
     uint8_t dregs[CS_DREGS];
-} CSState;
+};
 
 #define CS_RAP(s) ((s)->regs[0] & CS_MAXDREG)
 #define CS_VER 0xa0
diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c
index 59705a8d47..7d60ce6f0e 100644
--- a/hw/audio/cs4231a.c
+++ b/hw/audio/cs4231a.c
@@ -32,6 +32,7 @@
 #include "qemu/module.h"
 #include "qemu/timer.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 /*
   Missing features:
@@ -62,9 +63,11 @@ static struct {
 #define CS_DREGS 32
 
 #define TYPE_CS4231A "cs4231a"
-#define CS4231A(obj) OBJECT_CHECK (CSState, (obj), TYPE_CS4231A)
+typedef struct CSState CSState;
+DECLARE_INSTANCE_CHECKER(CSState, CS4231A,
+                         TYPE_CS4231A)
 
-typedef struct CSState {
+struct CSState {
     ISADevice dev;
     QEMUSoundCard card;
     MemoryRegion ioports;
@@ -82,7 +85,7 @@ typedef struct CSState {
     int aci_counter;
     SWVoiceOut *voice;
     int16_t *tab;
-} CSState;
+};
 
 #define MODE2 (1 << 6)
 #define MCE (1 << 6)
diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c
index 4255463a49..a824f8949e 100644
--- a/hw/audio/es1370.c
+++ b/hw/audio/es1370.c
@@ -33,6 +33,7 @@
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "sysemu/dma.h"
+#include "qom/object.h"
 
 /* Missing stuff:
    SCTRL_P[12](END|ST)INC
@@ -263,7 +264,7 @@ struct chan {
     uint32_t frame_cnt;
 };
 
-typedef struct ES1370State {
+struct ES1370State {
     PCIDevice dev;
     QEMUSoundCard card;
     MemoryRegion io;
@@ -276,7 +277,8 @@ typedef struct ES1370State {
     uint32_t mempage;
     uint32_t codec;
     uint32_t sctl;
-} ES1370State;
+};
+typedef struct ES1370State ES1370State;
 
 struct chan_bits {
     uint32_t ctl_en;
@@ -291,8 +293,8 @@ struct chan_bits {
 };
 
 #define TYPE_ES1370 "ES1370"
-#define ES1370(obj) \
-    OBJECT_CHECK(ES1370State, (obj), TYPE_ES1370)
+DECLARE_INSTANCE_CHECKER(ES1370State, ES1370,
+                         TYPE_ES1370)
 
 static void es1370_dac1_calc_freq (ES1370State *s, uint32_t ctl,
                                    uint32_t *old_freq, uint32_t *new_freq);
diff --git a/hw/audio/gus.c b/hw/audio/gus.c
index 7e4a8cadad..307fd48315 100644
--- a/hw/audio/gus.c
+++ b/hw/audio/gus.c
@@ -33,6 +33,7 @@
 #include "migration/vmstate.h"
 #include "gusemu.h"
 #include "gustate.h"
+#include "qom/object.h"
 
 #define dolog(...) AUD_log ("audio", __VA_ARGS__)
 #ifdef DEBUG
@@ -42,9 +43,11 @@
 #endif
 
 #define TYPE_GUS "gus"
-#define GUS(obj) OBJECT_CHECK (GUSState, (obj), TYPE_GUS)
+typedef struct GUSState GUSState;
+DECLARE_INSTANCE_CHECKER(GUSState, GUS,
+                         TYPE_GUS)
 
-typedef struct GUSState {
+struct GUSState {
     ISADevice dev;
     GUSEmuState emu;
     QEMUSoundCard card;
@@ -60,7 +63,7 @@ typedef struct GUSState {
     IsaDma *isa_dma;
     PortioList portio_list1;
     PortioList portio_list2;
-} GUSState;
+};
 
 static uint32_t gus_readb(void *opaque, uint32_t nport)
 {
diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c
index 2d16448181..77d31b91a4 100644
--- a/hw/audio/hda-codec.c
+++ b/hw/audio/hda-codec.c
@@ -26,6 +26,7 @@
 #include "intel-hda-defs.h"
 #include "audio/audio.h"
 #include "trace.h"
+#include "qom/object.h"
 
 /* -------------------------------------------------------------------------- */
 
@@ -171,7 +172,8 @@ struct HDAAudioStream {
 };
 
 #define TYPE_HDA_AUDIO "hda-audio"
-#define HDA_AUDIO(obj) OBJECT_CHECK(HDAAudioState, (obj), TYPE_HDA_AUDIO)
+DECLARE_INSTANCE_CHECKER(HDAAudioState, HDA_AUDIO,
+                         TYPE_HDA_AUDIO)
 
 struct HDAAudioState {
     HDACodecDevice hda;
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index f6cea49686..4330213fff 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -32,6 +32,7 @@
 #include "intel-hda-defs.h"
 #include "sysemu/dma.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 /* --------------------------------------------------------------------- */
 /* hda bus                                                               */
@@ -203,8 +204,8 @@ struct IntelHDAState {
 
 #define TYPE_INTEL_HDA_GENERIC "intel-hda-generic"
 
-#define INTEL_HDA(obj) \
-    OBJECT_CHECK(IntelHDAState, (obj), TYPE_INTEL_HDA_GENERIC)
+DECLARE_INSTANCE_CHECKER(IntelHDAState, INTEL_HDA,
+                         TYPE_INTEL_HDA_GENERIC)
 
 struct IntelHDAReg {
     const char *name;      /* register name */
diff --git a/hw/audio/intel-hda.h b/hw/audio/intel-hda.h
index eee6fee5af..f5cce18fa3 100644
--- a/hw/audio/intel-hda.h
+++ b/hw/audio/intel-hda.h
@@ -2,23 +2,20 @@
 #define HW_INTEL_HDA_H
 
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 /* --------------------------------------------------------------------- */
 /* hda bus                                                               */
 
 #define TYPE_HDA_CODEC_DEVICE "hda-codec"
-#define HDA_CODEC_DEVICE(obj) \
-     OBJECT_CHECK(HDACodecDevice, (obj), TYPE_HDA_CODEC_DEVICE)
-#define HDA_CODEC_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(HDACodecDeviceClass, (klass), TYPE_HDA_CODEC_DEVICE)
-#define HDA_CODEC_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(HDACodecDeviceClass, (obj), TYPE_HDA_CODEC_DEVICE)
+OBJECT_DECLARE_TYPE(HDACodecDevice, HDACodecDeviceClass,
+                    hda_codec_device, HDA_CODEC_DEVICE)
 
 #define TYPE_HDA_BUS "HDA"
-#define HDA_BUS(obj) OBJECT_CHECK(HDACodecBus, (obj), TYPE_HDA_BUS)
-
 typedef struct HDACodecBus HDACodecBus;
-typedef struct HDACodecDevice HDACodecDevice;
+DECLARE_INSTANCE_CHECKER(HDACodecBus, HDA_BUS,
+                         TYPE_HDA_BUS)
+
 
 typedef void (*hda_codec_response_func)(HDACodecDevice *dev,
                                         bool solicited, uint32_t response);
@@ -33,15 +30,14 @@ struct HDACodecBus {
     hda_codec_xfer_func xfer;
 };
 
-typedef struct HDACodecDeviceClass
-{
+struct HDACodecDeviceClass {
     DeviceClass parent_class;
 
     int (*init)(HDACodecDevice *dev);
     void (*exit)(HDACodecDevice *dev);
     void (*command)(HDACodecDevice *dev, uint32_t nid, uint32_t data);
     void (*stream)(HDACodecDevice *dev, uint32_t stnr, bool running, bool output);
-} HDACodecDeviceClass;
+};
 
 struct HDACodecDevice {
     DeviceState         qdev;
diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c
index 8dfacec693..c8641562cc 100644
--- a/hw/audio/marvell_88w8618.c
+++ b/hw/audio/marvell_88w8618.c
@@ -19,6 +19,7 @@
 #include "audio/audio.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define MP_AUDIO_SIZE           0x00001000
 
@@ -42,10 +43,11 @@
 #define MP_AUDIO_CLOCK_24MHZ    (1 << 9)
 #define MP_AUDIO_MONO           (1 << 14)
 
-#define MV88W8618_AUDIO(obj) \
-    OBJECT_CHECK(mv88w8618_audio_state, (obj), TYPE_MV88W8618_AUDIO)
+typedef struct mv88w8618_audio_state mv88w8618_audio_state;
+DECLARE_INSTANCE_CHECKER(mv88w8618_audio_state, MV88W8618_AUDIO,
+                         TYPE_MV88W8618_AUDIO)
 
-typedef struct mv88w8618_audio_state {
+struct mv88w8618_audio_state {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -60,7 +62,7 @@ typedef struct mv88w8618_audio_state {
     uint32_t last_free;
     uint32_t clock_div;
     void *wm;
-} mv88w8618_audio_state;
+};
 
 static void mv88w8618_audio_callback(void *opaque, int free_out, int free_in)
 {
diff --git a/hw/audio/milkymist-ac97.c b/hw/audio/milkymist-ac97.c
index 0fa38adbe2..7893539019 100644
--- a/hw/audio/milkymist-ac97.c
+++ b/hw/audio/milkymist-ac97.c
@@ -29,6 +29,7 @@
 #include "audio/audio.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 enum {
     R_AC97_CTRL = 0,
@@ -55,8 +56,9 @@ enum {
 };
 
 #define TYPE_MILKYMIST_AC97 "milkymist-ac97"
-#define MILKYMIST_AC97(obj) \
-    OBJECT_CHECK(MilkymistAC97State, (obj), TYPE_MILKYMIST_AC97)
+typedef struct MilkymistAC97State MilkymistAC97State;
+DECLARE_INSTANCE_CHECKER(MilkymistAC97State, MILKYMIST_AC97,
+                         TYPE_MILKYMIST_AC97)
 
 struct MilkymistAC97State {
     SysBusDevice parent_obj;
@@ -74,7 +76,6 @@ struct MilkymistAC97State {
     qemu_irq dmar_irq;
     qemu_irq dmaw_irq;
 };
-typedef struct MilkymistAC97State MilkymistAC97State;
 
 static void update_voices(MilkymistAC97State *s)
 {
diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
index ea539e7605..cbee8855fb 100644
--- a/hw/audio/pcspk.c
+++ b/hw/audio/pcspk.c
@@ -33,15 +33,18 @@
 #include "migration/vmstate.h"
 #include "hw/audio/pcspk.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 #define PCSPK_BUF_LEN 1792
 #define PCSPK_SAMPLE_RATE 32000
 #define PCSPK_MAX_FREQ (PCSPK_SAMPLE_RATE >> 1)
 #define PCSPK_MIN_COUNT DIV_ROUND_UP(PIT_FREQ, PCSPK_MAX_FREQ)
 
-#define PC_SPEAKER(obj) OBJECT_CHECK(PCSpkState, (obj), TYPE_PC_SPEAKER)
+typedef struct PCSpkState PCSpkState;
+DECLARE_INSTANCE_CHECKER(PCSpkState, PC_SPEAKER,
+                         TYPE_PC_SPEAKER)
 
-typedef struct {
+struct PCSpkState {
     ISADevice parent_obj;
 
     MemoryRegion ioport;
@@ -56,7 +59,7 @@ typedef struct {
     uint8_t data_on;
     uint8_t dummy_refresh_clock;
     bool migrate;
-} PCSpkState;
+};
 
 static const char *s_spk = "pcspk";
 static PCSpkState *pcspk_state;
diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c
index c3d3eab6ed..570a234b72 100644
--- a/hw/audio/pl041.c
+++ b/hw/audio/pl041.c
@@ -30,6 +30,7 @@
 #include "pl041.h"
 #include "lm4549.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 #if 0
 #define PL041_DEBUG_LEVEL 1
@@ -77,9 +78,11 @@ typedef struct {
 } pl041_channel;
 
 #define TYPE_PL041 "pl041"
-#define PL041(obj) OBJECT_CHECK(PL041State, (obj), TYPE_PL041)
+typedef struct PL041State PL041State;
+DECLARE_INSTANCE_CHECKER(PL041State, PL041,
+                         TYPE_PL041)
 
-typedef struct PL041State {
+struct PL041State {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -90,7 +93,7 @@ typedef struct PL041State {
     pl041_regfile regs;
     pl041_channel fifo1;
     lm4549_state codec;
-} PL041State;
+};
 
 
 static const unsigned char pl041_default_id[8] = {
diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c
index 2d9e50f99b..6aa2c0fb93 100644
--- a/hw/audio/sb16.c
+++ b/hw/audio/sb16.c
@@ -34,6 +34,7 @@
 #include "qemu/log.h"
 #include "qemu/module.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 #define dolog(...) AUD_log ("sb16", __VA_ARGS__)
 
@@ -49,9 +50,11 @@
 static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
 
 #define TYPE_SB16 "sb16"
-#define SB16(obj) OBJECT_CHECK (SB16State, (obj), TYPE_SB16)
+typedef struct SB16State SB16State;
+DECLARE_INSTANCE_CHECKER(SB16State, SB16,
+                         TYPE_SB16)
 
-typedef struct SB16State {
+struct SB16State {
     ISADevice parent_obj;
 
     QEMUSoundCard card;
@@ -112,7 +115,7 @@ typedef struct SB16State {
     int mixer_nreg;
     uint8_t mixer_regs[256];
     PortioList portio_list;
-} SB16State;
+};
 
 static void SB_audio_callback (void *opaque, int free);
 
diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c
index 92b2902a10..7d6fcfec03 100644
--- a/hw/audio/wm8750.c
+++ b/hw/audio/wm8750.c
@@ -13,6 +13,7 @@
 #include "qemu/module.h"
 #include "hw/audio/wm8750.h"
 #include "audio/audio.h"
+#include "qom/object.h"
 
 #define IN_PORT_N	3
 #define OUT_PORT_N	3
@@ -26,9 +27,11 @@ typedef struct {
     int dac_hz;
 } WMRate;
 
-#define WM8750(obj) OBJECT_CHECK(WM8750State, (obj), TYPE_WM8750)
+typedef struct WM8750State WM8750State;
+DECLARE_INSTANCE_CHECKER(WM8750State, WM8750,
+                         TYPE_WM8750)
 
-typedef struct WM8750State {
+struct WM8750State {
     I2CSlave parent_obj;
 
     uint8_t i2c_data[2];
@@ -54,7 +57,7 @@ typedef struct WM8750State {
     const WMRate *rate;
     uint8_t rate_vmstate;
     int adc_hz, dac_hz, ext_adc_hz, ext_dac_hz, master;
-} WM8750State;
+};
 
 /* pow(10.0, -i / 20.0) * 255, i = 0..42 */
 static const uint8_t wm8750_vol_db_table[] = {
diff --git a/hw/avr/arduino.c b/hw/avr/arduino.c
index 65093ab6fd..3c8388490d 100644
--- a/hw/avr/arduino.c
+++ b/hw/avr/arduino.c
@@ -15,30 +15,29 @@
 #include "hw/boards.h"
 #include "atmega.h"
 #include "boot.h"
+#include "qom/object.h"
 
-typedef struct ArduinoMachineState {
+struct ArduinoMachineState {
     /*< private >*/
     MachineState parent_obj;
     /*< public >*/
     AtmegaMcuState mcu;
-} ArduinoMachineState;
+};
+typedef struct ArduinoMachineState ArduinoMachineState;
 
-typedef struct ArduinoMachineClass {
+struct ArduinoMachineClass {
     /*< private >*/
     MachineClass parent_class;
     /*< public >*/
     const char *mcu_type;
     uint64_t xtal_hz;
-} ArduinoMachineClass;
+};
+typedef struct ArduinoMachineClass ArduinoMachineClass;
 
 #define TYPE_ARDUINO_MACHINE \
         MACHINE_TYPE_NAME("arduino")
-#define ARDUINO_MACHINE(obj) \
-        OBJECT_CHECK(ArduinoMachineState, (obj), TYPE_ARDUINO_MACHINE)
-#define ARDUINO_MACHINE_CLASS(klass) \
-        OBJECT_CLASS_CHECK(ArduinoMachineClass, (klass), TYPE_ARDUINO_MACHINE)
-#define ARDUINO_MACHINE_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(ArduinoMachineClass, (obj), TYPE_ARDUINO_MACHINE)
+DECLARE_OBJ_CHECKERS(ArduinoMachineState, ArduinoMachineClass,
+                     ARDUINO_MACHINE, TYPE_ARDUINO_MACHINE)
 
 static void arduino_machine_init(MachineState *machine)
 {
diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
index 7131224431..44c6afebbb 100644
--- a/hw/avr/atmega.c
+++ b/hw/avr/atmega.c
@@ -17,6 +17,7 @@
 #include "sysemu/sysemu.h"
 #include "hw/qdev-properties.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 #include "hw/boards.h" /* FIXME memory_region_allocate_system_memory for sram */
 #include "hw/misc/unimp.h"
 #include "atmega.h"
@@ -45,7 +46,7 @@ typedef struct {
     bool is_timer16;
 } peripheral_cfg;
 
-typedef struct AtmegaMcuClass {
+struct AtmegaMcuClass {
     /*< private >*/
     SysBusDeviceClass parent_class;
     /*< public >*/
@@ -59,12 +60,11 @@ typedef struct AtmegaMcuClass {
     size_t adc_count;
     const uint8_t *irq;
     const peripheral_cfg *dev;
-} AtmegaMcuClass;
+};
+typedef struct AtmegaMcuClass AtmegaMcuClass;
 
-#define ATMEGA_MCU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(AtmegaMcuClass, (klass), TYPE_ATMEGA_MCU)
-#define ATMEGA_MCU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(AtmegaMcuClass, (obj), TYPE_ATMEGA_MCU)
+DECLARE_CLASS_CHECKERS(AtmegaMcuClass, ATMEGA_MCU,
+                       TYPE_ATMEGA_MCU)
 
 static const peripheral_cfg dev168_328[PERIFMAX] = {
     [USART0]        = {  0xc0, POWER0, 1 },
diff --git a/hw/avr/atmega.h b/hw/avr/atmega.h
index 0928cb0ce6..a99ee15c7e 100644
--- a/hw/avr/atmega.h
+++ b/hw/avr/atmega.h
@@ -15,6 +15,7 @@
 #include "hw/timer/avr_timer16.h"
 #include "hw/misc/avr_power.h"
 #include "target/avr/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_ATMEGA_MCU     "ATmega"
 #define TYPE_ATMEGA168_MCU  "ATmega168"
@@ -22,14 +23,16 @@
 #define TYPE_ATMEGA1280_MCU "ATmega1280"
 #define TYPE_ATMEGA2560_MCU "ATmega2560"
 
-#define ATMEGA_MCU(obj) OBJECT_CHECK(AtmegaMcuState, (obj), TYPE_ATMEGA_MCU)
+typedef struct AtmegaMcuState AtmegaMcuState;
+DECLARE_INSTANCE_CHECKER(AtmegaMcuState, ATMEGA_MCU,
+                         TYPE_ATMEGA_MCU)
 
 #define POWER_MAX 2
 #define USART_MAX 4
 #define TIMER_MAX 6
 #define GPIO_MAX 12
 
-typedef struct AtmegaMcuState {
+struct AtmegaMcuState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -43,6 +46,6 @@ typedef struct AtmegaMcuState {
     AVRUsartState usart[USART_MAX];
     AVRTimer16State timer[TIMER_MAX];
     uint64_t xtal_freq_hz;
-} AtmegaMcuState;
+};
 
 #endif /* HW_AVR_ATMEGA_H */
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index e9ed3eef45..224bac504f 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -46,6 +46,7 @@
 #include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "trace.h"
+#include "qom/object.h"
 
 /********************************************************/
 /* debug Floppy devices */
@@ -64,16 +65,18 @@
 /* qdev floppy bus                                      */
 
 #define TYPE_FLOPPY_BUS "floppy-bus"
-#define FLOPPY_BUS(obj) OBJECT_CHECK(FloppyBus, (obj), TYPE_FLOPPY_BUS)
+typedef struct FloppyBus FloppyBus;
+DECLARE_INSTANCE_CHECKER(FloppyBus, FLOPPY_BUS,
+                         TYPE_FLOPPY_BUS)
 
 typedef struct FDCtrl FDCtrl;
 typedef struct FDrive FDrive;
 static FDrive *get_drv(FDCtrl *fdctrl, int unit);
 
-typedef struct FloppyBus {
+struct FloppyBus {
     BusState bus;
     FDCtrl *fdc;
-} FloppyBus;
+};
 
 static const TypeInfo floppy_bus_info = {
     .name = TYPE_FLOPPY_BUS,
@@ -494,15 +497,16 @@ static const BlockDevOps fd_block_ops = {
 
 
 #define TYPE_FLOPPY_DRIVE "floppy"
-#define FLOPPY_DRIVE(obj) \
-     OBJECT_CHECK(FloppyDrive, (obj), TYPE_FLOPPY_DRIVE)
+typedef struct FloppyDrive FloppyDrive;
+DECLARE_INSTANCE_CHECKER(FloppyDrive, FLOPPY_DRIVE,
+                         TYPE_FLOPPY_DRIVE)
 
-typedef struct FloppyDrive {
+struct FloppyDrive {
     DeviceState     qdev;
     uint32_t        unit;
     BlockConf       conf;
     FloppyDriveType type;
-} FloppyDrive;
+};
 
 static Property floppy_drive_properties[] = {
     DEFINE_PROP_UINT32("unit", FloppyDrive, unit, -1),
@@ -886,19 +890,23 @@ static FloppyDriveType get_fallback_drive_type(FDrive *drv)
 }
 
 #define TYPE_SYSBUS_FDC "base-sysbus-fdc"
-#define SYSBUS_FDC(obj) OBJECT_CHECK(FDCtrlSysBus, (obj), TYPE_SYSBUS_FDC)
+typedef struct FDCtrlSysBus FDCtrlSysBus;
+DECLARE_INSTANCE_CHECKER(FDCtrlSysBus, SYSBUS_FDC,
+                         TYPE_SYSBUS_FDC)
 
-typedef struct FDCtrlSysBus {
+struct FDCtrlSysBus {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
 
     struct FDCtrl state;
-} FDCtrlSysBus;
+};
 
-#define ISA_FDC(obj) OBJECT_CHECK(FDCtrlISABus, (obj), TYPE_ISA_FDC)
+typedef struct FDCtrlISABus FDCtrlISABus;
+DECLARE_INSTANCE_CHECKER(FDCtrlISABus, ISA_FDC,
+                         TYPE_ISA_FDC)
 
-typedef struct FDCtrlISABus {
+struct FDCtrlISABus {
     ISADevice parent_obj;
 
     uint32_t iobase;
@@ -907,7 +915,7 @@ typedef struct FDCtrlISABus {
     struct FDCtrl state;
     int32_t bootindexA;
     int32_t bootindexB;
-} FDCtrlISABus;
+};
 
 static uint32_t fdctrl_read (void *opaque, uint32_t reg)
 {
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 15824450cd..8dae779c76 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -33,6 +33,7 @@
 #include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "trace.h"
+#include "qom/object.h"
 
 /* Fields for FlashPartInfo->flags */
 
@@ -414,7 +415,7 @@ typedef enum {
 
 #define M25P80_INTERNAL_DATA_BUFFER_SZ 16
 
-typedef struct Flash {
+struct Flash {
     SSISlave parent_obj;
 
     BlockBackend *blk;
@@ -454,20 +455,18 @@ typedef struct Flash {
 
     const FlashPartInfo *pi;
 
-} Flash;
+};
+typedef struct Flash Flash;
 
-typedef struct M25P80Class {
+struct M25P80Class {
     SSISlaveClass parent_class;
     FlashPartInfo *pi;
-} M25P80Class;
+};
+typedef struct M25P80Class M25P80Class;
 
 #define TYPE_M25P80 "m25p80-generic"
-#define M25P80(obj) \
-     OBJECT_CHECK(Flash, (obj), TYPE_M25P80)
-#define M25P80_CLASS(klass) \
-     OBJECT_CLASS_CHECK(M25P80Class, (klass), TYPE_M25P80)
-#define M25P80_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(M25P80Class, (obj), TYPE_M25P80)
+DECLARE_OBJ_CHECKERS(Flash, M25P80Class,
+                     M25P80, TYPE_M25P80)
 
 static inline Manufacturer get_man(Flash *s)
 {
diff --git a/hw/block/nand.c b/hw/block/nand.c
index 654e0cb5d1..5c8112ed5a 100644
--- a/hw/block/nand.c
+++ b/hw/block/nand.c
@@ -27,6 +27,7 @@
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 # define NAND_CMD_READ0		0x00
 # define NAND_CMD_READ1		0x01
@@ -89,8 +90,8 @@ struct NANDFlashState {
 
 #define TYPE_NAND "nand"
 
-#define NAND(obj) \
-    OBJECT_CHECK(NANDFlashState, (obj), TYPE_NAND)
+DECLARE_INSTANCE_CHECKER(NANDFlashState, NAND,
+                         TYPE_NAND)
 
 static void mem_and(uint8_t *dest, const uint8_t *src, size_t n)
 {
diff --git a/hw/block/onenand.c b/hw/block/onenand.c
index 898ac563a3..19f55aba66 100644
--- a/hw/block/onenand.c
+++ b/hw/block/onenand.c
@@ -31,6 +31,7 @@
 #include "qemu/error-report.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 /* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
 #define PAGE_SHIFT	11
@@ -39,9 +40,11 @@
 #define BLOCK_SHIFT	(PAGE_SHIFT + 6)
 
 #define TYPE_ONE_NAND "onenand"
-#define ONE_NAND(obj) OBJECT_CHECK(OneNANDState, (obj), TYPE_ONE_NAND)
+typedef struct OneNANDState OneNANDState;
+DECLARE_INSTANCE_CHECKER(OneNANDState, ONE_NAND,
+                         TYPE_ONE_NAND)
 
-typedef struct OneNANDState {
+struct OneNANDState {
     SysBusDevice parent_obj;
 
     struct {
@@ -85,7 +88,7 @@ typedef struct OneNANDState {
     int secs_cur;
     int blocks;
     uint8_t *blockwp;
-} OneNANDState;
+};
 
 enum {
     ONEN_BUF_BLOCK = 0,
diff --git a/hw/block/trace-events b/hw/block/trace-events
index 72cf2d15cb..ec94c56a41 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -4,8 +4,8 @@
 fdc_ioport_read(uint8_t reg, uint8_t value) "read reg 0x%02x val 0x%02x"
 fdc_ioport_write(uint8_t reg, uint8_t value) "write reg 0x%02x val 0x%02x"
 
-# pflash_cfi02.c
 # pflash_cfi01.c
+# pflash_cfi02.c
 pflash_reset(void) "reset"
 pflash_timer_expired(uint8_t cmd) "command 0x%02x done"
 pflash_io_read(uint64_t offset, unsigned size, uint32_t value, uint8_t cmd, uint8_t wcycle) "offset:0x%04"PRIx64" size:%u value:0x%04x cmd:0x%02x wcycle:%u"
diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c
index c8d938efb5..daaaca0f39 100644
--- a/hw/char/debugcon.c
+++ b/hw/char/debugcon.c
@@ -30,10 +30,12 @@
 #include "chardev/char-fe.h"
 #include "hw/isa/isa.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 #define TYPE_ISA_DEBUGCON_DEVICE "isa-debugcon"
-#define ISA_DEBUGCON_DEVICE(obj) \
-     OBJECT_CHECK(ISADebugconState, (obj), TYPE_ISA_DEBUGCON_DEVICE)
+typedef struct ISADebugconState ISADebugconState;
+DECLARE_INSTANCE_CHECKER(ISADebugconState, ISA_DEBUGCON_DEVICE,
+                         TYPE_ISA_DEBUGCON_DEVICE)
 
 //#define DEBUG_DEBUGCON
 
@@ -43,12 +45,12 @@ typedef struct DebugconState {
     uint32_t readback;
 } DebugconState;
 
-typedef struct ISADebugconState {
+struct ISADebugconState {
     ISADevice parent_obj;
 
     uint32_t iobase;
     DebugconState state;
-} ISADebugconState;
+};
 
 static void debugcon_ioport_write(void *opaque, hwaddr addr, uint64_t val,
                                   unsigned width)
diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c
index 947bdb649a..d9fba2ae6c 100644
--- a/hw/char/etraxfs_ser.c
+++ b/hw/char/etraxfs_ser.c
@@ -29,6 +29,7 @@
 #include "chardev/char-fe.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define D(x)
 
@@ -49,10 +50,11 @@
 #define STAT_TR_RDY  24
 
 #define TYPE_ETRAX_FS_SERIAL "etraxfs,serial"
-#define ETRAX_SERIAL(obj) \
-    OBJECT_CHECK(ETRAXSerial, (obj), TYPE_ETRAX_FS_SERIAL)
+typedef struct ETRAXSerial ETRAXSerial;
+DECLARE_INSTANCE_CHECKER(ETRAXSerial, ETRAX_SERIAL,
+                         TYPE_ETRAX_FS_SERIAL)
 
-typedef struct ETRAXSerial {
+struct ETRAXSerial {
     SysBusDevice parent_obj;
 
     MemoryRegion mmio;
@@ -67,7 +69,7 @@ typedef struct ETRAXSerial {
 
     /* Control registers.  */
     uint32_t regs[R_MAX];
-} ETRAXSerial;
+};
 
 static void ser_update_irq(ETRAXSerial *s)
 {
diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
index 9c8ab3a77d..b8ea34edbd 100644
--- a/hw/char/exynos4210_uart.c
+++ b/hw/char/exynos4210_uart.c
@@ -34,6 +34,7 @@
 #include "hw/qdev-properties.h"
 
 #include "trace.h"
+#include "qom/object.h"
 
 /*
  *  Offsets for UART registers relative to SFR base address
@@ -138,10 +139,11 @@ typedef struct {
 } Exynos4210UartFIFO;
 
 #define TYPE_EXYNOS4210_UART "exynos4210.uart"
-#define EXYNOS4210_UART(obj) \
-    OBJECT_CHECK(Exynos4210UartState, (obj), TYPE_EXYNOS4210_UART)
+typedef struct Exynos4210UartState Exynos4210UartState;
+DECLARE_INSTANCE_CHECKER(Exynos4210UartState, EXYNOS4210_UART,
+                         TYPE_EXYNOS4210_UART)
 
-typedef struct Exynos4210UartState {
+struct Exynos4210UartState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -159,7 +161,7 @@ typedef struct Exynos4210UartState {
 
     uint32_t channel;
 
-} Exynos4210UartState;
+};
 
 
 /* Used only for tracing */
diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c
index 16d0feac59..6fd88d83ad 100644
--- a/hw/char/grlib_apbuart.c
+++ b/hw/char/grlib_apbuart.c
@@ -31,6 +31,7 @@
 #include "chardev/char-fe.h"
 
 #include "trace.h"
+#include "qom/object.h"
 
 #define UART_REG_SIZE 20     /* Size of memory mapped registers */
 
@@ -72,10 +73,11 @@
 
 #define FIFO_LENGTH 1024
 
-#define GRLIB_APB_UART(obj) \
-    OBJECT_CHECK(UART, (obj), TYPE_GRLIB_APB_UART)
+typedef struct UART UART;
+DECLARE_INSTANCE_CHECKER(UART, GRLIB_APB_UART,
+                         TYPE_GRLIB_APB_UART)
 
-typedef struct UART {
+struct UART {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -91,7 +93,7 @@ typedef struct UART {
     char buffer[FIFO_LENGTH];
     int  len;
     int  current;
-} UART;
+};
 
 static int uart_data_to_read(UART *uart)
 {
diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c
index d7c497b939..2c987df8ad 100644
--- a/hw/char/ipoctal232.c
+++ b/hw/char/ipoctal232.c
@@ -16,6 +16,7 @@
 #include "qemu/bitops.h"
 #include "qemu/module.h"
 #include "chardev/char-fe.h"
+#include "qom/object.h"
 
 /* #define DEBUG_IPOCTAL */
 
@@ -122,8 +123,8 @@ struct IPOctalState {
 
 #define TYPE_IPOCTAL "ipoctal232"
 
-#define IPOCTAL(obj) \
-    OBJECT_CHECK(IPOctalState, (obj), TYPE_IPOCTAL)
+DECLARE_INSTANCE_CHECKER(IPOctalState, IPOCTAL,
+                         TYPE_IPOCTAL)
 
 static const VMStateDescription vmstate_scc2698_channel = {
     .name = "scc2698_channel",
diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c
index 3f34861233..5723f2e189 100644
--- a/hw/char/lm32_juart.c
+++ b/hw/char/lm32_juart.c
@@ -26,6 +26,7 @@
 
 #include "hw/char/lm32_juart.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 enum {
     LM32_JUART_MIN_SAVE_VERSION = 0,
@@ -41,7 +42,9 @@ enum {
     JRX_FULL = (1<<8),
 };
 
-#define LM32_JUART(obj) OBJECT_CHECK(LM32JuartState, (obj), TYPE_LM32_JUART)
+typedef struct LM32JuartState LM32JuartState;
+DECLARE_INSTANCE_CHECKER(LM32JuartState, LM32_JUART,
+                         TYPE_LM32_JUART)
 
 struct LM32JuartState {
     SysBusDevice parent_obj;
@@ -51,7 +54,6 @@ struct LM32JuartState {
     uint32_t jtx;
     uint32_t jrx;
 };
-typedef struct LM32JuartState LM32JuartState;
 
 uint32_t lm32_juart_get_jtx(DeviceState *d)
 {
diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c
index b0b1092889..624bc83c5f 100644
--- a/hw/char/lm32_uart.c
+++ b/hw/char/lm32_uart.c
@@ -31,6 +31,7 @@
 #include "chardev/char-fe.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 enum {
     R_RXTX = 0,
@@ -94,7 +95,9 @@ enum {
 };
 
 #define TYPE_LM32_UART "lm32-uart"
-#define LM32_UART(obj) OBJECT_CHECK(LM32UartState, (obj), TYPE_LM32_UART)
+typedef struct LM32UartState LM32UartState;
+DECLARE_INSTANCE_CHECKER(LM32UartState, LM32_UART,
+                         TYPE_LM32_UART)
 
 struct LM32UartState {
     SysBusDevice parent_obj;
@@ -105,7 +108,6 @@ struct LM32UartState {
 
     uint32_t regs[R_MAX];
 };
-typedef struct LM32UartState LM32UartState;
 
 static void uart_update_irq(LM32UartState *s)
 {
diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c
index 8d1b7f2bca..f6baa3ce77 100644
--- a/hw/char/mcf_uart.c
+++ b/hw/char/mcf_uart.c
@@ -14,8 +14,9 @@
 #include "hw/m68k/mcf.h"
 #include "hw/qdev-properties.h"
 #include "chardev/char-fe.h"
+#include "qom/object.h"
 
-typedef struct {
+struct mcf_uart_state {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -33,10 +34,12 @@ typedef struct {
     int rx_enabled;
     qemu_irq irq;
     CharBackend chr;
-} mcf_uart_state;
+};
+typedef struct mcf_uart_state mcf_uart_state;
 
 #define TYPE_MCF_UART "mcf-uart"
-#define MCF_UART(obj) OBJECT_CHECK(mcf_uart_state, (obj), TYPE_MCF_UART)
+DECLARE_INSTANCE_CHECKER(mcf_uart_state, MCF_UART,
+                         TYPE_MCF_UART)
 
 /* UART Status Register bits.  */
 #define MCF_UART_RxRDY  0x01
diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c
index 1439efb42a..41204a0e28 100644
--- a/hw/char/milkymist-uart.c
+++ b/hw/char/milkymist-uart.c
@@ -30,6 +30,7 @@
 #include "chardev/char-fe.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 enum {
     R_RXTX = 0,
@@ -57,8 +58,9 @@ enum {
 };
 
 #define TYPE_MILKYMIST_UART "milkymist-uart"
-#define MILKYMIST_UART(obj) \
-    OBJECT_CHECK(MilkymistUartState, (obj), TYPE_MILKYMIST_UART)
+typedef struct MilkymistUartState MilkymistUartState;
+DECLARE_INSTANCE_CHECKER(MilkymistUartState, MILKYMIST_UART,
+                         TYPE_MILKYMIST_UART)
 
 struct MilkymistUartState {
     SysBusDevice parent_obj;
@@ -69,7 +71,6 @@ struct MilkymistUartState {
 
     uint32_t regs[R_MAX];
 };
-typedef struct MilkymistUartState MilkymistUartState;
 
 static void uart_update_irq(MilkymistUartState *s)
 {
diff --git a/hw/char/parallel.c b/hw/char/parallel.c
index c0f34bf924..ddb14f3197 100644
--- a/hw/char/parallel.c
+++ b/hw/char/parallel.c
@@ -37,6 +37,7 @@
 #include "sysemu/reset.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
+#include "qom/object.h"
 
 //#define DEBUG_PARALLEL
 
@@ -92,17 +93,18 @@ typedef struct ParallelState {
 } ParallelState;
 
 #define TYPE_ISA_PARALLEL "isa-parallel"
-#define ISA_PARALLEL(obj) \
-    OBJECT_CHECK(ISAParallelState, (obj), TYPE_ISA_PARALLEL)
+typedef struct ISAParallelState ISAParallelState;
+DECLARE_INSTANCE_CHECKER(ISAParallelState, ISA_PARALLEL,
+                         TYPE_ISA_PARALLEL)
 
-typedef struct ISAParallelState {
+struct ISAParallelState {
     ISADevice parent_obj;
 
     uint32_t index;
     uint32_t iobase;
     uint32_t isairq;
     ParallelState state;
-} ISAParallelState;
+};
 
 static void parallel_update_irq(ParallelState *s)
 {
diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index 5848b4e9c5..81f6d0ed4f 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -24,6 +24,7 @@
 #include "hw/s390x/event-facility.h"
 #include "hw/qdev-properties.h"
 #include "hw/s390x/ebcdic.h"
+#include "qom/object.h"
 
 #define SIZE_BUFFER 4096
 #define NEWLINE     "\n"
@@ -37,18 +38,19 @@ typedef struct OprtnsCommand {
 /* max size for line-mode data in 4K SCCB page */
 #define SIZE_CONSOLE_BUFFER (SCCB_DATA_LEN - sizeof(OprtnsCommand))
 
-typedef struct SCLPConsoleLM {
+struct SCLPConsoleLM {
     SCLPEvent event;
     CharBackend chr;
     bool echo;                  /* immediate echo of input if true        */
     uint32_t write_errors;      /* errors writing to char layer           */
     uint32_t length;            /* length of byte stream in buffer        */
     uint8_t buf[SIZE_CONSOLE_BUFFER];
-} SCLPConsoleLM;
+};
+typedef struct SCLPConsoleLM SCLPConsoleLM;
 
 #define TYPE_SCLPLM_CONSOLE "sclplmconsole"
-#define SCLPLM_CONSOLE(obj) \
-    OBJECT_CHECK(SCLPConsoleLM, (obj), TYPE_SCLPLM_CONSOLE)
+DECLARE_INSTANCE_CHECKER(SCLPConsoleLM, SCLPLM_CONSOLE,
+                         TYPE_SCLPLM_CONSOLE)
 
 /*
 *  Character layer call-back functions
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index d6f7da0818..aa72ab40b9 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -22,6 +22,7 @@
 #include "hw/qdev-properties.h"
 #include "hw/s390x/event-facility.h"
 #include "chardev/char-fe.h"
+#include "qom/object.h"
 
 typedef struct ASCIIConsoleData {
     EventBufferHeader ebh;
@@ -31,7 +32,7 @@ typedef struct ASCIIConsoleData {
 /* max size for ASCII data in 4K SCCB page */
 #define SIZE_BUFFER_VT220 4080
 
-typedef struct SCLPConsole {
+struct SCLPConsole {
     SCLPEvent event;
     CharBackend chr;
     uint8_t iov[SIZE_BUFFER_VT220];
@@ -40,11 +41,12 @@ typedef struct SCLPConsole {
     uint32_t iov_data_len;  /* length of byte stream in buffer             */
     uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP     */
     bool notify;            /* qemu_notify_event() req'd if true           */
-} SCLPConsole;
+};
+typedef struct SCLPConsole SCLPConsole;
 
 #define TYPE_SCLP_CONSOLE "sclpconsole"
-#define SCLP_CONSOLE(obj) \
-    OBJECT_CHECK(SCLPConsole, (obj), TYPE_SCLP_CONSOLE)
+DECLARE_INSTANCE_CHECKER(SCLPConsole, SCLP_CONSOLE,
+                         TYPE_SCLP_CONSOLE)
 
 /* character layer call-back functions */
 
diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c
index b4c65949cd..d4aad81a85 100644
--- a/hw/char/serial-isa.c
+++ b/hw/char/serial-isa.c
@@ -32,17 +32,20 @@
 #include "hw/isa/isa.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
-#define ISA_SERIAL(obj) OBJECT_CHECK(ISASerialState, (obj), TYPE_ISA_SERIAL)
+typedef struct ISASerialState ISASerialState;
+DECLARE_INSTANCE_CHECKER(ISASerialState, ISA_SERIAL,
+                         TYPE_ISA_SERIAL)
 
-typedef struct ISASerialState {
+struct ISASerialState {
     ISADevice parent_obj;
 
     uint32_t index;
     uint32_t iobase;
     uint32_t isairq;
     SerialState state;
-} ISASerialState;
+};
 
 static const int isa_serial_io[MAX_ISA_SERIAL_PORTS] = {
     0x3f8, 0x2f8, 0x3e8, 0x2e8
diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c
index cd56924a43..f68948154e 100644
--- a/hw/char/serial-pci.c
+++ b/hw/char/serial-pci.c
@@ -33,15 +33,18 @@
 #include "hw/pci/pci.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
-typedef struct PCISerialState {
+struct PCISerialState {
     PCIDevice dev;
     SerialState state;
     uint8_t prog_if;
-} PCISerialState;
+};
+typedef struct PCISerialState PCISerialState;
 
 #define TYPE_PCI_SERIAL "pci-serial"
-#define PCI_SERIAL(s) OBJECT_CHECK(PCISerialState, (s), TYPE_PCI_SERIAL)
+DECLARE_INSTANCE_CHECKER(PCISerialState, PCI_SERIAL,
+                         TYPE_PCI_SERIAL)
 
 static void serial_pci_realize(PCIDevice *dev, Error **errp)
 {
diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
index 464a52342a..dd6dd2d8c3 100644
--- a/hw/char/spapr_vty.c
+++ b/hw/char/spapr_vty.c
@@ -8,19 +8,21 @@
 #include "hw/ppc/spapr.h"
 #include "hw/ppc/spapr_vio.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 #define VTERM_BUFSIZE   16
 
-typedef struct SpaprVioVty {
+struct SpaprVioVty {
     SpaprVioDevice sdev;
     CharBackend chardev;
     uint32_t in, out;
     uint8_t buf[VTERM_BUFSIZE];
-} SpaprVioVty;
+};
+typedef struct SpaprVioVty SpaprVioVty;
 
 #define TYPE_VIO_SPAPR_VTY_DEVICE "spapr-vty"
-#define VIO_SPAPR_VTY_DEVICE(obj) \
-     OBJECT_CHECK(SpaprVioVty, (obj), TYPE_VIO_SPAPR_VTY_DEVICE)
+DECLARE_INSTANCE_CHECKER(SpaprVioVty, VIO_SPAPR_VTY_DEVICE,
+                         TYPE_VIO_SPAPR_VTY_DEVICE)
 
 static int vty_can_receive(void *opaque)
 {
diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c
index 2c47ebf007..d77981bb6d 100644
--- a/hw/char/terminal3270.c
+++ b/hw/char/terminal3270.c
@@ -17,6 +17,7 @@
 #include "chardev/char-fe.h"
 #include "hw/qdev-properties.h"
 #include "hw/s390x/3270-ccw.h"
+#include "qom/object.h"
 
 /* Enough spaces for different window sizes. */
 #define INPUT_BUFFER_SIZE  1000
@@ -26,7 +27,7 @@
  */
 #define OUTPUT_BUFFER_SIZE 2051
 
-typedef struct Terminal3270 {
+struct Terminal3270 {
     EmulatedCcw3270Device cdev;
     CharBackend chr;
     uint8_t inv[INPUT_BUFFER_SIZE];
@@ -34,11 +35,12 @@ typedef struct Terminal3270 {
     int in_len;
     bool handshake_done;
     guint timer_tag;
-} Terminal3270;
+};
+typedef struct Terminal3270 Terminal3270;
 
 #define TYPE_TERMINAL_3270 "x-terminal3270"
-#define TERMINAL_3270(obj) \
-        OBJECT_CHECK(Terminal3270, (obj), TYPE_TERMINAL_3270)
+DECLARE_INSTANCE_CHECKER(Terminal3270, TERMINAL_3270,
+                         TYPE_TERMINAL_3270)
 
 static int terminal_can_read(void *opaque)
 {
diff --git a/hw/char/trace-events b/hw/char/trace-events
index d20eafd56f..2442a9f7d5 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -98,5 +98,5 @@ exynos_uart_rxsize(uint32_t channel, uint32_t size) "UART%d: Rx FIFO size: %d"
 exynos_uart_channel_error(uint32_t channel) "Wrong UART channel number: %d"
 exynos_uart_rx_timeout(uint32_t channel, uint32_t stat, uint32_t intsp) "UART%d: Rx timeout stat=0x%x intsp=0x%x"
 
-# hw/char/cadence_uart.c
+# cadence_uart.c
 cadence_uart_baudrate(unsigned baudrate) "baudrate %u"
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index 4f46753ea3..bc752cf90f 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -19,17 +19,19 @@
 #include "hw/virtio/virtio-serial.h"
 #include "qapi/error.h"
 #include "qapi/qapi-events-char.h"
+#include "qom/object.h"
 
 #define TYPE_VIRTIO_CONSOLE_SERIAL_PORT "virtserialport"
-#define VIRTIO_CONSOLE(obj) \
-    OBJECT_CHECK(VirtConsole, (obj), TYPE_VIRTIO_CONSOLE_SERIAL_PORT)
+typedef struct VirtConsole VirtConsole;
+DECLARE_INSTANCE_CHECKER(VirtConsole, VIRTIO_CONSOLE,
+                         TYPE_VIRTIO_CONSOLE_SERIAL_PORT)
 
-typedef struct VirtConsole {
+struct VirtConsole {
     VirtIOSerialPort parent_obj;
 
     CharBackend chr;
     guint watch;
-} VirtConsole;
+};
 
 /*
  * Callback function that's called from chardevs when backend becomes
diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c
index ae4ccd00c7..8e9f9cd9ec 100644
--- a/hw/char/xilinx_uartlite.c
+++ b/hw/char/xilinx_uartlite.c
@@ -29,6 +29,7 @@
 #include "hw/sysbus.h"
 #include "qemu/module.h"
 #include "chardev/char-fe.h"
+#include "qom/object.h"
 
 #define DUART(x)
 
@@ -52,10 +53,11 @@
 #define CONTROL_IE        0x10
 
 #define TYPE_XILINX_UARTLITE "xlnx.xps-uartlite"
-#define XILINX_UARTLITE(obj) \
-    OBJECT_CHECK(XilinxUARTLite, (obj), TYPE_XILINX_UARTLITE)
+typedef struct XilinxUARTLite XilinxUARTLite;
+DECLARE_INSTANCE_CHECKER(XilinxUARTLite, XILINX_UARTLITE,
+                         TYPE_XILINX_UARTLITE)
 
-typedef struct XilinxUARTLite {
+struct XilinxUARTLite {
     SysBusDevice parent_obj;
 
     MemoryRegion mmio;
@@ -67,7 +69,7 @@ typedef struct XilinxUARTLite {
     unsigned int rx_fifo_len;
 
     uint32_t regs[R_MAX];
-} XilinxUARTLite;
+};
 
 static void uart_update_irq(XilinxUARTLite *s)
 {
diff --git a/hw/core/irq.c b/hw/core/irq.c
index fb3045b912..8a9cbdd556 100644
--- a/hw/core/irq.c
+++ b/hw/core/irq.c
@@ -26,7 +26,8 @@
 #include "hw/irq.h"
 #include "qom/object.h"
 
-#define IRQ(obj) OBJECT_CHECK(struct IRQState, (obj), TYPE_IRQ)
+DECLARE_INSTANCE_CHECKER(struct IRQState, IRQ,
+                         TYPE_IRQ)
 
 struct IRQState {
     Object parent_obj;
diff --git a/hw/cpu/realview_mpcore.c b/hw/cpu/realview_mpcore.c
index 96f4d2517a..fb547aceef 100644
--- a/hw/cpu/realview_mpcore.c
+++ b/hw/cpu/realview_mpcore.c
@@ -15,15 +15,17 @@
 #include "hw/intc/realview_gic.h"
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 #define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore"
-#define REALVIEW_MPCORE_RIRQ(obj) \
-    OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_REALVIEW_MPCORE_RIRQ)
+typedef struct mpcore_rirq_state mpcore_rirq_state;
+DECLARE_INSTANCE_CHECKER(mpcore_rirq_state, REALVIEW_MPCORE_RIRQ,
+                         TYPE_REALVIEW_MPCORE_RIRQ)
 
 /* Dummy PIC to route IRQ lines.  The baseboard has 4 independent IRQ
    controllers.  The output of these, plus some of the raw input lines
    are fed into a single SMP-aware interrupt controller on the CPU.  */
-typedef struct {
+struct mpcore_rirq_state {
     SysBusDevice parent_obj;
 
     qemu_irq cpuic[32];
@@ -32,7 +34,7 @@ typedef struct {
 
     ARM11MPCorePriveState priv;
     RealViewGICState gic[4];
-} mpcore_rirq_state;
+};
 
 /* Map baseboard IRQs onto CPU IRQ lines.  */
 static const int mpcore_irq_map[32] = {
diff --git a/hw/display/ads7846.c b/hw/display/ads7846.c
index 56bf82fe07..4b87ee7135 100644
--- a/hw/display/ads7846.c
+++ b/hw/display/ads7846.c
@@ -16,8 +16,9 @@
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "ui/console.h"
+#include "qom/object.h"
 
-typedef struct {
+struct ADS7846State {
     SSISlave ssidev;
     qemu_irq interrupt;
 
@@ -27,10 +28,12 @@ typedef struct {
 
     int cycle;
     int output;
-} ADS7846State;
+};
+typedef struct ADS7846State ADS7846State;
 
 #define TYPE_ADS7846 "ads7846"
-#define ADS7846(obj) OBJECT_CHECK(ADS7846State, (obj), TYPE_ADS7846)
+DECLARE_INSTANCE_CHECKER(ADS7846State, ADS7846,
+                         TYPE_ADS7846)
 
 /* Control-byte bitfields */
 #define CB_PD0		(1 << 0)
diff --git a/hw/display/artist.c b/hw/display/artist.c
index 955296d3d8..80cd66e41d 100644
--- a/hw/display/artist.c
+++ b/hw/display/artist.c
@@ -22,9 +22,12 @@
 #include "ui/console.h"
 #include "trace.h"
 #include "framebuffer.h"
+#include "qom/object.h"
 
 #define TYPE_ARTIST "artist"
-#define ARTIST(obj) OBJECT_CHECK(ARTISTState, (obj), TYPE_ARTIST)
+typedef struct ARTISTState ARTISTState;
+DECLARE_INSTANCE_CHECKER(ARTISTState, ARTIST,
+                         TYPE_ARTIST)
 
 #ifdef HOST_WORDS_BIGENDIAN
 #define ROP8OFF(_i) (3 - (_i))
@@ -40,7 +43,7 @@ struct vram_buffer {
     unsigned int height;
 };
 
-typedef struct ARTISTState {
+struct ARTISTState {
     SysBusDevice parent_obj;
 
     QemuConsole *con;
@@ -103,7 +106,7 @@ typedef struct ARTISTState {
     uint32_t font_write_pos_y;
 
     int draw_line_pattern;
-} ARTISTState;
+};
 
 typedef enum {
     ARTIST_BUFFER_AP = 1,
diff --git a/hw/display/ati_int.h b/hw/display/ati_int.h
index 2a16708e4f..714005447d 100644
--- a/hw/display/ati_int.h
+++ b/hw/display/ati_int.h
@@ -13,6 +13,7 @@
 #include "hw/pci/pci.h"
 #include "hw/i2c/bitbang_i2c.h"
 #include "vga_int.h"
+#include "qom/object.h"
 
 /*#define DEBUG_ATI*/
 
@@ -29,7 +30,9 @@
 #define PCI_DEVICE_ID_ATI_RADEON_QY 0x5159
 
 #define TYPE_ATI_VGA "ati-vga"
-#define ATI_VGA(obj) OBJECT_CHECK(ATIVGAState, (obj), TYPE_ATI_VGA)
+typedef struct ATIVGAState ATIVGAState;
+DECLARE_INSTANCE_CHECKER(ATIVGAState, ATI_VGA,
+                         TYPE_ATI_VGA)
 
 typedef struct ATIVGARegs {
     uint32_t mm_index;
@@ -82,7 +85,7 @@ typedef struct ATIVGARegs {
     uint32_t default_sc_bottom_right;
 } ATIVGARegs;
 
-typedef struct ATIVGAState {
+struct ATIVGAState {
     PCIDevice dev;
     VGACommonState vga;
     char *model;
@@ -97,7 +100,7 @@ typedef struct ATIVGAState {
     MemoryRegion io;
     MemoryRegion mm;
     ATIVGARegs regs;
-} ATIVGAState;
+};
 
 const char *ati_reg_name(int num);
 
diff --git a/hw/display/bochs-display.c b/hw/display/bochs-display.c
index a8e8ab8325..41587388c4 100644
--- a/hw/display/bochs-display.c
+++ b/hw/display/bochs-display.c
@@ -18,6 +18,7 @@
 
 #include "ui/console.h"
 #include "ui/qemu-pixman.h"
+#include "qom/object.h"
 
 typedef struct BochsDisplayMode {
     pixman_format_code_t format;
@@ -29,7 +30,7 @@ typedef struct BochsDisplayMode {
     uint64_t             size;
 } BochsDisplayMode;
 
-typedef struct BochsDisplayState {
+struct BochsDisplayState {
     /* parent */
     PCIDevice        pci;
 
@@ -53,11 +54,12 @@ typedef struct BochsDisplayState {
 
     /* device state */
     BochsDisplayMode mode;
-} BochsDisplayState;
+};
+typedef struct BochsDisplayState BochsDisplayState;
 
 #define TYPE_BOCHS_DISPLAY "bochs-display"
-#define BOCHS_DISPLAY(obj) OBJECT_CHECK(BochsDisplayState, (obj), \
-                                        TYPE_BOCHS_DISPLAY)
+DECLARE_INSTANCE_CHECKER(BochsDisplayState, BOCHS_DISPLAY,
+                         TYPE_BOCHS_DISPLAY)
 
 static const VMStateDescription vmstate_bochs_display = {
     .name = "bochs-display",
diff --git a/hw/display/cg3.c b/hw/display/cg3.c
index 7cbe6e56ff..d66ba9ad6a 100644
--- a/hw/display/cg3.c
+++ b/hw/display/cg3.c
@@ -36,6 +36,7 @@
 #include "qemu/log.h"
 #include "qemu/module.h"
 #include "trace.h"
+#include "qom/object.h"
 
 /* Change to 1 to enable debugging */
 #define DEBUG_CG3 0
@@ -65,9 +66,11 @@
 #define CG3_VRAM_OFFSET 0x800000
 
 #define TYPE_CG3 "cgthree"
-#define CG3(obj) OBJECT_CHECK(CG3State, (obj), TYPE_CG3)
+typedef struct CG3State CG3State;
+DECLARE_INSTANCE_CHECKER(CG3State, CG3,
+                         TYPE_CG3)
 
-typedef struct CG3State {
+struct CG3State {
     SysBusDevice parent_obj;
 
     QemuConsole *con;
@@ -82,7 +85,7 @@ typedef struct CG3State {
     uint8_t r[256], g[256], b[256];
     uint16_t width, height, depth;
     uint8_t dac_index, dac_state;
-} CG3State;
+};
 
 static void cg3_update_display(void *opaque)
 {
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 41e71af08a..c088f38cf8 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -44,6 +44,7 @@
 #include "migration/vmstate.h"
 #include "ui/pixel_ops.h"
 #include "cirrus_vga_internal.h"
+#include "qom/object.h"
 
 /*
  * TODO:
@@ -178,14 +179,15 @@ typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
                               uint32_t dstaddr, int dst_pitch,
                               int width, int height);
 
-typedef struct PCICirrusVGAState {
+struct PCICirrusVGAState {
     PCIDevice dev;
     CirrusVGAState cirrus_vga;
-} PCICirrusVGAState;
+};
+typedef struct PCICirrusVGAState PCICirrusVGAState;
 
 #define TYPE_PCI_CIRRUS_VGA "cirrus-vga"
-#define PCI_CIRRUS_VGA(obj) \
-    OBJECT_CHECK(PCICirrusVGAState, (obj), TYPE_PCI_CIRRUS_VGA)
+DECLARE_INSTANCE_CHECKER(PCICirrusVGAState, PCI_CIRRUS_VGA,
+                         TYPE_PCI_CIRRUS_VGA)
 
 static uint8_t rop_to_index[256];
 
diff --git a/hw/display/cirrus_vga_isa.c b/hw/display/cirrus_vga_isa.c
index 825ba57298..e6adee1df4 100644
--- a/hw/display/cirrus_vga_isa.c
+++ b/hw/display/cirrus_vga_isa.c
@@ -30,16 +30,18 @@
 #include "hw/qdev-properties.h"
 #include "hw/isa/isa.h"
 #include "cirrus_vga_internal.h"
+#include "qom/object.h"
 
 #define TYPE_ISA_CIRRUS_VGA "isa-cirrus-vga"
-#define ISA_CIRRUS_VGA(obj) \
-    OBJECT_CHECK(ISACirrusVGAState, (obj), TYPE_ISA_CIRRUS_VGA)
+typedef struct ISACirrusVGAState ISACirrusVGAState;
+DECLARE_INSTANCE_CHECKER(ISACirrusVGAState, ISA_CIRRUS_VGA,
+                         TYPE_ISA_CIRRUS_VGA)
 
-typedef struct ISACirrusVGAState {
+struct ISACirrusVGAState {
     ISADevice parent_obj;
 
     CirrusVGAState cirrus_vga;
-} ISACirrusVGAState;
+};
 
 static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp)
 {
diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index 4b7286b7c9..3ef8698eb7 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -32,6 +32,7 @@
 #include "qemu/bswap.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
+#include "qom/object.h"
 
 /* Debug messages configuration */
 #define EXYNOS4210_FIMD_DEBUG              0
@@ -293,10 +294,11 @@ struct Exynos4210fimdWindow {
 };
 
 #define TYPE_EXYNOS4210_FIMD "exynos4210.fimd"
-#define EXYNOS4210_FIMD(obj) \
-    OBJECT_CHECK(Exynos4210fimdState, (obj), TYPE_EXYNOS4210_FIMD)
+typedef struct Exynos4210fimdState Exynos4210fimdState;
+DECLARE_INSTANCE_CHECKER(Exynos4210fimdState, EXYNOS4210_FIMD,
+                         TYPE_EXYNOS4210_FIMD)
 
-typedef struct {
+struct Exynos4210fimdState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -325,7 +327,7 @@ typedef struct {
     uint8_t *ifb;           /* Internal frame buffer */
     bool invalidate;        /* Image needs to be redrawn */
     bool enabled;           /* Display controller is enabled */
-} Exynos4210fimdState;
+};
 
 /* Perform byte/halfword/word swap of data according to WINCON */
 static inline void fimd_swap_data(unsigned int swap_ctl, uint64_t *data)
diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c
index adcba96e34..4a32fe4c94 100644
--- a/hw/display/g364fb.c
+++ b/hw/display/g364fb.c
@@ -29,6 +29,7 @@
 #include "trace.h"
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 typedef struct G364State {
     /* hardware */
@@ -486,13 +487,15 @@ static void g364fb_init(DeviceState *dev, G364State *s)
 }
 
 #define TYPE_G364 "sysbus-g364"
-#define G364(obj) OBJECT_CHECK(G364SysBusState, (obj), TYPE_G364)
+typedef struct G364SysBusState G364SysBusState;
+DECLARE_INSTANCE_CHECKER(G364SysBusState, G364,
+                         TYPE_G364)
 
-typedef struct {
+struct G364SysBusState {
     SysBusDevice parent_obj;
 
     G364State g364;
-} G364SysBusState;
+};
 
 static void g364fb_sysbus_realize(DeviceState *dev, Error **errp)
 {
diff --git a/hw/display/jazz_led.c b/hw/display/jazz_led.c
index 1d845597f9..647d05f602 100644
--- a/hw/display/jazz_led.c
+++ b/hw/display/jazz_led.c
@@ -29,22 +29,25 @@
 #include "trace.h"
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 typedef enum {
     REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2,
 } screen_state_t;
 
 #define TYPE_JAZZ_LED "jazz-led"
-#define JAZZ_LED(obj) OBJECT_CHECK(LedState, (obj), TYPE_JAZZ_LED)
+typedef struct LedState LedState;
+DECLARE_INSTANCE_CHECKER(LedState, JAZZ_LED,
+                         TYPE_JAZZ_LED)
 
-typedef struct LedState {
+struct LedState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
     uint8_t segments;
     QemuConsole *con;
     screen_state_t state;
-} LedState;
+};
 
 static uint64_t jazz_led_read(void *opaque, hwaddr addr,
                               unsigned int size)
diff --git a/hw/display/milkymist-tmu2.c b/hw/display/milkymist-tmu2.c
index c34ef1a1bf..8a9e7c23fb 100644
--- a/hw/display/milkymist-tmu2.c
+++ b/hw/display/milkymist-tmu2.c
@@ -38,6 +38,7 @@
 #include <X11/Xlib.h>
 #include <epoxy/gl.h>
 #include <epoxy/glx.h>
+#include "qom/object.h"
 
 enum {
     R_CTL = 0,
@@ -82,8 +83,9 @@ struct vertex {
 } QEMU_PACKED;
 
 #define TYPE_MILKYMIST_TMU2 "milkymist-tmu2"
-#define MILKYMIST_TMU2(obj) \
-    OBJECT_CHECK(MilkymistTMU2State, (obj), TYPE_MILKYMIST_TMU2)
+typedef struct MilkymistTMU2State MilkymistTMU2State;
+DECLARE_INSTANCE_CHECKER(MilkymistTMU2State, MILKYMIST_TMU2,
+                         TYPE_MILKYMIST_TMU2)
 
 struct MilkymistTMU2State {
     SysBusDevice parent_obj;
@@ -98,7 +100,6 @@ struct MilkymistTMU2State {
     GLXFBConfig glx_fb_config;
     GLXContext glx_context;
 };
-typedef struct MilkymistTMU2State MilkymistTMU2State;
 
 static const int glx_fbconfig_attr[] = {
     GLX_GREEN_SIZE, 5,
diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c
index 6a6441e6ea..2c879129fb 100644
--- a/hw/display/milkymist-vgafb.c
+++ b/hw/display/milkymist-vgafb.c
@@ -32,6 +32,7 @@
 #include "ui/pixel_ops.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define BITS 8
 #include "migration/vmstate.h"
@@ -68,8 +69,9 @@ enum {
 };
 
 #define TYPE_MILKYMIST_VGAFB "milkymist-vgafb"
-#define MILKYMIST_VGAFB(obj) \
-    OBJECT_CHECK(MilkymistVgafbState, (obj), TYPE_MILKYMIST_VGAFB)
+typedef struct MilkymistVgafbState MilkymistVgafbState;
+DECLARE_INSTANCE_CHECKER(MilkymistVgafbState, MILKYMIST_VGAFB,
+                         TYPE_MILKYMIST_VGAFB)
 
 struct MilkymistVgafbState {
     SysBusDevice parent_obj;
@@ -84,7 +86,6 @@ struct MilkymistVgafbState {
 
     uint32_t regs[R_MAX];
 };
-typedef struct MilkymistVgafbState MilkymistVgafbState;
 
 static int vgafb_enabled(MilkymistVgafbState *s)
 {
diff --git a/hw/display/next-fb.c b/hw/display/next-fb.c
index b0513a8fba..94db0202a3 100644
--- a/hw/display/next-fb.c
+++ b/hw/display/next-fb.c
@@ -30,8 +30,11 @@
 #include "framebuffer.h"
 #include "ui/pixel_ops.h"
 #include "hw/m68k/next-cube.h"
+#include "qom/object.h"
 
-#define NEXTFB(obj) OBJECT_CHECK(NeXTFbState, (obj), TYPE_NEXTFB)
+typedef struct NeXTFbState NeXTFbState;
+DECLARE_INSTANCE_CHECKER(NeXTFbState, NEXTFB,
+                         TYPE_NEXTFB)
 
 struct NeXTFbState {
     SysBusDevice parent_obj;
@@ -44,7 +47,6 @@ struct NeXTFbState {
     uint32_t rows;
     int invalidate;
 };
-typedef struct NeXTFbState NeXTFbState;
 
 static void nextfb_draw_line(void *opaque, uint8_t *d, const uint8_t *s,
                              int width, int pitch)
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
index 61fefbffb3..af51a2b9e7 100644
--- a/hw/display/pl110.c
+++ b/hw/display/pl110.c
@@ -17,6 +17,7 @@
 #include "qemu/timer.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define PL110_CR_EN   0x001
 #define PL110_CR_BGR  0x100
@@ -48,9 +49,11 @@ enum pl110_version
 };
 
 #define TYPE_PL110 "pl110"
-#define PL110(obj) OBJECT_CHECK(PL110State, (obj), TYPE_PL110)
+typedef struct PL110State PL110State;
+DECLARE_INSTANCE_CHECKER(PL110State, PL110,
+                         TYPE_PL110)
 
-typedef struct PL110State {
+struct PL110State {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -73,7 +76,7 @@ typedef struct PL110State {
     uint32_t palette[256];
     uint32_t raw_palette[128];
     qemu_irq irq;
-} PL110State;
+};
 
 static int vmstate_pl110_post_load(void *opaque, int version_id);
 
diff --git a/hw/display/qxl.h b/hw/display/qxl.h
index 707631a1f5..714cd01b63 100644
--- a/hw/display/qxl.h
+++ b/hw/display/qxl.h
@@ -8,6 +8,7 @@
 
 #include "ui/qemu-spice.h"
 #include "ui/spice-display.h"
+#include "qom/object.h"
 
 enum qxl_mode {
     QXL_MODE_UNDEFINED,
@@ -27,7 +28,7 @@ enum qxl_mode {
 #define QXL_PAGE_BITS 12
 #define QXL_PAGE_SIZE (1 << QXL_PAGE_BITS);
 
-typedef struct PCIQXLDevice {
+struct PCIQXLDevice {
     PCIDevice          pci;
     PortioList         vga_port_list;
     SimpleSpiceDisplay ssd;
@@ -126,10 +127,12 @@ typedef struct PCIQXLDevice {
     int                num_dirty_rects;
     QXLRect            dirty[QXL_NUM_DIRTY_RECTS];
     QEMUBH            *update_area_bh;
-} PCIQXLDevice;
+};
+typedef struct PCIQXLDevice PCIQXLDevice;
 
 #define TYPE_PCI_QXL "pci-qxl"
-#define PCI_QXL(obj) OBJECT_CHECK(PCIQXLDevice, (obj), TYPE_PCI_QXL)
+DECLARE_INSTANCE_CHECKER(PCIQXLDevice, PCI_QXL,
+                         TYPE_PCI_QXL)
 
 #define PANIC_ON(x) if ((x)) {                         \
     printf("%s: PANIC %s failed\n", __func__, #x); \
diff --git a/hw/display/ramfb-standalone.c b/hw/display/ramfb-standalone.c
index b18db97eeb..8c0094397f 100644
--- a/hw/display/ramfb-standalone.c
+++ b/hw/display/ramfb-standalone.c
@@ -5,14 +5,17 @@
 #include "hw/qdev-properties.h"
 #include "hw/display/ramfb.h"
 #include "ui/console.h"
+#include "qom/object.h"
 
-#define RAMFB(obj) OBJECT_CHECK(RAMFBStandaloneState, (obj), TYPE_RAMFB_DEVICE)
+typedef struct RAMFBStandaloneState RAMFBStandaloneState;
+DECLARE_INSTANCE_CHECKER(RAMFBStandaloneState, RAMFB,
+                         TYPE_RAMFB_DEVICE)
 
-typedef struct RAMFBStandaloneState {
+struct RAMFBStandaloneState {
     SysBusDevice parent_obj;
     QemuConsole *con;
     RAMFBState *state;
-} RAMFBStandaloneState;
+};
 
 static void display_update_wrapper(void *dev)
 {
diff --git a/hw/display/sii9022.c b/hw/display/sii9022.c
index 3b82a8567f..d88166f449 100644
--- a/hw/display/sii9022.c
+++ b/hw/display/sii9022.c
@@ -19,6 +19,7 @@
 #include "migration/vmstate.h"
 #include "hw/display/i2c-ddc.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define SII9022_SYS_CTRL_DATA 0x1a
 #define SII9022_SYS_CTRL_PWR_DWN 0x10
@@ -35,16 +36,18 @@
 #define SII9022_INT_STATUS_PLUGGED 0x04;
 
 #define TYPE_SII9022 "sii9022"
-#define SII9022(obj) OBJECT_CHECK(sii9022_state, (obj), TYPE_SII9022)
+typedef struct sii9022_state sii9022_state;
+DECLARE_INSTANCE_CHECKER(sii9022_state, SII9022,
+                         TYPE_SII9022)
 
-typedef struct sii9022_state {
+struct sii9022_state {
     I2CSlave parent_obj;
     uint8_t ptr;
     bool addr_byte;
     bool ddc_req;
     bool ddc_skip_finish;
     bool ddc;
-} sii9022_state;
+};
 
 static const VMStateDescription vmstate_sii9022 = {
     .name = "sii9022",
diff --git a/hw/display/sm501.c b/hw/display/sm501.c
index 9cccc68c35..51120c6c3e 100644
--- a/hw/display/sm501.c
+++ b/hw/display/sm501.c
@@ -40,6 +40,7 @@
 #include "ui/pixel_ops.h"
 #include "qemu/bswap.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define MMIO_BASE_OFFSET 0x3e00000
 #define MMIO_SIZE 0x200000
@@ -1931,10 +1932,11 @@ static const VMStateDescription vmstate_sm501_state = {
 };
 
 #define TYPE_SYSBUS_SM501 "sysbus-sm501"
-#define SYSBUS_SM501(obj) \
-    OBJECT_CHECK(SM501SysBusState, (obj), TYPE_SYSBUS_SM501)
+typedef struct SM501SysBusState SM501SysBusState;
+DECLARE_INSTANCE_CHECKER(SM501SysBusState, SYSBUS_SM501,
+                         TYPE_SYSBUS_SM501)
 
-typedef struct {
+struct SM501SysBusState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -1942,7 +1944,7 @@ typedef struct {
     uint32_t vram_size;
     uint32_t base;
     SerialMM serial;
-} SM501SysBusState;
+};
 
 static void sm501_realize_sysbus(DeviceState *dev, Error **errp)
 {
@@ -2034,15 +2036,17 @@ static const TypeInfo sm501_sysbus_info = {
 };
 
 #define TYPE_PCI_SM501 "sm501"
-#define PCI_SM501(obj) OBJECT_CHECK(SM501PCIState, (obj), TYPE_PCI_SM501)
+typedef struct SM501PCIState SM501PCIState;
+DECLARE_INSTANCE_CHECKER(SM501PCIState, PCI_SM501,
+                         TYPE_PCI_SM501)
 
-typedef struct {
+struct SM501PCIState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
     SM501State state;
     uint32_t vram_size;
-} SM501PCIState;
+};
 
 static void sm501_realize_pci(PCIDevice *dev, Error **errp)
 {
diff --git a/hw/display/ssd0303.c b/hw/display/ssd0303.c
index 718378f6de..0378573a42 100644
--- a/hw/display/ssd0303.c
+++ b/hw/display/ssd0303.c
@@ -16,6 +16,7 @@
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "ui/console.h"
+#include "qom/object.h"
 
 //#define DEBUG_SSD0303 1
 
@@ -46,9 +47,11 @@ enum ssd0303_cmd {
 };
 
 #define TYPE_SSD0303 "ssd0303"
-#define SSD0303(obj) OBJECT_CHECK(ssd0303_state, (obj), TYPE_SSD0303)
+typedef struct ssd0303_state ssd0303_state;
+DECLARE_INSTANCE_CHECKER(ssd0303_state, SSD0303,
+                         TYPE_SSD0303)
 
-typedef struct {
+struct ssd0303_state {
     I2CSlave parent_obj;
 
     QemuConsole *con;
@@ -63,7 +66,7 @@ typedef struct {
     enum ssd0303_mode mode;
     enum ssd0303_cmd cmd_state;
     uint8_t framebuffer[132*8];
-} ssd0303_state;
+};
 
 static uint8_t ssd0303_recv(I2CSlave *i2c)
 {
diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c
index 32d27f008a..037da81127 100644
--- a/hw/display/ssd0323.c
+++ b/hw/display/ssd0323.c
@@ -16,6 +16,7 @@
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "ui/console.h"
+#include "qom/object.h"
 
 //#define DEBUG_SSD0323 1
 
@@ -47,7 +48,7 @@ enum ssd0323_mode
     SSD0323_DATA
 };
 
-typedef struct {
+struct ssd0323_state {
     SSISlave ssidev;
     QemuConsole *con;
 
@@ -64,10 +65,12 @@ typedef struct {
     int32_t remap;
     uint32_t mode;
     uint8_t framebuffer[128 * 80 / 2];
-} ssd0323_state;
+};
+typedef struct ssd0323_state ssd0323_state;
 
 #define TYPE_SSD0323 "ssd0323"
-#define SSD0323(obj) OBJECT_CHECK(ssd0323_state, (obj), TYPE_SSD0323)
+DECLARE_INSTANCE_CHECKER(ssd0323_state, SSD0323,
+                         TYPE_SSD0323)
 
 
 static uint32_t ssd0323_transfer(SSISlave *dev, uint32_t data)
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
index 1fb45b1aab..69e901a800 100644
--- a/hw/display/tcx.c
+++ b/hw/display/tcx.c
@@ -33,6 +33,7 @@
 #include "migration/vmstate.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define TCX_ROM_FILE "QEMU,tcx.bin"
 #define FCODE_MAX_ROM_SIZE 0x10000
@@ -55,9 +56,11 @@
 #define TCX_THC_CURSBITS 0x980
 
 #define TYPE_TCX "SUNW,tcx"
-#define TCX(obj) OBJECT_CHECK(TCXState, (obj), TYPE_TCX)
+typedef struct TCXState TCXState;
+DECLARE_INSTANCE_CHECKER(TCXState, TCX,
+                         TYPE_TCX)
 
-typedef struct TCXState {
+struct TCXState {
     SysBusDevice parent_obj;
 
     QemuConsole *con;
@@ -93,7 +96,7 @@ typedef struct TCXState {
     uint32_t cursbits[32];
     uint16_t cursx;
     uint16_t cursy;
-} TCXState;
+};
 
 static void tcx_set_dirty(TCXState *s, ram_addr_t addr, int len)
 {
diff --git a/hw/display/trace-events b/hw/display/trace-events
index 970d6bac5d..957b8ba994 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -32,9 +32,11 @@ vmware_scratch_read(uint32_t index, uint32_t value) "index %d, value 0x%x"
 vmware_scratch_write(uint32_t index, uint32_t value) "index %d, value 0x%x"
 vmware_setmode(uint32_t w, uint32_t h, uint32_t bpp) "%dx%d @ %d bpp"
 
+# virtio-gpu-base.c
+virtio_gpu_features(bool virgl) "virgl %d"
+
 # virtio-gpu-3d.c
 # virtio-gpu.c
-virtio_gpu_features(bool virgl) "virgl %d"
 virtio_gpu_cmd_get_display_info(void) ""
 virtio_gpu_cmd_get_edid(uint32_t scanout) "scanout %d"
 virtio_gpu_cmd_set_scanout(uint32_t id, uint32_t res, uint32_t w, uint32_t h, uint32_t x, uint32_t y) "id %d, res 0x%x, w %d, h %d, x %d, y %d"
diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c
index 3aaeeeca1e..0ebfcca9d1 100644
--- a/hw/display/vga-isa.c
+++ b/hw/display/vga-isa.c
@@ -32,17 +32,20 @@
 #include "qemu/timer.h"
 #include "hw/loader.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 #define TYPE_ISA_VGA "isa-vga"
-#define ISA_VGA(obj) OBJECT_CHECK(ISAVGAState, (obj), TYPE_ISA_VGA)
+typedef struct ISAVGAState ISAVGAState;
+DECLARE_INSTANCE_CHECKER(ISAVGAState, ISA_VGA,
+                         TYPE_ISA_VGA)
 
-typedef struct ISAVGAState {
+struct ISAVGAState {
     ISADevice parent_obj;
 
     struct VGACommonState state;
     PortioList portio_vga;
     PortioList portio_vbe;
-} ISAVGAState;
+};
 
 static void vga_isa_reset(DeviceState *dev)
 {
diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
index a640fd866d..3b45fa3bad 100644
--- a/hw/display/vga-pci.c
+++ b/hw/display/vga-pci.c
@@ -34,6 +34,7 @@
 #include "qemu/timer.h"
 #include "hw/loader.h"
 #include "hw/display/edid.h"
+#include "qom/object.h"
 
 enum vga_pci_flags {
     PCI_VGA_FLAG_ENABLE_MMIO = 1,
@@ -41,7 +42,7 @@ enum vga_pci_flags {
     PCI_VGA_FLAG_ENABLE_EDID = 3,
 };
 
-typedef struct PCIVGAState {
+struct PCIVGAState {
     PCIDevice dev;
     VGACommonState vga;
     uint32_t flags;
@@ -49,10 +50,12 @@ typedef struct PCIVGAState {
     MemoryRegion mmio;
     MemoryRegion mrs[4];
     uint8_t edid[256];
-} PCIVGAState;
+};
+typedef struct PCIVGAState PCIVGAState;
 
 #define TYPE_PCI_VGA "pci-vga"
-#define PCI_VGA(obj) OBJECT_CHECK(PCIVGAState, (obj), TYPE_PCI_VGA)
+DECLARE_INSTANCE_CHECKER(PCIVGAState, PCI_VGA,
+                         TYPE_PCI_VGA)
 
 static const VMStateDescription vmstate_vga_pci = {
     .name = "vga",
diff --git a/hw/display/vhost-user-gpu-pci.c b/hw/display/vhost-user-gpu-pci.c
index 23ce655e0f..a02b23ecaf 100644
--- a/hw/display/vhost-user-gpu-pci.c
+++ b/hw/display/vhost-user-gpu-pci.c
@@ -11,16 +11,18 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "hw/virtio/virtio-gpu-pci.h"
+#include "qom/object.h"
 
 #define TYPE_VHOST_USER_GPU_PCI "vhost-user-gpu-pci"
-#define VHOST_USER_GPU_PCI(obj)                                     \
-    OBJECT_CHECK(VhostUserGPUPCI, (obj), TYPE_VHOST_USER_GPU_PCI)
+typedef struct VhostUserGPUPCI VhostUserGPUPCI;
+DECLARE_INSTANCE_CHECKER(VhostUserGPUPCI, VHOST_USER_GPU_PCI,
+                         TYPE_VHOST_USER_GPU_PCI)
 
-typedef struct VhostUserGPUPCI {
+struct VhostUserGPUPCI {
     VirtIOGPUPCIBase parent_obj;
 
     VhostUserGPU vdev;
-} VhostUserGPUPCI;
+};
 
 static void vhost_user_gpu_pci_initfn(Object *obj)
 {
diff --git a/hw/display/vhost-user-vga.c b/hw/display/vhost-user-vga.c
index 1690f6b610..a34a99856d 100644
--- a/hw/display/vhost-user-vga.c
+++ b/hw/display/vhost-user-vga.c
@@ -11,17 +11,19 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "virtio-vga.h"
+#include "qom/object.h"
 
 #define TYPE_VHOST_USER_VGA "vhost-user-vga"
 
-#define VHOST_USER_VGA(obj)                                \
-    OBJECT_CHECK(VhostUserVGA, (obj), TYPE_VHOST_USER_VGA)
+typedef struct VhostUserVGA VhostUserVGA;
+DECLARE_INSTANCE_CHECKER(VhostUserVGA, VHOST_USER_VGA,
+                         TYPE_VHOST_USER_VGA)
 
-typedef struct VhostUserVGA {
+struct VhostUserVGA {
     VirtIOVGABase parent_obj;
 
     VhostUserGPU vdev;
-} VhostUserVGA;
+};
 
 static void vhost_user_vga_inst_initfn(Object *obj)
 {
@@ -39,7 +41,7 @@ static void vhost_user_vga_inst_initfn(Object *obj)
 static const VirtioPCIDeviceTypeInfo vhost_user_vga_info = {
     .generic_name  = TYPE_VHOST_USER_VGA,
     .parent        = TYPE_VIRTIO_VGA_BASE,
-    .instance_size = sizeof(struct VhostUserVGA),
+    .instance_size = sizeof(VhostUserVGA),
     .instance_init = vhost_user_vga_inst_initfn,
 };
 
diff --git a/hw/display/virtio-gpu-pci.c b/hw/display/virtio-gpu-pci.c
index 34d8e93f28..d742a30aec 100644
--- a/hw/display/virtio-gpu-pci.c
+++ b/hw/display/virtio-gpu-pci.c
@@ -19,6 +19,7 @@
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-bus.h"
 #include "hw/virtio/virtio-gpu-pci.h"
+#include "qom/object.h"
 
 static Property virtio_gpu_pci_base_properties[] = {
     DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy),
@@ -65,13 +66,14 @@ static const TypeInfo virtio_gpu_pci_base_info = {
 };
 
 #define TYPE_VIRTIO_GPU_PCI "virtio-gpu-pci"
-#define VIRTIO_GPU_PCI(obj)                                 \
-    OBJECT_CHECK(VirtIOGPUPCI, (obj), TYPE_VIRTIO_GPU_PCI)
+typedef struct VirtIOGPUPCI VirtIOGPUPCI;
+DECLARE_INSTANCE_CHECKER(VirtIOGPUPCI, VIRTIO_GPU_PCI,
+                         TYPE_VIRTIO_GPU_PCI)
 
-typedef struct VirtIOGPUPCI {
+struct VirtIOGPUPCI {
     VirtIOGPUPCIBase parent_obj;
     VirtIOGPU vdev;
-} VirtIOGPUPCI;
+};
 
 static void virtio_gpu_initfn(Object *obj)
 {
diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
index f533d7d1b4..573e7d5928 100644
--- a/hw/display/virtio-vga.c
+++ b/hw/display/virtio-vga.c
@@ -5,6 +5,7 @@
 #include "qapi/error.h"
 #include "qemu/module.h"
 #include "virtio-vga.h"
+#include "qom/object.h"
 
 static void virtio_vga_base_invalidate_display(void *opaque)
 {
@@ -194,22 +195,23 @@ static void virtio_vga_base_class_init(ObjectClass *klass, void *data)
 static TypeInfo virtio_vga_base_info = {
     .name          = TYPE_VIRTIO_VGA_BASE,
     .parent        = TYPE_VIRTIO_PCI,
-    .instance_size = sizeof(struct VirtIOVGABase),
-    .class_size    = sizeof(struct VirtIOVGABaseClass),
+    .instance_size = sizeof(VirtIOVGABase),
+    .class_size    = sizeof(VirtIOVGABaseClass),
     .class_init    = virtio_vga_base_class_init,
     .abstract      = true,
 };
 
 #define TYPE_VIRTIO_VGA "virtio-vga"
 
-#define VIRTIO_VGA(obj)                             \
-    OBJECT_CHECK(VirtIOVGA, (obj), TYPE_VIRTIO_VGA)
+typedef struct VirtIOVGA VirtIOVGA;
+DECLARE_INSTANCE_CHECKER(VirtIOVGA, VIRTIO_VGA,
+                         TYPE_VIRTIO_VGA)
 
-typedef struct VirtIOVGA {
+struct VirtIOVGA {
     VirtIOVGABase parent_obj;
 
     VirtIOGPU     vdev;
-} VirtIOVGA;
+};
 
 static void virtio_vga_inst_initfn(Object *obj)
 {
@@ -224,7 +226,7 @@ static void virtio_vga_inst_initfn(Object *obj)
 static VirtioPCIDeviceTypeInfo virtio_vga_info = {
     .generic_name  = TYPE_VIRTIO_VGA,
     .parent        = TYPE_VIRTIO_VGA_BASE,
-    .instance_size = sizeof(struct VirtIOVGA),
+    .instance_size = sizeof(VirtIOVGA),
     .instance_init = virtio_vga_inst_initfn,
 };
 
diff --git a/hw/display/virtio-vga.h b/hw/display/virtio-vga.h
index c41281a010..5c5671c9c1 100644
--- a/hw/display/virtio-vga.h
+++ b/hw/display/virtio-vga.h
@@ -3,30 +3,27 @@
 
 #include "hw/virtio/virtio-gpu-pci.h"
 #include "vga_int.h"
+#include "qom/object.h"
 
 /*
  * virtio-vga-base: This extends VirtioPCIProxy.
  */
 #define TYPE_VIRTIO_VGA_BASE "virtio-vga-base"
-#define VIRTIO_VGA_BASE(obj)                                \
-    OBJECT_CHECK(VirtIOVGABase, (obj), TYPE_VIRTIO_VGA_BASE)
-#define VIRTIO_VGA_BASE_GET_CLASS(obj)                      \
-    OBJECT_GET_CLASS(VirtIOVGABaseClass, obj, TYPE_VIRTIO_VGA_BASE)
-#define VIRTIO_VGA_BASE_CLASS(klass)                        \
-    OBJECT_CLASS_CHECK(VirtIOVGABaseClass, klass, TYPE_VIRTIO_VGA_BASE)
+OBJECT_DECLARE_TYPE(VirtIOVGABase, VirtIOVGABaseClass,
+                    virtio_vga_base, VIRTIO_VGA_BASE)
 
-typedef struct VirtIOVGABase {
+struct VirtIOVGABase {
     VirtIOPCIProxy parent_obj;
 
     VirtIOGPUBase *vgpu;
     VGACommonState vga;
     MemoryRegion vga_mrs[3];
-} VirtIOVGABase;
+};
 
-typedef struct VirtIOVGABaseClass {
+struct VirtIOVGABaseClass {
     VirtioPCIClass parent_class;
 
     DeviceReset parent_reset;
-} VirtIOVGABaseClass;
+};
 
 #endif /* VIRTIO_VGA_H */
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 2579f6b218..bef0d7d69a 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -33,6 +33,7 @@
 #include "hw/pci/pci.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 #undef VERBOSE
 #define HW_RECT_ACCEL
@@ -85,8 +86,8 @@ struct vmsvga_state_s {
 
 #define TYPE_VMWARE_SVGA "vmware-svga"
 
-#define VMWARE_SVGA(obj) \
-    OBJECT_CHECK(struct pci_vmsvga_state_s, (obj), TYPE_VMWARE_SVGA)
+DECLARE_INSTANCE_CHECKER(struct pci_vmsvga_state_s, VMWARE_SVGA,
+                         TYPE_VMWARE_SVGA)
 
 struct pci_vmsvga_state_s {
     /*< private >*/
diff --git a/hw/dma/i82374.c b/hw/dma/i82374.c
index 6977d85ef8..5b7ff635f7 100644
--- a/hw/dma/i82374.c
+++ b/hw/dma/i82374.c
@@ -29,9 +29,12 @@
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
 #include "hw/dma/i8257.h"
+#include "qom/object.h"
 
 #define TYPE_I82374 "i82374"
-#define I82374(obj) OBJECT_CHECK(I82374State, (obj), TYPE_I82374)
+typedef struct I82374State I82374State;
+DECLARE_INSTANCE_CHECKER(I82374State, I82374,
+                         TYPE_I82374)
 
 //#define DEBUG_I82374
 
@@ -45,13 +48,13 @@ do {} while (0)
 #define BADF(fmt, ...) \
 do { fprintf(stderr, "i82374 ERROR: " fmt , ## __VA_ARGS__); } while (0)
 
-typedef struct I82374State {
+struct I82374State {
     ISADevice parent_obj;
 
     uint32_t iobase;
     uint8_t commands[8];
     PortioList port_list;
-} I82374State;
+};
 
 static const VMStateDescription vmstate_i82374 = {
     .name = "i82374",
diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c
index 0bd63a43f5..859586fd2f 100644
--- a/hw/dma/pl330.c
+++ b/hw/dma/pl330.c
@@ -26,6 +26,7 @@
 #include "qemu/log.h"
 #include "qemu/module.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #ifndef PL330_ERR_DEBUG
 #define PL330_ERR_DEBUG 0
@@ -271,7 +272,8 @@ struct PL330State {
 };
 
 #define TYPE_PL330 "pl330"
-#define PL330(obj) OBJECT_CHECK(PL330State, (obj), TYPE_PL330)
+DECLARE_INSTANCE_CHECKER(PL330State, PL330,
+                         TYPE_PL330)
 
 static const VMStateDescription vmstate_pl330 = {
     .name = "pl330",
diff --git a/hw/dma/puv3_dma.c b/hw/dma/puv3_dma.c
index 7fa979180f..825e3dc0ac 100644
--- a/hw/dma/puv3_dma.c
+++ b/hw/dma/puv3_dma.c
@@ -11,6 +11,7 @@
 
 #include "qemu/osdep.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #undef DEBUG_PUV3
 #include "hw/unicore32/puv3.h"
@@ -22,14 +23,16 @@
 #define PUV3_DMA_CH(offset)     ((offset) >> 8)
 
 #define TYPE_PUV3_DMA "puv3_dma"
-#define PUV3_DMA(obj) OBJECT_CHECK(PUV3DMAState, (obj), TYPE_PUV3_DMA)
+typedef struct PUV3DMAState PUV3DMAState;
+DECLARE_INSTANCE_CHECKER(PUV3DMAState, PUV3_DMA,
+                         TYPE_PUV3_DMA)
 
-typedef struct PUV3DMAState {
+struct PUV3DMAState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
     uint32_t reg_CFG[PUV3_DMA_CH_NR];
-} PUV3DMAState;
+};
 
 static uint64_t puv3_dma_read(void *opaque, hwaddr offset,
         unsigned size)
diff --git a/hw/dma/pxa2xx_dma.c b/hw/dma/pxa2xx_dma.c
index 78b2849bcb..4f6c0e5e5e 100644
--- a/hw/dma/pxa2xx_dma.c
+++ b/hw/dma/pxa2xx_dma.c
@@ -18,6 +18,7 @@
 #include "migration/vmstate.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define PXA255_DMA_NUM_CHANNELS 16
 #define PXA27X_DMA_NUM_CHANNELS 32
@@ -34,9 +35,11 @@ typedef struct {
 } PXA2xxDMAChannel;
 
 #define TYPE_PXA2XX_DMA "pxa2xx-dma"
-#define PXA2XX_DMA(obj) OBJECT_CHECK(PXA2xxDMAState, (obj), TYPE_PXA2XX_DMA)
+typedef struct PXA2xxDMAState PXA2xxDMAState;
+DECLARE_INSTANCE_CHECKER(PXA2xxDMAState, PXA2XX_DMA,
+                         TYPE_PXA2XX_DMA)
 
-typedef struct PXA2xxDMAState {
+struct PXA2xxDMAState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -58,7 +61,7 @@ typedef struct PXA2xxDMAState {
 
     /* Flag to avoid recursive DMA invocations.  */
     int running;
-} PXA2xxDMAState;
+};
 
 #define DCSR0	0x0000	/* DMA Control / Status register for Channel 0 */
 #define DCSR31	0x007c	/* DMA Control / Status register for Channel 31 */
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index 7eddc9a776..c584815d06 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -34,6 +34,7 @@
 #include "qemu/module.h"
 #include "exec/address-spaces.h"
 #include "trace.h"
+#include "qom/object.h"
 
 /********************************************************/
 /* rc4030 emulation                                     */
@@ -55,12 +56,13 @@ typedef struct dma_pagetable_entry {
 #define DMA_FLAG_ADDR_INTR  0x0400
 
 #define TYPE_RC4030 "rc4030"
-#define RC4030(obj) \
-    OBJECT_CHECK(rc4030State, (obj), TYPE_RC4030)
+typedef struct rc4030State rc4030State;
+DECLARE_INSTANCE_CHECKER(rc4030State, RC4030,
+                         TYPE_RC4030)
 
 #define TYPE_RC4030_IOMMU_MEMORY_REGION "rc4030-iommu-memory-region"
 
-typedef struct rc4030State {
+struct rc4030State {
 
     SysBusDevice parent;
 
@@ -101,7 +103,7 @@ typedef struct rc4030State {
 
     MemoryRegion iomem_chipset;
     MemoryRegion iomem_jazzio;
-} rc4030State;
+};
 
 static void set_next_tick(rc4030State *s)
 {
diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c
index bcd1626fbd..d20a5bc065 100644
--- a/hw/dma/sparc32_dma.c
+++ b/hw/dma/sparc32_dma.c
@@ -303,7 +303,7 @@ static void sparc32_espdma_device_realize(DeviceState *dev, Error **errp)
 
     d = qdev_new(TYPE_ESP);
     object_property_add_child(OBJECT(dev), "esp", OBJECT(d));
-    sysbus = ESP_STATE(d);
+    sysbus = ESP(d);
     esp = &sysbus->esp;
     esp->dma_memory_read = espdma_memory_read;
     esp->dma_memory_write = espdma_memory_write;
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index a4812e480a..498fc17d8a 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -35,6 +35,7 @@
 
 #include "sysemu/dma.h"
 #include "hw/stream.h"
+#include "qom/object.h"
 
 #define D(x)
 
@@ -42,16 +43,16 @@
 #define TYPE_XILINX_AXI_DMA_DATA_STREAM "xilinx-axi-dma-data-stream"
 #define TYPE_XILINX_AXI_DMA_CONTROL_STREAM "xilinx-axi-dma-control-stream"
 
-#define XILINX_AXI_DMA(obj) \
-     OBJECT_CHECK(XilinxAXIDMA, (obj), TYPE_XILINX_AXI_DMA)
+typedef struct XilinxAXIDMA XilinxAXIDMA;
+DECLARE_INSTANCE_CHECKER(XilinxAXIDMA, XILINX_AXI_DMA,
+                         TYPE_XILINX_AXI_DMA)
 
-#define XILINX_AXI_DMA_DATA_STREAM(obj) \
-     OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\
-     TYPE_XILINX_AXI_DMA_DATA_STREAM)
+typedef struct XilinxAXIDMAStreamSlave XilinxAXIDMAStreamSlave;
+DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSlave, XILINX_AXI_DMA_DATA_STREAM,
+                         TYPE_XILINX_AXI_DMA_DATA_STREAM)
 
-#define XILINX_AXI_DMA_CONTROL_STREAM(obj) \
-     OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\
-     TYPE_XILINX_AXI_DMA_CONTROL_STREAM)
+DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSlave, XILINX_AXI_DMA_CONTROL_STREAM,
+                         TYPE_XILINX_AXI_DMA_CONTROL_STREAM)
 
 #define R_DMACR             (0x00 / 4)
 #define R_DMASR             (0x04 / 4)
@@ -62,8 +63,6 @@
 #define CONTROL_PAYLOAD_WORDS 5
 #define CONTROL_PAYLOAD_SIZE (CONTROL_PAYLOAD_WORDS * (sizeof(uint32_t)))
 
-typedef struct XilinxAXIDMA XilinxAXIDMA;
-typedef struct XilinxAXIDMAStreamSlave XilinxAXIDMAStreamSlave;
 
 enum {
     DMACR_RUNSTOP = 1,
@@ -634,7 +633,7 @@ static const TypeInfo axidma_info = {
 static const TypeInfo xilinx_axidma_data_stream_info = {
     .name          = TYPE_XILINX_AXI_DMA_DATA_STREAM,
     .parent        = TYPE_OBJECT,
-    .instance_size = sizeof(struct XilinxAXIDMAStreamSlave),
+    .instance_size = sizeof(XilinxAXIDMAStreamSlave),
     .class_init    = xilinx_axidma_stream_class_init,
     .class_data    = &xilinx_axidma_data_stream_class,
     .interfaces = (InterfaceInfo[]) {
@@ -646,7 +645,7 @@ static const TypeInfo xilinx_axidma_data_stream_info = {
 static const TypeInfo xilinx_axidma_control_stream_info = {
     .name          = TYPE_XILINX_AXI_DMA_CONTROL_STREAM,
     .parent        = TYPE_OBJECT,
-    .instance_size = sizeof(struct XilinxAXIDMAStreamSlave),
+    .instance_size = sizeof(XilinxAXIDMAStreamSlave),
     .class_init    = xilinx_axidma_stream_class_init,
     .class_data    = &xilinx_axidma_control_stream_class,
     .interfaces = (InterfaceInfo[]) {
diff --git a/hw/dma/xlnx_dpdma.c b/hw/dma/xlnx_dpdma.c
index b40c897de2..967548abd3 100644
--- a/hw/dma/xlnx_dpdma.c
+++ b/hw/dma/xlnx_dpdma.c
@@ -388,7 +388,7 @@ static void xlnx_dpdma_dump_descriptor(DPDMADescriptor *desc)
 {
     if (DEBUG_DPDMA) {
         qemu_log("DUMP DESCRIPTOR:\n");
-        qemu_hexdump((char *)desc, stdout, "", sizeof(DPDMADescriptor));
+        qemu_hexdump(stdout, "", desc, sizeof(DPDMADescriptor));
     }
 }
 
diff --git a/hw/gpio/gpio_key.c b/hw/gpio/gpio_key.c
index 46bbd42772..86aa78aae4 100644
--- a/hw/gpio/gpio_key.c
+++ b/hw/gpio/gpio_key.c
@@ -28,17 +28,20 @@
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "qemu/timer.h"
+#include "qom/object.h"
 
 #define TYPE_GPIOKEY "gpio-key"
-#define GPIOKEY(obj) OBJECT_CHECK(GPIOKEYState, (obj), TYPE_GPIOKEY)
+typedef struct GPIOKEYState GPIOKEYState;
+DECLARE_INSTANCE_CHECKER(GPIOKEYState, GPIOKEY,
+                         TYPE_GPIOKEY)
 #define GPIO_KEY_LATENCY 100 /* 100ms */
 
-typedef struct GPIOKEYState {
+struct GPIOKEYState {
     SysBusDevice parent_obj;
 
     QEMUTimer *timer;
     qemu_irq irq;
-} GPIOKEYState;
+};
 
 static const VMStateDescription vmstate_gpio_key = {
     .name = "gpio-key",
diff --git a/hw/gpio/max7310.c b/hw/gpio/max7310.c
index 4f78774dc8..2888d071ac 100644
--- a/hw/gpio/max7310.c
+++ b/hw/gpio/max7310.c
@@ -13,12 +13,16 @@
 #include "hw/hw.h"
 #include "hw/irq.h"
 #include "migration/vmstate.h"
+#include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define TYPE_MAX7310 "max7310"
-#define MAX7310(obj) OBJECT_CHECK(MAX7310State, (obj), TYPE_MAX7310)
+typedef struct MAX7310State MAX7310State;
+DECLARE_INSTANCE_CHECKER(MAX7310State, MAX7310,
+                         TYPE_MAX7310)
 
-typedef struct MAX7310State {
+struct MAX7310State {
     I2CSlave parent_obj;
 
     int i2c_command_byte;
@@ -31,7 +35,7 @@ typedef struct MAX7310State {
     uint8_t command;
     qemu_irq handler[8];
     qemu_irq *gpio_in;
-} MAX7310State;
+};
 
 static void max7310_reset(DeviceState *dev)
 {
@@ -68,9 +72,8 @@ static uint8_t max7310_rx(I2CSlave *i2c)
         return 0xff;
 
     default:
-#ifdef VERBOSE
-        printf("%s: unknown register %02x\n", __func__, s->command);
-#endif
+        qemu_log_mask(LOG_UNIMP, "%s: Unsupported register 0x02%" PRIx8 "\n",
+                      __func__, s->command);
         break;
     }
     return 0xff;
@@ -122,9 +125,8 @@ static int max7310_tx(I2CSlave *i2c, uint8_t data)
     case 0x00:	/* Input port - ignore writes */
         break;
     default:
-#ifdef VERBOSE
-        printf("%s: unknown register %02x\n", __func__, s->command);
-#endif
+        qemu_log_mask(LOG_UNIMP, "%s: Unsupported register 0x02%" PRIx8 "\n",
+                      __func__, s->command);
         return 1;
     }
 
diff --git a/hw/gpio/mpc8xxx.c b/hw/gpio/mpc8xxx.c
index 1d99667094..dac8b1be38 100644
--- a/hw/gpio/mpc8xxx.c
+++ b/hw/gpio/mpc8xxx.c
@@ -24,11 +24,14 @@
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define TYPE_MPC8XXX_GPIO "mpc8xxx_gpio"
-#define MPC8XXX_GPIO(obj) OBJECT_CHECK(MPC8XXXGPIOState, (obj), TYPE_MPC8XXX_GPIO)
+typedef struct MPC8XXXGPIOState MPC8XXXGPIOState;
+DECLARE_INSTANCE_CHECKER(MPC8XXXGPIOState, MPC8XXX_GPIO,
+                         TYPE_MPC8XXX_GPIO)
 
-typedef struct MPC8XXXGPIOState {
+struct MPC8XXXGPIOState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -41,7 +44,7 @@ typedef struct MPC8XXXGPIOState {
     uint32_t ier;
     uint32_t imr;
     uint32_t icr;
-} MPC8XXXGPIOState;
+};
 
 static const VMStateDescription vmstate_mpc8xxx_gpio = {
     .name = "mpc8xxx_gpio",
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
index f662c4cb95..e25084b40c 100644
--- a/hw/gpio/omap_gpio.c
+++ b/hw/gpio/omap_gpio.c
@@ -392,8 +392,10 @@ static void omap2_gpio_module_write(void *opaque, hwaddr addr,
         break;
 
     case 0x10:	/* GPIO_SYSCONFIG */
-        if (((value >> 3) & 3) == 3)
-            fprintf(stderr, "%s: bad IDLEMODE value\n", __func__);
+        if (((value >> 3) & 3) == 3) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: Illegal IDLEMODE value: 3\n", __func__);
+        }
         if (value & 2)
             omap2_gpio_module_reset(s);
         s->config[0] = value & 0x1d;
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
index 6d3c36bc16..3420df0d1f 100644
--- a/hw/gpio/pl061.c
+++ b/hw/gpio/pl061.c
@@ -14,6 +14,7 @@
 #include "migration/vmstate.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 //#define DEBUG_PL061 1
 
@@ -34,11 +35,13 @@ static const uint8_t pl061_id_luminary[12] =
   { 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
 
 #define TYPE_PL061 "pl061"
-#define PL061(obj) OBJECT_CHECK(PL061State, (obj), TYPE_PL061)
+typedef struct PL061State PL061State;
+DECLARE_INSTANCE_CHECKER(PL061State, PL061,
+                         TYPE_PL061)
 
 #define N_GPIOS 8
 
-typedef struct PL061State {
+struct PL061State {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -67,7 +70,7 @@ typedef struct PL061State {
     qemu_irq out[N_GPIOS];
     const unsigned char *id;
     uint32_t rsvd_start; /* reserved area: [rsvd_start, 0xfcc] */
-} PL061State;
+};
 
 static const VMStateDescription vmstate_pl061 = {
     .name = "pl061",
diff --git a/hw/gpio/puv3_gpio.c b/hw/gpio/puv3_gpio.c
index 7362b6715f..98ea2b4c2e 100644
--- a/hw/gpio/puv3_gpio.c
+++ b/hw/gpio/puv3_gpio.c
@@ -11,6 +11,7 @@
 
 #include "qemu/osdep.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #undef DEBUG_PUV3
 #include "hw/unicore32/puv3.h"
@@ -18,9 +19,11 @@
 #include "qemu/log.h"
 
 #define TYPE_PUV3_GPIO "puv3_gpio"
-#define PUV3_GPIO(obj) OBJECT_CHECK(PUV3GPIOState, (obj), TYPE_PUV3_GPIO)
+typedef struct PUV3GPIOState PUV3GPIOState;
+DECLARE_INSTANCE_CHECKER(PUV3GPIOState, PUV3_GPIO,
+                         TYPE_PUV3_GPIO)
 
-typedef struct PUV3GPIOState {
+struct PUV3GPIOState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -29,7 +32,7 @@ typedef struct PUV3GPIOState {
     uint32_t reg_GPLR;
     uint32_t reg_GPDR;
     uint32_t reg_GPIR;
-} PUV3GPIOState;
+};
 
 static uint64_t puv3_gpio_read(void *opaque, hwaddr offset,
         unsigned size)
diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c
index 258e926493..3d25c55d06 100644
--- a/hw/gpio/zaurus.c
+++ b/hw/gpio/zaurus.c
@@ -23,13 +23,15 @@
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
+#include "qom/object.h"
 
 /* SCOOP devices */
 
 #define TYPE_SCOOP "scoop"
-#define SCOOP(obj) OBJECT_CHECK(ScoopInfo, (obj), TYPE_SCOOP)
-
 typedef struct ScoopInfo ScoopInfo;
+DECLARE_INSTANCE_CHECKER(ScoopInfo, SCOOP,
+                         TYPE_SCOOP)
+
 struct ScoopInfo {
     SysBusDevice parent_obj;
 
diff --git a/hw/hppa/dino.c b/hw/hppa/dino.c
index 7f0c6223a8..c0c9b8a2b8 100644
--- a/hw/hppa/dino.c
+++ b/hw/hppa/dino.c
@@ -22,6 +22,7 @@
 #include "hppa_sys.h"
 #include "exec/address-spaces.h"
 #include "trace.h"
+#include "qom/object.h"
 
 
 #define TYPE_DINO_PCI_HOST_BRIDGE "dino-pcihost"
@@ -80,8 +81,9 @@
 
 #define DINO_MEM_CHUNK_SIZE (8 * MiB)
 
-#define DINO_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(DinoState, (obj), TYPE_DINO_PCI_HOST_BRIDGE)
+typedef struct DinoState DinoState;
+DECLARE_INSTANCE_CHECKER(DinoState, DINO_PCI_HOST_BRIDGE,
+                         TYPE_DINO_PCI_HOST_BRIDGE)
 
 #define DINO800_REGS (1 + (DINO_TLTIM - DINO_GMASK) / 4)
 static const uint32_t reg800_keep_bits[DINO800_REGS] = {
@@ -100,7 +102,7 @@ static const uint32_t reg800_keep_bits[DINO800_REGS] = {
     MAKE_64BIT_MASK(0, 9),  /* TLTIM */
 };
 
-typedef struct DinoState {
+struct DinoState {
     PCIHostState parent_obj;
 
     /* PCI_CONFIG_ADDR is parent_obj.config_reg, via pci_host_conf_be_ops,
@@ -129,7 +131,7 @@ typedef struct DinoState {
     MemoryRegion bm_ram_alias;
     MemoryRegion bm_pci_alias;
     MemoryRegion bm_cpu_alias;
-} DinoState;
+};
 
 /*
  * Dino can forward memory accesses from the CPU in the range between
diff --git a/hw/hppa/lasi.c b/hw/hppa/lasi.c
index 194aa3e619..c0b970f55c 100644
--- a/hw/hppa/lasi.c
+++ b/hw/hppa/lasi.c
@@ -26,6 +26,7 @@
 #include "hw/input/lasips2.h"
 #include "exec/address-spaces.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 #define TYPE_LASI_CHIP "lasi-chip"
 
@@ -52,10 +53,11 @@
 #define ICR_BUS_ERROR_BIT  LASI_BIT(8)  /* bit 8 in ICR */
 #define ICR_TOC_BIT        LASI_BIT(1)  /* bit 1 in ICR */
 
-#define LASI_CHIP(obj) \
-    OBJECT_CHECK(LasiState, (obj), TYPE_LASI_CHIP)
+typedef struct LasiState LasiState;
+DECLARE_INSTANCE_CHECKER(LasiState, LASI_CHIP,
+                         TYPE_LASI_CHIP)
 
-typedef struct LasiState {
+struct LasiState {
     PCIHostState parent_obj;
 
     uint32_t irr;
@@ -70,7 +72,7 @@ typedef struct LasiState {
     time_t rtc_ref;
 
     MemoryRegion this_mem;
-} LasiState;
+};
 
 static bool lasi_chip_mem_valid(void *opaque, hwaddr addr,
                                 unsigned size, bool is_write,
diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
index 844d00776d..aa5a2a9bd8 100644
--- a/hw/hyperv/hyperv.c
+++ b/hw/hyperv/hyperv.c
@@ -20,8 +20,9 @@
 #include "qemu/rcu.h"
 #include "qemu/rcu_queue.h"
 #include "hw/hyperv/hyperv.h"
+#include "qom/object.h"
 
-typedef struct SynICState {
+struct SynICState {
     DeviceState parent_obj;
 
     CPUState *cs;
@@ -33,10 +34,12 @@ typedef struct SynICState {
     MemoryRegion event_page_mr;
     struct hyperv_message_page *msg_page;
     struct hyperv_event_flags_page *event_page;
-} SynICState;
+};
+typedef struct SynICState SynICState;
 
 #define TYPE_SYNIC "hyperv-synic"
-#define SYNIC(obj) OBJECT_CHECK(SynICState, (obj), TYPE_SYNIC)
+DECLARE_INSTANCE_CHECKER(SynICState, SYNIC,
+                         TYPE_SYNIC)
 
 static bool synic_enabled;
 
diff --git a/hw/hyperv/hyperv_testdev.c b/hw/hyperv/hyperv_testdev.c
index 88a5a63782..f6ee98e00c 100644
--- a/hw/hyperv/hyperv_testdev.c
+++ b/hw/hyperv/hyperv_testdev.c
@@ -17,6 +17,7 @@
 #include "qemu/queue.h"
 #include "hw/isa/isa.h"
 #include "hw/hyperv/hyperv.h"
+#include "qom/object.h"
 
 typedef struct TestSintRoute {
     QLIST_ENTRY(TestSintRoute) le;
@@ -49,8 +50,8 @@ struct HypervTestDev {
 typedef struct HypervTestDev HypervTestDev;
 
 #define TYPE_HYPERV_TEST_DEV "hyperv-testdev"
-#define HYPERV_TEST_DEV(obj) \
-        OBJECT_CHECK(HypervTestDev, (obj), TYPE_HYPERV_TEST_DEV)
+DECLARE_INSTANCE_CHECKER(HypervTestDev, HYPERV_TEST_DEV,
+                         TYPE_HYPERV_TEST_DEV)
 
 enum {
     HV_TEST_DEV_SINT_ROUTE_CREATE = 1,
diff --git a/hw/hyperv/trace-events b/hw/hyperv/trace-events
index ba5bd62d61..b4c35ca8e3 100644
--- a/hw/hyperv/trace-events
+++ b/hw/hyperv/trace-events
@@ -1,4 +1,4 @@
-# vmbus
+# vmbus.c
 vmbus_recv_message(uint32_t type, uint32_t size) "type %d size %d"
 vmbus_signal_event(void) ""
 vmbus_channel_notify_guest(uint32_t chan_id) "channel #%d"
diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c
index 75af6b83dd..6ef895bc35 100644
--- a/hw/hyperv/vmbus.c
+++ b/hw/hyperv/vmbus.c
@@ -380,7 +380,8 @@ static ssize_t gpadl_iter_io(GpadlIter *iter, void *buf, uint32_t len)
             }
         }
 
-        p = (void *)(((uintptr_t)iter->map & TARGET_PAGE_MASK) | off_in_page);
+        p = (void *)(uintptr_t)(((uintptr_t)iter->map & TARGET_PAGE_MASK) |
+                off_in_page);
         if (iter->dir == DMA_DIRECTION_FROM_DEVICE) {
             memcpy(p, buf, cplen);
         } else {
diff --git a/hw/i2c/bitbang_i2c.c b/hw/i2c/bitbang_i2c.c
index b000952b98..c1b9f298d9 100644
--- a/hw/i2c/bitbang_i2c.c
+++ b/hw/i2c/bitbang_i2c.c
@@ -15,6 +15,7 @@
 #include "hw/i2c/bitbang_i2c.h"
 #include "hw/sysbus.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 //#define DEBUG_BITBANG_I2C
 
@@ -162,16 +163,18 @@ void bitbang_i2c_init(bitbang_i2c_interface *s, I2CBus *bus)
 /* GPIO interface.  */
 
 #define TYPE_GPIO_I2C "gpio_i2c"
-#define GPIO_I2C(obj) OBJECT_CHECK(GPIOI2CState, (obj), TYPE_GPIO_I2C)
+typedef struct GPIOI2CState GPIOI2CState;
+DECLARE_INSTANCE_CHECKER(GPIOI2CState, GPIO_I2C,
+                         TYPE_GPIO_I2C)
 
-typedef struct GPIOI2CState {
+struct GPIOI2CState {
     SysBusDevice parent_obj;
 
     MemoryRegion dummy_iomem;
     bitbang_i2c_interface bitbang;
     int last_level;
     qemu_irq out;
-} GPIOI2CState;
+};
 
 static void bitbang_i2c_gpio_set(void *opaque, int irq, int level)
 {
diff --git a/hw/i2c/exynos4210_i2c.c b/hw/i2c/exynos4210_i2c.c
index a600f65560..ff82226e9f 100644
--- a/hw/i2c/exynos4210_i2c.c
+++ b/hw/i2c/exynos4210_i2c.c
@@ -27,14 +27,16 @@
 #include "migration/vmstate.h"
 #include "hw/i2c/i2c.h"
 #include "hw/irq.h"
+#include "qom/object.h"
 
 #ifndef EXYNOS4_I2C_DEBUG
 #define EXYNOS4_I2C_DEBUG                 0
 #endif
 
 #define TYPE_EXYNOS4_I2C                  "exynos4210.i2c"
-#define EXYNOS4_I2C(obj)                  \
-    OBJECT_CHECK(Exynos4210I2CState, (obj), TYPE_EXYNOS4_I2C)
+typedef struct Exynos4210I2CState Exynos4210I2CState;
+DECLARE_INSTANCE_CHECKER(Exynos4210I2CState, EXYNOS4_I2C,
+                         TYPE_EXYNOS4_I2C)
 
 /* Exynos4210 I2C memory map */
 #define EXYNOS4_I2C_MEM_SIZE              0x14
@@ -83,7 +85,7 @@ static const char *exynos4_i2c_get_regname(unsigned offset)
 #define DPRINT(fmt, args...)              do { } while (0)
 #endif
 
-typedef struct Exynos4210I2CState {
+struct Exynos4210I2CState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -96,7 +98,7 @@ typedef struct Exynos4210I2CState {
     uint8_t i2cds;
     uint8_t i2clc;
     bool scl_free;
-} Exynos4210I2CState;
+};
 
 static inline void exynos4210_i2c_raise_interrupt(Exynos4210I2CState *s)
 {
diff --git a/hw/i2c/mpc_i2c.c b/hw/i2c/mpc_i2c.c
index 9a724f3a3e..156a25a8e9 100644
--- a/hw/i2c/mpc_i2c.c
+++ b/hw/i2c/mpc_i2c.c
@@ -24,6 +24,7 @@
 #include "qemu/module.h"
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 /* #define DEBUG_I2C */
 
@@ -36,8 +37,9 @@
 #endif
 
 #define TYPE_MPC_I2C "mpc-i2c"
-#define MPC_I2C(obj) \
-    OBJECT_CHECK(MPCI2CState, (obj), TYPE_MPC_I2C)
+typedef struct MPCI2CState MPCI2CState;
+DECLARE_INSTANCE_CHECKER(MPCI2CState, MPC_I2C,
+                         TYPE_MPC_I2C)
 
 #define MPC_I2C_ADR   0x00
 #define MPC_I2C_FDR   0x04
@@ -70,7 +72,7 @@
 
 #define CYCLE_RESET 0xFF
 
-typedef struct MPCI2CState {
+struct MPCI2CState {
     SysBusDevice parent_obj;
 
     I2CBus *bus;
@@ -84,7 +86,7 @@ typedef struct MPCI2CState {
     uint8_t sr;
     uint8_t dr;
     uint8_t dfssr;
-} MPCI2CState;
+};
 
 static bool mpc_i2c_is_enabled(MPCI2CState *s)
 {
diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c
index b7def9eeb8..c6777844cf 100644
--- a/hw/i2c/smbus_eeprom.c
+++ b/hw/i2c/smbus_eeprom.c
@@ -31,23 +31,25 @@
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
 #include "hw/i2c/smbus_eeprom.h"
+#include "qom/object.h"
 
 //#define DEBUG
 
 #define TYPE_SMBUS_EEPROM "smbus-eeprom"
 
-#define SMBUS_EEPROM(obj) \
-    OBJECT_CHECK(SMBusEEPROMDevice, (obj), TYPE_SMBUS_EEPROM)
+typedef struct SMBusEEPROMDevice SMBusEEPROMDevice;
+DECLARE_INSTANCE_CHECKER(SMBusEEPROMDevice, SMBUS_EEPROM,
+                         TYPE_SMBUS_EEPROM)
 
 #define SMBUS_EEPROM_SIZE 256
 
-typedef struct SMBusEEPROMDevice {
+struct SMBusEEPROMDevice {
     SMBusDevice smbusdev;
     uint8_t data[SMBUS_EEPROM_SIZE];
     uint8_t *init_data;
     uint8_t offset;
     bool accessed;
-} SMBusEEPROMDevice;
+};
 
 static uint8_t eeprom_receive_byte(SMBusDevice *dev)
 {
diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c
index 48f1ff4191..2d4578511d 100644
--- a/hw/i2c/smbus_ich9.c
+++ b/hw/i2c/smbus_ich9.c
@@ -28,17 +28,19 @@
 #include "qemu/module.h"
 
 #include "hw/i386/ich9.h"
+#include "qom/object.h"
 
-#define ICH9_SMB_DEVICE(obj) \
-     OBJECT_CHECK(ICH9SMBState, (obj), TYPE_ICH9_SMB_DEVICE)
+typedef struct ICH9SMBState ICH9SMBState;
+DECLARE_INSTANCE_CHECKER(ICH9SMBState, ICH9_SMB_DEVICE,
+                         TYPE_ICH9_SMB_DEVICE)
 
-typedef struct ICH9SMBState {
+struct ICH9SMBState {
     PCIDevice dev;
 
     bool irq_enabled;
 
     PMSMBus smb;
-} ICH9SMBState;
+};
 
 static bool ich9_vmstate_need_smbus(void *opaque, int version_id)
 {
diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c
index da8cda2ec1..3a04ba3969 100644
--- a/hw/i2c/versatile_i2c.c
+++ b/hw/i2c/versatile_i2c.c
@@ -27,11 +27,12 @@
 #include "hw/registerfields.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
-
-#define VERSATILE_I2C(obj) \
-    OBJECT_CHECK(VersatileI2CState, (obj), TYPE_VERSATILE_I2C)
+#include "qom/object.h"
 
 typedef ArmSbconI2CState VersatileI2CState;
+DECLARE_INSTANCE_CHECKER(VersatileI2CState, VERSATILE_I2C,
+                         TYPE_VERSATILE_I2C)
+
 
 
 REG32(CONTROL_GET, 0)
diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
index e05a4eff5d..fa5feb183c 100644
--- a/hw/i386/amd_iommu.h
+++ b/hw/i386/amd_iommu.h
@@ -23,6 +23,7 @@
 
 #include "hw/pci/pci.h"
 #include "hw/i386/x86-iommu.h"
+#include "qom/object.h"
 
 /* Capability registers */
 #define AMDVI_CAPAB_BAR_LOW           0x04
@@ -296,8 +297,9 @@ struct irte_ga {
 };
 
 #define TYPE_AMD_IOMMU_DEVICE "amd-iommu"
-#define AMD_IOMMU_DEVICE(obj)\
-    OBJECT_CHECK(AMDVIState, (obj), TYPE_AMD_IOMMU_DEVICE)
+typedef struct AMDVIState AMDVIState;
+DECLARE_INSTANCE_CHECKER(AMDVIState, AMD_IOMMU_DEVICE,
+                         TYPE_AMD_IOMMU_DEVICE)
 
 #define TYPE_AMD_IOMMU_PCI "AMDVI-PCI"
 
@@ -310,7 +312,7 @@ typedef struct AMDVIPCIState {
     PCIDevice dev;               /* The PCI device itself        */
 } AMDVIPCIState;
 
-typedef struct AMDVIState {
+struct AMDVIState {
     X86IOMMUState iommu;        /* IOMMU bus device             */
     AMDVIPCIState pci;          /* IOMMU PCI device             */
 
@@ -367,6 +369,6 @@ typedef struct AMDVIState {
 
     /* Interrupt remapping */
     bool ga_enabled;
-} AMDVIState;
+};
 
 #endif
diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c
index 64283358f9..37f47540e5 100644
--- a/hw/i386/kvm/clock.c
+++ b/hw/i386/kvm/clock.c
@@ -29,11 +29,14 @@
 
 #include <linux/kvm.h>
 #include "standard-headers/asm-x86/kvm_para.h"
+#include "qom/object.h"
 
 #define TYPE_KVM_CLOCK "kvmclock"
-#define KVM_CLOCK(obj) OBJECT_CHECK(KVMClockState, (obj), TYPE_KVM_CLOCK)
+typedef struct KVMClockState KVMClockState;
+DECLARE_INSTANCE_CHECKER(KVMClockState, KVM_CLOCK,
+                         TYPE_KVM_CLOCK)
 
-typedef struct KVMClockState {
+struct KVMClockState {
     /*< private >*/
     SysBusDevice busdev;
     /*< public >*/
@@ -50,7 +53,7 @@ typedef struct KVMClockState {
     /* whether the 'clock' value was obtained in a host with
      * reliable KVM_GET_CLOCK */
     bool clock_is_reliable;
-} KVMClockState;
+};
 
 struct pvclock_vcpu_time_info {
     uint32_t   version;
diff --git a/hw/i386/kvm/i8254.c b/hw/i386/kvm/i8254.c
index 876f5aa6fa..e18fd337fa 100644
--- a/hw/i386/kvm/i8254.c
+++ b/hw/i386/kvm/i8254.c
@@ -33,30 +33,30 @@
 #include "hw/timer/i8254.h"
 #include "hw/timer/i8254_internal.h"
 #include "sysemu/kvm.h"
+#include "qom/object.h"
 
 #define KVM_PIT_REINJECT_BIT 0
 
 #define CALIBRATION_ROUNDS   3
 
-#define KVM_PIT(obj) OBJECT_CHECK(KVMPITState, (obj), TYPE_KVM_I8254)
-#define KVM_PIT_CLASS(class) \
-    OBJECT_CLASS_CHECK(KVMPITClass, (class), TYPE_KVM_I8254)
-#define KVM_PIT_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(KVMPITClass, (obj), TYPE_KVM_I8254)
+typedef struct KVMPITClass KVMPITClass;
+typedef struct KVMPITState KVMPITState;
+DECLARE_OBJ_CHECKERS(KVMPITState, KVMPITClass,
+                     KVM_PIT, TYPE_KVM_I8254)
 
-typedef struct KVMPITState {
+struct KVMPITState {
     PITCommonState parent_obj;
 
     LostTickPolicy lost_tick_policy;
     bool vm_stopped;
     int64_t kernel_clock_offset;
-} KVMPITState;
+};
 
-typedef struct KVMPITClass {
+struct KVMPITClass {
     PITCommonClass parent_class;
 
     DeviceRealize parent_realize;
-} KVMPITClass;
+};
 
 static int64_t abs64(int64_t v)
 {
diff --git a/hw/i386/kvm/i8259.c b/hw/i386/kvm/i8259.c
index e404fdcdac..3f8bf69e9c 100644
--- a/hw/i386/kvm/i8259.c
+++ b/hw/i386/kvm/i8259.c
@@ -17,22 +17,22 @@
 #include "hw/i386/apic_internal.h"
 #include "hw/irq.h"
 #include "sysemu/kvm.h"
+#include "qom/object.h"
 
 #define TYPE_KVM_I8259 "kvm-i8259"
-#define KVM_PIC_CLASS(class) \
-    OBJECT_CLASS_CHECK(KVMPICClass, (class), TYPE_KVM_I8259)
-#define KVM_PIC_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(KVMPICClass, (obj), TYPE_KVM_I8259)
+typedef struct KVMPICClass KVMPICClass;
+DECLARE_CLASS_CHECKERS(KVMPICClass, KVM_PIC,
+                       TYPE_KVM_I8259)
 
 /**
  * KVMPICClass:
  * @parent_realize: The parent's realizefn.
  */
-typedef struct KVMPICClass {
+struct KVMPICClass {
     PICCommonClass parent_class;
 
     DeviceRealize parent_realize;
-} KVMPICClass;
+};
 
 static void kvm_pic_get(PICCommonState *s)
 {
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index 51639202c2..a4e05f086e 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -22,6 +22,7 @@
 #include "hw/boards.h"
 #include "migration/vmstate.h"
 #include "tcg/tcg.h"
+#include "qom/object.h"
 
 #define VAPIC_IO_PORT           0x7e
 
@@ -56,7 +57,7 @@ typedef struct GuestROMState {
     VAPICHandlers mp;
 } QEMU_PACKED GuestROMState;
 
-typedef struct VAPICROMState {
+struct VAPICROMState {
     SysBusDevice busdev;
     MemoryRegion io;
     MemoryRegion rom;
@@ -69,10 +70,12 @@ typedef struct VAPICROMState {
     size_t rom_size;
     bool rom_mapped_writable;
     VMChangeStateEntry *vmsentry;
-} VAPICROMState;
+};
+typedef struct VAPICROMState VAPICROMState;
 
 #define TYPE_VAPIC "kvmvapic"
-#define VAPIC(obj) OBJECT_CHECK(VAPICROMState, (obj), TYPE_VAPIC)
+DECLARE_INSTANCE_CHECKER(VAPICROMState, VAPIC,
+                         TYPE_VAPIC)
 
 #define TPR_INSTR_ABS_MODRM             0x1
 #define TPR_INSTR_MATCH_MODRM_REG       0x2
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 32b1453e6a..33fa035fb7 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -930,7 +930,7 @@ void igd_passthrough_isa_bridge_create(PCIBus *bus, uint16_t gpu_dev_id)
     struct PCIDevice *bridge_dev;
     int i, num;
     uint16_t pch_dev_id = 0xffff;
-    uint8_t pch_rev_id;
+    uint8_t pch_rev_id = 0;
 
     num = ARRAY_SIZE(igd_combo_id_infos);
     for (i = 0; i < num; i++) {
diff --git a/hw/i386/port92.c b/hw/i386/port92.c
index 19866c44ef..c00dcb261b 100644
--- a/hw/i386/port92.c
+++ b/hw/i386/port92.c
@@ -12,16 +12,19 @@
 #include "hw/irq.h"
 #include "hw/i386/pc.h"
 #include "trace.h"
+#include "qom/object.h"
 
-#define PORT92(obj) OBJECT_CHECK(Port92State, (obj), TYPE_PORT92)
+typedef struct Port92State Port92State;
+DECLARE_INSTANCE_CHECKER(Port92State, PORT92,
+                         TYPE_PORT92)
 
-typedef struct Port92State {
+struct Port92State {
     ISADevice parent_obj;
 
     MemoryRegion io;
     uint8_t outport;
     qemu_irq a20_out;
-} Port92State;
+};
 
 static void port92_write(void *opaque, hwaddr addr, uint64_t val,
                          unsigned size)
diff --git a/hw/i386/vmmouse.c b/hw/i386/vmmouse.c
index ba5c987bd2..ae4cbc7add 100644
--- a/hw/i386/vmmouse.c
+++ b/hw/i386/vmmouse.c
@@ -30,6 +30,7 @@
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
 #include "cpu.h"
+#include "qom/object.h"
 
 /* debug only vmmouse */
 //#define DEBUG_VMMOUSE
@@ -50,10 +51,11 @@
 #endif
 
 #define TYPE_VMMOUSE "vmmouse"
-#define VMMOUSE(obj) OBJECT_CHECK(VMMouseState, (obj), TYPE_VMMOUSE)
+typedef struct VMMouseState VMMouseState;
+DECLARE_INSTANCE_CHECKER(VMMouseState, VMMOUSE,
+                         TYPE_VMMOUSE)
 
-typedef struct VMMouseState
-{
+struct VMMouseState {
     ISADevice parent_obj;
 
     uint32_t queue[VMMOUSE_QUEUE_SIZE];
@@ -63,7 +65,7 @@ typedef struct VMMouseState
     uint8_t absolute;
     QEMUPutMouseEntry *entry;
     ISAKBDState *i8042;
-} VMMouseState;
+};
 
 static void vmmouse_get_data(uint32_t *data)
 {
diff --git a/hw/i386/vmport.c b/hw/i386/vmport.c
index 89bda9108e..df52b6f903 100644
--- a/hw/i386/vmport.c
+++ b/hw/i386/vmport.c
@@ -38,6 +38,7 @@
 #include "qemu/log.h"
 #include "cpu.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define VMPORT_MAGIC   0x564D5868
 
@@ -62,9 +63,11 @@
 #define VCPU_INFO_LEGACY_X2APIC_BIT     3
 #define VCPU_INFO_RESERVED_BIT          31
 
-#define VMPORT(obj) OBJECT_CHECK(VMPortState, (obj), TYPE_VMPORT)
+typedef struct VMPortState VMPortState;
+DECLARE_INSTANCE_CHECKER(VMPortState, VMPORT,
+                         TYPE_VMPORT)
 
-typedef struct VMPortState {
+struct VMPortState {
     ISADevice parent_obj;
 
     MemoryRegion io;
@@ -75,7 +78,7 @@ typedef struct VMPortState {
     uint8_t vmware_vmx_type;
 
     uint32_t compat_flags;
-} VMPortState;
+};
 
 static VMPortState *port_state;
 
diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c
index a1492fdecd..a8bbe8c833 100644
--- a/hw/i386/xen/xen_platform.c
+++ b/hw/i386/xen/xen_platform.c
@@ -39,6 +39,7 @@
 #include "qemu/module.h"
 
 #include <xenguest.h>
+#include "qom/object.h"
 
 //#define DEBUG_PLATFORM
 
@@ -52,7 +53,7 @@
 
 #define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
 
-typedef struct PCIXenPlatformState {
+struct PCIXenPlatformState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
@@ -67,11 +68,12 @@ typedef struct PCIXenPlatformState {
     /* Log from guest drivers */
     char log_buffer[4096];
     int log_buffer_off;
-} PCIXenPlatformState;
+};
+typedef struct PCIXenPlatformState PCIXenPlatformState;
 
 #define TYPE_XEN_PLATFORM "xen-platform"
-#define XEN_PLATFORM(obj) \
-    OBJECT_CHECK(PCIXenPlatformState, (obj), TYPE_XEN_PLATFORM)
+DECLARE_INSTANCE_CHECKER(PCIXenPlatformState, XEN_PLATFORM,
+                         TYPE_XEN_PLATFORM)
 
 #define XEN_PLATFORM_IOPORT 0x10
 
diff --git a/hw/i386/xen/xen_pvdevice.c b/hw/i386/xen/xen_pvdevice.c
index ee2610c7a0..67f83616d3 100644
--- a/hw/i386/xen/xen_pvdevice.c
+++ b/hw/i386/xen/xen_pvdevice.c
@@ -36,13 +36,15 @@
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define TYPE_XEN_PV_DEVICE  "xen-pvdevice"
 
-#define XEN_PV_DEVICE(obj) \
-     OBJECT_CHECK(XenPVDevice, (obj), TYPE_XEN_PV_DEVICE)
+typedef struct XenPVDevice XenPVDevice;
+DECLARE_INSTANCE_CHECKER(XenPVDevice, XEN_PV_DEVICE,
+                         TYPE_XEN_PV_DEVICE)
 
-typedef struct XenPVDevice {
+struct XenPVDevice {
     /*< private >*/
     PCIDevice       parent_obj;
     /*< public >*/
@@ -51,7 +53,7 @@ typedef struct XenPVDevice {
     uint8_t         revision;
     uint32_t        size;
     MemoryRegion    mmio;
-} XenPVDevice;
+};
 
 static uint64_t xen_pv_mmio_read(void *opaque, hwaddr addr,
                                  unsigned size)
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index b696c6291a..ee1d47ff75 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1819,7 +1819,7 @@ type_init(sysbus_ahci_register_types)
 
 int32_t ahci_get_num_ports(PCIDevice *dev)
 {
-    AHCIPCIState *d = ICH_AHCI(dev);
+    AHCIPCIState *d = ICH9_AHCI(dev);
     AHCIState *ahci = &d->ahci;
 
     return ahci->ports;
@@ -1827,7 +1827,7 @@ int32_t ahci_get_num_ports(PCIDevice *dev)
 
 void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd)
 {
-    AHCIPCIState *d = ICH_AHCI(dev);
+    AHCIPCIState *d = ICH9_AHCI(dev);
     AHCIState *ahci = &d->ahci;
     int i;
 
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index eff3188fff..51cd2f38b7 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -91,14 +91,14 @@ static const VMStateDescription vmstate_ich9_ahci = {
 
 static void pci_ich9_reset(DeviceState *dev)
 {
-    AHCIPCIState *d = ICH_AHCI(dev);
+    AHCIPCIState *d = ICH9_AHCI(dev);
 
     ahci_reset(&d->ahci);
 }
 
 static void pci_ich9_ahci_init(Object *obj)
 {
-    struct AHCIPCIState *d = ICH_AHCI(obj);
+    struct AHCIPCIState *d = ICH9_AHCI(obj);
 
     ahci_init(&d->ahci, DEVICE(obj));
 }
@@ -108,7 +108,7 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
     struct AHCIPCIState *d;
     int sata_cap_offset;
     uint8_t *sata_cap;
-    d = ICH_AHCI(dev);
+    d = ICH9_AHCI(dev);
     int ret;
 
     ahci_realize(&d->ahci, DEVICE(dev), pci_get_address_space(dev), 6);
@@ -154,7 +154,7 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
 static void pci_ich9_uninit(PCIDevice *dev)
 {
     struct AHCIPCIState *d;
-    d = ICH_AHCI(dev);
+    d = ICH9_AHCI(dev);
 
     msi_uninit(dev);
     ahci_uninit(&d->ahci);
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index f28c8fba6c..9a3489691b 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -32,14 +32,17 @@
 #include "sysemu/dma.h"
 
 #include "hw/ide/internal.h"
+#include "qom/object.h"
 
 /***********************************************************/
 /* ISA IDE definitions */
 
 #define TYPE_ISA_IDE "isa-ide"
-#define ISA_IDE(obj) OBJECT_CHECK(ISAIDEState, (obj), TYPE_ISA_IDE)
+typedef struct ISAIDEState ISAIDEState;
+DECLARE_INSTANCE_CHECKER(ISAIDEState, ISA_IDE,
+                         TYPE_ISA_IDE)
 
-typedef struct ISAIDEState {
+struct ISAIDEState {
     ISADevice parent_obj;
 
     IDEBus    bus;
@@ -47,7 +50,7 @@ typedef struct ISAIDEState {
     uint32_t  iobase2;
     uint32_t  isairq;
     qemu_irq  irq;
-} ISAIDEState;
+};
 
 static void isa_ide_reset(DeviceState *d)
 {
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index c4cc0a84eb..6e7f5df901 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -31,9 +31,12 @@
 #include "sysemu/dma.h"
 
 #include "hw/ide/internal.h"
+#include "qom/object.h"
 
 #define TYPE_MICRODRIVE "microdrive"
-#define MICRODRIVE(obj) OBJECT_CHECK(MicroDriveState, (obj), TYPE_MICRODRIVE)
+typedef struct MicroDriveState MicroDriveState;
+DECLARE_INSTANCE_CHECKER(MicroDriveState, MICRODRIVE,
+                         TYPE_MICRODRIVE)
 
 /***********************************************************/
 /* CF-ATA Microdrive */
@@ -42,7 +45,7 @@
 
 /* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface.  */
 
-typedef struct MicroDriveState {
+struct MicroDriveState {
     /*< private >*/
     PCMCIACardState parent_obj;
     /*< public >*/
@@ -59,7 +62,7 @@ typedef struct MicroDriveState {
     uint8_t ctrl;
     uint16_t io;
     uint8_t cycle;
-} MicroDriveState;
+};
 
 /* Register bitfields */
 enum md_opt {
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index d233bd8c01..4bf6e3a8b7 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -31,6 +31,7 @@
 
 #include "hw/ide/internal.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 /***********************************************************/
 /* MMIO based ide port
@@ -39,9 +40,11 @@
  */
 
 #define TYPE_MMIO_IDE "mmio-ide"
-#define MMIO_IDE(obj) OBJECT_CHECK(MMIOState, (obj), TYPE_MMIO_IDE)
+typedef struct MMIOIDEState MMIOState;
+DECLARE_INSTANCE_CHECKER(MMIOState, MMIO_IDE,
+                         TYPE_MMIO_IDE)
 
-typedef struct MMIOIDEState {
+struct MMIOIDEState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -51,7 +54,7 @@ typedef struct MMIOIDEState {
     uint32_t shift;
     qemu_irq irq;
     MemoryRegion iomem1, iomem2;
-} MMIOState;
+};
 
 static void mmio_ide_reset(DeviceState *dev)
 {
diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c
index 94d2b57f95..968c239ab8 100644
--- a/hw/ide/sii3112.c
+++ b/hw/ide/sii3112.c
@@ -16,9 +16,11 @@
 #include "hw/ide/pci.h"
 #include "qemu/module.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define TYPE_SII3112_PCI "sii3112"
-#define SII3112_PCI(obj) OBJECT_CHECK(SiI3112PCIState, (obj), \
+typedef struct SiI3112PCIState SiI3112PCIState;
+DECLARE_INSTANCE_CHECKER(SiI3112PCIState, SII3112_PCI,
                          TYPE_SII3112_PCI)
 
 typedef struct SiI3112Regs {
@@ -28,11 +30,11 @@ typedef struct SiI3112Regs {
     uint8_t swdata;
 } SiI3112Regs;
 
-typedef struct SiI3112PCIState {
+struct SiI3112PCIState {
     PCIIDEState i;
     MemoryRegion mmio;
     SiI3112Regs regs[2];
-} SiI3112PCIState;
+};
 
 /* The sii3112_reg_read and sii3112_reg_write functions implement the
  * Internal Register Space - BAR5 (section 6.7 of the data sheet).
diff --git a/hw/input/adb-kbd.c b/hw/input/adb-kbd.c
index 3cfb6a7a20..fe0c363d64 100644
--- a/hw/input/adb-kbd.c
+++ b/hw/input/adb-kbd.c
@@ -30,30 +30,30 @@
 #include "hw/input/adb-keys.h"
 #include "adb-internal.h"
 #include "trace.h"
+#include "qom/object.h"
 
-#define ADB_KEYBOARD(obj) OBJECT_CHECK(KBDState, (obj), TYPE_ADB_KEYBOARD)
+typedef struct ADBKeyboardClass ADBKeyboardClass;
+typedef struct KBDState KBDState;
+DECLARE_OBJ_CHECKERS(KBDState, ADBKeyboardClass,
+                     ADB_KEYBOARD, TYPE_ADB_KEYBOARD)
 
-typedef struct KBDState {
+struct KBDState {
     /*< private >*/
     ADBDevice parent_obj;
     /*< public >*/
 
     uint8_t data[128];
     int rptr, wptr, count;
-} KBDState;
+};
 
-#define ADB_KEYBOARD_CLASS(class) \
-    OBJECT_CLASS_CHECK(ADBKeyboardClass, (class), TYPE_ADB_KEYBOARD)
-#define ADB_KEYBOARD_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(ADBKeyboardClass, (obj), TYPE_ADB_KEYBOARD)
 
-typedef struct ADBKeyboardClass {
+struct ADBKeyboardClass {
     /*< private >*/
     ADBDeviceClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
-} ADBKeyboardClass;
+};
 
 /* The adb keyboard doesn't have every key imaginable */
 #define NO_KEY 0xff
diff --git a/hw/input/adb-mouse.c b/hw/input/adb-mouse.c
index 577a38ff2e..f5750909b4 100644
--- a/hw/input/adb-mouse.c
+++ b/hw/input/adb-mouse.c
@@ -29,30 +29,30 @@
 #include "qemu/module.h"
 #include "adb-internal.h"
 #include "trace.h"
+#include "qom/object.h"
 
-#define ADB_MOUSE(obj) OBJECT_CHECK(MouseState, (obj), TYPE_ADB_MOUSE)
+typedef struct ADBMouseClass ADBMouseClass;
+typedef struct MouseState MouseState;
+DECLARE_OBJ_CHECKERS(MouseState, ADBMouseClass,
+                     ADB_MOUSE, TYPE_ADB_MOUSE)
 
-typedef struct MouseState {
+struct MouseState {
     /*< public >*/
     ADBDevice parent_obj;
     /*< private >*/
 
     int buttons_state, last_buttons_state;
     int dx, dy, dz;
-} MouseState;
+};
 
-#define ADB_MOUSE_CLASS(class) \
-    OBJECT_CLASS_CHECK(ADBMouseClass, (class), TYPE_ADB_MOUSE)
-#define ADB_MOUSE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(ADBMouseClass, (obj), TYPE_ADB_MOUSE)
 
-typedef struct ADBMouseClass {
+struct ADBMouseClass {
     /*< public >*/
     ADBDeviceClass parent_class;
     /*< private >*/
 
     DeviceRealize parent_realize;
-} ADBMouseClass;
+};
 
 static void adb_mouse_event(void *opaque,
                             int dx1, int dy1, int dz1, int buttons_state)
diff --git a/hw/input/lm832x.c b/hw/input/lm832x.c
index aa629ddbf1..70245fd817 100644
--- a/hw/input/lm832x.c
+++ b/hw/input/lm832x.c
@@ -25,11 +25,14 @@
 #include "qemu/module.h"
 #include "qemu/timer.h"
 #include "ui/console.h"
+#include "qom/object.h"
 
 #define TYPE_LM8323 "lm8323"
-#define LM8323(obj) OBJECT_CHECK(LM823KbdState, (obj), TYPE_LM8323)
+typedef struct LM823KbdState LM823KbdState;
+DECLARE_INSTANCE_CHECKER(LM823KbdState, LM8323,
+                         TYPE_LM8323)
 
-typedef struct {
+struct LM823KbdState {
     I2CSlave parent_obj;
 
     uint8_t i2c_dir;
@@ -72,7 +75,7 @@ typedef struct {
         uint8_t addr[3];
         QEMUTimer *tm[3];
     } pwm;
-} LM823KbdState;
+};
 
 #define INT_KEYPAD		(1 << 0)
 #define INT_ERROR		(1 << 3)
diff --git a/hw/input/milkymist-softusb.c b/hw/input/milkymist-softusb.c
index 3e0a7eb0bd..eaaf8adde4 100644
--- a/hw/input/milkymist-softusb.c
+++ b/hw/input/milkymist-softusb.c
@@ -32,6 +32,7 @@
 #include "hw/qdev-properties.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 enum {
     R_CTRL = 0,
@@ -50,8 +51,9 @@ enum {
 #define COMLOC_KEVT_BASE     0x1143
 
 #define TYPE_MILKYMIST_SOFTUSB "milkymist-softusb"
-#define MILKYMIST_SOFTUSB(obj) \
-    OBJECT_CHECK(MilkymistSoftUsbState, (obj), TYPE_MILKYMIST_SOFTUSB)
+typedef struct MilkymistSoftUsbState MilkymistSoftUsbState;
+DECLARE_INSTANCE_CHECKER(MilkymistSoftUsbState, MILKYMIST_SOFTUSB,
+                         TYPE_MILKYMIST_SOFTUSB)
 
 struct MilkymistSoftUsbState {
     SysBusDevice parent_obj;
@@ -80,7 +82,6 @@ struct MilkymistSoftUsbState {
     /* keyboard state */
     uint8_t kbd_hid_buffer[8];
 };
-typedef struct MilkymistSoftUsbState MilkymistSoftUsbState;
 
 static uint64_t softusb_read(void *opaque, hwaddr addr,
                              unsigned size)
diff --git a/hw/input/pl050.c b/hw/input/pl050.c
index 1123037b38..7c53ae97da 100644
--- a/hw/input/pl050.c
+++ b/hw/input/pl050.c
@@ -14,11 +14,14 @@
 #include "hw/irq.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define TYPE_PL050 "pl050"
-#define PL050(obj) OBJECT_CHECK(PL050State, (obj), TYPE_PL050)
+typedef struct PL050State PL050State;
+DECLARE_INSTANCE_CHECKER(PL050State, PL050,
+                         TYPE_PL050)
 
-typedef struct PL050State {
+struct PL050State {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -29,7 +32,7 @@ typedef struct PL050State {
     int pending;
     qemu_irq irq;
     bool is_mouse;
-} PL050State;
+};
 
 static const VMStateDescription vmstate_pl050 = {
     .name = "pl050",
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index 38aabd60cd..b6a05e5439 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -28,6 +28,7 @@
 #include "trace.h"
 #include "hw/i386/apic-msidef.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 #define MAX_APICS 255
 #define MAX_APIC_WORDS 8
@@ -39,8 +40,9 @@
 static APICCommonState *local_apics[MAX_APICS + 1];
 
 #define TYPE_APIC "apic"
-#define APIC(obj) \
-    OBJECT_CHECK(APICCommonState, (obj), TYPE_APIC)
+/*This is reusing the APICCommonState typedef from APIC_COMMON */
+DECLARE_INSTANCE_CHECKER(APICCommonState, APIC,
+                         TYPE_APIC)
 
 static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode);
 static void apic_update_irq(APICCommonState *s);
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index 07b95143c9..9494185cf4 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -29,20 +29,19 @@
 #include "kvm_arm.h"
 #include "gic_internal.h"
 #include "vgic_common.h"
+#include "qom/object.h"
 
 #define TYPE_KVM_ARM_GIC "kvm-arm-gic"
-#define KVM_ARM_GIC(obj) \
-     OBJECT_CHECK(GICState, (obj), TYPE_KVM_ARM_GIC)
-#define KVM_ARM_GIC_CLASS(klass) \
-     OBJECT_CLASS_CHECK(KVMARMGICClass, (klass), TYPE_KVM_ARM_GIC)
-#define KVM_ARM_GIC_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(KVMARMGICClass, (obj), TYPE_KVM_ARM_GIC)
-
-typedef struct KVMARMGICClass {
+typedef struct KVMARMGICClass KVMARMGICClass;
+/* This is reusing the GICState typedef from ARM_GIC_COMMON */
+DECLARE_OBJ_CHECKERS(GICState, KVMARMGICClass,
+                     KVM_ARM_GIC, TYPE_KVM_ARM_GIC)
+
+struct KVMARMGICClass {
     ARMGICCommonClass parent_class;
     DeviceRealize parent_realize;
     void (*parent_reset)(DeviceState *dev);
-} KVMARMGICClass;
+};
 
 void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level)
 {
diff --git a/hw/intc/arm_gicv2m.c b/hw/intc/arm_gicv2m.c
index 0b7e2b4f84..04d7a6d68b 100644
--- a/hw/intc/arm_gicv2m.c
+++ b/hw/intc/arm_gicv2m.c
@@ -34,9 +34,12 @@
 #include "sysemu/kvm.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define TYPE_ARM_GICV2M "arm-gicv2m"
-#define ARM_GICV2M(obj) OBJECT_CHECK(ARMGICv2mState, (obj), TYPE_ARM_GICV2M)
+typedef struct ARMGICv2mState ARMGICv2mState;
+DECLARE_INSTANCE_CHECKER(ARMGICv2mState, ARM_GICV2M,
+                         TYPE_ARM_GICV2M)
 
 #define GICV2M_NUM_SPI_MAX 128
 
@@ -48,7 +51,7 @@
 
 #define PRODUCT_ID_QEMU         0x51 /* ASCII code Q */
 
-typedef struct ARMGICv2mState {
+struct ARMGICv2mState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -56,7 +59,7 @@ typedef struct ARMGICv2mState {
 
     uint32_t base_spi;
     uint32_t num_spi;
-} ARMGICv2mState;
+};
 
 static void gicv2m_set_irq(void *opaque, int irq)
 {
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
index 46835ed085..4ee9875ecc 100644
--- a/hw/intc/arm_gicv3_its_kvm.c
+++ b/hw/intc/arm_gicv3_its_kvm.c
@@ -27,18 +27,18 @@
 #include "sysemu/kvm.h"
 #include "kvm_arm.h"
 #include "migration/blocker.h"
+#include "qom/object.h"
 
 #define TYPE_KVM_ARM_ITS "arm-its-kvm"
-#define KVM_ARM_ITS(obj) OBJECT_CHECK(GICv3ITSState, (obj), TYPE_KVM_ARM_ITS)
-#define KVM_ARM_ITS_CLASS(klass) \
-     OBJECT_CLASS_CHECK(KVMARMITSClass, (klass), TYPE_KVM_ARM_ITS)
-#define KVM_ARM_ITS_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(KVMARMITSClass, (obj), TYPE_KVM_ARM_ITS)
+typedef struct KVMARMITSClass KVMARMITSClass;
+/* This is reusing the GICv3ITSState typedef from ARM_GICV3_ITS_COMMON */
+DECLARE_OBJ_CHECKERS(GICv3ITSState, KVMARMITSClass,
+                     KVM_ARM_ITS, TYPE_KVM_ARM_ITS)
 
-typedef struct KVMARMITSClass {
+struct KVMARMITSClass {
     GICv3ITSCommonClass parent_class;
     void (*parent_reset)(DeviceState *dev);
-} KVMARMITSClass;
+};
 
 
 static int kvm_its_send_msi(GICv3ITSState *s, uint32_t value, uint16_t devid)
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index eddd07c743..187eb054e0 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -31,6 +31,7 @@
 #include "gicv3_internal.h"
 #include "vgic_common.h"
 #include "migration/blocker.h"
+#include "qom/object.h"
 
 #ifdef DEBUG_GICV3_KVM
 #define DPRINTF(fmt, ...) \
@@ -41,12 +42,10 @@
 #endif
 
 #define TYPE_KVM_ARM_GICV3 "kvm-arm-gicv3"
-#define KVM_ARM_GICV3(obj) \
-     OBJECT_CHECK(GICv3State, (obj), TYPE_KVM_ARM_GICV3)
-#define KVM_ARM_GICV3_CLASS(klass) \
-     OBJECT_CLASS_CHECK(KVMARMGICv3Class, (klass), TYPE_KVM_ARM_GICV3)
-#define KVM_ARM_GICV3_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(KVMARMGICv3Class, (obj), TYPE_KVM_ARM_GICV3)
+typedef struct KVMARMGICv3Class KVMARMGICv3Class;
+/* This is reusing the GICv3State typedef from ARM_GICV3_ITS_COMMON */
+DECLARE_OBJ_CHECKERS(GICv3State, KVMARMGICv3Class,
+                     KVM_ARM_GICV3, TYPE_KVM_ARM_GICV3)
 
 #define   KVM_DEV_ARM_VGIC_SYSREG(op0, op1, crn, crm, op2)         \
                              (ARM64_SYS_REG_SHIFT_MASK(op0, OP0) | \
@@ -74,11 +73,11 @@
 #define ICC_IGRPEN1_EL1 \
     KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 7)
 
-typedef struct KVMARMGICv3Class {
+struct KVMARMGICv3Class {
     ARMGICv3CommonClass parent_class;
     DeviceRealize parent_realize;
     void (*parent_reset)(DeviceState *dev);
-} KVMARMGICv3Class;
+};
 
 static void kvm_arm_gicv3_set_irq(void *opaque, int irq, int level)
 {
diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c
index 12988c7aa9..54ed4c77f7 100644
--- a/hw/intc/etraxfs_pic.c
+++ b/hw/intc/etraxfs_pic.c
@@ -27,6 +27,7 @@
 #include "qemu/module.h"
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 #define D(x)
 
@@ -38,8 +39,8 @@
 #define R_MAX       5
 
 #define TYPE_ETRAX_FS_PIC "etraxfs,pic"
-#define ETRAX_FS_PIC(obj) \
-    OBJECT_CHECK(struct etrax_pic, (obj), TYPE_ETRAX_FS_PIC)
+DECLARE_INSTANCE_CHECKER(struct etrax_pic, ETRAX_FS_PIC,
+                         TYPE_ETRAX_FS_PIC)
 
 struct etrax_pic
 {
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
index 59dd27fb16..7b01481ab8 100644
--- a/hw/intc/exynos4210_combiner.c
+++ b/hw/intc/exynos4210_combiner.c
@@ -36,6 +36,7 @@
 #include "hw/hw.h"
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 //#define DEBUG_COMBINER
 
@@ -63,10 +64,11 @@ typedef struct CombinerGroupState {
 } CombinerGroupState;
 
 #define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
-#define EXYNOS4210_COMBINER(obj) \
-    OBJECT_CHECK(Exynos4210CombinerState, (obj), TYPE_EXYNOS4210_COMBINER)
+typedef struct Exynos4210CombinerState Exynos4210CombinerState;
+DECLARE_INSTANCE_CHECKER(Exynos4210CombinerState, EXYNOS4210_COMBINER,
+                         TYPE_EXYNOS4210_COMBINER)
 
-typedef struct Exynos4210CombinerState {
+struct Exynos4210CombinerState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -77,7 +79,7 @@ typedef struct Exynos4210CombinerState {
     uint32_t external;          /* 1 means that this combiner is external */
 
     qemu_irq output_irq[IIC_NGRP];
-} Exynos4210CombinerState;
+};
 
 static const VMStateDescription vmstate_exynos4210_combiner_group_state = {
     .name = "exynos4210.combiner.groupstate",
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
index 0aa3b843a9..f9487673fc 100644
--- a/hw/intc/exynos4210_gic.c
+++ b/hw/intc/exynos4210_gic.c
@@ -28,6 +28,7 @@
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
 #include "hw/arm/exynos4210.h"
+#include "qom/object.h"
 
 enum ExtGicId {
     EXT_GIC_ID_MDMA_LCD0 = 66,
@@ -264,10 +265,11 @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
 /********* GIC part *********/
 
 #define TYPE_EXYNOS4210_GIC "exynos4210.gic"
-#define EXYNOS4210_GIC(obj) \
-    OBJECT_CHECK(Exynos4210GicState, (obj), TYPE_EXYNOS4210_GIC)
+typedef struct Exynos4210GicState Exynos4210GicState;
+DECLARE_INSTANCE_CHECKER(Exynos4210GicState, EXYNOS4210_GIC,
+                         TYPE_EXYNOS4210_GIC)
 
-typedef struct {
+struct Exynos4210GicState {
     SysBusDevice parent_obj;
 
     MemoryRegion cpu_container;
@@ -276,7 +278,7 @@ typedef struct {
     MemoryRegion dist_alias[EXYNOS4210_NCPUS];
     uint32_t num_cpu;
     DeviceState *gic;
-} Exynos4210GicState;
+};
 
 static void exynos4210_gic_set_irq(void *opaque, int irq, int level)
 {
@@ -382,16 +384,17 @@ type_init(exynos4210_gic_register_types)
  */
 
 #define TYPE_EXYNOS4210_IRQ_GATE "exynos4210.irq_gate"
-#define EXYNOS4210_IRQ_GATE(obj) \
-    OBJECT_CHECK(Exynos4210IRQGateState, (obj), TYPE_EXYNOS4210_IRQ_GATE)
+typedef struct Exynos4210IRQGateState Exynos4210IRQGateState;
+DECLARE_INSTANCE_CHECKER(Exynos4210IRQGateState, EXYNOS4210_IRQ_GATE,
+                         TYPE_EXYNOS4210_IRQ_GATE)
 
-typedef struct Exynos4210IRQGateState {
+struct Exynos4210IRQGateState {
     SysBusDevice parent_obj;
 
     uint32_t n_in;      /* inputs amount */
     uint32_t *level;    /* input levels */
     qemu_irq out;       /* output IRQ */
-} Exynos4210IRQGateState;
+};
 
 static Property exynos4210_irq_gate_properties[] = {
     DEFINE_PROP_UINT32("n_in", Exynos4210IRQGateState, n_in, 1),
diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c
index 794c643af2..9b34a8ae03 100644
--- a/hw/intc/grlib_irqmp.c
+++ b/hw/intc/grlib_irqmp.c
@@ -35,6 +35,7 @@
 #include "trace.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define IRQMP_MAX_CPU 16
 #define IRQMP_REG_SIZE 256      /* Size of memory mapped registers */
@@ -50,18 +51,20 @@
 #define FORCE_OFFSET     0x80
 #define EXTENDED_OFFSET  0xC0
 
-#define GRLIB_IRQMP(obj) OBJECT_CHECK(IRQMP, (obj), TYPE_GRLIB_IRQMP)
+typedef struct IRQMP IRQMP;
+DECLARE_INSTANCE_CHECKER(IRQMP, GRLIB_IRQMP,
+                         TYPE_GRLIB_IRQMP)
 
 typedef struct IRQMPState IRQMPState;
 
-typedef struct IRQMP {
+struct IRQMP {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
 
     IRQMPState *state;
     qemu_irq irq;
-} IRQMP;
+};
 
 struct IRQMPState {
     uint32_t level;
diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c
index 51b27f6a34..344fd04db1 100644
--- a/hw/intc/i8259.c
+++ b/hw/intc/i8259.c
@@ -30,6 +30,7 @@
 #include "qemu/log.h"
 #include "hw/isa/i8259_internal.h"
 #include "trace.h"
+#include "qom/object.h"
 
 /* debug PIC */
 //#define DEBUG_PIC
@@ -37,18 +38,19 @@
 //#define DEBUG_IRQ_LATENCY
 
 #define TYPE_I8259 "isa-i8259"
-#define PIC_CLASS(class) OBJECT_CLASS_CHECK(PICClass, (class), TYPE_I8259)
-#define PIC_GET_CLASS(obj) OBJECT_GET_CLASS(PICClass, (obj), TYPE_I8259)
+typedef struct PICClass PICClass;
+DECLARE_CLASS_CHECKERS(PICClass, PIC,
+                       TYPE_I8259)
 
 /**
  * PICClass:
  * @parent_realize: The parent's realizefn.
  */
-typedef struct PICClass {
+struct PICClass {
     PICCommonClass parent_class;
 
     DeviceRealize parent_realize;
-} PICClass;
+};
 
 #ifdef DEBUG_IRQ_LATENCY
 static int64_t irq_time[16];
diff --git a/hw/intc/lm32_pic.c b/hw/intc/lm32_pic.c
index 36de670c9e..e8b4015efd 100644
--- a/hw/intc/lm32_pic.c
+++ b/hw/intc/lm32_pic.c
@@ -27,9 +27,12 @@
 #include "hw/lm32/lm32_pic.h"
 #include "hw/intc/intc.h"
 #include "hw/irq.h"
+#include "qom/object.h"
 
 #define TYPE_LM32_PIC "lm32-pic"
-#define LM32_PIC(obj) OBJECT_CHECK(LM32PicState, (obj), TYPE_LM32_PIC)
+typedef struct LM32PicState LM32PicState;
+DECLARE_INSTANCE_CHECKER(LM32PicState, LM32_PIC,
+                         TYPE_LM32_PIC)
 
 struct LM32PicState {
     SysBusDevice parent_obj;
@@ -42,7 +45,6 @@ struct LM32PicState {
     /* statistics */
     uint64_t stats_irq_count[32];
 };
-typedef struct LM32PicState LM32PicState;
 
 static void update_irq(LM32PicState *s)
 {
diff --git a/hw/intc/loongson_liointc.c b/hw/intc/loongson_liointc.c
index 23ca51cc2e..30fb375b72 100644
--- a/hw/intc/loongson_liointc.c
+++ b/hw/intc/loongson_liointc.c
@@ -23,6 +23,7 @@
 #include "qemu/module.h"
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 #define D(x)
 
@@ -43,8 +44,8 @@
 #define R_END                   0x64
 
 #define TYPE_LOONGSON_LIOINTC "loongson.liointc"
-#define LOONGSON_LIOINTC(obj) \
-        OBJECT_CHECK(struct loongson_liointc, (obj), TYPE_LOONGSON_LIOINTC)
+DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
+                         TYPE_LOONGSON_LIOINTC)
 
 struct loongson_liointc {
     SysBusDevice parent_obj;
diff --git a/hw/intc/nios2_iic.c b/hw/intc/nios2_iic.c
index 86d088f9b5..aa26f059a1 100644
--- a/hw/intc/nios2_iic.c
+++ b/hw/intc/nios2_iic.c
@@ -25,16 +25,18 @@
 #include "hw/irq.h"
 #include "hw/sysbus.h"
 #include "cpu.h"
+#include "qom/object.h"
 
 #define TYPE_ALTERA_IIC "altera,iic"
-#define ALTERA_IIC(obj) \
-    OBJECT_CHECK(AlteraIIC, (obj), TYPE_ALTERA_IIC)
+typedef struct AlteraIIC AlteraIIC;
+DECLARE_INSTANCE_CHECKER(AlteraIIC, ALTERA_IIC,
+                         TYPE_ALTERA_IIC)
 
-typedef struct AlteraIIC {
+struct AlteraIIC {
     SysBusDevice  parent_obj;
     void         *cpu;
     qemu_irq      parent_irq;
-} AlteraIIC;
+};
 
 static void update_irq(AlteraIIC *pv)
 {
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
index b8a1d1fd7d..d7183d035e 100644
--- a/hw/intc/omap_intc.c
+++ b/hw/intc/omap_intc.c
@@ -676,7 +676,7 @@ static const TypeInfo omap2_intc_info = {
 static const TypeInfo omap_intc_type_info = {
     .name          = TYPE_OMAP_INTC,
     .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(struct omap_intr_handler_s),
+    .instance_size = sizeof(omap_intr_handler),
     .abstract      = true,
 };
 
diff --git a/hw/intc/ompic.c b/hw/intc/ompic.c
index c354427a61..a8ea621d9e 100644
--- a/hw/intc/ompic.c
+++ b/hw/intc/ompic.c
@@ -15,9 +15,12 @@
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
 #include "exec/memory.h"
+#include "qom/object.h"
 
 #define TYPE_OR1K_OMPIC "or1k-ompic"
-#define OR1K_OMPIC(obj) OBJECT_CHECK(OR1KOMPICState, (obj), TYPE_OR1K_OMPIC)
+typedef struct OR1KOMPICState OR1KOMPICState;
+DECLARE_INSTANCE_CHECKER(OR1KOMPICState, OR1K_OMPIC,
+                         TYPE_OR1K_OMPIC)
 
 #define OMPIC_CTRL_IRQ_ACK  (1 << 31)
 #define OMPIC_CTRL_IRQ_GEN  (1 << 30)
@@ -37,7 +40,6 @@
 #define OMPIC_MAX_CPUS 4 /* Real max is much higher, but dont waste memory */
 #define OMPIC_ADDRSPACE_SZ (OMPIC_MAX_CPUS * 2 * 4) /* 2 32-bit regs per cpu */
 
-typedef struct OR1KOMPICState OR1KOMPICState;
 typedef struct OR1KOMPICCPUState OR1KOMPICCPUState;
 
 struct OR1KOMPICCPUState {
diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c
index e4bf47d885..8c8fbeddfe 100644
--- a/hw/intc/openpic_kvm.c
+++ b/hw/intc/openpic_kvm.c
@@ -35,13 +35,15 @@
 #include "sysemu/kvm.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define GCR_RESET        0x80000000
 
-#define KVM_OPENPIC(obj) \
-    OBJECT_CHECK(KVMOpenPICState, (obj), TYPE_KVM_OPENPIC)
+typedef struct KVMOpenPICState KVMOpenPICState;
+DECLARE_INSTANCE_CHECKER(KVMOpenPICState, KVM_OPENPIC,
+                         TYPE_KVM_OPENPIC)
 
-typedef struct KVMOpenPICState {
+struct KVMOpenPICState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -51,7 +53,7 @@ typedef struct KVMOpenPICState {
     uint32_t fd;
     uint32_t model;
     hwaddr mapped;
-} KVMOpenPICState;
+};
 
 static void kvm_openpic_set_irq(void *opaque, int n_IRQ, int level)
 {
diff --git a/hw/intc/pl190.c b/hw/intc/pl190.c
index e3bd3dd121..ee3206132f 100644
--- a/hw/intc/pl190.c
+++ b/hw/intc/pl190.c
@@ -13,6 +13,7 @@
 #include "migration/vmstate.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 /* The number of virtual priority levels.  16 user vectors plus the
    unvectored IRQ.  Chained interrupts would require an additional level
@@ -21,9 +22,11 @@
 #define PL190_NUM_PRIO 17
 
 #define TYPE_PL190 "pl190"
-#define PL190(obj) OBJECT_CHECK(PL190State, (obj), TYPE_PL190)
+typedef struct PL190State PL190State;
+DECLARE_INSTANCE_CHECKER(PL190State, PL190,
+                         TYPE_PL190)
 
-typedef struct PL190State {
+struct PL190State {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -41,7 +44,7 @@ typedef struct PL190State {
     int prev_prio[PL190_NUM_PRIO];
     qemu_irq irq;
     qemu_irq fiq;
-} PL190State;
+};
 
 static const unsigned char pl190_id[] =
 { 0x90, 0x11, 0x04, 0x00, 0x0D, 0xf0, 0x05, 0xb1 };
diff --git a/hw/intc/puv3_intc.c b/hw/intc/puv3_intc.c
index 090d4839d1..8bceede256 100644
--- a/hw/intc/puv3_intc.c
+++ b/hw/intc/puv3_intc.c
@@ -12,6 +12,7 @@
 #include "qemu/osdep.h"
 #include "hw/irq.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #undef DEBUG_PUV3
 #include "hw/unicore32/puv3.h"
@@ -19,9 +20,11 @@
 #include "qemu/log.h"
 
 #define TYPE_PUV3_INTC "puv3_intc"
-#define PUV3_INTC(obj) OBJECT_CHECK(PUV3INTCState, (obj), TYPE_PUV3_INTC)
+typedef struct PUV3INTCState PUV3INTCState;
+DECLARE_INSTANCE_CHECKER(PUV3INTCState, PUV3_INTC,
+                         TYPE_PUV3_INTC)
 
-typedef struct PUV3INTCState {
+struct PUV3INTCState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -29,7 +32,7 @@ typedef struct PUV3INTCState {
 
     uint32_t reg_ICMR;
     uint32_t reg_ICPR;
-} PUV3INTCState;
+};
 
 /* Update interrupt status after enabled or pending bits have been changed.  */
 static void puv3_intc_update(PUV3INTCState *s)
diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
index dbd4e682ce..35d91afa55 100644
--- a/hw/intc/s390_flic_kvm.c
+++ b/hw/intc/s390_flic_kvm.c
@@ -24,6 +24,7 @@
 #include "hw/s390x/css.h"
 #include "migration/qemu-file-types.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define FLIC_SAVE_INITIAL_SIZE qemu_real_host_page_size
 #define FLIC_FAILED (-1UL)
@@ -569,16 +570,15 @@ static const VMStateDescription kvm_s390_flic_vmstate = {
     }
 };
 
-typedef struct KVMS390FLICStateClass {
+struct KVMS390FLICStateClass {
     S390FLICStateClass parent_class;
     DeviceRealize parent_realize;
-} KVMS390FLICStateClass;
+};
+typedef struct KVMS390FLICStateClass KVMS390FLICStateClass;
 
-#define KVM_S390_FLIC_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(KVMS390FLICStateClass, (obj), TYPE_KVM_S390_FLIC)
+DECLARE_CLASS_CHECKERS(KVMS390FLICStateClass, KVM_S390_FLIC,
+                       TYPE_KVM_S390_FLIC)
 
-#define KVM_S390_FLIC_CLASS(klass) \
-    OBJECT_CLASS_CHECK(KVMS390FLICStateClass, (klass), TYPE_KVM_S390_FLIC)
 
 static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
 {
diff --git a/hw/intc/slavio_intctl.c b/hw/intc/slavio_intctl.c
index c4cf9096eb..4a72ef5d0d 100644
--- a/hw/intc/slavio_intctl.c
+++ b/hw/intc/slavio_intctl.c
@@ -30,6 +30,7 @@
 #include "hw/intc/intc.h"
 #include "hw/irq.h"
 #include "trace.h"
+#include "qom/object.h"
 
 //#define DEBUG_IRQ_COUNT
 
@@ -58,10 +59,11 @@ typedef struct SLAVIO_CPUINTCTLState {
 } SLAVIO_CPUINTCTLState;
 
 #define TYPE_SLAVIO_INTCTL "slavio_intctl"
-#define SLAVIO_INTCTL(obj) \
-    OBJECT_CHECK(SLAVIO_INTCTLState, (obj), TYPE_SLAVIO_INTCTL)
+typedef struct SLAVIO_INTCTLState SLAVIO_INTCTLState;
+DECLARE_INSTANCE_CHECKER(SLAVIO_INTCTLState, SLAVIO_INTCTL,
+                         TYPE_SLAVIO_INTCTL)
 
-typedef struct SLAVIO_INTCTLState {
+struct SLAVIO_INTCTLState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -73,7 +75,7 @@ typedef struct SLAVIO_INTCTLState {
     uint32_t intregm_pending;
     uint32_t intregm_disabled;
     uint32_t target_cpu;
-} SLAVIO_INTCTLState;
+};
 
 #define INTCTL_MAXADDR 0xf
 #define INTCTL_SIZE (INTCTL_MAXADDR + 1)
diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c
index 3e65e68619..4c4397b3d2 100644
--- a/hw/intc/xilinx_intc.c
+++ b/hw/intc/xilinx_intc.c
@@ -27,6 +27,7 @@
 #include "qemu/module.h"
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 #define D(x)
 
@@ -41,7 +42,8 @@
 #define R_MAX       8
 
 #define TYPE_XILINX_INTC "xlnx.xps-intc"
-#define XILINX_INTC(obj) OBJECT_CHECK(struct xlx_pic, (obj), TYPE_XILINX_INTC)
+DECLARE_INSTANCE_CHECKER(struct xlx_pic, XILINX_INTC,
+                         TYPE_XILINX_INTC)
 
 struct xlx_pic
 {
diff --git a/hw/ipack/tpci200.c b/hw/ipack/tpci200.c
index f931d4df62..b35e1d2ac4 100644
--- a/hw/ipack/tpci200.c
+++ b/hw/ipack/tpci200.c
@@ -16,6 +16,7 @@
 #include "migration/vmstate.h"
 #include "qemu/bitops.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 /* #define DEBUG_TPCI */
 
@@ -54,7 +55,7 @@
 #define REG_STATUS    0x0C
 #define IP_N_FROM_REG(REG) ((REG) / 2 - 1)
 
-typedef struct {
+struct TPCI200State {
     PCIDevice dev;
     IPackBus bus;
     MemoryRegion mmio;
@@ -67,12 +68,13 @@ typedef struct {
     uint8_t ctrl[N_MODULES];
     uint16_t status;
     uint8_t int_set;
-} TPCI200State;
+};
+typedef struct TPCI200State TPCI200State;
 
 #define TYPE_TPCI200 "tpci200"
 
-#define TPCI200(obj) \
-    OBJECT_CHECK(TPCI200State, (obj), TYPE_TPCI200)
+DECLARE_INSTANCE_CHECKER(TPCI200State, TPCI200,
+                         TYPE_TPCI200)
 
 static const uint8_t local_config_regs[] = {
     0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFC, 0xFF, 0x0F, 0x00, 0x00, 0x00,
diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c
index f9a13e0a44..159831cbc5 100644
--- a/hw/ipmi/ipmi_bmc_extern.c
+++ b/hw/ipmi/ipmi_bmc_extern.c
@@ -36,6 +36,7 @@
 #include "hw/ipmi/ipmi.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 #define VM_MSG_CHAR        0xA0 /* Marks end of message */
 #define VM_CMD_CHAR        0xA1 /* Marks end of a command */
@@ -61,9 +62,10 @@
 #define VM_CMD_GRACEFUL_SHUTDOWN   0x09
 
 #define TYPE_IPMI_BMC_EXTERN "ipmi-bmc-extern"
-#define IPMI_BMC_EXTERN(obj) OBJECT_CHECK(IPMIBmcExtern, (obj), \
-                                        TYPE_IPMI_BMC_EXTERN)
-typedef struct IPMIBmcExtern {
+typedef struct IPMIBmcExtern IPMIBmcExtern;
+DECLARE_INSTANCE_CHECKER(IPMIBmcExtern, IPMI_BMC_EXTERN,
+                         TYPE_IPMI_BMC_EXTERN)
+struct IPMIBmcExtern {
     IPMIBmc parent;
 
     CharBackend chr;
@@ -85,7 +87,7 @@ typedef struct IPMIBmcExtern {
 
     /* A reset event is pending to be sent upstream. */
     bool send_reset;
-} IPMIBmcExtern;
+};
 
 static unsigned char
 ipmb_checksum(const unsigned char *data, int size, unsigned char start)
diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c
index c8dc0a09dc..0b69acc2e9 100644
--- a/hw/ipmi/isa_ipmi_bt.c
+++ b/hw/ipmi/isa_ipmi_bt.c
@@ -31,18 +31,20 @@
 #include "hw/isa/isa.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 #define TYPE_ISA_IPMI_BT "isa-ipmi-bt"
-#define ISA_IPMI_BT(obj) OBJECT_CHECK(ISAIPMIBTDevice, (obj), \
-                                      TYPE_ISA_IPMI_BT)
+typedef struct ISAIPMIBTDevice ISAIPMIBTDevice;
+DECLARE_INSTANCE_CHECKER(ISAIPMIBTDevice, ISA_IPMI_BT,
+                         TYPE_ISA_IPMI_BT)
 
-typedef struct ISAIPMIBTDevice {
+struct ISAIPMIBTDevice {
     ISADevice dev;
     int32_t isairq;
     qemu_irq irq;
     IPMIBT bt;
     uint32_t uuid;
-} ISAIPMIBTDevice;
+};
 
 static void isa_ipmi_bt_get_fwinfo(struct IPMIInterface *ii, IPMIFwInfo *info)
 {
diff --git a/hw/ipmi/isa_ipmi_kcs.c b/hw/ipmi/isa_ipmi_kcs.c
index 4b421c33f4..af69e9a008 100644
--- a/hw/ipmi/isa_ipmi_kcs.c
+++ b/hw/ipmi/isa_ipmi_kcs.c
@@ -31,18 +31,20 @@
 #include "hw/isa/isa.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 #define TYPE_ISA_IPMI_KCS "isa-ipmi-kcs"
-#define ISA_IPMI_KCS(obj) OBJECT_CHECK(ISAIPMIKCSDevice, (obj), \
-                                       TYPE_ISA_IPMI_KCS)
+typedef struct ISAIPMIKCSDevice ISAIPMIKCSDevice;
+DECLARE_INSTANCE_CHECKER(ISAIPMIKCSDevice, ISA_IPMI_KCS,
+                         TYPE_ISA_IPMI_KCS)
 
-typedef struct ISAIPMIKCSDevice {
+struct ISAIPMIKCSDevice {
     ISADevice dev;
     int32_t isairq;
     qemu_irq irq;
     IPMIKCS kcs;
     uint32_t uuid;
-} ISAIPMIKCSDevice;
+};
 
 static void isa_ipmi_kcs_get_fwinfo(IPMIInterface *ii, IPMIFwInfo *info)
 {
diff --git a/hw/ipmi/pci_ipmi_bt.c b/hw/ipmi/pci_ipmi_bt.c
index ba9cf016b5..7e5ecea6cc 100644
--- a/hw/ipmi/pci_ipmi_bt.c
+++ b/hw/ipmi/pci_ipmi_bt.c
@@ -26,17 +26,19 @@
 #include "qapi/error.h"
 #include "hw/ipmi/ipmi_bt.h"
 #include "hw/pci/pci.h"
+#include "qom/object.h"
 
 #define TYPE_PCI_IPMI_BT "pci-ipmi-bt"
-#define PCI_IPMI_BT(obj) OBJECT_CHECK(PCIIPMIBTDevice, (obj), \
-                                       TYPE_PCI_IPMI_BT)
+typedef struct PCIIPMIBTDevice PCIIPMIBTDevice;
+DECLARE_INSTANCE_CHECKER(PCIIPMIBTDevice, PCI_IPMI_BT,
+                         TYPE_PCI_IPMI_BT)
 
-typedef struct PCIIPMIBTDevice {
+struct PCIIPMIBTDevice {
     PCIDevice dev;
     IPMIBT bt;
     bool irq_enabled;
     uint32_t uuid;
-} PCIIPMIBTDevice;
+};
 
 static void pci_ipmi_raise_irq(IPMIBT *ik)
 {
diff --git a/hw/ipmi/pci_ipmi_kcs.c b/hw/ipmi/pci_ipmi_kcs.c
index 99f46152f4..c2a283a982 100644
--- a/hw/ipmi/pci_ipmi_kcs.c
+++ b/hw/ipmi/pci_ipmi_kcs.c
@@ -26,17 +26,19 @@
 #include "qapi/error.h"
 #include "hw/ipmi/ipmi_kcs.h"
 #include "hw/pci/pci.h"
+#include "qom/object.h"
 
 #define TYPE_PCI_IPMI_KCS "pci-ipmi-kcs"
-#define PCI_IPMI_KCS(obj) OBJECT_CHECK(PCIIPMIKCSDevice, (obj), \
-                                       TYPE_PCI_IPMI_KCS)
+typedef struct PCIIPMIKCSDevice PCIIPMIKCSDevice;
+DECLARE_INSTANCE_CHECKER(PCIIPMIKCSDevice, PCI_IPMI_KCS,
+                         TYPE_PCI_IPMI_KCS)
 
-typedef struct PCIIPMIKCSDevice {
+struct PCIIPMIKCSDevice {
     PCIDevice dev;
     IPMIKCS kcs;
     bool irq_enabled;
     uint32_t uuid;
-} PCIIPMIKCSDevice;
+};
 
 static void pci_ipmi_raise_irq(IPMIKCS *ik)
 {
diff --git a/hw/ipmi/smbus_ipmi.c b/hw/ipmi/smbus_ipmi.c
index f1a0148755..cd4c05dd1b 100644
--- a/hw/ipmi/smbus_ipmi.c
+++ b/hw/ipmi/smbus_ipmi.c
@@ -27,9 +27,12 @@
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "hw/ipmi/ipmi.h"
+#include "qom/object.h"
 
 #define TYPE_SMBUS_IPMI "smbus-ipmi"
-#define SMBUS_IPMI(obj) OBJECT_CHECK(SMBusIPMIDevice, (obj), TYPE_SMBUS_IPMI)
+typedef struct SMBusIPMIDevice SMBusIPMIDevice;
+DECLARE_INSTANCE_CHECKER(SMBusIPMIDevice, SMBUS_IPMI,
+                         TYPE_SMBUS_IPMI)
 
 #define SSIF_IPMI_REQUEST                       2
 #define SSIF_IPMI_MULTI_PART_REQUEST_START      6
@@ -44,7 +47,7 @@
 
 #define IPMI_GET_SYS_INTF_CAP_CMD 0x57
 
-typedef struct SMBusIPMIDevice {
+struct SMBusIPMIDevice {
     SMBusDevice parent;
 
     IPMIBmc *bmc;
@@ -67,7 +70,7 @@ typedef struct SMBusIPMIDevice {
     uint8_t waiting_rsp;
 
     uint32_t uuid;
-} SMBusIPMIDevice;
+};
 
 static void smbus_ipmi_handle_event(IPMIInterface *ii)
 {
diff --git a/hw/isa/i82378.c b/hw/isa/i82378.c
index 75a2da2881..1dcf525f3f 100644
--- a/hw/isa/i82378.c
+++ b/hw/isa/i82378.c
@@ -24,18 +24,20 @@
 #include "hw/timer/i8254.h"
 #include "migration/vmstate.h"
 #include "hw/audio/pcspk.h"
+#include "qom/object.h"
 
 #define TYPE_I82378 "i82378"
-#define I82378(obj) \
-    OBJECT_CHECK(I82378State, (obj), TYPE_I82378)
+typedef struct I82378State I82378State;
+DECLARE_INSTANCE_CHECKER(I82378State, I82378,
+                         TYPE_I82378)
 
-typedef struct I82378State {
+struct I82378State {
     PCIDevice parent_obj;
 
     qemu_irq out[2];
     qemu_irq *i8259;
     MemoryRegion io;
-} I82378State;
+};
 
 static const VMStateDescription vmstate_i82378 = {
     .name = "pci-i82378",
diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c
index 58fde178f9..10bb7ffa43 100644
--- a/hw/isa/isa-bus.c
+++ b/hw/isa/isa-bus.c
@@ -21,7 +21,6 @@
 #include "qemu/error-report.h"
 #include "qemu/module.h"
 #include "qapi/error.h"
-#include "hw/hw.h"
 #include "monitor/monitor.h"
 #include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
@@ -85,18 +84,14 @@ void isa_bus_irqs(ISABus *bus, qemu_irq *irqs)
 qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq)
 {
     assert(!dev || ISA_BUS(qdev_get_parent_bus(DEVICE(dev))) == isabus);
-    if (isairq >= ISA_NUM_IRQS) {
-        hw_error("isa irq %d invalid", isairq);
-    }
+    assert(isairq < ISA_NUM_IRQS);
     return isabus->irqs[isairq];
 }
 
 void isa_init_irq(ISADevice *dev, qemu_irq *p, unsigned isairq)
 {
     assert(dev->nirqs < ARRAY_SIZE(dev->isairq));
-    if (isairq >= ISA_NUM_IRQS) {
-        hw_error("isa irq %d invalid", isairq);
-    }
+    assert(isairq < ISA_NUM_IRQS);
     dev->isairq[dev->nirqs] = isairq;
     *p = isa_get_irq(dev, isairq);
     dev->nirqs++;
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index cd6e169d47..3303d2eab6 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -792,7 +792,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data)
 static const TypeInfo ich9_lpc_info = {
     .name       = TYPE_ICH9_LPC_DEVICE,
     .parent     = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(struct ICH9LPCState),
+    .instance_size = sizeof(ICH9LPCState),
     .instance_init = ich9_lpc_initfn,
     .class_init  = ich9_lpc_class_init,
     .interfaces = (InterfaceInfo[]) {
diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c
index 0cacbbc91b..8d7b8d3db2 100644
--- a/hw/isa/pc87312.c
+++ b/hw/isa/pc87312.c
@@ -371,7 +371,7 @@ static void pc87312_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo pc87312_type_info = {
-    .name          = TYPE_PC87312_SUPERIO,
+    .name          = TYPE_PC87312,
     .parent        = TYPE_ISA_SUPERIO,
     .instance_size = sizeof(PC87312State),
     .instance_init = pc87312_initfn,
diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c
index ac044afa95..8e3ac845b8 100644
--- a/hw/isa/piix4.c
+++ b/hw/isa/piix4.c
@@ -38,10 +38,11 @@
 #include "migration/vmstate.h"
 #include "sysemu/reset.h"
 #include "sysemu/runstate.h"
+#include "qom/object.h"
 
 PCIDevice *piix4_dev;
 
-typedef struct PIIX4State {
+struct PIIX4State {
     PCIDevice dev;
     qemu_irq cpu_intr;
     qemu_irq *isa;
@@ -50,10 +51,11 @@ typedef struct PIIX4State {
     /* Reset Control Register */
     MemoryRegion rcr_mem;
     uint8_t rcr;
-} PIIX4State;
+};
+typedef struct PIIX4State PIIX4State;
 
-#define PIIX4_PCI_DEVICE(obj) \
-    OBJECT_CHECK(PIIX4State, (obj), TYPE_PIIX4_PCI_DEVICE)
+DECLARE_INSTANCE_CHECKER(PIIX4State, PIIX4_PCI_DEVICE,
+                         TYPE_PIIX4_PCI_DEVICE)
 
 static void piix4_isa_reset(DeviceState *dev)
 {
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index 18160ca445..1e6b48b2a2 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -27,6 +27,7 @@
 #include "qemu/module.h"
 #include "qemu/timer.h"
 #include "exec/address-spaces.h"
+#include "qom/object.h"
 
 /* #define DEBUG_VT82C686B */
 
@@ -42,15 +43,16 @@ typedef struct SuperIOConfig {
     uint8_t data;
 } SuperIOConfig;
 
-typedef struct VT82C686BState {
+struct VT82C686BState {
     PCIDevice dev;
     MemoryRegion superio;
     SuperIOConfig superio_conf;
-} VT82C686BState;
+};
+typedef struct VT82C686BState VT82C686BState;
 
 #define TYPE_VT82C686B_DEVICE "VT82C686B"
-#define VT82C686B_DEVICE(obj) \
-    OBJECT_CHECK(VT82C686BState, (obj), TYPE_VT82C686B_DEVICE)
+DECLARE_INSTANCE_CHECKER(VT82C686BState, VT82C686B_DEVICE,
+                         TYPE_VT82C686B_DEVICE)
 
 static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data,
                                   unsigned size)
@@ -159,34 +161,37 @@ static void vt82c686b_write_config(PCIDevice *d, uint32_t address,
 
 #define ACPI_DBG_IO_ADDR  0xb044
 
-typedef struct VT686PMState {
+struct VT686PMState {
     PCIDevice dev;
     MemoryRegion io;
     ACPIREGS ar;
     APMState apm;
     PMSMBus smb;
     uint32_t smb_io_base;
-} VT686PMState;
+};
+typedef struct VT686PMState VT686PMState;
 
-typedef struct VT686AC97State {
+struct VT686AC97State {
     PCIDevice dev;
-} VT686AC97State;
+};
+typedef struct VT686AC97State VT686AC97State;
 
-typedef struct VT686MC97State {
+struct VT686MC97State {
     PCIDevice dev;
-} VT686MC97State;
+};
+typedef struct VT686MC97State VT686MC97State;
 
 #define TYPE_VT82C686B_PM_DEVICE "VT82C686B_PM"
-#define VT82C686B_PM_DEVICE(obj) \
-    OBJECT_CHECK(VT686PMState, (obj), TYPE_VT82C686B_PM_DEVICE)
+DECLARE_INSTANCE_CHECKER(VT686PMState, VT82C686B_PM_DEVICE,
+                         TYPE_VT82C686B_PM_DEVICE)
 
 #define TYPE_VT82C686B_MC97_DEVICE "VT82C686B_MC97"
-#define VT82C686B_MC97_DEVICE(obj) \
-    OBJECT_CHECK(VT686MC97State, (obj), TYPE_VT82C686B_MC97_DEVICE)
+DECLARE_INSTANCE_CHECKER(VT686MC97State, VT82C686B_MC97_DEVICE,
+                         TYPE_VT82C686B_MC97_DEVICE)
 
 #define TYPE_VT82C686B_AC97_DEVICE "VT82C686B_AC97"
-#define VT82C686B_AC97_DEVICE(obj) \
-    OBJECT_CHECK(VT686AC97State, (obj), TYPE_VT82C686B_AC97_DEVICE)
+DECLARE_INSTANCE_CHECKER(VT686AC97State, VT82C686B_AC97_DEVICE,
+                         TYPE_VT82C686B_AC97_DEVICE)
 
 static void pm_update_sci(VT686PMState *s)
 {
diff --git a/hw/m68k/mcf_intc.c b/hw/m68k/mcf_intc.c
index e01e2e111b..7ee447240b 100644
--- a/hw/m68k/mcf_intc.c
+++ b/hw/m68k/mcf_intc.c
@@ -15,11 +15,14 @@
 #include "hw/irq.h"
 #include "hw/sysbus.h"
 #include "hw/m68k/mcf.h"
+#include "qom/object.h"
 
 #define TYPE_MCF_INTC "mcf-intc"
-#define MCF_INTC(obj) OBJECT_CHECK(mcf_intc_state, (obj), TYPE_MCF_INTC)
+typedef struct mcf_intc_state mcf_intc_state;
+DECLARE_INSTANCE_CHECKER(mcf_intc_state, MCF_INTC,
+                         TYPE_MCF_INTC)
 
-typedef struct {
+struct mcf_intc_state {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -30,7 +33,7 @@ typedef struct {
     uint8_t icr[64];
     M68kCPU *cpu;
     int active_vector;
-} mcf_intc_state;
+};
 
 static void mcf_intc_update(mcf_intc_state *s)
 {
diff --git a/hw/m68k/next-cube.c b/hw/m68k/next-cube.c
index d3f25cd6d7..cbd913b0a2 100644
--- a/hw/m68k/next-cube.c
+++ b/hw/m68k/next-cube.c
@@ -21,6 +21,7 @@
 #include "hw/loader.h"
 #include "hw/scsi/esp.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 #include "hw/char/escc.h" /* ZILOG 8530 Serial Emulation */
 #include "hw/block/fdc.h"
 #include "hw/qdev-properties.h"
@@ -37,7 +38,9 @@
 #endif
 
 #define TYPE_NEXT_MACHINE MACHINE_TYPE_NAME("next-cube")
-#define NEXT_MACHINE(obj) OBJECT_CHECK(NeXTState, (obj), TYPE_NEXT_MACHINE)
+typedef struct NeXTState NeXTState;
+DECLARE_INSTANCE_CHECKER(NeXTState, NEXT_MACHINE,
+                         TYPE_NEXT_MACHINE)
 
 #define ENTRY       0x0100001e
 #define RAM_SIZE    0x4000000
@@ -69,7 +72,7 @@ typedef struct NextRtc {
     uint8_t retval;
 } NextRtc;
 
-typedef struct {
+struct NeXTState {
     MachineState parent;
 
     uint32_t int_mask;
@@ -87,7 +90,7 @@ typedef struct {
     uint32_t scr2;
 
     NextRtc rtc;
-} NeXTState;
+};
 
 /* Thanks to NeXT forums for this */
 /*
diff --git a/hw/m68k/next-kbd.c b/hw/m68k/next-kbd.c
index 2dff87be15..c7ca3fbbc9 100644
--- a/hw/m68k/next-kbd.c
+++ b/hw/m68k/next-kbd.c
@@ -36,8 +36,11 @@
 #include "ui/console.h"
 #include "sysemu/sysemu.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
-#define NEXTKBD(obj) OBJECT_CHECK(NextKBDState, (obj), TYPE_NEXTKBD)
+typedef struct NextKBDState NextKBDState;
+DECLARE_INSTANCE_CHECKER(NextKBDState, NEXTKBD,
+                         TYPE_NEXTKBD)
 
 /* following defintions from next68k netbsd */
 #define CSR_INT 0x00800000
@@ -63,12 +66,12 @@ typedef struct {
 } KBDQueue;
 
 
-typedef struct NextKBDState {
+struct NextKBDState {
     SysBusDevice sbd;
     MemoryRegion mr;
     KBDQueue queue;
     uint16_t shift;
-} NextKBDState;
+};
 
 static void queue_code(void *opaque, int code);
 
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 1ca482ad81..ce4b47c3e3 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -290,7 +290,7 @@ static void q800_init(MachineState *machine)
     /* SCSI */
 
     dev = qdev_new(TYPE_ESP);
-    sysbus_esp = ESP_STATE(dev);
+    sysbus_esp = ESP(dev);
     esp = &sysbus_esp->esp;
     esp->dma_memory_read = NULL;
     esp->dma_memory_write = NULL;
diff --git a/hw/microblaze/xlnx-zynqmp-pmu.c b/hw/microblaze/xlnx-zynqmp-pmu.c
index 5f994547f7..ab9924bf20 100644
--- a/hw/microblaze/xlnx-zynqmp-pmu.c
+++ b/hw/microblaze/xlnx-zynqmp-pmu.c
@@ -24,12 +24,14 @@
 
 #include "hw/intc/xlnx-zynqmp-ipi.h"
 #include "hw/intc/xlnx-pmu-iomod-intc.h"
+#include "qom/object.h"
 
 /* Define the PMU device */
 
 #define TYPE_XLNX_ZYNQMP_PMU_SOC "xlnx,zynqmp-pmu-soc"
-#define XLNX_ZYNQMP_PMU_SOC(obj) OBJECT_CHECK(XlnxZynqMPPMUSoCState, (obj), \
-                                              TYPE_XLNX_ZYNQMP_PMU_SOC)
+typedef struct XlnxZynqMPPMUSoCState XlnxZynqMPPMUSoCState;
+DECLARE_INSTANCE_CHECKER(XlnxZynqMPPMUSoCState, XLNX_ZYNQMP_PMU_SOC,
+                         TYPE_XLNX_ZYNQMP_PMU_SOC)
 
 #define XLNX_ZYNQMP_PMU_ROM_SIZE    0x8000
 #define XLNX_ZYNQMP_PMU_ROM_ADDR    0xFFD00000
@@ -46,7 +48,7 @@ static const uint64_t ipi_irq[XLNX_ZYNQMP_PMU_NUM_IPIS] = {
     19, 20, 21, 22,
 };
 
-typedef struct XlnxZynqMPPMUSoCState {
+struct XlnxZynqMPPMUSoCState {
     /*< private >*/
     DeviceState parent_obj;
 
@@ -54,7 +56,7 @@ typedef struct XlnxZynqMPPMUSoCState {
     MicroBlazeCPU cpu;
     XlnxPMUIOIntc intc;
     XlnxZynqMPIPI ipi[XLNX_ZYNQMP_PMU_NUM_IPIS];
-}  XlnxZynqMPPMUSoCState;
+};
 
 
 static void xlnx_zynqmp_pmu_soc_init(Object *obj)
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
index 766458c015..1b3f69e949 100644
--- a/hw/mips/boston.c
+++ b/hw/mips/boston.c
@@ -41,11 +41,14 @@
 #include "sysemu/runstate.h"
 
 #include <libfdt.h>
+#include "qom/object.h"
 
 #define TYPE_MIPS_BOSTON "mips-boston"
-#define BOSTON(obj) OBJECT_CHECK(BostonState, (obj), TYPE_MIPS_BOSTON)
+typedef struct BostonState BostonState;
+DECLARE_INSTANCE_CHECKER(BostonState, BOSTON,
+                         TYPE_MIPS_BOSTON)
 
-typedef struct {
+struct BostonState {
     SysBusDevice parent_obj;
 
     MachineState *mach;
@@ -58,7 +61,7 @@ typedef struct {
 
     hwaddr kernel_entry;
     hwaddr fdt_base;
-} BostonState;
+};
 
 enum boston_plat_reg {
     PLAT_FPGA_BUILD     = 0x00,
diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c
index 8ca31e5162..f28609976b 100644
--- a/hw/mips/fuloong2e.c
+++ b/hw/mips/fuloong2e.c
@@ -240,10 +240,7 @@ static void vt82c686b_southbridge_init(PCIBus *pci_bus, int slot, qemu_irq intc,
     PCIDevice *dev;
 
     isa_bus = vt82c686b_isa_init(pci_bus, PCI_DEVFN(slot, 0));
-    if (!isa_bus) {
-        fprintf(stderr, "vt82c686b_init error\n");
-        exit(1);
-    }
+    assert(isa_bus);
     *p_isa_bus = isa_bus;
     /* Interrupt controller */
     /* The 8259 -> IP5  */
diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c
index 756ac9ae12..b613e1e011 100644
--- a/hw/mips/gt64xxx_pci.c
+++ b/hw/mips/gt64xxx_pci.c
@@ -35,6 +35,7 @@
 #include "hw/irq.h"
 #include "exec/address-spaces.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define GT_REGS                 (0x1000 >> 2)
 
@@ -230,10 +231,11 @@
 
 #define TYPE_GT64120_PCI_HOST_BRIDGE "gt64120"
 
-#define GT64120_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(GT64120State, (obj), TYPE_GT64120_PCI_HOST_BRIDGE)
+typedef struct GT64120State GT64120State;
+DECLARE_INSTANCE_CHECKER(GT64120State, GT64120_PCI_HOST_BRIDGE,
+                         TYPE_GT64120_PCI_HOST_BRIDGE)
 
-typedef struct GT64120State {
+struct GT64120State {
     PCIHostState parent_obj;
 
     uint32_t regs[GT_REGS];
@@ -243,7 +245,7 @@ typedef struct GT64120State {
     PCI_MAPPING_ENTRY(ISD);
     MemoryRegion pci0_mem;
     AddressSpace pci0_mem_as;
-} GT64120State;
+};
 
 /* Adjust range to avoid touching space which isn't mappable via PCI */
 /*
diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c
index 82a6e3220e..47723093b6 100644
--- a/hw/mips/jazz.c
+++ b/hw/mips/jazz.c
@@ -309,7 +309,7 @@ static void mips_jazz_init(MachineState *machine,
 
     /* SCSI adapter */
     dev = qdev_new(TYPE_ESP);
-    sysbus_esp = ESP_STATE(dev);
+    sysbus_esp = ESP(dev);
     esp = &sysbus_esp->esp;
     esp->dma_memory_read = rc4030_dma_read;
     esp->dma_memory_write = rc4030_dma_write;
diff --git a/hw/mips/malta.c b/hw/mips/malta.c
index a59e20c81c..5b73ea4692 100644
--- a/hw/mips/malta.c
+++ b/hw/mips/malta.c
@@ -45,6 +45,7 @@
 #include "hw/loader.h"
 #include "elf.h"
 #include "exec/address-spaces.h"
+#include "qom/object.h"
 #include "hw/sysbus.h"             /* SysBusDevice */
 #include "qemu/host-utils.h"
 #include "sysemu/qtest.h"
@@ -88,14 +89,16 @@ typedef struct {
 } MaltaFPGAState;
 
 #define TYPE_MIPS_MALTA "mips-malta"
-#define MIPS_MALTA(obj) OBJECT_CHECK(MaltaState, (obj), TYPE_MIPS_MALTA)
+typedef struct MaltaState MaltaState;
+DECLARE_INSTANCE_CHECKER(MaltaState, MIPS_MALTA,
+                         TYPE_MIPS_MALTA)
 
-typedef struct {
+struct MaltaState {
     SysBusDevice parent_obj;
 
     MIPSCPSState cps;
     qemu_irq i8259[ISA_NUM_IRQS];
-} MaltaState;
+};
 
 static struct _loaderparams {
     int ram_size, ram_low_size;
diff --git a/hw/mips/trace-events b/hw/mips/trace-events
index 321933283f..915139d981 100644
--- a/hw/mips/trace-events
+++ b/hw/mips/trace-events
@@ -1,4 +1,4 @@
-# gt64xxx.c
+# gt64xxx_pci.c
 gt64120_read(const char *regname, unsigned size, uint64_t value) "gt64120 read %s size:%u value:0x%08" PRIx64
 gt64120_write(const char *regname, unsigned size, uint64_t value) "gt64120 write %s size:%u value:0x%08" PRIx64
 gt64120_isd_remap(uint64_t from_length, uint64_t from_addr, uint64_t to_length, uint64_t to_addr) "ISD: 0x%08" PRIx64 "@0x%08" PRIx64 " -> 0x%08" PRIx64 "@0x%08" PRIx64
diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
index 1c4addb201..dca3fba028 100644
--- a/hw/misc/applesmc.c
+++ b/hw/misc/applesmc.c
@@ -36,6 +36,7 @@
 #include "ui/console.h"
 #include "qemu/module.h"
 #include "qemu/timer.h"
+#include "qom/object.h"
 
 /* #define DEBUG_SMC */
 
@@ -89,9 +90,10 @@ struct AppleSMCData {
     QLIST_ENTRY(AppleSMCData) node;
 };
 
-#define APPLE_SMC(obj) OBJECT_CHECK(AppleSMCState, (obj), TYPE_APPLE_SMC)
-
 typedef struct AppleSMCState AppleSMCState;
+DECLARE_INSTANCE_CHECKER(AppleSMCState, APPLE_SMC,
+                         TYPE_APPLE_SMC)
+
 struct AppleSMCState {
     ISADevice parent_obj;
 
diff --git a/hw/misc/arm_integrator_debug.c b/hw/misc/arm_integrator_debug.c
index 3e23201ae6..822deffc0c 100644
--- a/hw/misc/arm_integrator_debug.c
+++ b/hw/misc/arm_integrator_debug.c
@@ -19,15 +19,17 @@
 #include "hw/misc/arm_integrator_debug.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
-#define INTEGRATOR_DEBUG(obj) \
-    OBJECT_CHECK(IntegratorDebugState, (obj), TYPE_INTEGRATOR_DEBUG)
+typedef struct IntegratorDebugState IntegratorDebugState;
+DECLARE_INSTANCE_CHECKER(IntegratorDebugState, INTEGRATOR_DEBUG,
+                         TYPE_INTEGRATOR_DEBUG)
 
-typedef struct {
+struct IntegratorDebugState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
-} IntegratorDebugState;
+};
 
 static uint64_t intdbg_control_read(void *opaque, hwaddr offset,
                                     unsigned size)
diff --git a/hw/misc/arm_l2x0.c b/hw/misc/arm_l2x0.c
index 2066c97f5f..93948c3bd8 100644
--- a/hw/misc/arm_l2x0.c
+++ b/hw/misc/arm_l2x0.c
@@ -24,14 +24,17 @@
 #include "migration/vmstate.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 /* L2C-310 r3p2 */
 #define CACHE_ID 0x410000c8
 
 #define TYPE_ARM_L2X0 "l2x0"
-#define ARM_L2X0(obj) OBJECT_CHECK(L2x0State, (obj), TYPE_ARM_L2X0)
+typedef struct L2x0State L2x0State;
+DECLARE_INSTANCE_CHECKER(L2x0State, ARM_L2X0,
+                         TYPE_ARM_L2X0)
 
-typedef struct L2x0State {
+struct L2x0State {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -42,7 +45,7 @@ typedef struct L2x0State {
     uint32_t tag_ctrl;
     uint32_t filter_start;
     uint32_t filter_end;
-} L2x0State;
+};
 
 static const VMStateDescription vmstate_l2x0 = {
     .name = "l2x0",
diff --git a/hw/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c
index a474bbdd19..f0f49e76e8 100644
--- a/hw/misc/arm_sysctl.c
+++ b/hw/misc/arm_sysctl.c
@@ -18,14 +18,16 @@
 #include "hw/arm/primecell.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define LOCK_VALUE 0xa05f
 
 #define TYPE_ARM_SYSCTL "realview_sysctl"
-#define ARM_SYSCTL(obj) \
-    OBJECT_CHECK(arm_sysctl_state, (obj), TYPE_ARM_SYSCTL)
+typedef struct arm_sysctl_state arm_sysctl_state;
+DECLARE_INSTANCE_CHECKER(arm_sysctl_state, ARM_SYSCTL,
+                         TYPE_ARM_SYSCTL)
 
-typedef struct {
+struct arm_sysctl_state {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -51,7 +53,7 @@ typedef struct {
     uint32_t *db_voltage;
     uint32_t db_num_clocks;
     uint32_t *db_clock_reset;
-} arm_sysctl_state;
+};
 
 static const VMStateDescription vmstate_arm_sysctl = {
     .name = "realview_sysctl",
diff --git a/hw/misc/debugexit.c b/hw/misc/debugexit.c
index 99a814f10c..c6b0cffd77 100644
--- a/hw/misc/debugexit.c
+++ b/hw/misc/debugexit.c
@@ -11,18 +11,20 @@
 #include "hw/isa/isa.h"
 #include "hw/qdev-properties.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define TYPE_ISA_DEBUG_EXIT_DEVICE "isa-debug-exit"
-#define ISA_DEBUG_EXIT_DEVICE(obj) \
-     OBJECT_CHECK(ISADebugExitState, (obj), TYPE_ISA_DEBUG_EXIT_DEVICE)
+typedef struct ISADebugExitState ISADebugExitState;
+DECLARE_INSTANCE_CHECKER(ISADebugExitState, ISA_DEBUG_EXIT_DEVICE,
+                         TYPE_ISA_DEBUG_EXIT_DEVICE)
 
-typedef struct ISADebugExitState {
+struct ISADebugExitState {
     ISADevice parent_obj;
 
     uint32_t iobase;
     uint32_t iosize;
     MemoryRegion io;
-} ISADebugExitState;
+};
 
 static uint64_t debug_exit_read(void *opaque, hwaddr addr, unsigned size)
 {
diff --git a/hw/misc/eccmemctl.c b/hw/misc/eccmemctl.c
index aec447368e..468c2a491d 100644
--- a/hw/misc/eccmemctl.c
+++ b/hw/misc/eccmemctl.c
@@ -29,6 +29,7 @@
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "trace.h"
+#include "qom/object.h"
 
 /* There are 3 versions of this chip used in SMP sun4m systems:
  * MCC (version 0, implementation 0) SS-600MP
@@ -126,9 +127,11 @@
 #define ECC_DIAG_MASK  (ECC_DIAG_SIZE - 1)
 
 #define TYPE_ECC_MEMCTL "eccmemctl"
-#define ECC_MEMCTL(obj) OBJECT_CHECK(ECCState, (obj), TYPE_ECC_MEMCTL)
+typedef struct ECCState ECCState;
+DECLARE_INSTANCE_CHECKER(ECCState, ECC_MEMCTL,
+                         TYPE_ECC_MEMCTL)
 
-typedef struct ECCState {
+struct ECCState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem, iomem_diag;
@@ -136,7 +139,7 @@ typedef struct ECCState {
     uint32_t regs[ECC_NREGS];
     uint8_t diag[ECC_DIAG_SIZE];
     uint32_t version;
-} ECCState;
+};
 
 static void ecc_mem_write(void *opaque, hwaddr addr, uint64_t val,
                           unsigned size)
diff --git a/hw/misc/edu.c b/hw/misc/edu.c
index ec617e63f3..0ff9d1ac78 100644
--- a/hw/misc/edu.c
+++ b/hw/misc/edu.c
@@ -28,12 +28,15 @@
 #include "hw/hw.h"
 #include "hw/pci/msi.h"
 #include "qemu/timer.h"
+#include "qom/object.h"
 #include "qemu/main-loop.h" /* iothread mutex */
 #include "qemu/module.h"
 #include "qapi/visitor.h"
 
 #define TYPE_PCI_EDU_DEVICE "edu"
-#define EDU(obj)        OBJECT_CHECK(EduState, obj, TYPE_PCI_EDU_DEVICE)
+typedef struct EduState EduState;
+DECLARE_INSTANCE_CHECKER(EduState, EDU,
+                         TYPE_PCI_EDU_DEVICE)
 
 #define FACT_IRQ        0x00000001
 #define DMA_IRQ         0x00000100
@@ -41,7 +44,7 @@
 #define DMA_START       0x40000
 #define DMA_SIZE        4096
 
-typedef struct {
+struct EduState {
     PCIDevice pdev;
     MemoryRegion mmio;
 
@@ -72,7 +75,7 @@ typedef struct {
     QEMUTimer dma_timer;
     char dma_buf[DMA_SIZE];
     uint64_t dma_mask;
-} EduState;
+};
 
 static bool edu_msi_enabled(EduState *edu)
 {
diff --git a/hw/misc/empty_slot.c b/hw/misc/empty_slot.c
index 9a011b1c11..57dcdfbe14 100644
--- a/hw/misc/empty_slot.c
+++ b/hw/misc/empty_slot.c
@@ -15,17 +15,20 @@
 #include "hw/misc/empty_slot.h"
 #include "qapi/error.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define TYPE_EMPTY_SLOT "empty_slot"
-#define EMPTY_SLOT(obj) OBJECT_CHECK(EmptySlot, (obj), TYPE_EMPTY_SLOT)
+typedef struct EmptySlot EmptySlot;
+DECLARE_INSTANCE_CHECKER(EmptySlot, EMPTY_SLOT,
+                         TYPE_EMPTY_SLOT)
 
-typedef struct EmptySlot {
+struct EmptySlot {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
     char *name;
     uint64_t size;
-} EmptySlot;
+};
 
 static uint64_t empty_slot_read(void *opaque, hwaddr addr,
                                 unsigned size)
diff --git a/hw/misc/exynos4210_clk.c b/hw/misc/exynos4210_clk.c
index bc1463ff89..4b469f6419 100644
--- a/hw/misc/exynos4210_clk.c
+++ b/hw/misc/exynos4210_clk.c
@@ -22,10 +22,12 @@
 #include "migration/vmstate.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define TYPE_EXYNOS4210_CLK             "exynos4210.clk"
-#define EXYNOS4210_CLK(obj) \
-    OBJECT_CHECK(Exynos4210ClkState, (obj), TYPE_EXYNOS4210_CLK)
+typedef struct Exynos4210ClkState Exynos4210ClkState;
+DECLARE_INSTANCE_CHECKER(Exynos4210ClkState, EXYNOS4210_CLK,
+                         TYPE_EXYNOS4210_CLK)
 
 #define CLK_PLL_LOCKED                  BIT(29)
 
@@ -55,12 +57,12 @@ static const Exynos4210Reg exynos4210_clk_regs[] = {
 
 #define EXYNOS4210_REGS_NUM       ARRAY_SIZE(exynos4210_clk_regs)
 
-typedef struct Exynos4210ClkState {
+struct Exynos4210ClkState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
     uint32_t reg[EXYNOS4210_REGS_NUM];
-} Exynos4210ClkState;
+};
 
 static uint64_t exynos4210_clk_read(void *opaque, hwaddr offset,
                                     unsigned size)
diff --git a/hw/misc/exynos4210_pmu.c b/hw/misc/exynos4210_pmu.c
index 500f28343f..b19b82a88c 100644
--- a/hw/misc/exynos4210_pmu.c
+++ b/hw/misc/exynos4210_pmu.c
@@ -29,6 +29,7 @@
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "sysemu/runstate.h"
+#include "qom/object.h"
 
 #ifndef DEBUG_PMU
 #define DEBUG_PMU           0
@@ -394,15 +395,16 @@ static const Exynos4210PmuReg exynos4210_pmu_regs[] = {
 #define PMU_NUM_OF_REGISTERS ARRAY_SIZE(exynos4210_pmu_regs)
 
 #define TYPE_EXYNOS4210_PMU "exynos4210.pmu"
-#define EXYNOS4210_PMU(obj) \
-    OBJECT_CHECK(Exynos4210PmuState, (obj), TYPE_EXYNOS4210_PMU)
+typedef struct Exynos4210PmuState Exynos4210PmuState;
+DECLARE_INSTANCE_CHECKER(Exynos4210PmuState, EXYNOS4210_PMU,
+                         TYPE_EXYNOS4210_PMU)
 
-typedef struct Exynos4210PmuState {
+struct Exynos4210PmuState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
     uint32_t reg[PMU_NUM_OF_REGISTERS];
-} Exynos4210PmuState;
+};
 
 static void exynos4210_pmu_poweroff(void)
 {
diff --git a/hw/misc/exynos4210_rng.c b/hw/misc/exynos4210_rng.c
index 38cd61c7ea..13ec6e188b 100644
--- a/hw/misc/exynos4210_rng.c
+++ b/hw/misc/exynos4210_rng.c
@@ -24,6 +24,7 @@
 #include "qemu/log.h"
 #include "qemu/guest-random.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define DEBUG_EXYNOS_RNG 0
 
@@ -35,8 +36,9 @@
     } while (0)
 
 #define TYPE_EXYNOS4210_RNG             "exynos4210.rng"
-#define EXYNOS4210_RNG(obj) \
-    OBJECT_CHECK(Exynos4210RngState, (obj), TYPE_EXYNOS4210_RNG)
+typedef struct Exynos4210RngState Exynos4210RngState;
+DECLARE_INSTANCE_CHECKER(Exynos4210RngState, EXYNOS4210_RNG,
+                         TYPE_EXYNOS4210_RNG)
 
 /*
  * Exynos4220, PRNG, only polling mode is supported.
@@ -68,7 +70,7 @@
 
 #define EXYNOS4210_RNG_REGS_MEM_SIZE            0x200
 
-typedef struct Exynos4210RngState {
+struct Exynos4210RngState {
     SysBusDevice parent_obj;
     MemoryRegion iomem;
 
@@ -79,7 +81,7 @@ typedef struct Exynos4210RngState {
     /* Register values */
     uint32_t reg_control;
     uint32_t reg_status;
-} Exynos4210RngState;
+};
 
 static bool exynos4210_rng_seed_ready(const Exynos4210RngState *s)
 {
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 2b6882face..e321e5cb69 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -38,6 +38,7 @@
 #include "qapi/visitor.h"
 
 #include "hw/misc/ivshmem.h"
+#include "qom/object.h"
 
 #define PCI_VENDOR_ID_IVSHMEM   PCI_VENDOR_ID_REDHAT_QUMRANET
 #define PCI_DEVICE_ID_IVSHMEM   0x1110
@@ -57,20 +58,21 @@
     } while (0)
 
 #define TYPE_IVSHMEM_COMMON "ivshmem-common"
-#define IVSHMEM_COMMON(obj) \
-    OBJECT_CHECK(IVShmemState, (obj), TYPE_IVSHMEM_COMMON)
+typedef struct IVShmemState IVShmemState;
+DECLARE_INSTANCE_CHECKER(IVShmemState, IVSHMEM_COMMON,
+                         TYPE_IVSHMEM_COMMON)
 
 #define TYPE_IVSHMEM_PLAIN "ivshmem-plain"
-#define IVSHMEM_PLAIN(obj) \
-    OBJECT_CHECK(IVShmemState, (obj), TYPE_IVSHMEM_PLAIN)
+DECLARE_INSTANCE_CHECKER(IVShmemState, IVSHMEM_PLAIN,
+                         TYPE_IVSHMEM_PLAIN)
 
 #define TYPE_IVSHMEM_DOORBELL "ivshmem-doorbell"
-#define IVSHMEM_DOORBELL(obj) \
-    OBJECT_CHECK(IVShmemState, (obj), TYPE_IVSHMEM_DOORBELL)
+DECLARE_INSTANCE_CHECKER(IVShmemState, IVSHMEM_DOORBELL,
+                         TYPE_IVSHMEM_DOORBELL)
 
 #define TYPE_IVSHMEM "ivshmem"
-#define IVSHMEM(obj) \
-    OBJECT_CHECK(IVShmemState, (obj), TYPE_IVSHMEM)
+DECLARE_INSTANCE_CHECKER(IVShmemState, IVSHMEM,
+                         TYPE_IVSHMEM)
 
 typedef struct Peer {
     int nb_eventfds;
@@ -83,7 +85,7 @@ typedef struct MSIVector {
     bool unmasked;
 } MSIVector;
 
-typedef struct IVShmemState {
+struct IVShmemState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
@@ -115,7 +117,7 @@ typedef struct IVShmemState {
     /* migration stuff */
     OnOffAuto master;
     Error *migration_blocker;
-} IVShmemState;
+};
 
 /* registers for the Inter-VM shared memory device */
 enum ivshmem_registers {
diff --git a/hw/misc/milkymist-hpdmc.c b/hw/misc/milkymist-hpdmc.c
index 61e86e6b34..f25715e09e 100644
--- a/hw/misc/milkymist-hpdmc.c
+++ b/hw/misc/milkymist-hpdmc.c
@@ -27,6 +27,7 @@
 #include "trace.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 enum {
     R_SYSTEM = 0,
@@ -43,8 +44,9 @@ enum {
 };
 
 #define TYPE_MILKYMIST_HPDMC "milkymist-hpdmc"
-#define MILKYMIST_HPDMC(obj) \
-    OBJECT_CHECK(MilkymistHpdmcState, (obj), TYPE_MILKYMIST_HPDMC)
+typedef struct MilkymistHpdmcState MilkymistHpdmcState;
+DECLARE_INSTANCE_CHECKER(MilkymistHpdmcState, MILKYMIST_HPDMC,
+                         TYPE_MILKYMIST_HPDMC)
 
 struct MilkymistHpdmcState {
     SysBusDevice parent_obj;
@@ -53,7 +55,6 @@ struct MilkymistHpdmcState {
 
     uint32_t regs[R_MAX];
 };
-typedef struct MilkymistHpdmcState MilkymistHpdmcState;
 
 static uint64_t hpdmc_read(void *opaque, hwaddr addr,
                            unsigned size)
diff --git a/hw/misc/milkymist-pfpu.c b/hw/misc/milkymist-pfpu.c
index 516825e83d..489bb8873f 100644
--- a/hw/misc/milkymist-pfpu.c
+++ b/hw/misc/milkymist-pfpu.c
@@ -31,6 +31,7 @@
 #include "qemu/module.h"
 #include "qemu/error-report.h"
 #include <math.h>
+#include "qom/object.h"
 
 /* #define TRACE_EXEC */
 
@@ -120,8 +121,9 @@ static const char *opcode_to_str[] = {
 #endif
 
 #define TYPE_MILKYMIST_PFPU "milkymist-pfpu"
-#define MILKYMIST_PFPU(obj) \
-    OBJECT_CHECK(MilkymistPFPUState, (obj), TYPE_MILKYMIST_PFPU)
+typedef struct MilkymistPFPUState MilkymistPFPUState;
+DECLARE_INSTANCE_CHECKER(MilkymistPFPUState, MILKYMIST_PFPU,
+                         TYPE_MILKYMIST_PFPU)
 
 struct MilkymistPFPUState {
     SysBusDevice parent_obj;
@@ -137,7 +139,6 @@ struct MilkymistPFPUState {
     int output_queue_pos;
     uint32_t output_queue[MAX_LATENCY];
 };
-typedef struct MilkymistPFPUState MilkymistPFPUState;
 
 static inline uint32_t
 get_dma_address(uint32_t base, uint32_t x, uint32_t y)
diff --git a/hw/misc/mst_fpga.c b/hw/misc/mst_fpga.c
index 81abdf8ede..f74d8cdd4a 100644
--- a/hw/misc/mst_fpga.c
+++ b/hw/misc/mst_fpga.c
@@ -16,6 +16,7 @@
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 /* Mainstone FPGA for extern irqs */
 #define FPGA_GPIO_PIN	0
@@ -40,10 +41,11 @@
 #define MST_PCMCIA_CD1_IRQ	13
 
 #define TYPE_MAINSTONE_FPGA "mainstone-fpga"
-#define MAINSTONE_FPGA(obj) \
-    OBJECT_CHECK(mst_irq_state, (obj), TYPE_MAINSTONE_FPGA)
+typedef struct mst_irq_state mst_irq_state;
+DECLARE_INSTANCE_CHECKER(mst_irq_state, MAINSTONE_FPGA,
+                         TYPE_MAINSTONE_FPGA)
 
-typedef struct mst_irq_state{
+struct mst_irq_state {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -63,7 +65,7 @@ typedef struct mst_irq_state{
     uint32_t intsetclr;
     uint32_t pcmcia0;
     uint32_t pcmcia1;
-}mst_irq_state;
+};
 
 static void
 mst_fpga_set_irq(void *opaque, int irq, int level)
diff --git a/hw/misc/pc-testdev.c b/hw/misc/pc-testdev.c
index 8aa8e6549f..577a15bf58 100644
--- a/hw/misc/pc-testdev.c
+++ b/hw/misc/pc-testdev.c
@@ -39,10 +39,11 @@
 #include "qemu/module.h"
 #include "hw/irq.h"
 #include "hw/isa/isa.h"
+#include "qom/object.h"
 
 #define IOMEM_LEN    0x10000
 
-typedef struct PCTestdev {
+struct PCTestdev {
     ISADevice parent_obj;
 
     MemoryRegion ioport;
@@ -52,11 +53,12 @@ typedef struct PCTestdev {
     MemoryRegion iomem;
     uint32_t ioport_data;
     char iomem_buf[IOMEM_LEN];
-} PCTestdev;
+};
+typedef struct PCTestdev PCTestdev;
 
 #define TYPE_TESTDEV "pc-testdev"
-#define TESTDEV(obj) \
-     OBJECT_CHECK(PCTestdev, (obj), TYPE_TESTDEV)
+DECLARE_INSTANCE_CHECKER(PCTestdev, TESTDEV,
+                         TYPE_TESTDEV)
 
 static uint64_t test_irq_line_read(void *opaque, hwaddr addr, unsigned size)
 {
diff --git a/hw/misc/pca9552.c b/hw/misc/pca9552.c
index e4ccdeaf78..b7686e27d7 100644
--- a/hw/misc/pca9552.c
+++ b/hw/misc/pca9552.c
@@ -22,20 +22,20 @@
 #include "qapi/error.h"
 #include "qapi/visitor.h"
 #include "trace.h"
+#include "qom/object.h"
 
-typedef struct PCA955xClass {
+struct PCA955xClass {
     /*< private >*/
     I2CSlaveClass parent_class;
     /*< public >*/
 
     uint8_t pin_count;
     uint8_t max_reg;
-} PCA955xClass;
+};
+typedef struct PCA955xClass PCA955xClass;
 
-#define PCA955X_CLASS(klass) \
-    OBJECT_CLASS_CHECK(PCA955xClass, (klass), TYPE_PCA955X)
-#define PCA955X_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(PCA955xClass, (obj), TYPE_PCA955X)
+DECLARE_CLASS_CHECKERS(PCA955xClass, PCA955X,
+                       TYPE_PCA955X)
 
 #define PCA9552_LED_ON   0x0
 #define PCA9552_LED_OFF  0x1
diff --git a/hw/misc/pci-testdev.c b/hw/misc/pci-testdev.c
index 188de4d9cc..86d4816769 100644
--- a/hw/misc/pci-testdev.c
+++ b/hw/misc/pci-testdev.c
@@ -24,6 +24,7 @@
 #include "qemu/event_notifier.h"
 #include "qemu/module.h"
 #include "sysemu/kvm.h"
+#include "qom/object.h"
 
 typedef struct PCITestDevHdr {
     uint8_t test;
@@ -78,7 +79,7 @@ enum {
 #define IOTEST_ACCESS_TYPE uint8_t
 #define IOTEST_ACCESS_WIDTH (sizeof(uint8_t))
 
-typedef struct PCITestDevState {
+struct PCITestDevState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
@@ -90,12 +91,13 @@ typedef struct PCITestDevState {
 
     uint64_t membar_size;
     MemoryRegion membar;
-} PCITestDevState;
+};
+typedef struct PCITestDevState PCITestDevState;
 
 #define TYPE_PCI_TEST_DEV "pci-testdev"
 
-#define PCI_TEST_DEV(obj) \
-    OBJECT_CHECK(PCITestDevState, (obj), TYPE_PCI_TEST_DEV)
+DECLARE_INSTANCE_CHECKER(PCITestDevState, PCI_TEST_DEV,
+                         TYPE_PCI_TEST_DEV)
 
 #define IOTEST_IS_MEM(i) (strcmp(IOTEST_TYPE(i), "portio"))
 #define IOTEST_REGION(d, i) (IOTEST_IS_MEM(i) ?  &(d)->mmio : &(d)->portio)
diff --git a/hw/misc/puv3_pm.c b/hw/misc/puv3_pm.c
index 8989d363cd..cac8497f81 100644
--- a/hw/misc/puv3_pm.c
+++ b/hw/misc/puv3_pm.c
@@ -11,6 +11,7 @@
 
 #include "qemu/osdep.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #undef DEBUG_PUV3
 #include "hw/unicore32/puv3.h"
@@ -18,9 +19,11 @@
 #include "qemu/log.h"
 
 #define TYPE_PUV3_PM "puv3_pm"
-#define PUV3_PM(obj) OBJECT_CHECK(PUV3PMState, (obj), TYPE_PUV3_PM)
+typedef struct PUV3PMState PUV3PMState;
+DECLARE_INSTANCE_CHECKER(PUV3PMState, PUV3_PM,
+                         TYPE_PUV3_PM)
 
-typedef struct PUV3PMState {
+struct PUV3PMState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -31,7 +34,7 @@ typedef struct PUV3PMState {
     uint32_t reg_PLL_DDR_CFG;
     uint32_t reg_PLL_VGA_CFG;
     uint32_t reg_DIVCFG;
-} PUV3PMState;
+};
 
 static uint64_t puv3_pm_read(void *opaque, hwaddr offset,
         unsigned size)
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
index abb10bbcaf..598d5471a4 100644
--- a/hw/misc/pvpanic.c
+++ b/hw/misc/pvpanic.c
@@ -20,6 +20,7 @@
 #include "hw/nvram/fw_cfg.h"
 #include "hw/qdev-properties.h"
 #include "hw/misc/pvpanic.h"
+#include "qom/object.h"
 
 /* The bit of supported pv event, TODO: include uapi header and remove this */
 #define PVPANIC_F_PANICKED      0
@@ -29,8 +30,9 @@
 #define PVPANIC_PANICKED        (1 << PVPANIC_F_PANICKED)
 #define PVPANIC_CRASHLOADED     (1 << PVPANIC_F_CRASHLOADED)
 
-#define ISA_PVPANIC_DEVICE(obj)    \
-    OBJECT_CHECK(PVPanicState, (obj), TYPE_PVPANIC)
+typedef struct PVPanicState PVPanicState;
+DECLARE_INSTANCE_CHECKER(PVPanicState, ISA_PVPANIC_DEVICE,
+                         TYPE_PVPANIC)
 
 static void handle_event(int event)
 {
@@ -54,12 +56,12 @@ static void handle_event(int event)
 
 #include "hw/isa/isa.h"
 
-typedef struct PVPanicState {
+struct PVPanicState {
     ISADevice parent_obj;
 
     MemoryRegion io;
     uint16_t ioport;
-} PVPanicState;
+};
 
 /* return supported events on read */
 static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size)
diff --git a/hw/misc/sga.c b/hw/misc/sga.c
index 6866bf72cb..477f587ef3 100644
--- a/hw/misc/sga.c
+++ b/hw/misc/sga.c
@@ -29,15 +29,18 @@
 #include "hw/isa/isa.h"
 #include "hw/loader.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define SGABIOS_FILENAME "sgabios.bin"
 
 #define TYPE_SGA "sga"
-#define SGA(obj) OBJECT_CHECK(ISASGAState, (obj), TYPE_SGA)
+typedef struct ISASGAState ISASGAState;
+DECLARE_INSTANCE_CHECKER(ISASGAState, SGA,
+                         TYPE_SGA)
 
-typedef struct ISASGAState {
+struct ISASGAState {
     ISADevice parent_obj;
-} ISASGAState;
+};
 
 static void sga_realizefn(DeviceState *dev, Error **errp)
 {
diff --git a/hw/misc/slavio_misc.c b/hw/misc/slavio_misc.c
index 279b38dfc7..ab27ad462e 100644
--- a/hw/misc/slavio_misc.c
+++ b/hw/misc/slavio_misc.c
@@ -29,6 +29,7 @@
 #include "qemu/module.h"
 #include "sysemu/runstate.h"
 #include "trace.h"
+#include "qom/object.h"
 
 /*
  * This is the auxio port, chip control and system control part of
@@ -39,9 +40,11 @@
  */
 
 #define TYPE_SLAVIO_MISC "slavio_misc"
-#define SLAVIO_MISC(obj) OBJECT_CHECK(MiscState, (obj), TYPE_SLAVIO_MISC)
+typedef struct MiscState MiscState;
+DECLARE_INSTANCE_CHECKER(MiscState, SLAVIO_MISC,
+                         TYPE_SLAVIO_MISC)
 
-typedef struct MiscState {
+struct MiscState {
     SysBusDevice parent_obj;
 
     MemoryRegion cfg_iomem;
@@ -59,17 +62,19 @@ typedef struct MiscState {
     uint8_t diag, mctrl;
     uint8_t sysctrl;
     uint16_t leds;
-} MiscState;
+};
 
 #define TYPE_APC "apc"
-#define APC(obj) OBJECT_CHECK(APCState, (obj), TYPE_APC)
+typedef struct APCState APCState;
+DECLARE_INSTANCE_CHECKER(APCState, APC,
+                         TYPE_APC)
 
-typedef struct APCState {
+struct APCState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
     qemu_irq cpu_halt;
-} APCState;
+};
 
 #define MISC_SIZE 1
 #define LED_SIZE 2
diff --git a/hw/misc/tmp105.h b/hw/misc/tmp105.h
index 9ba05ecc9c..7ee8a496ff 100644
--- a/hw/misc/tmp105.h
+++ b/hw/misc/tmp105.h
@@ -16,9 +16,12 @@
 
 #include "hw/i2c/i2c.h"
 #include "hw/misc/tmp105_regs.h"
+#include "qom/object.h"
 
 #define TYPE_TMP105 "tmp105"
-#define TMP105(obj) OBJECT_CHECK(TMP105State, (obj), TYPE_TMP105)
+typedef struct TMP105State TMP105State;
+DECLARE_INSTANCE_CHECKER(TMP105State, TMP105,
+                         TYPE_TMP105)
 
 /**
  * TMP105State:
@@ -27,7 +30,7 @@
  *
  * @see_also: http://www.ti.com/lit/gpn/tmp105
  */
-typedef struct TMP105State {
+struct TMP105State {
     /*< private >*/
     I2CSlave i2c;
     /*< public >*/
@@ -42,6 +45,6 @@ typedef struct TMP105State {
     int16_t limit[2];
     int faults;
     uint8_t alarm;
-} TMP105State;
+};
 
 #endif
diff --git a/hw/misc/tmp421.c b/hw/misc/tmp421.c
index 49abe2d246..212d6e0e83 100644
--- a/hw/misc/tmp421.c
+++ b/hw/misc/tmp421.c
@@ -30,6 +30,7 @@
 #include "qapi/error.h"
 #include "qapi/visitor.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 /* Manufacturer / Device ID's */
 #define TMP421_MANUFACTURER_ID          0x55
@@ -48,7 +49,7 @@ static const DeviceInfo devices[] = {
     { TMP423_DEVICE_ID, "tmp423" },
 };
 
-typedef struct TMP421State {
+struct TMP421State {
     /*< private >*/
     I2CSlave i2c;
     /*< public >*/
@@ -63,20 +64,19 @@ typedef struct TMP421State {
     uint8_t buf[2];
     uint8_t pointer;
 
-} TMP421State;
+};
+typedef struct TMP421State TMP421State;
 
-typedef struct TMP421Class {
+struct TMP421Class {
     I2CSlaveClass parent_class;
     DeviceInfo *dev;
-} TMP421Class;
+};
+typedef struct TMP421Class TMP421Class;
 
 #define TYPE_TMP421 "tmp421-generic"
-#define TMP421(obj) OBJECT_CHECK(TMP421State, (obj), TYPE_TMP421)
+DECLARE_OBJ_CHECKERS(TMP421State, TMP421Class,
+                     TMP421, TYPE_TMP421)
 
-#define TMP421_CLASS(klass) \
-     OBJECT_CLASS_CHECK(TMP421Class, (klass), TYPE_TMP421)
-#define TMP421_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(TMP421Class, (obj), TYPE_TMP421)
 
 /* the TMP421 registers */
 #define TMP421_STATUS_REG               0x08
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 066752aa90..56a622d1e9 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -44,7 +44,6 @@ ecc_diag_mem_writeb(uint64_t addr, uint32_t val) "Write diagnostic %"PRId64" = 0
 ecc_diag_mem_readb(uint64_t addr, uint32_t ret) "Read diagnostic %"PRId64"= 0x%02x"
 
 # empty_slot.c
-empty_slot_read(uint64_t addr, unsigned width, uint64_t value, unsigned size, const char *name) "rd addr:0x%04"PRIx64" data:0x%0*"PRIx64" size %u [%s]"
 empty_slot_write(uint64_t addr, unsigned width, uint64_t value, unsigned size, const char *name) "wr addr:0x%04"PRIx64" data:0x%0*"PRIx64" size %u [%s]"
 
 # slavio_misc.c
@@ -111,13 +110,13 @@ mos6522_set_sr_int(void) "set sr_int"
 mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
 mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
 
-# stm32f4xx_syscfg
+# stm32f4xx_syscfg.c
 stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
 stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
 stm32f4xx_syscfg_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " "
 stm32f4xx_syscfg_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
 
-# stm32f4xx_exti
+# stm32f4xx_exti.c
 stm32f4xx_exti_set_irq(int irq, int leve) "Set EXTI: %d to %d"
 stm32f4xx_exti_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " "
 stm32f4xx_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
@@ -182,11 +181,13 @@ armsse_mhu_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 MHU wri
 # aspeed_xdma.c
 aspeed_xdma_write(uint64_t offset, uint64_t data) "XDMA write: offset 0x%" PRIx64 " data 0x%" PRIx64
 
+# bcm2835_property.c
+bcm2835_mbox_property(uint32_t tag, uint32_t bufsize, size_t resplen) "mbox property tag:0x%08x in_sz:%u out_sz:%zu"
+
 # bcm2835_mbox.c
 bcm2835_mbox_write(unsigned int size, uint64_t addr, uint64_t value) "mbox write sz:%u addr:0x%"PRIx64" data:0x%"PRIx64
 bcm2835_mbox_read(unsigned int size, uint64_t addr, uint64_t value) "mbox read sz:%u addr:0x%"PRIx64" data:0x%"PRIx64
 bcm2835_mbox_irq(unsigned level) "mbox irq:ARM level:%u"
-bcm2835_mbox_property(uint32_t tag, uint32_t bufsize, size_t resplen) "mbox property tag:0x%08x in_sz:%u out_sz:%zu"
 
 # mac_via.c
 via1_rtc_update_data_out(int count, int value) "count=%d value=0x%02x"
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index f7472d1f3c..bedf09a6f5 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -23,6 +23,7 @@
 #include "qemu/module.h"
 #include "hw/registerfields.h"
 #include "hw/qdev-clock.h"
+#include "qom/object.h"
 
 #ifndef ZYNQ_SLCR_ERR_DEBUG
 #define ZYNQ_SLCR_ERR_DEBUG 0
@@ -182,9 +183,11 @@ REG32(DDRIOB, 0xb40)
 #define ZYNQ_SLCR_NUM_REGS      (ZYNQ_SLCR_MMIO_SIZE / 4)
 
 #define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr"
-#define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR)
+typedef struct ZynqSLCRState ZynqSLCRState;
+DECLARE_INSTANCE_CHECKER(ZynqSLCRState, ZYNQ_SLCR,
+                         TYPE_ZYNQ_SLCR)
 
-typedef struct ZynqSLCRState {
+struct ZynqSLCRState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -194,7 +197,7 @@ typedef struct ZynqSLCRState {
     Clock *ps_clk;
     Clock *uart0_ref_clk;
     Clock *uart1_ref_clk;
-} ZynqSLCRState;
+};
 
 /*
  * return the output frequency of ARM/DDR/IO pll
diff --git a/hw/net/can/can_kvaser_pci.c b/hw/net/can/can_kvaser_pci.c
index 4b941370d0..168b3a620d 100644
--- a/hw/net/can/can_kvaser_pci.c
+++ b/hw/net/can/can_kvaser_pci.c
@@ -43,11 +43,13 @@
 #include "net/can_emu.h"
 
 #include "can_sja1000.h"
+#include "qom/object.h"
 
 #define TYPE_CAN_PCI_DEV "kvaser_pci"
 
-#define KVASER_PCI_DEV(obj) \
-    OBJECT_CHECK(KvaserPCIState, (obj), TYPE_CAN_PCI_DEV)
+typedef struct KvaserPCIState KvaserPCIState;
+DECLARE_INSTANCE_CHECKER(KvaserPCIState, KVASER_PCI_DEV,
+                         TYPE_CAN_PCI_DEV)
 
 #ifndef KVASER_PCI_VENDOR_ID1
 #define KVASER_PCI_VENDOR_ID1     0x10e8    /* the PCI device and vendor IDs */
@@ -78,7 +80,7 @@
 
 #define KVASER_PCI_XILINX_VERSION_NUMBER 13
 
-typedef struct KvaserPCIState {
+struct KvaserPCIState {
     /*< private >*/
     PCIDevice       dev;
     /*< public >*/
@@ -93,7 +95,7 @@ typedef struct KvaserPCIState {
     uint32_t        s5920_irqstate;
 
     CanBusState     *canbus;
-} KvaserPCIState;
+};
 
 static void kvaser_pci_irq_handler(void *opaque, int irq_num, int level)
 {
diff --git a/hw/net/can/can_mioe3680_pci.c b/hw/net/can/can_mioe3680_pci.c
index 695e762a8d..7a79e2605a 100644
--- a/hw/net/can/can_mioe3680_pci.c
+++ b/hw/net/can/can_mioe3680_pci.c
@@ -39,11 +39,13 @@
 #include "net/can_emu.h"
 
 #include "can_sja1000.h"
+#include "qom/object.h"
 
 #define TYPE_CAN_PCI_DEV "mioe3680_pci"
 
-#define MIOe3680_PCI_DEV(obj) \
-    OBJECT_CHECK(Mioe3680PCIState, (obj), TYPE_CAN_PCI_DEV)
+typedef struct Mioe3680PCIState Mioe3680PCIState;
+DECLARE_INSTANCE_CHECKER(Mioe3680PCIState, MIOe3680_PCI_DEV,
+                         TYPE_CAN_PCI_DEV)
 
 /* the PCI device and vendor IDs */
 #ifndef MIOe3680_PCI_VENDOR_ID1
@@ -59,7 +61,7 @@
 
 #define MIOe3680_PCI_BYTES_PER_SJA 0x80
 
-typedef struct Mioe3680PCIState {
+struct Mioe3680PCIState {
     /*< private >*/
     PCIDevice       dev;
     /*< public >*/
@@ -70,7 +72,7 @@ typedef struct Mioe3680PCIState {
 
     char            *model; /* The model that support, only SJA1000 now. */
     CanBusState     *canbus[MIOe3680_PCI_SJA_COUNT];
-} Mioe3680PCIState;
+};
 
 static void mioe3680_pci_reset(DeviceState *dev)
 {
diff --git a/hw/net/can/can_pcm3680_pci.c b/hw/net/can/can_pcm3680_pci.c
index 4218e63eb2..8ef4e74af0 100644
--- a/hw/net/can/can_pcm3680_pci.c
+++ b/hw/net/can/can_pcm3680_pci.c
@@ -39,11 +39,13 @@
 #include "net/can_emu.h"
 
 #include "can_sja1000.h"
+#include "qom/object.h"
 
 #define TYPE_CAN_PCI_DEV "pcm3680_pci"
 
-#define PCM3680i_PCI_DEV(obj) \
-    OBJECT_CHECK(Pcm3680iPCIState, (obj), TYPE_CAN_PCI_DEV)
+typedef struct Pcm3680iPCIState Pcm3680iPCIState;
+DECLARE_INSTANCE_CHECKER(Pcm3680iPCIState, PCM3680i_PCI_DEV,
+                         TYPE_CAN_PCI_DEV)
 
 /* the PCI device and vendor IDs */
 #ifndef PCM3680i_PCI_VENDOR_ID1
@@ -59,7 +61,7 @@
 
 #define PCM3680i_PCI_BYTES_PER_SJA 0x20
 
-typedef struct Pcm3680iPCIState {
+struct Pcm3680iPCIState {
     /*< private >*/
     PCIDevice       dev;
     /*< public >*/
@@ -70,7 +72,7 @@ typedef struct Pcm3680iPCIState {
 
     char            *model; /* The model that support, only SJA1000 now. */
     CanBusState     *canbus[PCM3680i_PCI_SJA_COUNT];
-} Pcm3680iPCIState;
+};
 
 static void pcm3680i_pci_reset(DeviceState *dev)
 {
diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index c54db0d62d..56b96e9b0f 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -27,6 +27,7 @@
 #include "qemu/module.h"
 #include "qemu/timer.h"
 #include <zlib.h>
+#include "qom/object.h"
 
 //#define DEBUG_SONIC
 
@@ -150,9 +151,11 @@ do { printf("sonic ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
 #define SONIC_DESC_ADDR  0xFFFE
 
 #define TYPE_DP8393X "dp8393x"
-#define DP8393X(obj) OBJECT_CHECK(dp8393xState, (obj), TYPE_DP8393X)
+typedef struct dp8393xState dp8393xState;
+DECLARE_INSTANCE_CHECKER(dp8393xState, DP8393X,
+                         TYPE_DP8393X)
 
-typedef struct dp8393xState {
+struct dp8393xState {
     SysBusDevice parent_obj;
 
     /* Hardware */
@@ -182,7 +185,7 @@ typedef struct dp8393xState {
     /* Memory access */
     MemoryRegion *dma_mr;
     AddressSpace as;
-} dp8393xState;
+};
 
 /* Accessor functions for values which are formed by
  * concatenating two 16 bit device registers. By putting these
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index c4d896a9e6..83347cbd87 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -39,6 +39,7 @@
 
 #include "e1000x_common.h"
 #include "trace.h"
+#include "qom/object.h"
 
 static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
@@ -76,7 +77,7 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
  *  Others never tested
  */
 
-typedef struct E1000State_st {
+struct E1000State_st {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
@@ -137,24 +138,22 @@ typedef struct E1000State_st {
     bool received_tx_tso;
     bool use_tso_for_migration;
     e1000x_txd_props mig_props;
-} E1000State;
+};
+typedef struct E1000State_st E1000State;
 
 #define chkflag(x)     (s->compat_flags & E1000_FLAG_##x)
 
-typedef struct E1000BaseClass {
+struct E1000BaseClass {
     PCIDeviceClass parent_class;
     uint16_t phy_id2;
-} E1000BaseClass;
+};
+typedef struct E1000BaseClass E1000BaseClass;
 
 #define TYPE_E1000_BASE "e1000-base"
 
-#define E1000(obj) \
-    OBJECT_CHECK(E1000State, (obj), TYPE_E1000_BASE)
+DECLARE_OBJ_CHECKERS(E1000State, E1000BaseClass,
+                     E1000, TYPE_E1000_BASE)
 
-#define E1000_CLASS(klass) \
-     OBJECT_CLASS_CHECK(E1000BaseClass, (klass), TYPE_E1000_BASE)
-#define E1000_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(E1000BaseClass, (obj), TYPE_E1000_BASE)
 
 static void
 e1000_link_up(E1000State *s)
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index fda34518c9..938d44f198 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -53,11 +53,14 @@
 
 #include "trace.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 #define TYPE_E1000E "e1000e"
-#define E1000E(obj) OBJECT_CHECK(E1000EState, (obj), TYPE_E1000E)
+typedef struct E1000EState E1000EState;
+DECLARE_INSTANCE_CHECKER(E1000EState, E1000E,
+                         TYPE_E1000E)
 
-typedef struct E1000EState {
+struct E1000EState {
     PCIDevice parent_obj;
     NICState *nic;
     NICConf conf;
@@ -79,7 +82,7 @@ typedef struct E1000EState {
 
     E1000ECore core;
 
-} E1000EState;
+};
 
 #define E1000E_MMIO_IDX     0
 #define E1000E_FLASH_IDX    1
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index bcd186cac5..bcfd46696f 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -2916,7 +2916,6 @@ static const readops e1000e_macreg_readops[] = {
     e1000e_getreg(TSYNCRXCTL),
     e1000e_getreg(TDH),
     e1000e_getreg(LEDCTL),
-    e1000e_getreg(STATUS),
     e1000e_getreg(TCTL),
     e1000e_getreg(TDBAL),
     e1000e_getreg(TDLEN),
@@ -3142,7 +3141,6 @@ static const writeops e1000e_macreg_writeops[] = {
     e1000e_putreg(RXCFGL),
     e1000e_putreg(TSYNCRXCTL),
     e1000e_putreg(TSYNCTXCTL),
-    e1000e_putreg(FLSWDATA),
     e1000e_putreg(EXTCNF_SIZE),
     e1000e_putreg(EEMNGCTL),
     e1000e_putreg(RA),
diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c
index 3408ceacb5..36d898ad16 100644
--- a/hw/net/etraxfs_eth.c
+++ b/hw/net/etraxfs_eth.c
@@ -30,6 +30,7 @@
 #include "qemu/error-report.h"
 #include "qemu/module.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define D(x)
 
@@ -323,11 +324,11 @@ static void mdio_cycle(struct qemu_mdio *bus)
 #define FS_ETH_MAX_REGS      0x17
 
 #define TYPE_ETRAX_FS_ETH "etraxfs-eth"
-#define ETRAX_FS_ETH(obj) \
-    OBJECT_CHECK(ETRAXFSEthState, (obj), TYPE_ETRAX_FS_ETH)
+typedef struct ETRAXFSEthState ETRAXFSEthState;
+DECLARE_INSTANCE_CHECKER(ETRAXFSEthState, ETRAX_FS_ETH,
+                         TYPE_ETRAX_FS_ETH)
 
-typedef struct ETRAXFSEthState
-{
+struct ETRAXFSEthState {
     SysBusDevice parent_obj;
 
     MemoryRegion mmio;
@@ -348,7 +349,7 @@ typedef struct ETRAXFSEthState
 
     /* PHY.     */
     struct qemu_phy phy;
-} ETRAXFSEthState;
+};
 
 static void eth_validate_duplex(ETRAXFSEthState *eth)
 {
diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c
index ad20b22cdd..93886bba60 100644
--- a/hw/net/fsl_etsec/etsec.c
+++ b/hw/net/fsl_etsec/etsec.c
@@ -357,7 +357,7 @@ static ssize_t etsec_receive(NetClientState *nc,
 
 #if defined(HEX_DUMP)
     fprintf(stderr, "%s receive size:%zd\n", nc->name, size);
-    qemu_hexdump((void *)buf, stderr, "", size);
+    qemu_hexdump(stderr, "", buf, size);
 #endif
     /* Flush is unnecessary as are already in receiving path */
     etsec->need_flush = false;
diff --git a/hw/net/fsl_etsec/etsec.h b/hw/net/fsl_etsec/etsec.h
index 7951c3ad65..0c929d9afd 100644
--- a/hw/net/fsl_etsec/etsec.h
+++ b/hw/net/fsl_etsec/etsec.h
@@ -28,6 +28,7 @@
 #include "hw/sysbus.h"
 #include "net/net.h"
 #include "hw/ptimer.h"
+#include "qom/object.h"
 
 /* Buffer Descriptors */
 
@@ -104,7 +105,7 @@ typedef struct eTSEC_Register {
     uint32_t    value;
 } eTSEC_Register;
 
-typedef struct eTSEC {
+struct eTSEC {
     SysBusDevice  busdev;
 
     MemoryRegion  io_area;
@@ -145,11 +146,12 @@ typedef struct eTSEC {
 
     /* Whether we should flush the rx queue when buffer becomes available. */
     bool need_flush;
-} eTSEC;
+};
+typedef struct eTSEC eTSEC;
 
 #define TYPE_ETSEC_COMMON "eTSEC"
-#define ETSEC_COMMON(obj) \
-     OBJECT_CHECK(eTSEC, (obj), TYPE_ETSEC_COMMON)
+DECLARE_INSTANCE_CHECKER(eTSEC, ETSEC_COMMON,
+                         TYPE_ETSEC_COMMON)
 
 #define eTSEC_TRANSMIT 1
 #define eTSEC_RECEIVE  2
diff --git a/hw/net/fsl_etsec/rings.c b/hw/net/fsl_etsec/rings.c
index 337a55fc95..628648a9c3 100644
--- a/hw/net/fsl_etsec/rings.c
+++ b/hw/net/fsl_etsec/rings.c
@@ -269,7 +269,7 @@ static void process_tx_bd(eTSEC         *etsec,
 
 #if defined(HEX_DUMP)
             qemu_log("eTSEC Send packet size:%d\n", etsec->tx_buffer_len);
-            qemu_hexdump(etsec->tx_buffer, stderr, "", etsec->tx_buffer_len);
+            qemu_hexdump(stderr, "", etsec->tx_buffer, etsec->tx_buffer_len);
 #endif  /* ETSEC_RING_DEBUG */
 
             if (etsec->first_bd.flags & BD_TX_TOEUN) {
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index e35f00fb9f..57a59accd0 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -25,6 +25,7 @@
 #include "qemu/module.h"
 /* For crc32 */
 #include <zlib.h>
+#include "qom/object.h"
 
 //#define DEBUG_LAN9118
 
@@ -180,9 +181,11 @@ static const VMStateDescription vmstate_lan9118_packet = {
     }
 };
 
-#define LAN9118(obj) OBJECT_CHECK(lan9118_state, (obj), TYPE_LAN9118)
+typedef struct lan9118_state lan9118_state;
+DECLARE_INSTANCE_CHECKER(lan9118_state, LAN9118,
+                         TYPE_LAN9118)
 
-typedef struct {
+struct lan9118_state {
     SysBusDevice parent_obj;
 
     NICState *nic;
@@ -258,7 +261,7 @@ typedef struct {
     uint32_t read_long;
 
     uint32_t mode_16bit;
-} lan9118_state;
+};
 
 static const VMStateDescription vmstate_lan9118 = {
     .name = "lan9118",
diff --git a/hw/net/milkymist-minimac2.c b/hw/net/milkymist-minimac2.c
index 1ba01754ee..41a8543edf 100644
--- a/hw/net/milkymist-minimac2.c
+++ b/hw/net/milkymist-minimac2.c
@@ -24,6 +24,7 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 #include "cpu.h" /* FIXME: why does this use TARGET_PAGE_ALIGN? */
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
@@ -98,8 +99,9 @@ struct MilkymistMinimac2MdioState {
 typedef struct MilkymistMinimac2MdioState MilkymistMinimac2MdioState;
 
 #define TYPE_MILKYMIST_MINIMAC2 "milkymist-minimac2"
-#define MILKYMIST_MINIMAC2(obj) \
-    OBJECT_CHECK(MilkymistMinimac2State, (obj), TYPE_MILKYMIST_MINIMAC2)
+typedef struct MilkymistMinimac2State MilkymistMinimac2State;
+DECLARE_INSTANCE_CHECKER(MilkymistMinimac2State, MILKYMIST_MINIMAC2,
+                         TYPE_MILKYMIST_MINIMAC2)
 
 struct MilkymistMinimac2State {
     SysBusDevice parent_obj;
@@ -123,7 +125,6 @@ struct MilkymistMinimac2State {
     uint8_t *rx1_buf;
     uint8_t *tx_buf;
 };
-typedef struct MilkymistMinimac2State MilkymistMinimac2State;
 
 static const uint8_t preamble_sfd[] = {
         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5
diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c
index 0c578c430c..61dbd575da 100644
--- a/hw/net/mipsnet.c
+++ b/hw/net/mipsnet.c
@@ -6,6 +6,7 @@
 #include "trace.h"
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 /* MIPSnet register offsets */
 
@@ -24,9 +25,11 @@
 #define MAX_ETH_FRAME_SIZE      1514
 
 #define TYPE_MIPS_NET "mipsnet"
-#define MIPS_NET(obj) OBJECT_CHECK(MIPSnetState, (obj), TYPE_MIPS_NET)
+typedef struct MIPSnetState MIPSnetState;
+DECLARE_INSTANCE_CHECKER(MIPSnetState, MIPS_NET,
+                         TYPE_MIPS_NET)
 
-typedef struct MIPSnetState {
+struct MIPSnetState {
     SysBusDevice parent_obj;
 
     uint32_t busy;
@@ -41,7 +44,7 @@ typedef struct MIPSnetState {
     qemu_irq irq;
     NICState *nic;
     NICConf conf;
-} MIPSnetState;
+};
 
 static void mipsnet_reset(MIPSnetState *s)
 {
diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c
index a878056426..688a0cc4f6 100644
--- a/hw/net/ne2000-isa.c
+++ b/hw/net/ne2000-isa.c
@@ -31,16 +31,19 @@
 #include "qapi/error.h"
 #include "qapi/visitor.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
-#define ISA_NE2000(obj) OBJECT_CHECK(ISANE2000State, (obj), TYPE_ISA_NE2000)
+typedef struct ISANE2000State ISANE2000State;
+DECLARE_INSTANCE_CHECKER(ISANE2000State, ISA_NE2000,
+                         TYPE_ISA_NE2000)
 
-typedef struct ISANE2000State {
+struct ISANE2000State {
     ISADevice parent_obj;
 
     uint32_t iobase;
     uint32_t isairq;
     NE2000State ne2000;
-} ISANE2000State;
+};
 
 static NetClientInfo net_ne2000_isa_info = {
     .type = NET_CLIENT_DRIVER_NIC,
diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c
index 2ba0dc8c2f..5cd204c30c 100644
--- a/hw/net/opencores_eth.c
+++ b/hw/net/opencores_eth.c
@@ -40,6 +40,7 @@
 #include "qemu/module.h"
 #include "net/eth.h"
 #include "trace.h"
+#include "qom/object.h"
 
 /* RECSMALL is not used because it breaks tap networking in linux:
  * incoming ARP responses are too short
@@ -271,9 +272,11 @@ typedef struct desc {
 #define DEFAULT_PHY 1
 
 #define TYPE_OPEN_ETH "open_eth"
-#define OPEN_ETH(obj) OBJECT_CHECK(OpenEthState, (obj), TYPE_OPEN_ETH)
+typedef struct OpenEthState OpenEthState;
+DECLARE_INSTANCE_CHECKER(OpenEthState, OPEN_ETH,
+                         TYPE_OPEN_ETH)
 
-typedef struct OpenEthState {
+struct OpenEthState {
     SysBusDevice parent_obj;
 
     NICState *nic;
@@ -287,7 +290,7 @@ typedef struct OpenEthState {
     unsigned tx_desc;
     unsigned rx_desc;
     desc desc[128];
-} OpenEthState;
+};
 
 static desc *rx_desc(OpenEthState *s)
 {
diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c
index 49d3e42e83..449970bc52 100644
--- a/hw/net/pcnet-pci.c
+++ b/hw/net/pcnet-pci.c
@@ -40,6 +40,7 @@
 #include "trace.h"
 
 #include "pcnet.h"
+#include "qom/object.h"
 
 //#define PCNET_DEBUG
 //#define PCNET_DEBUG_IO
@@ -51,17 +52,18 @@
 
 #define TYPE_PCI_PCNET "pcnet"
 
-#define PCI_PCNET(obj) \
-     OBJECT_CHECK(PCIPCNetState, (obj), TYPE_PCI_PCNET)
+typedef struct PCIPCNetState PCIPCNetState;
+DECLARE_INSTANCE_CHECKER(PCIPCNetState, PCI_PCNET,
+                         TYPE_PCI_PCNET)
 
-typedef struct {
+struct PCIPCNetState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
 
     PCNetState state;
     MemoryRegion io_bar;
-} PCIPCNetState;
+};
 
 static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
diff --git a/hw/net/rocker/rocker.h b/hw/net/rocker/rocker.h
index e4c22db4ff..941c932265 100644
--- a/hw/net/rocker/rocker.h
+++ b/hw/net/rocker/rocker.h
@@ -20,6 +20,7 @@
 #define ROCKER_H
 
 #include "qemu/sockets.h"
+#include "qom/object.h"
 
 #if defined(DEBUG_ROCKER)
 #  define DPRINTF(fmt, ...) \
@@ -72,8 +73,8 @@ typedef struct desc_ring DescRing;
 
 #define TYPE_ROCKER "rocker"
 typedef struct rocker Rocker;
-#define ROCKER(obj) \
-    OBJECT_CHECK(Rocker, (obj), TYPE_ROCKER)
+DECLARE_INSTANCE_CHECKER(Rocker, ROCKER,
+                         TYPE_ROCKER)
 
 Rocker *rocker_find(const char *name);
 uint32_t rocker_fp_ports(Rocker *r);
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index ab93d78ab3..9246388f58 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -62,6 +62,7 @@
 #include "net/net.h"
 #include "net/eth.h"
 #include "sysemu/sysemu.h"
+#include "qom/object.h"
 
 /* debug RTL8139 card */
 //#define DEBUG_RTL8139 1
@@ -93,8 +94,9 @@ static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...)
 
 #define TYPE_RTL8139 "rtl8139"
 
-#define RTL8139(obj) \
-     OBJECT_CHECK(RTL8139State, (obj), TYPE_RTL8139)
+typedef struct RTL8139State RTL8139State;
+DECLARE_INSTANCE_CHECKER(RTL8139State, RTL8139,
+                         TYPE_RTL8139)
 
 /* Symbolic offsets to registers. */
 enum RTL8139_registers {
@@ -431,7 +433,7 @@ typedef struct RTL8139TallyCounters
 /* Clears all tally counters */
 static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters);
 
-typedef struct RTL8139State {
+struct RTL8139State {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
@@ -513,7 +515,7 @@ typedef struct RTL8139State {
 
     /* Support migration to/from old versions */
     int rtl8139_mmio_io_addr_dummy;
-} RTL8139State;
+};
 
 /* Writes tally counters to memory via DMA */
 static void RTL8139TallyCounters_dma_write(RTL8139State *s, dma_addr_t tc_addr);
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
index a347b6a4d5..9fad904321 100644
--- a/hw/net/smc91c111.c
+++ b/hw/net/smc91c111.c
@@ -19,14 +19,17 @@
 #include "qemu/module.h"
 /* For crc32 */
 #include <zlib.h>
+#include "qom/object.h"
 
 /* Number of 2k memory pages available.  */
 #define NUM_PACKETS 4
 
 #define TYPE_SMC91C111 "smc91c111"
-#define SMC91C111(obj) OBJECT_CHECK(smc91c111_state, (obj), TYPE_SMC91C111)
+typedef struct smc91c111_state smc91c111_state;
+DECLARE_INSTANCE_CHECKER(smc91c111_state, SMC91C111,
+                         TYPE_SMC91C111)
 
-typedef struct {
+struct smc91c111_state {
     SysBusDevice parent_obj;
 
     NICState *nic;
@@ -55,7 +58,7 @@ typedef struct {
     uint8_t int_level;
     uint8_t int_mask;
     MemoryRegion mmio;
-} smc91c111_state;
+};
 
 static const VMStateDescription vmstate_smc91c111 = {
     .name = "smc91c111",
diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
index 4cd02dda01..d34cb29607 100644
--- a/hw/net/spapr_llan.c
+++ b/hw/net/spapr_llan.c
@@ -38,6 +38,7 @@
 #include "trace.h"
 
 #include <libfdt.h>
+#include "qom/object.h"
 
 #define ETH_ALEN        6
 #define MAX_PACKET_SIZE 65536
@@ -84,8 +85,9 @@ typedef uint64_t vlan_bd_t;
 #define VLAN_MAX_BUFS        (VLAN_RX_BDS_LEN / 8)
 
 #define TYPE_VIO_SPAPR_VLAN_DEVICE "spapr-vlan"
-#define VIO_SPAPR_VLAN_DEVICE(obj) \
-     OBJECT_CHECK(SpaprVioVlan, (obj), TYPE_VIO_SPAPR_VLAN_DEVICE)
+typedef struct SpaprVioVlan SpaprVioVlan;
+DECLARE_INSTANCE_CHECKER(SpaprVioVlan, VIO_SPAPR_VLAN_DEVICE,
+                         TYPE_VIO_SPAPR_VLAN_DEVICE)
 
 #define RX_POOL_MAX_BDS 4096
 #define RX_MAX_POOLS 5
@@ -96,7 +98,7 @@ typedef struct {
     vlan_bd_t bds[RX_POOL_MAX_BDS];
 } RxBufPool;
 
-typedef struct SpaprVioVlan {
+struct SpaprVioVlan {
     SpaprVioDevice sdev;
     NICConf nicconf;
     NICState *nic;
@@ -108,7 +110,7 @@ typedef struct SpaprVioVlan {
     QEMUTimer *rxp_timer;
     uint32_t compat_flags;             /* Compatibility flags for migration */
     RxBufPool *rx_pool[RX_MAX_POOLS];  /* Receive buffer descriptor pools */
-} SpaprVioVlan;
+};
 
 static bool spapr_vlan_can_receive(NetClientState *nc)
 {
diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c
index cb6e2509ea..9f13afa4e4 100644
--- a/hw/net/stellaris_enet.c
+++ b/hw/net/stellaris_enet.c
@@ -16,6 +16,7 @@
 #include "qemu/log.h"
 #include "qemu/module.h"
 #include <zlib.h>
+#include "qom/object.h"
 
 //#define DEBUG_STELLARIS_ENET 1
 
@@ -50,15 +51,16 @@ do { fprintf(stderr, "stellaris_enet: error: " fmt , ## __VA_ARGS__);} while (0)
 #define SE_TCTL_DUPLEX  0x08
 
 #define TYPE_STELLARIS_ENET "stellaris_enet"
-#define STELLARIS_ENET(obj) \
-    OBJECT_CHECK(stellaris_enet_state, (obj), TYPE_STELLARIS_ENET)
+typedef struct stellaris_enet_state stellaris_enet_state;
+DECLARE_INSTANCE_CHECKER(stellaris_enet_state, STELLARIS_ENET,
+                         TYPE_STELLARIS_ENET)
 
 typedef struct {
     uint8_t data[2048];
     uint32_t len;
 } StellarisEnetRxFrame;
 
-typedef struct {
+struct stellaris_enet_state {
     SysBusDevice parent_obj;
 
     uint32_t ris;
@@ -82,7 +84,7 @@ typedef struct {
     NICConf conf;
     qemu_irq irq;
     MemoryRegion mmio;
-} stellaris_enet_state;
+};
 
 static const VMStateDescription vmstate_rx_frame = {
     .name = "stellaris_enet/rx_frame",
diff --git a/hw/net/sungem.c b/hw/net/sungem.c
index e4b7b57704..91753830a7 100644
--- a/hw/net/sungem.c
+++ b/hw/net/sungem.c
@@ -19,10 +19,13 @@
 #include "hw/net/mii.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define TYPE_SUNGEM "sungem"
 
-#define SUNGEM(obj) OBJECT_CHECK(SunGEMState, (obj), TYPE_SUNGEM)
+typedef struct SunGEMState SunGEMState;
+DECLARE_INSTANCE_CHECKER(SunGEMState, SUNGEM,
+                         TYPE_SUNGEM)
 
 #define MAX_PACKET_SIZE 9016
 
@@ -192,7 +195,7 @@ struct gem_rxd {
 #define RXDCTRL_ALTMAC    0x2000000000000000ULL  /* Matched ALT MAC */
 
 
-typedef struct {
+struct SunGEMState {
     PCIDevice pdev;
 
     MemoryRegion sungem;
@@ -221,7 +224,7 @@ typedef struct {
     uint8_t tx_data[MAX_PACKET_SIZE];
     uint32_t tx_size;
     uint64_t tx_first_ctl;
-} SunGEMState;
+};
 
 
 static void sungem_eval_irq(SunGEMState *s)
diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c
index bc48d46b9f..7364ba1019 100644
--- a/hw/net/sunhme.c
+++ b/hw/net/sunhme.c
@@ -33,6 +33,7 @@
 #include "net/eth.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define HME_REG_SIZE                   0x8000
 
@@ -129,7 +130,9 @@
 #define MII_COMMAND_WRITE      0x1
 
 #define TYPE_SUNHME "sunhme"
-#define SUNHME(obj) OBJECT_CHECK(SunHMEState, (obj), TYPE_SUNHME)
+typedef struct SunHMEState SunHMEState;
+DECLARE_INSTANCE_CHECKER(SunHMEState, SUNHME,
+                         TYPE_SUNHME)
 
 /* Maximum size of buffer */
 #define HME_FIFO_SIZE          0x800
@@ -153,7 +156,7 @@
 
 #define HME_MII_REGS_SIZE      0x20
 
-typedef struct SunHMEState {
+struct SunHMEState {
     /*< private >*/
     PCIDevice parent_obj;
 
@@ -174,7 +177,7 @@ typedef struct SunHMEState {
     uint32_t mifregs[HME_MIF_REG_SIZE >> 2];
 
     uint16_t miiregs[HME_MII_REGS_SIZE];
-} SunHMEState;
+};
 
 static Property sunhme_properties[] = {
     DEFINE_NIC_PROPERTIES(SunHMEState, conf),
diff --git a/hw/net/tulip.h b/hw/net/tulip.h
index c3fcd4d4e1..87e3ab79bc 100644
--- a/hw/net/tulip.h
+++ b/hw/net/tulip.h
@@ -3,10 +3,12 @@
 
 #include "qemu/units.h"
 #include "net/net.h"
+#include "qom/object.h"
 
 #define TYPE_TULIP "tulip"
 typedef struct TULIPState TULIPState;
-#define TULIP(obj) OBJECT_CHECK(TULIPState, (obj), TYPE_TULIP)
+DECLARE_INSTANCE_CHECKER(TULIPState, TULIP,
+                         TYPE_TULIP)
 
 #define CSR(_x) ((_x) << 3)
 
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 7a6ca4ec35..eff299f629 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -35,6 +35,7 @@
 #include "vmware_utils.h"
 #include "net_tx_pkt.h"
 #include "net_rx_pkt.h"
+#include "qom/object.h"
 
 #define PCI_DEVICE_ID_VMWARE_VMXNET3_REVISION 0x1
 #define VMXNET3_MSIX_BAR_SIZE 0x2000
@@ -128,15 +129,14 @@
 
 #define VMXNET_FLAG_IS_SET(field, flag) (((field) & (flag)) == (flag))
 
-typedef struct VMXNET3Class {
+struct VMXNET3Class {
     PCIDeviceClass parent_class;
     DeviceRealize parent_dc_realize;
-} VMXNET3Class;
+};
+typedef struct VMXNET3Class VMXNET3Class;
 
-#define VMXNET3_DEVICE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(VMXNET3Class, (klass), TYPE_VMXNET3)
-#define VMXNET3_DEVICE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(VMXNET3Class, (obj), TYPE_VMXNET3)
+DECLARE_CLASS_CHECKERS(VMXNET3Class, VMXNET3_DEVICE,
+                       TYPE_VMXNET3)
 
 static inline void vmxnet3_ring_init(PCIDevice *d,
                                      Vmxnet3Ring *ring,
diff --git a/hw/net/vmxnet3_defs.h b/hw/net/vmxnet3_defs.h
index 65780c576d..71440509ca 100644
--- a/hw/net/vmxnet3_defs.h
+++ b/hw/net/vmxnet3_defs.h
@@ -19,9 +19,12 @@
 
 #include "net/net.h"
 #include "hw/net/vmxnet3.h"
+#include "qom/object.h"
 
 #define TYPE_VMXNET3 "vmxnet3"
-#define VMXNET3(obj) OBJECT_CHECK(VMXNET3State, (obj), TYPE_VMXNET3)
+typedef struct VMXNET3State VMXNET3State;
+DECLARE_INSTANCE_CHECKER(VMXNET3State, VMXNET3,
+                         TYPE_VMXNET3)
 
 /* Device state and helper functions */
 #define VMXNET3_RX_RINGS_PER_QUEUE (2)
@@ -58,7 +61,7 @@ typedef struct {
     bool is_asserted;
 } Vmxnet3IntState;
 
-typedef struct {
+struct VMXNET3State {
         PCIDevice parent_obj;
         NICState *nic;
         NICConf conf;
@@ -132,6 +135,6 @@ typedef struct {
 
         /* Compatibility flags for migration */
         uint32_t compat_flags;
-} VMXNET3State;
+};
 
 #endif
diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c
index 5bf1b61012..a066550023 100644
--- a/hw/net/xgmac.c
+++ b/hw/net/xgmac.c
@@ -32,6 +32,7 @@
 #include "qemu/log.h"
 #include "qemu/module.h"
 #include "net/net.h"
+#include "qom/object.h"
 
 #ifdef DEBUG_XGMAC
 #define DEBUGF_BRK(message, args...) do { \
@@ -139,9 +140,11 @@ typedef struct RxTxStats {
 } RxTxStats;
 
 #define TYPE_XGMAC "xgmac"
-#define XGMAC(obj) OBJECT_CHECK(XgmacState, (obj), TYPE_XGMAC)
+typedef struct XgmacState XgmacState;
+DECLARE_INSTANCE_CHECKER(XgmacState, XGMAC,
+                         TYPE_XGMAC)
 
-typedef struct XgmacState {
+struct XgmacState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -153,7 +156,7 @@ typedef struct XgmacState {
 
     struct RxTxStats stats;
     uint32_t regs[R_MAX];
-} XgmacState;
+};
 
 static const VMStateDescription vmstate_rxtx_stats = {
     .name = "xgmac_stats",
diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
index 2e89f236b4..4e13786e50 100644
--- a/hw/net/xilinx_axienet.c
+++ b/hw/net/xilinx_axienet.c
@@ -35,6 +35,7 @@
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
 #include "hw/stream.h"
+#include "qom/object.h"
 
 #define DPHY(x)
 
@@ -42,16 +43,16 @@
 #define TYPE_XILINX_AXI_ENET_DATA_STREAM "xilinx-axienet-data-stream"
 #define TYPE_XILINX_AXI_ENET_CONTROL_STREAM "xilinx-axienet-control-stream"
 
-#define XILINX_AXI_ENET(obj) \
-     OBJECT_CHECK(XilinxAXIEnet, (obj), TYPE_XILINX_AXI_ENET)
+typedef struct XilinxAXIEnet XilinxAXIEnet;
+DECLARE_INSTANCE_CHECKER(XilinxAXIEnet, XILINX_AXI_ENET,
+                         TYPE_XILINX_AXI_ENET)
 
-#define XILINX_AXI_ENET_DATA_STREAM(obj) \
-     OBJECT_CHECK(XilinxAXIEnetStreamSlave, (obj),\
-     TYPE_XILINX_AXI_ENET_DATA_STREAM)
+typedef struct XilinxAXIEnetStreamSlave XilinxAXIEnetStreamSlave;
+DECLARE_INSTANCE_CHECKER(XilinxAXIEnetStreamSlave, XILINX_AXI_ENET_DATA_STREAM,
+                         TYPE_XILINX_AXI_ENET_DATA_STREAM)
 
-#define XILINX_AXI_ENET_CONTROL_STREAM(obj) \
-     OBJECT_CHECK(XilinxAXIEnetStreamSlave, (obj),\
-     TYPE_XILINX_AXI_ENET_CONTROL_STREAM)
+DECLARE_INSTANCE_CHECKER(XilinxAXIEnetStreamSlave, XILINX_AXI_ENET_CONTROL_STREAM,
+                         TYPE_XILINX_AXI_ENET_CONTROL_STREAM)
 
 /* Advertisement control register. */
 #define ADVERTISE_10FULL        0x0040  /* Try for 10mbps full-duplex  */
@@ -310,8 +311,6 @@ struct TEMAC  {
     void *parent;
 };
 
-typedef struct XilinxAXIEnetStreamSlave XilinxAXIEnetStreamSlave;
-typedef struct XilinxAXIEnet XilinxAXIEnet;
 
 struct XilinxAXIEnetStreamSlave {
     Object parent;
@@ -1046,7 +1045,7 @@ static const TypeInfo xilinx_enet_info = {
 static const TypeInfo xilinx_enet_data_stream_info = {
     .name          = TYPE_XILINX_AXI_ENET_DATA_STREAM,
     .parent        = TYPE_OBJECT,
-    .instance_size = sizeof(struct XilinxAXIEnetStreamSlave),
+    .instance_size = sizeof(XilinxAXIEnetStreamSlave),
     .class_init    = xilinx_enet_data_stream_class_init,
     .interfaces = (InterfaceInfo[]) {
             { TYPE_STREAM_SLAVE },
@@ -1057,7 +1056,7 @@ static const TypeInfo xilinx_enet_data_stream_info = {
 static const TypeInfo xilinx_enet_control_stream_info = {
     .name          = TYPE_XILINX_AXI_ENET_CONTROL_STREAM,
     .parent        = TYPE_OBJECT,
-    .instance_size = sizeof(struct XilinxAXIEnetStreamSlave),
+    .instance_size = sizeof(XilinxAXIEnetStreamSlave),
     .class_init    = xilinx_enet_control_stream_class_init,
     .interfaces = (InterfaceInfo[]) {
             { TYPE_STREAM_SLAVE },
diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
index 71d16fef3d..6e09f7e422 100644
--- a/hw/net/xilinx_ethlite.c
+++ b/hw/net/xilinx_ethlite.c
@@ -24,6 +24,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 #include "cpu.h" /* FIXME should not use tswap* */
 #include "hw/sysbus.h"
 #include "hw/irq.h"
@@ -52,8 +53,8 @@
 #define CTRL_S     0x1
 
 #define TYPE_XILINX_ETHLITE "xlnx.xps-ethernetlite"
-#define XILINX_ETHLITE(obj) \
-    OBJECT_CHECK(struct xlx_ethlite, (obj), TYPE_XILINX_ETHLITE)
+DECLARE_INSTANCE_CHECKER(struct xlx_ethlite, XILINX_ETHLITE,
+                         TYPE_XILINX_ETHLITE)
 
 struct xlx_ethlite
 {
diff --git a/hw/nvram/ds1225y.c b/hw/nvram/ds1225y.c
index d5cb922287..44fb7a94d3 100644
--- a/hw/nvram/ds1225y.c
+++ b/hw/nvram/ds1225y.c
@@ -29,6 +29,7 @@
 #include "trace.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 typedef struct {
     MemoryRegion iomem;
@@ -109,13 +110,15 @@ static const VMStateDescription vmstate_nvram = {
 };
 
 #define TYPE_DS1225Y "ds1225y"
-#define DS1225Y(obj) OBJECT_CHECK(SysBusNvRamState, (obj), TYPE_DS1225Y)
+typedef struct SysBusNvRamState SysBusNvRamState;
+DECLARE_INSTANCE_CHECKER(SysBusNvRamState, DS1225Y,
+                         TYPE_DS1225Y)
 
-typedef struct {
+struct SysBusNvRamState {
     SysBusDevice parent_obj;
 
     NvRamState nvram;
-} SysBusNvRamState;
+};
 
 static void nvram_sysbus_realize(DeviceState *dev, Error **errp)
 {
diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c
index d46a2bec3f..3e93dbbffb 100644
--- a/hw/nvram/eeprom_at24c.c
+++ b/hw/nvram/eeprom_at24c.c
@@ -14,6 +14,7 @@
 #include "hw/i2c/i2c.h"
 #include "hw/qdev-properties.h"
 #include "sysemu/block-backend.h"
+#include "qom/object.h"
 
 /* #define DEBUG_AT24C */
 
@@ -27,9 +28,11 @@
                             ## __VA_ARGS__)
 
 #define TYPE_AT24C_EE "at24c-eeprom"
-#define AT24C_EE(obj) OBJECT_CHECK(EEPROMState, (obj), TYPE_AT24C_EE)
+typedef struct EEPROMState EEPROMState;
+DECLARE_INSTANCE_CHECKER(EEPROMState, AT24C_EE,
+                         TYPE_AT24C_EE)
 
-typedef struct EEPROMState {
+struct EEPROMState {
     I2CSlave parent_obj;
 
     /* address counter */
@@ -45,7 +48,7 @@ typedef struct EEPROMState {
     uint8_t *mem;
 
     BlockBackend *blk;
-} EEPROMState;
+};
 
 static
 int at24c_eeprom_event(I2CSlave *s, enum i2c_event event)
diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c
index 386513499f..57ccc174f2 100644
--- a/hw/nvram/spapr_nvram.c
+++ b/hw/nvram/spapr_nvram.c
@@ -39,18 +39,20 @@
 #include "hw/ppc/spapr.h"
 #include "hw/ppc/spapr_vio.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
-typedef struct SpaprNvram {
+struct SpaprNvram {
     SpaprVioDevice sdev;
     uint32_t size;
     uint8_t *buf;
     BlockBackend *blk;
     VMChangeStateEntry *vmstate;
-} SpaprNvram;
+};
+typedef struct SpaprNvram SpaprNvram;
 
 #define TYPE_VIO_SPAPR_NVRAM "spapr-nvram"
-#define VIO_SPAPR_NVRAM(obj) \
-     OBJECT_CHECK(SpaprNvram, (obj), TYPE_VIO_SPAPR_NVRAM)
+DECLARE_INSTANCE_CHECKER(SpaprNvram, VIO_SPAPR_NVRAM,
+                         TYPE_VIO_SPAPR_NVRAM)
 
 #define MIN_NVRAM_SIZE      (8 * KiB)
 #define DEFAULT_NVRAM_SIZE  (64 * KiB)
diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c
index 677a310b96..e88998d88c 100644
--- a/hw/pci-bridge/dec.c
+++ b/hw/pci-bridge/dec.c
@@ -32,12 +32,15 @@
 #include "hw/pci/pci_host.h"
 #include "hw/pci/pci_bridge.h"
 #include "hw/pci/pci_bus.h"
+#include "qom/object.h"
 
-#define DEC_21154(obj) OBJECT_CHECK(DECState, (obj), TYPE_DEC_21154)
+typedef struct DECState DECState;
+DECLARE_INSTANCE_CHECKER(DECState, DEC_21154,
+                         TYPE_DEC_21154)
 
-typedef struct DECState {
+struct DECState {
     PCIHostState parent_obj;
-} DECState;
+};
 
 static int dec_map_irq(PCIDevice *pci_dev, int irq_num)
 {
diff --git a/hw/pci-bridge/gen_pcie_root_port.c b/hw/pci-bridge/gen_pcie_root_port.c
index bb26e272c1..67c71d566b 100644
--- a/hw/pci-bridge/gen_pcie_root_port.c
+++ b/hw/pci-bridge/gen_pcie_root_port.c
@@ -17,10 +17,12 @@
 #include "hw/pci/pcie_port.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 #define TYPE_GEN_PCIE_ROOT_PORT                "pcie-root-port"
-#define GEN_PCIE_ROOT_PORT(obj) \
-        OBJECT_CHECK(GenPCIERootPort, (obj), TYPE_GEN_PCIE_ROOT_PORT)
+typedef struct GenPCIERootPort GenPCIERootPort;
+DECLARE_INSTANCE_CHECKER(GenPCIERootPort, GEN_PCIE_ROOT_PORT,
+                         TYPE_GEN_PCIE_ROOT_PORT)
 
 #define GEN_PCIE_ROOT_PORT_AER_OFFSET           0x100
 #define GEN_PCIE_ROOT_PORT_ACS_OFFSET \
@@ -28,7 +30,7 @@
 
 #define GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR       1
 
-typedef struct GenPCIERootPort {
+struct GenPCIERootPort {
     /*< private >*/
     PCIESlot parent_obj;
     /*< public >*/
@@ -37,7 +39,7 @@ typedef struct GenPCIERootPort {
 
     /* additional resources to reserve */
     PCIResReserve res_reserve;
-} GenPCIERootPort;
+};
 
 static uint8_t gen_rp_aer_vector(const PCIDevice *d)
 {
diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c
index 4a080b7c7b..b86d76caf3 100644
--- a/hw/pci-bridge/pci_bridge_dev.c
+++ b/hw/pci-bridge/pci_bridge_dev.c
@@ -31,11 +31,13 @@
 #include "exec/memory.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/hotplug.h"
+#include "qom/object.h"
 
 #define TYPE_PCI_BRIDGE_DEV      "pci-bridge"
 #define TYPE_PCI_BRIDGE_SEAT_DEV "pci-bridge-seat"
-#define PCI_BRIDGE_DEV(obj) \
-    OBJECT_CHECK(PCIBridgeDev, (obj), TYPE_PCI_BRIDGE_DEV)
+typedef struct PCIBridgeDev PCIBridgeDev;
+DECLARE_INSTANCE_CHECKER(PCIBridgeDev, PCI_BRIDGE_DEV,
+                         TYPE_PCI_BRIDGE_DEV)
 
 struct PCIBridgeDev {
     /*< private >*/
@@ -52,7 +54,6 @@ struct PCIBridgeDev {
     /* additional resources to reserve */
     PCIResReserve res_reserve;
 };
-typedef struct PCIBridgeDev PCIBridgeDev;
 
 static void pci_bridge_dev_realize(PCIDevice *dev, Error **errp)
 {
diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c
index 22f9fc223b..aedded1064 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -22,35 +22,42 @@
 #include "qemu/module.h"
 #include "sysemu/numa.h"
 #include "hw/boards.h"
+#include "qom/object.h"
 
 #define TYPE_PXB_BUS "pxb-bus"
-#define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS)
+typedef struct PXBBus PXBBus;
+DECLARE_INSTANCE_CHECKER(PXBBus, PXB_BUS,
+                         TYPE_PXB_BUS)
 
 #define TYPE_PXB_PCIE_BUS "pxb-pcie-bus"
-#define PXB_PCIE_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_PCIE_BUS)
+DECLARE_INSTANCE_CHECKER(PXBBus, PXB_PCIE_BUS,
+                         TYPE_PXB_PCIE_BUS)
 
-typedef struct PXBBus {
+struct PXBBus {
     /*< private >*/
     PCIBus parent_obj;
     /*< public >*/
 
     char bus_path[8];
-} PXBBus;
+};
 
 #define TYPE_PXB_DEVICE "pxb"
-#define PXB_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_DEVICE)
+typedef struct PXBDev PXBDev;
+DECLARE_INSTANCE_CHECKER(PXBDev, PXB_DEV,
+                         TYPE_PXB_DEVICE)
 
 #define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
-#define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE)
+DECLARE_INSTANCE_CHECKER(PXBDev, PXB_PCIE_DEV,
+                         TYPE_PXB_PCIE_DEVICE)
 
-typedef struct PXBDev {
+struct PXBDev {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
 
     uint8_t bus_nr;
     uint16_t numa_node;
-} PXBDev;
+};
 
 static PXBDev *convert_to_pxb(PCIDevice *dev)
 {
diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c
index eade133968..abc98f8cd9 100644
--- a/hw/pci-bridge/pcie_pci_bridge.c
+++ b/hw/pci-bridge/pcie_pci_bridge.c
@@ -17,19 +17,21 @@
 #include "hw/pci/shpc.h"
 #include "hw/pci/slotid_cap.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
-typedef struct PCIEPCIBridge {
+struct PCIEPCIBridge {
     /*< private >*/
     PCIBridge parent_obj;
 
     OnOffAuto msi;
     MemoryRegion shpc_bar;
     /*< public >*/
-} PCIEPCIBridge;
+};
+typedef struct PCIEPCIBridge PCIEPCIBridge;
 
 #define TYPE_PCIE_PCI_BRIDGE_DEV "pcie-pci-bridge"
-#define PCIE_PCI_BRIDGE_DEV(obj) \
-        OBJECT_CHECK(PCIEPCIBridge, (obj), TYPE_PCIE_PCI_BRIDGE_DEV)
+DECLARE_INSTANCE_CHECKER(PCIEPCIBridge, PCIE_PCI_BRIDGE_DEV,
+                         TYPE_PCIE_PCI_BRIDGE_DEV)
 
 static void pcie_pci_bridge_realize(PCIDevice *d, Error **errp)
 {
diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
index 1405b3fc70..d10fbd39d3 100644
--- a/hw/pci-host/bonito.c
+++ b/hw/pci-host/bonito.c
@@ -52,6 +52,7 @@
 #include "exec/address-spaces.h"
 #include "hw/misc/unimp.h"
 #include "hw/registerfields.h"
+#include "qom/object.h"
 
 /* #define DEBUG_BONITO */
 
@@ -200,7 +201,7 @@ FIELD(BONGENCFG, PCIQUEUE,      12, 1)
 
 typedef struct BonitoState BonitoState;
 
-typedef struct PCIBonitoState {
+struct PCIBonitoState {
     PCIDevice dev;
 
     BonitoState *pcihost;
@@ -228,7 +229,8 @@ typedef struct PCIBonitoState {
     MemoryRegion bonito_pciio;
     MemoryRegion bonito_localio;
 
-} PCIBonitoState;
+};
+typedef struct PCIBonitoState PCIBonitoState;
 
 struct BonitoState {
     PCIHostState parent_obj;
@@ -238,12 +240,12 @@ struct BonitoState {
 };
 
 #define TYPE_BONITO_PCI_HOST_BRIDGE "Bonito-pcihost"
-#define BONITO_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(BonitoState, (obj), TYPE_BONITO_PCI_HOST_BRIDGE)
+DECLARE_INSTANCE_CHECKER(BonitoState, BONITO_PCI_HOST_BRIDGE,
+                         TYPE_BONITO_PCI_HOST_BRIDGE)
 
 #define TYPE_PCI_BONITO "Bonito"
-#define PCI_BONITO(obj) \
-    OBJECT_CHECK(PCIBonitoState, (obj), TYPE_PCI_BONITO)
+DECLARE_INSTANCE_CHECKER(PCIBonitoState, PCI_BONITO,
+                         TYPE_PCI_BONITO)
 
 static void bonito_writel(void *opaque, hwaddr addr,
                           uint64_t val, unsigned size)
diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c
index 4b3af0c704..fd7d6dcc06 100644
--- a/hw/pci-host/grackle.c
+++ b/hw/pci-host/grackle.c
@@ -33,11 +33,13 @@
 #include "qapi/error.h"
 #include "qemu/module.h"
 #include "trace.h"
+#include "qom/object.h"
 
-#define GRACKLE_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(GrackleState, (obj), TYPE_GRACKLE_PCI_HOST_BRIDGE)
+typedef struct GrackleState GrackleState;
+DECLARE_INSTANCE_CHECKER(GrackleState, GRACKLE_PCI_HOST_BRIDGE,
+                         TYPE_GRACKLE_PCI_HOST_BRIDGE)
 
-typedef struct GrackleState {
+struct GrackleState {
     PCIHostState parent_obj;
 
     uint32_t ofw_addr;
@@ -46,7 +48,7 @@ typedef struct GrackleState {
     MemoryRegion pci_mmio;
     MemoryRegion pci_hole;
     MemoryRegion pci_io;
-} GrackleState;
+};
 
 /* Don't know if this matches real hardware, but it agrees with OHW.  */
 static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num)
diff --git a/hw/pci-host/i440fx.c b/hw/pci-host/i440fx.c
index 8ed2417f0c..93c62235ca 100644
--- a/hw/pci-host/i440fx.c
+++ b/hw/pci-host/i440fx.c
@@ -35,22 +35,24 @@
 #include "migration/vmstate.h"
 #include "qapi/visitor.h"
 #include "qemu/error-report.h"
+#include "qom/object.h"
 
 /*
  * I440FX chipset data sheet.
  * https://wiki.qemu.org/File:29054901.pdf
  */
 
-#define I440FX_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(I440FXState, (obj), TYPE_I440FX_PCI_HOST_BRIDGE)
+typedef struct I440FXState I440FXState;
+DECLARE_INSTANCE_CHECKER(I440FXState, I440FX_PCI_HOST_BRIDGE,
+                         TYPE_I440FX_PCI_HOST_BRIDGE)
 
-typedef struct I440FXState {
+struct I440FXState {
     PCIHostState parent_obj;
     Range pci_hole;
     uint64_t pci_hole64_size;
     bool pci_hole64_fix;
     uint32_t short_root_bus;
-} I440FXState;
+};
 
 #define I440FX_PAM      0x59
 #define I440FX_PAM_SIZE 7
diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index 82132c12ca..a7f9685005 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -18,6 +18,7 @@
 #include "hw/ppc/pnv.h"
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 #define phb3_error(phb, fmt, ...)                                       \
     qemu_log_mask(LOG_GUEST_ERROR, "phb3[%d:%d]: " fmt "\n",            \
@@ -877,8 +878,8 @@ static IOMMUTLBEntry pnv_phb3_translate_iommu(IOMMUMemoryRegion *iommu,
 }
 
 #define TYPE_PNV_PHB3_IOMMU_MEMORY_REGION "pnv-phb3-iommu-memory-region"
-#define PNV_PHB3_IOMMU_MEMORY_REGION(obj) \
-    OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_PNV_PHB3_IOMMU_MEMORY_REGION)
+DECLARE_INSTANCE_CHECKER(IOMMUMemoryRegion, PNV_PHB3_IOMMU_MEMORY_REGION,
+                         TYPE_PNV_PHB3_IOMMU_MEMORY_REGION)
 
 static void pnv_phb3_iommu_memory_region_class_init(ObjectClass *klass,
                                                     void *data)
diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 75ad766fe0..03daf40a23 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -21,6 +21,7 @@
 #include "hw/ppc/pnv_xscom.h"
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 #define phb_error(phb, fmt, ...)                                        \
     qemu_log_mask(LOG_GUEST_ERROR, "phb4[%d:%d]: " fmt "\n",            \
@@ -1042,8 +1043,8 @@ static IOMMUTLBEntry pnv_phb4_translate_iommu(IOMMUMemoryRegion *iommu,
 }
 
 #define TYPE_PNV_PHB4_IOMMU_MEMORY_REGION "pnv-phb4-iommu-memory-region"
-#define PNV_PHB4_IOMMU_MEMORY_REGION(obj) \
-    OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_PNV_PHB4_IOMMU_MEMORY_REGION)
+DECLARE_INSTANCE_CHECKER(IOMMUMemoryRegion, PNV_PHB4_IOMMU_MEMORY_REGION,
+                         TYPE_PNV_PHB4_IOMMU_MEMORY_REGION)
 
 static void pnv_phb4_iommu_memory_region_class_init(ObjectClass *klass,
                                                     void *data)
diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
index 1a62b2f8cc..f376374e24 100644
--- a/hw/pci-host/ppce500.c
+++ b/hw/pci-host/ppce500.c
@@ -24,6 +24,7 @@
 #include "qemu/bswap.h"
 #include "qemu/module.h"
 #include "hw/pci-host/ppce500.h"
+#include "qom/object.h"
 
 #ifdef DEBUG_PCI
 #define pci_debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
@@ -91,8 +92,9 @@ struct pci_inbound {
 
 #define TYPE_PPC_E500_PCI_HOST_BRIDGE "e500-pcihost"
 
-#define PPC_E500_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(PPCE500PCIState, (obj), TYPE_PPC_E500_PCI_HOST_BRIDGE)
+typedef struct PPCE500PCIState PPCE500PCIState;
+DECLARE_INSTANCE_CHECKER(PPCE500PCIState, PPC_E500_PCI_HOST_BRIDGE,
+                         TYPE_PPC_E500_PCI_HOST_BRIDGE)
 
 struct PPCE500PCIState {
     PCIHostState parent_obj;
@@ -114,8 +116,9 @@ struct PPCE500PCIState {
 };
 
 #define TYPE_PPC_E500_PCI_BRIDGE "e500-host-bridge"
-#define PPC_E500_PCI_BRIDGE(obj) \
-    OBJECT_CHECK(PPCE500PCIBridgeState, (obj), TYPE_PPC_E500_PCI_BRIDGE)
+typedef struct PPCE500PCIBridgeState PPCE500PCIBridgeState;
+DECLARE_INSTANCE_CHECKER(PPCE500PCIBridgeState, PPC_E500_PCI_BRIDGE,
+                         TYPE_PPC_E500_PCI_BRIDGE)
 
 struct PPCE500PCIBridgeState {
     /*< private >*/
@@ -125,8 +128,6 @@ struct PPCE500PCIBridgeState {
     MemoryRegion bar0;
 };
 
-typedef struct PPCE500PCIBridgeState PPCE500PCIBridgeState;
-typedef struct PPCE500PCIState PPCE500PCIState;
 
 static uint64_t pci_reg_read4(void *opaque, hwaddr addr,
                               unsigned size)
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
index 4b93fd2b01..b234fd7c8a 100644
--- a/hw/pci-host/prep.c
+++ b/hw/pci-host/prep.c
@@ -38,25 +38,28 @@
 #include "hw/or-irq.h"
 #include "exec/address-spaces.h"
 #include "elf.h"
+#include "qom/object.h"
 
 #define TYPE_RAVEN_PCI_DEVICE "raven"
 #define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost"
 
-#define RAVEN_PCI_DEVICE(obj) \
-    OBJECT_CHECK(RavenPCIState, (obj), TYPE_RAVEN_PCI_DEVICE)
+typedef struct RavenPCIState RavenPCIState;
+DECLARE_INSTANCE_CHECKER(RavenPCIState, RAVEN_PCI_DEVICE,
+                         TYPE_RAVEN_PCI_DEVICE)
 
-typedef struct RavenPCIState {
+struct RavenPCIState {
     PCIDevice dev;
 
     uint32_t elf_machine;
     char *bios_name;
     MemoryRegion bios;
-} RavenPCIState;
+};
 
-#define RAVEN_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(PREPPCIState, (obj), TYPE_RAVEN_PCI_HOST_BRIDGE)
+typedef struct PRePPCIState PREPPCIState;
+DECLARE_INSTANCE_CHECKER(PREPPCIState, RAVEN_PCI_HOST_BRIDGE,
+                         TYPE_RAVEN_PCI_HOST_BRIDGE)
 
-typedef struct PRePPCIState {
+struct PRePPCIState {
     PCIHostState parent_obj;
 
     qemu_or_irq *or_irq;
@@ -75,7 +78,7 @@ typedef struct PRePPCIState {
 
     int contiguous_map;
     bool is_legacy_prep;
-} PREPPCIState;
+};
 
 #define BIOS_SIZE (1 * MiB)
 
diff --git a/hw/pci-host/sabre.c b/hw/pci-host/sabre.c
index 0cc68585f8..5ac6283623 100644
--- a/hw/pci-host/sabre.c
+++ b/hw/pci-host/sabre.c
@@ -338,7 +338,7 @@ static void pci_sabre_set_irq(void *opaque, int irq_num, int level)
 
 static void sabre_reset(DeviceState *d)
 {
-    SabreState *s = SABRE_DEVICE(d);
+    SabreState *s = SABRE(d);
     PCIDevice *pci_dev;
     unsigned int i;
     uint16_t cmd;
@@ -376,7 +376,7 @@ static const MemoryRegionOps pci_config_ops = {
 
 static void sabre_realize(DeviceState *dev, Error **errp)
 {
-    SabreState *s = SABRE_DEVICE(dev);
+    SabreState *s = SABRE(dev);
     PCIHostState *phb = PCI_HOST_BRIDGE(dev);
     SysBusDevice *sbd = SYS_BUS_DEVICE(s);
     PCIDevice *pci_dev;
@@ -421,7 +421,7 @@ static void sabre_realize(DeviceState *dev, Error **errp)
 
 static void sabre_init(Object *obj)
 {
-    SabreState *s = SABRE_DEVICE(obj);
+    SabreState *s = SABRE(obj);
     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
     unsigned int i;
 
@@ -502,7 +502,7 @@ static const TypeInfo sabre_pci_info = {
 
 static char *sabre_ofw_unit_address(const SysBusDevice *dev)
 {
-    SabreState *s = SABRE_DEVICE(dev);
+    SabreState *s = SABRE(dev);
 
     return g_strdup_printf("%x,%x",
                (uint32_t)((s->special_base >> 32) & 0xffffffff),
diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
index 7e4aa467a2..3553277f94 100644
--- a/hw/pci-host/versatile.c
+++ b/hw/pci-host/versatile.c
@@ -18,6 +18,7 @@
 #include "hw/qdev-properties.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 /* Old and buggy versions of QEMU used the wrong mapping from
  * PCI IRQs to system interrupt lines. Unfortunately the Linux
@@ -71,7 +72,7 @@ enum {
     PCI_VPB_IRQMAP_FORCE_OK,
 };
 
-typedef struct {
+struct PCIVPBState {
     PCIHostState parent_obj;
 
     qemu_irq irq[4];
@@ -100,7 +101,8 @@ typedef struct {
     uint32_t selfid;
     uint32_t flags;
     uint8_t irq_mapping;
-} PCIVPBState;
+};
+typedef struct PCIVPBState PCIVPBState;
 
 static void pci_vpb_update_window(PCIVPBState *s, int i)
 {
@@ -156,12 +158,12 @@ static const VMStateDescription pci_vpb_vmstate = {
 };
 
 #define TYPE_VERSATILE_PCI "versatile_pci"
-#define PCI_VPB(obj) \
-    OBJECT_CHECK(PCIVPBState, (obj), TYPE_VERSATILE_PCI)
+DECLARE_INSTANCE_CHECKER(PCIVPBState, PCI_VPB,
+                         TYPE_VERSATILE_PCI)
 
 #define TYPE_VERSATILE_PCI_HOST "versatile_pci_host"
-#define PCI_VPB_HOST(obj) \
-    OBJECT_CHECK(PCIDevice, (obj), TYPE_VERSATILE_PCI_HOST)
+DECLARE_INSTANCE_CHECKER(PCIDevice, PCI_VPB_HOST,
+                         TYPE_VERSATILE_PCI_HOST)
 
 typedef enum {
     PCI_IMAP0 = 0x0,
diff --git a/hw/ppc/e500-ccsr.h b/hw/ppc/e500-ccsr.h
index 12a2ba4b97..de4b9d2bc3 100644
--- a/hw/ppc/e500-ccsr.h
+++ b/hw/ppc/e500-ccsr.h
@@ -2,16 +2,19 @@
 #define E500_CCSR_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
-typedef struct PPCE500CCSRState {
+struct PPCE500CCSRState {
     /*< private >*/
     SysBusDevice parent;
     /*< public >*/
 
     MemoryRegion ccsr_space;
-} PPCE500CCSRState;
+};
+typedef struct PPCE500CCSRState PPCE500CCSRState;
 
 #define TYPE_CCSR "e500-ccsr"
-#define CCSR(obj) OBJECT_CHECK(PPCE500CCSRState, (obj), TYPE_CCSR)
+DECLARE_INSTANCE_CHECKER(PPCE500CCSRState, CCSR,
+                         TYPE_CCSR)
 
 #endif /* E500_CCSR_H */
diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h
index 3fd9f825ca..63870751ff 100644
--- a/hw/ppc/e500.h
+++ b/hw/ppc/e500.h
@@ -3,8 +3,9 @@
 
 #include "hw/boards.h"
 #include "hw/platform-bus.h"
+#include "qom/object.h"
 
-typedef struct PPCE500MachineState {
+struct PPCE500MachineState {
     /*< private >*/
     MachineState parent_obj;
 
@@ -12,9 +13,10 @@ typedef struct PPCE500MachineState {
      * board supports dynamic sysbus devices
      */
     PlatformBusDevice *pbus_dev;
-} PPCE500MachineState;
+};
+typedef struct PPCE500MachineState PPCE500MachineState;
 
-typedef struct PPCE500MachineClass {
+struct PPCE500MachineClass {
     /*< private >*/
     MachineClass parent_class;
 
@@ -36,18 +38,15 @@ typedef struct PPCE500MachineClass {
     hwaddr pci_mmio_base;
     hwaddr pci_mmio_bus_base;
     hwaddr spin_base;
-} PPCE500MachineClass;
+};
+typedef struct PPCE500MachineClass PPCE500MachineClass;
 
 void ppce500_init(MachineState *machine);
 
 hwaddr booke206_page_size_to_tlb(uint64_t size);
 
 #define TYPE_PPCE500_MACHINE      "ppce500-base-machine"
-#define PPCE500_MACHINE(obj) \
-    OBJECT_CHECK(PPCE500MachineState, (obj), TYPE_PPCE500_MACHINE)
-#define PPCE500_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(PPCE500MachineClass, obj, TYPE_PPCE500_MACHINE)
-#define PPCE500_MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(PPCE500MachineClass, klass, TYPE_PPCE500_MACHINE)
+DECLARE_OBJ_CHECKERS(PPCE500MachineState, PPCE500MachineClass,
+                     PPCE500_MACHINE, TYPE_PPCE500_MACHINE)
 
 #endif
diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index 6af87d1fa0..2b6425f600 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -34,6 +34,7 @@
 #include "hw/misc/mos6522.h"
 #include "hw/pci/pci_host.h"
 #include "hw/pci-host/uninorth.h"
+#include "qom/object.h"
 
 /* SMP is not enabled, for now */
 #define MAX_CPUS 1
@@ -71,29 +72,31 @@
 
 /* Core99 machine */
 #define TYPE_CORE99_MACHINE MACHINE_TYPE_NAME("mac99")
-#define CORE99_MACHINE(obj) OBJECT_CHECK(Core99MachineState, (obj), \
-                                         TYPE_CORE99_MACHINE)
+typedef struct Core99MachineState Core99MachineState;
+DECLARE_INSTANCE_CHECKER(Core99MachineState, CORE99_MACHINE,
+                         TYPE_CORE99_MACHINE)
 
 #define CORE99_VIA_CONFIG_CUDA     0x0
 #define CORE99_VIA_CONFIG_PMU      0x1
 #define CORE99_VIA_CONFIG_PMU_ADB  0x2
 
-typedef struct Core99MachineState {
+struct Core99MachineState {
     /*< private >*/
     MachineState parent;
 
     uint8_t via_config;
-} Core99MachineState;
+};
 
 /* Grackle PCI */
 #define TYPE_GRACKLE_PCI_HOST_BRIDGE "grackle-pcihost"
 
 /* Mac NVRAM */
 #define TYPE_MACIO_NVRAM "macio-nvram"
-#define MACIO_NVRAM(obj) \
-    OBJECT_CHECK(MacIONVRAMState, (obj), TYPE_MACIO_NVRAM)
+typedef struct MacIONVRAMState MacIONVRAMState;
+DECLARE_INSTANCE_CHECKER(MacIONVRAMState, MACIO_NVRAM,
+                         TYPE_MACIO_NVRAM)
 
-typedef struct MacIONVRAMState {
+struct MacIONVRAMState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -103,7 +106,7 @@ typedef struct MacIONVRAMState {
 
     MemoryRegion mem;
     uint8_t *data;
-} MacIONVRAMState;
+};
 
 void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len);
 #endif /* PPC_MAC_H */
diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c
index b96ea36f98..b76b5e4701 100644
--- a/hw/ppc/mpc8544_guts.c
+++ b/hw/ppc/mpc8544_guts.c
@@ -22,6 +22,7 @@
 #include "sysemu/runstate.h"
 #include "cpu.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define MPC8544_GUTS_MMIO_SIZE        0x1000
 #define MPC8544_GUTS_RSTCR_RESET      0x02
@@ -54,7 +55,9 @@
 #define MPC8544_GUTS_ADDR_SRDS2CR3    0xF18
 
 #define TYPE_MPC8544_GUTS "mpc8544-guts"
-#define MPC8544_GUTS(obj) OBJECT_CHECK(GutsState, (obj), TYPE_MPC8544_GUTS)
+typedef struct GutsState GutsState;
+DECLARE_INSTANCE_CHECKER(GutsState, MPC8544_GUTS,
+                         TYPE_MPC8544_GUTS)
 
 struct GutsState {
     /*< private >*/
@@ -64,7 +67,6 @@ struct GutsState {
     MemoryRegion iomem;
 };
 
-typedef struct GutsState GutsState;
 
 static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr,
                                   unsigned size)
diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c
index 2ee2d4f4fc..a564fcd600 100644
--- a/hw/ppc/ppc440_pcix.c
+++ b/hw/ppc/ppc440_pcix.c
@@ -30,6 +30,7 @@
 #include "hw/pci/pci_host.h"
 #include "exec/address-spaces.h"
 #include "trace.h"
+#include "qom/object.h"
 
 struct PLBOutMap {
     uint64_t la;
@@ -45,13 +46,14 @@ struct PLBInMap {
 };
 
 #define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host"
-#define PPC440_PCIX_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE)
+typedef struct PPC440PCIXState PPC440PCIXState;
+DECLARE_INSTANCE_CHECKER(PPC440PCIXState, PPC440_PCIX_HOST_BRIDGE,
+                         TYPE_PPC440_PCIX_HOST_BRIDGE)
 
 #define PPC440_PCIX_NR_POMS 3
 #define PPC440_PCIX_NR_PIMS 3
 
-typedef struct PPC440PCIXState {
+struct PPC440PCIXState {
     PCIHostState parent_obj;
 
     PCIDevice *dev;
@@ -65,7 +67,7 @@ typedef struct PPC440PCIXState {
     MemoryRegion container;
     MemoryRegion iomem;
     MemoryRegion busmem;
-} PPC440PCIXState;
+};
 
 #define PPC440_REG_BASE     0x80000
 #define PPC440_REG_SIZE     0xff
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 38fc392438..d9ca6bba9b 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -24,6 +24,7 @@
 #include "sysemu/block-backend.h"
 #include "sysemu/reset.h"
 #include "ppc440.h"
+#include "qom/object.h"
 
 /*****************************************************************************/
 /* L2 Cache as SRAM */
@@ -1032,10 +1033,11 @@ void ppc4xx_dma_init(CPUPPCState *env, int dcr_base)
 #include "hw/pci/pcie_host.h"
 
 #define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host"
-#define PPC460EX_PCIE_HOST(obj) \
-    OBJECT_CHECK(PPC460EXPCIEState, (obj), TYPE_PPC460EX_PCIE_HOST)
+typedef struct PPC460EXPCIEState PPC460EXPCIEState;
+DECLARE_INSTANCE_CHECKER(PPC460EXPCIEState, PPC460EX_PCIE_HOST,
+                         TYPE_PPC460EX_PCIE_HOST)
 
-typedef struct PPC460EXPCIEState {
+struct PPC460EXPCIEState {
     PCIExpressHost host;
 
     MemoryRegion iomem;
@@ -1056,7 +1058,7 @@ typedef struct PPC460EXPCIEState {
     uint32_t reg_mask;
     uint32_t special;
     uint32_t cfg;
-} PPC460EXPCIEState;
+};
 
 #define DCRN_PCIE0_BASE 0x100
 #define DCRN_PCIE1_BASE 0x120
diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c
index 503ef46b39..c24bac96c3 100644
--- a/hw/ppc/ppc4xx_pci.c
+++ b/hw/ppc/ppc4xx_pci.c
@@ -30,6 +30,7 @@
 #include "hw/pci/pci_host.h"
 #include "exec/address-spaces.h"
 #include "trace.h"
+#include "qom/object.h"
 
 struct PCIMasterMap {
     uint32_t la;
@@ -43,8 +44,9 @@ struct PCITargetMap {
     uint32_t la;
 };
 
-#define PPC4xx_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(PPC4xxPCIState, (obj), TYPE_PPC4xx_PCI_HOST_BRIDGE)
+typedef struct PPC4xxPCIState PPC4xxPCIState;
+DECLARE_INSTANCE_CHECKER(PPC4xxPCIState, PPC4xx_PCI_HOST_BRIDGE,
+                         TYPE_PPC4xx_PCI_HOST_BRIDGE)
 
 #define PPC4xx_PCI_NR_PMMS 3
 #define PPC4xx_PCI_NR_PTMS 2
@@ -59,7 +61,6 @@ struct PPC4xxPCIState {
     MemoryRegion container;
     MemoryRegion iomem;
 };
-typedef struct PPC4xxPCIState PPC4xxPCIState;
 
 #define PCIC0_CFGADDR       0x0
 #define PCIC0_CFGDATA       0x4
diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c
index 66c1065db2..cd8000ad73 100644
--- a/hw/ppc/ppce500_spin.c
+++ b/hw/ppc/ppce500_spin.c
@@ -34,6 +34,7 @@
 #include "hw/sysbus.h"
 #include "sysemu/hw_accel.h"
 #include "e500.h"
+#include "qom/object.h"
 
 #define MAX_CPUS 32
 
@@ -46,14 +47,16 @@ typedef struct spin_info {
 } QEMU_PACKED SpinInfo;
 
 #define TYPE_E500_SPIN "e500-spin"
-#define E500_SPIN(obj) OBJECT_CHECK(SpinState, (obj), TYPE_E500_SPIN)
+typedef struct SpinState SpinState;
+DECLARE_INSTANCE_CHECKER(SpinState, E500_SPIN,
+                         TYPE_E500_SPIN)
 
-typedef struct SpinState {
+struct SpinState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
     SpinInfo spin[MAX_CPUS];
-} SpinState;
+};
 
 static void spin_reset(DeviceState *dev)
 {
diff --git a/hw/ppc/prep_systemio.c b/hw/ppc/prep_systemio.c
index bbc51b6e9a..d1e2fb3f8b 100644
--- a/hw/ppc/prep_systemio.c
+++ b/hw/ppc/prep_systemio.c
@@ -28,6 +28,7 @@
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
 #include "exec/address-spaces.h"
+#include "qom/object.h"
 #include "qemu/error-report.h" /* for error_report() */
 #include "qemu/module.h"
 #include "sysemu/runstate.h"
@@ -35,13 +36,14 @@
 #include "trace.h"
 
 #define TYPE_PREP_SYSTEMIO "prep-systemio"
-#define PREP_SYSTEMIO(obj) \
-    OBJECT_CHECK(PrepSystemIoState, (obj), TYPE_PREP_SYSTEMIO)
+typedef struct PrepSystemIoState PrepSystemIoState;
+DECLARE_INSTANCE_CHECKER(PrepSystemIoState, PREP_SYSTEMIO,
+                         TYPE_PREP_SYSTEMIO)
 
 /* Bit as defined in PowerPC Reference Plaform v1.1, sect. 6.1.5, p. 132 */
 #define PREP_BIT(n) (1 << (7 - (n)))
 
-typedef struct PrepSystemIoState {
+struct PrepSystemIoState {
     ISADevice parent_obj;
     MemoryRegion ppc_parity_mem;
 
@@ -53,7 +55,7 @@ typedef struct PrepSystemIoState {
     uint8_t ibm_planar_id; /* 0x0852 */
     qemu_irq softreset_irq;
     PortioList portio;
-} PrepSystemIoState;
+};
 
 /* PORT 0092 -- Special Port 92 (Read/Write) */
 
diff --git a/hw/ppc/rs6000_mc.c b/hw/ppc/rs6000_mc.c
index ce97365f5e..8611ffa96d 100644
--- a/hw/ppc/rs6000_mc.c
+++ b/hw/ppc/rs6000_mc.c
@@ -26,12 +26,14 @@
 #include "hw/boards.h"
 #include "qapi/error.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define TYPE_RS6000MC "rs6000-mc"
-#define RS6000MC_DEVICE(obj) \
-    OBJECT_CHECK(RS6000MCState, (obj), TYPE_RS6000MC)
+typedef struct RS6000MCState RS6000MCState;
+DECLARE_INSTANCE_CHECKER(RS6000MCState, RS6000MC,
+                         TYPE_RS6000MC)
 
-typedef struct RS6000MCState {
+struct RS6000MCState {
     ISADevice parent_obj;
     /* see US patent 5,684,979 for details (expired 2001-11-04) */
     uint32_t ram_size;
@@ -41,7 +43,7 @@ typedef struct RS6000MCState {
     uint32_t end_address[8];
     uint8_t port0820_index;
     PortioList portio;
-} RS6000MCState;
+};
 
 /* P0RT 0803 -- SIMM ID Register (32/8 MB) (Read Only) */
 
@@ -141,7 +143,7 @@ static const MemoryRegionPortio rs6000mc_port_list[] = {
 
 static void rs6000mc_realize(DeviceState *dev, Error **errp)
 {
-    RS6000MCState *s = RS6000MC_DEVICE(dev);
+    RS6000MCState *s = RS6000MC(dev);
     int socket = 0;
     unsigned int ram_size = s->ram_size / MiB;
     Error *local_err = NULL;
diff --git a/hw/ppc/spapr_rng.c b/hw/ppc/spapr_rng.c
index 85bf64d68e..6c99633faa 100644
--- a/hw/ppc/spapr_rng.c
+++ b/hw/ppc/spapr_rng.c
@@ -28,9 +28,11 @@
 #include "hw/ppc/spapr.h"
 #include "hw/qdev-properties.h"
 #include "kvm_ppc.h"
+#include "qom/object.h"
 
-#define SPAPR_RNG(obj) \
-    OBJECT_CHECK(SpaprRngState, (obj), TYPE_SPAPR_RNG)
+typedef struct SpaprRngState SpaprRngState;
+DECLARE_INSTANCE_CHECKER(SpaprRngState, SPAPR_RNG,
+                         TYPE_SPAPR_RNG)
 
 struct SpaprRngState {
     /*< private >*/
@@ -38,7 +40,6 @@ struct SpaprRngState {
     RngBackend *backend;
     bool use_kvm;
 };
-typedef struct SpaprRngState SpaprRngState;
 
 struct HRandomData {
     QemuSemaphore sem;
diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
index 7c0be4102e..dcc06d49b5 100644
--- a/hw/ppc/trace-events
+++ b/hw/ppc/trace-events
@@ -9,11 +9,8 @@ spapr_pci_msi_write(uint64_t addr, uint64_t data, uint32_t dt_irq) "@0x%"PRIx64"
 spapr_pci_lsi_set(const char *busname, int pin, uint32_t irq) "%s PIN%d IRQ %u"
 spapr_pci_msi_retry(unsigned config_addr, unsigned req_num, unsigned max_irqs) "Guest device at 0x%x asked %u, have only %u"
 
-# spapr.c
-spapr_cas_failed(unsigned long n) "DT diff buffer is too small: %ld bytes"
-spapr_cas_continue(unsigned long n) "Copy changes to the guest: %ld bytes"
-
 # spapr_hcall.c
+spapr_cas_continue(unsigned long n) "Copy changes to the guest: %ld bytes"
 spapr_cas_pvr(uint32_t cur_pvr, bool explicit_match, uint32_t new_pvr) "current=0x%x, explicit_match=%u, new=0x%x"
 spapr_h_resize_hpt_prepare(uint64_t flags, uint64_t shift) "flags=0x%"PRIx64", shift=%"PRIu64
 spapr_h_resize_hpt_commit(uint64_t flags, uint64_t shift) "flags=0x%"PRIx64", shift=%"PRIu64
@@ -21,7 +18,7 @@ spapr_update_dt(unsigned cb) "New blob %u bytes"
 spapr_update_dt_failed_size(unsigned cbold, unsigned cbnew, unsigned magic) "Old blob %u bytes, new blob %u bytes, magic 0x%x"
 spapr_update_dt_failed_check(unsigned cbold, unsigned cbnew, unsigned magic) "Old blob %u bytes, new blob %u bytes, magic 0x%x"
 
-# spapr_hcall_tpm.c
+# spapr_tpm_proxy.c
 spapr_h_tpm_comm(const char *device_path, uint64_t operation) "tpm_device_path=%s operation=0x%"PRIu64
 spapr_tpm_execute(uint64_t data_in, uint64_t data_in_sz, uint64_t data_out, uint64_t data_out_sz) "data_in=0x%"PRIx64", data_in_sz=%"PRIu64", data_out=0x%"PRIx64", data_out_sz=%"PRIu64
 
@@ -77,9 +74,6 @@ spapr_vio_free_crq(uint32_t reg) "CRQ for dev 0x%" PRIx32 " freed"
 # ppc.c
 ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "adjusted from 0x%"PRIx64" to 0x%"PRIx64", diff %"PRId64" (%"PRId64"s)"
 
-# prep.c
-prep_io_800_writeb(uint32_t addr, uint32_t val) "0x%08" PRIx32 " => 0x%02" PRIx32
-prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRIx32
 
 # prep_systemio.c
 prep_systemio_read(uint32_t addr, uint32_t val) "read addr=0x%x val=0x%x"
diff --git a/hw/rdma/vmw/pvrdma.h b/hw/rdma/vmw/pvrdma.h
index a8a04a253c..1d36a76f1e 100644
--- a/hw/rdma/vmw/pvrdma.h
+++ b/hw/rdma/vmw/pvrdma.h
@@ -29,6 +29,7 @@
 #include "standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h"
 #include "standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h"
 #include "pvrdma_dev_ring.h"
+#include "qom/object.h"
 
 /* BARs */
 #define RDMA_MSIX_BAR_IDX    0
@@ -78,7 +79,7 @@ typedef struct PVRDMADevStats {
     uint64_t interrupts;
 } PVRDMADevStats;
 
-typedef struct PVRDMADev {
+struct PVRDMADev {
     PCIDevice parent_obj;
     MemoryRegion msix;
     MemoryRegion regs;
@@ -98,8 +99,10 @@ typedef struct PVRDMADev {
     VMXNET3State *func0;
     Notifier shutdown_notifier;
     PVRDMADevStats stats;
-} PVRDMADev;
-#define PVRDMA_DEV(dev) OBJECT_CHECK(PVRDMADev, (dev), PVRDMA_HW_NAME)
+};
+typedef struct PVRDMADev PVRDMADev;
+DECLARE_INSTANCE_CHECKER(PVRDMADev, PVRDMA_DEV,
+                         PVRDMA_HW_NAME)
 
 static inline int get_reg_val(PVRDMADev *dev, hwaddr addr, uint32_t *val)
 {
diff --git a/hw/rtc/ds1338.c b/hw/rtc/ds1338.c
index 588a9ba9be..10fac3d9c9 100644
--- a/hw/rtc/ds1338.c
+++ b/hw/rtc/ds1338.c
@@ -16,6 +16,7 @@
 #include "migration/vmstate.h"
 #include "qemu/bcd.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 /* Size of NVRAM including both the user-accessible area and the
  * secondary register area.
@@ -29,9 +30,11 @@
 #define CTRL_OSF   0x20
 
 #define TYPE_DS1338 "ds1338"
-#define DS1338(obj) OBJECT_CHECK(DS1338State, (obj), TYPE_DS1338)
+typedef struct DS1338State DS1338State;
+DECLARE_INSTANCE_CHECKER(DS1338State, DS1338,
+                         TYPE_DS1338)
 
-typedef struct DS1338State {
+struct DS1338State {
     I2CSlave parent_obj;
 
     int64_t offset;
@@ -39,7 +42,7 @@ typedef struct DS1338State {
     uint8_t nvram[NVRAM_SIZE];
     int32_t ptr;
     bool addr_byte;
-} DS1338State;
+};
 
 static const VMStateDescription vmstate_ds1338 = {
     .name = "ds1338",
diff --git a/hw/rtc/exynos4210_rtc.c b/hw/rtc/exynos4210_rtc.c
index f85483a07f..f8a4fe8a47 100644
--- a/hw/rtc/exynos4210_rtc.c
+++ b/hw/rtc/exynos4210_rtc.c
@@ -38,6 +38,7 @@
 #include "hw/irq.h"
 
 #include "hw/arm/exynos4210.h"
+#include "qom/object.h"
 
 #define DEBUG_RTC 0
 
@@ -84,10 +85,11 @@
 #define     RTC_BASE_FREQ       32768
 
 #define TYPE_EXYNOS4210_RTC "exynos4210.rtc"
-#define EXYNOS4210_RTC(obj) \
-    OBJECT_CHECK(Exynos4210RTCState, (obj), TYPE_EXYNOS4210_RTC)
+typedef struct Exynos4210RTCState Exynos4210RTCState;
+DECLARE_INSTANCE_CHECKER(Exynos4210RTCState, EXYNOS4210_RTC,
+                         TYPE_EXYNOS4210_RTC)
 
-typedef struct Exynos4210RTCState {
+struct Exynos4210RTCState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -113,7 +115,7 @@ typedef struct Exynos4210RTCState {
     qemu_irq        alm_irq;    /* alarm irq */
 
     struct tm   current_tm;     /* current time */
-} Exynos4210RTCState;
+};
 
 #define TICCKSEL(value) ((value & (0x0F << 4)) >> 4)
 
diff --git a/hw/rtc/m41t80.c b/hw/rtc/m41t80.c
index 914ecac8f4..0b7048c3f4 100644
--- a/hw/rtc/m41t80.c
+++ b/hw/rtc/m41t80.c
@@ -14,14 +14,17 @@
 #include "qemu/timer.h"
 #include "qemu/bcd.h"
 #include "hw/i2c/i2c.h"
+#include "qom/object.h"
 
 #define TYPE_M41T80 "m41t80"
-#define M41T80(obj) OBJECT_CHECK(M41t80State, (obj), TYPE_M41T80)
+typedef struct M41t80State M41t80State;
+DECLARE_INSTANCE_CHECKER(M41t80State, M41T80,
+                         TYPE_M41T80)
 
-typedef struct M41t80State {
+struct M41t80State {
     I2CSlave parent_obj;
     int8_t addr;
-} M41t80State;
+};
 
 static void m41t80_realize(DeviceState *dev, Error **errp)
 {
diff --git a/hw/rtc/m48t59-isa.c b/hw/rtc/m48t59-isa.c
index 50430b7a85..cae315e488 100644
--- a/hw/rtc/m48t59-isa.c
+++ b/hw/rtc/m48t59-isa.c
@@ -30,26 +30,25 @@
 #include "m48t59-internal.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define TYPE_M48TXX_ISA "isa-m48txx"
-#define M48TXX_ISA_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(M48txxISADeviceClass, (obj), TYPE_M48TXX_ISA)
-#define M48TXX_ISA_CLASS(klass) \
-    OBJECT_CLASS_CHECK(M48txxISADeviceClass, (klass), TYPE_M48TXX_ISA)
-#define M48TXX_ISA(obj) \
-    OBJECT_CHECK(M48txxISAState, (obj), TYPE_M48TXX_ISA)
-
-typedef struct M48txxISAState {
+typedef struct M48txxISADeviceClass M48txxISADeviceClass;
+typedef struct M48txxISAState M48txxISAState;
+DECLARE_OBJ_CHECKERS(M48txxISAState, M48txxISADeviceClass,
+                     M48TXX_ISA, TYPE_M48TXX_ISA)
+
+struct M48txxISAState {
     ISADevice parent_obj;
     M48t59State state;
     uint32_t io_base;
     MemoryRegion io;
-} M48txxISAState;
+};
 
-typedef struct M48txxISADeviceClass {
+struct M48txxISADeviceClass {
     ISADeviceClass parent_class;
     M48txxInfo info;
-} M48txxISADeviceClass;
+};
 
 static M48txxInfo m48txx_isa_info[] = {
     {
diff --git a/hw/rtc/m48t59.c b/hw/rtc/m48t59.c
index b428a06045..6525206976 100644
--- a/hw/rtc/m48t59.c
+++ b/hw/rtc/m48t59.c
@@ -40,14 +40,13 @@
 
 #include "m48t59-internal.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 #define TYPE_M48TXX_SYS_BUS "sysbus-m48txx"
-#define M48TXX_SYS_BUS_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(M48txxSysBusDeviceClass, (obj), TYPE_M48TXX_SYS_BUS)
-#define M48TXX_SYS_BUS_CLASS(klass) \
-    OBJECT_CLASS_CHECK(M48txxSysBusDeviceClass, (klass), TYPE_M48TXX_SYS_BUS)
-#define M48TXX_SYS_BUS(obj) \
-    OBJECT_CHECK(M48txxSysBusState, (obj), TYPE_M48TXX_SYS_BUS)
+typedef struct M48txxSysBusDeviceClass M48txxSysBusDeviceClass;
+typedef struct M48txxSysBusState M48txxSysBusState;
+DECLARE_OBJ_CHECKERS(M48txxSysBusState, M48txxSysBusDeviceClass,
+                     M48TXX_SYS_BUS, TYPE_M48TXX_SYS_BUS)
 
 /*
  * Chipset docs:
@@ -56,16 +55,16 @@
  * http://www.st.com/stonline/products/literature/od/7001/m48t59y.pdf
  */
 
-typedef struct M48txxSysBusState {
+struct M48txxSysBusState {
     SysBusDevice parent_obj;
     M48t59State state;
     MemoryRegion io;
-} M48txxSysBusState;
+};
 
-typedef struct M48txxSysBusDeviceClass {
+struct M48txxSysBusDeviceClass {
     SysBusDeviceClass parent_class;
     M48txxInfo info;
-} M48txxSysBusDeviceClass;
+};
 
 static M48txxInfo m48txx_sysbus_info[] = {
     {
diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
index 52caea8654..18979d25d0 100644
--- a/hw/rtc/sun4v-rtc.c
+++ b/hw/rtc/sun4v-rtc.c
@@ -16,16 +16,19 @@
 #include "qemu/timer.h"
 #include "hw/rtc/sun4v-rtc.h"
 #include "trace.h"
+#include "qom/object.h"
 
 
 #define TYPE_SUN4V_RTC "sun4v_rtc"
-#define SUN4V_RTC(obj) OBJECT_CHECK(Sun4vRtc, (obj), TYPE_SUN4V_RTC)
+typedef struct Sun4vRtc Sun4vRtc;
+DECLARE_INSTANCE_CHECKER(Sun4vRtc, SUN4V_RTC,
+                         TYPE_SUN4V_RTC)
 
-typedef struct Sun4vRtc {
+struct Sun4vRtc {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
-} Sun4vRtc;
+};
 
 static uint64_t sun4v_rtc_read(void *opaque, hwaddr addr,
                                 unsigned size)
diff --git a/hw/rtc/trace-events b/hw/rtc/trace-events
index 1bc7147d0e..8bdcf74264 100644
--- a/hw/rtc/trace-events
+++ b/hw/rtc/trace-events
@@ -18,7 +18,7 @@ pl031_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
 pl031_alarm_raised(void) "alarm raised"
 pl031_set_alarm(uint32_t ticks) "alarm set for %u ticks"
 
-# aspeed-rtc.c
+# aspeed_rtc.c
 aspeed_rtc_read(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64
 aspeed_rtc_write(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64
 
diff --git a/hw/rtc/twl92230.c b/hw/rtc/twl92230.c
index d0011be89e..4f83eff5c3 100644
--- a/hw/rtc/twl92230.c
+++ b/hw/rtc/twl92230.c
@@ -29,13 +29,16 @@
 #include "sysemu/sysemu.h"
 #include "qemu/bcd.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define VERBOSE 1
 
 #define TYPE_TWL92230 "twl92230"
-#define TWL92230(obj) OBJECT_CHECK(MenelausState, (obj), TYPE_TWL92230)
+typedef struct MenelausState MenelausState;
+DECLARE_INSTANCE_CHECKER(MenelausState, TWL92230,
+                         TYPE_TWL92230)
 
-typedef struct MenelausState {
+struct MenelausState {
     I2CSlave parent_obj;
 
     int firstbyte;
@@ -71,7 +74,7 @@ typedef struct MenelausState {
     uint16_t rtc_next_vmstate;
     qemu_irq out[4];
     uint8_t pwrbtn_state;
-} MenelausState;
+};
 
 static inline void menelaus_update(MenelausState *s)
 {
diff --git a/hw/rx/rx-gdbsim.c b/hw/rx/rx-gdbsim.c
index 6914de2e59..417ec0564b 100644
--- a/hw/rx/rx-gdbsim.c
+++ b/hw/rx/rx-gdbsim.c
@@ -30,34 +30,33 @@
 #include "sysemu/qtest.h"
 #include "sysemu/device_tree.h"
 #include "hw/boards.h"
+#include "qom/object.h"
 
 /* Same address of GDB integrated simulator */
 #define SDRAM_BASE  EXT_CS_BASE
 
-typedef struct RxGdbSimMachineClass {
+struct RxGdbSimMachineClass {
     /*< private >*/
     MachineClass parent_class;
     /*< public >*/
     const char *mcu_name;
     uint32_t xtal_freq_hz;
-} RxGdbSimMachineClass;
+};
+typedef struct RxGdbSimMachineClass RxGdbSimMachineClass;
 
-typedef struct RxGdbSimMachineState {
+struct RxGdbSimMachineState {
     /*< private >*/
     MachineState parent_obj;
     /*< public >*/
     RX62NState mcu;
-} RxGdbSimMachineState;
+};
+typedef struct RxGdbSimMachineState RxGdbSimMachineState;
 
 #define TYPE_RX_GDBSIM_MACHINE MACHINE_TYPE_NAME("rx62n-common")
 
-#define RX_GDBSIM_MACHINE(obj) \
-    OBJECT_CHECK(RxGdbSimMachineState, (obj), TYPE_RX_GDBSIM_MACHINE)
+DECLARE_OBJ_CHECKERS(RxGdbSimMachineState, RxGdbSimMachineClass,
+                     RX_GDBSIM_MACHINE, TYPE_RX_GDBSIM_MACHINE)
 
-#define RX_GDBSIM_MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(RxGdbSimMachineClass, (klass), TYPE_RX_GDBSIM_MACHINE)
-#define RX_GDBSIM_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(RxGdbSimMachineClass, (obj), TYPE_RX_GDBSIM_MACHINE)
 
 static void rx_load_image(RXCPU *cpu, const char *filename,
                           uint32_t start, uint32_t size)
diff --git a/hw/rx/rx62n.c b/hw/rx/rx62n.c
index b9c217ebfa..6eb4eea700 100644
--- a/hw/rx/rx62n.c
+++ b/hw/rx/rx62n.c
@@ -31,6 +31,7 @@
 #include "sysemu/sysemu.h"
 #include "sysemu/qtest.h"
 #include "cpu.h"
+#include "qom/object.h"
 
 /*
  * RX62N Internal Memory
@@ -60,7 +61,7 @@
 #define RX62N_XTAL_MAX_HZ (14 * 1000 * 1000)
 #define RX62N_PCLK_MAX_HZ (50 * 1000 * 1000)
 
-typedef struct RX62NClass {
+struct RX62NClass {
     /*< private >*/
     DeviceClass parent_class;
     /*< public >*/
@@ -68,12 +69,11 @@ typedef struct RX62NClass {
     uint64_t ram_size;
     uint64_t rom_flash_size;
     uint64_t data_flash_size;
-} RX62NClass;
+};
+typedef struct RX62NClass RX62NClass;
 
-#define RX62N_MCU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(RX62NClass, (klass), TYPE_RX62N_MCU)
-#define RX62N_MCU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(RX62NClass, (obj), TYPE_RX62N_MCU)
+DECLARE_CLASS_CHECKERS(RX62NClass, RX62N_MCU,
+                       TYPE_RX62N_MCU)
 
 /*
  * IRQ -> IPR mapping table
diff --git a/hw/s390x/ap-device.c b/hw/s390x/ap-device.c
index fc0b41e937..237d1f19c5 100644
--- a/hw/s390x/ap-device.c
+++ b/hw/s390x/ap-device.c
@@ -21,7 +21,7 @@ static void ap_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo ap_device_info = {
-    .name = AP_DEVICE_TYPE,
+    .name = TYPE_AP_DEVICE,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(APDevice),
     .class_size = sizeof(DeviceClass),
diff --git a/hw/s390x/ccw-device.h b/hw/s390x/ccw-device.h
index 4e6af287e7..cf7d492084 100644
--- a/hw/s390x/ccw-device.h
+++ b/hw/s390x/ccw-device.h
@@ -15,7 +15,7 @@
 #include "hw/qdev-core.h"
 #include "hw/s390x/css.h"
 
-typedef struct CcwDevice {
+struct CcwDevice {
     DeviceState parent_obj;
     SubchDev *sch;
     /* <cssid>.<ssid>.<device number> */
@@ -25,18 +25,20 @@ typedef struct CcwDevice {
     CssDevId dev_id;
     /* The actual busid of the virtual subchannel. */
     CssDevId subch_id;
-} CcwDevice;
+};
+typedef struct CcwDevice CcwDevice;
 
 extern const VMStateDescription vmstate_ccw_dev;
 #define VMSTATE_CCW_DEVICE(_field, _state)                     \
     VMSTATE_STRUCT(_field, _state, 1, vmstate_ccw_dev, CcwDevice)
 
-typedef struct CCWDeviceClass {
+struct CCWDeviceClass {
     DeviceClass parent_class;
     void (*unplug)(HotplugHandler *, DeviceState *, Error **);
     void (*realize)(CcwDevice *, Error **);
     void (*refill_ids)(CcwDevice *);
-} CCWDeviceClass;
+};
+typedef struct CCWDeviceClass CCWDeviceClass;
 
 static inline CcwDevice *to_ccw_dev_fast(DeviceState *d)
 {
@@ -45,10 +47,7 @@ static inline CcwDevice *to_ccw_dev_fast(DeviceState *d)
 
 #define TYPE_CCW_DEVICE "ccw-device"
 
-#define CCW_DEVICE(obj) OBJECT_CHECK(CcwDevice, (obj), TYPE_CCW_DEVICE)
-#define CCW_DEVICE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(CCWDeviceClass, (obj), TYPE_CCW_DEVICE)
-#define CCW_DEVICE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(CCWDeviceClass, (klass), TYPE_CCW_DEVICE)
+DECLARE_OBJ_CHECKERS(CcwDevice, CCWDeviceClass,
+                     CCW_DEVICE, TYPE_CCW_DEVICE)
 
 #endif
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index 53cc9eb5ac..9e6061a043 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -16,6 +16,7 @@
 #include "cpu.h"
 #include "exec/address-spaces.h"
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 struct IPLBlockPVComp {
     uint64_t tweak_pref;
@@ -152,7 +153,9 @@ struct QemuIplParameters {
 typedef struct QemuIplParameters QemuIplParameters;
 
 #define TYPE_S390_IPL "s390-ipl"
-#define S390_IPL(obj) OBJECT_CHECK(S390IPLState, (obj), TYPE_S390_IPL)
+typedef struct S390IPLState S390IPLState;
+DECLARE_INSTANCE_CHECKER(S390IPLState, S390_IPL,
+                         TYPE_S390_IPL)
 
 struct S390IPLState {
     /*< private >*/
@@ -183,7 +186,6 @@ struct S390IPLState {
     uint16_t devno;
     bool iplbext_migration;
 };
-typedef struct S390IPLState S390IPLState;
 QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong");
 
 #define DIAG_308_RC_OK              0x0001
diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h
index 550f3cc5e9..045805980f 100644
--- a/hw/s390x/s390-pci-bus.h
+++ b/hw/s390x/s390-pci-bus.h
@@ -19,6 +19,7 @@
 #include "hw/s390x/sclp.h"
 #include "hw/s390x/s390_flic.h"
 #include "hw/s390x/css.h"
+#include "qom/object.h"
 
 #define TYPE_S390_PCI_HOST_BRIDGE "s390-pcihost"
 #define TYPE_S390_PCI_BUS "s390-pcibus"
@@ -36,14 +37,18 @@
 #define UID_UNDEFINED 0
 #define UID_CHECKING_ENABLED 0x01
 
-#define S390_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(S390pciState, (obj), TYPE_S390_PCI_HOST_BRIDGE)
-#define S390_PCI_BUS(obj) \
-    OBJECT_CHECK(S390PCIBus, (obj), TYPE_S390_PCI_BUS)
-#define S390_PCI_DEVICE(obj) \
-    OBJECT_CHECK(S390PCIBusDevice, (obj), TYPE_S390_PCI_DEVICE)
-#define S390_PCI_IOMMU(obj) \
-    OBJECT_CHECK(S390PCIIOMMU, (obj), TYPE_S390_PCI_IOMMU)
+typedef struct S390pciState S390pciState;
+DECLARE_INSTANCE_CHECKER(S390pciState, S390_PCI_HOST_BRIDGE,
+                         TYPE_S390_PCI_HOST_BRIDGE)
+typedef struct S390PCIBus S390PCIBus;
+DECLARE_INSTANCE_CHECKER(S390PCIBus, S390_PCI_BUS,
+                         TYPE_S390_PCI_BUS)
+typedef struct S390PCIBusDevice S390PCIBusDevice;
+DECLARE_INSTANCE_CHECKER(S390PCIBusDevice, S390_PCI_DEVICE,
+                         TYPE_S390_PCI_DEVICE)
+typedef struct S390PCIIOMMU S390PCIIOMMU;
+DECLARE_INSTANCE_CHECKER(S390PCIIOMMU, S390_PCI_IOMMU,
+                         TYPE_S390_PCI_IOMMU)
 
 #define HP_EVENT_TO_CONFIGURED        0x0301
 #define HP_EVENT_RESERVED_TO_STANDBY  0x0302
@@ -265,8 +270,7 @@ typedef struct S390IOTLBEntry {
     uint64_t perm;
 } S390IOTLBEntry;
 
-typedef struct S390PCIBusDevice S390PCIBusDevice;
-typedef struct S390PCIIOMMU {
+struct S390PCIIOMMU {
     Object parent_obj;
     S390PCIBusDevice *pbdev;
     AddressSpace as;
@@ -277,7 +281,7 @@ typedef struct S390PCIIOMMU {
     uint64_t pba;
     uint64_t pal;
     GHashTable *iotlb;
-} S390PCIIOMMU;
+};
 
 typedef struct S390PCIIOMMUTable {
     uint64_t key;
@@ -339,11 +343,11 @@ struct S390PCIBusDevice {
     QTAILQ_ENTRY(S390PCIBusDevice) link;
 };
 
-typedef struct S390PCIBus {
+struct S390PCIBus {
     BusState qbus;
-} S390PCIBus;
+};
 
-typedef struct S390pciState {
+struct S390pciState {
     PCIHostState parent_obj;
     uint32_t next_idx;
     int bus_no;
@@ -352,7 +356,7 @@ typedef struct S390pciState {
     GHashTable *zpci_table;
     QTAILQ_HEAD(, SeiContainer) pending_sei;
     QTAILQ_HEAD(, S390PCIBusDevice) zpci_devs;
-} S390pciState;
+};
 
 S390pciState *s390_get_phb(void);
 int pci_chsc_sei_nt2_get_event(void *res);
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index b281896f7d..cea259685d 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -17,6 +17,7 @@
 #include "hw/virtio/virtio-net.h"
 #include "hw/virtio/virtio-serial.h"
 #include "hw/virtio/virtio-scsi.h"
+#include "qom/object.h"
 #ifdef CONFIG_VHOST_SCSI
 #include "hw/virtio/vhost-scsi.h"
 #endif
@@ -53,32 +54,25 @@
 #define CCW_CMD_SET_VIRTIO_REV 0x83
 
 #define TYPE_VIRTIO_CCW_DEVICE "virtio-ccw-device"
-#define VIRTIO_CCW_DEVICE(obj) \
-     OBJECT_CHECK(VirtioCcwDevice, (obj), TYPE_VIRTIO_CCW_DEVICE)
-#define VIRTIO_CCW_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(VirtIOCCWDeviceClass, (klass), TYPE_VIRTIO_CCW_DEVICE)
-#define VIRTIO_CCW_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(VirtIOCCWDeviceClass, (obj), TYPE_VIRTIO_CCW_DEVICE)
+typedef struct VirtIOCCWDeviceClass VirtIOCCWDeviceClass;
+typedef struct VirtioCcwDevice VirtioCcwDevice;
+DECLARE_OBJ_CHECKERS(VirtioCcwDevice, VirtIOCCWDeviceClass,
+                     VIRTIO_CCW_DEVICE, TYPE_VIRTIO_CCW_DEVICE)
 
 typedef struct VirtioBusState VirtioCcwBusState;
 typedef struct VirtioBusClass VirtioCcwBusClass;
 
 #define TYPE_VIRTIO_CCW_BUS "virtio-ccw-bus"
-#define VIRTIO_CCW_BUS(obj) \
-     OBJECT_CHECK(VirtioCcwBusState, (obj), TYPE_VIRTIO_CCW_BUS)
-#define VIRTIO_CCW_BUS_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(VirtioCcwBusClass, (obj), TYPE_VIRTIO_CCW_BUS)
-#define VIRTIO_CCW_BUS_CLASS(klass) \
-    OBJECT_CLASS_CHECK(VirtioCcwBusClass, klass, TYPE_VIRTIO_CCW_BUS)
+DECLARE_OBJ_CHECKERS(VirtioCcwBusState, VirtioCcwBusClass,
+                     VIRTIO_CCW_BUS, TYPE_VIRTIO_CCW_BUS)
 
-typedef struct VirtioCcwDevice VirtioCcwDevice;
 
-typedef struct VirtIOCCWDeviceClass {
+struct VirtIOCCWDeviceClass {
     CCWDeviceClass parent_class;
     void (*realize)(VirtioCcwDevice *dev, Error **errp);
     void (*unrealize)(VirtioCcwDevice *dev);
     void (*parent_reset)(DeviceState *dev);
-} VirtIOCCWDeviceClass;
+};
 
 /* Performance improves when virtqueue kick processing is decoupled from the
  * vcpu thread using ioeventfd for some devices. */
@@ -111,92 +105,100 @@ static inline int virtio_ccw_rev_max(VirtioCcwDevice *dev)
 /* virtio-scsi-ccw */
 
 #define TYPE_VIRTIO_SCSI_CCW "virtio-scsi-ccw"
-#define VIRTIO_SCSI_CCW(obj) \
-        OBJECT_CHECK(VirtIOSCSICcw, (obj), TYPE_VIRTIO_SCSI_CCW)
+typedef struct VirtIOSCSICcw VirtIOSCSICcw;
+DECLARE_INSTANCE_CHECKER(VirtIOSCSICcw, VIRTIO_SCSI_CCW,
+                         TYPE_VIRTIO_SCSI_CCW)
 
-typedef struct VirtIOSCSICcw {
+struct VirtIOSCSICcw {
     VirtioCcwDevice parent_obj;
     VirtIOSCSI vdev;
-} VirtIOSCSICcw;
+};
 
 #ifdef CONFIG_VHOST_SCSI
 /* vhost-scsi-ccw */
 
 #define TYPE_VHOST_SCSI_CCW "vhost-scsi-ccw"
-#define VHOST_SCSI_CCW(obj) \
-        OBJECT_CHECK(VHostSCSICcw, (obj), TYPE_VHOST_SCSI_CCW)
+typedef struct VHostSCSICcw VHostSCSICcw;
+DECLARE_INSTANCE_CHECKER(VHostSCSICcw, VHOST_SCSI_CCW,
+                         TYPE_VHOST_SCSI_CCW)
 
-typedef struct VHostSCSICcw {
+struct VHostSCSICcw {
     VirtioCcwDevice parent_obj;
     VHostSCSI vdev;
-} VHostSCSICcw;
+};
 #endif
 
 /* virtio-blk-ccw */
 
 #define TYPE_VIRTIO_BLK_CCW "virtio-blk-ccw"
-#define VIRTIO_BLK_CCW(obj) \
-        OBJECT_CHECK(VirtIOBlkCcw, (obj), TYPE_VIRTIO_BLK_CCW)
+typedef struct VirtIOBlkCcw VirtIOBlkCcw;
+DECLARE_INSTANCE_CHECKER(VirtIOBlkCcw, VIRTIO_BLK_CCW,
+                         TYPE_VIRTIO_BLK_CCW)
 
-typedef struct VirtIOBlkCcw {
+struct VirtIOBlkCcw {
     VirtioCcwDevice parent_obj;
     VirtIOBlock vdev;
-} VirtIOBlkCcw;
+};
 
 /* virtio-balloon-ccw */
 
 #define TYPE_VIRTIO_BALLOON_CCW "virtio-balloon-ccw"
-#define VIRTIO_BALLOON_CCW(obj) \
-        OBJECT_CHECK(VirtIOBalloonCcw, (obj), TYPE_VIRTIO_BALLOON_CCW)
+typedef struct VirtIOBalloonCcw VirtIOBalloonCcw;
+DECLARE_INSTANCE_CHECKER(VirtIOBalloonCcw, VIRTIO_BALLOON_CCW,
+                         TYPE_VIRTIO_BALLOON_CCW)
 
-typedef struct VirtIOBalloonCcw {
+struct VirtIOBalloonCcw {
     VirtioCcwDevice parent_obj;
     VirtIOBalloon vdev;
-} VirtIOBalloonCcw;
+};
 
 /* virtio-serial-ccw */
 
 #define TYPE_VIRTIO_SERIAL_CCW "virtio-serial-ccw"
-#define VIRTIO_SERIAL_CCW(obj) \
-        OBJECT_CHECK(VirtioSerialCcw, (obj), TYPE_VIRTIO_SERIAL_CCW)
+typedef struct VirtioSerialCcw VirtioSerialCcw;
+DECLARE_INSTANCE_CHECKER(VirtioSerialCcw, VIRTIO_SERIAL_CCW,
+                         TYPE_VIRTIO_SERIAL_CCW)
 
-typedef struct VirtioSerialCcw {
+struct VirtioSerialCcw {
     VirtioCcwDevice parent_obj;
     VirtIOSerial vdev;
-} VirtioSerialCcw;
+};
 
 /* virtio-net-ccw */
 
 #define TYPE_VIRTIO_NET_CCW "virtio-net-ccw"
-#define VIRTIO_NET_CCW(obj) \
-        OBJECT_CHECK(VirtIONetCcw, (obj), TYPE_VIRTIO_NET_CCW)
+typedef struct VirtIONetCcw VirtIONetCcw;
+DECLARE_INSTANCE_CHECKER(VirtIONetCcw, VIRTIO_NET_CCW,
+                         TYPE_VIRTIO_NET_CCW)
 
-typedef struct VirtIONetCcw {
+struct VirtIONetCcw {
     VirtioCcwDevice parent_obj;
     VirtIONet vdev;
-} VirtIONetCcw;
+};
 
 /* virtio-rng-ccw */
 
 #define TYPE_VIRTIO_RNG_CCW "virtio-rng-ccw"
-#define VIRTIO_RNG_CCW(obj) \
-        OBJECT_CHECK(VirtIORNGCcw, (obj), TYPE_VIRTIO_RNG_CCW)
+typedef struct VirtIORNGCcw VirtIORNGCcw;
+DECLARE_INSTANCE_CHECKER(VirtIORNGCcw, VIRTIO_RNG_CCW,
+                         TYPE_VIRTIO_RNG_CCW)
 
-typedef struct VirtIORNGCcw {
+struct VirtIORNGCcw {
     VirtioCcwDevice parent_obj;
     VirtIORNG vdev;
-} VirtIORNGCcw;
+};
 
 /* virtio-crypto-ccw */
 
 #define TYPE_VIRTIO_CRYPTO_CCW "virtio-crypto-ccw"
-#define VIRTIO_CRYPTO_CCW(obj) \
-        OBJECT_CHECK(VirtIOCryptoCcw, (obj), TYPE_VIRTIO_CRYPTO_CCW)
+typedef struct VirtIOCryptoCcw VirtIOCryptoCcw;
+DECLARE_INSTANCE_CHECKER(VirtIOCryptoCcw, VIRTIO_CRYPTO_CCW,
+                         TYPE_VIRTIO_CRYPTO_CCW)
 
-typedef struct VirtIOCryptoCcw {
+struct VirtIOCryptoCcw {
     VirtioCcwDevice parent_obj;
     VirtIOCrypto vdev;
-} VirtIOCryptoCcw;
+};
 
 VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch);
 
@@ -204,56 +206,61 @@ VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch);
 #include "hw/9pfs/virtio-9p.h"
 
 #define TYPE_VIRTIO_9P_CCW "virtio-9p-ccw"
-#define VIRTIO_9P_CCW(obj) \
-    OBJECT_CHECK(V9fsCCWState, (obj), TYPE_VIRTIO_9P_CCW)
+typedef struct V9fsCCWState V9fsCCWState;
+DECLARE_INSTANCE_CHECKER(V9fsCCWState, VIRTIO_9P_CCW,
+                         TYPE_VIRTIO_9P_CCW)
 
-typedef struct V9fsCCWState {
+struct V9fsCCWState {
     VirtioCcwDevice parent_obj;
     V9fsVirtioState vdev;
-} V9fsCCWState;
+};
 
 #endif /* CONFIG_VIRTFS */
 
 #ifdef CONFIG_VHOST_VSOCK
 #define TYPE_VHOST_VSOCK_CCW "vhost-vsock-ccw"
-#define VHOST_VSOCK_CCW(obj) \
-    OBJECT_CHECK(VHostVSockCCWState, (obj), TYPE_VHOST_VSOCK_CCW)
+typedef struct VHostVSockCCWState VHostVSockCCWState;
+DECLARE_INSTANCE_CHECKER(VHostVSockCCWState, VHOST_VSOCK_CCW,
+                         TYPE_VHOST_VSOCK_CCW)
 
-typedef struct VHostVSockCCWState {
+struct VHostVSockCCWState {
     VirtioCcwDevice parent_obj;
     VHostVSock vdev;
-} VHostVSockCCWState;
+};
 
 #endif /* CONFIG_VHOST_VSOCK */
 
 #define TYPE_VIRTIO_GPU_CCW "virtio-gpu-ccw"
-#define VIRTIO_GPU_CCW(obj) \
-        OBJECT_CHECK(VirtIOGPUCcw, (obj), TYPE_VIRTIO_GPU_CCW)
+typedef struct VirtIOGPUCcw VirtIOGPUCcw;
+DECLARE_INSTANCE_CHECKER(VirtIOGPUCcw, VIRTIO_GPU_CCW,
+                         TYPE_VIRTIO_GPU_CCW)
 
-typedef struct VirtIOGPUCcw {
+struct VirtIOGPUCcw {
     VirtioCcwDevice parent_obj;
     VirtIOGPU vdev;
-} VirtIOGPUCcw;
+};
 
 #define TYPE_VIRTIO_INPUT_CCW "virtio-input-ccw"
-#define VIRTIO_INPUT_CCW(obj) \
-        OBJECT_CHECK(VirtIOInputCcw, (obj), TYPE_VIRTIO_INPUT_CCW)
+typedef struct VirtIOInputCcw VirtIOInputCcw;
+DECLARE_INSTANCE_CHECKER(VirtIOInputCcw, VIRTIO_INPUT_CCW,
+                         TYPE_VIRTIO_INPUT_CCW)
 
-typedef struct VirtIOInputCcw {
+struct VirtIOInputCcw {
     VirtioCcwDevice parent_obj;
     VirtIOInput vdev;
-} VirtIOInputCcw;
+};
 
 #define TYPE_VIRTIO_INPUT_HID_CCW "virtio-input-hid-ccw"
 #define TYPE_VIRTIO_KEYBOARD_CCW "virtio-keyboard-ccw"
 #define TYPE_VIRTIO_MOUSE_CCW "virtio-mouse-ccw"
 #define TYPE_VIRTIO_TABLET_CCW "virtio-tablet-ccw"
-#define VIRTIO_INPUT_HID_CCW(obj) \
-        OBJECT_CHECK(VirtIOInputHIDCcw, (obj), TYPE_VIRTIO_INPUT_HID_CCW)
+typedef struct VirtIOInputHIDCcw VirtIOInputHIDCcw;
+DECLARE_INSTANCE_CHECKER(VirtIOInputHIDCcw, VIRTIO_INPUT_HID_CCW,
+                         TYPE_VIRTIO_INPUT_HID_CCW)
 
-typedef struct VirtIOInputHIDCcw {
+struct VirtIOInputHIDCcw {
     VirtioCcwDevice parent_obj;
     VirtIOInputHID vdev;
-} VirtIOInputHIDCcw;
+};
 
 #endif
diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
index 90432ef107..2ce96dc56e 100644
--- a/hw/scsi/esp-pci.c
+++ b/hw/scsi/esp-pci.c
@@ -33,11 +33,13 @@
 #include "qapi/error.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define TYPE_AM53C974_DEVICE "am53c974"
 
-#define PCI_ESP(obj) \
-    OBJECT_CHECK(PCIESPState, (obj), TYPE_AM53C974_DEVICE)
+typedef struct PCIESPState PCIESPState;
+DECLARE_INSTANCE_CHECKER(PCIESPState, PCI_ESP,
+                         TYPE_AM53C974_DEVICE)
 
 #define DMA_CMD   0x0
 #define DMA_STC   0x1
@@ -64,7 +66,7 @@
 
 #define SBAC_STATUS (1 << 24)
 
-typedef struct PCIESPState {
+struct PCIESPState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
@@ -73,7 +75,7 @@ typedef struct PCIESPState {
     uint32_t dma_regs[8];
     uint32_t sbac;
     ESPState esp;
-} PCIESPState;
+};
 
 static void esp_pci_handle_idle(PCIESPState *pci, uint32_t val)
 {
@@ -408,14 +410,15 @@ static const TypeInfo esp_pci_info = {
     },
 };
 
-typedef struct {
+struct DC390State {
     PCIESPState pci;
     eeprom_t *eeprom;
-} DC390State;
+};
+typedef struct DC390State DC390State;
 
 #define TYPE_DC390_DEVICE "dc390"
-#define DC390(obj) \
-    OBJECT_CHECK(DC390State, obj, TYPE_DC390_DEVICE)
+DECLARE_INSTANCE_CHECKER(DC390State, DC390,
+                         TYPE_DC390_DEVICE)
 
 #define EE_ADAPT_SCSI_ID 64
 #define EE_MODE2         65
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 405f8b7cbc..b84e0fe33e 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -929,7 +929,7 @@ static const struct SCSIBusInfo esp_scsi_info = {
 
 static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
 {
-    SysBusESPState *sysbus = ESP_STATE(opaque);
+    SysBusESPState *sysbus = ESP(opaque);
     ESPState *s = &sysbus->esp;
 
     switch (irq) {
@@ -945,7 +945,7 @@ static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
 static void sysbus_esp_realize(DeviceState *dev, Error **errp)
 {
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
-    SysBusESPState *sysbus = ESP_STATE(dev);
+    SysBusESPState *sysbus = ESP(dev);
     ESPState *s = &sysbus->esp;
 
     sysbus_init_irq(sbd, &s->irq);
@@ -967,7 +967,7 @@ static void sysbus_esp_realize(DeviceState *dev, Error **errp)
 
 static void sysbus_esp_hard_reset(DeviceState *dev)
 {
-    SysBusESPState *sysbus = ESP_STATE(dev);
+    SysBusESPState *sysbus = ESP(dev);
     esp_hard_reset(&sysbus->esp);
 }
 
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index 63ff4181de..e8354a47da 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -23,6 +23,7 @@
 #include "qemu/log.h"
 #include "qemu/module.h"
 #include "trace.h"
+#include "qom/object.h"
 
 static const char *names[] = {
     "SCNTL0", "SCNTL1", "SCNTL2", "SCNTL3", "SCID", "SXFER", "SDID", "GPREG",
@@ -213,7 +214,7 @@ enum {
     LSI_MSG_ACTION_DIN = 3,
 };
 
-typedef struct {
+struct LSIState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
@@ -303,13 +304,14 @@ typedef struct {
     uint32_t adder;
 
     uint8_t script_ram[2048 * sizeof(uint32_t)];
-} LSIState;
+};
+typedef struct LSIState LSIState;
 
 #define TYPE_LSI53C810  "lsi53c810"
 #define TYPE_LSI53C895A "lsi53c895a"
 
-#define LSI53C895A(obj) \
-    OBJECT_CHECK(LSIState, (obj), TYPE_LSI53C895A)
+DECLARE_INSTANCE_CHECKER(LSIState, LSI53C895A,
+                         TYPE_LSI53C895A)
 
 static const char *scsi_phases[] = {
     "DOUT",
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 390c2f2edb..e90c00823a 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -34,6 +34,7 @@
 #include "qapi/error.h"
 #include "mfi.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 #define MEGASAS_VERSION_GEN1 "1.70"
 #define MEGASAS_VERSION_GEN2 "1.80"
@@ -72,7 +73,7 @@ typedef struct MegasasCmd {
     struct MegasasState *state;
 } MegasasCmd;
 
-typedef struct MegasasState {
+struct MegasasState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
@@ -116,28 +117,26 @@ typedef struct MegasasState {
     MegasasCmd frames[MEGASAS_MAX_FRAMES];
     DECLARE_BITMAP(frame_map, MEGASAS_MAX_FRAMES);
     SCSIBus bus;
-} MegasasState;
+};
+typedef struct MegasasState MegasasState;
 
-typedef struct MegasasBaseClass {
+struct MegasasBaseClass {
     PCIDeviceClass parent_class;
     const char *product_name;
     const char *product_version;
     int mmio_bar;
     int ioport_bar;
     int osts;
-} MegasasBaseClass;
+};
+typedef struct MegasasBaseClass MegasasBaseClass;
 
 #define TYPE_MEGASAS_BASE "megasas-base"
 #define TYPE_MEGASAS_GEN1 "megasas"
 #define TYPE_MEGASAS_GEN2 "megasas-gen2"
 
-#define MEGASAS(obj) \
-    OBJECT_CHECK(MegasasState, (obj), TYPE_MEGASAS_BASE)
+DECLARE_OBJ_CHECKERS(MegasasState, MegasasBaseClass,
+                     MEGASAS, TYPE_MEGASAS_BASE)
 
-#define MEGASAS_CLASS(oc) \
-    OBJECT_CLASS_CHECK(MegasasBaseClass, (oc), TYPE_MEGASAS_BASE)
-#define MEGASAS_GET_CLASS(oc) \
-    OBJECT_GET_CLASS(MegasasBaseClass, (oc), TYPE_MEGASAS_BASE)
 
 #define MEGASAS_INTR_DISABLED_MASK 0xFFFFFFFF
 
diff --git a/hw/scsi/mptsas.h b/hw/scsi/mptsas.h
index 9ac98fc20e..b85ac1a5fc 100644
--- a/hw/scsi/mptsas.h
+++ b/hw/scsi/mptsas.h
@@ -2,6 +2,7 @@
 #define MPTSAS_H
 
 #include "mpi.h"
+#include "qom/object.h"
 
 #define MPTSAS_NUM_PORTS 8
 #define MPTSAS_MAX_FRAMES 2048     /* Firmware limit at 65535 */
@@ -15,8 +16,8 @@ typedef struct MPTSASRequest MPTSASRequest;
 
 #define TYPE_MPTSAS1068 "mptsas1068"
 typedef struct MPTSASState MPTSASState;
-#define MPT_SAS(obj) \
-    OBJECT_CHECK(MPTSASState, (obj), TYPE_MPTSAS1068)
+DECLARE_INSTANCE_CHECKER(MPTSASState, MPT_SAS,
+                         TYPE_MPTSAS1068)
 
 enum {
     DOORBELL_NONE,
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 7612035a4e..1f0388a755 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -38,6 +38,7 @@
 #include "sysemu/sysemu.h"
 #include "qemu/cutils.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #ifdef __linux
 #include <scsi/sg.h>
@@ -54,20 +55,18 @@
 
 #define TYPE_SCSI_DISK_BASE         "scsi-disk-base"
 
-#define SCSI_DISK_BASE(obj) \
-     OBJECT_CHECK(SCSIDiskState, (obj), TYPE_SCSI_DISK_BASE)
-#define SCSI_DISK_BASE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(SCSIDiskClass, (klass), TYPE_SCSI_DISK_BASE)
-#define SCSI_DISK_BASE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(SCSIDiskClass, (obj), TYPE_SCSI_DISK_BASE)
+typedef struct SCSIDiskClass SCSIDiskClass;
+typedef struct SCSIDiskState SCSIDiskState;
+DECLARE_OBJ_CHECKERS(SCSIDiskState, SCSIDiskClass,
+                     SCSI_DISK_BASE, TYPE_SCSI_DISK_BASE)
 
-typedef struct SCSIDiskClass {
+struct SCSIDiskClass {
     SCSIDeviceClass parent_class;
     DMAIOFunc       *dma_readv;
     DMAIOFunc       *dma_writev;
     bool            (*need_fua_emulation)(SCSICommand *cmd);
     void            (*update_sense)(SCSIRequest *r);
-} SCSIDiskClass;
+};
 
 typedef struct SCSIDiskReq {
     SCSIRequest req;
@@ -87,8 +86,7 @@ typedef struct SCSIDiskReq {
 #define SCSI_DISK_F_DPOFUA                1
 #define SCSI_DISK_F_NO_REMOVABLE_DEVOPS   2
 
-typedef struct SCSIDiskState
-{
+struct SCSIDiskState {
     SCSIDevice qdev;
     uint32_t features;
     bool media_changed;
@@ -113,7 +111,7 @@ typedef struct SCSIDiskState
      * 0xffff        - reserved
      */
     uint16_t rotation_rate;
-} SCSIDiskState;
+};
 
 static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed);
 
diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
index 57f0a1336f..c3e6d1ecef 100644
--- a/hw/scsi/spapr_vscsi.c
+++ b/hw/scsi/spapr_vscsi.c
@@ -46,6 +46,7 @@
 #include "trace.h"
 
 #include <libfdt.h>
+#include "qom/object.h"
 
 /*
  * Virtual SCSI device
@@ -90,14 +91,15 @@ typedef struct vscsi_req {
 } vscsi_req;
 
 #define TYPE_VIO_SPAPR_VSCSI_DEVICE "spapr-vscsi"
-#define VIO_SPAPR_VSCSI_DEVICE(obj) \
-     OBJECT_CHECK(VSCSIState, (obj), TYPE_VIO_SPAPR_VSCSI_DEVICE)
+typedef struct VSCSIState VSCSIState;
+DECLARE_INSTANCE_CHECKER(VSCSIState, VIO_SPAPR_VSCSI_DEVICE,
+                         TYPE_VIO_SPAPR_VSCSI_DEVICE)
 
-typedef struct {
+struct VSCSIState {
     SpaprVioDevice vdev;
     SCSIBus bus;
     vscsi_req reqs[VSCSI_REQ_LIMIT];
-} VSCSIState;
+};
 
 static union viosrp_iu *req_iu(vscsi_req *req)
 {
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index c071e0c7aa..40095bed09 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -36,6 +36,7 @@
 #include "hw/qdev-properties.h"
 #include "vmw_pvscsi.h"
 #include "trace.h"
+#include "qom/object.h"
 
 
 #define PVSCSI_USE_64BIT         (true)
@@ -56,18 +57,17 @@
     (stl_le_pci_dma(&container_of(m, PVSCSIState, rings)->parent_obj, \
                  (m)->rs_pa + offsetof(struct PVSCSIRingsState, field), val))
 
-typedef struct PVSCSIClass {
+struct PVSCSIClass {
     PCIDeviceClass parent_class;
     DeviceRealize parent_dc_realize;
-} PVSCSIClass;
+};
+typedef struct PVSCSIClass PVSCSIClass;
 
 #define TYPE_PVSCSI "pvscsi"
-#define PVSCSI(obj) OBJECT_CHECK(PVSCSIState, (obj), TYPE_PVSCSI)
+typedef struct PVSCSIState PVSCSIState;
+DECLARE_OBJ_CHECKERS(PVSCSIState, PVSCSIClass,
+                     PVSCSI, TYPE_PVSCSI)
 
-#define PVSCSI_CLASS(klass) \
-    OBJECT_CLASS_CHECK(PVSCSIClass, (klass), TYPE_PVSCSI)
-#define PVSCSI_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(PVSCSIClass, (obj), TYPE_PVSCSI)
 
 /* Compatibility flags for migration */
 #define PVSCSI_COMPAT_OLD_PCI_CONFIGURATION_BIT 0
@@ -104,7 +104,7 @@ typedef struct PVSCSISGState {
 
 typedef QTAILQ_HEAD(, PVSCSIRequest) PVSCSIRequestList;
 
-typedef struct {
+struct PVSCSIState {
     PCIDevice parent_obj;
     MemoryRegion io_space;
     SCSIBus bus;
@@ -132,7 +132,7 @@ typedef struct {
     uint32_t resetting;                  /* Reset in progress                */
 
     uint32_t compat_flags;
-} PVSCSIState;
+};
 
 typedef struct PVSCSIRequest {
     SCSIRequest *sreq;
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
index e82afb75eb..bea6d97ef8 100644
--- a/hw/sd/allwinner-sdhost.c
+++ b/hw/sd/allwinner-sdhost.c
@@ -29,10 +29,12 @@
 #include "hw/sd/allwinner-sdhost.h"
 #include "migration/vmstate.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define TYPE_AW_SDHOST_BUS "allwinner-sdhost-bus"
-#define AW_SDHOST_BUS(obj) \
-    OBJECT_CHECK(SDBus, (obj), TYPE_AW_SDHOST_BUS)
+/* This is reusing the SDBus typedef from SD_BUS */
+DECLARE_INSTANCE_CHECKER(SDBus, AW_SDHOST_BUS,
+                         TYPE_AW_SDHOST_BUS)
 
 /* SD Host register offsets */
 enum {
diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c
index 2c7a675a2d..50f5fdb88b 100644
--- a/hw/sd/bcm2835_sdhost.c
+++ b/hw/sd/bcm2835_sdhost.c
@@ -19,10 +19,12 @@
 #include "hw/sd/bcm2835_sdhost.h"
 #include "migration/vmstate.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define TYPE_BCM2835_SDHOST_BUS "bcm2835-sdhost-bus"
-#define BCM2835_SDHOST_BUS(obj) \
-    OBJECT_CHECK(SDBus, (obj), TYPE_BCM2835_SDHOST_BUS)
+/* This is reusing the SDBus typedef from SD_BUS */
+DECLARE_INSTANCE_CHECKER(SDBus, BCM2835_SDHOST_BUS,
+                         TYPE_BCM2835_SDHOST_BUS)
 
 #define SDCMD  0x00 /* Command to SD card              - 16 R/W */
 #define SDARG  0x04 /* Argument to SD card             - 32 R/W */
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index be89a93876..4d3ec28f5d 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -32,6 +32,7 @@
 #include "sysemu/blockdev.h"
 #include "hw/qdev-properties.h"
 #include "hw/sd/sd.h"
+#include "qom/object.h"
 
 enum {
     ENABLE_CMD_TX   = (1<<0),
@@ -63,8 +64,9 @@ enum {
 };
 
 #define TYPE_MILKYMIST_MEMCARD "milkymist-memcard"
-#define MILKYMIST_MEMCARD(obj) \
-    OBJECT_CHECK(MilkymistMemcardState, (obj), TYPE_MILKYMIST_MEMCARD)
+typedef struct MilkymistMemcardState MilkymistMemcardState;
+DECLARE_INSTANCE_CHECKER(MilkymistMemcardState, MILKYMIST_MEMCARD,
+                         TYPE_MILKYMIST_MEMCARD)
 
 #define TYPE_MILKYMIST_SDBUS "milkymist-sdbus"
 
@@ -83,7 +85,6 @@ struct MilkymistMemcardState {
     uint8_t response[17];
     uint32_t regs[R_MAX];
 };
-typedef struct MilkymistMemcardState MilkymistMemcardState;
 
 static void update_pending_bits(MilkymistMemcardState *s)
 {
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 579d68ad83..7829e933a5 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -18,15 +18,18 @@
 #include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define PL181_FIFO_LEN 16
 
 #define TYPE_PL181 "pl181"
-#define PL181(obj) OBJECT_CHECK(PL181State, (obj), TYPE_PL181)
+typedef struct PL181State PL181State;
+DECLARE_INSTANCE_CHECKER(PL181State, PL181,
+                         TYPE_PL181)
 
 #define TYPE_PL181_BUS "pl181-bus"
 
-typedef struct PL181State {
+struct PL181State {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -56,7 +59,7 @@ typedef struct PL181State {
     /* GPIO outputs for 'card is readonly' and 'card inserted' */
     qemu_irq card_readonly;
     qemu_irq card_inserted;
-} PL181State;
+};
 
 static const VMStateDescription vmstate_pl181 = {
     .name = "pl181",
diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index 3a47b380dd..3dd2fc7a83 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -21,9 +21,12 @@
 #include "qemu/log.h"
 #include "qemu/module.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define TYPE_PXA2XX_MMCI_BUS "pxa2xx-mmci-bus"
-#define PXA2XX_MMCI_BUS(obj) OBJECT_CHECK(SDBus, (obj), TYPE_PXA2XX_MMCI_BUS)
+/* This is reusing the SDBus typedef from SD_BUS */
+DECLARE_INSTANCE_CHECKER(SDBus, PXA2XX_MMCI_BUS,
+                         TYPE_PXA2XX_MMCI_BUS)
 
 struct PXA2xxMMCIState {
     SysBusDevice parent_obj;
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 483c4f1720..0012882222 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1785,7 +1785,7 @@ send_response:
     }
 
 #ifdef DEBUG_SD
-    qemu_hexdump((const char *)response, stderr, "Response", rsplen);
+    qemu_hexdump(stderr, "Response", response, rsplen);
 #endif
 
     return rsplen;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 1785d7e1f7..6900213083 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -37,9 +37,12 @@
 #include "qemu/log.h"
 #include "qemu/module.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define TYPE_SDHCI_BUS "sdhci-bus"
-#define SDHCI_BUS(obj) OBJECT_CHECK(SDBus, (obj), TYPE_SDHCI_BUS)
+/* This is reusing the SDBus typedef from SD_BUS */
+DECLARE_INSTANCE_CHECKER(SDBus, SDHCI_BUS,
+                         TYPE_SDHCI_BUS)
 
 #define MASKED_WRITE(reg, mask, val)  (reg = (reg & (mask)) | (val))
 
diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index a7ef9cb922..dd07258d4e 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -18,6 +18,7 @@
 #include "hw/sd/sd.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 //#define DEBUG_SSI_SD 1
 
@@ -40,7 +41,7 @@ typedef enum {
     SSI_SD_DATA_READ,
 } ssi_sd_mode;
 
-typedef struct {
+struct ssi_sd_state {
     SSISlave ssidev;
     uint32_t mode;
     int cmd;
@@ -50,10 +51,12 @@ typedef struct {
     int32_t response_pos;
     int32_t stopping;
     SDBus sdbus;
-} ssi_sd_state;
+};
+typedef struct ssi_sd_state ssi_sd_state;
 
 #define TYPE_SSI_SD "ssi-sd"
-#define SSI_SD(obj) OBJECT_CHECK(ssi_sd_state, (obj), TYPE_SSI_SD)
+DECLARE_INSTANCE_CHECKER(ssi_sd_state, SSI_SD,
+                         TYPE_SSI_SD)
 
 /* State word bits.  */
 #define SSI_SDR_LOCKED          0x0001
diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c
index 0a3e86f949..dc73845125 100644
--- a/hw/sh4/sh_pci.c
+++ b/hw/sh4/sh_pci.c
@@ -31,13 +31,15 @@
 #include "qemu/bswap.h"
 #include "qemu/module.h"
 #include "exec/address-spaces.h"
+#include "qom/object.h"
 
 #define TYPE_SH_PCI_HOST_BRIDGE "sh_pci"
 
-#define SH_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(SHPCIState, (obj), TYPE_SH_PCI_HOST_BRIDGE)
+typedef struct SHPCIState SHPCIState;
+DECLARE_INSTANCE_CHECKER(SHPCIState, SH_PCI_HOST_BRIDGE,
+                         TYPE_SH_PCI_HOST_BRIDGE)
 
-typedef struct SHPCIState {
+struct SHPCIState {
     PCIHostState parent_obj;
 
     PCIDevice *dev;
@@ -48,7 +50,7 @@ typedef struct SHPCIState {
     uint32_t par;
     uint32_t mbr;
     uint32_t iobr;
-} SHPCIState;
+};
 
 static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val,
                               unsigned size)
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 6bf9d27d8a..947b69d159 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -52,6 +52,7 @@
 #include "hw/loader.h"
 #include "elf.h"
 #include "trace.h"
+#include "qom/object.h"
 
 /*
  * Sun4m architecture was used in the following machines:
@@ -334,7 +335,7 @@ static void *sparc32_dma_init(hwaddr dma_base,
                                    OBJECT(dma), "espdma"));
     sysbus_connect_irq(SYS_BUS_DEVICE(espdma), 0, espdma_irq);
 
-    esp = ESP_STATE(object_resolve_path_component(OBJECT(espdma), "esp"));
+    esp = ESP(object_resolve_path_component(OBJECT(espdma), "esp"));
     sysbus_mmio_map(SYS_BUS_DEVICE(esp), 0, esp_base);
     scsi_bus_legacy_handle_cmdline(&esp->esp.bus);
 
@@ -581,14 +582,15 @@ static void idreg_init(hwaddr addr)
                             idreg_data, sizeof(idreg_data));
 }
 
-#define MACIO_ID_REGISTER(obj) \
-    OBJECT_CHECK(IDRegState, (obj), TYPE_MACIO_ID_REGISTER)
+typedef struct IDRegState IDRegState;
+DECLARE_INSTANCE_CHECKER(IDRegState, MACIO_ID_REGISTER,
+                         TYPE_MACIO_ID_REGISTER)
 
-typedef struct IDRegState {
+struct IDRegState {
     SysBusDevice parent_obj;
 
     MemoryRegion mem;
-} IDRegState;
+};
 
 static void idreg_realize(DeviceState *ds, Error **errp)
 {
@@ -623,13 +625,15 @@ static const TypeInfo idreg_info = {
 };
 
 #define TYPE_TCX_AFX "tcx_afx"
-#define TCX_AFX(obj) OBJECT_CHECK(AFXState, (obj), TYPE_TCX_AFX)
+typedef struct AFXState AFXState;
+DECLARE_INSTANCE_CHECKER(AFXState, TCX_AFX,
+                         TYPE_TCX_AFX)
 
-typedef struct AFXState {
+struct AFXState {
     SysBusDevice parent_obj;
 
     MemoryRegion mem;
-} AFXState;
+};
 
 /* SS-5 TCX AFX register */
 static void afx_init(hwaddr addr)
@@ -676,13 +680,15 @@ static const TypeInfo afx_info = {
 };
 
 #define TYPE_OPENPROM "openprom"
-#define OPENPROM(obj) OBJECT_CHECK(PROMState, (obj), TYPE_OPENPROM)
+typedef struct PROMState PROMState;
+DECLARE_INSTANCE_CHECKER(PROMState, OPENPROM,
+                         TYPE_OPENPROM)
 
-typedef struct PROMState {
+struct PROMState {
     SysBusDevice parent_obj;
 
     MemoryRegion prom;
-} PROMState;
+};
 
 /* Boot PROM (OpenBIOS) */
 static uint64_t translate_prom_address(void *opaque, uint64_t addr)
@@ -764,12 +770,14 @@ static const TypeInfo prom_info = {
 };
 
 #define TYPE_SUN4M_MEMORY "memory"
-#define SUN4M_RAM(obj) OBJECT_CHECK(RamDevice, (obj), TYPE_SUN4M_MEMORY)
+typedef struct RamDevice RamDevice;
+DECLARE_INSTANCE_CHECKER(RamDevice, SUN4M_RAM,
+                         TYPE_SUN4M_MEMORY)
 
-typedef struct RamDevice {
+struct RamDevice {
     SysBusDevice parent_obj;
     HostMemoryBackend *memdev;
-} RamDevice;
+};
 
 /* System RAM */
 static void ram_realize(DeviceState *dev, Error **errp)
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 37310b73e6..b4aabfc076 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -55,6 +55,7 @@
 #include "hw/fw-path-provider.h"
 #include "elf.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define KERNEL_LOAD_ADDR     0x00404000
 #define CMDLINE_ADDR         0x003ff000
@@ -79,7 +80,7 @@ struct hwdef {
     uint64_t console_serial_base;
 };
 
-typedef struct EbusState {
+struct EbusState {
     /*< private >*/
     PCIDevice parent_obj;
 
@@ -88,10 +89,12 @@ typedef struct EbusState {
     uint64_t console_serial_base;
     MemoryRegion bar0;
     MemoryRegion bar1;
-} EbusState;
+};
+typedef struct EbusState EbusState;
 
 #define TYPE_EBUS "ebus"
-#define EBUS(obj) OBJECT_CHECK(EbusState, (obj), TYPE_EBUS)
+DECLARE_INSTANCE_CHECKER(EbusState, EBUS,
+                         TYPE_EBUS)
 
 const char *fw_cfg_arch_key_name(uint16_t key)
 {
@@ -226,13 +229,15 @@ typedef struct ResetData {
 } ResetData;
 
 #define TYPE_SUN4U_POWER "power"
-#define SUN4U_POWER(obj) OBJECT_CHECK(PowerDevice, (obj), TYPE_SUN4U_POWER)
+typedef struct PowerDevice PowerDevice;
+DECLARE_INSTANCE_CHECKER(PowerDevice, SUN4U_POWER,
+                         TYPE_SUN4U_POWER)
 
-typedef struct PowerDevice {
+struct PowerDevice {
     SysBusDevice parent_obj;
 
     MemoryRegion power_mmio;
-} PowerDevice;
+};
 
 /* Power */
 static uint64_t power_mem_read(void *opaque, hwaddr addr, unsigned size)
@@ -399,13 +404,15 @@ static const TypeInfo ebus_info = {
 };
 
 #define TYPE_OPENPROM "openprom"
-#define OPENPROM(obj) OBJECT_CHECK(PROMState, (obj), TYPE_OPENPROM)
+typedef struct PROMState PROMState;
+DECLARE_INSTANCE_CHECKER(PROMState, OPENPROM,
+                         TYPE_OPENPROM)
 
-typedef struct PROMState {
+struct PROMState {
     SysBusDevice parent_obj;
 
     MemoryRegion prom;
-} PROMState;
+};
 
 static uint64_t translate_prom_address(void *opaque, uint64_t addr)
 {
@@ -487,14 +494,16 @@ static const TypeInfo prom_info = {
 
 
 #define TYPE_SUN4U_MEMORY "memory"
-#define SUN4U_RAM(obj) OBJECT_CHECK(RamDevice, (obj), TYPE_SUN4U_MEMORY)
+typedef struct RamDevice RamDevice;
+DECLARE_INSTANCE_CHECKER(RamDevice, SUN4U_RAM,
+                         TYPE_SUN4U_MEMORY)
 
-typedef struct RamDevice {
+struct RamDevice {
     SysBusDevice parent_obj;
 
     MemoryRegion ram;
     uint64_t size;
-} RamDevice;
+};
 
 /* System RAM */
 static void ram_realize(DeviceState *dev, Error **errp)
@@ -576,7 +585,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     prom_init(hwdef->prom_addr, bios_name);
 
     /* Init sabre (PCI host bridge) */
-    sabre = SABRE_DEVICE(qdev_new(TYPE_SABRE));
+    sabre = SABRE(qdev_new(TYPE_SABRE));
     qdev_prop_set_uint64(DEVICE(sabre), "special-base", PBM_SPECIAL_BASE);
     qdev_prop_set_uint64(DEVICE(sabre), "mem-base", PBM_MEM_BASE);
     object_property_set_link(OBJECT(sabre), "iommu", OBJECT(iommu),
diff --git a/hw/ssi/ssi.c b/hw/ssi/ssi.c
index a35d7ebb26..faf7633e70 100644
--- a/hw/ssi/ssi.c
+++ b/hw/ssi/ssi.c
@@ -17,13 +17,15 @@
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 struct SSIBus {
     BusState parent_obj;
 };
 
 #define TYPE_SSI_BUS "SSI"
-#define SSI_BUS(obj) OBJECT_CHECK(SSIBus, (obj), TYPE_SSI_BUS)
+DECLARE_INSTANCE_CHECKER(SSIBus, SSI_BUS,
+                         TYPE_SSI_BUS)
 
 static const TypeInfo ssi_bus_info = {
     .name = TYPE_SSI_BUS,
diff --git a/hw/ssi/xilinx_spi.c b/hw/ssi/xilinx_spi.c
index 80d1488dc7..34fc8da69a 100644
--- a/hw/ssi/xilinx_spi.c
+++ b/hw/ssi/xilinx_spi.c
@@ -34,6 +34,7 @@
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
 #include "hw/ssi/ssi.h"
+#include "qom/object.h"
 
 #ifdef XILINX_SPI_ERR_DEBUG
 #define DB_PRINT(...) do { \
@@ -78,9 +79,11 @@
 #define FIFO_CAPACITY 256
 
 #define TYPE_XILINX_SPI "xlnx.xps-spi"
-#define XILINX_SPI(obj) OBJECT_CHECK(XilinxSPI, (obj), TYPE_XILINX_SPI)
+typedef struct XilinxSPI XilinxSPI;
+DECLARE_INSTANCE_CHECKER(XilinxSPI, XILINX_SPI,
+                         TYPE_XILINX_SPI)
 
-typedef struct XilinxSPI {
+struct XilinxSPI {
     SysBusDevice parent_obj;
 
     MemoryRegion mmio;
@@ -97,7 +100,7 @@ typedef struct XilinxSPI {
     Fifo8 tx_fifo;
 
     uint32_t regs[R_MAX];
-} XilinxSPI;
+};
 
 static void txfifo_reset(XilinxSPI *s)
 {
diff --git a/hw/timer/altera_timer.c b/hw/timer/altera_timer.c
index be81b7a518..c694c98d08 100644
--- a/hw/timer/altera_timer.c
+++ b/hw/timer/altera_timer.c
@@ -26,6 +26,7 @@
 #include "hw/irq.h"
 #include "hw/ptimer.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
 #define R_STATUS      0
 #define R_CONTROL     1
@@ -44,17 +45,18 @@
 #define CONTROL_STOP  0x0008
 
 #define TYPE_ALTERA_TIMER "ALTR.timer"
-#define ALTERA_TIMER(obj) \
-    OBJECT_CHECK(AlteraTimer, (obj), TYPE_ALTERA_TIMER)
+typedef struct AlteraTimer AlteraTimer;
+DECLARE_INSTANCE_CHECKER(AlteraTimer, ALTERA_TIMER,
+                         TYPE_ALTERA_TIMER)
 
-typedef struct AlteraTimer {
+struct AlteraTimer {
     SysBusDevice  busdev;
     MemoryRegion  mmio;
     qemu_irq      irq;
     uint32_t      freq_hz;
     ptimer_state *ptimer;
     uint32_t      regs[R_MAX];
-} AlteraTimer;
+};
 
 static int timer_irq_state(AlteraTimer *t)
 {
diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
index 9607366d78..79117f45b0 100644
--- a/hw/timer/arm_timer.c
+++ b/hw/timer/arm_timer.c
@@ -16,6 +16,7 @@
 #include "hw/qdev-properties.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
+#include "qom/object.h"
 
 /* Common timer implementation.  */
 
@@ -190,9 +191,11 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
 */
 
 #define TYPE_SP804 "sp804"
-#define SP804(obj) OBJECT_CHECK(SP804State, (obj), TYPE_SP804)
+typedef struct SP804State SP804State;
+DECLARE_INSTANCE_CHECKER(SP804State, SP804,
+                         TYPE_SP804)
 
-typedef struct SP804State {
+struct SP804State {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -200,7 +203,7 @@ typedef struct SP804State {
     uint32_t freq0, freq1;
     int level[2];
     qemu_irq irq;
-} SP804State;
+};
 
 static const uint8_t sp804_ids[] = {
     /* Timer ID */
@@ -310,15 +313,16 @@ static void sp804_realize(DeviceState *dev, Error **errp)
 /* Integrator/CP timer module.  */
 
 #define TYPE_INTEGRATOR_PIT "integrator_pit"
-#define INTEGRATOR_PIT(obj) \
-    OBJECT_CHECK(icp_pit_state, (obj), TYPE_INTEGRATOR_PIT)
+typedef struct icp_pit_state icp_pit_state;
+DECLARE_INSTANCE_CHECKER(icp_pit_state, INTEGRATOR_PIT,
+                         TYPE_INTEGRATOR_PIT)
 
-typedef struct {
+struct icp_pit_state {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
     arm_timer_state *timer[3];
-} icp_pit_state;
+};
 
 static uint64_t icp_pit_read(void *opaque, hwaddr offset,
                              unsigned size)
diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c
index b0ba6b2bba..52e637545a 100644
--- a/hw/timer/cadence_ttc.c
+++ b/hw/timer/cadence_ttc.c
@@ -22,6 +22,7 @@
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "qemu/timer.h"
+#include "qom/object.h"
 
 #ifdef CADENCE_TTC_ERR_DEBUG
 #define DB_PRINT(...) do { \
@@ -69,15 +70,16 @@ typedef struct {
 } CadenceTimerState;
 
 #define TYPE_CADENCE_TTC "cadence_ttc"
-#define CADENCE_TTC(obj) \
-    OBJECT_CHECK(CadenceTTCState, (obj), TYPE_CADENCE_TTC)
+typedef struct CadenceTTCState CadenceTTCState;
+DECLARE_INSTANCE_CHECKER(CadenceTTCState, CADENCE_TTC,
+                         TYPE_CADENCE_TTC)
 
-typedef struct CadenceTTCState {
+struct CadenceTTCState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
     CadenceTimerState timer[3];
-} CadenceTTCState;
+};
 
 static void cadence_timer_update(CadenceTimerState *s)
 {
diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c
index afe3d30a8e..48f2e3ade2 100644
--- a/hw/timer/etraxfs_timer.c
+++ b/hw/timer/etraxfs_timer.c
@@ -30,6 +30,7 @@
 #include "qemu/timer.h"
 #include "hw/irq.h"
 #include "hw/ptimer.h"
+#include "qom/object.h"
 
 #define D(x)
 
@@ -48,10 +49,11 @@
 #define R_MASKED_INTR 0x54
 
 #define TYPE_ETRAX_FS_TIMER "etraxfs,timer"
-#define ETRAX_TIMER(obj) \
-    OBJECT_CHECK(ETRAXTimerState, (obj), TYPE_ETRAX_FS_TIMER)
+typedef struct ETRAXTimerState ETRAXTimerState;
+DECLARE_INSTANCE_CHECKER(ETRAXTimerState, ETRAX_TIMER,
+                         TYPE_ETRAX_FS_TIMER)
 
-typedef struct ETRAXTimerState {
+struct ETRAXTimerState {
     SysBusDevice parent_obj;
 
     MemoryRegion mmio;
@@ -79,7 +81,7 @@ typedef struct ETRAXTimerState {
     uint32_t rw_ack_intr;
     uint32_t r_intr;
     uint32_t r_masked_intr;
-} ETRAXTimerState;
+};
 
 static uint64_t
 timer_read(void *opaque, hwaddr addr, unsigned int size)
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index 29a4b10676..0329cae3d9 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -62,6 +62,7 @@
 
 #include "hw/arm/exynos4210.h"
 #include "hw/irq.h"
+#include "qom/object.h"
 
 //#define DEBUG_MCT
 
@@ -242,10 +243,11 @@ typedef struct {
 } Exynos4210MCTLT;
 
 #define TYPE_EXYNOS4210_MCT "exynos4210.mct"
-#define EXYNOS4210_MCT(obj) \
-    OBJECT_CHECK(Exynos4210MCTState, (obj), TYPE_EXYNOS4210_MCT)
+typedef struct Exynos4210MCTState Exynos4210MCTState;
+DECLARE_INSTANCE_CHECKER(Exynos4210MCTState, EXYNOS4210_MCT,
+                         TYPE_EXYNOS4210_MCT)
 
-typedef struct Exynos4210MCTState {
+struct Exynos4210MCTState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -257,7 +259,7 @@ typedef struct Exynos4210MCTState {
     Exynos4210MCTGT g_timer;
 
     uint32_t    freq;                   /* all timers tick frequency, TCLK */
-} Exynos4210MCTState;
+};
 
 /*** VMState ***/
 static const VMStateDescription vmstate_tick_timer = {
diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c
index 59a8c08db0..5340fc0425 100644
--- a/hw/timer/exynos4210_pwm.c
+++ b/hw/timer/exynos4210_pwm.c
@@ -30,6 +30,7 @@
 
 #include "hw/arm/exynos4210.h"
 #include "hw/irq.h"
+#include "qom/object.h"
 
 //#define DEBUG_PWM
 
@@ -102,10 +103,11 @@ typedef struct {
 } Exynos4210PWM;
 
 #define TYPE_EXYNOS4210_PWM "exynos4210.pwm"
-#define EXYNOS4210_PWM(obj) \
-    OBJECT_CHECK(Exynos4210PWMState, (obj), TYPE_EXYNOS4210_PWM)
+typedef struct Exynos4210PWMState Exynos4210PWMState;
+DECLARE_INSTANCE_CHECKER(Exynos4210PWMState, EXYNOS4210_PWM,
+                         TYPE_EXYNOS4210_PWM)
 
-typedef struct Exynos4210PWMState {
+struct Exynos4210PWMState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -116,7 +118,7 @@ typedef struct Exynos4210PWMState {
 
     Exynos4210PWM timer[EXYNOS4210_PWM_TIMERS_NUM];
 
-} Exynos4210PWMState;
+};
 
 /*** VMState ***/
 static const VMStateDescription vmstate_exynos4210_pwm = {
diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
index eff0ee3491..e539fc24f0 100644
--- a/hw/timer/grlib_gptimer.c
+++ b/hw/timer/grlib_gptimer.c
@@ -32,6 +32,7 @@
 #include "qemu/module.h"
 
 #include "trace.h"
+#include "qom/object.h"
 
 #define UNIT_REG_SIZE    16     /* Size of memory mapped regs for the unit */
 #define GPTIMER_REG_SIZE 16     /* Size of memory mapped regs for a GPTimer */
@@ -55,11 +56,11 @@
 #define COUNTER_RELOAD_OFFSET 0x04
 #define TIMER_BASE            0x10
 
-#define GRLIB_GPTIMER(obj) \
-    OBJECT_CHECK(GPTimerUnit, (obj), TYPE_GRLIB_GPTIMER)
+typedef struct GPTimerUnit GPTimerUnit;
+DECLARE_INSTANCE_CHECKER(GPTimerUnit, GRLIB_GPTIMER,
+                         TYPE_GRLIB_GPTIMER)
 
 typedef struct GPTimer     GPTimer;
-typedef struct GPTimerUnit GPTimerUnit;
 
 struct GPTimer {
     struct ptimer_state *ptimer;
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index 380acfa7c8..44bbe3a536 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -37,6 +37,7 @@
 #include "migration/vmstate.h"
 #include "hw/timer/i8254.h"
 #include "exec/address-spaces.h"
+#include "qom/object.h"
 
 //#define HPET_DEBUG
 #ifdef HPET_DEBUG
@@ -47,7 +48,9 @@
 
 #define HPET_MSI_SUPPORT        0
 
-#define HPET(obj) OBJECT_CHECK(HPETState, (obj), TYPE_HPET)
+typedef struct HPETState HPETState;
+DECLARE_INSTANCE_CHECKER(HPETState, HPET,
+                         TYPE_HPET)
 
 struct HPETState;
 typedef struct HPETTimer {  /* timers */
@@ -65,7 +68,7 @@ typedef struct HPETTimer {  /* timers */
                              */
 } HPETTimer;
 
-typedef struct HPETState {
+struct HPETState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -87,7 +90,7 @@ typedef struct HPETState {
     uint64_t isr;               /* interrupt status reg */
     uint64_t hpet_counter;      /* main counter */
     uint8_t  hpet_id;           /* instance id */
-} HPETState;
+};
 
 static uint32_t hpet_in_legacy_mode(HPETState *s)
 {
diff --git a/hw/timer/i8254.c b/hw/timer/i8254.c
index 29f62e5356..c01ee2c72a 100644
--- a/hw/timer/i8254.c
+++ b/hw/timer/i8254.c
@@ -28,6 +28,7 @@
 #include "qemu/timer.h"
 #include "hw/timer/i8254.h"
 #include "hw/timer/i8254_internal.h"
+#include "qom/object.h"
 
 //#define DEBUG_PIT
 
@@ -36,14 +37,15 @@
 #define RW_STATE_WORD0 3
 #define RW_STATE_WORD1 4
 
-#define PIT_CLASS(class) OBJECT_CLASS_CHECK(PITClass, (class), TYPE_I8254)
-#define PIT_GET_CLASS(obj) OBJECT_GET_CLASS(PITClass, (obj), TYPE_I8254)
+typedef struct PITClass PITClass;
+DECLARE_CLASS_CHECKERS(PITClass, PIT,
+                       TYPE_I8254)
 
-typedef struct PITClass {
+struct PITClass {
     PITCommonClass parent_class;
 
     DeviceRealize parent_realize;
-} PITClass;
+};
 
 static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
 
diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c
index f703f407f5..93ecb51a97 100644
--- a/hw/timer/lm32_timer.c
+++ b/hw/timer/lm32_timer.c
@@ -31,6 +31,7 @@
 #include "hw/qdev-properties.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define DEFAULT_FREQUENCY (50*1000000)
 
@@ -55,7 +56,9 @@ enum {
 };
 
 #define TYPE_LM32_TIMER "lm32-timer"
-#define LM32_TIMER(obj) OBJECT_CHECK(LM32TimerState, (obj), TYPE_LM32_TIMER)
+typedef struct LM32TimerState LM32TimerState;
+DECLARE_INSTANCE_CHECKER(LM32TimerState, LM32_TIMER,
+                         TYPE_LM32_TIMER)
 
 struct LM32TimerState {
     SysBusDevice parent_obj;
@@ -69,7 +72,6 @@ struct LM32TimerState {
 
     uint32_t regs[R_MAX];
 };
-typedef struct LM32TimerState LM32TimerState;
 
 static void timer_update_irq(LM32TimerState *s)
 {
diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
index 94389820b2..29500e0457 100644
--- a/hw/timer/milkymist-sysctl.c
+++ b/hw/timer/milkymist-sysctl.c
@@ -32,6 +32,7 @@
 #include "hw/qdev-properties.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 enum {
     CTRL_ENABLE      = (1<<0),
@@ -62,8 +63,9 @@ enum {
 };
 
 #define TYPE_MILKYMIST_SYSCTL "milkymist-sysctl"
-#define MILKYMIST_SYSCTL(obj) \
-    OBJECT_CHECK(MilkymistSysctlState, (obj), TYPE_MILKYMIST_SYSCTL)
+typedef struct MilkymistSysctlState MilkymistSysctlState;
+DECLARE_INSTANCE_CHECKER(MilkymistSysctlState, MILKYMIST_SYSCTL,
+                         TYPE_MILKYMIST_SYSCTL)
 
 struct MilkymistSysctlState {
     SysBusDevice parent_obj;
@@ -84,7 +86,6 @@ struct MilkymistSysctlState {
     qemu_irq timer0_irq;
     qemu_irq timer1_irq;
 };
-typedef struct MilkymistSysctlState MilkymistSysctlState;
 
 static void sysctl_icap_write(MilkymistSysctlState *s, uint32_t value)
 {
diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c
index f76b0bb1ca..3a35ac2b0a 100644
--- a/hw/timer/puv3_ost.c
+++ b/hw/timer/puv3_ost.c
@@ -15,15 +15,18 @@
 #include "hw/ptimer.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
+#include "qom/object.h"
 
 #undef DEBUG_PUV3
 #include "hw/unicore32/puv3.h"
 
 #define TYPE_PUV3_OST "puv3_ost"
-#define PUV3_OST(obj) OBJECT_CHECK(PUV3OSTState, (obj), TYPE_PUV3_OST)
+typedef struct PUV3OSTState PUV3OSTState;
+DECLARE_INSTANCE_CHECKER(PUV3OSTState, PUV3_OST,
+                         TYPE_PUV3_OST)
 
 /* puv3 ostimer implementation. */
-typedef struct PUV3OSTState {
+struct PUV3OSTState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -34,7 +37,7 @@ typedef struct PUV3OSTState {
     uint32_t reg_OSCR;
     uint32_t reg_OSSR;
     uint32_t reg_OIER;
-} PUV3OSTState;
+};
 
 static uint64_t puv3_ost_read(void *opaque, hwaddr offset,
         unsigned size)
diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c
index 944c165889..8c3a1f5489 100644
--- a/hw/timer/pxa2xx_timer.c
+++ b/hw/timer/pxa2xx_timer.c
@@ -17,6 +17,7 @@
 #include "migration/vmstate.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define OSMR0	0x00
 #define OSMR1	0x04
@@ -66,10 +67,10 @@ static int pxa2xx_timer4_freq[8] = {
 };
 
 #define TYPE_PXA2XX_TIMER "pxa2xx-timer"
-#define PXA2XX_TIMER(obj) \
-    OBJECT_CHECK(PXA2xxTimerInfo, (obj), TYPE_PXA2XX_TIMER)
-
 typedef struct PXA2xxTimerInfo PXA2xxTimerInfo;
+DECLARE_INSTANCE_CHECKER(PXA2xxTimerInfo, PXA2XX_TIMER,
+                         TYPE_PXA2XX_TIMER)
+
 
 typedef struct {
     uint32_t value;
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
index 4c5d65e391..08d6888015 100644
--- a/hw/timer/slavio_timer.c
+++ b/hw/timer/slavio_timer.c
@@ -31,6 +31,7 @@
 #include "migration/vmstate.h"
 #include "trace.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 /*
  * Registers of hardware timer in sun4m.
@@ -59,16 +60,17 @@ typedef struct CPUTimerState {
 } CPUTimerState;
 
 #define TYPE_SLAVIO_TIMER "slavio_timer"
-#define SLAVIO_TIMER(obj) \
-    OBJECT_CHECK(SLAVIO_TIMERState, (obj), TYPE_SLAVIO_TIMER)
+typedef struct SLAVIO_TIMERState SLAVIO_TIMERState;
+DECLARE_INSTANCE_CHECKER(SLAVIO_TIMERState, SLAVIO_TIMER,
+                         TYPE_SLAVIO_TIMER)
 
-typedef struct SLAVIO_TIMERState {
+struct SLAVIO_TIMERState {
     SysBusDevice parent_obj;
 
     uint32_t num_cpus;
     uint32_t cputimer_mode;
     CPUTimerState cputimer[MAX_CPUS + 1];
-} SLAVIO_TIMERState;
+};
 
 typedef struct TimerContext {
     MemoryRegion iomem;
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
index 447b7c405b..1537c3e6ec 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -81,7 +81,6 @@ avr_timer16_read(uint8_t addr, uint8_t value) "timer16 read addr:%u value:%u"
 avr_timer16_read_ifr(uint8_t value) "timer16 read addr:ifr value:%u"
 avr_timer16_read_imsk(uint8_t value) "timer16 read addr:imsk value:%u"
 avr_timer16_write(uint8_t addr, uint8_t value) "timer16 write addr:%u value:%u"
-avr_timer16_write_ifr(uint8_t value) "timer16 write addr:ifr value:%u"
 avr_timer16_write_imsk(uint8_t value) "timer16 write addr:imsk value:%u"
 avr_timer16_interrupt_count(uint8_t cnt) "count: %u"
 avr_timer16_interrupt_overflow(const char *reason) "overflow: %s"
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
index 0190aa47d0..1eb927eb84 100644
--- a/hw/timer/xilinx_timer.c
+++ b/hw/timer/xilinx_timer.c
@@ -29,6 +29,7 @@
 #include "hw/qdev-properties.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define D(x)
 
@@ -61,8 +62,8 @@ struct xlx_timer
 };
 
 #define TYPE_XILINX_TIMER "xlnx.xps-timer"
-#define XILINX_TIMER(obj) \
-    OBJECT_CHECK(struct timerblock, (obj), TYPE_XILINX_TIMER)
+DECLARE_INSTANCE_CHECKER(struct timerblock, XILINX_TIMER,
+                         TYPE_XILINX_TIMER)
 
 struct timerblock
 {
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 60247295d4..aa9c00aad3 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -29,8 +29,9 @@
 #include "tpm_prop.h"
 #include "tpm_ppi.h"
 #include "trace.h"
+#include "qom/object.h"
 
-typedef struct CRBState {
+struct CRBState {
     DeviceState parent_obj;
 
     TPMBackend *tpmbe;
@@ -43,9 +44,11 @@ typedef struct CRBState {
 
     bool ppi_enabled;
     TPMPPI ppi;
-} CRBState;
+};
+typedef struct CRBState CRBState;
 
-#define CRB(obj) OBJECT_CHECK(CRBState, (obj), TYPE_TPM_CRB)
+DECLARE_INSTANCE_CHECKER(CRBState, CRB,
+                         TYPE_TPM_CRB)
 
 #define CRB_INTF_TYPE_CRB_ACTIVE 0b1
 #define CRB_INTF_VERSION_CRB 0b1
diff --git a/hw/tpm/tpm_spapr.c b/hw/tpm/tpm_spapr.c
index 8288ab0a15..e3775adc57 100644
--- a/hw/tpm/tpm_spapr.c
+++ b/hw/tpm/tpm_spapr.c
@@ -26,11 +26,13 @@
 #include "hw/ppc/spapr.h"
 #include "hw/ppc/spapr_vio.h"
 #include "trace.h"
+#include "qom/object.h"
 
 #define DEBUG_SPAPR 0
 
-#define VIO_SPAPR_VTPM(obj) \
-     OBJECT_CHECK(SpaprTpmState, (obj), TYPE_TPM_SPAPR)
+typedef struct SpaprTpmState SpaprTpmState;
+DECLARE_INSTANCE_CHECKER(SpaprTpmState, VIO_SPAPR_VTPM,
+                         TYPE_TPM_SPAPR)
 
 typedef struct TpmCrq {
     uint8_t valid;  /* 0x80: cmd; 0xc0: init crq */
@@ -64,7 +66,7 @@ typedef struct TpmCrq {
 
 #define TPM_SPAPR_BUFFER_MAX                 4096
 
-typedef struct {
+struct SpaprTpmState {
     SpaprVioDevice vdev;
 
     TpmCrq crq; /* track single TPM command */
@@ -84,7 +86,7 @@ typedef struct {
     TPMVersion be_tpm_version;
 
     size_t be_buffer_size;
-} SpaprTpmState;
+};
 
 /*
  * Send a request to the TPM.
diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c
index 5faf6231c0..fafdcffa9c 100644
--- a/hw/tpm/tpm_tis_isa.c
+++ b/hw/tpm/tpm_tis_isa.c
@@ -29,16 +29,19 @@
 #include "hw/acpi/tpm.h"
 #include "tpm_prop.h"
 #include "tpm_tis.h"
+#include "qom/object.h"
 
-typedef struct TPMStateISA {
+struct TPMStateISA {
     /*< private >*/
     ISADevice parent_obj;
 
     /*< public >*/
     TPMState state; /* not a QOM object */
-} TPMStateISA;
+};
+typedef struct TPMStateISA TPMStateISA;
 
-#define TPM_TIS_ISA(obj) OBJECT_CHECK(TPMStateISA, (obj), TYPE_TPM_TIS_ISA)
+DECLARE_INSTANCE_CHECKER(TPMStateISA, TPM_TIS_ISA,
+                         TYPE_TPM_TIS_ISA)
 
 static int tpm_tis_pre_save_isa(void *opaque)
 {
diff --git a/hw/tpm/tpm_tis_sysbus.c b/hw/tpm/tpm_tis_sysbus.c
index 4a3bc70625..20b28eeb28 100644
--- a/hw/tpm/tpm_tis_sysbus.c
+++ b/hw/tpm/tpm_tis_sysbus.c
@@ -29,16 +29,19 @@
 #include "tpm_prop.h"
 #include "hw/sysbus.h"
 #include "tpm_tis.h"
+#include "qom/object.h"
 
-typedef struct TPMStateSysBus {
+struct TPMStateSysBus {
     /*< private >*/
     SysBusDevice parent_obj;
 
     /*< public >*/
     TPMState state; /* not a QOM object */
-} TPMStateSysBus;
+};
+typedef struct TPMStateSysBus TPMStateSysBus;
 
-#define TPM_TIS_SYSBUS(obj) OBJECT_CHECK(TPMStateSysBus, (obj), TYPE_TPM_TIS_SYSBUS)
+DECLARE_INSTANCE_CHECKER(TPMStateSysBus, TPM_TIS_SYSBUS,
+                         TYPE_TPM_TIS_SYSBUS)
 
 static int tpm_tis_pre_save_sysbus(void *opaque)
 {
diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events
index de9bf1e01b..266de17d38 100644
--- a/hw/tpm/trace-events
+++ b/hw/tpm/trace-events
@@ -4,7 +4,7 @@
 tpm_crb_mmio_read(uint64_t addr, unsigned size, uint32_t val) "CRB read 0x%016" PRIx64 " len:%u val: 0x%" PRIx32
 tpm_crb_mmio_write(uint64_t addr, unsigned size, uint32_t val) "CRB write 0x%016" PRIx64 " len:%u val: 0x%" PRIx32
 
-# tpm_tis.c
+# tpm_tis_common.c
 tpm_tis_raise_irq(uint32_t irqmask) "Raising IRQ for flag 0x%08x"
 tpm_tis_new_active_locality(uint8_t locty) "Active locality is now %d"
 tpm_tis_abort(uint8_t locty) "New active locality is %d"
diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c
index 0f1afd66be..5e4649d367 100644
--- a/hw/usb/ccid-card-emulated.c
+++ b/hw/usb/ccid-card-emulated.c
@@ -35,6 +35,7 @@
 #include "ccid.h"
 #include "hw/qdev-properties.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 #define DPRINTF(card, lvl, fmt, ...) \
 do {\
@@ -45,8 +46,9 @@ do {\
 
 
 #define TYPE_EMULATED_CCID "ccid-card-emulated"
-#define EMULATED_CCID_CARD(obj) \
-    OBJECT_CHECK(EmulatedState, (obj), TYPE_EMULATED_CCID)
+typedef struct EmulatedState EmulatedState;
+DECLARE_INSTANCE_CHECKER(EmulatedState, EMULATED_CCID_CARD,
+                         TYPE_EMULATED_CCID)
 
 #define BACKEND_NSS_EMULATED_NAME "nss-emulated"
 #define BACKEND_CERTIFICATES_NAME "certificates"
@@ -58,7 +60,6 @@ enum {
 
 #define DEFAULT_BACKEND BACKEND_NSS_EMULATED
 
-typedef struct EmulatedState EmulatedState;
 
 enum {
     EMUL_READER_INSERT = 0,
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index bb325dbc4a..e8e9d37e88 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -20,6 +20,7 @@
 #include "qemu/sockets.h"
 #include "ccid.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 #define DPRINTF(card, lvl, fmt, ...)                    \
 do {                                                    \
@@ -64,8 +65,8 @@ struct PassthruState {
 };
 
 #define TYPE_CCID_PASSTHRU "ccid-card-passthru"
-#define PASSTHRU_CCID_CARD(obj) \
-    OBJECT_CHECK(PassthruState, (obj), TYPE_CCID_PASSTHRU)
+DECLARE_INSTANCE_CHECKER(PassthruState, PASSTHRU_CCID_CARD,
+                         TYPE_CCID_PASSTHRU)
 
 /*
  * VSCard protocol over chardev
diff --git a/hw/usb/ccid.h b/hw/usb/ccid.h
index 531bf28fb0..ef2bb3462d 100644
--- a/hw/usb/ccid.h
+++ b/hw/usb/ccid.h
@@ -11,23 +11,21 @@
 #define CCID_H
 
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 typedef struct CCIDCardState CCIDCardState;
 typedef struct CCIDCardInfo CCIDCardInfo;
 
 #define TYPE_CCID_CARD "ccid-card"
-#define CCID_CARD(obj) \
-     OBJECT_CHECK(CCIDCardState, (obj), TYPE_CCID_CARD)
-#define CCID_CARD_CLASS(klass) \
-     OBJECT_CLASS_CHECK(CCIDCardClass, (klass), TYPE_CCID_CARD)
-#define CCID_CARD_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(CCIDCardClass, (obj), TYPE_CCID_CARD)
+typedef struct CCIDCardClass CCIDCardClass;
+DECLARE_OBJ_CHECKERS(CCIDCardState, CCIDCardClass,
+                     CCID_CARD, TYPE_CCID_CARD)
 
 /*
  * callbacks to be used by the CCID device (hw/usb-ccid.c) to call
  * into the smartcard device (hw/ccid-card-*.c)
  */
-typedef struct CCIDCardClass {
+struct CCIDCardClass {
     /*< private >*/
     DeviceClass parent_class;
     /*< public >*/
@@ -37,7 +35,7 @@ typedef struct CCIDCardClass {
                             uint32_t len);
     void (*realize)(CCIDCardState *card, Error **errp);
     void (*unrealize)(CCIDCardState *card);
-} CCIDCardClass;
+};
 
 /*
  * state of the CCID Card device (i.e. hw/ccid-card-*.c)
diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
index 1371c44f48..65247ca799 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -36,6 +36,7 @@
 #include "migration/vmstate.h"
 #include "desc.h"
 #include "audio/audio.h"
+#include "qom/object.h"
 
 static void usb_audio_reinit(USBDevice *dev, unsigned channels);
 
@@ -633,7 +634,7 @@ static uint8_t *streambuf_get(struct streambuf *buf, size_t *len)
     return data;
 }
 
-typedef struct USBAudioState {
+struct USBAudioState {
     /* qemu interfaces */
     USBDevice dev;
     QEMUSoundCard card;
@@ -652,10 +653,12 @@ typedef struct USBAudioState {
     uint32_t debug;
     uint32_t buffer_user, buffer;
     bool multi;
-} USBAudioState;
+};
+typedef struct USBAudioState USBAudioState;
 
 #define TYPE_USB_AUDIO "usb-audio"
-#define USB_AUDIO(obj) OBJECT_CHECK(USBAudioState, (obj), TYPE_USB_AUDIO)
+DECLARE_INSTANCE_CHECKER(USBAudioState, USB_AUDIO,
+                         TYPE_USB_AUDIO)
 
 static void output_callback(void *opaque, int avail)
 {
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
index c73f7b2fe2..05cfe6baca 100644
--- a/hw/usb/dev-hid.c
+++ b/hw/usb/dev-hid.c
@@ -34,18 +34,21 @@
 #include "hw/input/hid.h"
 #include "hw/usb/hid.h"
 #include "hw/qdev-properties.h"
+#include "qom/object.h"
 
-typedef struct USBHIDState {
+struct USBHIDState {
     USBDevice dev;
     USBEndpoint *intr;
     HIDState hid;
     uint32_t usb_version;
     char *display;
     uint32_t head;
-} USBHIDState;
+};
+typedef struct USBHIDState USBHIDState;
 
 #define TYPE_USB_HID "usb-hid"
-#define USB_HID(obj) OBJECT_CHECK(USBHIDState, (obj), TYPE_USB_HID)
+DECLARE_INSTANCE_CHECKER(USBHIDState, USB_HID,
+                         TYPE_USB_HID)
 
 enum {
     STR_MANUFACTURER = 1,
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index 5f19dd9fb5..7a182f9bec 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -32,6 +32,7 @@
 #include "desc.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define MAX_PORTS 8
 
@@ -41,17 +42,19 @@ typedef struct USBHubPort {
     uint16_t wPortChange;
 } USBHubPort;
 
-typedef struct USBHubState {
+struct USBHubState {
     USBDevice dev;
     USBEndpoint *intr;
     uint32_t num_ports;
     bool port_power;
     QEMUTimer *port_timer;
     USBHubPort ports[MAX_PORTS];
-} USBHubState;
+};
+typedef struct USBHubState USBHubState;
 
 #define TYPE_USB_HUB "usb-hub"
-#define USB_HUB(obj) OBJECT_CHECK(USBHubState, (obj), TYPE_USB_HUB)
+DECLARE_INSTANCE_CHECKER(USBHubState, USB_HUB,
+                         TYPE_USB_HUB)
 
 #define ClearHubFeature		(0x2000 | USB_REQ_CLEAR_FEATURE)
 #define ClearPortFeature	(0x2300 | USB_REQ_CLEAR_FEATURE)
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 15a2243101..c61c0e0878 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -28,6 +28,7 @@
 #include "migration/vmstate.h"
 #include "desc.h"
 #include "qemu/units.h"
+#include "qom/object.h"
 
 /* ----------------------------------------------------------------------- */
 
@@ -237,7 +238,8 @@ typedef struct {
 } QEMU_PACKED ObjectInfo;
 
 #define TYPE_USB_MTP "usb-mtp"
-#define USB_MTP(obj) OBJECT_CHECK(MTPState, (obj), TYPE_USB_MTP)
+DECLARE_INSTANCE_CHECKER(MTPState, USB_MTP,
+                         TYPE_USB_MTP)
 
 #define QEMU_STORAGE_ID 0x00010001
 
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index c69756709b..cd32f57685 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -37,6 +37,7 @@
 #include "qemu/iov.h"
 #include "qemu/module.h"
 #include "qemu/cutils.h"
+#include "qom/object.h"
 
 /*#define TRAFFIC_DEBUG*/
 /* Thanks to NetChip Technologies for donating this product ID.
@@ -629,7 +630,7 @@ struct rndis_response {
     uint8_t buf[];
 };
 
-typedef struct USBNetState {
+struct USBNetState {
     USBDevice dev;
 
     enum rndis_state rndis_state;
@@ -651,10 +652,12 @@ typedef struct USBNetState {
     NICState *nic;
     NICConf conf;
     QTAILQ_HEAD(, rndis_response) rndis_resp;
-} USBNetState;
+};
+typedef struct USBNetState USBNetState;
 
 #define TYPE_USB_NET "usb-net"
-#define USB_NET(obj) OBJECT_CHECK(USBNetState, (obj), TYPE_USB_NET)
+DECLARE_INSTANCE_CHECKER(USBNetState, USB_NET,
+                         TYPE_USB_NET)
 
 static int is_rndis(USBNetState *s)
 {
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 7e50e3ba47..1a038a222e 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -19,6 +19,7 @@
 #include "desc.h"
 #include "chardev/char-serial.h"
 #include "chardev/char-fe.h"
+#include "qom/object.h"
 
 //#define DEBUG_Serial
 
@@ -96,7 +97,7 @@ do { printf("usb-serial: " fmt , ## __VA_ARGS__); } while (0)
 #define FTDI_TEMT (1<<6)        // Transmitter Empty
 #define FTDI_FIFO (1<<7)        // Error in FIFO
 
-typedef struct {
+struct USBSerialState {
     USBDevice dev;
     USBEndpoint *intr;
     uint8_t recv_buf[RECV_BUF];
@@ -108,10 +109,12 @@ typedef struct {
     QEMUSerialSetParams params;
     int latency;        /* ms */
     CharBackend cs;
-} USBSerialState;
+};
+typedef struct USBSerialState USBSerialState;
 
 #define TYPE_USB_SERIAL "usb-serial-dev"
-#define USB_SERIAL_DEV(obj) OBJECT_CHECK(USBSerialState, (obj), TYPE_USB_SERIAL)
+DECLARE_INSTANCE_CHECKER(USBSerialState, USB_SERIAL,
+                         TYPE_USB_SERIAL)
 
 enum {
     STR_MANUFACTURER = 1,
@@ -514,7 +517,7 @@ static void usb_serial_event(void *opaque, QEMUChrEvent event)
 
 static void usb_serial_realize(USBDevice *dev, Error **errp)
 {
-    USBSerialState *s = USB_SERIAL_DEV(dev);
+    USBSerialState *s = USB_SERIAL(dev);
     Error *local_err = NULL;
 
     usb_desc_create_serial(dev);
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index fcfe216594..59b2248f34 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -46,6 +46,7 @@
 #include "desc.h"
 
 #include "ccid.h"
+#include "qom/object.h"
 
 #define DPRINTF(s, lvl, fmt, ...) \
 do { \
@@ -59,8 +60,10 @@ do { \
 #define D_MORE_INFO 3
 #define D_VERBOSE 4
 
-#define CCID_DEV_NAME "usb-ccid"
-#define USB_CCID_DEV(obj) OBJECT_CHECK(USBCCIDState, (obj), CCID_DEV_NAME)
+#define TYPE_USB_CCID_DEV "usb-ccid"
+typedef struct USBCCIDState USBCCIDState;
+DECLARE_INSTANCE_CHECKER(USBCCIDState, USB_CCID_DEV,
+                         TYPE_USB_CCID_DEV)
 /*
  * The two options for variable sized buffers:
  * make them constant size, for large enough constant,
@@ -274,14 +277,15 @@ typedef struct BulkIn {
     uint32_t pos;
 } BulkIn;
 
-typedef struct CCIDBus {
+struct CCIDBus {
     BusState qbus;
-} CCIDBus;
+};
+typedef struct CCIDBus CCIDBus;
 
 /*
  * powered - defaults to true, changed by PowerOn/PowerOff messages
  */
-typedef struct USBCCIDState {
+struct USBCCIDState {
     USBDevice dev;
     USBEndpoint *intr;
     USBEndpoint *bulk;
@@ -309,7 +313,7 @@ typedef struct USBCCIDState {
     uint8_t  powered;
     uint8_t  notify_slot_change;
     uint8_t  debug;
-} USBCCIDState;
+};
 
 /*
  * CCID Spec chapter 4: CCID uses a standard device descriptor per Chapter 9,
@@ -1173,7 +1177,8 @@ static Property ccid_props[] = {
 };
 
 #define TYPE_CCID_BUS "ccid-bus"
-#define CCID_BUS(obj) OBJECT_CHECK(CCIDBus, (obj), TYPE_CCID_BUS)
+DECLARE_INSTANCE_CHECKER(CCIDBus, CCID_BUS,
+                         TYPE_CCID_BUS)
 
 static const TypeInfo ccid_bus_info = {
     .name = TYPE_CCID_BUS,
@@ -1457,7 +1462,7 @@ static void ccid_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo ccid_info = {
-    .name          = CCID_DEV_NAME,
+    .name          = TYPE_USB_CCID_DEV,
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBCCIDState),
     .class_init    = ccid_class_initfn,
@@ -1490,7 +1495,7 @@ static void ccid_register_types(void)
     type_register_static(&ccid_bus_info);
     type_register_static(&ccid_card_type_info);
     type_register_static(&ccid_info);
-    usb_legacy_register(CCID_DEV_NAME, "ccid", NULL);
+    usb_legacy_register(TYPE_USB_CCID_DEV, "ccid", NULL);
 }
 
 type_init(ccid_register_types)
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 405a4ccfe7..648340323f 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -22,6 +22,7 @@
 #include "sysemu/block-backend.h"
 #include "qapi/visitor.h"
 #include "qemu/cutils.h"
+#include "qom/object.h"
 
 //#define DEBUG_MSD
 
@@ -50,7 +51,7 @@ struct usb_msd_csw {
     uint8_t status;
 };
 
-typedef struct {
+struct MSDState {
     USBDevice dev;
     enum USBMSDMode mode;
     uint32_t scsi_off;
@@ -65,10 +66,12 @@ typedef struct {
     BlockConf conf;
     uint32_t removable;
     SCSIDevice *scsi_dev;
-} MSDState;
+};
+typedef struct MSDState MSDState;
 
 #define TYPE_USB_STORAGE "usb-storage-dev"
-#define USB_STORAGE_DEV(obj) OBJECT_CHECK(MSDState, (obj), TYPE_USB_STORAGE)
+DECLARE_INSTANCE_CHECKER(MSDState, USB_STORAGE_DEV,
+                         TYPE_USB_STORAGE)
 
 struct usb_msd_cbw {
     uint32_t sig;
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index a3a4d41c07..c36c8e7820 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -23,6 +23,7 @@
 #include "hw/qdev-properties.h"
 #include "hw/scsi/scsi.h"
 #include "scsi/constants.h"
+#include "qom/object.h"
 
 /* --------------------------------------------------------------------- */
 
@@ -132,7 +133,8 @@ struct UASDevice {
 };
 
 #define TYPE_USB_UAS "usb-uas"
-#define USB_UAS(obj) OBJECT_CHECK(UASDevice, (obj), TYPE_USB_UAS)
+DECLARE_INSTANCE_CHECKER(UASDevice, USB_UAS,
+                         TYPE_USB_UAS)
 
 struct UASRequest {
     uint16_t     tag;
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index 76fc5a5dab..85c4d827bf 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -33,12 +33,13 @@
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "desc.h"
+#include "qom/object.h"
 
 /* Interface requests */
 #define WACOM_GET_REPORT	0x2101
 #define WACOM_SET_REPORT	0x2109
 
-typedef struct USBWacomState {
+struct USBWacomState {
     USBDevice dev;
     USBEndpoint *intr;
     QEMUPutMouseEntry *eh_entry;
@@ -51,10 +52,12 @@ typedef struct USBWacomState {
     } mode;
     uint8_t idle;
     int changed;
-} USBWacomState;
+};
+typedef struct USBWacomState USBWacomState;
 
 #define TYPE_USB_WACOM "usb-wacom-tablet"
-#define USB_WACOM(obj) OBJECT_CHECK(USBWacomState, (obj), TYPE_USB_WACOM)
+DECLARE_INSTANCE_CHECKER(USBWacomState, USB_WACOM,
+                         TYPE_USB_WACOM)
 
 enum {
     STR_MANUFACTURER = 1,
diff --git a/hw/usb/hcd-dwc2.h b/hw/usb/hcd-dwc2.h
index 54111d835e..919e3e43b1 100644
--- a/hw/usb/hcd-dwc2.h
+++ b/hw/usb/hcd-dwc2.h
@@ -24,6 +24,7 @@
 #include "hw/sysbus.h"
 #include "hw/usb.h"
 #include "sysemu/dma.h"
+#include "qom/object.h"
 
 #define DWC2_MMIO_SIZE      0x11000
 
@@ -180,11 +181,7 @@ struct DWC2Class {
 };
 
 #define TYPE_DWC2_USB   "dwc2-usb"
-#define DWC2_USB(obj) \
-    OBJECT_CHECK(DWC2State, (obj), TYPE_DWC2_USB)
-#define DWC2_USB_CLASS(klass) \
-    OBJECT_CLASS_CHECK(DWC2Class, (klass), TYPE_DWC2_USB)
-#define DWC2_USB_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(DWC2Class, (obj), TYPE_DWC2_USB)
+DECLARE_OBJ_CHECKERS(DWC2State, DWC2Class,
+                     DWC2_USB, TYPE_DWC2_USB)
 
 #endif
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index 57b38cfc05..1301ce0be7 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -23,6 +23,7 @@
 #include "sysemu/dma.h"
 #include "hw/pci/pci.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #ifndef EHCI_DEBUG
 #define EHCI_DEBUG   0
@@ -328,15 +329,17 @@ void usb_ehci_unrealize(EHCIState *s, DeviceState *dev);
 void ehci_reset(void *opaque);
 
 #define TYPE_PCI_EHCI "pci-ehci-usb"
-#define PCI_EHCI(obj) OBJECT_CHECK(EHCIPCIState, (obj), TYPE_PCI_EHCI)
+typedef struct EHCIPCIState EHCIPCIState;
+DECLARE_INSTANCE_CHECKER(EHCIPCIState, PCI_EHCI,
+                         TYPE_PCI_EHCI)
 
-typedef struct EHCIPCIState {
+struct EHCIPCIState {
     /*< private >*/
     PCIDevice pcidev;
     /*< public >*/
 
     EHCIState ehci;
-} EHCIPCIState;
+};
 
 
 #define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
@@ -347,22 +350,20 @@ typedef struct EHCIPCIState {
 #define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
 #define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
 
-#define SYS_BUS_EHCI(obj) \
-    OBJECT_CHECK(EHCISysBusState, (obj), TYPE_SYS_BUS_EHCI)
-#define SYS_BUS_EHCI_CLASS(class) \
-    OBJECT_CLASS_CHECK(SysBusEHCIClass, (class), TYPE_SYS_BUS_EHCI)
-#define SYS_BUS_EHCI_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(SysBusEHCIClass, (obj), TYPE_SYS_BUS_EHCI)
+typedef struct EHCISysBusState EHCISysBusState;
+typedef struct SysBusEHCIClass SysBusEHCIClass;
+DECLARE_OBJ_CHECKERS(EHCISysBusState, SysBusEHCIClass,
+                     SYS_BUS_EHCI, TYPE_SYS_BUS_EHCI)
 
-typedef struct EHCISysBusState {
+struct EHCISysBusState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
 
     EHCIState ehci;
-} EHCISysBusState;
+};
 
-typedef struct SysBusEHCIClass {
+struct SysBusEHCIClass {
     /*< private >*/
     SysBusDeviceClass parent_class;
     /*< public >*/
@@ -371,17 +372,18 @@ typedef struct SysBusEHCIClass {
     uint16_t opregbase;
     uint16_t portscbase;
     uint16_t portnr;
-} SysBusEHCIClass;
+};
 
-#define FUSBH200_EHCI(obj) \
-    OBJECT_CHECK(FUSBH200EHCIState, (obj), TYPE_FUSBH200_EHCI)
+typedef struct FUSBH200EHCIState FUSBH200EHCIState;
+DECLARE_INSTANCE_CHECKER(FUSBH200EHCIState, FUSBH200_EHCI,
+                         TYPE_FUSBH200_EHCI)
 
-typedef struct FUSBH200EHCIState {
+struct FUSBH200EHCIState {
     /*< private >*/
     EHCISysBusState parent_obj;
     /*< public >*/
 
     MemoryRegion mem_vendor;
-} FUSBH200EHCIState;
+};
 
 #endif
diff --git a/hw/usb/hcd-ohci-pci.c b/hw/usb/hcd-ohci-pci.c
index a7fb1666af..f8168a06a3 100644
--- a/hw/usb/hcd-ohci-pci.c
+++ b/hw/usb/hcd-ohci-pci.c
@@ -29,11 +29,14 @@
 #include "hw/qdev-properties.h"
 #include "trace.h"
 #include "hcd-ohci.h"
+#include "qom/object.h"
 
 #define TYPE_PCI_OHCI "pci-ohci"
-#define PCI_OHCI(obj) OBJECT_CHECK(OHCIPCIState, (obj), TYPE_PCI_OHCI)
+typedef struct OHCIPCIState OHCIPCIState;
+DECLARE_INSTANCE_CHECKER(OHCIPCIState, PCI_OHCI,
+                         TYPE_PCI_OHCI)
 
-typedef struct {
+struct OHCIPCIState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
@@ -42,7 +45,7 @@ typedef struct {
     char *masterbus;
     uint32_t num_ports;
     uint32_t firstport;
-} OHCIPCIState;
+};
 
 /**
  * A typical PCI OHCI will additionally set PERR in its configspace to
diff --git a/hw/usb/hcd-ohci.h b/hw/usb/hcd-ohci.h
index 5c8819aedf..6e28e97839 100644
--- a/hw/usb/hcd-ohci.h
+++ b/hw/usb/hcd-ohci.h
@@ -23,6 +23,7 @@
 
 #include "sysemu/dma.h"
 #include "hw/usb.h"
+#include "qom/object.h"
 
 /* Number of Downstream Ports on the root hub: */
 #define OHCI_MAX_PORTS 15
@@ -92,9 +93,11 @@ typedef struct OHCIState {
 } OHCIState;
 
 #define TYPE_SYSBUS_OHCI "sysbus-ohci"
-#define SYSBUS_OHCI(obj) OBJECT_CHECK(OHCISysBusState, (obj), TYPE_SYSBUS_OHCI)
+typedef struct OHCISysBusState OHCISysBusState;
+DECLARE_INSTANCE_CHECKER(OHCISysBusState, SYSBUS_OHCI,
+                         TYPE_SYSBUS_OHCI)
 
-typedef struct {
+struct OHCISysBusState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -104,7 +107,7 @@ typedef struct {
     uint32_t num_ports;
     uint32_t firstport;
     dma_addr_t dma_offset;
-} OHCISysBusState;
+};
 
 extern const VMStateDescription vmstate_ohci_state;
 
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 37f7beb3fa..27ca237d71 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -39,6 +39,7 @@
 #include "trace.h"
 #include "qemu/main-loop.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 #define FRAME_TIMER_FREQ 1000
 
@@ -160,7 +161,8 @@ static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td);
 static void uhci_resume(void *opaque);
 
 #define TYPE_UHCI "pci-uhci-usb"
-#define UHCI(obj) OBJECT_CHECK(UHCIState, (obj), TYPE_UHCI)
+DECLARE_INSTANCE_CHECKER(UHCIState, UHCI,
+                         TYPE_UHCI)
 
 static inline int32_t uhci_queue_token(UHCI_TD *td)
 {
diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h
index 946af51fc2..2110c0399e 100644
--- a/hw/usb/hcd-xhci.h
+++ b/hw/usb/hcd-xhci.h
@@ -21,13 +21,15 @@
 
 #ifndef HW_USB_HCD_XHCI_H
 #define HW_USB_HCD_XHCI_H
+#include "qom/object.h"
 
 #define TYPE_XHCI "base-xhci"
 #define TYPE_NEC_XHCI "nec-usb-xhci"
 #define TYPE_QEMU_XHCI "qemu-xhci"
 
-#define XHCI(obj) \
-    OBJECT_CHECK(XHCIState, (obj), TYPE_XHCI)
+typedef struct XHCIState XHCIState;
+DECLARE_INSTANCE_CHECKER(XHCIState, XHCI,
+                         TYPE_XHCI)
 
 #define MAXPORTS_2 15
 #define MAXPORTS_3 15
@@ -39,7 +41,6 @@
 /* Very pessimistic, let's hope it's enough for all cases */
 #define EV_QUEUE (((3 * 24) + 16) * MAXSLOTS)
 
-typedef struct XHCIState XHCIState;
 typedef struct XHCIStreamContext XHCIStreamContext;
 typedef struct XHCIEPContext XHCIEPContext;
 
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index 08604f787f..43c93504a2 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -34,6 +34,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qom/object.h"
 #ifndef CONFIG_WIN32
 #include <poll.h>
 #endif
@@ -60,10 +61,10 @@
 /* ------------------------------------------------------------------------ */
 
 #define TYPE_USB_HOST_DEVICE "usb-host"
-#define USB_HOST_DEVICE(obj) \
-     OBJECT_CHECK(USBHostDevice, (obj), TYPE_USB_HOST_DEVICE)
-
 typedef struct USBHostDevice USBHostDevice;
+DECLARE_INSTANCE_CHECKER(USBHostDevice, USB_HOST_DEVICE,
+                         TYPE_USB_HOST_DEVICE)
+
 typedef struct USBHostRequest USBHostRequest;
 typedef struct USBHostIsoXfer USBHostIsoXfer;
 typedef struct USBHostIsoRing USBHostIsoRing;
@@ -942,7 +943,7 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd)
     usb_host_ep_update(s);
 
     libusb_speed = libusb_get_device_speed(dev);
-#ifdef CONFIG_LINUX
+#if LIBUSB_API_VERSION >= 0x01000107 && defined(CONFIG_LINUX)
     if (hostfd && libusb_speed == 0) {
         /*
          * Workaround libusb bug: libusb_get_device_speed() does not
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 417a60a2e6..3238de6bb8 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -45,6 +45,7 @@
 #include "hw/usb.h"
 #include "migration/qemu-file-types.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 /* ERROR is defined below. Remove any previous definition. */
 #undef ERROR
@@ -144,7 +145,8 @@ struct USBRedirDevice {
 };
 
 #define TYPE_USB_REDIR "usb-redir"
-#define USB_REDIRECT(obj) OBJECT_CHECK(USBRedirDevice, (obj), TYPE_USB_REDIR)
+DECLARE_INSTANCE_CHECKER(USBRedirDevice, USB_REDIRECT,
+                         TYPE_USB_REDIR)
 
 static void usbredir_hello(void *priv, struct usb_redir_hello_header *h);
 static void usbredir_device_connect(void *priv,
@@ -240,7 +242,7 @@ static void usbredir_log_data(USBRedirDevice *dev, const char *desc,
     if (dev->debug < usbredirparser_debug_data) {
         return;
     }
-    qemu_hexdump((char *)data, stderr, desc, len);
+    qemu_hexdump(stderr, desc, data, len);
 }
 
 /*
diff --git a/hw/usb/trace-events b/hw/usb/trace-events
index e9cdeeed14..72e4298780 100644
--- a/hw/usb/trace-events
+++ b/hw/usb/trace-events
@@ -10,6 +10,9 @@ usb_port_attach(int bus, const char *port, const char *devspeed, const char *por
 usb_port_detach(int bus, const char *port) "bus %d, port %s"
 usb_port_release(int bus, const char *port) "bus %d, port %s"
 
+# hcd-ohci-pci.c
+usb_ohci_exit(const char *s) "%s"
+
 # hcd-ohci.c
 usb_ohci_iso_td_read_failed(uint32_t addr) "ISO_TD read error at 0x%x"
 usb_ohci_iso_td_head(uint32_t head, uint32_t tail, uint32_t flags, uint32_t bp, uint32_t next, uint32_t be, uint32_t framenum, uint32_t startframe, uint32_t framecount, int rel_frame_num) "ISO_TD ED head 0x%.8x tailp 0x%.8x\n0x%.8x 0x%.8x 0x%.8x 0x%.8x\nframe_number 0x%.8x starting_frame 0x%.8x\nframe_count  0x%.8x relative %d"
@@ -35,7 +38,6 @@ usb_ohci_reset(const char *s) "%s"
 usb_ohci_start(const char *s) "%s: USB Operational"
 usb_ohci_resume(const char *s) "%s: USB Resume"
 usb_ohci_stop(const char *s) "%s: USB Suspended"
-usb_ohci_exit(const char *s) "%s"
 usb_ohci_set_ctl(const char *s, uint32_t new_state) "%s: new state 0x%x"
 usb_ohci_td_underrun(void) ""
 usb_ohci_td_dev_error(void) ""
diff --git a/hw/usb/tusb6010.c b/hw/usb/tusb6010.c
index 27eb28d3e4..dd20996d13 100644
--- a/hw/usb/tusb6010.c
+++ b/hw/usb/tusb6010.c
@@ -28,11 +28,14 @@
 #include "hw/hw.h"
 #include "hw/irq.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_TUSB6010 "tusb6010"
-#define TUSB(obj) OBJECT_CHECK(TUSBState, (obj), TYPE_TUSB6010)
+typedef struct TUSBState TUSBState;
+DECLARE_INSTANCE_CHECKER(TUSBState, TUSB6010,
+                         TYPE_TUSB6010)
 
-typedef struct TUSBState {
+struct TUSBState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem[2];
@@ -68,7 +71,7 @@ typedef struct TUSBState {
     uint32_t pullup[2];
     uint32_t control_config;
     uint32_t otg_timer_val;
-} TUSBState;
+};
 
 #define TUSB_DEVCLOCK			60000000	/* 60 MHz */
 
@@ -776,7 +779,7 @@ static void tusb6010_irq(void *opaque, int source, int level)
 
 static void tusb6010_reset(DeviceState *dev)
 {
-    TUSBState *s = TUSB(dev);
+    TUSBState *s = TUSB6010(dev);
     int i;
 
     s->test_reset = TUSB_PROD_TEST_RESET_VAL;
@@ -812,7 +815,7 @@ static void tusb6010_reset(DeviceState *dev)
 
 static void tusb6010_realize(DeviceState *dev, Error **errp)
 {
-    TUSBState *s = TUSB(dev);
+    TUSBState *s = TUSB6010(dev);
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 
     s->otg_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tusb_otg_tick, s);
diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c
index cec6fe1599..582c091a24 100644
--- a/hw/vfio/ap.c
+++ b/hw/vfio/ap.c
@@ -28,16 +28,18 @@
 #include "hw/qdev-properties.h"
 #include "hw/s390x/ap-bridge.h"
 #include "exec/address-spaces.h"
+#include "qom/object.h"
 
-#define VFIO_AP_DEVICE_TYPE      "vfio-ap"
+#define TYPE_VFIO_AP_DEVICE      "vfio-ap"
 
-typedef struct VFIOAPDevice {
+struct VFIOAPDevice {
     APDevice apdev;
     VFIODevice vdev;
-} VFIOAPDevice;
+};
+typedef struct VFIOAPDevice VFIOAPDevice;
 
-#define VFIO_AP_DEVICE(obj) \
-        OBJECT_CHECK(VFIOAPDevice, (obj), VFIO_AP_DEVICE_TYPE)
+DECLARE_INSTANCE_CHECKER(VFIOAPDevice, VFIO_AP_DEVICE,
+                         TYPE_VFIO_AP_DEVICE)
 
 static void vfio_ap_compute_needs_reset(VFIODevice *vdev)
 {
@@ -70,7 +72,7 @@ static VFIOGroup *vfio_ap_get_group(VFIOAPDevice *vapdev, Error **errp)
 
     if (!group_path) {
         error_setg(errp, "%s: no iommu_group found for %s: %s",
-                   VFIO_AP_DEVICE_TYPE, vapdev->vdev.sysfsdev, gerror->message);
+                   TYPE_VFIO_AP_DEVICE, vapdev->vdev.sysfsdev, gerror->message);
         g_error_free(gerror);
         return NULL;
     }
@@ -174,8 +176,8 @@ static void vfio_ap_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo vfio_ap_info = {
-    .name = VFIO_AP_DEVICE_TYPE,
-    .parent = AP_DEVICE_TYPE,
+    .name = TYPE_VFIO_AP_DEVICE,
+    .parent = TYPE_AP_DEVICE,
     .instance_size = sizeof(VFIOAPDevice),
     .class_init = vfio_ap_class_init,
 };
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 3611dcd38b..0d83eb0e47 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -230,7 +230,7 @@ static void vfio_intx_update(VFIOPCIDevice *vdev, PCIINTxRoute *route)
 
 static void vfio_intx_routing_notifier(PCIDevice *pdev)
 {
-    VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+    VFIOPCIDevice *vdev = VFIO_PCI(pdev);
     PCIINTxRoute route;
 
     if (vdev->interrupt != VFIO_INT_INTx) {
@@ -456,7 +456,7 @@ static void vfio_update_kvm_msi_virq(VFIOMSIVector *vector, MSIMessage msg,
 static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
                                    MSIMessage *msg, IOHandler *handler)
 {
-    VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+    VFIOPCIDevice *vdev = VFIO_PCI(pdev);
     VFIOMSIVector *vector;
     int ret;
 
@@ -541,7 +541,7 @@ static int vfio_msix_vector_use(PCIDevice *pdev,
 
 static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr)
 {
-    VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+    VFIOPCIDevice *vdev = VFIO_PCI(pdev);
     VFIOMSIVector *vector = &vdev->msi_vectors[nr];
 
     trace_vfio_msix_vector_release(vdev->vbasedev.name, nr);
@@ -1048,7 +1048,7 @@ static const MemoryRegionOps vfio_vga_ops = {
  */
 static void vfio_sub_page_bar_update_mapping(PCIDevice *pdev, int bar)
 {
-    VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+    VFIOPCIDevice *vdev = VFIO_PCI(pdev);
     VFIORegion *region = &vdev->bars[bar].region;
     MemoryRegion *mmap_mr, *region_mr, *base_mr;
     PCIIORegion *r;
@@ -1094,7 +1094,7 @@ static void vfio_sub_page_bar_update_mapping(PCIDevice *pdev, int bar)
  */
 uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len)
 {
-    VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+    VFIOPCIDevice *vdev = VFIO_PCI(pdev);
     uint32_t emu_bits = 0, emu_val = 0, phys_val = 0, val;
 
     memcpy(&emu_bits, vdev->emulated_config_bits + addr, len);
@@ -1127,7 +1127,7 @@ uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len)
 void vfio_pci_write_config(PCIDevice *pdev,
                            uint32_t addr, uint32_t val, int len)
 {
-    VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+    VFIOPCIDevice *vdev = VFIO_PCI(pdev);
     uint32_t val_le = cpu_to_le32(val);
 
     trace_vfio_pci_write_config(vdev->vbasedev.name, addr, val, len);
@@ -2701,7 +2701,7 @@ static void vfio_unregister_req_notifier(VFIOPCIDevice *vdev)
 
 static void vfio_realize(PCIDevice *pdev, Error **errp)
 {
-    VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+    VFIOPCIDevice *vdev = VFIO_PCI(pdev);
     VFIODevice *vbasedev_iter;
     VFIOGroup *group;
     char *tmp, *subsys, group_path[PATH_MAX], *group_name;
@@ -3033,7 +3033,7 @@ error:
 
 static void vfio_instance_finalize(Object *obj)
 {
-    VFIOPCIDevice *vdev = PCI_VFIO(obj);
+    VFIOPCIDevice *vdev = VFIO_PCI(obj);
     VFIOGroup *group = vdev->vbasedev.group;
 
     vfio_display_finalize(vdev);
@@ -3057,7 +3057,7 @@ static void vfio_instance_finalize(Object *obj)
 
 static void vfio_exitfn(PCIDevice *pdev)
 {
-    VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+    VFIOPCIDevice *vdev = VFIO_PCI(pdev);
 
     vfio_unregister_req_notifier(vdev);
     vfio_unregister_err_notifier(vdev);
@@ -3075,7 +3075,7 @@ static void vfio_exitfn(PCIDevice *pdev)
 
 static void vfio_pci_reset(DeviceState *dev)
 {
-    VFIOPCIDevice *vdev = PCI_VFIO(dev);
+    VFIOPCIDevice *vdev = VFIO_PCI(dev);
 
     trace_vfio_pci_reset(vdev->vbasedev.name);
 
@@ -3115,7 +3115,7 @@ post_reset:
 static void vfio_instance_init(Object *obj)
 {
     PCIDevice *pci_dev = PCI_DEVICE(obj);
-    VFIOPCIDevice *vdev = PCI_VFIO(obj);
+    VFIOPCIDevice *vdev = VFIO_PCI(obj);
 
     device_add_bootindex_property(obj, &vdev->bootindex,
                                   "bootindex", NULL,
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index 3c0dca024b..5e53d5b863 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -18,6 +18,7 @@
 #include "qemu/event_notifier.h"
 #include "qemu/queue.h"
 #include "qemu/timer.h"
+#include "qom/object.h"
 
 #define PCI_ANY_ID (~0)
 
@@ -114,9 +115,11 @@ typedef struct VFIOMSIXInfo {
 } VFIOMSIXInfo;
 
 #define TYPE_VFIO_PCI "vfio-pci"
-#define PCI_VFIO(obj)    OBJECT_CHECK(VFIOPCIDevice, obj, TYPE_VFIO_PCI)
+typedef struct VFIOPCIDevice VFIOPCIDevice;
+DECLARE_INSTANCE_CHECKER(VFIOPCIDevice, VFIO_PCI,
+                         TYPE_VFIO_PCI)
 
-typedef struct VFIOPCIDevice {
+struct VFIOPCIDevice {
     PCIDevice pdev;
     VFIODevice vbasedev;
     VFIOINTx intx;
@@ -173,7 +176,7 @@ typedef struct VFIOPCIDevice {
     VFIODisplay *dpy;
     Error *migration_blocker;
     Notifier irqchip_change_notifier;
-} VFIOPCIDevice;
+};
 
 /* Use uin32_t for vendor & device so PCI_ANY_ID expands and cannot match hw */
 static inline bool vfio_pci_is(VFIOPCIDevice *vdev, uint32_t vendor, uint32_t device)
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index b1ef55a33f..93a0bc2522 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -80,16 +80,18 @@ vfio_quirk_ati_bonaire_reset(const char *name) "%s"
 vfio_ioeventfd_exit(const char *name, uint64_t addr, unsigned size, uint64_t data) "%s+0x%"PRIx64"[%d]:0x%"PRIx64
 vfio_ioeventfd_handler(const char *name, uint64_t addr, unsigned size, uint64_t data) "%s+0x%"PRIx64"[%d] -> 0x%"PRIx64
 vfio_ioeventfd_init(const char *name, uint64_t addr, unsigned size, uint64_t data, bool vfio) "%s+0x%"PRIx64"[%d]:0x%"PRIx64" vfio:%d"
-vfio_pci_igd_bar4_write(const char *name, uint32_t index, uint32_t data, uint32_t base) "%s [0x%03x] 0x%08x -> 0x%08x"
-vfio_pci_igd_bdsm_enabled(const char *name, int size) "%s %dMB"
 vfio_pci_igd_opregion_enabled(const char *name) "%s"
-vfio_pci_igd_host_bridge_enabled(const char *name) "%s"
-vfio_pci_igd_lpc_bridge_enabled(const char *name) "%s"
 
 vfio_pci_nvidia_gpu_setup_quirk(const char *name, uint64_t tgt, uint64_t size) "%s tgt=0x%"PRIx64" size=0x%"PRIx64
 vfio_pci_nvlink2_setup_quirk_ssatgt(const char *name, uint64_t tgt, uint64_t size) "%s tgt=0x%"PRIx64" size=0x%"PRIx64
 vfio_pci_nvlink2_setup_quirk_lnkspd(const char *name, uint32_t link_speed) "%s link_speed=0x%x"
 
+# igd.c
+vfio_pci_igd_bar4_write(const char *name, uint32_t index, uint32_t data, uint32_t base) "%s [0x%03x] 0x%08x -> 0x%08x"
+vfio_pci_igd_bdsm_enabled(const char *name, int size) "%s %dMB"
+vfio_pci_igd_host_bridge_enabled(const char *name) "%s"
+vfio_pci_igd_lpc_bridge_enabled(const char *name) "%s"
+
 # common.c
 vfio_region_write(const char *name, int index, uint64_t addr, uint64_t data, unsigned size) " (%s:region%d+0x%"PRIx64", 0x%"PRIx64 ", %d)"
 vfio_region_read(char *name, int index, uint64_t addr, unsigned size, uint64_t data) " (%s:region%d+0x%"PRIx64", %d) = 0x%"PRIx64
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 045e89cae6..845200bf10 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -55,7 +55,7 @@ virtio_mmio_guest_page(uint64_t size, int shift) "guest page size 0x%" PRIx64 "
 virtio_mmio_queue_write(uint64_t value, int max_size) "mmio_queue write 0x%" PRIx64 " max %d"
 virtio_mmio_setting_irq(int level) "virtio_mmio setting IRQ %d"
 
-# hw/virtio/virtio-iommu.c
+# virtio-iommu.c
 virtio_iommu_device_reset(void) "reset!"
 virtio_iommu_get_features(uint64_t features) "device supports features=0x%"PRIx64
 virtio_iommu_device_status(uint8_t status) "driver status = %d"
diff --git a/hw/virtio/vhost-scsi-pci.c b/hw/virtio/vhost-scsi-pci.c
index a6bb0dc60d..cb71a294fa 100644
--- a/hw/virtio/vhost-scsi-pci.c
+++ b/hw/virtio/vhost-scsi-pci.c
@@ -22,6 +22,7 @@
 #include "qapi/error.h"
 #include "qemu/module.h"
 #include "virtio-pci.h"
+#include "qom/object.h"
 
 typedef struct VHostSCSIPCI VHostSCSIPCI;
 
@@ -29,8 +30,8 @@ typedef struct VHostSCSIPCI VHostSCSIPCI;
  * vhost-scsi-pci: This extends VirtioPCIProxy.
  */
 #define TYPE_VHOST_SCSI_PCI "vhost-scsi-pci-base"
-#define VHOST_SCSI_PCI(obj) \
-        OBJECT_CHECK(VHostSCSIPCI, (obj), TYPE_VHOST_SCSI_PCI)
+DECLARE_INSTANCE_CHECKER(VHostSCSIPCI, VHOST_SCSI_PCI,
+                         TYPE_VHOST_SCSI_PCI)
 
 struct VHostSCSIPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/vhost-user-blk-pci.c b/hw/virtio/vhost-user-blk-pci.c
index a62a71e067..33b404d8a2 100644
--- a/hw/virtio/vhost-user-blk-pci.c
+++ b/hw/virtio/vhost-user-blk-pci.c
@@ -27,6 +27,7 @@
 #include "qemu/error-report.h"
 #include "qemu/module.h"
 #include "virtio-pci.h"
+#include "qom/object.h"
 
 typedef struct VHostUserBlkPCI VHostUserBlkPCI;
 
@@ -34,8 +35,8 @@ typedef struct VHostUserBlkPCI VHostUserBlkPCI;
  * vhost-user-blk-pci: This extends VirtioPCIProxy.
  */
 #define TYPE_VHOST_USER_BLK_PCI "vhost-user-blk-pci-base"
-#define VHOST_USER_BLK_PCI(obj) \
-        OBJECT_CHECK(VHostUserBlkPCI, (obj), TYPE_VHOST_USER_BLK_PCI)
+DECLARE_INSTANCE_CHECKER(VHostUserBlkPCI, VHOST_USER_BLK_PCI,
+                         TYPE_VHOST_USER_BLK_PCI)
 
 struct VHostUserBlkPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/vhost-user-fs-pci.c b/hw/virtio/vhost-user-fs-pci.c
index e11c889d82..8bb389bd28 100644
--- a/hw/virtio/vhost-user-fs-pci.c
+++ b/hw/virtio/vhost-user-fs-pci.c
@@ -15,6 +15,7 @@
 #include "hw/qdev-properties.h"
 #include "hw/virtio/vhost-user-fs.h"
 #include "virtio-pci.h"
+#include "qom/object.h"
 
 struct VHostUserFSPCI {
     VirtIOPCIProxy parent_obj;
@@ -25,8 +26,8 @@ typedef struct VHostUserFSPCI VHostUserFSPCI;
 
 #define TYPE_VHOST_USER_FS_PCI "vhost-user-fs-pci-base"
 
-#define VHOST_USER_FS_PCI(obj) \
-        OBJECT_CHECK(VHostUserFSPCI, (obj), TYPE_VHOST_USER_FS_PCI)
+DECLARE_INSTANCE_CHECKER(VHostUserFSPCI, VHOST_USER_FS_PCI,
+                         TYPE_VHOST_USER_FS_PCI)
 
 static Property vhost_user_fs_pci_properties[] = {
     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
diff --git a/hw/virtio/vhost-user-input-pci.c b/hw/virtio/vhost-user-input-pci.c
index 0a50015599..c9d3e9113a 100644
--- a/hw/virtio/vhost-user-input-pci.c
+++ b/hw/virtio/vhost-user-input-pci.c
@@ -10,13 +10,14 @@
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "virtio-pci.h"
+#include "qom/object.h"
 
 typedef struct VHostUserInputPCI VHostUserInputPCI;
 
 #define TYPE_VHOST_USER_INPUT_PCI "vhost-user-input-pci"
 
-#define VHOST_USER_INPUT_PCI(obj) \
-    OBJECT_CHECK(VHostUserInputPCI, (obj), TYPE_VHOST_USER_INPUT_PCI)
+DECLARE_INSTANCE_CHECKER(VHostUserInputPCI, VHOST_USER_INPUT_PCI,
+                         TYPE_VHOST_USER_INPUT_PCI)
 
 struct VHostUserInputPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/vhost-user-scsi-pci.c b/hw/virtio/vhost-user-scsi-pci.c
index 25e97ca54e..d5343412a1 100644
--- a/hw/virtio/vhost-user-scsi-pci.c
+++ b/hw/virtio/vhost-user-scsi-pci.c
@@ -31,12 +31,13 @@
 #include "hw/loader.h"
 #include "sysemu/kvm.h"
 #include "virtio-pci.h"
+#include "qom/object.h"
 
 typedef struct VHostUserSCSIPCI VHostUserSCSIPCI;
 
 #define TYPE_VHOST_USER_SCSI_PCI "vhost-user-scsi-pci-base"
-#define VHOST_USER_SCSI_PCI(obj) \
-        OBJECT_CHECK(VHostUserSCSIPCI, (obj), TYPE_VHOST_USER_SCSI_PCI)
+DECLARE_INSTANCE_CHECKER(VHostUserSCSIPCI, VHOST_USER_SCSI_PCI,
+                         TYPE_VHOST_USER_SCSI_PCI)
 
 struct VHostUserSCSIPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/vhost-user-vsock-pci.c b/hw/virtio/vhost-user-vsock-pci.c
index f4cf95873d..763f89984e 100644
--- a/hw/virtio/vhost-user-vsock-pci.c
+++ b/hw/virtio/vhost-user-vsock-pci.c
@@ -13,6 +13,7 @@
 #include "virtio-pci.h"
 #include "hw/qdev-properties.h"
 #include "hw/virtio/vhost-user-vsock.h"
+#include "qom/object.h"
 
 typedef struct VHostUserVSockPCI VHostUserVSockPCI;
 
@@ -20,8 +21,8 @@ typedef struct VHostUserVSockPCI VHostUserVSockPCI;
  * vhost-user-vsock-pci: This extends VirtioPCIProxy.
  */
 #define TYPE_VHOST_USER_VSOCK_PCI "vhost-user-vsock-pci-base"
-#define VHOST_USER_VSOCK_PCI(obj) \
-        OBJECT_CHECK(VHostUserVSockPCI, (obj), TYPE_VHOST_USER_VSOCK_PCI)
+DECLARE_INSTANCE_CHECKER(VHostUserVSockPCI, VHOST_USER_VSOCK_PCI,
+                         TYPE_VHOST_USER_VSOCK_PCI)
 
 struct VHostUserVSockPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/vhost-vsock-pci.c b/hw/virtio/vhost-vsock-pci.c
index a815278e69..e56067b427 100644
--- a/hw/virtio/vhost-vsock-pci.c
+++ b/hw/virtio/vhost-vsock-pci.c
@@ -17,6 +17,7 @@
 #include "hw/qdev-properties.h"
 #include "hw/virtio/vhost-vsock.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 typedef struct VHostVSockPCI VHostVSockPCI;
 
@@ -24,8 +25,8 @@ typedef struct VHostVSockPCI VHostVSockPCI;
  * vhost-vsock-pci: This extends VirtioPCIProxy.
  */
 #define TYPE_VHOST_VSOCK_PCI "vhost-vsock-pci-base"
-#define VHOST_VSOCK_PCI(obj) \
-        OBJECT_CHECK(VHostVSockPCI, (obj), TYPE_VHOST_VSOCK_PCI)
+DECLARE_INSTANCE_CHECKER(VHostVSockPCI, VHOST_VSOCK_PCI,
+                         TYPE_VHOST_VSOCK_PCI)
 
 struct VHostVSockPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/virtio-9p-pci.c b/hw/virtio/virtio-9p-pci.c
index cbcb062faa..e07adcd9ea 100644
--- a/hw/virtio/virtio-9p-pci.c
+++ b/hw/virtio/virtio-9p-pci.c
@@ -19,19 +19,21 @@
 #include "hw/9pfs/virtio-9p.h"
 #include "hw/qdev-properties.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 /*
  * virtio-9p-pci: This extends VirtioPCIProxy.
  */
 
 #define TYPE_VIRTIO_9P_PCI "virtio-9p-pci-base"
-#define VIRTIO_9P_PCI(obj) \
-        OBJECT_CHECK(V9fsPCIState, (obj), TYPE_VIRTIO_9P_PCI)
+typedef struct V9fsPCIState V9fsPCIState;
+DECLARE_INSTANCE_CHECKER(V9fsPCIState, VIRTIO_9P_PCI,
+                         TYPE_VIRTIO_9P_PCI)
 
-typedef struct V9fsPCIState {
+struct V9fsPCIState {
     VirtIOPCIProxy parent_obj;
     V9fsVirtioState vdev;
-} V9fsPCIState;
+};
 
 static void virtio_9p_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
 {
diff --git a/hw/virtio/virtio-balloon-pci.c b/hw/virtio/virtio-balloon-pci.c
index 5adc4e5819..a2c5cc7207 100644
--- a/hw/virtio/virtio-balloon-pci.c
+++ b/hw/virtio/virtio-balloon-pci.c
@@ -19,6 +19,7 @@
 #include "hw/virtio/virtio-balloon.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 typedef struct VirtIOBalloonPCI VirtIOBalloonPCI;
 
@@ -26,8 +27,8 @@ typedef struct VirtIOBalloonPCI VirtIOBalloonPCI;
  * virtio-balloon-pci: This extends VirtioPCIProxy.
  */
 #define TYPE_VIRTIO_BALLOON_PCI "virtio-balloon-pci-base"
-#define VIRTIO_BALLOON_PCI(obj) \
-        OBJECT_CHECK(VirtIOBalloonPCI, (obj), TYPE_VIRTIO_BALLOON_PCI)
+DECLARE_INSTANCE_CHECKER(VirtIOBalloonPCI, VIRTIO_BALLOON_PCI,
+                         TYPE_VIRTIO_BALLOON_PCI)
 
 struct VirtIOBalloonPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/virtio-blk-pci.c b/hw/virtio/virtio-blk-pci.c
index 37c6e0aeb4..9d5795810c 100644
--- a/hw/virtio/virtio-blk-pci.c
+++ b/hw/virtio/virtio-blk-pci.c
@@ -22,6 +22,7 @@
 #include "virtio-pci.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 typedef struct VirtIOBlkPCI VirtIOBlkPCI;
 
@@ -29,8 +30,8 @@ typedef struct VirtIOBlkPCI VirtIOBlkPCI;
  * virtio-blk-pci: This extends VirtioPCIProxy.
  */
 #define TYPE_VIRTIO_BLK_PCI "virtio-blk-pci-base"
-#define VIRTIO_BLK_PCI(obj) \
-        OBJECT_CHECK(VirtIOBlkPCI, (obj), TYPE_VIRTIO_BLK_PCI)
+DECLARE_INSTANCE_CHECKER(VirtIOBlkPCI, VIRTIO_BLK_PCI,
+                         TYPE_VIRTIO_BLK_PCI)
 
 struct VirtIOBlkPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/virtio-crypto-pci.c b/hw/virtio/virtio-crypto-pci.c
index 198f86e08c..0783dc2f7e 100644
--- a/hw/virtio/virtio-crypto-pci.c
+++ b/hw/virtio/virtio-crypto-pci.c
@@ -21,6 +21,7 @@
 #include "hw/virtio/virtio-crypto.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 typedef struct VirtIOCryptoPCI VirtIOCryptoPCI;
 
@@ -28,8 +29,8 @@ typedef struct VirtIOCryptoPCI VirtIOCryptoPCI;
  * virtio-crypto-pci: This extends VirtioPCIProxy.
  */
 #define TYPE_VIRTIO_CRYPTO_PCI "virtio-crypto-pci"
-#define VIRTIO_CRYPTO_PCI(obj) \
-        OBJECT_CHECK(VirtIOCryptoPCI, (obj), TYPE_VIRTIO_CRYPTO_PCI)
+DECLARE_INSTANCE_CHECKER(VirtIOCryptoPCI, VIRTIO_CRYPTO_PCI,
+                         TYPE_VIRTIO_CRYPTO_PCI)
 
 struct VirtIOCryptoPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/virtio-input-host-pci.c b/hw/virtio/virtio-input-host-pci.c
index a82eb5d914..0ac360de4f 100644
--- a/hw/virtio/virtio-input-host-pci.c
+++ b/hw/virtio/virtio-input-host-pci.c
@@ -11,12 +11,13 @@
 #include "virtio-pci.h"
 #include "hw/virtio/virtio-input.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 typedef struct VirtIOInputHostPCI VirtIOInputHostPCI;
 
 #define TYPE_VIRTIO_INPUT_HOST_PCI "virtio-input-host-pci"
-#define VIRTIO_INPUT_HOST_PCI(obj) \
-        OBJECT_CHECK(VirtIOInputHostPCI, (obj), TYPE_VIRTIO_INPUT_HOST_PCI)
+DECLARE_INSTANCE_CHECKER(VirtIOInputHostPCI, VIRTIO_INPUT_HOST_PCI,
+                         TYPE_VIRTIO_INPUT_HOST_PCI)
 
 struct VirtIOInputHostPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/virtio-input-pci.c b/hw/virtio/virtio-input-pci.c
index 74651a42ea..85acd3d2eb 100644
--- a/hw/virtio/virtio-input-pci.c
+++ b/hw/virtio/virtio-input-pci.c
@@ -12,6 +12,7 @@
 #include "hw/qdev-properties.h"
 #include "hw/virtio/virtio-input.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 typedef struct VirtIOInputPCI VirtIOInputPCI;
 typedef struct VirtIOInputHIDPCI VirtIOInputHIDPCI;
@@ -19,8 +20,8 @@ typedef struct VirtIOInputHIDPCI VirtIOInputHIDPCI;
 /*
  * virtio-input-pci: This extends VirtioPCIProxy.
  */
-#define VIRTIO_INPUT_PCI(obj) \
-        OBJECT_CHECK(VirtIOInputPCI, (obj), TYPE_VIRTIO_INPUT_PCI)
+DECLARE_INSTANCE_CHECKER(VirtIOInputPCI, VIRTIO_INPUT_PCI,
+                         TYPE_VIRTIO_INPUT_PCI)
 
 struct VirtIOInputPCI {
     VirtIOPCIProxy parent_obj;
@@ -31,8 +32,8 @@ struct VirtIOInputPCI {
 #define TYPE_VIRTIO_KEYBOARD_PCI  "virtio-keyboard-pci"
 #define TYPE_VIRTIO_MOUSE_PCI     "virtio-mouse-pci"
 #define TYPE_VIRTIO_TABLET_PCI    "virtio-tablet-pci"
-#define VIRTIO_INPUT_HID_PCI(obj) \
-        OBJECT_CHECK(VirtIOInputHIDPCI, (obj), TYPE_VIRTIO_INPUT_HID_PCI)
+DECLARE_INSTANCE_CHECKER(VirtIOInputHIDPCI, VIRTIO_INPUT_HID_PCI,
+                         TYPE_VIRTIO_INPUT_HID_PCI)
 
 struct VirtIOInputHIDPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/virtio-iommu-pci.c b/hw/virtio/virtio-iommu-pci.c
index ba62d60a0a..76540e57b1 100644
--- a/hw/virtio/virtio-iommu-pci.c
+++ b/hw/virtio/virtio-iommu-pci.c
@@ -16,6 +16,7 @@
 #include "hw/qdev-properties.h"
 #include "qapi/error.h"
 #include "hw/boards.h"
+#include "qom/object.h"
 
 typedef struct VirtIOIOMMUPCI VirtIOIOMMUPCI;
 
@@ -23,8 +24,8 @@ typedef struct VirtIOIOMMUPCI VirtIOIOMMUPCI;
  * virtio-iommu-pci: This extends VirtioPCIProxy.
  *
  */
-#define VIRTIO_IOMMU_PCI(obj) \
-        OBJECT_CHECK(VirtIOIOMMUPCI, (obj), TYPE_VIRTIO_IOMMU_PCI)
+DECLARE_INSTANCE_CHECKER(VirtIOIOMMUPCI, VIRTIO_IOMMU_PCI,
+                         TYPE_VIRTIO_IOMMU_PCI)
 
 struct VirtIOIOMMUPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/virtio-mem-pci.h b/hw/virtio/virtio-mem-pci.h
index b51a28b275..e636e1a48d 100644
--- a/hw/virtio/virtio-mem-pci.h
+++ b/hw/virtio/virtio-mem-pci.h
@@ -15,6 +15,7 @@
 
 #include "hw/virtio/virtio-pci.h"
 #include "hw/virtio/virtio-mem.h"
+#include "qom/object.h"
 
 typedef struct VirtIOMEMPCI VirtIOMEMPCI;
 
@@ -22,8 +23,8 @@ typedef struct VirtIOMEMPCI VirtIOMEMPCI;
  * virtio-mem-pci: This extends VirtioPCIProxy.
  */
 #define TYPE_VIRTIO_MEM_PCI "virtio-mem-pci-base"
-#define VIRTIO_MEM_PCI(obj) \
-        OBJECT_CHECK(VirtIOMEMPCI, (obj), TYPE_VIRTIO_MEM_PCI)
+DECLARE_INSTANCE_CHECKER(VirtIOMEMPCI, VIRTIO_MEM_PCI,
+                         TYPE_VIRTIO_MEM_PCI)
 
 struct VirtIOMEMPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c
index 489b5dbad6..292d13d278 100644
--- a/hw/virtio/virtio-net-pci.c
+++ b/hw/virtio/virtio-net-pci.c
@@ -22,6 +22,7 @@
 #include "virtio-pci.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 typedef struct VirtIONetPCI VirtIONetPCI;
 
@@ -29,8 +30,8 @@ typedef struct VirtIONetPCI VirtIONetPCI;
  * virtio-net-pci: This extends VirtioPCIProxy.
  */
 #define TYPE_VIRTIO_NET_PCI "virtio-net-pci-base"
-#define VIRTIO_NET_PCI(obj) \
-        OBJECT_CHECK(VirtIONetPCI, (obj), TYPE_VIRTIO_NET_PCI)
+DECLARE_INSTANCE_CHECKER(VirtIONetPCI, VIRTIO_NET_PCI,
+                         TYPE_VIRTIO_NET_PCI)
 
 struct VirtIONetPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index 91096f0291..47b6bb4e26 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -17,6 +17,7 @@
 
 #include "hw/pci/msi.h"
 #include "hw/virtio/virtio-bus.h"
+#include "qom/object.h"
 
 typedef struct VirtIOPCIProxy VirtIOPCIProxy;
 
@@ -26,12 +27,8 @@ typedef struct VirtioBusState VirtioPCIBusState;
 typedef struct VirtioBusClass VirtioPCIBusClass;
 
 #define TYPE_VIRTIO_PCI_BUS "virtio-pci-bus"
-#define VIRTIO_PCI_BUS(obj) \
-        OBJECT_CHECK(VirtioPCIBusState, (obj), TYPE_VIRTIO_PCI_BUS)
-#define VIRTIO_PCI_BUS_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(VirtioPCIBusClass, obj, TYPE_VIRTIO_PCI_BUS)
-#define VIRTIO_PCI_BUS_CLASS(klass) \
-        OBJECT_CLASS_CHECK(VirtioPCIBusClass, klass, TYPE_VIRTIO_PCI_BUS)
+DECLARE_OBJ_CHECKERS(VirtioPCIBusState, VirtioPCIBusClass,
+                     VIRTIO_PCI_BUS, TYPE_VIRTIO_PCI_BUS)
 
 enum {
     VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT,
@@ -94,18 +91,15 @@ typedef struct {
  * virtio-pci: This is the PCIDevice which has a virtio-pci-bus.
  */
 #define TYPE_VIRTIO_PCI "virtio-pci"
-#define VIRTIO_PCI_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(VirtioPCIClass, obj, TYPE_VIRTIO_PCI)
-#define VIRTIO_PCI_CLASS(klass) \
-        OBJECT_CLASS_CHECK(VirtioPCIClass, klass, TYPE_VIRTIO_PCI)
-#define VIRTIO_PCI(obj) \
-        OBJECT_CHECK(VirtIOPCIProxy, (obj), TYPE_VIRTIO_PCI)
-
-typedef struct VirtioPCIClass {
+typedef struct VirtioPCIClass VirtioPCIClass;
+DECLARE_OBJ_CHECKERS(VirtIOPCIProxy, VirtioPCIClass,
+                     VIRTIO_PCI, TYPE_VIRTIO_PCI)
+
+struct VirtioPCIClass {
     PCIDeviceClass parent_class;
     DeviceRealize parent_dc_realize;
     void (*realize)(VirtIOPCIProxy *vpci_dev, Error **errp);
-} VirtioPCIClass;
+};
 
 typedef struct VirtIOPCIRegion {
     MemoryRegion mr;
diff --git a/hw/virtio/virtio-pmem-pci.h b/hw/virtio/virtio-pmem-pci.h
index 616abef093..63cfe727f7 100644
--- a/hw/virtio/virtio-pmem-pci.h
+++ b/hw/virtio/virtio-pmem-pci.h
@@ -16,6 +16,7 @@
 
 #include "hw/virtio/virtio-pci.h"
 #include "hw/virtio/virtio-pmem.h"
+#include "qom/object.h"
 
 typedef struct VirtIOPMEMPCI VirtIOPMEMPCI;
 
@@ -23,8 +24,8 @@ typedef struct VirtIOPMEMPCI VirtIOPMEMPCI;
  * virtio-pmem-pci: This extends VirtioPCIProxy.
  */
 #define TYPE_VIRTIO_PMEM_PCI "virtio-pmem-pci-base"
-#define VIRTIO_PMEM_PCI(obj) \
-        OBJECT_CHECK(VirtIOPMEMPCI, (obj), TYPE_VIRTIO_PMEM_PCI)
+DECLARE_INSTANCE_CHECKER(VirtIOPMEMPCI, VIRTIO_PMEM_PCI,
+                         TYPE_VIRTIO_PMEM_PCI)
 
 struct VirtIOPMEMPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/virtio-rng-pci.c b/hw/virtio/virtio-rng-pci.c
index 8afbb4c209..c1f916268b 100644
--- a/hw/virtio/virtio-rng-pci.c
+++ b/hw/virtio/virtio-rng-pci.c
@@ -15,6 +15,7 @@
 #include "hw/virtio/virtio-rng.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 typedef struct VirtIORngPCI VirtIORngPCI;
 
@@ -22,8 +23,8 @@ typedef struct VirtIORngPCI VirtIORngPCI;
  * virtio-rng-pci: This extends VirtioPCIProxy.
  */
 #define TYPE_VIRTIO_RNG_PCI "virtio-rng-pci-base"
-#define VIRTIO_RNG_PCI(obj) \
-        OBJECT_CHECK(VirtIORngPCI, (obj), TYPE_VIRTIO_RNG_PCI)
+DECLARE_INSTANCE_CHECKER(VirtIORngPCI, VIRTIO_RNG_PCI,
+                         TYPE_VIRTIO_RNG_PCI)
 
 struct VirtIORngPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/virtio-scsi-pci.c b/hw/virtio/virtio-scsi-pci.c
index fa4b3bfb50..97fab74236 100644
--- a/hw/virtio/virtio-scsi-pci.c
+++ b/hw/virtio/virtio-scsi-pci.c
@@ -19,6 +19,7 @@
 #include "hw/virtio/virtio-scsi.h"
 #include "qemu/module.h"
 #include "virtio-pci.h"
+#include "qom/object.h"
 
 typedef struct VirtIOSCSIPCI VirtIOSCSIPCI;
 
@@ -26,8 +27,8 @@ typedef struct VirtIOSCSIPCI VirtIOSCSIPCI;
  * virtio-scsi-pci: This extends VirtioPCIProxy.
  */
 #define TYPE_VIRTIO_SCSI_PCI "virtio-scsi-pci-base"
-#define VIRTIO_SCSI_PCI(obj) \
-        OBJECT_CHECK(VirtIOSCSIPCI, (obj), TYPE_VIRTIO_SCSI_PCI)
+DECLARE_INSTANCE_CHECKER(VirtIOSCSIPCI, VIRTIO_SCSI_PCI,
+                         TYPE_VIRTIO_SCSI_PCI)
 
 struct VirtIOSCSIPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/virtio-serial-pci.c b/hw/virtio/virtio-serial-pci.c
index 95d25d54da..35bcd961c9 100644
--- a/hw/virtio/virtio-serial-pci.c
+++ b/hw/virtio/virtio-serial-pci.c
@@ -21,6 +21,7 @@
 #include "hw/virtio/virtio-serial.h"
 #include "qemu/module.h"
 #include "virtio-pci.h"
+#include "qom/object.h"
 
 typedef struct VirtIOSerialPCI VirtIOSerialPCI;
 
@@ -28,8 +29,8 @@ typedef struct VirtIOSerialPCI VirtIOSerialPCI;
  * virtio-serial-pci: This extends VirtioPCIProxy.
  */
 #define TYPE_VIRTIO_SERIAL_PCI "virtio-serial-pci-base"
-#define VIRTIO_SERIAL_PCI(obj) \
-        OBJECT_CHECK(VirtIOSerialPCI, (obj), TYPE_VIRTIO_SERIAL_PCI)
+DECLARE_INSTANCE_CHECKER(VirtIOSerialPCI, VIRTIO_SERIAL_PCI,
+                         TYPE_VIRTIO_SERIAL_PCI)
 
 struct VirtIOSerialPCI {
     VirtIOPCIProxy parent_obj;
diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c
index 370cf92e85..4f64899a56 100644
--- a/hw/watchdog/wdt_i6300esb.c
+++ b/hw/watchdog/wdt_i6300esb.c
@@ -26,6 +26,7 @@
 #include "sysemu/watchdog.h"
 #include "hw/pci/pci.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 /*#define I6300ESB_DEBUG 1*/
 
@@ -104,8 +105,8 @@ struct I6300State {
 typedef struct I6300State I6300State;
 
 #define TYPE_WATCHDOG_I6300ESB_DEVICE "i6300esb"
-#define WATCHDOG_I6300ESB_DEVICE(obj) \
-    OBJECT_CHECK(I6300State, (obj), TYPE_WATCHDOG_I6300ESB_DEVICE)
+DECLARE_INSTANCE_CHECKER(I6300State, WATCHDOG_I6300ESB_DEVICE,
+                         TYPE_WATCHDOG_I6300ESB_DEVICE)
 
 /* This function is called when the watchdog has either been enabled
  * (hence it starts counting down) or has been keep-alived.
diff --git a/hw/watchdog/wdt_ib700.c b/hw/watchdog/wdt_ib700.c
index 985944a84a..177aaa503f 100644
--- a/hw/watchdog/wdt_ib700.c
+++ b/hw/watchdog/wdt_ib700.c
@@ -25,6 +25,7 @@
 #include "sysemu/watchdog.h"
 #include "hw/isa/isa.h"
 #include "migration/vmstate.h"
+#include "qom/object.h"
 
 /*#define IB700_DEBUG 1*/
 
@@ -36,15 +37,17 @@
 #endif
 
 #define TYPE_IB700 "ib700"
-#define IB700(obj) OBJECT_CHECK(IB700State, (obj), TYPE_IB700)
+typedef struct IB700state IB700State;
+DECLARE_INSTANCE_CHECKER(IB700State, IB700,
+                         TYPE_IB700)
 
-typedef struct IB700state {
+struct IB700state {
     ISADevice parent_obj;
 
     QEMUTimer *timer;
 
     PortioList port_list;
-} IB700State;
+};
 
 /* This is the timer.  We use a global here because the watchdog
  * code ensures there is only one watchdog (it is located at a fixed,
diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
index 6e9cec95f3..f46971eac6 100644
--- a/hw/xen/xen_pt.h
+++ b/hw/xen/xen_pt.h
@@ -4,6 +4,7 @@
 #include "hw/xen/xen_common.h"
 #include "hw/pci/pci.h"
 #include "xen-host-pci-device.h"
+#include "qom/object.h"
 
 bool xen_igd_gfx_pt_enabled(void);
 void xen_igd_gfx_pt_set(bool value, Error **errp);
@@ -39,8 +40,8 @@ typedef struct XenPTReg XenPTReg;
 typedef struct XenPCIPassthroughState XenPCIPassthroughState;
 
 #define TYPE_XEN_PT_DEVICE "xen-pci-passthrough"
-#define XEN_PT_DEVICE(obj) \
-    OBJECT_CHECK(XenPCIPassthroughState, (obj), TYPE_XEN_PT_DEVICE)
+DECLARE_INSTANCE_CHECKER(XenPCIPassthroughState, XEN_PT_DEVICE,
+                         TYPE_XEN_PT_DEVICE)
 
 uint32_t igd_read_opregion(XenPCIPassthroughState *s);
 void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val);
diff --git a/include/authz/base.h b/include/authz/base.h
index 0782981ad8..06b5e29f6f 100644
--- a/include/authz/base.h
+++ b/include/authz/base.h
@@ -27,18 +27,9 @@
 
 #define TYPE_QAUTHZ "authz"
 
-#define QAUTHZ_CLASS(klass) \
-     OBJECT_CLASS_CHECK(QAuthZClass, (klass), \
-                        TYPE_QAUTHZ)
-#define QAUTHZ_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(QAuthZClass, (obj), \
-                      TYPE_QAUTHZ)
-#define QAUTHZ(obj) \
-     OBJECT_CHECK(QAuthZ, (obj), \
-                  TYPE_QAUTHZ)
-
-typedef struct QAuthZ QAuthZ;
-typedef struct QAuthZClass QAuthZClass;
+OBJECT_DECLARE_TYPE(QAuthZ, QAuthZClass,
+                    qauthz, QAUTHZ)
+
 
 /**
  * QAuthZ:
diff --git a/include/authz/list.h b/include/authz/list.h
index a88cdbbcf8..5676bb375c 100644
--- a/include/authz/list.h
+++ b/include/authz/list.h
@@ -23,21 +23,13 @@
 
 #include "authz/base.h"
 #include "qapi/qapi-types-authz.h"
+#include "qom/object.h"
 
 #define TYPE_QAUTHZ_LIST "authz-list"
 
-#define QAUTHZ_LIST_CLASS(klass)                        \
-    OBJECT_CLASS_CHECK(QAuthZListClass, (klass),        \
-                       TYPE_QAUTHZ_LIST)
-#define QAUTHZ_LIST_GET_CLASS(obj)              \
-    OBJECT_GET_CLASS(QAuthZListClass, (obj),    \
-                      TYPE_QAUTHZ_LIST)
-#define QAUTHZ_LIST(obj) \
-    OBJECT_CHECK(QAuthZList, (obj), \
-                 TYPE_QAUTHZ_LIST)
+OBJECT_DECLARE_SIMPLE_TYPE(QAuthZList, qauthz_list,
+                           QAUTHZ_LIST, QAuthZClass)
 
-typedef struct QAuthZList QAuthZList;
-typedef struct QAuthZListClass QAuthZListClass;
 
 
 /**
@@ -76,9 +68,6 @@ struct QAuthZList {
 };
 
 
-struct QAuthZListClass {
-    QAuthZClass parent_class;
-};
 
 
 QAuthZList *qauthz_list_new(const char *id,
diff --git a/include/authz/listfile.h b/include/authz/listfile.h
index 24ae2e606c..b491227bbe 100644
--- a/include/authz/listfile.h
+++ b/include/authz/listfile.h
@@ -23,21 +23,13 @@
 
 #include "authz/list.h"
 #include "qemu/filemonitor.h"
+#include "qom/object.h"
 
 #define TYPE_QAUTHZ_LIST_FILE "authz-list-file"
 
-#define QAUTHZ_LIST_FILE_CLASS(klass)                        \
-    OBJECT_CLASS_CHECK(QAuthZListFileClass, (klass),        \
-                       TYPE_QAUTHZ_LIST_FILE)
-#define QAUTHZ_LIST_FILE_GET_CLASS(obj)              \
-    OBJECT_GET_CLASS(QAuthZListFileClass, (obj),    \
-                      TYPE_QAUTHZ_LIST_FILE)
-#define QAUTHZ_LIST_FILE(obj) \
-    OBJECT_CHECK(QAuthZListFile, (obj), \
-                 TYPE_QAUTHZ_LIST_FILE)
+OBJECT_DECLARE_SIMPLE_TYPE(QAuthZListFile, qauthz_list_file,
+                           QAUTHZ_LIST_FILE, QAuthZClass)
 
-typedef struct QAuthZListFile QAuthZListFile;
-typedef struct QAuthZListFileClass QAuthZListFileClass;
 
 
 /**
@@ -95,9 +87,6 @@ struct QAuthZListFile {
 };
 
 
-struct QAuthZListFileClass {
-    QAuthZClass parent_class;
-};
 
 
 QAuthZListFile *qauthz_list_file_new(const char *id,
diff --git a/include/authz/pamacct.h b/include/authz/pamacct.h
index f3a7ef1011..7804853ddf 100644
--- a/include/authz/pamacct.h
+++ b/include/authz/pamacct.h
@@ -22,22 +22,14 @@
 #define QAUTHZ_PAMACCT_H
 
 #include "authz/base.h"
+#include "qom/object.h"
 
 
 #define TYPE_QAUTHZ_PAM "authz-pam"
 
-#define QAUTHZ_PAM_CLASS(klass) \
-     OBJECT_CLASS_CHECK(QAuthZPAMClass, (klass), \
-                        TYPE_QAUTHZ_PAM)
-#define QAUTHZ_PAM_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(QAuthZPAMClass, (obj), \
-                      TYPE_QAUTHZ_PAM)
-#define QAUTHZ_PAM(obj) \
-     OBJECT_CHECK(QAuthZPAM, (obj), \
-                  TYPE_QAUTHZ_PAM)
+OBJECT_DECLARE_SIMPLE_TYPE(QAuthZPAM, qauthz_pam,
+                           QAUTHZ_PAM, QAuthZClass)
 
-typedef struct QAuthZPAM QAuthZPAM;
-typedef struct QAuthZPAMClass QAuthZPAMClass;
 
 
 /**
@@ -87,9 +79,6 @@ struct QAuthZPAM {
 };
 
 
-struct QAuthZPAMClass {
-    QAuthZClass parent_class;
-};
 
 
 QAuthZPAM *qauthz_pam_new(const char *id,
diff --git a/include/authz/simple.h b/include/authz/simple.h
index 2b7ab0cdd9..346fcb0c6c 100644
--- a/include/authz/simple.h
+++ b/include/authz/simple.h
@@ -22,21 +22,13 @@
 #define QAUTHZ_SIMPLE_H
 
 #include "authz/base.h"
+#include "qom/object.h"
 
 #define TYPE_QAUTHZ_SIMPLE "authz-simple"
 
-#define QAUTHZ_SIMPLE_CLASS(klass)                        \
-    OBJECT_CLASS_CHECK(QAuthZSimpleClass, (klass),        \
-                       TYPE_QAUTHZ_SIMPLE)
-#define QAUTHZ_SIMPLE_GET_CLASS(obj)              \
-    OBJECT_GET_CLASS(QAuthZSimpleClass, (obj),    \
-                      TYPE_QAUTHZ_SIMPLE)
-#define QAUTHZ_SIMPLE(obj) \
-    OBJECT_CHECK(QAuthZSimple, (obj), \
-                 TYPE_QAUTHZ_SIMPLE)
+OBJECT_DECLARE_SIMPLE_TYPE(QAuthZSimple, qauthz_simple,
+                           QAUTHZ_SIMPLE, QAuthZClass)
 
-typedef struct QAuthZSimple QAuthZSimple;
-typedef struct QAuthZSimpleClass QAuthZSimpleClass;
 
 
 /**
@@ -70,9 +62,6 @@ struct QAuthZSimple {
 };
 
 
-struct QAuthZSimpleClass {
-    QAuthZClass parent_class;
-};
 
 
 QAuthZSimple *qauthz_simple_new(const char *id,
diff --git a/include/block/block.h b/include/block/block.h
index 6e36154061..981ab5b314 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -532,7 +532,7 @@ BlockDriverState *bdrv_next(BdrvNextIterator *it);
 void bdrv_next_cleanup(BdrvNextIterator *it);
 
 BlockDriverState *bdrv_next_monitor_owned(BlockDriverState *bs);
-bool bdrv_is_encrypted(BlockDriverState *bs);
+bool bdrv_supports_compressed_writes(BlockDriverState *bs);
 void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
                          void *opaque, bool read_only);
 const char *bdrv_get_node_name(const BlockDriverState *bs);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 9da7a42927..38cad9d15c 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -92,9 +92,17 @@ struct BlockDriver {
     int instance_size;
 
     /* set to true if the BlockDriver is a block filter. Block filters pass
-     * certain callbacks that refer to data (see block.c) to their bs->file if
-     * the driver doesn't implement them. Drivers that do not wish to forward
-     * must implement them and return -ENOTSUP.
+     * certain callbacks that refer to data (see block.c) to their bs->file
+     * or bs->backing (whichever one exists) if the driver doesn't implement
+     * them. Drivers that do not wish to forward must implement them and return
+     * -ENOTSUP.
+     * Note that filters are not allowed to modify data.
+     *
+     * Filters generally cannot have more than a single filtered child,
+     * because the data they present must at all times be the same as
+     * that on their filtered child.  That would be impossible to
+     * achieve for multiple filtered children.
+     * (And this filtered child must then be bs->file or bs->backing.)
      */
     bool is_filter;
     /*
@@ -839,11 +847,20 @@ struct BlockDriverState {
     bool walking_aio_notifiers; /* to make removal during iteration safe */
 
     char filename[PATH_MAX];
-    char backing_file[PATH_MAX]; /* if non zero, the image is a diff of
-                                    this file image */
-    /* The backing filename indicated by the image header; if we ever
-     * open this file, then this is replaced by the resulting BDS's
-     * filename (i.e. after a bdrv_refresh_filename() run). */
+    /*
+     * If not empty, this image is a diff in relation to backing_file.
+     * Note that this is the name given in the image header and
+     * therefore may or may not be equal to .backing->bs->filename.
+     * If this field contains a relative path, it is to be resolved
+     * relatively to the overlay's location.
+     */
+    char backing_file[PATH_MAX];
+    /*
+     * The backing filename indicated by the image header.  Contrary
+     * to backing_file, if we ever open this file, auto_backing_file
+     * is replaced by the resulting BDS's filename (i.e. after a
+     * bdrv_refresh_filename() run).
+     */
     char auto_backing_file[PATH_MAX];
     char backing_format[16]; /* if non-zero and backing_file exists */
 
@@ -995,11 +1012,6 @@ typedef enum BlockMirrorBackingMode {
     MIRROR_LEAVE_BACKING_CHAIN,
 } BlockMirrorBackingMode;
 
-static inline BlockDriverState *backing_bs(BlockDriverState *bs)
-{
-    return bs->backing ? bs->backing->bs : NULL;
-}
-
 
 /* Essential block drivers which must always be statically linked into qemu, and
  * which therefore can be accessed without using bdrv_find_format() */
@@ -1050,6 +1062,8 @@ BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
 void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
                                       QDict *options);
 
+bool bdrv_backing_overridden(BlockDriverState *bs);
+
 
 /**
  * bdrv_add_before_write_notifier:
@@ -1300,28 +1314,6 @@ void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
                         uint64_t perm, uint64_t shared,
                         uint64_t *nperm, uint64_t *nshared);
 
-/*
- * Default implementation for drivers to pass bdrv_co_block_status() to
- * their file.
- */
-int coroutine_fn bdrv_co_block_status_from_file(BlockDriverState *bs,
-                                                bool want_zero,
-                                                int64_t offset,
-                                                int64_t bytes,
-                                                int64_t *pnum,
-                                                int64_t *map,
-                                                BlockDriverState **file);
-/*
- * Default implementation for drivers to pass bdrv_co_block_status() to
- * their backing file.
- */
-int coroutine_fn bdrv_co_block_status_from_backing(BlockDriverState *bs,
-                                                   bool want_zero,
-                                                   int64_t offset,
-                                                   int64_t bytes,
-                                                   int64_t *pnum,
-                                                   int64_t *map,
-                                                   BlockDriverState **file);
 const char *bdrv_get_parent_name(const BlockDriverState *bs);
 void blk_dev_change_media_cb(BlockBackend *blk, bool load, Error **errp);
 bool blk_dev_has_removable_media(BlockBackend *blk);
@@ -1382,4 +1374,37 @@ BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
                                            BlockDriverState **bitmap_bs,
                                            Error **errp);
 
+BdrvChild *bdrv_cow_child(BlockDriverState *bs);
+BdrvChild *bdrv_filter_child(BlockDriverState *bs);
+BdrvChild *bdrv_filter_or_cow_child(BlockDriverState *bs);
+BdrvChild *bdrv_primary_child(BlockDriverState *bs);
+BlockDriverState *bdrv_skip_implicit_filters(BlockDriverState *bs);
+BlockDriverState *bdrv_skip_filters(BlockDriverState *bs);
+BlockDriverState *bdrv_backing_chain_next(BlockDriverState *bs);
+
+static inline BlockDriverState *child_bs(BdrvChild *child)
+{
+    return child ? child->bs : NULL;
+}
+
+static inline BlockDriverState *bdrv_cow_bs(BlockDriverState *bs)
+{
+    return child_bs(bdrv_cow_child(bs));
+}
+
+static inline BlockDriverState *bdrv_filter_bs(BlockDriverState *bs)
+{
+    return child_bs(bdrv_filter_child(bs));
+}
+
+static inline BlockDriverState *bdrv_filter_or_cow_bs(BlockDriverState *bs)
+{
+    return child_bs(bdrv_filter_or_cow_child(bs));
+}
+
+static inline BlockDriverState *bdrv_primary_bs(BlockDriverState *bs)
+{
+    return child_bs(bdrv_primary_child(bs));
+}
+
 #endif /* BLOCK_INT_H */
diff --git a/include/block/throttle-groups.h b/include/block/throttle-groups.h
index 5e77db700f..20b308f619 100644
--- a/include/block/throttle-groups.h
+++ b/include/block/throttle-groups.h
@@ -27,6 +27,7 @@
 
 #include "qemu/throttle.h"
 #include "block/block_int.h"
+#include "qom/object.h"
 
 /* The ThrottleGroupMember structure indicates membership in a ThrottleGroup
  * and holds related data.
@@ -60,7 +61,8 @@ typedef struct ThrottleGroupMember {
 
 #define TYPE_THROTTLE_GROUP "throttle-group"
 typedef struct ThrottleGroup ThrottleGroup;
-#define THROTTLE_GROUP(obj) OBJECT_CHECK(ThrottleGroup, (obj), TYPE_THROTTLE_GROUP)
+DECLARE_INSTANCE_CHECKER(ThrottleGroup, THROTTLE_GROUP,
+                         TYPE_THROTTLE_GROUP)
 
 const char *throttle_group_get_name(ThrottleGroupMember *tgm);
 
diff --git a/include/chardev/char-fd.h b/include/chardev/char-fd.h
index e7c2b176f9..9de0e440de 100644
--- a/include/chardev/char-fd.h
+++ b/include/chardev/char-fd.h
@@ -26,17 +26,20 @@
 
 #include "io/channel.h"
 #include "chardev/char.h"
+#include "qom/object.h"
 
-typedef struct FDChardev {
+struct FDChardev {
     Chardev parent;
 
     QIOChannel *ioc_in, *ioc_out;
     int max_size;
-} FDChardev;
+};
+typedef struct FDChardev FDChardev;
 
 #define TYPE_CHARDEV_FD "chardev-fd"
 
-#define FD_CHARDEV(obj) OBJECT_CHECK(FDChardev, (obj), TYPE_CHARDEV_FD)
+DECLARE_INSTANCE_CHECKER(FDChardev, FD_CHARDEV,
+                         TYPE_CHARDEV_FD)
 
 void qemu_chr_open_fd(Chardev *chr, int fd_in, int fd_out);
 int qmp_chardev_open_file_source(char *src, int flags, Error **errp);
diff --git a/include/chardev/char-win.h b/include/chardev/char-win.h
index fa59e9e423..485521469c 100644
--- a/include/chardev/char-win.h
+++ b/include/chardev/char-win.h
@@ -25,8 +25,9 @@
 #define CHAR_WIN_H
 
 #include "chardev/char.h"
+#include "qom/object.h"
 
-typedef struct {
+struct WinChardev {
     Chardev parent;
 
     bool keep_open; /* console do not close file */
@@ -36,13 +37,15 @@ typedef struct {
 
     /* Protected by the Chardev chr_write_lock.  */
     OVERLAPPED osend;
-} WinChardev;
+};
+typedef struct WinChardev WinChardev;
 
 #define NSENDBUF 2048
 #define NRECVBUF 2048
 
 #define TYPE_CHARDEV_WIN "chardev-win"
-#define WIN_CHARDEV(obj) OBJECT_CHECK(WinChardev, (obj), TYPE_CHARDEV_WIN)
+DECLARE_INSTANCE_CHECKER(WinChardev, WIN_CHARDEV,
+                         TYPE_CHARDEV_WIN)
 
 void win_chr_set_file(Chardev *chr, HANDLE file, bool keep_open);
 int win_chr_serial_init(Chardev *chr, const char *filename, Error **errp);
diff --git a/include/chardev/char.h b/include/chardev/char.h
index 00589a6025..5874de57ea 100644
--- a/include/chardev/char.h
+++ b/include/chardev/char.h
@@ -226,11 +226,9 @@ int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, bool write_all);
 int qemu_chr_wait_connected(Chardev *chr, Error **errp);
 
 #define TYPE_CHARDEV "chardev"
-#define CHARDEV(obj) OBJECT_CHECK(Chardev, (obj), TYPE_CHARDEV)
-#define CHARDEV_CLASS(klass) \
-    OBJECT_CLASS_CHECK(ChardevClass, (klass), TYPE_CHARDEV)
-#define CHARDEV_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(ChardevClass, (obj), TYPE_CHARDEV)
+typedef struct ChardevClass ChardevClass;
+DECLARE_OBJ_CHECKERS(Chardev, ChardevClass,
+                     CHARDEV, TYPE_CHARDEV)
 
 #define TYPE_CHARDEV_NULL "chardev-null"
 #define TYPE_CHARDEV_MUX "chardev-mux"
@@ -251,7 +249,7 @@ int qemu_chr_wait_connected(Chardev *chr, Error **errp);
 #define CHARDEV_IS_PTY(chr) \
     object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_PTY)
 
-typedef struct ChardevClass {
+struct ChardevClass {
     ObjectClass parent_class;
 
     bool internal; /* TODO: eventually use TYPE_USER_CREATABLE */
@@ -276,7 +274,7 @@ typedef struct ChardevClass {
     void (*chr_be_event)(Chardev *s, QEMUChrEvent event);
     /* Return 0 if succeeded, 1 if failed */
     int (*chr_machine_done)(Chardev *chr);
-} ChardevClass;
+};
 
 Chardev *qemu_chardev_new(const char *id, const char *typename,
                           ChardevBackend *backend, GMainContext *context,
diff --git a/include/chardev/spice.h b/include/chardev/spice.h
index 1f7339b649..99f26aedde 100644
--- a/include/chardev/spice.h
+++ b/include/chardev/spice.h
@@ -3,8 +3,9 @@
 
 #include <spice.h>
 #include "chardev/char-fe.h"
+#include "qom/object.h"
 
-typedef struct SpiceChardev {
+struct SpiceChardev {
     Chardev               parent;
 
     SpiceCharDeviceInstance sin;
@@ -13,13 +14,15 @@ typedef struct SpiceChardev {
     const uint8_t         *datapos;
     int                   datalen;
     QLIST_ENTRY(SpiceChardev) next;
-} SpiceChardev;
+};
+typedef struct SpiceChardev SpiceChardev;
 
 #define TYPE_CHARDEV_SPICE "chardev-spice"
 #define TYPE_CHARDEV_SPICEVMC "chardev-spicevmc"
 #define TYPE_CHARDEV_SPICEPORT "chardev-spiceport"
 
-#define SPICE_CHARDEV(obj) OBJECT_CHECK(SpiceChardev, (obj), TYPE_CHARDEV_SPICE)
+DECLARE_INSTANCE_CHECKER(SpiceChardev, SPICE_CHARDEV,
+                         TYPE_CHARDEV_SPICE)
 
 void qemu_chr_open_spice_port(Chardev *chr, ChardevBackend *backend,
                               bool *be_opened, Error **errp);
diff --git a/include/crypto/aes.h b/include/crypto/aes.h
index 12fb321b89..ba297d6a73 100644
--- a/include/crypto/aes.h
+++ b/include/crypto/aes.h
@@ -16,7 +16,6 @@ typedef struct aes_key_st AES_KEY;
 #define AES_set_decrypt_key QEMU_AES_set_decrypt_key
 #define AES_encrypt QEMU_AES_encrypt
 #define AES_decrypt QEMU_AES_decrypt
-#define AES_cbc_encrypt QEMU_AES_cbc_encrypt
 
 int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
 	AES_KEY *key);
@@ -27,9 +26,6 @@ void AES_encrypt(const unsigned char *in, unsigned char *out,
 	const AES_KEY *key);
 void AES_decrypt(const unsigned char *in, unsigned char *out,
 	const AES_KEY *key);
-void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
-		     const unsigned long length, const AES_KEY *key,
-		     unsigned char *ivec, const int enc);
 
 extern const uint8_t AES_sbox[256];
 extern const uint8_t AES_isbox[256];
diff --git a/include/crypto/cipher.h b/include/crypto/cipher.h
index 5928e5ecc7..083e12a7d9 100644
--- a/include/crypto/cipher.h
+++ b/include/crypto/cipher.h
@@ -24,6 +24,7 @@
 #include "qapi/qapi-types-crypto.h"
 
 typedef struct QCryptoCipher QCryptoCipher;
+typedef struct QCryptoCipherDriver QCryptoCipherDriver;
 
 /* See also "QCryptoCipherAlgorithm" and "QCryptoCipherMode"
  * enums defined in qapi/crypto.json */
@@ -79,8 +80,7 @@ typedef struct QCryptoCipher QCryptoCipher;
 struct QCryptoCipher {
     QCryptoCipherAlgorithm alg;
     QCryptoCipherMode mode;
-    void *opaque;
-    void *driver;
+    const QCryptoCipherDriver *driver;
 };
 
 /**
diff --git a/include/crypto/secret.h b/include/crypto/secret.h
index 2deb461d2f..5d20ae6d2f 100644
--- a/include/crypto/secret.h
+++ b/include/crypto/secret.h
@@ -26,10 +26,10 @@
 #include "crypto/secret_common.h"
 
 #define TYPE_QCRYPTO_SECRET "secret"
-#define QCRYPTO_SECRET(obj)                  \
-    OBJECT_CHECK(QCryptoSecret, (obj), TYPE_QCRYPTO_SECRET)
-
 typedef struct QCryptoSecret QCryptoSecret;
+DECLARE_INSTANCE_CHECKER(QCryptoSecret, QCRYPTO_SECRET,
+                         TYPE_QCRYPTO_SECRET)
+
 typedef struct QCryptoSecretClass QCryptoSecretClass;
 
 /**
diff --git a/include/crypto/secret_common.h b/include/crypto/secret_common.h
index 980c02ab71..daf00c3b2a 100644
--- a/include/crypto/secret_common.h
+++ b/include/crypto/secret_common.h
@@ -25,17 +25,9 @@
 #include "qom/object.h"
 
 #define TYPE_QCRYPTO_SECRET_COMMON "secret_common"
-#define QCRYPTO_SECRET_COMMON(obj) \
-    OBJECT_CHECK(QCryptoSecretCommon, (obj), TYPE_QCRYPTO_SECRET_COMMON)
-#define QCRYPTO_SECRET_COMMON_CLASS(class) \
-    OBJECT_CLASS_CHECK(QCryptoSecretCommonClass, \
-                       (class), TYPE_QCRYPTO_SECRET_COMMON)
-#define QCRYPTO_SECRET_COMMON_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(QCryptoSecretCommonClass, \
-                     (obj), TYPE_QCRYPTO_SECRET_COMMON)
+OBJECT_DECLARE_TYPE(QCryptoSecretCommon, QCryptoSecretCommonClass,
+                    qcrypto_secret_common, QCRYPTO_SECRET_COMMON)
 
-typedef struct QCryptoSecretCommon QCryptoSecretCommon;
-typedef struct QCryptoSecretCommonClass QCryptoSecretCommonClass;
 
 struct QCryptoSecretCommon {
     Object parent_obj;
diff --git a/include/crypto/secret_keyring.h b/include/crypto/secret_keyring.h
index 9f371ad251..73d2a8f501 100644
--- a/include/crypto/secret_keyring.h
+++ b/include/crypto/secret_keyring.h
@@ -26,27 +26,15 @@
 #include "crypto/secret_common.h"
 
 #define TYPE_QCRYPTO_SECRET_KEYRING "secret_keyring"
-#define QCRYPTO_SECRET_KEYRING(obj) \
-    OBJECT_CHECK(QCryptoSecretKeyring, (obj), \
-                 TYPE_QCRYPTO_SECRET_KEYRING)
-#define QCRYPTO_SECRET_KEYRING_CLASS(class) \
-    OBJECT_CLASS_CHECK(QCryptoSecretKeyringClass, \
-                       (class), TYPE_QCRYPTO_SECRET_KEYRING)
-#define QCRYPTO_SECRET_KEYRING_GET_CLASS(class) \
-    OBJECT_GET_CLASS(QCryptoSecretKeyringClass, \
-                     (class), TYPE_QCRYPTO_SECRET_KEYRING)
-
-typedef struct QCryptoSecretKeyring QCryptoSecretKeyring;
-typedef struct QCryptoSecretKeyringClass QCryptoSecretKeyringClass;
-
-typedef struct QCryptoSecretKeyring {
+OBJECT_DECLARE_SIMPLE_TYPE(QCryptoSecretKeyring, qcrypto_secret_keyring,
+                           QCRYPTO_SECRET_KEYRING, QCryptoSecretCommonClass)
+
+
+struct QCryptoSecretKeyring {
     QCryptoSecretCommon parent;
     int32_t serial;
-} QCryptoSecretKeyring;
+};
 
 
-typedef struct QCryptoSecretKeyringClass {
-    QCryptoSecretCommonClass parent;
-} QCryptoSecretKeyringClass;
 
 #endif /* QCRYPTO_SECRET_KEYRING_H */
diff --git a/include/crypto/tls-cipher-suites.h b/include/crypto/tls-cipher-suites.h
index 28b3a73ce1..bb9ee53e03 100644
--- a/include/crypto/tls-cipher-suites.h
+++ b/include/crypto/tls-cipher-suites.h
@@ -15,14 +15,15 @@
 #include "crypto/tlscreds.h"
 
 #define TYPE_QCRYPTO_TLS_CIPHER_SUITES "tls-cipher-suites"
-#define QCRYPTO_TLS_CIPHER_SUITES(obj) \
-    OBJECT_CHECK(QCryptoTLSCipherSuites, (obj), TYPE_QCRYPTO_TLS_CIPHER_SUITES)
+typedef struct QCryptoTLSCipherSuites QCryptoTLSCipherSuites;
+DECLARE_INSTANCE_CHECKER(QCryptoTLSCipherSuites, QCRYPTO_TLS_CIPHER_SUITES,
+                         TYPE_QCRYPTO_TLS_CIPHER_SUITES)
 
-typedef struct QCryptoTLSCipherSuites {
+struct QCryptoTLSCipherSuites {
     /* <private> */
     QCryptoTLSCreds parent_obj;
     /* <public> */
-} QCryptoTLSCipherSuites;
+};
 
 /**
   * qcrypto_tls_cipher_suites_get_data:
diff --git a/include/crypto/tlscreds.h b/include/crypto/tlscreds.h
index fd7a284aa2..079e376047 100644
--- a/include/crypto/tlscreds.h
+++ b/include/crypto/tlscreds.h
@@ -29,10 +29,10 @@
 #endif
 
 #define TYPE_QCRYPTO_TLS_CREDS "tls-creds"
-#define QCRYPTO_TLS_CREDS(obj)                  \
-    OBJECT_CHECK(QCryptoTLSCreds, (obj), TYPE_QCRYPTO_TLS_CREDS)
-
 typedef struct QCryptoTLSCreds QCryptoTLSCreds;
+DECLARE_INSTANCE_CHECKER(QCryptoTLSCreds, QCRYPTO_TLS_CREDS,
+                         TYPE_QCRYPTO_TLS_CREDS)
+
 typedef struct QCryptoTLSCredsClass QCryptoTLSCredsClass;
 
 #define QCRYPTO_TLS_CREDS_DH_PARAMS "dh-params.pem"
diff --git a/include/crypto/tlscredsanon.h b/include/crypto/tlscredsanon.h
index 9e9a5ce1a8..3f464a3809 100644
--- a/include/crypto/tlscredsanon.h
+++ b/include/crypto/tlscredsanon.h
@@ -22,13 +22,14 @@
 #define QCRYPTO_TLSCREDSANON_H
 
 #include "crypto/tlscreds.h"
+#include "qom/object.h"
 
 #define TYPE_QCRYPTO_TLS_CREDS_ANON "tls-creds-anon"
-#define QCRYPTO_TLS_CREDS_ANON(obj)                  \
-    OBJECT_CHECK(QCryptoTLSCredsAnon, (obj), TYPE_QCRYPTO_TLS_CREDS_ANON)
+typedef struct QCryptoTLSCredsAnon QCryptoTLSCredsAnon;
+DECLARE_INSTANCE_CHECKER(QCryptoTLSCredsAnon, QCRYPTO_TLS_CREDS_ANON,
+                         TYPE_QCRYPTO_TLS_CREDS_ANON)
 
 
-typedef struct QCryptoTLSCredsAnon QCryptoTLSCredsAnon;
 typedef struct QCryptoTLSCredsAnonClass QCryptoTLSCredsAnonClass;
 
 /**
diff --git a/include/crypto/tlscredspsk.h b/include/crypto/tlscredspsk.h
index 907035a29b..d7e6bdb5ed 100644
--- a/include/crypto/tlscredspsk.h
+++ b/include/crypto/tlscredspsk.h
@@ -22,12 +22,13 @@
 #define QCRYPTO_TLSCREDSPSK_H
 
 #include "crypto/tlscreds.h"
+#include "qom/object.h"
 
 #define TYPE_QCRYPTO_TLS_CREDS_PSK "tls-creds-psk"
-#define QCRYPTO_TLS_CREDS_PSK(obj)                  \
-    OBJECT_CHECK(QCryptoTLSCredsPSK, (obj), TYPE_QCRYPTO_TLS_CREDS_PSK)
-
 typedef struct QCryptoTLSCredsPSK QCryptoTLSCredsPSK;
+DECLARE_INSTANCE_CHECKER(QCryptoTLSCredsPSK, QCRYPTO_TLS_CREDS_PSK,
+                         TYPE_QCRYPTO_TLS_CREDS_PSK)
+
 typedef struct QCryptoTLSCredsPSKClass QCryptoTLSCredsPSKClass;
 
 #define QCRYPTO_TLS_CREDS_PSKFILE "keys.psk"
diff --git a/include/crypto/tlscredsx509.h b/include/crypto/tlscredsx509.h
index e1542e5c8c..c6d89b7881 100644
--- a/include/crypto/tlscredsx509.h
+++ b/include/crypto/tlscredsx509.h
@@ -22,12 +22,13 @@
 #define QCRYPTO_TLSCREDSX509_H
 
 #include "crypto/tlscreds.h"
+#include "qom/object.h"
 
 #define TYPE_QCRYPTO_TLS_CREDS_X509 "tls-creds-x509"
-#define QCRYPTO_TLS_CREDS_X509(obj)                  \
-    OBJECT_CHECK(QCryptoTLSCredsX509, (obj), TYPE_QCRYPTO_TLS_CREDS_X509)
-
 typedef struct QCryptoTLSCredsX509 QCryptoTLSCredsX509;
+DECLARE_INSTANCE_CHECKER(QCryptoTLSCredsX509, QCRYPTO_TLS_CREDS_X509,
+                         TYPE_QCRYPTO_TLS_CREDS_X509)
+
 typedef struct QCryptoTLSCredsX509Class QCryptoTLSCredsX509Class;
 
 #define QCRYPTO_TLS_CREDS_X509_CA_CERT "ca-cert.pem"
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 0cfe987ab4..f1bb2a7df5 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -34,18 +34,13 @@
 #define MAX_PHYS_ADDR            (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1)
 
 #define TYPE_MEMORY_REGION "qemu:memory-region"
-#define MEMORY_REGION(obj) \
-        OBJECT_CHECK(MemoryRegion, (obj), TYPE_MEMORY_REGION)
+DECLARE_INSTANCE_CHECKER(MemoryRegion, MEMORY_REGION,
+                         TYPE_MEMORY_REGION)
 
 #define TYPE_IOMMU_MEMORY_REGION "qemu:iommu-memory-region"
-#define IOMMU_MEMORY_REGION(obj) \
-        OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_IOMMU_MEMORY_REGION)
-#define IOMMU_MEMORY_REGION_CLASS(klass) \
-        OBJECT_CLASS_CHECK(IOMMUMemoryRegionClass, (klass), \
-                         TYPE_IOMMU_MEMORY_REGION)
-#define IOMMU_MEMORY_REGION_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(IOMMUMemoryRegionClass, (obj), \
-                         TYPE_IOMMU_MEMORY_REGION)
+typedef struct IOMMUMemoryRegionClass IOMMUMemoryRegionClass;
+DECLARE_OBJ_CHECKERS(IOMMUMemoryRegion, IOMMUMemoryRegionClass,
+                     IOMMU_MEMORY_REGION, TYPE_IOMMU_MEMORY_REGION)
 
 extern bool global_dirty_log;
 
@@ -216,7 +211,7 @@ enum IOMMUMemoryRegionAttr {
     IOMMU_ATTR_SPAPR_TCE_FD
 };
 
-/**
+/*
  * IOMMUMemoryRegionClass:
  *
  * All IOMMU implementations need to subclass TYPE_IOMMU_MEMORY_REGION
@@ -242,7 +237,7 @@ enum IOMMUMemoryRegionAttr {
  * only a single IOMMU index. A more complex IOMMU might have one index
  * for secure transactions and one for non-secure transactions.
  */
-typedef struct IOMMUMemoryRegionClass {
+struct IOMMUMemoryRegionClass {
     /* private */
     MemoryRegionClass parent_class;
 
@@ -355,7 +350,7 @@ typedef struct IOMMUMemoryRegionClass {
      * @iommu: the IOMMUMemoryRegion
      */
     int (*num_indexes)(IOMMUMemoryRegion *iommu);
-} IOMMUMemoryRegionClass;
+};
 
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
 typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
index a2a12af9b9..9adf1e4706 100644
--- a/include/hw/acpi/acpi_dev_interface.h
+++ b/include/hw/acpi/acpi_dev_interface.h
@@ -18,12 +18,9 @@ typedef enum {
 
 #define TYPE_ACPI_DEVICE_IF "acpi-device-interface"
 
-#define ACPI_DEVICE_IF_CLASS(klass) \
-     OBJECT_CLASS_CHECK(AcpiDeviceIfClass, (klass), \
-                        TYPE_ACPI_DEVICE_IF)
-#define ACPI_DEVICE_IF_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(AcpiDeviceIfClass, (obj), \
-                      TYPE_ACPI_DEVICE_IF)
+typedef struct AcpiDeviceIfClass AcpiDeviceIfClass;
+DECLARE_CLASS_CHECKERS(AcpiDeviceIfClass, ACPI_DEVICE_IF,
+                       TYPE_ACPI_DEVICE_IF)
 #define ACPI_DEVICE_IF(obj) \
      INTERFACE_CHECK(AcpiDeviceIf, (obj), \
                      TYPE_ACPI_DEVICE_IF)
@@ -48,7 +45,7 @@ void acpi_send_event(DeviceState *dev, AcpiEventStatusBits event);
  * knowledge about internals of actual device that implements
  * ACPI interface.
  */
-typedef struct AcpiDeviceIfClass {
+struct AcpiDeviceIfClass {
     /* <private> */
     InterfaceClass parent_class;
 
@@ -57,5 +54,5 @@ typedef struct AcpiDeviceIfClass {
     void (*send_event)(AcpiDeviceIf *adev, AcpiEventStatusBits ev);
     void (*madt_cpu)(AcpiDeviceIf *adev, int uid,
                      const CPUArchIdList *apic_ids, GArray *entry);
-} AcpiDeviceIfClass;
+};
 #endif
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
index 90a9180db5..1be05a3c0f 100644
--- a/include/hw/acpi/generic_event_device.h
+++ b/include/hw/acpi/generic_event_device.h
@@ -62,12 +62,14 @@
 #include "hw/sysbus.h"
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/ghes.h"
+#include "qom/object.h"
 
 #define ACPI_POWER_BUTTON_DEVICE "PWRB"
 
 #define TYPE_ACPI_GED "acpi-ged"
-#define ACPI_GED(obj) \
-    OBJECT_CHECK(AcpiGedState, (obj), TYPE_ACPI_GED)
+typedef struct AcpiGedState AcpiGedState;
+DECLARE_INSTANCE_CHECKER(AcpiGedState, ACPI_GED,
+                         TYPE_ACPI_GED)
 
 #define ACPI_GED_EVT_SEL_OFFSET    0x0
 #define ACPI_GED_EVT_SEL_LEN       0x4
@@ -90,7 +92,7 @@ typedef struct GEDState {
     uint32_t     sel;
 } GEDState;
 
-typedef struct AcpiGedState {
+struct AcpiGedState {
     SysBusDevice parent_obj;
     MemHotplugState memhp_state;
     MemoryRegion container_memhp;
@@ -98,7 +100,7 @@ typedef struct AcpiGedState {
     uint32_t ged_event_bitmap;
     qemu_irq irq;
     AcpiGhesState ghes_state;
-} AcpiGedState;
+};
 
 void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev,
                    uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base);
diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h
index c49d913f3e..aff574df5f 100644
--- a/include/hw/acpi/vmgenid.h
+++ b/include/hw/acpi/vmgenid.h
@@ -4,8 +4,9 @@
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/qdev-core.h"
 #include "qemu/uuid.h"
+#include "qom/object.h"
 
-#define VMGENID_DEVICE           "vmgenid"
+#define TYPE_VMGENID           "vmgenid"
 #define VMGENID_GUID             "guid"
 #define VMGENID_GUID_FW_CFG_FILE      "etc/vmgenid_guid"
 #define VMGENID_ADDR_FW_CFG_FILE      "etc/vmgenid_addr"
@@ -15,18 +16,20 @@
                                        * OVMF SDT Header Probe Supressor
                                        */
 
-#define VMGENID(obj) OBJECT_CHECK(VmGenIdState, (obj), VMGENID_DEVICE)
+typedef struct VmGenIdState VmGenIdState;
+DECLARE_INSTANCE_CHECKER(VmGenIdState, VMGENID,
+                         TYPE_VMGENID)
 
-typedef struct VmGenIdState {
+struct VmGenIdState {
     DeviceClass parent_obj;
     QemuUUID guid;                /* The 128-bit GUID seen by the guest */
     uint8_t vmgenid_addr_le[8];   /* Address of the GUID (little-endian) */
-} VmGenIdState;
+};
 
 /* returns NULL unless there is exactly one device */
 static inline Object *find_vmgenid_dev(void)
 {
-    return object_resolve_path_type("", VMGENID_DEVICE, NULL);
+    return object_resolve_path_type("", TYPE_VMGENID, NULL);
 }
 
 void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
diff --git a/include/hw/adc/stm32f2xx_adc.h b/include/hw/adc/stm32f2xx_adc.h
index 663b79f4f3..6a4f8e955b 100644
--- a/include/hw/adc/stm32f2xx_adc.h
+++ b/include/hw/adc/stm32f2xx_adc.h
@@ -26,6 +26,7 @@
 #define HW_STM32F2XX_ADC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define ADC_SR    0x00
 #define ADC_CR1   0x04
@@ -58,10 +59,11 @@
 #define ADC_COMMON_ADDRESS 0x100
 
 #define TYPE_STM32F2XX_ADC "stm32f2xx-adc"
-#define STM32F2XX_ADC(obj) \
-    OBJECT_CHECK(STM32F2XXADCState, (obj), TYPE_STM32F2XX_ADC)
+typedef struct STM32F2XXADCState STM32F2XXADCState;
+DECLARE_INSTANCE_CHECKER(STM32F2XXADCState, STM32F2XX_ADC,
+                         TYPE_STM32F2XX_ADC)
 
-typedef struct {
+struct STM32F2XXADCState {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -84,6 +86,6 @@ typedef struct {
     uint32_t adc_dr;
 
     qemu_irq irq;
-} STM32F2XXADCState;
+};
 
 #endif /* HW_STM32F2XX_ADC_H */
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
index 77c82a9982..d13b6cf50f 100644
--- a/include/hw/arm/allwinner-a10.h
+++ b/include/hw/arm/allwinner-a10.h
@@ -14,6 +14,7 @@
 #include "hw/rtc/allwinner-rtc.h"
 
 #include "target/arm/cpu.h"
+#include "qom/object.h"
 
 
 #define AW_A10_SDRAM_BASE       0x40000000
@@ -21,9 +22,11 @@
 #define AW_A10_NUM_USB          2
 
 #define TYPE_AW_A10 "allwinner-a10"
-#define AW_A10(obj) OBJECT_CHECK(AwA10State, (obj), TYPE_AW_A10)
+typedef struct AwA10State AwA10State;
+DECLARE_INSTANCE_CHECKER(AwA10State, AW_A10,
+                         TYPE_AW_A10)
 
-typedef struct AwA10State {
+struct AwA10State {
     /*< private >*/
     DeviceState parent_obj;
     /*< public >*/
@@ -38,6 +41,6 @@ typedef struct AwA10State {
     MemoryRegion sram_a;
     EHCISysBusState ehci[AW_A10_NUM_USB];
     OHCISysBusState ohci[AW_A10_NUM_USB];
-} AwA10State;
+};
 
 #endif
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
index 626139dcb3..a93e019521 100644
--- a/include/hw/arm/allwinner-h3.h
+++ b/include/hw/arm/allwinner-h3.h
@@ -106,7 +106,9 @@ enum {
 #define TYPE_AW_H3 "allwinner-h3"
 
 /** Convert input object to Allwinner H3 state object */
-#define AW_H3(obj) OBJECT_CHECK(AwH3State, (obj), TYPE_AW_H3)
+typedef struct AwH3State AwH3State;
+DECLARE_INSTANCE_CHECKER(AwH3State, AW_H3,
+                         TYPE_AW_H3)
 
 /** @} */
 
@@ -116,7 +118,7 @@ enum {
  * This struct contains the state of all the devices
  * which are currently emulated by the H3 SoC code.
  */
-typedef struct AwH3State {
+struct AwH3State {
     /*< private >*/
     DeviceState parent_obj;
     /*< public >*/
@@ -136,7 +138,7 @@ typedef struct AwH3State {
     MemoryRegion sram_a1;
     MemoryRegion sram_a2;
     MemoryRegion sram_c;
-} AwH3State;
+};
 
 /**
  * Emulate Boot ROM firmware setup functionality.
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 347b977ae5..b844ef6bc0 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -105,9 +105,11 @@
 #include "hw/or-irq.h"
 #include "hw/core/split-irq.h"
 #include "hw/cpu/cluster.h"
+#include "qom/object.h"
 
 #define TYPE_ARM_SSE "arm-sse"
-#define ARM_SSE(obj) OBJECT_CHECK(ARMSSE, (obj), TYPE_ARM_SSE)
+OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
+                    arm_sse, ARM_SSE)
 
 /*
  * These type names are for specific IoTKit subsystems; other than
@@ -140,7 +142,7 @@
 #define RAM3_PPU 6
 #define NUM_PPUS 7
 
-typedef struct ARMSSE {
+struct ARMSSE {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -215,18 +217,14 @@ typedef struct ARMSSE {
     uint32_t init_svtor;
     bool cpu_fpu[SSE_MAX_CPUS];
     bool cpu_dsp[SSE_MAX_CPUS];
-} ARMSSE;
+};
 
 typedef struct ARMSSEInfo ARMSSEInfo;
 
-typedef struct ARMSSEClass {
+struct ARMSSEClass {
     SysBusDeviceClass parent_class;
     const ARMSSEInfo *info;
-} ARMSSEClass;
+};
 
-#define ARM_SSE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(ARMSSEClass, (klass), TYPE_ARM_SSE)
-#define ARM_SSE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(ARMSSEClass, (obj), TYPE_ARM_SSE)
 
 #endif
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
index a30e3c6471..dcb891d9cc 100644
--- a/include/hw/arm/armv7m.h
+++ b/include/hw/arm/armv7m.h
@@ -13,11 +13,14 @@
 #include "hw/sysbus.h"
 #include "hw/intc/armv7m_nvic.h"
 #include "target/arm/idau.h"
+#include "qom/object.h"
 
 #define TYPE_BITBAND "ARM,bitband-memory"
-#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
+typedef struct BitBandState BitBandState;
+DECLARE_INSTANCE_CHECKER(BitBandState, BITBAND,
+                         TYPE_BITBAND)
 
-typedef struct {
+struct BitBandState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -26,10 +29,12 @@ typedef struct {
     MemoryRegion iomem;
     uint32_t base;
     MemoryRegion *source_memory;
-} BitBandState;
+};
 
 #define TYPE_ARMV7M "armv7m"
-#define ARMV7M(obj) OBJECT_CHECK(ARMv7MState, (obj), TYPE_ARMV7M)
+typedef struct ARMv7MState ARMv7MState;
+DECLARE_INSTANCE_CHECKER(ARMv7MState, ARMV7M,
+                         TYPE_ARMV7M)
 
 #define ARMV7M_NUM_BITBANDS 2
 
@@ -49,7 +54,7 @@ typedef struct {
  * + Property "dsp": enable DSP (forwarded to CPU object)
  * + Property "enable-bitband": expose bitbanded IO
  */
-typedef struct ARMv7MState {
+struct ARMv7MState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -72,6 +77,6 @@ typedef struct ARMv7MState {
     bool start_powered_off;
     bool vfp;
     bool dsp;
-} ARMv7MState;
+};
 
 #endif
diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h
index 09da9d9acc..c9747b15fc 100644
--- a/include/hw/arm/aspeed.h
+++ b/include/hw/arm/aspeed.h
@@ -10,24 +10,22 @@
 #define ARM_ASPEED_H
 
 #include "hw/boards.h"
+#include "qom/object.h"
 
 typedef struct AspeedMachineState AspeedMachineState;
 
 #define TYPE_ASPEED_MACHINE       MACHINE_TYPE_NAME("aspeed")
-#define ASPEED_MACHINE(obj) \
-    OBJECT_CHECK(AspeedMachineState, (obj), TYPE_ASPEED_MACHINE)
+typedef struct AspeedMachineClass AspeedMachineClass;
+DECLARE_OBJ_CHECKERS(AspeedMachineState, AspeedMachineClass,
+                     ASPEED_MACHINE, TYPE_ASPEED_MACHINE)
 
 #define ASPEED_MAC0_ON   (1 << 0)
 #define ASPEED_MAC1_ON   (1 << 1)
 #define ASPEED_MAC2_ON   (1 << 2)
 #define ASPEED_MAC3_ON   (1 << 3)
 
-#define ASPEED_MACHINE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(AspeedMachineClass, (klass), TYPE_ASPEED_MACHINE)
-#define ASPEED_MACHINE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(AspeedMachineClass, (obj), TYPE_ASPEED_MACHINE)
 
-typedef struct AspeedMachineClass {
+struct AspeedMachineClass {
     MachineClass parent_obj;
 
     const char *name;
@@ -40,7 +38,7 @@ typedef struct AspeedMachineClass {
     uint32_t num_cs;
     uint32_t macs_mask;
     void (*i2c_init)(AspeedMachineState *bmc);
-} AspeedMachineClass;
+};
 
 
 #endif
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index d46f197cbe..05c7d53df3 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -27,6 +27,7 @@
 #include "hw/gpio/aspeed_gpio.h"
 #include "hw/sd/aspeed_sdhci.h"
 #include "hw/usb/hcd-ehci.h"
+#include "qom/object.h"
 
 #define ASPEED_SPIS_NUM  2
 #define ASPEED_EHCIS_NUM 2
@@ -34,7 +35,7 @@
 #define ASPEED_CPUS_NUM  2
 #define ASPEED_MACS_NUM  4
 
-typedef struct AspeedSoCState {
+struct AspeedSoCState {
     /*< private >*/
     DeviceState parent;
 
@@ -60,12 +61,15 @@ typedef struct AspeedSoCState {
     AspeedGPIOState gpio_1_8v;
     AspeedSDHCIState sdhci;
     AspeedSDHCIState emmc;
-} AspeedSoCState;
+};
+typedef struct AspeedSoCState AspeedSoCState;
 
 #define TYPE_ASPEED_SOC "aspeed-soc"
-#define ASPEED_SOC(obj) OBJECT_CHECK(AspeedSoCState, (obj), TYPE_ASPEED_SOC)
+typedef struct AspeedSoCClass AspeedSoCClass;
+DECLARE_OBJ_CHECKERS(AspeedSoCState, AspeedSoCClass,
+                     ASPEED_SOC, TYPE_ASPEED_SOC)
 
-typedef struct AspeedSoCClass {
+struct AspeedSoCClass {
     DeviceClass parent_class;
 
     const char *name;
@@ -79,12 +83,8 @@ typedef struct AspeedSoCClass {
     const int *irqmap;
     const hwaddr *memmap;
     uint32_t num_cpus;
-} AspeedSoCClass;
+};
 
-#define ASPEED_SOC_CLASS(klass)                                         \
-    OBJECT_CLASS_CHECK(AspeedSoCClass, (klass), TYPE_ASPEED_SOC)
-#define ASPEED_SOC_GET_CLASS(obj)                               \
-    OBJECT_GET_CLASS(AspeedSoCClass, (obj), TYPE_ASPEED_SOC)
 
 enum {
     ASPEED_DEV_IOMEM,
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
index 48a0ad1633..b4d3ae121a 100644
--- a/include/hw/arm/bcm2835_peripherals.h
+++ b/include/hw/arm/bcm2835_peripherals.h
@@ -29,12 +29,14 @@
 #include "hw/timer/bcm2835_systmr.h"
 #include "hw/usb/hcd-dwc2.h"
 #include "hw/misc/unimp.h"
+#include "qom/object.h"
 
 #define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
-#define BCM2835_PERIPHERALS(obj) \
-    OBJECT_CHECK(BCM2835PeripheralState, (obj), TYPE_BCM2835_PERIPHERALS)
+typedef struct BCM2835PeripheralState BCM2835PeripheralState;
+DECLARE_INSTANCE_CHECKER(BCM2835PeripheralState, BCM2835_PERIPHERALS,
+                         TYPE_BCM2835_PERIPHERALS)
 
-typedef struct BCM2835PeripheralState {
+struct BCM2835PeripheralState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -70,6 +72,6 @@ typedef struct BCM2835PeripheralState {
     UnimplementedDeviceState smi;
     DWC2State dwc2;
     UnimplementedDeviceState sdramc;
-} BCM2835PeripheralState;
+};
 
 #endif /* BCM2835_PERIPHERALS_H */
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
index 79dfff9d73..181d9563d0 100644
--- a/include/hw/arm/bcm2836.h
+++ b/include/hw/arm/bcm2836.h
@@ -15,9 +15,13 @@
 #include "hw/arm/bcm2835_peripherals.h"
 #include "hw/intc/bcm2836_control.h"
 #include "target/arm/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_BCM283X "bcm283x"
-#define BCM283X(obj) OBJECT_CHECK(BCM283XState, (obj), TYPE_BCM283X)
+typedef struct BCM283XClass BCM283XClass;
+typedef struct BCM283XState BCM283XState;
+DECLARE_OBJ_CHECKERS(BCM283XState, BCM283XClass,
+                     BCM283X, TYPE_BCM283X)
 
 #define BCM283X_NCPUS 4
 
@@ -28,7 +32,7 @@
 #define TYPE_BCM2836 "bcm2836"
 #define TYPE_BCM2837 "bcm2837"
 
-typedef struct BCM283XState {
+struct BCM283XState {
     /*< private >*/
     DeviceState parent_obj;
     /*< public >*/
@@ -40,18 +44,14 @@ typedef struct BCM283XState {
     } cpu[BCM283X_NCPUS];
     BCM2836ControlState control;
     BCM2835PeripheralState peripherals;
-} BCM283XState;
+};
 
 typedef struct BCM283XInfo BCM283XInfo;
 
-typedef struct BCM283XClass {
+struct BCM283XClass {
     DeviceClass parent_class;
     const BCM283XInfo *info;
-} BCM283XClass;
+};
 
-#define BCM283X_CLASS(klass) \
-    OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
-#define BCM283X_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
 
 #endif /* BCM2836_H */
diff --git a/include/hw/arm/digic.h b/include/hw/arm/digic.h
index 63785baaa8..f3ba398914 100644
--- a/include/hw/arm/digic.h
+++ b/include/hw/arm/digic.h
@@ -21,14 +21,17 @@
 #include "cpu.h"
 #include "hw/timer/digic-timer.h"
 #include "hw/char/digic-uart.h"
+#include "qom/object.h"
 
 #define TYPE_DIGIC "digic"
 
-#define DIGIC(obj) OBJECT_CHECK(DigicState, (obj), TYPE_DIGIC)
+typedef struct DigicState DigicState;
+DECLARE_INSTANCE_CHECKER(DigicState, DIGIC,
+                         TYPE_DIGIC)
 
 #define DIGIC4_NB_TIMERS 3
 
-typedef struct DigicState {
+struct DigicState {
     /*< private >*/
     DeviceState parent_obj;
     /*< public >*/
@@ -37,6 +40,6 @@ typedef struct DigicState {
 
     DigicTimerState timer[DIGIC4_NB_TIMERS];
     DigicUartState uart;
-} DigicState;
+};
 
 #endif /* HW_ARM_DIGIC_H */
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
index 55260394af..c2de1dc102 100644
--- a/include/hw/arm/exynos4210.h
+++ b/include/hw/arm/exynos4210.h
@@ -27,6 +27,7 @@
 #include "hw/or-irq.h"
 #include "hw/sysbus.h"
 #include "target/arm/cpu-qom.h"
+#include "qom/object.h"
 
 #define EXYNOS4210_NCPUS                    2
 
@@ -85,7 +86,7 @@ typedef struct Exynos4210Irq {
     qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
 } Exynos4210Irq;
 
-typedef struct Exynos4210State {
+struct Exynos4210State {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -101,11 +102,12 @@ typedef struct Exynos4210State {
     MemoryRegion bootreg_mem;
     I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
     qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
-} Exynos4210State;
+};
+typedef struct Exynos4210State Exynos4210State;
 
 #define TYPE_EXYNOS4210_SOC "exynos4210"
-#define EXYNOS4210_SOC(obj) \
-    OBJECT_CHECK(Exynos4210State, obj, TYPE_EXYNOS4210_SOC)
+DECLARE_INSTANCE_CHECKER(Exynos4210State, EXYNOS4210_SOC,
+                         TYPE_EXYNOS4210_SOC)
 
 void exynos4210_write_secondary(ARMCPU *cpu,
         const struct arm_boot_info *info);
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
index 54ee1bfd78..e239505724 100644
--- a/include/hw/arm/fsl-imx25.h
+++ b/include/hw/arm/fsl-imx25.h
@@ -32,9 +32,12 @@
 #include "hw/watchdog/wdt_imx2.h"
 #include "exec/memory.h"
 #include "target/arm/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_FSL_IMX25 "fsl,imx25"
-#define FSL_IMX25(obj) OBJECT_CHECK(FslIMX25State, (obj), TYPE_FSL_IMX25)
+typedef struct FslIMX25State FslIMX25State;
+DECLARE_INSTANCE_CHECKER(FslIMX25State, FSL_IMX25,
+                         TYPE_FSL_IMX25)
 
 #define FSL_IMX25_NUM_UARTS 5
 #define FSL_IMX25_NUM_GPTS 4
@@ -44,7 +47,7 @@
 #define FSL_IMX25_NUM_ESDHCS 2
 #define FSL_IMX25_NUM_USBS 2
 
-typedef struct FslIMX25State {
+struct FslIMX25State {
     /*< private >*/
     DeviceState parent_obj;
 
@@ -66,7 +69,7 @@ typedef struct FslIMX25State {
     MemoryRegion   iram;
     MemoryRegion   iram_alias;
     uint32_t       phy_num;
-} FslIMX25State;
+};
 
 /**
  * i.MX25 memory map
diff --git a/include/hw/arm/fsl-imx31.h b/include/hw/arm/fsl-imx31.h
index dd8561b309..64b4ca07b7 100644
--- a/include/hw/arm/fsl-imx31.h
+++ b/include/hw/arm/fsl-imx31.h
@@ -28,16 +28,19 @@
 #include "hw/watchdog/wdt_imx2.h"
 #include "exec/memory.h"
 #include "target/arm/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_FSL_IMX31 "fsl,imx31"
-#define FSL_IMX31(obj) OBJECT_CHECK(FslIMX31State, (obj), TYPE_FSL_IMX31)
+typedef struct FslIMX31State FslIMX31State;
+DECLARE_INSTANCE_CHECKER(FslIMX31State, FSL_IMX31,
+                         TYPE_FSL_IMX31)
 
 #define FSL_IMX31_NUM_UARTS 2
 #define FSL_IMX31_NUM_EPITS 2
 #define FSL_IMX31_NUM_I2CS 3
 #define FSL_IMX31_NUM_GPIOS 3
 
-typedef struct FslIMX31State {
+struct FslIMX31State {
     /*< private >*/
     DeviceState parent_obj;
 
@@ -55,7 +58,7 @@ typedef struct FslIMX31State {
     MemoryRegion   rom;
     MemoryRegion   iram;
     MemoryRegion   iram_alias;
-} FslIMX31State;
+};
 
 #define FSL_IMX31_SECURE_ROM_ADDR       0x00000000
 #define FSL_IMX31_SECURE_ROM_SIZE       0x4000
diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
index 162fe99375..602b9aff36 100644
--- a/include/hw/arm/fsl-imx6.h
+++ b/include/hw/arm/fsl-imx6.h
@@ -34,9 +34,12 @@
 #include "hw/usb/imx-usb-phy.h"
 #include "exec/memory.h"
 #include "cpu.h"
+#include "qom/object.h"
 
 #define TYPE_FSL_IMX6 "fsl,imx6"
-#define FSL_IMX6(obj) OBJECT_CHECK(FslIMX6State, (obj), TYPE_FSL_IMX6)
+typedef struct FslIMX6State FslIMX6State;
+DECLARE_INSTANCE_CHECKER(FslIMX6State, FSL_IMX6,
+                         TYPE_FSL_IMX6)
 
 #define FSL_IMX6_NUM_CPUS 4
 #define FSL_IMX6_NUM_UARTS 5
@@ -49,7 +52,7 @@
 #define FSL_IMX6_NUM_USB_PHYS 2
 #define FSL_IMX6_NUM_USBS 4
 
-typedef struct FslIMX6State {
+struct FslIMX6State {
     /*< private >*/
     DeviceState parent_obj;
 
@@ -74,7 +77,7 @@ typedef struct FslIMX6State {
     MemoryRegion   ocram;
     MemoryRegion   ocram_alias;
     uint32_t       phy_num;
-} FslIMX6State;
+};
 
 
 #define FSL_IMX6_MMDC_ADDR 0x10000000
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
index fcbaf3dc86..e4862fdb2c 100644
--- a/include/hw/arm/fsl-imx6ul.h
+++ b/include/hw/arm/fsl-imx6ul.h
@@ -38,9 +38,12 @@
 #include "hw/usb/imx-usb-phy.h"
 #include "exec/memory.h"
 #include "cpu.h"
+#include "qom/object.h"
 
 #define TYPE_FSL_IMX6UL "fsl,imx6ul"
-#define FSL_IMX6UL(obj) OBJECT_CHECK(FslIMX6ULState, (obj), TYPE_FSL_IMX6UL)
+typedef struct FslIMX6ULState FslIMX6ULState;
+DECLARE_INSTANCE_CHECKER(FslIMX6ULState, FSL_IMX6UL,
+                         TYPE_FSL_IMX6UL)
 
 enum FslIMX6ULConfiguration {
     FSL_IMX6UL_NUM_CPUS         = 1,
@@ -60,7 +63,7 @@ enum FslIMX6ULConfiguration {
     FSL_IMX6UL_NUM_USBS         = 2,
 };
 
-typedef struct FslIMX6ULState {
+struct FslIMX6ULState {
     /*< private >*/
     DeviceState    parent_obj;
 
@@ -89,7 +92,7 @@ typedef struct FslIMX6ULState {
     MemoryRegion       ocram_alias;
 
     uint32_t           phy_num[FSL_IMX6UL_NUM_ETHS];
-} FslIMX6ULState;
+};
 
 enum FslIMX6ULMemoryMap {
     FSL_IMX6UL_MMDC_ADDR            = 0x80000000,
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
index ad88923707..434d1d0641 100644
--- a/include/hw/arm/fsl-imx7.h
+++ b/include/hw/arm/fsl-imx7.h
@@ -39,9 +39,12 @@
 #include "hw/pci-host/designware.h"
 #include "hw/usb/chipidea.h"
 #include "cpu.h"
+#include "qom/object.h"
 
 #define TYPE_FSL_IMX7 "fsl,imx7"
-#define FSL_IMX7(obj) OBJECT_CHECK(FslIMX7State, (obj), TYPE_FSL_IMX7)
+typedef struct FslIMX7State FslIMX7State;
+DECLARE_INSTANCE_CHECKER(FslIMX7State, FSL_IMX7,
+                         TYPE_FSL_IMX7)
 
 enum FslIMX7Configuration {
     FSL_IMX7_NUM_CPUS         = 2,
@@ -59,7 +62,7 @@ enum FslIMX7Configuration {
     FSL_IMX7_NUM_ADCS         = 2,
 };
 
-typedef struct FslIMX7State {
+struct FslIMX7State {
     /*< private >*/
     DeviceState    parent_obj;
 
@@ -82,7 +85,7 @@ typedef struct FslIMX7State {
     ChipideaState      usb[FSL_IMX7_NUM_USBS];
     DesignwarePCIEHost pcie;
     uint32_t           phy_num[FSL_IMX7_NUM_ETHS];
-} FslIMX7State;
+};
 
 enum FslIMX7MemoryMap {
     FSL_IMX7_MMDC_ADDR            = 0x80000000,
diff --git a/include/hw/arm/linux-boot-if.h b/include/hw/arm/linux-boot-if.h
index 7bbdfd1cc6..c85f33b2c5 100644
--- a/include/hw/arm/linux-boot-if.h
+++ b/include/hw/arm/linux-boot-if.h
@@ -9,16 +9,15 @@
 #include "qom/object.h"
 
 #define TYPE_ARM_LINUX_BOOT_IF "arm-linux-boot-if"
-#define ARM_LINUX_BOOT_IF_CLASS(klass) \
-    OBJECT_CLASS_CHECK(ARMLinuxBootIfClass, (klass), TYPE_ARM_LINUX_BOOT_IF)
-#define ARM_LINUX_BOOT_IF_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(ARMLinuxBootIfClass, (obj), TYPE_ARM_LINUX_BOOT_IF)
+typedef struct ARMLinuxBootIfClass ARMLinuxBootIfClass;
+DECLARE_CLASS_CHECKERS(ARMLinuxBootIfClass, ARM_LINUX_BOOT_IF,
+                       TYPE_ARM_LINUX_BOOT_IF)
 #define ARM_LINUX_BOOT_IF(obj) \
     INTERFACE_CHECK(ARMLinuxBootIf, (obj), TYPE_ARM_LINUX_BOOT_IF)
 
 typedef struct ARMLinuxBootIf ARMLinuxBootIf;
 
-typedef struct ARMLinuxBootIfClass {
+struct ARMLinuxBootIfClass {
     /*< private >*/
     InterfaceClass parent_class;
 
@@ -35,6 +34,6 @@ typedef struct ARMLinuxBootIfClass {
      * (or for a CPU which doesn't support TrustZone)
      */
     void (*arm_linux_init)(ARMLinuxBootIf *obj, bool secure_boot);
-} ARMLinuxBootIfClass;
+};
 
 #endif
diff --git a/include/hw/arm/msf2-soc.h b/include/hw/arm/msf2-soc.h
index c9cb214aa6..9b93d0d64e 100644
--- a/include/hw/arm/msf2-soc.h
+++ b/include/hw/arm/msf2-soc.h
@@ -30,9 +30,12 @@
 #include "hw/misc/msf2-sysreg.h"
 #include "hw/ssi/mss-spi.h"
 #include "hw/net/msf2-emac.h"
+#include "qom/object.h"
 
 #define TYPE_MSF2_SOC     "msf2-soc"
-#define MSF2_SOC(obj)     OBJECT_CHECK(MSF2State, (obj), TYPE_MSF2_SOC)
+typedef struct MSF2State MSF2State;
+DECLARE_INSTANCE_CHECKER(MSF2State, MSF2_SOC,
+                         TYPE_MSF2_SOC)
 
 #define MSF2_NUM_SPIS         2
 #define MSF2_NUM_UARTS        2
@@ -44,7 +47,7 @@
  */
 #define MSF2_NUM_TIMERS       2
 
-typedef struct MSF2State {
+struct MSF2State {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -64,6 +67,6 @@ typedef struct MSF2State {
     MSSTimerState timer;
     MSSSpiState spi[MSF2_NUM_SPIS];
     MSF2EmacState emac;
-} MSF2State;
+};
 
 #endif
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
index 0cb78aafea..b69492b29d 100644
--- a/include/hw/arm/nrf51_soc.h
+++ b/include/hw/arm/nrf51_soc.h
@@ -17,14 +17,16 @@
 #include "hw/gpio/nrf51_gpio.h"
 #include "hw/nvram/nrf51_nvm.h"
 #include "hw/timer/nrf51_timer.h"
+#include "qom/object.h"
 
 #define TYPE_NRF51_SOC "nrf51-soc"
-#define NRF51_SOC(obj) \
-    OBJECT_CHECK(NRF51State, (obj), TYPE_NRF51_SOC)
+typedef struct NRF51State NRF51State;
+DECLARE_INSTANCE_CHECKER(NRF51State, NRF51_SOC,
+                         TYPE_NRF51_SOC)
 
 #define NRF51_NUM_TIMERS 3
 
-typedef struct NRF51State {
+struct NRF51State {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -50,6 +52,6 @@ typedef struct NRF51State {
 
     MemoryRegion container;
 
-} NRF51State;
+};
 
 #endif
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
index 6be386d0e2..0dbf1712f4 100644
--- a/include/hw/arm/omap.h
+++ b/include/hw/arm/omap.h
@@ -24,6 +24,7 @@
 #include "hw/input/tsc2xxx.h"
 #include "target/arm/cpu-qom.h"
 #include "qemu/log.h"
+#include "qom/object.h"
 
 # define OMAP_EMIFS_BASE	0x00000000
 # define OMAP2_Q0_BASE		0x00000000
@@ -69,10 +70,10 @@ void omap_clk_reparent(omap_clk clk, omap_clk parent);
 
 /* omap_intc.c */
 #define TYPE_OMAP_INTC "common-omap-intc"
-#define OMAP_INTC(obj)                                              \
-    OBJECT_CHECK(omap_intr_handler, (obj), TYPE_OMAP_INTC)
-
 typedef struct omap_intr_handler_s omap_intr_handler;
+DECLARE_INSTANCE_CHECKER(omap_intr_handler, OMAP_INTC,
+                         TYPE_OMAP_INTC)
+
 
 /*
  * TODO: Ideally we should have a clock framework that
@@ -93,9 +94,10 @@ void omap_intc_set_fclk(omap_intr_handler *intc, omap_clk clk);
 
 /* omap_i2c.c */
 #define TYPE_OMAP_I2C "omap_i2c"
-#define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C)
-
 typedef struct OMAPI2CState OMAPI2CState;
+DECLARE_INSTANCE_CHECKER(OMAPI2CState, OMAP_I2C,
+                         TYPE_OMAP_I2C)
+
 
 /* TODO: clock framework (see above) */
 void omap_i2c_set_iclk(OMAPI2CState *i2c, omap_clk clk);
@@ -103,12 +105,12 @@ void omap_i2c_set_fclk(OMAPI2CState *i2c, omap_clk clk);
 
 /* omap_gpio.c */
 #define TYPE_OMAP1_GPIO "omap-gpio"
-#define OMAP1_GPIO(obj)                                         \
-    OBJECT_CHECK(struct omap_gpif_s, (obj), TYPE_OMAP1_GPIO)
+DECLARE_INSTANCE_CHECKER(struct omap_gpif_s, OMAP1_GPIO,
+                         TYPE_OMAP1_GPIO)
 
 #define TYPE_OMAP2_GPIO "omap2-gpio"
-#define OMAP2_GPIO(obj)                                         \
-    OBJECT_CHECK(struct omap2_gpif_s, (obj), TYPE_OMAP2_GPIO)
+DECLARE_INSTANCE_CHECKER(struct omap2_gpif_s, OMAP2_GPIO,
+                         TYPE_OMAP2_GPIO)
 
 typedef struct omap_gpif_s omap_gpif;
 typedef struct omap2_gpif_s omap2_gpif;
diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
index 09c1336071..9046876134 100644
--- a/include/hw/arm/pxa.h
+++ b/include/hw/arm/pxa.h
@@ -13,6 +13,7 @@
 #include "exec/memory.h"
 #include "target/arm/cpu-qom.h"
 #include "hw/pcmcia.h"
+#include "qom/object.h"
 
 /* Interrupt numbers */
 # define PXA2XX_PIC_SSP3	0
@@ -88,7 +89,8 @@ void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq handler);
 /* pxa2xx_mmci.c */
 #define TYPE_PXA2XX_MMCI "pxa2xx-mmci"
 typedef struct PXA2xxMMCIState PXA2xxMMCIState;
-#define PXA2XX_MMCI(obj) OBJECT_CHECK(PXA2xxMMCIState, (obj), TYPE_PXA2XX_MMCI)
+DECLARE_INSTANCE_CHECKER(PXA2xxMMCIState, PXA2XX_MMCI,
+                         TYPE_PXA2XX_MMCI)
 
 PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
                 hwaddr base,
@@ -99,8 +101,8 @@ void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly,
 /* pxa2xx_pcmcia.c */
 #define TYPE_PXA2XX_PCMCIA "pxa2xx-pcmcia"
 typedef struct PXA2xxPCMCIAState PXA2xxPCMCIAState;
-#define PXA2XX_PCMCIA(obj) \
-    OBJECT_CHECK(PXA2xxPCMCIAState, obj, TYPE_PXA2XX_PCMCIA)
+DECLARE_INSTANCE_CHECKER(PXA2xxPCMCIAState, PXA2XX_PCMCIA,
+                         TYPE_PXA2XX_PCMCIA)
 
 PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
                                       hwaddr base);
@@ -128,12 +130,13 @@ I2CBus *pxa2xx_i2c_bus(PXA2xxI2CState *s);
 
 #define TYPE_PXA2XX_I2C "pxa2xx_i2c"
 typedef struct PXA2xxI2SState PXA2xxI2SState;
-#define PXA2XX_I2C(obj) \
-    OBJECT_CHECK(PXA2xxI2CState, (obj), TYPE_PXA2XX_I2C)
+DECLARE_INSTANCE_CHECKER(PXA2xxI2CState, PXA2XX_I2C,
+                         TYPE_PXA2XX_I2C)
 
 #define TYPE_PXA2XX_FIR "pxa2xx-fir"
 typedef struct PXA2xxFIrState PXA2xxFIrState;
-#define PXA2XX_FIR(obj) OBJECT_CHECK(PXA2xxFIrState, (obj), TYPE_PXA2XX_FIR)
+DECLARE_INSTANCE_CHECKER(PXA2xxFIrState, PXA2XX_FIR,
+                         TYPE_PXA2XX_FIR)
 
 typedef struct {
     ARMCPU *cpu;
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
index 880dccd7c0..54d0872fd8 100644
--- a/include/hw/arm/smmu-common.h
+++ b/include/hw/arm/smmu-common.h
@@ -21,6 +21,7 @@
 
 #include "hw/sysbus.h"
 #include "hw/pci/pci.h"
+#include "qom/object.h"
 
 #define SMMU_PCI_BUS_MAX      256
 #define SMMU_PCI_DEVFN_MAX    256
@@ -102,7 +103,7 @@ typedef struct SMMUIOTLBKey {
     uint8_t level;
 } SMMUIOTLBKey;
 
-typedef struct SMMUState {
+struct SMMUState {
     /* <private> */
     SysBusDevice  dev;
     const char *mrtypename;
@@ -116,9 +117,10 @@ typedef struct SMMUState {
     QLIST_HEAD(, SMMUDevice) devices_with_notifiers;
     uint8_t bus_num;
     PCIBus *primary_bus;
-} SMMUState;
+};
+typedef struct SMMUState SMMUState;
 
-typedef struct {
+struct SMMUBaseClass {
     /* <private> */
     SysBusDeviceClass parent_class;
 
@@ -126,14 +128,12 @@ typedef struct {
 
     DeviceRealize parent_realize;
 
-} SMMUBaseClass;
+};
+typedef struct SMMUBaseClass SMMUBaseClass;
 
 #define TYPE_ARM_SMMU "arm-smmu"
-#define ARM_SMMU(obj) OBJECT_CHECK(SMMUState, (obj), TYPE_ARM_SMMU)
-#define ARM_SMMU_CLASS(klass)                                    \
-    OBJECT_CLASS_CHECK(SMMUBaseClass, (klass), TYPE_ARM_SMMU)
-#define ARM_SMMU_GET_CLASS(obj)                              \
-    OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU)
+DECLARE_OBJ_CHECKERS(SMMUState, SMMUBaseClass,
+                     ARM_SMMU, TYPE_ARM_SMMU)
 
 /* Return the SMMUPciBus handle associated to a PCI bus number */
 SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num);
diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h
index 68d7a963e0..2a3f6dd197 100644
--- a/include/hw/arm/smmuv3.h
+++ b/include/hw/arm/smmuv3.h
@@ -21,6 +21,7 @@
 
 #include "hw/arm/smmu-common.h"
 #include "hw/registerfields.h"
+#include "qom/object.h"
 
 #define TYPE_SMMUV3_IOMMU_MEMORY_REGION "smmuv3-iommu-memory-region"
 
@@ -32,7 +33,7 @@ typedef struct SMMUQueue {
      uint8_t log2size;
 } SMMUQueue;
 
-typedef struct SMMUv3State {
+struct SMMUv3State {
     SMMUState     smmu_state;
 
     uint32_t features;
@@ -61,7 +62,8 @@ typedef struct SMMUv3State {
 
     qemu_irq     irq[4];
     QemuMutex mutex;
-} SMMUv3State;
+};
+typedef struct SMMUv3State SMMUv3State;
 
 typedef enum {
     SMMU_IRQ_EVTQ,
@@ -70,20 +72,18 @@ typedef enum {
     SMMU_IRQ_GERROR,
 } SMMUIrq;
 
-typedef struct {
+struct SMMUv3Class {
     /*< private >*/
     SMMUBaseClass smmu_base_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
     DeviceReset   parent_reset;
-} SMMUv3Class;
+};
+typedef struct SMMUv3Class SMMUv3Class;
 
 #define TYPE_ARM_SMMUV3   "arm-smmuv3"
-#define ARM_SMMUV3(obj) OBJECT_CHECK(SMMUv3State, (obj), TYPE_ARM_SMMUV3)
-#define ARM_SMMUV3_CLASS(klass)                              \
-    OBJECT_CLASS_CHECK(SMMUv3Class, (klass), TYPE_ARM_SMMUV3)
-#define ARM_SMMUV3_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(SMMUv3Class, (obj), TYPE_ARM_SMMUV3)
+DECLARE_OBJ_CHECKERS(SMMUv3State, SMMUv3Class,
+                     ARM_SMMUV3, TYPE_ARM_SMMUV3)
 
 #endif
diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h
index 922a733f88..9c2f4818a6 100644
--- a/include/hw/arm/stm32f205_soc.h
+++ b/include/hw/arm/stm32f205_soc.h
@@ -32,10 +32,12 @@
 #include "hw/or-irq.h"
 #include "hw/ssi/stm32f2xx_spi.h"
 #include "hw/arm/armv7m.h"
+#include "qom/object.h"
 
 #define TYPE_STM32F205_SOC "stm32f205-soc"
-#define STM32F205_SOC(obj) \
-    OBJECT_CHECK(STM32F205State, (obj), TYPE_STM32F205_SOC)
+typedef struct STM32F205State STM32F205State;
+DECLARE_INSTANCE_CHECKER(STM32F205State, STM32F205_SOC,
+                         TYPE_STM32F205_SOC)
 
 #define STM_NUM_USARTS 6
 #define STM_NUM_TIMERS 4
@@ -47,7 +49,7 @@
 #define SRAM_BASE_ADDRESS 0x20000000
 #define SRAM_SIZE (128 * 1024)
 
-typedef struct STM32F205State {
+struct STM32F205State {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -63,6 +65,6 @@ typedef struct STM32F205State {
     STM32F2XXSPIState spi[STM_NUM_SPIS];
 
     qemu_or_irq *adc_irqs;
-} STM32F205State;
+};
 
 #endif
diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
index 1fe97f8c3a..f1a22763f4 100644
--- a/include/hw/arm/stm32f405_soc.h
+++ b/include/hw/arm/stm32f405_soc.h
@@ -33,10 +33,12 @@
 #include "hw/or-irq.h"
 #include "hw/ssi/stm32f2xx_spi.h"
 #include "hw/arm/armv7m.h"
+#include "qom/object.h"
 
 #define TYPE_STM32F405_SOC "stm32f405-soc"
-#define STM32F405_SOC(obj) \
-    OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
+typedef struct STM32F405State STM32F405State;
+DECLARE_INSTANCE_CHECKER(STM32F405State, STM32F405_SOC,
+                         TYPE_STM32F405_SOC)
 
 #define STM_NUM_USARTS 7
 #define STM_NUM_TIMERS 4
@@ -48,7 +50,7 @@
 #define SRAM_BASE_ADDRESS 0x20000000
 #define SRAM_SIZE (192 * 1024)
 
-typedef struct STM32F405State {
+struct STM32F405State {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -68,6 +70,6 @@ typedef struct STM32F405State {
     MemoryRegion sram;
     MemoryRegion flash;
     MemoryRegion flash_alias;
-} STM32F405State;
+};
 
 #endif
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index dff67e1bef..392b0bd571 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -37,6 +37,7 @@
 #include "hw/block/flash.h"
 #include "sysemu/kvm.h"
 #include "hw/intc/arm_gicv3_common.h"
+#include "qom/object.h"
 
 #define NUM_GICV2M_SPIS       64
 #define NUM_VIRTIO_TRANSPORTS 32
@@ -115,7 +116,7 @@ typedef struct MemMapEntry {
     hwaddr size;
 } MemMapEntry;
 
-typedef struct {
+struct VirtMachineClass {
     MachineClass parent;
     bool disallow_affinity_adjustment;
     bool no_its;
@@ -126,9 +127,10 @@ typedef struct {
     bool no_ged;   /* Machines < 4.2 has no support for ACPI GED device */
     bool kvm_no_adjvtime;
     bool acpi_expose_flash;
-} VirtMachineClass;
+};
+typedef struct VirtMachineClass VirtMachineClass;
 
-typedef struct {
+struct VirtMachineState {
     MachineState parent;
     Notifier machine_done;
     DeviceState *platform_bus_dev;
@@ -162,17 +164,14 @@ typedef struct {
     DeviceState *gic;
     DeviceState *acpi_dev;
     Notifier powerdown_notifier;
-} VirtMachineState;
+};
+typedef struct VirtMachineState VirtMachineState;
 
 #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
 
 #define TYPE_VIRT_MACHINE   MACHINE_TYPE_NAME("virt")
-#define VIRT_MACHINE(obj) \
-    OBJECT_CHECK(VirtMachineState, (obj), TYPE_VIRT_MACHINE)
-#define VIRT_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(VirtMachineClass, obj, TYPE_VIRT_MACHINE)
-#define VIRT_MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE)
+DECLARE_OBJ_CHECKERS(VirtMachineState, VirtMachineClass,
+                     VIRT_MACHINE, TYPE_VIRT_MACHINE)
 
 void virt_acpi_setup(VirtMachineState *vms);
 bool virt_is_acpi_enabled(VirtMachineState *vms);
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 9c9f47ba9d..eaa9023fd6 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -20,9 +20,12 @@
 #include "hw/dma/xlnx-zdma.h"
 #include "hw/net/cadence_gem.h"
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
+#include "qom/object.h"
 
 #define TYPE_XLNX_VERSAL "xlnx-versal"
-#define XLNX_VERSAL(obj) OBJECT_CHECK(Versal, (obj), TYPE_XLNX_VERSAL)
+typedef struct Versal Versal;
+DECLARE_INSTANCE_CHECKER(Versal, XLNX_VERSAL,
+                         TYPE_XLNX_VERSAL)
 
 #define XLNX_VERSAL_NR_ACPUS   2
 #define XLNX_VERSAL_NR_UARTS   2
@@ -31,7 +34,7 @@
 #define XLNX_VERSAL_NR_SDS     2
 #define XLNX_VERSAL_NR_IRQS    192
 
-typedef struct Versal {
+struct Versal {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -74,7 +77,7 @@ typedef struct Versal {
         MemoryRegion *mr_ddr;
         uint32_t psci_conduit;
     } cfg;
-} Versal;
+};
 
 /* Memory-map and IRQ definitions. Copied a subset from
  * auto-generated files.  */
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index 53076fa29a..4cc97b4610 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -32,10 +32,12 @@
 #include "hw/rtc/xlnx-zynqmp-rtc.h"
 #include "hw/cpu/cluster.h"
 #include "target/arm/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
-#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
-                                       TYPE_XLNX_ZYNQMP)
+typedef struct XlnxZynqMPState XlnxZynqMPState;
+DECLARE_INSTANCE_CHECKER(XlnxZynqMPState, XLNX_ZYNQMP,
+                         TYPE_XLNX_ZYNQMP)
 
 #define XLNX_ZYNQMP_NUM_APU_CPUS 4
 #define XLNX_ZYNQMP_NUM_RPU_CPUS 2
@@ -73,7 +75,7 @@
 #define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \
                                   XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE)
 
-typedef struct XlnxZynqMPState {
+struct XlnxZynqMPState {
     /*< private >*/
     DeviceState parent_obj;
 
@@ -112,6 +114,6 @@ typedef struct XlnxZynqMPState {
     bool virt;
     /* Has the RPU subsystem?  */
     bool has_rpu;
-}  XlnxZynqMPState;
+};
 
 #endif
diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h
index 2136a2d5e4..3e26303705 100644
--- a/include/hw/block/flash.h
+++ b/include/hw/block/flash.h
@@ -4,14 +4,15 @@
 /* NOR flash devices */
 
 #include "exec/hwaddr.h"
+#include "qom/object.h"
 
 /* pflash_cfi01.c */
 
 #define TYPE_PFLASH_CFI01 "cfi.pflash01"
-#define PFLASH_CFI01(obj) \
-    OBJECT_CHECK(PFlashCFI01, (obj), TYPE_PFLASH_CFI01)
-
 typedef struct PFlashCFI01 PFlashCFI01;
+DECLARE_INSTANCE_CHECKER(PFlashCFI01, PFLASH_CFI01,
+                         TYPE_PFLASH_CFI01)
+
 
 PFlashCFI01 *pflash_cfi01_register(hwaddr base,
                                    const char *name,
@@ -29,10 +30,10 @@ void pflash_cfi01_legacy_drive(PFlashCFI01 *dev, DriveInfo *dinfo);
 /* pflash_cfi02.c */
 
 #define TYPE_PFLASH_CFI02 "cfi.pflash02"
-#define PFLASH_CFI02(obj) \
-    OBJECT_CHECK(PFlashCFI02, (obj), TYPE_PFLASH_CFI02)
-
 typedef struct PFlashCFI02 PFlashCFI02;
+DECLARE_INSTANCE_CHECKER(PFlashCFI02, PFLASH_CFI02,
+                         TYPE_PFLASH_CFI02)
+
 
 PFlashCFI02 *pflash_cfi02_register(hwaddr base,
                                    const char *name,
diff --git a/include/hw/block/swim.h b/include/hw/block/swim.h
index 9d8b65c561..8287da7c30 100644
--- a/include/hw/block/swim.h
+++ b/include/hw/block/swim.h
@@ -13,6 +13,7 @@
 
 #include "qemu/osdep.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define SWIM_MAX_FD            2
 
@@ -21,7 +22,8 @@ typedef struct SWIMBus SWIMBus;
 typedef struct SWIMCtrl SWIMCtrl;
 
 #define TYPE_SWIM_DRIVE "swim-drive"
-#define SWIM_DRIVE(obj) OBJECT_CHECK(SWIMDrive, (obj), TYPE_SWIM_DRIVE)
+DECLARE_INSTANCE_CHECKER(SWIMDrive, SWIM_DRIVE,
+                         TYPE_SWIM_DRIVE)
 
 struct SWIMDrive {
     DeviceState qdev;
@@ -30,7 +32,8 @@ struct SWIMDrive {
 };
 
 #define TYPE_SWIM_BUS "swim-bus"
-#define SWIM_BUS(obj) OBJECT_CHECK(SWIMBus, (obj), TYPE_SWIM_BUS)
+DECLARE_INSTANCE_CHECKER(SWIMBus, SWIM_BUS,
+                         TYPE_SWIM_BUS)
 
 struct SWIMBus {
     BusState bus;
@@ -67,10 +70,12 @@ struct SWIMCtrl {
 };
 
 #define TYPE_SWIM "swim"
-#define SWIM(obj) OBJECT_CHECK(Swim, (obj), TYPE_SWIM)
+typedef struct Swim Swim;
+DECLARE_INSTANCE_CHECKER(Swim, SWIM,
+                         TYPE_SWIM)
 
-typedef struct Swim {
+struct Swim {
     SysBusDevice parent_obj;
     SWIMCtrl     ctrl;
-} Swim;
+};
 #endif
diff --git a/include/hw/boards.h b/include/hw/boards.h
index bc5b82ad20..795910d01b 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -21,12 +21,8 @@
 
 #define TYPE_MACHINE "machine"
 #undef MACHINE  /* BSD defines it and QEMU does not use it */
-#define MACHINE(obj) \
-    OBJECT_CHECK(MachineState, (obj), TYPE_MACHINE)
-#define MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(MachineClass, (obj), TYPE_MACHINE)
-#define MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(MachineClass, (klass), TYPE_MACHINE)
+DECLARE_OBJ_CHECKERS(MachineState, MachineClass,
+                     MACHINE, TYPE_MACHINE)
 
 extern MachineState *current_machine;
 
diff --git a/include/hw/char/avr_usart.h b/include/hw/char/avr_usart.h
index 5739aaf26f..5202f152b0 100644
--- a/include/hw/char/avr_usart.h
+++ b/include/hw/char/avr_usart.h
@@ -25,6 +25,7 @@
 #include "hw/sysbus.h"
 #include "chardev/char-fe.h"
 #include "hw/hw.h"
+#include "qom/object.h"
 
 /* Offsets of registers. */
 #define USART_DR   0x06
@@ -57,10 +58,11 @@
 #define USART_CSRC_CSZ0   (1 << 1)
 
 #define TYPE_AVR_USART "avr-usart"
-#define AVR_USART(obj) \
-    OBJECT_CHECK(AVRUsartState, (obj), TYPE_AVR_USART)
+typedef struct AVRUsartState AVRUsartState;
+DECLARE_INSTANCE_CHECKER(AVRUsartState, AVR_USART,
+                         TYPE_AVR_USART)
 
-typedef struct {
+struct AVRUsartState {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -88,6 +90,6 @@ typedef struct {
     qemu_irq txc_irq;
     /* Data Register Empty */
     qemu_irq dre_irq;
-} AVRUsartState;
+};
 
 #endif /* HW_CHAR_AVR_USART_H */
diff --git a/include/hw/char/bcm2835_aux.h b/include/hw/char/bcm2835_aux.h
index 934acf9c81..a08795c47f 100644
--- a/include/hw/char/bcm2835_aux.h
+++ b/include/hw/char/bcm2835_aux.h
@@ -11,13 +11,16 @@
 
 #include "hw/sysbus.h"
 #include "chardev/char-fe.h"
+#include "qom/object.h"
 
 #define TYPE_BCM2835_AUX "bcm2835-aux"
-#define BCM2835_AUX(obj) OBJECT_CHECK(BCM2835AuxState, (obj), TYPE_BCM2835_AUX)
+typedef struct BCM2835AuxState BCM2835AuxState;
+DECLARE_INSTANCE_CHECKER(BCM2835AuxState, BCM2835_AUX,
+                         TYPE_BCM2835_AUX)
 
 #define BCM2835_AUX_RX_FIFO_LEN 8
 
-typedef struct {
+struct BCM2835AuxState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -29,6 +32,6 @@ typedef struct {
     uint8_t read_fifo[BCM2835_AUX_RX_FIFO_LEN];
     uint8_t read_pos, read_count;
     uint8_t ier, iir;
-} BCM2835AuxState;
+};
 
 #endif
diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h
index dabc49ea4f..1734f53541 100644
--- a/include/hw/char/cadence_uart.h
+++ b/include/hw/char/cadence_uart.h
@@ -24,6 +24,7 @@
 #include "chardev/char-fe.h"
 #include "qapi/error.h"
 #include "qemu/timer.h"
+#include "qom/object.h"
 
 #define CADENCE_UART_RX_FIFO_SIZE           16
 #define CADENCE_UART_TX_FIFO_SIZE           16
@@ -31,10 +32,11 @@
 #define CADENCE_UART_R_MAX (0x48/4)
 
 #define TYPE_CADENCE_UART "cadence_uart"
-#define CADENCE_UART(obj) OBJECT_CHECK(CadenceUARTState, (obj), \
-                                       TYPE_CADENCE_UART)
+typedef struct CadenceUARTState CadenceUARTState;
+DECLARE_INSTANCE_CHECKER(CadenceUARTState, CADENCE_UART,
+                         TYPE_CADENCE_UART)
 
-typedef struct {
+struct CadenceUARTState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -51,6 +53,6 @@ typedef struct {
     qemu_irq irq;
     QEMUTimer *fifo_trigger_handle;
     Clock *refclk;
-} CadenceUARTState;
+};
 
 #endif
diff --git a/include/hw/char/cmsdk-apb-uart.h b/include/hw/char/cmsdk-apb-uart.h
index bc9069f9fd..2c3869aa16 100644
--- a/include/hw/char/cmsdk-apb-uart.h
+++ b/include/hw/char/cmsdk-apb-uart.h
@@ -15,12 +15,14 @@
 #include "hw/qdev-properties.h"
 #include "hw/sysbus.h"
 #include "chardev/char-fe.h"
+#include "qom/object.h"
 
 #define TYPE_CMSDK_APB_UART "cmsdk-apb-uart"
-#define CMSDK_APB_UART(obj) OBJECT_CHECK(CMSDKAPBUART, (obj), \
-                                         TYPE_CMSDK_APB_UART)
+typedef struct CMSDKAPBUART CMSDKAPBUART;
+DECLARE_INSTANCE_CHECKER(CMSDKAPBUART, CMSDK_APB_UART,
+                         TYPE_CMSDK_APB_UART)
 
-typedef struct {
+struct CMSDKAPBUART {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -42,7 +44,7 @@ typedef struct {
     /* This UART has no FIFO, only a 1-character buffer for each of Tx and Rx */
     uint8_t txbuf;
     uint8_t rxbuf;
-} CMSDKAPBUART;
+};
 
 /**
  * cmsdk_apb_uart_create - convenience function to create TYPE_CMSDK_APB_UART
diff --git a/include/hw/char/digic-uart.h b/include/hw/char/digic-uart.h
index de9a3e3551..01d406833d 100644
--- a/include/hw/char/digic-uart.h
+++ b/include/hw/char/digic-uart.h
@@ -20,10 +20,12 @@
 
 #include "hw/sysbus.h"
 #include "chardev/char-fe.h"
+#include "qom/object.h"
 
 #define TYPE_DIGIC_UART "digic-uart"
-#define DIGIC_UART(obj) \
-    OBJECT_CHECK(DigicUartState, (obj), TYPE_DIGIC_UART)
+typedef struct DigicUartState DigicUartState;
+DECLARE_INSTANCE_CHECKER(DigicUartState, DIGIC_UART,
+                         TYPE_DIGIC_UART)
 
 enum {
     R_TX = 0x00,
@@ -32,7 +34,7 @@ enum {
     R_MAX
 };
 
-typedef struct DigicUartState {
+struct DigicUartState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -42,6 +44,6 @@ typedef struct DigicUartState {
 
     uint32_t reg_rx;
     uint32_t reg_st;
-} DigicUartState;
+};
 
 #endif /* HW_CHAR_DIGIC_UART_H */
diff --git a/include/hw/char/escc.h b/include/hw/char/escc.h
index 794b653484..5eaec507da 100644
--- a/include/hw/char/escc.h
+++ b/include/hw/char/escc.h
@@ -5,12 +5,15 @@
 #include "chardev/char-serial.h"
 #include "hw/sysbus.h"
 #include "ui/input.h"
+#include "qom/object.h"
 
 /* escc.c */
 #define TYPE_ESCC "escc"
 #define ESCC_SIZE 4
 
-#define ESCC(obj) OBJECT_CHECK(ESCCState, (obj), TYPE_ESCC)
+typedef struct ESCCState ESCCState;
+DECLARE_INSTANCE_CHECKER(ESCCState, ESCC,
+                         TYPE_ESCC)
 
 typedef enum {
     escc_chn_a, escc_chn_b,
@@ -46,7 +49,7 @@ typedef struct ESCCChannelState {
     QemuInputHandlerState *hs;
 } ESCCChannelState;
 
-typedef struct ESCCState {
+struct ESCCState {
     SysBusDevice parent_obj;
 
     struct ESCCChannelState chn[2];
@@ -55,6 +58,6 @@ typedef struct ESCCState {
     MemoryRegion mmio;
     uint32_t disabled;
     uint32_t frequency;
-} ESCCState;
+};
 
 #endif
diff --git a/include/hw/char/ibex_uart.h b/include/hw/char/ibex_uart.h
index b6bd5a6700..36eb75fc4c 100644
--- a/include/hw/char/ibex_uart.h
+++ b/include/hw/char/ibex_uart.h
@@ -29,6 +29,7 @@
 #include "hw/registerfields.h"
 #include "chardev/char-fe.h"
 #include "qemu/timer.h"
+#include "qom/object.h"
 
 REG32(INTR_STATE, 0x00)
     FIELD(INTR_STATE, TX_WATERMARK, 0, 1)
@@ -69,10 +70,11 @@ REG32(TIMEOUT_CTRL, 0x2c)
 #define IBEX_UART_CLOCK 50000000 /* 50MHz clock */
 
 #define TYPE_IBEX_UART "ibex-uart"
-#define IBEX_UART(obj) \
-    OBJECT_CHECK(IbexUartState, (obj), TYPE_IBEX_UART)
+typedef struct IbexUartState IbexUartState;
+DECLARE_INSTANCE_CHECKER(IbexUartState, IBEX_UART,
+                         TYPE_IBEX_UART)
 
-typedef struct {
+struct IbexUartState {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -103,5 +105,5 @@ typedef struct {
     qemu_irq rx_watermark;
     qemu_irq tx_empty;
     qemu_irq rx_overflow;
-} IbexUartState;
+};
 #endif /* HW_IBEX_UART_H */
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
index c8b74284f8..200f1ec33a 100644
--- a/include/hw/char/imx_serial.h
+++ b/include/hw/char/imx_serial.h
@@ -20,9 +20,12 @@
 
 #include "hw/sysbus.h"
 #include "chardev/char-fe.h"
+#include "qom/object.h"
 
 #define TYPE_IMX_SERIAL "imx.serial"
-#define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL)
+typedef struct IMXSerialState IMXSerialState;
+DECLARE_INSTANCE_CHECKER(IMXSerialState, IMX_SERIAL,
+                         TYPE_IMX_SERIAL)
 
 #define URXD_CHARRDY    (1<<15)   /* character read is valid */
 #define URXD_ERR        (1<<14)   /* Character has error */
@@ -76,7 +79,7 @@
 #define UTS1_TXFULL     (1<<4)
 #define UTS1_RXFULL     (1<<3)
 
-typedef struct IMXSerialState {
+struct IMXSerialState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -103,6 +106,6 @@ typedef struct IMXSerialState {
 
     qemu_irq irq;
     CharBackend chr;
-} IMXSerialState;
+};
 
 #endif
diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h
index eb1c15b490..0cf3c4e328 100644
--- a/include/hw/char/nrf51_uart.h
+++ b/include/hw/char/nrf51_uart.h
@@ -14,12 +14,15 @@
 #include "hw/sysbus.h"
 #include "chardev/char-fe.h"
 #include "hw/registerfields.h"
+#include "qom/object.h"
 
 #define UART_FIFO_LENGTH 6
 #define UART_SIZE 0x1000
 
 #define TYPE_NRF51_UART "nrf51_soc.uart"
-#define NRF51_UART(obj) OBJECT_CHECK(NRF51UARTState, (obj), TYPE_NRF51_UART)
+typedef struct NRF51UARTState NRF51UARTState;
+DECLARE_INSTANCE_CHECKER(NRF51UARTState, NRF51_UART,
+                         TYPE_NRF51_UART)
 
 REG32(UART_STARTRX, 0x000)
 REG32(UART_STOPRX, 0x004)
@@ -54,7 +57,7 @@ REG32(UART_TXD, 0x51C)
 REG32(UART_BAUDRATE, 0x524)
 REG32(UART_CONFIG, 0x56C)
 
-typedef struct NRF51UARTState {
+struct NRF51UARTState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -72,6 +75,6 @@ typedef struct NRF51UARTState {
     bool tx_started;
     bool pending_tx_byte;
     bool enabled;
-} NRF51UARTState;
+};
 
 #endif
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
index bed758350f..80de4ecde6 100644
--- a/include/hw/char/pl011.h
+++ b/include/hw/char/pl011.h
@@ -19,14 +19,17 @@
 #include "hw/sysbus.h"
 #include "chardev/char-fe.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 #define TYPE_PL011 "pl011"
-#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
+typedef struct PL011State PL011State;
+DECLARE_INSTANCE_CHECKER(PL011State, PL011,
+                         TYPE_PL011)
 
 /* This shares the same struct (and cast macro) as the base pl011 device */
 #define TYPE_PL011_LUMINARY "pl011_luminary"
 
-typedef struct PL011State {
+struct PL011State {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -49,7 +52,7 @@ typedef struct PL011State {
     CharBackend chr;
     qemu_irq irq[6];
     const unsigned char *id;
-} PL011State;
+};
 
 static inline DeviceState *pl011_create(hwaddr addr,
                                         qemu_irq irq,
diff --git a/include/hw/char/renesas_sci.h b/include/hw/char/renesas_sci.h
index efdebc620a..a4764e3eee 100644
--- a/include/hw/char/renesas_sci.h
+++ b/include/hw/char/renesas_sci.h
@@ -11,9 +11,12 @@
 
 #include "chardev/char-fe.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_RENESAS_SCI "renesas-sci"
-#define RSCI(obj) OBJECT_CHECK(RSCIState, (obj), TYPE_RENESAS_SCI)
+typedef struct RSCIState RSCIState;
+DECLARE_INSTANCE_CHECKER(RSCIState, RSCI,
+                         TYPE_RENESAS_SCI)
 
 enum {
     ERI = 0,
@@ -23,7 +26,7 @@ enum {
     SCI_NR_IRQ = 4
 };
 
-typedef struct {
+struct RSCIState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -46,6 +49,6 @@ typedef struct {
     int64_t trtime;
     int64_t rx_next;
     uint64_t input_freq;
-} RSCIState;
+};
 
 #endif
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
index 535fa23a2b..264f529a7f 100644
--- a/include/hw/char/serial.h
+++ b/include/hw/char/serial.h
@@ -31,10 +31,11 @@
 #include "qemu/fifo8.h"
 #include "chardev/char.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define UART_FIFO_LENGTH    16      /* 16550A Fifo Length */
 
-typedef struct SerialState {
+struct SerialState {
     DeviceState parent;
 
     uint16_t divider;
@@ -77,22 +78,25 @@ typedef struct SerialState {
 
     QEMUTimer *modem_status_poll;
     MemoryRegion io;
-} SerialState;
+};
+typedef struct SerialState SerialState;
 
-typedef struct SerialMM {
+struct SerialMM {
     SysBusDevice parent;
 
     SerialState serial;
 
     uint8_t regshift;
     uint8_t endianness;
-} SerialMM;
+};
+typedef struct SerialMM SerialMM;
 
-typedef struct SerialIO {
+struct SerialIO {
     SysBusDevice parent;
 
     SerialState serial;
-} SerialIO;
+};
+typedef struct SerialIO SerialIO;
 
 extern const VMStateDescription vmstate_serial;
 extern const MemoryRegionOps serial_io_ops;
@@ -100,13 +104,16 @@ extern const MemoryRegionOps serial_io_ops;
 void serial_set_frequency(SerialState *s, uint32_t frequency);
 
 #define TYPE_SERIAL "serial"
-#define SERIAL(s) OBJECT_CHECK(SerialState, (s), TYPE_SERIAL)
+DECLARE_INSTANCE_CHECKER(SerialState, SERIAL,
+                         TYPE_SERIAL)
 
 #define TYPE_SERIAL_MM "serial-mm"
-#define SERIAL_MM(s) OBJECT_CHECK(SerialMM, (s), TYPE_SERIAL_MM)
+DECLARE_INSTANCE_CHECKER(SerialMM, SERIAL_MM,
+                         TYPE_SERIAL_MM)
 
 #define TYPE_SERIAL_IO "serial-io"
-#define SERIAL_IO(s) OBJECT_CHECK(SerialIO, (s), TYPE_SERIAL_IO)
+DECLARE_INSTANCE_CHECKER(SerialIO, SERIAL_IO,
+                         TYPE_SERIAL_IO)
 
 SerialMM *serial_mm_init(MemoryRegion *address_space,
                          hwaddr base, int regshift,
diff --git a/include/hw/char/stm32f2xx_usart.h b/include/hw/char/stm32f2xx_usart.h
index 8e112671e3..1670c076d4 100644
--- a/include/hw/char/stm32f2xx_usart.h
+++ b/include/hw/char/stm32f2xx_usart.h
@@ -27,6 +27,7 @@
 
 #include "hw/sysbus.h"
 #include "chardev/char-fe.h"
+#include "qom/object.h"
 
 #define USART_SR   0x00
 #define USART_DR   0x04
@@ -53,10 +54,11 @@
 #define USART_CR1_RE  (1 << 2)
 
 #define TYPE_STM32F2XX_USART "stm32f2xx-usart"
-#define STM32F2XX_USART(obj) \
-    OBJECT_CHECK(STM32F2XXUsartState, (obj), TYPE_STM32F2XX_USART)
+typedef struct STM32F2XXUsartState STM32F2XXUsartState;
+DECLARE_INSTANCE_CHECKER(STM32F2XXUsartState, STM32F2XX_USART,
+                         TYPE_STM32F2XX_USART)
 
-typedef struct {
+struct STM32F2XXUsartState {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -73,5 +75,5 @@ typedef struct {
 
     CharBackend chr;
     qemu_irq irq;
-} STM32F2XXUsartState;
+};
 #endif /* HW_STM32F2XX_USART_H */
diff --git a/include/hw/clock.h b/include/hw/clock.h
index 9ecd78b2c3..b524509b47 100644
--- a/include/hw/clock.h
+++ b/include/hw/clock.h
@@ -18,7 +18,9 @@
 #include "qemu/queue.h"
 
 #define TYPE_CLOCK "clock"
-#define CLOCK(obj) OBJECT_CHECK(Clock, (obj), TYPE_CLOCK)
+typedef struct Clock Clock;
+DECLARE_INSTANCE_CHECKER(Clock, CLOCK,
+                         TYPE_CLOCK)
 
 typedef void ClockCallback(void *opaque);
 
@@ -54,7 +56,6 @@ typedef void ClockCallback(void *opaque);
  * @sibling: structure used to form a clock list
  */
 
-typedef struct Clock Clock;
 
 struct Clock {
     /*< private >*/
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 9fc2696db5..99dc33ffeb 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -30,6 +30,7 @@
 #include "qemu/queue.h"
 #include "qemu/thread.h"
 #include "qemu/plugin.h"
+#include "qom/object.h"
 
 typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
                                      void *opaque);
@@ -61,8 +62,9 @@ typedef uint64_t vaddr;
  */
 #define CPU(obj) ((CPUState *)(obj))
 
-#define CPU_CLASS(class) OBJECT_CLASS_CHECK(CPUClass, (class), TYPE_CPU)
-#define CPU_GET_CLASS(obj) OBJECT_GET_CLASS(CPUClass, (obj), TYPE_CPU)
+typedef struct CPUClass CPUClass;
+DECLARE_CLASS_CHECKERS(CPUClass, CPU,
+                       TYPE_CPU)
 
 typedef enum MMUAccessType {
     MMU_DATA_LOAD  = 0,
@@ -156,7 +158,7 @@ struct TranslationBlock;
  *
  * Represents a CPU family or model.
  */
-typedef struct CPUClass {
+struct CPUClass {
     /*< private >*/
     DeviceClass parent_class;
     /*< public >*/
@@ -222,7 +224,7 @@ typedef struct CPUClass {
     /* Keep non-pointer data at the end to minimize holes.  */
     int gdb_num_core_regs;
     bool gdb_stop_before_watchpoint;
-} CPUClass;
+};
 
 /*
  * Low 16 bits: number of cycles left, used only in icount mode.
diff --git a/include/hw/core/generic-loader.h b/include/hw/core/generic-loader.h
index 9ffce1c5a3..8e86532df6 100644
--- a/include/hw/core/generic-loader.h
+++ b/include/hw/core/generic-loader.h
@@ -20,8 +20,9 @@
 
 #include "elf.h"
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
-typedef struct GenericLoaderState {
+struct GenericLoaderState {
     /* <private> */
     DeviceState parent_obj;
 
@@ -38,10 +39,11 @@ typedef struct GenericLoaderState {
     bool force_raw;
     bool data_be;
     bool set_pc;
-} GenericLoaderState;
+};
+typedef struct GenericLoaderState GenericLoaderState;
 
 #define TYPE_GENERIC_LOADER "loader"
-#define GENERIC_LOADER(obj) OBJECT_CHECK(GenericLoaderState, (obj), \
-                                         TYPE_GENERIC_LOADER)
+DECLARE_INSTANCE_CHECKER(GenericLoaderState, GENERIC_LOADER,
+                         TYPE_GENERIC_LOADER)
 
 #endif
diff --git a/include/hw/core/split-irq.h b/include/hw/core/split-irq.h
index 872a39aa4f..76d42b29aa 100644
--- a/include/hw/core/split-irq.h
+++ b/include/hw/core/split-irq.h
@@ -44,7 +44,8 @@
 
 typedef struct SplitIRQ SplitIRQ;
 
-#define SPLIT_IRQ(obj) OBJECT_CHECK(SplitIRQ, (obj), TYPE_SPLIT_IRQ)
+DECLARE_INSTANCE_CHECKER(SplitIRQ, SPLIT_IRQ,
+                         TYPE_SPLIT_IRQ)
 
 struct SplitIRQ {
     DeviceState parent_obj;
diff --git a/include/hw/cpu/a15mpcore.h b/include/hw/cpu/a15mpcore.h
index b423533d20..58d8ac7415 100644
--- a/include/hw/cpu/a15mpcore.h
+++ b/include/hw/cpu/a15mpcore.h
@@ -22,14 +22,16 @@
 
 #include "hw/sysbus.h"
 #include "hw/intc/arm_gic.h"
+#include "qom/object.h"
 
 /* A15MP private memory region.  */
 
 #define TYPE_A15MPCORE_PRIV "a15mpcore_priv"
-#define A15MPCORE_PRIV(obj) \
-    OBJECT_CHECK(A15MPPrivState, (obj), TYPE_A15MPCORE_PRIV)
+typedef struct A15MPPrivState A15MPPrivState;
+DECLARE_INSTANCE_CHECKER(A15MPPrivState, A15MPCORE_PRIV,
+                         TYPE_A15MPCORE_PRIV)
 
-typedef struct A15MPPrivState {
+struct A15MPPrivState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -39,6 +41,6 @@ typedef struct A15MPPrivState {
     MemoryRegion container;
 
     GICState gic;
-} A15MPPrivState;
+};
 
 #endif
diff --git a/include/hw/cpu/a9mpcore.h b/include/hw/cpu/a9mpcore.h
index 5d67ca22c4..37e5cfce08 100644
--- a/include/hw/cpu/a9mpcore.h
+++ b/include/hw/cpu/a9mpcore.h
@@ -15,12 +15,14 @@
 #include "hw/misc/a9scu.h"
 #include "hw/timer/arm_mptimer.h"
 #include "hw/timer/a9gtimer.h"
+#include "qom/object.h"
 
 #define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
-#define A9MPCORE_PRIV(obj) \
-    OBJECT_CHECK(A9MPPrivState, (obj), TYPE_A9MPCORE_PRIV)
+typedef struct A9MPPrivState A9MPPrivState;
+DECLARE_INSTANCE_CHECKER(A9MPPrivState, A9MPCORE_PRIV,
+                         TYPE_A9MPCORE_PRIV)
 
-typedef struct A9MPPrivState {
+struct A9MPPrivState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -34,6 +36,6 @@ typedef struct A9MPPrivState {
     A9GTimerState gtimer;
     ARMMPTimerState mptimer;
     ARMMPTimerState wdt;
-} A9MPPrivState;
+};
 
 #endif
diff --git a/include/hw/cpu/arm11mpcore.h b/include/hw/cpu/arm11mpcore.h
index 6196109ca2..411d7e6659 100644
--- a/include/hw/cpu/arm11mpcore.h
+++ b/include/hw/cpu/arm11mpcore.h
@@ -14,12 +14,14 @@
 #include "hw/misc/arm11scu.h"
 #include "hw/intc/arm_gic.h"
 #include "hw/timer/arm_mptimer.h"
+#include "qom/object.h"
 
 #define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv"
-#define ARM11MPCORE_PRIV(obj) \
-    OBJECT_CHECK(ARM11MPCorePriveState, (obj), TYPE_ARM11MPCORE_PRIV)
+typedef struct ARM11MPCorePriveState ARM11MPCorePriveState;
+DECLARE_INSTANCE_CHECKER(ARM11MPCorePriveState, ARM11MPCORE_PRIV,
+                         TYPE_ARM11MPCORE_PRIV)
 
-typedef struct ARM11MPCorePriveState {
+struct ARM11MPCorePriveState {
     SysBusDevice parent_obj;
 
     uint32_t num_cpu;
@@ -30,6 +32,6 @@ typedef struct ARM11MPCorePriveState {
     GICState gic;
     ARMMPTimerState mptimer;
     ARMMPTimerState wdtimer;
-} ARM11MPCorePriveState;
+};
 
 #endif
diff --git a/include/hw/cpu/cluster.h b/include/hw/cpu/cluster.h
index a616501a55..1c807c5902 100644
--- a/include/hw/cpu/cluster.h
+++ b/include/hw/cpu/cluster.h
@@ -21,6 +21,7 @@
 #define HW_CPU_CLUSTER_H
 
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 /*
  * CPU Cluster type
@@ -54,8 +55,9 @@
  */
 
 #define TYPE_CPU_CLUSTER "cpu-cluster"
-#define CPU_CLUSTER(obj) \
-    OBJECT_CHECK(CPUClusterState, (obj), TYPE_CPU_CLUSTER)
+typedef struct CPUClusterState CPUClusterState;
+DECLARE_INSTANCE_CHECKER(CPUClusterState, CPU_CLUSTER,
+                         TYPE_CPU_CLUSTER)
 
 /*
  * This limit is imposed by TCG, which puts the cluster ID into an
@@ -70,12 +72,12 @@
  *
  * State of a CPU cluster.
  */
-typedef struct CPUClusterState {
+struct CPUClusterState {
     /*< private >*/
     DeviceState parent_obj;
 
     /*< public >*/
     uint32_t cluster_id;
-} CPUClusterState;
+};
 
 #endif
diff --git a/include/hw/cpu/core.h b/include/hw/cpu/core.h
index 555ad831bb..61ea3481f8 100644
--- a/include/hw/cpu/core.h
+++ b/include/hw/cpu/core.h
@@ -10,20 +10,22 @@
 #define HW_CPU_CORE_H
 
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 #define TYPE_CPU_CORE "cpu-core"
 
-#define CPU_CORE(obj) \
-    OBJECT_CHECK(CPUCore, (obj), TYPE_CPU_CORE)
+typedef struct CPUCore CPUCore;
+DECLARE_INSTANCE_CHECKER(CPUCore, CPU_CORE,
+                         TYPE_CPU_CORE)
 
-typedef struct CPUCore {
+struct CPUCore {
     /*< private >*/
     DeviceState parent_obj;
 
     /*< public >*/
     int core_id;
     int nr_threads;
-} CPUCore;
+};
 
 /* Note: topology field names need to be kept in sync with
  * 'CpuInstanceProperties' */
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
index 2246be74d8..226d77a264 100644
--- a/include/hw/display/bcm2835_fb.h
+++ b/include/hw/display/bcm2835_fb.h
@@ -14,9 +14,12 @@
 
 #include "hw/sysbus.h"
 #include "ui/console.h"
+#include "qom/object.h"
 
 #define TYPE_BCM2835_FB "bcm2835-fb"
-#define BCM2835_FB(obj) OBJECT_CHECK(BCM2835FBState, (obj), TYPE_BCM2835_FB)
+typedef struct BCM2835FBState BCM2835FBState;
+DECLARE_INSTANCE_CHECKER(BCM2835FBState, BCM2835_FB,
+                         TYPE_BCM2835_FB)
 
 /*
  * Configuration information about the fb which the guest can program
@@ -32,7 +35,7 @@ typedef struct {
     uint32_t alpha;
 } BCM2835FBConfig;
 
-typedef struct {
+struct BCM2835FBState {
     /*< private >*/
     SysBusDevice busdev;
     /*< public >*/
@@ -49,7 +52,7 @@ typedef struct {
 
     BCM2835FBConfig config;
     BCM2835FBConfig initial_config;
-} BCM2835FBState;
+};
 
 void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
 
diff --git a/include/hw/display/dpcd.h b/include/hw/display/dpcd.h
index 6880ee36a3..09304dd1f6 100644
--- a/include/hw/display/dpcd.h
+++ b/include/hw/display/dpcd.h
@@ -24,11 +24,13 @@
 
 #ifndef DPCD_H
 #define DPCD_H
+#include "qom/object.h"
 
 typedef struct DPCDState DPCDState;
 
 #define TYPE_DPCD "dpcd"
-#define DPCD(obj) OBJECT_CHECK(DPCDState, (obj), TYPE_DPCD)
+DECLARE_INSTANCE_CHECKER(DPCDState, DPCD,
+                         TYPE_DPCD)
 
 /* DCPD Revision. */
 #define DPCD_REVISION                           0x00
diff --git a/include/hw/display/i2c-ddc.h b/include/hw/display/i2c-ddc.h
index 1cf53a0c8d..fbabfea5a9 100644
--- a/include/hw/display/i2c-ddc.h
+++ b/include/hw/display/i2c-ddc.h
@@ -21,6 +21,7 @@
 
 #include "hw/display/edid.h"
 #include "hw/i2c/i2c.h"
+#include "qom/object.h"
 
 /* A simple I2C slave which just returns the contents of its EDID blob. */
 struct I2CDDCState {
@@ -36,6 +37,7 @@ struct I2CDDCState {
 typedef struct I2CDDCState I2CDDCState;
 
 #define TYPE_I2CDDC "i2c-ddc"
-#define I2CDDC(obj) OBJECT_CHECK(I2CDDCState, (obj), TYPE_I2CDDC)
+DECLARE_INSTANCE_CHECKER(I2CDDCState, I2CDDC,
+                         TYPE_I2CDDC)
 
 #endif /* I2C_DDC_H */
diff --git a/include/hw/display/macfb.h b/include/hw/display/macfb.h
index 347871b623..0960480b75 100644
--- a/include/hw/display/macfb.h
+++ b/include/hw/display/macfb.h
@@ -16,6 +16,7 @@
 #include "qemu/osdep.h"
 #include "exec/memory.h"
 #include "ui/console.h"
+#include "qom/object.h"
 
 typedef struct MacfbState {
     MemoryRegion mem_vram;
@@ -31,34 +32,33 @@ typedef struct MacfbState {
 } MacfbState;
 
 #define TYPE_MACFB "sysbus-macfb"
-#define MACFB(obj) \
-    OBJECT_CHECK(MacfbSysBusState, (obj), TYPE_MACFB)
+typedef struct MacfbSysBusState MacfbSysBusState;
+DECLARE_INSTANCE_CHECKER(MacfbSysBusState, MACFB,
+                         TYPE_MACFB)
 
-typedef struct {
+struct MacfbSysBusState {
     SysBusDevice busdev;
 
     MacfbState macfb;
-} MacfbSysBusState;
+};
 
-#define NUBUS_MACFB_CLASS(class) \
-    OBJECT_CLASS_CHECK(MacfbNubusDeviceClass, (class), TYPE_NUBUS_MACFB)
-#define NUBUS_MACFB_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(MacfbNubusDeviceClass, (obj), TYPE_NUBUS_MACFB)
+#define TYPE_NUBUS_MACFB "nubus-macfb"
+typedef struct MacfbNubusDeviceClass MacfbNubusDeviceClass;
+typedef struct MacfbNubusState MacfbNubusState;
+DECLARE_OBJ_CHECKERS(MacfbNubusState, MacfbNubusDeviceClass,
+                     NUBUS_MACFB, TYPE_NUBUS_MACFB)
 
-typedef struct MacfbNubusDeviceClass {
+struct MacfbNubusDeviceClass {
     DeviceClass parent_class;
 
     DeviceRealize parent_realize;
-} MacfbNubusDeviceClass;
+};
 
-#define TYPE_NUBUS_MACFB "nubus-macfb"
-#define NUBUS_MACFB(obj) \
-    OBJECT_CHECK(MacfbNubusState, (obj), TYPE_NUBUS_MACFB)
 
-typedef struct {
+struct MacfbNubusState {
     NubusDevice busdev;
 
     MacfbState macfb;
-} MacfbNubusState;
+};
 
 #endif
diff --git a/include/hw/display/xlnx_dp.h b/include/hw/display/xlnx_dp.h
index ab0dd250cc..3b7d9e5a2a 100644
--- a/include/hw/display/xlnx_dp.h
+++ b/include/hw/display/xlnx_dp.h
@@ -34,6 +34,7 @@
 #include "qemu/units.h"
 #include "hw/dma/xlnx_dpdma.h"
 #include "audio/audio.h"
+#include "qom/object.h"
 
 #define AUD_CHBUF_MAX_DEPTH                 (32 * KiB)
 #define MAX_QEMU_BUFFER_SIZE                (4 * KiB)
@@ -48,7 +49,7 @@ struct PixmanPlane {
     DisplaySurface *surface;
 };
 
-typedef struct XlnxDPState {
+struct XlnxDPState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -101,9 +102,11 @@ typedef struct XlnxDPState {
      */
     DPCDState *dpcd;
     I2CDDCState *edid;
-} XlnxDPState;
+};
+typedef struct XlnxDPState XlnxDPState;
 
 #define TYPE_XLNX_DP "xlnx.v-dp"
-#define XLNX_DP(obj) OBJECT_CHECK(XlnxDPState, (obj), TYPE_XLNX_DP)
+DECLARE_INSTANCE_CHECKER(XlnxDPState, XLNX_DP,
+                         TYPE_XLNX_DP)
 
 #endif
diff --git a/include/hw/dma/bcm2835_dma.h b/include/hw/dma/bcm2835_dma.h
index a6747842b7..b94dae779a 100644
--- a/include/hw/dma/bcm2835_dma.h
+++ b/include/hw/dma/bcm2835_dma.h
@@ -9,6 +9,7 @@
 #define BCM2835_DMA_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 typedef struct {
     uint32_t cs;
@@ -25,12 +26,13 @@ typedef struct {
 } BCM2835DMAChan;
 
 #define TYPE_BCM2835_DMA "bcm2835-dma"
-#define BCM2835_DMA(obj) \
-        OBJECT_CHECK(BCM2835DMAState, (obj), TYPE_BCM2835_DMA)
+typedef struct BCM2835DMAState BCM2835DMAState;
+DECLARE_INSTANCE_CHECKER(BCM2835DMAState, BCM2835_DMA,
+                         TYPE_BCM2835_DMA)
 
 #define BCM2835_DMA_NCHANS 16
 
-typedef struct {
+struct BCM2835DMAState {
     /*< private >*/
     SysBusDevice busdev;
     /*< public >*/
@@ -42,6 +44,6 @@ typedef struct {
     BCM2835DMAChan chan[BCM2835_DMA_NCHANS];
     uint32_t int_status;
     uint32_t enable;
-} BCM2835DMAState;
+};
 
 #endif
diff --git a/include/hw/dma/i8257.h b/include/hw/dma/i8257.h
index ee06371699..362ce7b8dc 100644
--- a/include/hw/dma/i8257.h
+++ b/include/hw/dma/i8257.h
@@ -3,10 +3,12 @@
 
 #include "hw/isa/isa.h"
 #include "exec/ioport.h"
+#include "qom/object.h"
 
 #define TYPE_I8257 "i8257"
-#define I8257(obj) \
-    OBJECT_CHECK(I8257State, (obj), TYPE_I8257)
+typedef struct I8257State I8257State;
+DECLARE_INSTANCE_CHECKER(I8257State, I8257,
+                         TYPE_I8257)
 
 typedef struct I8257Regs {
     int now[2];
@@ -20,7 +22,7 @@ typedef struct I8257Regs {
     void *opaque;
 } I8257Regs;
 
-typedef struct I8257State {
+struct I8257State {
     /* <private> */
     ISADevice parent_obj;
 
@@ -43,7 +45,7 @@ typedef struct I8257State {
     int running;
     PortioList portio_page;
     PortioList portio_pageh;
-} I8257State;
+};
 
 void i8257_dma_init(ISABus *bus, bool high_page_enable);
 
diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h
index 9d4b3df143..e9669bf5ae 100644
--- a/include/hw/dma/pl080.h
+++ b/include/hw/dma/pl080.h
@@ -29,6 +29,7 @@
 #define HW_DMA_PL080_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define PL080_MAX_CHANNELS 8
 
@@ -42,9 +43,11 @@ typedef struct {
 
 #define TYPE_PL080 "pl080"
 #define TYPE_PL081 "pl081"
-#define PL080(obj) OBJECT_CHECK(PL080State, (obj), TYPE_PL080)
+typedef struct PL080State PL080State;
+DECLARE_INSTANCE_CHECKER(PL080State, PL080,
+                         TYPE_PL080)
 
-typedef struct PL080State {
+struct PL080State {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -66,6 +69,6 @@ typedef struct PL080State {
 
     MemoryRegion *downstream;
     AddressSpace downstream_as;
-} PL080State;
+};
 
 #endif
diff --git a/include/hw/dma/xlnx-zdma.h b/include/hw/dma/xlnx-zdma.h
index 0b240b4c3c..f638abe568 100644
--- a/include/hw/dma/xlnx-zdma.h
+++ b/include/hw/dma/xlnx-zdma.h
@@ -32,6 +32,7 @@
 #include "hw/sysbus.h"
 #include "hw/register.h"
 #include "sysemu/dma.h"
+#include "qom/object.h"
 
 #define ZDMA_R_MAX (0x204 / 4)
 
@@ -50,7 +51,7 @@ typedef union {
     uint32_t words[4];
 } XlnxZDMADescr;
 
-typedef struct XlnxZDMA {
+struct XlnxZDMA {
     SysBusDevice parent_obj;
     MemoryRegion iomem;
     MemTxAttrs attr;
@@ -74,11 +75,12 @@ typedef struct XlnxZDMA {
     /* We don't model the common bufs. Must be at least 16 bytes
        to model write only mode.  */
     uint8_t buf[2048];
-} XlnxZDMA;
+};
+typedef struct XlnxZDMA XlnxZDMA;
 
 #define TYPE_XLNX_ZDMA "xlnx.zdma"
 
-#define XLNX_ZDMA(obj) \
-     OBJECT_CHECK(XlnxZDMA, (obj), TYPE_XLNX_ZDMA)
+DECLARE_INSTANCE_CHECKER(XlnxZDMA, XLNX_ZDMA,
+                         TYPE_XLNX_ZDMA)
 
 #endif /* XLNX_ZDMA_H */
diff --git a/include/hw/dma/xlnx-zynq-devcfg.h b/include/hw/dma/xlnx-zynq-devcfg.h
index 1d3969d91f..e16b08f9c5 100644
--- a/include/hw/dma/xlnx-zynq-devcfg.h
+++ b/include/hw/dma/xlnx-zynq-devcfg.h
@@ -29,11 +29,13 @@
 
 #include "hw/register.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_XLNX_ZYNQ_DEVCFG "xlnx.ps7-dev-cfg"
 
-#define XLNX_ZYNQ_DEVCFG(obj) \
-    OBJECT_CHECK(XlnxZynqDevcfg, (obj), TYPE_XLNX_ZYNQ_DEVCFG)
+typedef struct XlnxZynqDevcfg XlnxZynqDevcfg;
+DECLARE_INSTANCE_CHECKER(XlnxZynqDevcfg, XLNX_ZYNQ_DEVCFG,
+                         TYPE_XLNX_ZYNQ_DEVCFG)
 
 #define XLNX_ZYNQ_DEVCFG_R_MAX (0x100 / 4)
 
@@ -46,7 +48,7 @@ typedef struct XlnxZynqDevcfgDMACmd {
     uint32_t dest_len;
 } XlnxZynqDevcfgDMACmd;
 
-typedef struct XlnxZynqDevcfg {
+struct XlnxZynqDevcfg {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -57,6 +59,6 @@ typedef struct XlnxZynqDevcfg {
 
     uint32_t regs[XLNX_ZYNQ_DEVCFG_R_MAX];
     RegisterInfo regs_info[XLNX_ZYNQ_DEVCFG_R_MAX];
-} XlnxZynqDevcfg;
+};
 
 #endif
diff --git a/include/hw/dma/xlnx_dpdma.h b/include/hw/dma/xlnx_dpdma.h
index 7a304a5bb4..94b01cad0a 100644
--- a/include/hw/dma/xlnx_dpdma.h
+++ b/include/hw/dma/xlnx_dpdma.h
@@ -28,6 +28,7 @@
 #include "hw/sysbus.h"
 #include "ui/console.h"
 #include "sysemu/dma.h"
+#include "qom/object.h"
 
 #define XLNX_DPDMA_REG_ARRAY_SIZE (0x1000 >> 2)
 
@@ -45,7 +46,8 @@ struct XlnxDPDMAState {
 typedef struct XlnxDPDMAState XlnxDPDMAState;
 
 #define TYPE_XLNX_DPDMA "xlnx.dpdma"
-#define XLNX_DPDMA(obj) OBJECT_CHECK(XlnxDPDMAState, (obj), TYPE_XLNX_DPDMA)
+DECLARE_INSTANCE_CHECKER(XlnxDPDMAState, XLNX_DPDMA,
+                         TYPE_XLNX_DPDMA)
 
 /*
  * xlnx_dpdma_start_operation: Start the operation on the specified channel. The
diff --git a/include/hw/fw-path-provider.h b/include/hw/fw-path-provider.h
index 10d1bd4959..8e1d45651c 100644
--- a/include/hw/fw-path-provider.h
+++ b/include/hw/fw-path-provider.h
@@ -22,20 +22,19 @@
 
 #define TYPE_FW_PATH_PROVIDER "fw-path-provider"
 
-#define FW_PATH_PROVIDER_CLASS(klass) \
-     OBJECT_CLASS_CHECK(FWPathProviderClass, (klass), TYPE_FW_PATH_PROVIDER)
-#define FW_PATH_PROVIDER_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(FWPathProviderClass, (obj), TYPE_FW_PATH_PROVIDER)
+typedef struct FWPathProviderClass FWPathProviderClass;
+DECLARE_CLASS_CHECKERS(FWPathProviderClass, FW_PATH_PROVIDER,
+                       TYPE_FW_PATH_PROVIDER)
 #define FW_PATH_PROVIDER(obj) \
      INTERFACE_CHECK(FWPathProvider, (obj), TYPE_FW_PATH_PROVIDER)
 
 typedef struct FWPathProvider FWPathProvider;
 
-typedef struct FWPathProviderClass {
+struct FWPathProviderClass {
     InterfaceClass parent_class;
 
     char *(*get_dev_path)(FWPathProvider *p, BusState *bus, DeviceState *dev);
-} FWPathProviderClass;
+};
 
 char *fw_path_provider_get_dev_path(FWPathProvider *p, BusState *bus,
                                     DeviceState *dev);
diff --git a/include/hw/gpio/aspeed_gpio.h b/include/hw/gpio/aspeed_gpio.h
index a2deac046a..2582e6e0dc 100644
--- a/include/hw/gpio/aspeed_gpio.h
+++ b/include/hw/gpio/aspeed_gpio.h
@@ -11,13 +11,13 @@
 #define ASPEED_GPIO_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_ASPEED_GPIO "aspeed.gpio"
-#define ASPEED_GPIO(obj) OBJECT_CHECK(AspeedGPIOState, (obj), TYPE_ASPEED_GPIO)
-#define ASPEED_GPIO_CLASS(klass) \
-     OBJECT_CLASS_CHECK(AspeedGPIOClass, (klass), TYPE_ASPEED_GPIO)
-#define ASPEED_GPIO_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(AspeedGPIOClass, (obj), TYPE_ASPEED_GPIO)
+typedef struct AspeedGPIOClass AspeedGPIOClass;
+typedef struct AspeedGPIOState AspeedGPIOState;
+DECLARE_OBJ_CHECKERS(AspeedGPIOState, AspeedGPIOClass,
+                     ASPEED_GPIO, TYPE_ASPEED_GPIO)
 
 #define ASPEED_GPIO_MAX_NR_SETS 8
 #define ASPEED_REGS_PER_BANK 14
@@ -58,16 +58,16 @@ typedef struct AspeedGPIOReg {
     enum GPIORegType type;
  } AspeedGPIOReg;
 
-typedef struct  AspeedGPIOClass {
+struct AspeedGPIOClass {
     SysBusDevice parent_obj;
     const GPIOSetProperties *props;
     uint32_t nr_gpio_pins;
     uint32_t nr_gpio_sets;
     uint32_t gap;
     const AspeedGPIOReg *reg_table;
-}  AspeedGPIOClass;
+};
 
-typedef struct AspeedGPIOState {
+struct AspeedGPIOState {
     /* <private> */
     SysBusDevice parent;
 
@@ -95,6 +95,6 @@ typedef struct AspeedGPIOState {
         uint32_t debounce_2;
         uint32_t input_mask;
     } sets[ASPEED_GPIO_MAX_NR_SETS];
-} AspeedGPIOState;
+};
 
 #endif /* _ASPEED_GPIO_H_ */
diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h
index b0de0a3c74..e06e08a0fe 100644
--- a/include/hw/gpio/bcm2835_gpio.h
+++ b/include/hw/gpio/bcm2835_gpio.h
@@ -16,8 +16,9 @@
 
 #include "hw/sd/sd.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
-typedef struct BCM2835GpioState {
+struct BCM2835GpioState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -31,10 +32,11 @@ typedef struct BCM2835GpioState {
     uint32_t lev0, lev1;
     uint8_t sd_fsel;
     qemu_irq out[54];
-} BCM2835GpioState;
+};
+typedef struct BCM2835GpioState BCM2835GpioState;
 
 #define TYPE_BCM2835_GPIO "bcm2835_gpio"
-#define BCM2835_GPIO(obj) \
-    OBJECT_CHECK(BCM2835GpioState, (obj), TYPE_BCM2835_GPIO)
+DECLARE_INSTANCE_CHECKER(BCM2835GpioState, BCM2835_GPIO,
+                         TYPE_BCM2835_GPIO)
 
 #endif
diff --git a/include/hw/gpio/imx_gpio.h b/include/hw/gpio/imx_gpio.h
index ffab437f23..a72b272ace 100644
--- a/include/hw/gpio/imx_gpio.h
+++ b/include/hw/gpio/imx_gpio.h
@@ -21,9 +21,12 @@
 #define IMX_GPIO_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_IMX_GPIO "imx.gpio"
-#define IMX_GPIO(obj) OBJECT_CHECK(IMXGPIOState, (obj), TYPE_IMX_GPIO)
+typedef struct IMXGPIOState IMXGPIOState;
+DECLARE_INSTANCE_CHECKER(IMXGPIOState, IMX_GPIO,
+                         TYPE_IMX_GPIO)
 
 #define IMX_GPIO_MEM_SIZE 0x20
 
@@ -39,7 +42,7 @@
 
 #define IMX_GPIO_PIN_COUNT 32
 
-typedef struct IMXGPIOState {
+struct IMXGPIOState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -58,6 +61,6 @@ typedef struct IMXGPIOState {
 
     qemu_irq irq[2];
     qemu_irq output[IMX_GPIO_PIN_COUNT];
-} IMXGPIOState;
+};
 
 #endif /* IMX_GPIO_H */
diff --git a/include/hw/gpio/nrf51_gpio.h b/include/hw/gpio/nrf51_gpio.h
index 1d62bbc928..55d7d24a52 100644
--- a/include/hw/gpio/nrf51_gpio.h
+++ b/include/hw/gpio/nrf51_gpio.h
@@ -27,8 +27,11 @@
 #define NRF51_GPIO_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 #define TYPE_NRF51_GPIO "nrf51_soc.gpio"
-#define NRF51_GPIO(obj) OBJECT_CHECK(NRF51GPIOState, (obj), TYPE_NRF51_GPIO)
+typedef struct NRF51GPIOState NRF51GPIOState;
+DECLARE_INSTANCE_CHECKER(NRF51GPIOState, NRF51_GPIO,
+                         TYPE_NRF51_GPIO)
 
 #define NRF51_GPIO_PINS 32
 
@@ -47,7 +50,7 @@
 #define NRF51_GPIO_PULLDOWN 1
 #define NRF51_GPIO_PULLUP 3
 
-typedef struct NRF51GPIOState {
+struct NRF51GPIOState {
     SysBusDevice parent_obj;
 
     MemoryRegion mmio;
@@ -63,7 +66,7 @@ typedef struct NRF51GPIOState {
     uint32_t old_out_connected;
 
     qemu_irq output[NRF51_GPIO_PINS];
-} NRF51GPIOState;
+};
 
 
 #endif
diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h
index 6321e292fd..e15f59c8b3 100644
--- a/include/hw/hotplug.h
+++ b/include/hw/hotplug.h
@@ -16,10 +16,9 @@
 
 #define TYPE_HOTPLUG_HANDLER "hotplug-handler"
 
-#define HOTPLUG_HANDLER_CLASS(klass) \
-     OBJECT_CLASS_CHECK(HotplugHandlerClass, (klass), TYPE_HOTPLUG_HANDLER)
-#define HOTPLUG_HANDLER_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(HotplugHandlerClass, (obj), TYPE_HOTPLUG_HANDLER)
+typedef struct HotplugHandlerClass HotplugHandlerClass;
+DECLARE_CLASS_CHECKERS(HotplugHandlerClass, HOTPLUG_HANDLER,
+                       TYPE_HOTPLUG_HANDLER)
 #define HOTPLUG_HANDLER(obj) \
      INTERFACE_CHECK(HotplugHandler, (obj), TYPE_HOTPLUG_HANDLER)
 
@@ -50,7 +49,7 @@ typedef void (*hotplug_fn)(HotplugHandler *plug_handler,
  *          Used for device removal with devices that implement
  *          asynchronous and synchronous (surprise) removal.
  */
-typedef struct HotplugHandlerClass {
+struct HotplugHandlerClass {
     /* <private> */
     InterfaceClass parent;
 
@@ -59,7 +58,7 @@ typedef struct HotplugHandlerClass {
     hotplug_fn plug;
     hotplug_fn unplug_request;
     hotplug_fn unplug;
-} HotplugHandlerClass;
+};
 
 /**
  * hotplug_handler_plug:
diff --git a/include/hw/hyperv/vmbus-bridge.h b/include/hw/hyperv/vmbus-bridge.h
index fe90bda01b..1324873775 100644
--- a/include/hw/hyperv/vmbus-bridge.h
+++ b/include/hw/hyperv/vmbus-bridge.h
@@ -12,18 +12,21 @@
 
 #include "hw/sysbus.h"
 #include "hw/hyperv/vmbus.h"
+#include "qom/object.h"
 
 #define TYPE_VMBUS_BRIDGE "vmbus-bridge"
 
-typedef struct VMBusBridge {
+struct VMBusBridge {
     SysBusDevice parent_obj;
 
     uint8_t irq;
 
     VMBus *bus;
-} VMBusBridge;
+};
+typedef struct VMBusBridge VMBusBridge;
 
-#define VMBUS_BRIDGE(obj) OBJECT_CHECK(VMBusBridge, (obj), TYPE_VMBUS_BRIDGE)
+DECLARE_INSTANCE_CHECKER(VMBusBridge, VMBUS_BRIDGE,
+                         TYPE_VMBUS_BRIDGE)
 
 static inline VMBusBridge *vmbus_bridge_find(void)
 {
diff --git a/include/hw/hyperv/vmbus.h b/include/hw/hyperv/vmbus.h
index cd98ec24e7..00ad8798c1 100644
--- a/include/hw/hyperv/vmbus.h
+++ b/include/hw/hyperv/vmbus.h
@@ -16,19 +16,17 @@
 #include "migration/vmstate.h"
 #include "hw/hyperv/vmbus-proto.h"
 #include "qemu/uuid.h"
+#include "qom/object.h"
 
 #define TYPE_VMBUS_DEVICE "vmbus-dev"
 
-#define VMBUS_DEVICE(obj) \
-    OBJECT_CHECK(VMBusDevice, (obj), TYPE_VMBUS_DEVICE)
-#define VMBUS_DEVICE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(VMBusDeviceClass, (klass), TYPE_VMBUS_DEVICE)
-#define VMBUS_DEVICE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(VMBusDeviceClass, (obj), TYPE_VMBUS_DEVICE)
+OBJECT_DECLARE_TYPE(VMBusDevice, VMBusDeviceClass,
+                    vmbus_device, VMBUS_DEVICE)
 
 #define TYPE_VMBUS "vmbus"
 typedef struct VMBus VMBus;
-#define VMBUS(obj) OBJECT_CHECK(VMBus, (obj), TYPE_VMBUS)
+DECLARE_INSTANCE_CHECKER(VMBus, VMBUS,
+                         TYPE_VMBUS)
 
 /*
  * Object wrapping a GPADL -- GPA Descriptor List -- an array of guest physical
@@ -44,11 +42,10 @@ typedef struct VMBusChannel VMBusChannel;
  * Base class for VMBus devices.  Includes one or more channels.  Identified by
  * class GUID and instance GUID.
  */
-typedef struct VMBusDevice VMBusDevice;
 
 typedef void(*VMBusChannelNotifyCb)(struct VMBusChannel *chan);
 
-typedef struct VMBusDeviceClass {
+struct VMBusDeviceClass {
     DeviceClass parent;
 
     QemuUUID classid;
@@ -80,7 +77,7 @@ typedef struct VMBusDeviceClass {
      * side, when there's work to do with the data in the channel ring buffers.
      */
     VMBusChannelNotifyCb chan_notify_cb;
-} VMBusDeviceClass;
+};
 
 struct VMBusDevice {
     DeviceState parent;
diff --git a/include/hw/i2c/arm_sbcon_i2c.h b/include/hw/i2c/arm_sbcon_i2c.h
index 5d96507ab6..ad96781e7a 100644
--- a/include/hw/i2c/arm_sbcon_i2c.h
+++ b/include/hw/i2c/arm_sbcon_i2c.h
@@ -14,14 +14,16 @@
 
 #include "hw/sysbus.h"
 #include "hw/i2c/bitbang_i2c.h"
+#include "qom/object.h"
 
 #define TYPE_VERSATILE_I2C "versatile_i2c"
 #define TYPE_ARM_SBCON_I2C TYPE_VERSATILE_I2C
 
-#define ARM_SBCON_I2C(obj) \
-    OBJECT_CHECK(ArmSbconI2CState, (obj), TYPE_ARM_SBCON_I2C)
+typedef struct ArmSbconI2CState ArmSbconI2CState;
+DECLARE_INSTANCE_CHECKER(ArmSbconI2CState, ARM_SBCON_I2C,
+                         TYPE_ARM_SBCON_I2C)
 
-typedef struct ArmSbconI2CState {
+struct ArmSbconI2CState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -30,6 +32,6 @@ typedef struct ArmSbconI2CState {
     bitbang_i2c_interface bitbang;
     int out;
     int in;
-} ArmSbconI2CState;
+};
 
 #endif /* HW_I2C_ARM_SBCON_H */
diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
index 243789ae5d..695e1c0928 100644
--- a/include/hw/i2c/aspeed_i2c.h
+++ b/include/hw/i2c/aspeed_i2c.h
@@ -23,13 +23,16 @@
 
 #include "hw/i2c/i2c.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_ASPEED_I2C "aspeed.i2c"
 #define TYPE_ASPEED_2400_I2C TYPE_ASPEED_I2C "-ast2400"
 #define TYPE_ASPEED_2500_I2C TYPE_ASPEED_I2C "-ast2500"
 #define TYPE_ASPEED_2600_I2C TYPE_ASPEED_I2C "-ast2600"
-#define ASPEED_I2C(obj) \
-    OBJECT_CHECK(AspeedI2CState, (obj), TYPE_ASPEED_I2C)
+typedef struct AspeedI2CClass AspeedI2CClass;
+typedef struct AspeedI2CState AspeedI2CState;
+DECLARE_OBJ_CHECKERS(AspeedI2CState, AspeedI2CClass,
+                     ASPEED_I2C, TYPE_ASPEED_I2C)
 
 #define ASPEED_I2C_NR_BUSSES 16
 #define ASPEED_I2C_MAX_POOL_SIZE 0x800
@@ -56,7 +59,7 @@ typedef struct AspeedI2CBus {
     uint32_t dma_len;
 } AspeedI2CBus;
 
-typedef struct AspeedI2CState {
+struct AspeedI2CState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -70,14 +73,10 @@ typedef struct AspeedI2CState {
     AspeedI2CBus busses[ASPEED_I2C_NR_BUSSES];
     MemoryRegion *dram_mr;
     AddressSpace dram_as;
-} AspeedI2CState;
+};
 
-#define ASPEED_I2C_CLASS(klass) \
-     OBJECT_CLASS_CHECK(AspeedI2CClass, (klass), TYPE_ASPEED_I2C)
-#define ASPEED_I2C_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(AspeedI2CClass, (obj), TYPE_ASPEED_I2C)
 
-typedef struct AspeedI2CClass {
+struct AspeedI2CClass {
     SysBusDeviceClass parent_class;
 
     uint8_t num_busses;
@@ -91,7 +90,7 @@ typedef struct AspeedI2CClass {
     bool check_sram;
     bool has_dma;
 
-} AspeedI2CClass;
+};
 
 I2CBus *aspeed_i2c_get_bus(AspeedI2CState *s, int busnr);
 
diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
index f57808851e..5b8eef62c6 100644
--- a/include/hw/i2c/i2c.h
+++ b/include/hw/i2c/i2c.h
@@ -2,6 +2,7 @@
 #define QEMU_I2C_H
 
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 /* The QEMU I2C implementation only supports simple transfers that complete
    immediately.  It does not support slave devices that need to be able to
@@ -15,17 +16,12 @@ enum i2c_event {
     I2C_NACK /* Masker NACKed a receive byte.  */
 };
 
-typedef struct I2CSlave I2CSlave;
 
 #define TYPE_I2C_SLAVE "i2c-slave"
-#define I2C_SLAVE(obj) \
-     OBJECT_CHECK(I2CSlave, (obj), TYPE_I2C_SLAVE)
-#define I2C_SLAVE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(I2CSlaveClass, (klass), TYPE_I2C_SLAVE)
-#define I2C_SLAVE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(I2CSlaveClass, (obj), TYPE_I2C_SLAVE)
-
-typedef struct I2CSlaveClass {
+OBJECT_DECLARE_TYPE(I2CSlave, I2CSlaveClass,
+                    i2c_slave, I2C_SLAVE)
+
+struct I2CSlaveClass {
     DeviceClass parent_class;
 
     /* Master to slave. Returns non-zero for a NAK, 0 for success. */
@@ -43,7 +39,7 @@ typedef struct I2CSlaveClass {
      * return code is not used and should be zero.
      */
     int (*event)(I2CSlave *s, enum i2c_event event);
-} I2CSlaveClass;
+};
 
 struct I2CSlave {
     DeviceState qdev;
@@ -53,7 +49,8 @@ struct I2CSlave {
 };
 
 #define TYPE_I2C_BUS "i2c-bus"
-#define I2C_BUS(obj) OBJECT_CHECK(I2CBus, (obj), TYPE_I2C_BUS)
+DECLARE_INSTANCE_CHECKER(I2CBus, I2C_BUS,
+                         TYPE_I2C_BUS)
 
 typedef struct I2CNode I2CNode;
 
diff --git a/include/hw/i2c/imx_i2c.h b/include/hw/i2c/imx_i2c.h
index 7c73a1fa28..e7f09104cf 100644
--- a/include/hw/i2c/imx_i2c.h
+++ b/include/hw/i2c/imx_i2c.h
@@ -22,9 +22,12 @@
 #define IMX_I2C_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_IMX_I2C "imx.i2c"
-#define IMX_I2C(obj) OBJECT_CHECK(IMXI2CState, (obj), TYPE_IMX_I2C)
+typedef struct IMXI2CState IMXI2CState;
+DECLARE_INSTANCE_CHECKER(IMXI2CState, IMX_I2C,
+                         TYPE_IMX_I2C)
 
 #define IMX_I2C_MEM_SIZE           0x14
 
@@ -65,7 +68,7 @@
 
 #define ADDR_RESET                 0xFF00
 
-typedef struct IMXI2CState {
+struct IMXI2CState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -82,6 +85,6 @@ typedef struct IMXI2CState {
     uint16_t i2sr;
     uint16_t i2dr_read;
     uint16_t i2dr_write;
-} IMXI2CState;
+};
 
 #endif /* IMX_I2C_H */
diff --git a/include/hw/i2c/microbit_i2c.h b/include/hw/i2c/microbit_i2c.h
index 2bff36680c..69d70287d7 100644
--- a/include/hw/i2c/microbit_i2c.h
+++ b/include/hw/i2c/microbit_i2c.h
@@ -13,6 +13,7 @@
 
 #include "hw/sysbus.h"
 #include "hw/arm/nrf51.h"
+#include "qom/object.h"
 
 #define NRF51_TWI_TASK_STARTRX 0x000
 #define NRF51_TWI_TASK_STARTTX 0x008
@@ -26,17 +27,18 @@
 #define NRF51_TWI_REG_ADDRESS 0x588
 
 #define TYPE_MICROBIT_I2C "microbit.i2c"
-#define MICROBIT_I2C(obj) \
-    OBJECT_CHECK(MicrobitI2CState, (obj), TYPE_MICROBIT_I2C)
+typedef struct MicrobitI2CState MicrobitI2CState;
+DECLARE_INSTANCE_CHECKER(MicrobitI2CState, MICROBIT_I2C,
+                         TYPE_MICROBIT_I2C)
 
 #define MICROBIT_I2C_NREGS (NRF51_PERIPHERAL_SIZE / sizeof(uint32_t))
 
-typedef struct {
+struct MicrobitI2CState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
     uint32_t regs[MICROBIT_I2C_NREGS];
     uint32_t read_idx;
-} MicrobitI2CState;
+};
 
 #endif /* MICROBIT_I2C_H */
diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h
index f6f837fbec..7cbcdaf12f 100644
--- a/include/hw/i2c/ppc4xx_i2c.h
+++ b/include/hw/i2c/ppc4xx_i2c.h
@@ -29,11 +29,14 @@
 
 #include "hw/sysbus.h"
 #include "hw/i2c/bitbang_i2c.h"
+#include "qom/object.h"
 
 #define TYPE_PPC4xx_I2C "ppc4xx-i2c"
-#define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C)
+typedef struct PPC4xxI2CState PPC4xxI2CState;
+DECLARE_INSTANCE_CHECKER(PPC4xxI2CState, PPC4xx_I2C,
+                         TYPE_PPC4xx_I2C)
 
-typedef struct PPC4xxI2CState {
+struct PPC4xxI2CState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -57,6 +60,6 @@ typedef struct PPC4xxI2CState {
     uint8_t xfrcnt;
     uint8_t xtcntlss;
     uint8_t directcntl;
-} PPC4xxI2CState;
+};
 
 #endif /* PPC4XX_I2C_H */
diff --git a/include/hw/i2c/smbus_slave.h b/include/hw/i2c/smbus_slave.h
index ebe068304e..cb9cb372f9 100644
--- a/include/hw/i2c/smbus_slave.h
+++ b/include/hw/i2c/smbus_slave.h
@@ -26,19 +26,14 @@
 #define HW_SMBUS_SLAVE_H
 
 #include "hw/i2c/i2c.h"
+#include "qom/object.h"
 
 #define TYPE_SMBUS_DEVICE "smbus-device"
-#define SMBUS_DEVICE(obj) \
-     OBJECT_CHECK(SMBusDevice, (obj), TYPE_SMBUS_DEVICE)
-#define SMBUS_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(SMBusDeviceClass, (klass), TYPE_SMBUS_DEVICE)
-#define SMBUS_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(SMBusDeviceClass, (obj), TYPE_SMBUS_DEVICE)
+OBJECT_DECLARE_TYPE(SMBusDevice, SMBusDeviceClass,
+                    smbus_device, SMBUS_DEVICE)
 
-typedef struct SMBusDevice SMBusDevice;
 
-typedef struct SMBusDeviceClass
-{
+struct SMBusDeviceClass {
     I2CSlaveClass parent_class;
 
     /*
@@ -67,7 +62,7 @@ typedef struct SMBusDeviceClass
      * return 0xff in that case.
      */
     uint8_t (*receive_byte)(SMBusDevice *dev);
-} SMBusDeviceClass;
+};
 
 #define SMBUS_DATA_MAX_LEN 34  /* command + len + 32 bytes of data.  */
 
diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h
index 2597000e03..da38541627 100644
--- a/include/hw/i386/apic_internal.h
+++ b/include/hw/i386/apic_internal.h
@@ -25,6 +25,7 @@
 #include "exec/memory.h"
 #include "qemu/timer.h"
 #include "target/i386/cpu-qom.h"
+#include "qom/object.h"
 
 /* APIC Local Vector Table */
 #define APIC_LVT_TIMER                  0
@@ -125,15 +126,11 @@
 typedef struct APICCommonState APICCommonState;
 
 #define TYPE_APIC_COMMON "apic-common"
-#define APIC_COMMON(obj) \
-     OBJECT_CHECK(APICCommonState, (obj), TYPE_APIC_COMMON)
-#define APIC_COMMON_CLASS(klass) \
-     OBJECT_CLASS_CHECK(APICCommonClass, (klass), TYPE_APIC_COMMON)
-#define APIC_COMMON_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(APICCommonClass, (obj), TYPE_APIC_COMMON)
-
-typedef struct APICCommonClass
-{
+typedef struct APICCommonClass APICCommonClass;
+DECLARE_OBJ_CHECKERS(APICCommonState, APICCommonClass,
+                     APIC_COMMON, TYPE_APIC_COMMON)
+
+struct APICCommonClass {
     DeviceClass parent_class;
 
     DeviceRealize realize;
@@ -151,7 +148,7 @@ typedef struct APICCommonClass
      * device, but it's convenient to have it here for now.
      */
     void (*send_msi)(MSIMessage *msi);
-} APICCommonClass;
+};
 
 struct APICCommonState {
     /*< private >*/
diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h
index a98d10b252..e750d67975 100644
--- a/include/hw/i386/ich9.h
+++ b/include/hw/i386/ich9.h
@@ -11,6 +11,7 @@
 #include "hw/acpi/acpi.h"
 #include "hw/acpi/ich9.h"
 #include "hw/pci/pci_bus.h"
+#include "qom/object.h"
 
 void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
 int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx);
@@ -23,10 +24,11 @@ void ich9_generate_smi(void);
 #define ICH9_CC_SIZE (16 * 1024) /* 16KB. Chipset configuration registers */
 
 #define TYPE_ICH9_LPC_DEVICE "ICH9-LPC"
-#define ICH9_LPC_DEVICE(obj) \
-     OBJECT_CHECK(ICH9LPCState, (obj), TYPE_ICH9_LPC_DEVICE)
+typedef struct ICH9LPCState ICH9LPCState;
+DECLARE_INSTANCE_CHECKER(ICH9LPCState, ICH9_LPC_DEVICE,
+                         TYPE_ICH9_LPC_DEVICE)
 
-typedef struct ICH9LPCState {
+struct ICH9LPCState {
     /* ICH9 LPC PCI to ISA bridge */
     PCIDevice d;
 
@@ -77,7 +79,7 @@ typedef struct ICH9LPCState {
     Notifier machine_ready;
 
     qemu_irq gsi[GSI_NUM_PINS];
-} ICH9LPCState;
+};
 
 #define Q35_MASK(bit, ms_bit, ls_bit) \
 ((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 3870052f5f..98cfc77723 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -24,10 +24,12 @@
 
 #include "hw/i386/x86-iommu.h"
 #include "qemu/iova-tree.h"
+#include "qom/object.h"
 
 #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
-#define INTEL_IOMMU_DEVICE(obj) \
-     OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
+typedef struct IntelIOMMUState IntelIOMMUState;
+DECLARE_INSTANCE_CHECKER(IntelIOMMUState, INTEL_IOMMU_DEVICE,
+                         TYPE_INTEL_IOMMU_DEVICE)
 
 #define TYPE_INTEL_IOMMU_MEMORY_REGION "intel-iommu-iommu-memory-region"
 
@@ -56,7 +58,6 @@
 
 typedef struct VTDContextEntry VTDContextEntry;
 typedef struct VTDContextCacheEntry VTDContextCacheEntry;
-typedef struct IntelIOMMUState IntelIOMMUState;
 typedef struct VTDAddressSpace VTDAddressSpace;
 typedef struct VTDIOTLBEntry VTDIOTLBEntry;
 typedef struct VTDBus VTDBus;
diff --git a/include/hw/i386/ioapic_internal.h b/include/hw/i386/ioapic_internal.h
index fe06938bda..e9cc2eaf54 100644
--- a/include/hw/i386/ioapic_internal.h
+++ b/include/hw/i386/ioapic_internal.h
@@ -25,6 +25,7 @@
 #include "exec/memory.h"
 #include "hw/sysbus.h"
 #include "qemu/notify.h"
+#include "qom/object.h"
 
 #define MAX_IOAPICS                     1
 
@@ -84,21 +85,18 @@
 typedef struct IOAPICCommonState IOAPICCommonState;
 
 #define TYPE_IOAPIC_COMMON "ioapic-common"
-#define IOAPIC_COMMON(obj) \
-     OBJECT_CHECK(IOAPICCommonState, (obj), TYPE_IOAPIC_COMMON)
-#define IOAPIC_COMMON_CLASS(klass) \
-     OBJECT_CLASS_CHECK(IOAPICCommonClass, (klass), TYPE_IOAPIC_COMMON)
-#define IOAPIC_COMMON_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(IOAPICCommonClass, (obj), TYPE_IOAPIC_COMMON)
-
-typedef struct IOAPICCommonClass {
+typedef struct IOAPICCommonClass IOAPICCommonClass;
+DECLARE_OBJ_CHECKERS(IOAPICCommonState, IOAPICCommonClass,
+                     IOAPIC_COMMON, TYPE_IOAPIC_COMMON)
+
+struct IOAPICCommonClass {
     SysBusDeviceClass parent_class;
 
     DeviceRealize realize;
     DeviceUnrealize unrealize;
     void (*pre_save)(IOAPICCommonState *s);
     void (*post_load)(IOAPICCommonState *s);
-} IOAPICCommonClass;
+};
 
 struct IOAPICCommonState {
     SysBusDevice busdev;
diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h
index fd34b78e0d..36dbcdd123 100644
--- a/include/hw/i386/microvm.h
+++ b/include/hw/i386/microvm.h
@@ -24,6 +24,7 @@
 
 #include "hw/boards.h"
 #include "hw/i386/x86.h"
+#include "qom/object.h"
 
 /* Platform virtio definitions */
 #define VIRTIO_MMIO_BASE      0xfeb00000
@@ -39,13 +40,14 @@
 #define MICROVM_MACHINE_OPTION_ROMS         "x-option-roms"
 #define MICROVM_MACHINE_AUTO_KERNEL_CMDLINE "auto-kernel-cmdline"
 
-typedef struct {
+struct MicrovmMachineClass {
     X86MachineClass parent;
     HotplugHandler *(*orig_hotplug_handler)(MachineState *machine,
                                            DeviceState *dev);
-} MicrovmMachineClass;
+};
+typedef struct MicrovmMachineClass MicrovmMachineClass;
 
-typedef struct {
+struct MicrovmMachineState {
     X86MachineState parent;
 
     /* Machine type options */
@@ -58,14 +60,11 @@ typedef struct {
 
     /* Machine state */
     bool kernel_cmdline_fixed;
-} MicrovmMachineState;
+};
+typedef struct MicrovmMachineState MicrovmMachineState;
 
 #define TYPE_MICROVM_MACHINE   MACHINE_TYPE_NAME("microvm")
-#define MICROVM_MACHINE(obj) \
-    OBJECT_CHECK(MicrovmMachineState, (obj), TYPE_MICROVM_MACHINE)
-#define MICROVM_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(MicrovmMachineClass, obj, TYPE_MICROVM_MACHINE)
-#define MICROVM_MACHINE_CLASS(class) \
-    OBJECT_CLASS_CHECK(MicrovmMachineClass, class, TYPE_MICROVM_MACHINE)
+DECLARE_OBJ_CHECKERS(MicrovmMachineState, MicrovmMachineClass,
+                     MICROVM_MACHINE, TYPE_MICROVM_MACHINE)
 
 #endif
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index fe52e165b2..421a77acc2 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -10,6 +10,7 @@
 
 #include "hw/acpi/acpi_dev_interface.h"
 #include "hw/hotplug.h"
+#include "qom/object.h"
 
 #define HPET_INTCAP "hpet-intcap"
 
@@ -76,7 +77,7 @@ struct PCMachineState {
  *                  way we can use 1GByte pages in the host.
  *
  */
-typedef struct PCMachineClass {
+struct PCMachineClass {
     /*< private >*/
     X86MachineClass parent_class;
 
@@ -118,15 +119,12 @@ typedef struct PCMachineClass {
 
     /* use PVH to load kernels that support this feature */
     bool pvh_enabled;
-} PCMachineClass;
+};
+typedef struct PCMachineClass PCMachineClass;
 
 #define TYPE_PC_MACHINE "generic-pc-machine"
-#define PC_MACHINE(obj) \
-    OBJECT_CHECK(PCMachineState, (obj), TYPE_PC_MACHINE)
-#define PC_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(PCMachineClass, (obj), TYPE_PC_MACHINE)
-#define PC_MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(PCMachineClass, (klass), TYPE_PC_MACHINE)
+DECLARE_OBJ_CHECKERS(PCMachineState, PCMachineClass,
+                     PC_MACHINE, TYPE_PC_MACHINE)
 
 /* ioapic.c */
 
diff --git a/include/hw/i386/x86-iommu.h b/include/hw/i386/x86-iommu.h
index 18420ada15..bbfaf44e79 100644
--- a/include/hw/i386/x86-iommu.h
+++ b/include/hw/i386/x86-iommu.h
@@ -23,19 +23,16 @@
 #include "hw/sysbus.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/msi.h"
+#include "qom/object.h"
 
 #define  TYPE_X86_IOMMU_DEVICE  ("x86-iommu")
-#define  X86_IOMMU_DEVICE(obj) \
-    OBJECT_CHECK(X86IOMMUState, (obj), TYPE_X86_IOMMU_DEVICE)
-#define  X86_IOMMU_DEVICE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(X86IOMMUClass, (klass), TYPE_X86_IOMMU_DEVICE)
-#define  X86_IOMMU_DEVICE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(X86IOMMUClass, obj, TYPE_X86_IOMMU_DEVICE)
+typedef struct X86IOMMUClass X86IOMMUClass;
+typedef struct X86IOMMUState X86IOMMUState;
+DECLARE_OBJ_CHECKERS(X86IOMMUState, X86IOMMUClass,
+                     X86_IOMMU_DEVICE, TYPE_X86_IOMMU_DEVICE)
 
 #define X86_IOMMU_SID_INVALID             (0xffff)
 
-typedef struct X86IOMMUState X86IOMMUState;
-typedef struct X86IOMMUClass X86IOMMUClass;
 typedef struct X86IOMMUIrq X86IOMMUIrq;
 typedef struct X86IOMMU_MSIMessage X86IOMMU_MSIMessage;
 
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index 4d9a26326d..1a188a7dea 100644
--- a/include/hw/i386/x86.h
+++ b/include/hw/i386/x86.h
@@ -26,8 +26,9 @@
 #include "hw/nmi.h"
 #include "hw/isa/isa.h"
 #include "hw/i386/ioapic.h"
+#include "qom/object.h"
 
-typedef struct {
+struct X86MachineClass {
     /*< private >*/
     MachineClass parent;
 
@@ -37,9 +38,10 @@ typedef struct {
     bool save_tsc_khz;
     /* Enables contiguous-apic-ID mode */
     bool compat_apic_id_mode;
-} X86MachineClass;
+};
+typedef struct X86MachineClass X86MachineClass;
 
-typedef struct {
+struct X86MachineState {
     /*< private >*/
     MachineState parent;
 
@@ -68,18 +70,15 @@ typedef struct {
      * will be translated to MSI messages in the address space.
      */
     AddressSpace *ioapic_as;
-} X86MachineState;
+};
+typedef struct X86MachineState X86MachineState;
 
 #define X86_MACHINE_SMM              "smm"
 #define X86_MACHINE_ACPI             "acpi"
 
 #define TYPE_X86_MACHINE   MACHINE_TYPE_NAME("x86")
-#define X86_MACHINE(obj) \
-    OBJECT_CHECK(X86MachineState, (obj), TYPE_X86_MACHINE)
-#define X86_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(X86MachineClass, obj, TYPE_X86_MACHINE)
-#define X86_MACHINE_CLASS(class) \
-    OBJECT_CLASS_CHECK(X86MachineClass, class, TYPE_X86_MACHINE)
+DECLARE_OBJ_CHECKERS(X86MachineState, X86MachineClass,
+                     X86_MACHINE, TYPE_X86_MACHINE)
 
 void init_topo_info(X86CPUTopoInfo *topo_info, const X86MachineState *x86ms);
 
diff --git a/include/hw/ide/ahci.h b/include/hw/ide/ahci.h
index 41bb517047..da3cddcc65 100644
--- a/include/hw/ide/ahci.h
+++ b/include/hw/ide/ahci.h
@@ -25,6 +25,7 @@
 #define HW_IDE_AHCI_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 typedef struct AHCIDevice AHCIDevice;
 
@@ -53,38 +54,41 @@ typedef struct AHCIState {
 typedef struct AHCIPCIState AHCIPCIState;
 
 #define TYPE_ICH9_AHCI "ich9-ahci"
-#define ICH_AHCI(obj) \
-    OBJECT_CHECK(AHCIPCIState, (obj), TYPE_ICH9_AHCI)
+DECLARE_INSTANCE_CHECKER(AHCIPCIState, ICH9_AHCI,
+                         TYPE_ICH9_AHCI)
 
 int32_t ahci_get_num_ports(PCIDevice *dev);
 void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd);
 
 #define TYPE_SYSBUS_AHCI "sysbus-ahci"
-#define SYSBUS_AHCI(obj) OBJECT_CHECK(SysbusAHCIState, (obj), TYPE_SYSBUS_AHCI)
+typedef struct SysbusAHCIState SysbusAHCIState;
+DECLARE_INSTANCE_CHECKER(SysbusAHCIState, SYSBUS_AHCI,
+                         TYPE_SYSBUS_AHCI)
 
-typedef struct SysbusAHCIState {
+struct SysbusAHCIState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
 
     AHCIState ahci;
     uint32_t num_ports;
-} SysbusAHCIState;
+};
 
 #define TYPE_ALLWINNER_AHCI "allwinner-ahci"
-#define ALLWINNER_AHCI(obj) \
-        OBJECT_CHECK(AllwinnerAHCIState, (obj), TYPE_ALLWINNER_AHCI)
+typedef struct AllwinnerAHCIState AllwinnerAHCIState;
+DECLARE_INSTANCE_CHECKER(AllwinnerAHCIState, ALLWINNER_AHCI,
+                         TYPE_ALLWINNER_AHCI)
 
 #define ALLWINNER_AHCI_MMIO_OFF  0x80
 #define ALLWINNER_AHCI_MMIO_SIZE 0x80
 
-typedef struct AllwinnerAHCIState {
+struct AllwinnerAHCIState {
     /*< private >*/
     SysbusAHCIState parent_obj;
     /*< public >*/
 
     MemoryRegion mmio;
     uint32_t regs[ALLWINNER_AHCI_MMIO_SIZE/4];
-} AllwinnerAHCIState;
+};
 
 #endif /* HW_IDE_AHCI_H */
diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h
index 1a7869e85d..eb9eb4e0ae 100644
--- a/include/hw/ide/internal.h
+++ b/include/hw/ide/internal.h
@@ -17,6 +17,7 @@
 
 /* debug IDE devices */
 #define USE_DMA_CDROM
+#include "qom/object.h"
 
 typedef struct IDEBus IDEBus;
 typedef struct IDEDevice IDEDevice;
@@ -25,7 +26,8 @@ typedef struct IDEDMA IDEDMA;
 typedef struct IDEDMAOps IDEDMAOps;
 
 #define TYPE_IDE_BUS "IDE"
-#define IDE_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS)
+DECLARE_INSTANCE_CHECKER(IDEBus, IDE_BUS,
+                         TYPE_IDE_BUS)
 
 #define MAX_IDE_DEVS 2
 
@@ -486,17 +488,14 @@ struct IDEBus {
 };
 
 #define TYPE_IDE_DEVICE "ide-device"
-#define IDE_DEVICE(obj) \
-     OBJECT_CHECK(IDEDevice, (obj), TYPE_IDE_DEVICE)
-#define IDE_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(IDEDeviceClass, (klass), TYPE_IDE_DEVICE)
-#define IDE_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(IDEDeviceClass, (obj), TYPE_IDE_DEVICE)
-
-typedef struct IDEDeviceClass {
+typedef struct IDEDeviceClass IDEDeviceClass;
+DECLARE_OBJ_CHECKERS(IDEDevice, IDEDeviceClass,
+                     IDE_DEVICE, TYPE_IDE_DEVICE)
+
+struct IDEDeviceClass {
     DeviceClass parent_class;
     void (*realize)(IDEDevice *dev, Error **errp);
-} IDEDeviceClass;
+};
 
 struct IDEDevice {
     DeviceState qdev;
diff --git a/include/hw/ide/pci.h b/include/hw/ide/pci.h
index dd504e5a0b..b8d7270ec8 100644
--- a/include/hw/ide/pci.h
+++ b/include/hw/ide/pci.h
@@ -3,6 +3,7 @@
 
 #include "hw/ide/internal.h"
 #include "hw/pci/pci.h"
+#include "qom/object.h"
 
 #define BM_STATUS_DMAING 0x01
 #define BM_STATUS_ERROR  0x02
@@ -39,9 +40,11 @@ typedef struct BMDMAState {
 } BMDMAState;
 
 #define TYPE_PCI_IDE "pci-ide"
-#define PCI_IDE(obj) OBJECT_CHECK(PCIIDEState, (obj), TYPE_PCI_IDE)
+typedef struct PCIIDEState PCIIDEState;
+DECLARE_INSTANCE_CHECKER(PCIIDEState, PCI_IDE,
+                         TYPE_PCI_IDE)
 
-typedef struct PCIIDEState {
+struct PCIIDEState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
@@ -52,7 +55,7 @@ typedef struct PCIIDEState {
     MemoryRegion bmdma_bar;
     MemoryRegion cmd_bar[2];
     MemoryRegion data_bar[2];
-} PCIIDEState;
+};
 
 static inline IDEState *bmdma_active_if(BMDMAState *bmdma)
 {
diff --git a/include/hw/input/adb.h b/include/hw/input/adb.h
index bb75a7b1e3..285f70db55 100644
--- a/include/hw/input/adb.h
+++ b/include/hw/input/adb.h
@@ -27,6 +27,7 @@
 #define ADB_H
 
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 #define MAX_ADB_DEVICES 16
 
@@ -42,7 +43,9 @@ typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out,
 typedef bool ADBDeviceHasData(ADBDevice *d);
 
 #define TYPE_ADB_DEVICE "adb-device"
-#define ADB_DEVICE(obj) OBJECT_CHECK(ADBDevice, (obj), TYPE_ADB_DEVICE)
+typedef struct ADBDeviceClass ADBDeviceClass;
+DECLARE_OBJ_CHECKERS(ADBDevice, ADBDeviceClass,
+                     ADB_DEVICE, TYPE_ADB_DEVICE)
 
 struct ADBDevice {
     /*< private >*/
@@ -53,22 +56,19 @@ struct ADBDevice {
     int handler;
 };
 
-#define ADB_DEVICE_CLASS(cls) \
-    OBJECT_CLASS_CHECK(ADBDeviceClass, (cls), TYPE_ADB_DEVICE)
-#define ADB_DEVICE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(ADBDeviceClass, (obj), TYPE_ADB_DEVICE)
 
-typedef struct ADBDeviceClass {
+struct ADBDeviceClass {
     /*< private >*/
     DeviceClass parent_class;
     /*< public >*/
 
     ADBDeviceRequest *devreq;
     ADBDeviceHasData *devhasdata;
-} ADBDeviceClass;
+};
 
 #define TYPE_ADB_BUS "apple-desktop-bus"
-#define ADB_BUS(obj) OBJECT_CHECK(ADBBusState, (obj), TYPE_ADB_BUS)
+DECLARE_INSTANCE_CHECKER(ADBBusState, ADB_BUS,
+                         TYPE_ADB_BUS)
 
 #define ADB_STATUS_BUSTIMEOUT  0x1
 #define ADB_STATUS_POLLREPLY   0x2
diff --git a/include/hw/input/i8042.h b/include/hw/input/i8042.h
index 4569dfddd9..f8a3bf88ac 100644
--- a/include/hw/input/i8042.h
+++ b/include/hw/input/i8042.h
@@ -9,13 +9,15 @@
 #define HW_INPUT_I8042_H
 
 #include "hw/isa/isa.h"
+#include "qom/object.h"
 
 #define TYPE_I8042 "i8042"
-#define I8042(obj) OBJECT_CHECK(ISAKBDState, (obj), TYPE_I8042)
+typedef struct ISAKBDState ISAKBDState;
+DECLARE_INSTANCE_CHECKER(ISAKBDState, I8042,
+                         TYPE_I8042)
 
 #define I8042_A20_LINE "a20"
 
-typedef struct ISAKBDState ISAKBDState;
 
 void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
                    MemoryRegion *region, ram_addr_t size,
diff --git a/include/hw/intc/allwinner-a10-pic.h b/include/hw/intc/allwinner-a10-pic.h
index a5895401d1..4d7199480a 100644
--- a/include/hw/intc/allwinner-a10-pic.h
+++ b/include/hw/intc/allwinner-a10-pic.h
@@ -2,9 +2,12 @@
 #define ALLWINNER_A10_PIC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_AW_A10_PIC  "allwinner-a10-pic"
-#define AW_A10_PIC(obj) OBJECT_CHECK(AwA10PICState, (obj), TYPE_AW_A10_PIC)
+typedef struct AwA10PICState AwA10PICState;
+DECLARE_INSTANCE_CHECKER(AwA10PICState, AW_A10_PIC,
+                         TYPE_AW_A10_PIC)
 
 #define AW_A10_PIC_VECTOR       0
 #define AW_A10_PIC_BASE_ADDR    4
@@ -19,7 +22,7 @@
 #define AW_A10_PIC_INT_NR       95
 #define AW_A10_PIC_REG_NUM      DIV_ROUND_UP(AW_A10_PIC_INT_NR, 32)
 
-typedef struct AwA10PICState {
+struct AwA10PICState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -37,6 +40,6 @@ typedef struct AwA10PICState {
     uint32_t enable[AW_A10_PIC_REG_NUM];
     uint32_t mask[AW_A10_PIC_REG_NUM];
     /*priority setting here*/
-} AwA10PICState;
+};
 
 #endif
diff --git a/include/hw/intc/arm_gic.h b/include/hw/intc/arm_gic.h
index 303b9748cb..116ccbb5a9 100644
--- a/include/hw/intc/arm_gic.h
+++ b/include/hw/intc/arm_gic.h
@@ -65,6 +65,7 @@
 #define HW_ARM_GIC_H
 
 #include "arm_gic_common.h"
+#include "qom/object.h"
 
 /* Number of SGI target-list bits */
 #define GIC_TARGETLIST_BITS 8
@@ -72,19 +73,17 @@
 #define GIC_MIN_PRIORITY_BITS 4
 
 #define TYPE_ARM_GIC "arm_gic"
-#define ARM_GIC(obj) \
-     OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC)
-#define ARM_GIC_CLASS(klass) \
-     OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC)
-#define ARM_GIC_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC)
+typedef struct ARMGICClass ARMGICClass;
+/* This is reusing the GICState typedef from TYPE_ARM_GIC_COMMON */
+DECLARE_OBJ_CHECKERS(GICState, ARMGICClass,
+                     ARM_GIC, TYPE_ARM_GIC)
 
-typedef struct ARMGICClass {
+struct ARMGICClass {
     /*< private >*/
     ARMGICCommonClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
-} ARMGICClass;
+};
 
 #endif
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index 6e0d6b8a88..7080375008 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -22,6 +22,7 @@
 #define HW_ARM_GIC_COMMON_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 /* Maximum number of possible interrupts, determined by the GIC architecture */
 #define GIC_MAXIRQ 1020
@@ -61,7 +62,7 @@ typedef struct gic_irq_state {
     uint8_t group;
 } gic_irq_state;
 
-typedef struct GICState {
+struct GICState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -143,24 +144,22 @@ typedef struct GICState {
     bool irq_reset_nonsecure; /* configure IRQs as group 1 (NS) on reset? */
     int dev_fd; /* kvm device fd if backed by kvm vgic support */
     Error *migration_blocker;
-} GICState;
+};
+typedef struct GICState GICState;
 
 #define TYPE_ARM_GIC_COMMON "arm_gic_common"
-#define ARM_GIC_COMMON(obj) \
-     OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON)
-#define ARM_GIC_COMMON_CLASS(klass) \
-     OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON)
-#define ARM_GIC_COMMON_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON)
-
-typedef struct ARMGICCommonClass {
+typedef struct ARMGICCommonClass ARMGICCommonClass;
+DECLARE_OBJ_CHECKERS(GICState, ARMGICCommonClass,
+                     ARM_GIC_COMMON, TYPE_ARM_GIC_COMMON)
+
+struct ARMGICCommonClass {
     /*< private >*/
     SysBusDeviceClass parent_class;
     /*< public >*/
 
     void (*pre_save)(GICState *s);
     void (*post_load)(GICState *s);
-} ARMGICCommonClass;
+};
 
 void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
                             const MemoryRegionOps *ops,
diff --git a/include/hw/intc/arm_gicv3.h b/include/hw/intc/arm_gicv3.h
index 4a6fd85e22..a81a6ae7ec 100644
--- a/include/hw/intc/arm_gicv3.h
+++ b/include/hw/intc/arm_gicv3.h
@@ -13,20 +13,20 @@
 #define HW_ARM_GICV3_H
 
 #include "arm_gicv3_common.h"
+#include "qom/object.h"
 
 #define TYPE_ARM_GICV3 "arm-gicv3"
-#define ARM_GICV3(obj) OBJECT_CHECK(GICv3State, (obj), TYPE_ARM_GICV3)
-#define ARM_GICV3_CLASS(klass) \
-     OBJECT_CLASS_CHECK(ARMGICv3Class, (klass), TYPE_ARM_GICV3)
-#define ARM_GICV3_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(ARMGICv3Class, (obj), TYPE_ARM_GICV3)
+typedef struct ARMGICv3Class ARMGICv3Class;
+/* This is reusing the GICState typedef from TYPE_ARM_GICV3_COMMON */
+DECLARE_OBJ_CHECKERS(GICv3State, ARMGICv3Class,
+                     ARM_GICV3, TYPE_ARM_GICV3)
 
-typedef struct ARMGICv3Class {
+struct ARMGICv3Class {
     /*< private >*/
     ARMGICv3CommonClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
-} ARMGICv3Class;
+};
 
 #endif
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
index 31ec9a1ae4..0331b0ffdb 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -26,6 +26,7 @@
 
 #include "hw/sysbus.h"
 #include "hw/intc/arm_gic_common.h"
+#include "qom/object.h"
 
 /*
  * Maximum number of possible interrupts, determined by the GIC architecture.
@@ -279,21 +280,18 @@ GICV3_BITMAP_ACCESSORS(level)
 GICV3_BITMAP_ACCESSORS(edge_trigger)
 
 #define TYPE_ARM_GICV3_COMMON "arm-gicv3-common"
-#define ARM_GICV3_COMMON(obj) \
-     OBJECT_CHECK(GICv3State, (obj), TYPE_ARM_GICV3_COMMON)
-#define ARM_GICV3_COMMON_CLASS(klass) \
-     OBJECT_CLASS_CHECK(ARMGICv3CommonClass, (klass), TYPE_ARM_GICV3_COMMON)
-#define ARM_GICV3_COMMON_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(ARMGICv3CommonClass, (obj), TYPE_ARM_GICV3_COMMON)
-
-typedef struct ARMGICv3CommonClass {
+typedef struct ARMGICv3CommonClass ARMGICv3CommonClass;
+DECLARE_OBJ_CHECKERS(GICv3State, ARMGICv3CommonClass,
+                     ARM_GICV3_COMMON, TYPE_ARM_GICV3_COMMON)
+
+struct ARMGICv3CommonClass {
     /*< private >*/
     SysBusDeviceClass parent_class;
     /*< public >*/
 
     void (*pre_save)(GICv3State *s);
     void (*post_load)(GICv3State *s);
-} ARMGICv3CommonClass;
+};
 
 void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
                               const MemoryRegionOps *ops, Error **errp);
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
index fd1fe64c03..5a0952b404 100644
--- a/include/hw/intc/arm_gicv3_its_common.h
+++ b/include/hw/intc/arm_gicv3_its_common.h
@@ -23,6 +23,7 @@
 
 #include "hw/sysbus.h"
 #include "hw/intc/arm_gicv3_common.h"
+#include "qom/object.h"
 
 #define ITS_CONTROL_SIZE 0x10000
 #define ITS_TRANS_SIZE   0x10000
@@ -64,12 +65,9 @@ typedef struct GICv3ITSState GICv3ITSState;
 void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops);
 
 #define TYPE_ARM_GICV3_ITS_COMMON "arm-gicv3-its-common"
-#define ARM_GICV3_ITS_COMMON(obj) \
-     OBJECT_CHECK(GICv3ITSState, (obj), TYPE_ARM_GICV3_ITS_COMMON)
-#define ARM_GICV3_ITS_COMMON_CLASS(klass) \
-     OBJECT_CLASS_CHECK(GICv3ITSCommonClass, (klass), TYPE_ARM_GICV3_ITS_COMMON)
-#define ARM_GICV3_ITS_COMMON_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(GICv3ITSCommonClass, (obj), TYPE_ARM_GICV3_ITS_COMMON)
+typedef struct GICv3ITSCommonClass GICv3ITSCommonClass;
+DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSCommonClass,
+                     ARM_GICV3_ITS_COMMON, TYPE_ARM_GICV3_ITS_COMMON)
 
 struct GICv3ITSCommonClass {
     /*< private >*/
@@ -81,6 +79,5 @@ struct GICv3ITSCommonClass {
     void (*post_load)(GICv3ITSState *s);
 };
 
-typedef struct GICv3ITSCommonClass GICv3ITSCommonClass;
 
 #endif
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
index a472c9b8f0..bb087b23c3 100644
--- a/include/hw/intc/armv7m_nvic.h
+++ b/include/hw/intc/armv7m_nvic.h
@@ -13,11 +13,13 @@
 #include "target/arm/cpu.h"
 #include "hw/sysbus.h"
 #include "hw/timer/armv7m_systick.h"
+#include "qom/object.h"
 
 #define TYPE_NVIC "armv7m_nvic"
 
-#define NVIC(obj) \
-    OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
+typedef struct NVICState NVICState;
+DECLARE_INSTANCE_CHECKER(NVICState, NVIC,
+                         TYPE_NVIC)
 
 /* Highest permitted number of exceptions (architectural limit) */
 #define NVIC_MAX_VECTORS 512
@@ -35,7 +37,7 @@ typedef struct VecInfo {
     uint8_t level; /* exceptions <=15 never set level */
 } VecInfo;
 
-typedef struct NVICState {
+struct NVICState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -88,6 +90,6 @@ typedef struct NVICState {
     qemu_irq sysresetreq;
 
     SysTickState systick[M_REG_NUM_BANKS];
-} NVICState;
+};
 
 #endif
diff --git a/include/hw/intc/aspeed_vic.h b/include/hw/intc/aspeed_vic.h
index 107ff17c3b..8f2e67db5a 100644
--- a/include/hw/intc/aspeed_vic.h
+++ b/include/hw/intc/aspeed_vic.h
@@ -14,13 +14,16 @@
 #define ASPEED_VIC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_ASPEED_VIC "aspeed.vic"
-#define ASPEED_VIC(obj) OBJECT_CHECK(AspeedVICState, (obj), TYPE_ASPEED_VIC)
+typedef struct AspeedVICState AspeedVICState;
+DECLARE_INSTANCE_CHECKER(AspeedVICState, ASPEED_VIC,
+                         TYPE_ASPEED_VIC)
 
 #define ASPEED_VIC_NR_IRQS 51
 
-typedef struct AspeedVICState {
+struct AspeedVICState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -43,6 +46,6 @@ typedef struct AspeedVICState {
 
     /* 0=low-sensitive/falling-edge, 1=high-sensitive/rising-edge */
     uint64_t event;
-} AspeedVICState;
+};
 
 #endif /* ASPEED_VIC_H */
diff --git a/include/hw/intc/bcm2835_ic.h b/include/hw/intc/bcm2835_ic.h
index 392ded1cb3..fd4a767845 100644
--- a/include/hw/intc/bcm2835_ic.h
+++ b/include/hw/intc/bcm2835_ic.h
@@ -9,14 +9,17 @@
 #define BCM2835_IC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_BCM2835_IC "bcm2835-ic"
-#define BCM2835_IC(obj) OBJECT_CHECK(BCM2835ICState, (obj), TYPE_BCM2835_IC)
+typedef struct BCM2835ICState BCM2835ICState;
+DECLARE_INSTANCE_CHECKER(BCM2835ICState, BCM2835_IC,
+                         TYPE_BCM2835_IC)
 
 #define BCM2835_IC_GPU_IRQ "gpu-irq"
 #define BCM2835_IC_ARM_IRQ "arm-irq"
 
-typedef struct BCM2835ICState {
+struct BCM2835ICState {
     /*< private >*/
     SysBusDevice busdev;
     /*< public >*/
@@ -30,6 +33,6 @@ typedef struct BCM2835ICState {
     uint8_t arm_irq_level, arm_irq_enable;
     bool fiq_enable;
     uint8_t fiq_select;
-} BCM2835ICState;
+};
 
 #endif
diff --git a/include/hw/intc/bcm2836_control.h b/include/hw/intc/bcm2836_control.h
index 2c22405686..f23292776e 100644
--- a/include/hw/intc/bcm2836_control.h
+++ b/include/hw/intc/bcm2836_control.h
@@ -17,16 +17,18 @@
 
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
+#include "qom/object.h"
 
 /* 4 mailboxes per core, for 16 total */
 #define BCM2836_NCORES 4
 #define BCM2836_MBPERCORE 4
 
 #define TYPE_BCM2836_CONTROL "bcm2836-control"
-#define BCM2836_CONTROL(obj) \
-    OBJECT_CHECK(BCM2836ControlState, (obj), TYPE_BCM2836_CONTROL)
+typedef struct BCM2836ControlState BCM2836ControlState;
+DECLARE_INSTANCE_CHECKER(BCM2836ControlState, BCM2836_CONTROL,
+                         TYPE_BCM2836_CONTROL)
 
-typedef struct BCM2836ControlState {
+struct BCM2836ControlState {
     /*< private >*/
     SysBusDevice busdev;
     /*< public >*/
@@ -56,6 +58,6 @@ typedef struct BCM2836ControlState {
     /* outputs to CPU cores */
     qemu_irq irq[BCM2836_NCORES];
     qemu_irq fiq[BCM2836_NCORES];
-} BCM2836ControlState;
+};
 
 #endif
diff --git a/include/hw/intc/heathrow_pic.h b/include/hw/intc/heathrow_pic.h
index b163e27ab9..f8c9bc20ab 100644
--- a/include/hw/intc/heathrow_pic.h
+++ b/include/hw/intc/heathrow_pic.h
@@ -27,9 +27,12 @@
 #define HW_INTC_HEATHROW_PIC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_HEATHROW "heathrow"
-#define HEATHROW(obj) OBJECT_CHECK(HeathrowState, (obj), TYPE_HEATHROW)
+typedef struct HeathrowState HeathrowState;
+DECLARE_INSTANCE_CHECKER(HeathrowState, HEATHROW,
+                         TYPE_HEATHROW)
 
 typedef struct HeathrowPICState {
     uint32_t events;
@@ -38,13 +41,13 @@ typedef struct HeathrowPICState {
     uint32_t level_triggered;
 } HeathrowPICState;
 
-typedef struct HeathrowState {
+struct HeathrowState {
     SysBusDevice parent_obj;
 
     MemoryRegion mem;
     HeathrowPICState pics[2];
     qemu_irq irqs[1];
-} HeathrowState;
+};
 
 #define HEATHROW_NUM_IRQS 64
 
diff --git a/include/hw/intc/ibex_plic.h b/include/hw/intc/ibex_plic.h
index d8eb09b258..8da6b03805 100644
--- a/include/hw/intc/ibex_plic.h
+++ b/include/hw/intc/ibex_plic.h
@@ -20,12 +20,14 @@
 #define HW_IBEX_PLIC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_IBEX_PLIC "ibex-plic"
-#define IBEX_PLIC(obj) \
-    OBJECT_CHECK(IbexPlicState, (obj), TYPE_IBEX_PLIC)
+typedef struct IbexPlicState IbexPlicState;
+DECLARE_INSTANCE_CHECKER(IbexPlicState, IBEX_PLIC,
+                         TYPE_IBEX_PLIC)
 
-typedef struct IbexPlicState {
+struct IbexPlicState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -59,6 +61,6 @@ typedef struct IbexPlicState {
     uint32_t threshold_base;
 
     uint32_t claim_base;
-} IbexPlicState;
+};
 
 #endif /* HW_IBEX_PLIC_H */
diff --git a/include/hw/intc/imx_avic.h b/include/hw/intc/imx_avic.h
index 1b80769018..621742533c 100644
--- a/include/hw/intc/imx_avic.h
+++ b/include/hw/intc/imx_avic.h
@@ -18,9 +18,12 @@
 #define IMX_AVIC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_IMX_AVIC "imx.avic"
-#define IMX_AVIC(obj) OBJECT_CHECK(IMXAVICState, (obj), TYPE_IMX_AVIC)
+typedef struct IMXAVICState IMXAVICState;
+DECLARE_INSTANCE_CHECKER(IMXAVICState, IMX_AVIC,
+                         TYPE_IMX_AVIC)
 
 #define IMX_AVIC_NUM_IRQS 64
 
@@ -36,7 +39,7 @@
 #define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4)
 #define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD)
 
-typedef struct IMXAVICState{
+struct IMXAVICState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -50,6 +53,6 @@ typedef struct IMXAVICState{
     qemu_irq irq;
     qemu_irq fiq;
     uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */
-} IMXAVICState;
+};
 
 #endif /* IMX_AVIC_H */
diff --git a/include/hw/intc/imx_gpcv2.h b/include/hw/intc/imx_gpcv2.h
index ed978b24bb..2d8075e527 100644
--- a/include/hw/intc/imx_gpcv2.h
+++ b/include/hw/intc/imx_gpcv2.h
@@ -2,21 +2,24 @@
 #define IMX_GPCV2_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 enum IMXGPCv2Registers {
     GPC_NUM        = 0xE00 / sizeof(uint32_t),
 };
 
-typedef struct IMXGPCv2State {
+struct IMXGPCv2State {
     /*< private >*/
     SysBusDevice parent_obj;
 
     /*< public >*/
     MemoryRegion iomem;
     uint32_t     regs[GPC_NUM];
-} IMXGPCv2State;
+};
+typedef struct IMXGPCv2State IMXGPCv2State;
 
 #define TYPE_IMX_GPCV2 "imx-gpcv2"
-#define IMX_GPCV2(obj) OBJECT_CHECK(IMXGPCv2State, (obj), TYPE_IMX_GPCV2)
+DECLARE_INSTANCE_CHECKER(IMXGPCv2State, IMX_GPCV2,
+                         TYPE_IMX_GPCV2)
 
 #endif /* IMX_GPCV2_H */
diff --git a/include/hw/intc/intc.h b/include/hw/intc/intc.h
index fb3e8e621f..7018f608ca 100644
--- a/include/hw/intc/intc.h
+++ b/include/hw/intc/intc.h
@@ -5,19 +5,16 @@
 
 #define TYPE_INTERRUPT_STATS_PROVIDER "intctrl"
 
-#define INTERRUPT_STATS_PROVIDER_CLASS(klass) \
-    OBJECT_CLASS_CHECK(InterruptStatsProviderClass, (klass), \
+typedef struct InterruptStatsProviderClass InterruptStatsProviderClass;
+DECLARE_CLASS_CHECKERS(InterruptStatsProviderClass, INTERRUPT_STATS_PROVIDER,
                        TYPE_INTERRUPT_STATS_PROVIDER)
-#define INTERRUPT_STATS_PROVIDER_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(InterruptStatsProviderClass, (obj), \
-                     TYPE_INTERRUPT_STATS_PROVIDER)
 #define INTERRUPT_STATS_PROVIDER(obj) \
     INTERFACE_CHECK(InterruptStatsProvider, (obj), \
                     TYPE_INTERRUPT_STATS_PROVIDER)
 
 typedef struct InterruptStatsProvider InterruptStatsProvider;
 
-typedef struct InterruptStatsProviderClass {
+struct InterruptStatsProviderClass {
     InterfaceClass parent;
 
     /* The returned pointer and statistics must remain valid until
@@ -26,6 +23,6 @@ typedef struct InterruptStatsProviderClass {
     bool (*get_statistics)(InterruptStatsProvider *obj, uint64_t **irq_counts,
                            unsigned int *nb_irqs);
     void (*print_info)(InterruptStatsProvider *obj, Monitor *mon);
-} InterruptStatsProviderClass;
+};
 
 #endif
diff --git a/include/hw/intc/mips_gic.h b/include/hw/intc/mips_gic.h
index 8428287bf9..65aa3a9a5e 100644
--- a/include/hw/intc/mips_gic.h
+++ b/include/hw/intc/mips_gic.h
@@ -15,6 +15,7 @@
 #include "hw/timer/mips_gictimer.h"
 #include "hw/sysbus.h"
 #include "cpu.h"
+#include "qom/object.h"
 /*
  * GIC Specific definitions
  */
@@ -170,13 +171,14 @@
 #define GIC_LOCAL_INT_WD        0 /* GIC watchdog */
 
 #define TYPE_MIPS_GIC "mips-gic"
-#define MIPS_GIC(obj) OBJECT_CHECK(MIPSGICState, (obj), TYPE_MIPS_GIC)
+typedef struct MIPSGICState MIPSGICState;
+DECLARE_INSTANCE_CHECKER(MIPSGICState, MIPS_GIC,
+                         TYPE_MIPS_GIC)
 
 /* Support up to 32 VPs and 256 IRQs */
 #define GIC_MAX_VPS             32
 #define GIC_MAX_INTRS           256
 
-typedef struct MIPSGICState MIPSGICState;
 typedef struct MIPSGICIRQState MIPSGICIRQState;
 typedef struct MIPSGICVPState MIPSGICVPState;
 
diff --git a/include/hw/intc/realview_gic.h b/include/hw/intc/realview_gic.h
index 1783ea11b9..a93ace87c8 100644
--- a/include/hw/intc/realview_gic.h
+++ b/include/hw/intc/realview_gic.h
@@ -12,17 +12,19 @@
 
 #include "hw/sysbus.h"
 #include "hw/intc/arm_gic.h"
+#include "qom/object.h"
 
 #define TYPE_REALVIEW_GIC "realview_gic"
-#define REALVIEW_GIC(obj) \
-    OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC)
+typedef struct RealViewGICState RealViewGICState;
+DECLARE_INSTANCE_CHECKER(RealViewGICState, REALVIEW_GIC,
+                         TYPE_REALVIEW_GIC)
 
-typedef struct RealViewGICState {
+struct RealViewGICState {
     SysBusDevice parent_obj;
 
     MemoryRegion container;
 
     GICState gic;
-} RealViewGICState;
+};
 
 #endif
diff --git a/include/hw/intc/rx_icu.h b/include/hw/intc/rx_icu.h
index 7176015cd9..ec02df35e3 100644
--- a/include/hw/intc/rx_icu.h
+++ b/include/hw/intc/rx_icu.h
@@ -22,6 +22,7 @@
 #define HW_INTC_RX_ICU_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 enum TRG_MODE {
     TRG_LEVEL = 0,
@@ -71,6 +72,7 @@ struct RXICUState {
 typedef struct RXICUState RXICUState;
 
 #define TYPE_RX_ICU "rx-icu"
-#define RX_ICU(obj) OBJECT_CHECK(RXICUState, (obj), TYPE_RX_ICU)
+DECLARE_INSTANCE_CHECKER(RXICUState, RX_ICU,
+                         TYPE_RX_ICU)
 
 #endif /* RX_ICU_H */
diff --git a/include/hw/intc/xlnx-pmu-iomod-intc.h b/include/hw/intc/xlnx-pmu-iomod-intc.h
index 0bd118884a..7a560e97af 100644
--- a/include/hw/intc/xlnx-pmu-iomod-intc.h
+++ b/include/hw/intc/xlnx-pmu-iomod-intc.h
@@ -27,16 +27,18 @@
 
 #include "hw/sysbus.h"
 #include "hw/register.h"
+#include "qom/object.h"
 
 #define TYPE_XLNX_PMU_IO_INTC "xlnx.pmu_io_intc"
 
-#define XLNX_PMU_IO_INTC(obj) \
-     OBJECT_CHECK(XlnxPMUIOIntc, (obj), TYPE_XLNX_PMU_IO_INTC)
+typedef struct XlnxPMUIOIntc XlnxPMUIOIntc;
+DECLARE_INSTANCE_CHECKER(XlnxPMUIOIntc, XLNX_PMU_IO_INTC,
+                         TYPE_XLNX_PMU_IO_INTC)
 
 /* This is R_PIT3_CONTROL + 1 */
 #define XLNXPMUIOINTC_R_MAX (0x78 + 1)
 
-typedef struct XlnxPMUIOIntc {
+struct XlnxPMUIOIntc {
     SysBusDevice parent_obj;
     MemoryRegion iomem;
 
@@ -52,6 +54,6 @@ typedef struct XlnxPMUIOIntc {
 
     uint32_t regs[XLNXPMUIOINTC_R_MAX];
     RegisterInfo regs_info[XLNXPMUIOINTC_R_MAX];
-} XlnxPMUIOIntc;
+};
 
 #endif /* HW_INTC_XLNX_PMU_IOMOD_INTC_H */
diff --git a/include/hw/intc/xlnx-zynqmp-ipi.h b/include/hw/intc/xlnx-zynqmp-ipi.h
index 866c719c6f..29c48db307 100644
--- a/include/hw/intc/xlnx-zynqmp-ipi.h
+++ b/include/hw/intc/xlnx-zynqmp-ipi.h
@@ -27,18 +27,20 @@
 
 #include "hw/sysbus.h"
 #include "hw/register.h"
+#include "qom/object.h"
 
 #define TYPE_XLNX_ZYNQMP_IPI "xlnx.zynqmp_ipi"
 
-#define XLNX_ZYNQMP_IPI(obj) \
-     OBJECT_CHECK(XlnxZynqMPIPI, (obj), TYPE_XLNX_ZYNQMP_IPI)
+typedef struct XlnxZynqMPIPI XlnxZynqMPIPI;
+DECLARE_INSTANCE_CHECKER(XlnxZynqMPIPI, XLNX_ZYNQMP_IPI,
+                         TYPE_XLNX_ZYNQMP_IPI)
 
 /* This is R_IPI_IDR + 1 */
 #define R_XLNX_ZYNQMP_IPI_MAX ((0x1c / 4) + 1)
 
 #define NUM_IPIS 11
 
-typedef struct XlnxZynqMPIPI {
+struct XlnxZynqMPIPI {
     /* Private */
     SysBusDevice parent_obj;
 
@@ -51,6 +53,6 @@ typedef struct XlnxZynqMPIPI {
 
     uint32_t regs[R_XLNX_ZYNQMP_IPI_MAX];
     RegisterInfo regs_info[R_XLNX_ZYNQMP_IPI_MAX];
-} XlnxZynqMPIPI;
+};
 
 #endif /* XLNX_ZYNQMP_IPI_H */
diff --git a/include/hw/ipack/ipack.h b/include/hw/ipack/ipack.h
index 1c07969bc9..a59a487853 100644
--- a/include/hw/ipack/ipack.h
+++ b/include/hw/ipack/ipack.h
@@ -12,11 +12,13 @@
 #define QEMU_IPACK_H
 
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 typedef struct IPackBus IPackBus;
 
 #define TYPE_IPACK_BUS "IndustryPack"
-#define IPACK_BUS(obj) OBJECT_CHECK(IPackBus, (obj), TYPE_IPACK_BUS)
+DECLARE_INSTANCE_CHECKER(IPackBus, IPACK_BUS,
+                         TYPE_IPACK_BUS)
 
 struct IPackBus {
     /*< private >*/
@@ -28,16 +30,10 @@ struct IPackBus {
     qemu_irq_handler set_irq;
 };
 
-typedef struct IPackDevice IPackDevice;
-typedef struct IPackDeviceClass IPackDeviceClass;
 
 #define TYPE_IPACK_DEVICE "ipack-device"
-#define IPACK_DEVICE(obj) \
-     OBJECT_CHECK(IPackDevice, (obj), TYPE_IPACK_DEVICE)
-#define IPACK_DEVICE_CLASS(klass)                                        \
-     OBJECT_CLASS_CHECK(IPackDeviceClass, (klass), TYPE_IPACK_DEVICE)
-#define IPACK_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(IPackDeviceClass, (obj), TYPE_IPACK_DEVICE)
+OBJECT_DECLARE_TYPE(IPackDevice, IPackDeviceClass,
+                    ipack_device, IPACK_DEVICE)
 
 struct IPackDeviceClass {
     /*< private >*/
diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h
index c1efdaa4cb..3fa5a4abd0 100644
--- a/include/hw/ipmi/ipmi.h
+++ b/include/hw/ipmi/ipmi.h
@@ -27,6 +27,7 @@
 
 #include "exec/memory.h"
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 #define MAX_IPMI_MSG_SIZE 300
 
@@ -110,14 +111,13 @@ uint32_t ipmi_next_uuid(void);
 #define TYPE_IPMI_INTERFACE "ipmi-interface"
 #define IPMI_INTERFACE(obj) \
      INTERFACE_CHECK(IPMIInterface, (obj), TYPE_IPMI_INTERFACE)
-#define IPMI_INTERFACE_CLASS(class) \
-     OBJECT_CLASS_CHECK(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE)
-#define IPMI_INTERFACE_GET_CLASS(class) \
-     OBJECT_GET_CLASS(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE)
+typedef struct IPMIInterfaceClass IPMIInterfaceClass;
+DECLARE_CLASS_CHECKERS(IPMIInterfaceClass, IPMI_INTERFACE,
+                       TYPE_IPMI_INTERFACE)
 
 typedef struct IPMIInterface IPMIInterface;
 
-typedef struct IPMIInterfaceClass {
+struct IPMIInterfaceClass {
     InterfaceClass parent;
 
     /*
@@ -170,28 +170,24 @@ typedef struct IPMIInterfaceClass {
      * Return the firmware info for a device.
      */
     void (*get_fwinfo)(struct IPMIInterface *s, IPMIFwInfo *info);
-} IPMIInterfaceClass;
+};
 
 /*
  * Define a BMC simulator (or perhaps a connection to a real BMC)
  */
 #define TYPE_IPMI_BMC "ipmi-bmc"
-#define IPMI_BMC(obj) \
-     OBJECT_CHECK(IPMIBmc, (obj), TYPE_IPMI_BMC)
-#define IPMI_BMC_CLASS(obj_class) \
-     OBJECT_CLASS_CHECK(IPMIBmcClass, (obj_class), TYPE_IPMI_BMC)
-#define IPMI_BMC_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(IPMIBmcClass, (obj), TYPE_IPMI_BMC)
-
-typedef struct IPMIBmc {
+OBJECT_DECLARE_TYPE(IPMIBmc, IPMIBmcClass,
+                    ipmi_bmc, IPMI_BMC)
+
+struct IPMIBmc {
     DeviceState parent;
 
     uint8_t slave_addr;
 
     IPMIInterface *intf;
-} IPMIBmc;
+};
 
-typedef struct IPMIBmcClass {
+struct IPMIBmcClass {
     DeviceClass parent;
 
     /* Called when the system resets to report to the bmc. */
@@ -204,7 +200,7 @@ typedef struct IPMIBmcClass {
                            uint8_t *cmd, unsigned int cmd_len,
                            unsigned int max_cmd_len,
                            uint8_t msg_id);
-} IPMIBmcClass;
+};
 
 /*
  * Add a link property to obj that points to a BMC.
@@ -268,10 +264,10 @@ int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
 void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log);
 
 #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
-#define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
-                                        TYPE_IPMI_BMC_SIMULATOR)
-
 typedef struct IPMIBmcSim IPMIBmcSim;
+DECLARE_INSTANCE_CHECKER(IPMIBmcSim, IPMI_BMC_SIMULATOR,
+                         TYPE_IPMI_BMC_SIMULATOR)
+
 
 typedef struct RspBuffer {
     uint8_t buffer[MAX_IPMI_MSG_SIZE];
diff --git a/include/hw/isa/i8259_internal.h b/include/hw/isa/i8259_internal.h
index 861d70d8f8..cd050bb9f2 100644
--- a/include/hw/isa/i8259_internal.h
+++ b/include/hw/isa/i8259_internal.h
@@ -28,24 +28,21 @@
 #include "hw/isa/isa.h"
 #include "hw/intc/intc.h"
 #include "hw/intc/i8259.h"
+#include "qom/object.h"
 
 typedef struct PICCommonState PICCommonState;
 
 #define TYPE_PIC_COMMON "pic-common"
-#define PIC_COMMON(obj) \
-     OBJECT_CHECK(PICCommonState, (obj), TYPE_PIC_COMMON)
-#define PIC_COMMON_CLASS(klass) \
-     OBJECT_CLASS_CHECK(PICCommonClass, (klass), TYPE_PIC_COMMON)
-#define PIC_COMMON_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PICCommonClass, (obj), TYPE_PIC_COMMON)
+typedef struct PICCommonClass PICCommonClass;
+DECLARE_OBJ_CHECKERS(PICCommonState, PICCommonClass,
+                     PIC_COMMON, TYPE_PIC_COMMON)
 
-typedef struct PICCommonClass
-{
+struct PICCommonClass {
     ISADeviceClass parent_class;
 
     void (*pre_save)(PICCommonState *s);
     void (*post_load)(PICCommonState *s);
-} PICCommonClass;
+};
 
 struct PICCommonState {
     ISADevice parent_obj;
diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
index 52b61eed88..ddb6a2d168 100644
--- a/include/hw/isa/isa.h
+++ b/include/hw/isa/isa.h
@@ -6,19 +6,18 @@
 #include "exec/memory.h"
 #include "exec/ioport.h"
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 #define ISA_NUM_IRQS 16
 
 #define TYPE_ISA_DEVICE "isa-device"
-#define ISA_DEVICE(obj) \
-     OBJECT_CHECK(ISADevice, (obj), TYPE_ISA_DEVICE)
-#define ISA_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(ISADeviceClass, (klass), TYPE_ISA_DEVICE)
-#define ISA_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(ISADeviceClass, (obj), TYPE_ISA_DEVICE)
+typedef struct ISADeviceClass ISADeviceClass;
+DECLARE_OBJ_CHECKERS(ISADevice, ISADeviceClass,
+                     ISA_DEVICE, TYPE_ISA_DEVICE)
 
 #define TYPE_ISA_BUS "ISA"
-#define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS)
+DECLARE_INSTANCE_CHECKER(ISABus, ISA_BUS,
+                         TYPE_ISA_BUS)
 
 #define TYPE_APPLE_SMC "isa-applesmc"
 #define APPLESMC_MAX_DATA_LENGTH       32
@@ -36,10 +35,9 @@ static inline uint16_t applesmc_port(void)
 
 #define TYPE_ISADMA "isa-dma"
 
-#define ISADMA_CLASS(klass) \
-    OBJECT_CLASS_CHECK(IsaDmaClass, (klass), TYPE_ISADMA)
-#define ISADMA_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(IsaDmaClass, (obj), TYPE_ISADMA)
+typedef struct IsaDmaClass IsaDmaClass;
+DECLARE_CLASS_CHECKERS(IsaDmaClass, ISADMA,
+                       TYPE_ISADMA)
 #define ISADMA(obj) \
     INTERFACE_CHECK(IsaDma, (obj), TYPE_ISADMA)
 
@@ -53,7 +51,7 @@ typedef enum {
 typedef int (*IsaDmaTransferHandler)(void *opaque, int nchan, int pos,
                                      int size);
 
-typedef struct IsaDmaClass {
+struct IsaDmaClass {
     InterfaceClass parent;
 
     bool (*has_autoinitialization)(IsaDma *obj, int nchan);
@@ -65,12 +63,12 @@ typedef struct IsaDmaClass {
     void (*register_channel)(IsaDma *obj, int nchan,
                              IsaDmaTransferHandler transfer_handler,
                              void *opaque);
-} IsaDmaClass;
+};
 
-typedef struct ISADeviceClass {
+struct ISADeviceClass {
     DeviceClass parent_class;
     void (*build_aml)(ISADevice *dev, Aml *scope);
-} ISADeviceClass;
+};
 
 struct ISABus {
     /*< private >*/
diff --git a/include/hw/isa/pc87312.h b/include/hw/isa/pc87312.h
index e16263d4b1..da8dc5ddf5 100644
--- a/include/hw/isa/pc87312.h
+++ b/include/hw/isa/pc87312.h
@@ -26,12 +26,15 @@
 #define QEMU_PC87312_H
 
 #include "hw/isa/superio.h"
+#include "qom/object.h"
 
 
-#define TYPE_PC87312_SUPERIO "pc87312"
-#define PC87312(obj) OBJECT_CHECK(PC87312State, (obj), TYPE_PC87312_SUPERIO)
+#define TYPE_PC87312 "pc87312"
+typedef struct PC87312State PC87312State;
+DECLARE_INSTANCE_CHECKER(PC87312State, PC87312,
+                         TYPE_PC87312)
 
-typedef struct PC87312State {
+struct PC87312State {
     /*< private >*/
     ISASuperIODevice parent_dev;
     /*< public >*/
@@ -49,7 +52,7 @@ typedef struct PC87312State {
     uint8_t selected_index;
 
     uint8_t regs[3];
-} PC87312State;
+};
 
 
 #endif
diff --git a/include/hw/isa/superio.h b/include/hw/isa/superio.h
index 147cc0a7b7..b9f5c19155 100644
--- a/include/hw/isa/superio.h
+++ b/include/hw/isa/superio.h
@@ -12,18 +12,17 @@
 
 #include "sysemu/sysemu.h"
 #include "hw/isa/isa.h"
+#include "qom/object.h"
 
 #define TYPE_ISA_SUPERIO "isa-superio"
-#define ISA_SUPERIO(obj) \
-    OBJECT_CHECK(ISASuperIODevice, (obj), TYPE_ISA_SUPERIO)
-#define ISA_SUPERIO_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(ISASuperIOClass, (obj), TYPE_ISA_SUPERIO)
-#define ISA_SUPERIO_CLASS(klass) \
-    OBJECT_CLASS_CHECK(ISASuperIOClass, (klass), TYPE_ISA_SUPERIO)
+typedef struct ISASuperIOClass ISASuperIOClass;
+typedef struct ISASuperIODevice ISASuperIODevice;
+DECLARE_OBJ_CHECKERS(ISASuperIODevice, ISASuperIOClass,
+                     ISA_SUPERIO, TYPE_ISA_SUPERIO)
 
 #define SUPERIO_MAX_SERIAL_PORTS 4
 
-typedef struct ISASuperIODevice {
+struct ISASuperIODevice {
     /*< private >*/
     ISADevice parent_obj;
     /*< public >*/
@@ -33,7 +32,7 @@ typedef struct ISASuperIODevice {
     ISADevice *floppy;
     ISADevice *kbc;
     ISADevice *ide;
-} ISASuperIODevice;
+};
 
 typedef struct ISASuperIOFuncs {
     size_t count;
@@ -43,7 +42,7 @@ typedef struct ISASuperIOFuncs {
     unsigned int (*get_dma)(ISASuperIODevice *sio, uint8_t index);
 } ISASuperIOFuncs;
 
-typedef struct ISASuperIOClass {
+struct ISASuperIOClass {
     /*< private >*/
     ISADeviceClass parent_class;
     /*< public >*/
@@ -53,7 +52,7 @@ typedef struct ISASuperIOClass {
     ISASuperIOFuncs serial;
     ISASuperIOFuncs floppy;
     ISASuperIOFuncs ide;
-} ISASuperIOClass;
+};
 
 #define TYPE_FDC37M81X_SUPERIO  "fdc37m81x-superio"
 #define TYPE_SMC37C669_SUPERIO  "smc37c669-superio"
diff --git a/include/hw/m68k/mcf_fec.h b/include/hw/m68k/mcf_fec.h
index c09e33a57c..840c5bbf53 100644
--- a/include/hw/m68k/mcf_fec.h
+++ b/include/hw/m68k/mcf_fec.h
@@ -9,10 +9,12 @@
 
 #ifndef HW_M68K_MCF_FEC_H
 #define HW_M68K_MCF_FEC_H
+#include "qom/object.h"
 
 #define TYPE_MCF_FEC_NET "mcf-fec"
 typedef struct mcf_fec_state mcf_fec_state;
-#define MCF_FEC_NET(obj) OBJECT_CHECK(mcf_fec_state, (obj), TYPE_MCF_FEC_NET)
+DECLARE_INSTANCE_CHECKER(mcf_fec_state, MCF_FEC_NET,
+                         TYPE_MCF_FEC_NET)
 
 #define FEC_NUM_IRQ 13
 
diff --git a/include/hw/mem/memory-device.h b/include/hw/mem/memory-device.h
index 04476acb8f..cde52e83c9 100644
--- a/include/hw/mem/memory-device.h
+++ b/include/hw/mem/memory-device.h
@@ -19,10 +19,9 @@
 
 #define TYPE_MEMORY_DEVICE "memory-device"
 
-#define MEMORY_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(MemoryDeviceClass, (klass), TYPE_MEMORY_DEVICE)
-#define MEMORY_DEVICE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(MemoryDeviceClass, (obj), TYPE_MEMORY_DEVICE)
+typedef struct MemoryDeviceClass MemoryDeviceClass;
+DECLARE_CLASS_CHECKERS(MemoryDeviceClass, MEMORY_DEVICE,
+                       TYPE_MEMORY_DEVICE)
 #define MEMORY_DEVICE(obj) \
      INTERFACE_CHECK(MemoryDeviceState, (obj), TYPE_MEMORY_DEVICE)
 
@@ -43,7 +42,7 @@ typedef struct MemoryDeviceState MemoryDeviceState;
  * be provided. Scattered memory regions are not supported for single
  * devices.
  */
-typedef struct MemoryDeviceClass {
+struct MemoryDeviceClass {
     /* private */
     InterfaceClass parent_class;
 
@@ -94,7 +93,7 @@ typedef struct MemoryDeviceClass {
      */
     void (*fill_device_info)(const MemoryDeviceState *md,
                              MemoryDeviceInfo *info);
-} MemoryDeviceClass;
+};
 
 MemoryDeviceInfoList *qmp_memory_device_list(void);
 uint64_t get_plugged_memory_size(void);
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index b67a1aedf6..19e3d3092d 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -27,6 +27,7 @@
 #include "hw/acpi/bios-linker-loader.h"
 #include "qemu/uuid.h"
 #include "hw/acpi/aml-build.h"
+#include "qom/object.h"
 
 #define NVDIMM_DEBUG 0
 #define nvdimm_debug(fmt, ...)                                \
@@ -45,10 +46,10 @@
 #define MIN_NAMESPACE_LABEL_SIZE      (128UL << 10)
 
 #define TYPE_NVDIMM      "nvdimm"
-#define NVDIMM(obj)      OBJECT_CHECK(NVDIMMDevice, (obj), TYPE_NVDIMM)
-#define NVDIMM_CLASS(oc) OBJECT_CLASS_CHECK(NVDIMMClass, (oc), TYPE_NVDIMM)
-#define NVDIMM_GET_CLASS(obj) OBJECT_GET_CLASS(NVDIMMClass, (obj), \
-                                               TYPE_NVDIMM)
+typedef struct NVDIMMClass NVDIMMClass;
+typedef struct NVDIMMDevice NVDIMMDevice;
+DECLARE_OBJ_CHECKERS(NVDIMMDevice, NVDIMMClass,
+                     NVDIMM, TYPE_NVDIMM)
 
 #define NVDIMM_LABEL_SIZE_PROP "label-size"
 #define NVDIMM_UUID_PROP       "uuid"
@@ -92,7 +93,6 @@ struct NVDIMMDevice {
      */
     QemuUUID uuid;
 };
-typedef struct NVDIMMDevice NVDIMMDevice;
 
 struct NVDIMMClass {
     /* private */
@@ -107,7 +107,6 @@ struct NVDIMMClass {
     void (*write_label_data)(NVDIMMDevice *nvdimm, const void *buf,
                              uint64_t size, uint64_t offset);
 };
-typedef struct NVDIMMClass NVDIMMClass;
 
 #define NVDIMM_DSM_MEM_FILE     "etc/acpi/nvdimm-mem"
 
diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
index 289edc0f3d..1d570defc9 100644
--- a/include/hw/mem/pc-dimm.h
+++ b/include/hw/mem/pc-dimm.h
@@ -18,14 +18,11 @@
 
 #include "exec/memory.h"
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 #define TYPE_PC_DIMM "pc-dimm"
-#define PC_DIMM(obj) \
-    OBJECT_CHECK(PCDIMMDevice, (obj), TYPE_PC_DIMM)
-#define PC_DIMM_CLASS(oc) \
-    OBJECT_CLASS_CHECK(PCDIMMDeviceClass, (oc), TYPE_PC_DIMM)
-#define PC_DIMM_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(PCDIMMDeviceClass, (obj), TYPE_PC_DIMM)
+OBJECT_DECLARE_TYPE(PCDIMMDevice, PCDIMMDeviceClass,
+                    pc_dimm, PC_DIMM)
 
 #define PC_DIMM_ADDR_PROP "addr"
 #define PC_DIMM_SLOT_PROP "slot"
@@ -44,7 +41,7 @@
  *        Default value: -1, means that slot is auto-allocated.
  * @hostmem: host memory backend providing memory for @PCDIMMDevice
  */
-typedef struct PCDIMMDevice {
+struct PCDIMMDevice {
     /* private */
     DeviceState parent_obj;
 
@@ -53,7 +50,7 @@ typedef struct PCDIMMDevice {
     uint32_t node;
     int32_t slot;
     HostMemoryBackend *hostmem;
-} PCDIMMDevice;
+};
 
 /**
  * PCDIMMDeviceClass:
@@ -63,7 +60,7 @@ typedef struct PCDIMMDevice {
  * memory of @dimm should be kept during live migration. Will not fail
  * after the device was realized.
  */
-typedef struct PCDIMMDeviceClass {
+struct PCDIMMDeviceClass {
     /* private */
     DeviceClass parent_class;
 
@@ -71,7 +68,7 @@ typedef struct PCDIMMDeviceClass {
     void (*realize)(PCDIMMDevice *dimm, Error **errp);
     MemoryRegion *(*get_vmstate_memory_region)(PCDIMMDevice *dimm,
                                                Error **errp);
-} PCDIMMDeviceClass;
+};
 
 void pc_dimm_pre_plug(PCDIMMDevice *dimm, MachineState *machine,
                       const uint64_t *legacy_align, Error **errp);
diff --git a/include/hw/mips/cps.h b/include/hw/mips/cps.h
index a941c55f27..849e640570 100644
--- a/include/hw/mips/cps.h
+++ b/include/hw/mips/cps.h
@@ -26,11 +26,14 @@
 #include "hw/misc/mips_cpc.h"
 #include "hw/misc/mips_itu.h"
 #include "target/mips/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_MIPS_CPS "mips-cps"
-#define MIPS_CPS(obj) OBJECT_CHECK(MIPSCPSState, (obj), TYPE_MIPS_CPS)
+typedef struct MIPSCPSState MIPSCPSState;
+DECLARE_INSTANCE_CHECKER(MIPSCPSState, MIPS_CPS,
+                         TYPE_MIPS_CPS)
 
-typedef struct MIPSCPSState {
+struct MIPSCPSState {
     SysBusDevice parent_obj;
 
     uint32_t num_vp;
@@ -42,7 +45,7 @@ typedef struct MIPSCPSState {
     MIPSGICState gic;
     MIPSCPCState cpc;
     MIPSITUState itu;
-} MIPSCPSState;
+};
 
 qemu_irq get_cps_irq(MIPSCPSState *cps, int pin_number);
 
diff --git a/include/hw/misc/a9scu.h b/include/hw/misc/a9scu.h
index efb0c305c2..fd1b92e923 100644
--- a/include/hw/misc/a9scu.h
+++ b/include/hw/misc/a9scu.h
@@ -11,10 +11,11 @@
 #define HW_MISC_A9SCU_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 /* A9MP private memory region.  */
 
-typedef struct A9SCUState {
+struct A9SCUState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -23,9 +24,11 @@ typedef struct A9SCUState {
     uint32_t control;
     uint32_t status;
     uint32_t num_cpu;
-} A9SCUState;
+};
+typedef struct A9SCUState A9SCUState;
 
 #define TYPE_A9_SCU "a9-scu"
-#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU)
+DECLARE_INSTANCE_CHECKER(A9SCUState, A9_SCU,
+                         TYPE_A9_SCU)
 
 #endif
diff --git a/include/hw/misc/allwinner-cpucfg.h b/include/hw/misc/allwinner-cpucfg.h
index 2c3693a8be..058514de15 100644
--- a/include/hw/misc/allwinner-cpucfg.h
+++ b/include/hw/misc/allwinner-cpucfg.h
@@ -29,15 +29,16 @@
  */
 
 #define TYPE_AW_CPUCFG   "allwinner-cpucfg"
-#define AW_CPUCFG(obj) \
-    OBJECT_CHECK(AwCpuCfgState, (obj), TYPE_AW_CPUCFG)
+typedef struct AwCpuCfgState AwCpuCfgState;
+DECLARE_INSTANCE_CHECKER(AwCpuCfgState, AW_CPUCFG,
+                         TYPE_AW_CPUCFG)
 
 /** @} */
 
 /**
  * Allwinner CPU Configuration Module instance state
  */
-typedef struct AwCpuCfgState {
+struct AwCpuCfgState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -47,6 +48,6 @@ typedef struct AwCpuCfgState {
     uint32_t super_standby;
     uint32_t entry_addr;
 
-} AwCpuCfgState;
+};
 
 #endif /* HW_MISC_ALLWINNER_CPUCFG_H */
diff --git a/include/hw/misc/allwinner-h3-ccu.h b/include/hw/misc/allwinner-h3-ccu.h
index eec59649f3..05f5c7bd8e 100644
--- a/include/hw/misc/allwinner-h3-ccu.h
+++ b/include/hw/misc/allwinner-h3-ccu.h
@@ -42,15 +42,16 @@
  */
 
 #define TYPE_AW_H3_CCU    "allwinner-h3-ccu"
-#define AW_H3_CCU(obj) \
-    OBJECT_CHECK(AwH3ClockCtlState, (obj), TYPE_AW_H3_CCU)
+typedef struct AwH3ClockCtlState AwH3ClockCtlState;
+DECLARE_INSTANCE_CHECKER(AwH3ClockCtlState, AW_H3_CCU,
+                         TYPE_AW_H3_CCU)
 
 /** @} */
 
 /**
  * Allwinner H3 CCU object instance state.
  */
-typedef struct AwH3ClockCtlState {
+struct AwH3ClockCtlState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -61,6 +62,6 @@ typedef struct AwH3ClockCtlState {
     /** Array of hardware registers */
     uint32_t regs[AW_H3_CCU_REGS_NUM];
 
-} AwH3ClockCtlState;
+};
 
 #endif /* HW_MISC_ALLWINNER_H3_CCU_H */
diff --git a/include/hw/misc/allwinner-h3-dramc.h b/include/hw/misc/allwinner-h3-dramc.h
index bacdf236b7..60a13a6958 100644
--- a/include/hw/misc/allwinner-h3-dramc.h
+++ b/include/hw/misc/allwinner-h3-dramc.h
@@ -58,15 +58,16 @@
  */
 
 #define TYPE_AW_H3_DRAMC "allwinner-h3-dramc"
-#define AW_H3_DRAMC(obj) \
-    OBJECT_CHECK(AwH3DramCtlState, (obj), TYPE_AW_H3_DRAMC)
+typedef struct AwH3DramCtlState AwH3DramCtlState;
+DECLARE_INSTANCE_CHECKER(AwH3DramCtlState, AW_H3_DRAMC,
+                         TYPE_AW_H3_DRAMC)
 
 /** @} */
 
 /**
  * Allwinner H3 SDRAM Controller object instance state.
  */
-typedef struct AwH3DramCtlState {
+struct AwH3DramCtlState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -101,6 +102,6 @@ typedef struct AwH3DramCtlState {
 
     /** @} */
 
-} AwH3DramCtlState;
+};
 
 #endif /* HW_MISC_ALLWINNER_H3_DRAMC_H */
diff --git a/include/hw/misc/allwinner-h3-sysctrl.h b/include/hw/misc/allwinner-h3-sysctrl.h
index af4119e026..50baa8eb07 100644
--- a/include/hw/misc/allwinner-h3-sysctrl.h
+++ b/include/hw/misc/allwinner-h3-sysctrl.h
@@ -43,15 +43,16 @@
  */
 
 #define TYPE_AW_H3_SYSCTRL    "allwinner-h3-sysctrl"
-#define AW_H3_SYSCTRL(obj) \
-    OBJECT_CHECK(AwH3SysCtrlState, (obj), TYPE_AW_H3_SYSCTRL)
+typedef struct AwH3SysCtrlState AwH3SysCtrlState;
+DECLARE_INSTANCE_CHECKER(AwH3SysCtrlState, AW_H3_SYSCTRL,
+                         TYPE_AW_H3_SYSCTRL)
 
 /** @} */
 
 /**
  * Allwinner H3 System Control object instance state
  */
-typedef struct AwH3SysCtrlState {
+struct AwH3SysCtrlState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -62,6 +63,6 @@ typedef struct AwH3SysCtrlState {
     /** Array of hardware registers */
     uint32_t regs[AW_H3_SYSCTRL_REGS_NUM];
 
-} AwH3SysCtrlState;
+};
 
 #endif /* HW_MISC_ALLWINNER_H3_SYSCTRL_H */
diff --git a/include/hw/misc/allwinner-sid.h b/include/hw/misc/allwinner-sid.h
index 4c1fa4762b..b8e83bb7ce 100644
--- a/include/hw/misc/allwinner-sid.h
+++ b/include/hw/misc/allwinner-sid.h
@@ -30,15 +30,16 @@
  */
 
 #define TYPE_AW_SID    "allwinner-sid"
-#define AW_SID(obj) \
-    OBJECT_CHECK(AwSidState, (obj), TYPE_AW_SID)
+typedef struct AwSidState AwSidState;
+DECLARE_INSTANCE_CHECKER(AwSidState, AW_SID,
+                         TYPE_AW_SID)
 
 /** @} */
 
 /**
  * Allwinner Security ID object instance state
  */
-typedef struct AwSidState {
+struct AwSidState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -55,6 +56,6 @@ typedef struct AwSidState {
     /** Stores the emulated device identifier */
     QemuUUID identifier;
 
-} AwSidState;
+};
 
 #endif /* HW_MISC_ALLWINNER_SID_H */
diff --git a/include/hw/misc/arm11scu.h b/include/hw/misc/arm11scu.h
index 5ad0f3d339..71b4bc9a22 100644
--- a/include/hw/misc/arm11scu.h
+++ b/include/hw/misc/arm11scu.h
@@ -12,11 +12,14 @@
 #define HW_MISC_ARM11SCU_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_ARM11_SCU "arm11-scu"
-#define ARM11_SCU(obj) OBJECT_CHECK(ARM11SCUState, (obj), TYPE_ARM11_SCU)
+typedef struct ARM11SCUState ARM11SCUState;
+DECLARE_INSTANCE_CHECKER(ARM11SCUState, ARM11_SCU,
+                         TYPE_ARM11_SCU)
 
-typedef struct ARM11SCUState {
+struct ARM11SCUState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -24,6 +27,6 @@ typedef struct ARM11SCUState {
     uint32_t control;
     uint32_t num_cpu;
     MemoryRegion iomem;
-} ARM11SCUState;
+};
 
 #endif
diff --git a/include/hw/misc/armsse-cpuid.h b/include/hw/misc/armsse-cpuid.h
index 0ef33fcaba..80691c7180 100644
--- a/include/hw/misc/armsse-cpuid.h
+++ b/include/hw/misc/armsse-cpuid.h
@@ -23,11 +23,14 @@
 #define HW_MISC_ARMSSE_CPUID_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_ARMSSE_CPUID "armsse-cpuid"
-#define ARMSSE_CPUID(obj) OBJECT_CHECK(ARMSSECPUID, (obj), TYPE_ARMSSE_CPUID)
+typedef struct ARMSSECPUID ARMSSECPUID;
+DECLARE_INSTANCE_CHECKER(ARMSSECPUID, ARMSSE_CPUID,
+                         TYPE_ARMSSE_CPUID)
 
-typedef struct ARMSSECPUID {
+struct ARMSSECPUID {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -36,6 +39,6 @@ typedef struct ARMSSECPUID {
 
     /* Properties */
     uint32_t cpuid;
-} ARMSSECPUID;
+};
 
 #endif
diff --git a/include/hw/misc/armsse-mhu.h b/include/hw/misc/armsse-mhu.h
index cf5d8a73e6..310643a022 100644
--- a/include/hw/misc/armsse-mhu.h
+++ b/include/hw/misc/armsse-mhu.h
@@ -24,11 +24,14 @@
 #define HW_MISC_ARMSSE_MHU_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_ARMSSE_MHU "armsse-mhu"
-#define ARMSSE_MHU(obj) OBJECT_CHECK(ARMSSEMHU, (obj), TYPE_ARMSSE_MHU)
+typedef struct ARMSSEMHU ARMSSEMHU;
+DECLARE_INSTANCE_CHECKER(ARMSSEMHU, ARMSSE_MHU,
+                         TYPE_ARMSSE_MHU)
 
-typedef struct ARMSSEMHU {
+struct ARMSSEMHU {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -39,6 +42,6 @@ typedef struct ARMSSEMHU {
 
     uint32_t cpu0intr;
     uint32_t cpu1intr;
-} ARMSSEMHU;
+};
 
 #endif
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
index 9cd530afa2..8d3b14acd4 100644
--- a/include/hw/misc/aspeed_scu.h
+++ b/include/hw/misc/aspeed_scu.h
@@ -12,9 +12,13 @@
 #define ASPEED_SCU_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_ASPEED_SCU "aspeed.scu"
-#define ASPEED_SCU(obj) OBJECT_CHECK(AspeedSCUState, (obj), TYPE_ASPEED_SCU)
+typedef struct AspeedSCUClass AspeedSCUClass;
+typedef struct AspeedSCUState AspeedSCUState;
+DECLARE_OBJ_CHECKERS(AspeedSCUState, AspeedSCUClass,
+                     ASPEED_SCU, TYPE_ASPEED_SCU)
 #define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400"
 #define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500"
 #define TYPE_ASPEED_2600_SCU TYPE_ASPEED_SCU "-ast2600"
@@ -22,7 +26,7 @@
 #define ASPEED_SCU_NR_REGS (0x1A8 >> 2)
 #define ASPEED_AST2600_SCU_NR_REGS (0xE20 >> 2)
 
-typedef struct AspeedSCUState {
+struct AspeedSCUState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -34,7 +38,7 @@ typedef struct AspeedSCUState {
     uint32_t hw_strap1;
     uint32_t hw_strap2;
     uint32_t hw_prot_key;
-} AspeedSCUState;
+};
 
 #define AST2400_A0_SILICON_REV   0x02000303U
 #define AST2400_A1_SILICON_REV   0x02010303U
@@ -47,12 +51,8 @@ typedef struct AspeedSCUState {
 
 extern bool is_supported_silicon_rev(uint32_t silicon_rev);
 
-#define ASPEED_SCU_CLASS(klass) \
-     OBJECT_CLASS_CHECK(AspeedSCUClass, (klass), TYPE_ASPEED_SCU)
-#define ASPEED_SCU_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(AspeedSCUClass, (obj), TYPE_ASPEED_SCU)
 
-typedef struct  AspeedSCUClass {
+struct AspeedSCUClass {
     SysBusDeviceClass parent_class;
 
     const uint32_t *resets;
@@ -60,7 +60,7 @@ typedef struct  AspeedSCUClass {
     uint32_t apb_divider;
     uint32_t nr_regs;
     const MemoryRegionOps *ops;
-}  AspeedSCUClass;
+};
 
 #define ASPEED_SCU_PROT_KEY      0x1688A8A8
 
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
index c6226957dd..3375afc89b 100644
--- a/include/hw/misc/aspeed_sdmc.h
+++ b/include/hw/misc/aspeed_sdmc.h
@@ -10,9 +10,13 @@
 #define ASPEED_SDMC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_ASPEED_SDMC "aspeed.sdmc"
-#define ASPEED_SDMC(obj) OBJECT_CHECK(AspeedSDMCState, (obj), TYPE_ASPEED_SDMC)
+typedef struct AspeedSDMCClass AspeedSDMCClass;
+typedef struct AspeedSDMCState AspeedSDMCState;
+DECLARE_OBJ_CHECKERS(AspeedSDMCState, AspeedSDMCClass,
+                     ASPEED_SDMC, TYPE_ASPEED_SDMC)
 #define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400"
 #define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500"
 #define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600"
@@ -30,7 +34,7 @@
  */
 #define ASPEED_SDMC_NR_REGS (0x500 >> 2)
 
-typedef struct AspeedSDMCState {
+struct AspeedSDMCState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -40,20 +44,16 @@ typedef struct AspeedSDMCState {
     uint32_t regs[ASPEED_SDMC_NR_REGS];
     uint64_t ram_size;
     uint64_t max_ram_size;
-} AspeedSDMCState;
+};
 
-#define ASPEED_SDMC_CLASS(klass) \
-     OBJECT_CLASS_CHECK(AspeedSDMCClass, (klass), TYPE_ASPEED_SDMC)
-#define ASPEED_SDMC_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(AspeedSDMCClass, (obj), TYPE_ASPEED_SDMC)
 
-typedef struct AspeedSDMCClass {
+struct AspeedSDMCClass {
     SysBusDeviceClass parent_class;
 
     uint64_t max_ram_size;
     const uint64_t *valid_ram_sizes;
     uint32_t (*compute_conf)(AspeedSDMCState *s, uint32_t data);
     void (*write)(AspeedSDMCState *s, uint32_t reg, uint32_t data);
-} AspeedSDMCClass;
+};
 
 #endif /* ASPEED_SDMC_H */
diff --git a/include/hw/misc/aspeed_xdma.h b/include/hw/misc/aspeed_xdma.h
index 00b45d931f..0e62c04520 100644
--- a/include/hw/misc/aspeed_xdma.h
+++ b/include/hw/misc/aspeed_xdma.h
@@ -10,14 +10,17 @@
 #define ASPEED_XDMA_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_ASPEED_XDMA "aspeed.xdma"
-#define ASPEED_XDMA(obj) OBJECT_CHECK(AspeedXDMAState, (obj), TYPE_ASPEED_XDMA)
+typedef struct AspeedXDMAState AspeedXDMAState;
+DECLARE_INSTANCE_CHECKER(AspeedXDMAState, ASPEED_XDMA,
+                         TYPE_ASPEED_XDMA)
 
 #define ASPEED_XDMA_NUM_REGS (ASPEED_XDMA_REG_SIZE / sizeof(uint32_t))
 #define ASPEED_XDMA_REG_SIZE 0x7C
 
-typedef struct AspeedXDMAState {
+struct AspeedXDMAState {
     SysBusDevice parent;
 
     MemoryRegion iomem;
@@ -25,6 +28,6 @@ typedef struct AspeedXDMAState {
 
     char bmc_cmdq_readp_set;
     uint32_t regs[ASPEED_XDMA_NUM_REGS];
-} AspeedXDMAState;
+};
 
 #endif /* ASPEED_XDMA_H */
diff --git a/include/hw/misc/auxbus.h b/include/hw/misc/auxbus.h
index 041edfc9e9..f910d94118 100644
--- a/include/hw/misc/auxbus.h
+++ b/include/hw/misc/auxbus.h
@@ -27,6 +27,7 @@
 
 #include "exec/memory.h"
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 typedef struct AUXBus AUXBus;
 typedef struct AUXSlave AUXSlave;
@@ -35,7 +36,8 @@ typedef enum AUXReply AUXReply;
 
 #define TYPE_AUXTOI2C "aux-to-i2c-bridge"
 typedef struct AUXTOI2CState AUXTOI2CState;
-#define AUXTOI2C(obj) OBJECT_CHECK(AUXTOI2CState, (obj), TYPE_AUXTOI2C)
+DECLARE_INSTANCE_CHECKER(AUXTOI2CState, AUXTOI2C,
+                         TYPE_AUXTOI2C)
 
 enum AUXCommand {
     WRITE_I2C = 0,
@@ -56,7 +58,8 @@ enum AUXReply {
 };
 
 #define TYPE_AUX_BUS "aux-bus"
-#define AUX_BUS(obj) OBJECT_CHECK(AUXBus, (obj), TYPE_AUX_BUS)
+DECLARE_INSTANCE_CHECKER(AUXBus, AUX_BUS,
+                         TYPE_AUX_BUS)
 
 struct AUXBus {
     /* < private > */
@@ -75,8 +78,8 @@ struct AUXBus {
 };
 
 #define TYPE_AUX_SLAVE "aux-slave"
-#define AUX_SLAVE(obj) \
-     OBJECT_CHECK(AUXSlave, (obj), TYPE_AUX_SLAVE)
+DECLARE_INSTANCE_CHECKER(AUXSlave, AUX_SLAVE,
+                         TYPE_AUX_SLAVE)
 
 struct AUXSlave {
     /* < private > */
diff --git a/include/hw/misc/avr_power.h b/include/hw/misc/avr_power.h
index e08e44f629..938ab3e21b 100644
--- a/include/hw/misc/avr_power.h
+++ b/include/hw/misc/avr_power.h
@@ -27,12 +27,15 @@
 
 #include "hw/sysbus.h"
 #include "hw/hw.h"
+#include "qom/object.h"
 
 
 #define TYPE_AVR_MASK "avr-power"
-#define AVR_MASK(obj) OBJECT_CHECK(AVRMaskState, (obj), TYPE_AVR_MASK)
+typedef struct AVRMaskState AVRMaskState;
+DECLARE_INSTANCE_CHECKER(AVRMaskState, AVR_MASK,
+                         TYPE_AVR_MASK)
 
-typedef struct {
+struct AVRMaskState {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -41,6 +44,6 @@ typedef struct {
 
     uint8_t val;
     qemu_irq irq[8];
-} AVRMaskState;
+};
 
 #endif /* HW_MISC_AVR_POWER_H */
diff --git a/include/hw/misc/bcm2835_mbox.h b/include/hw/misc/bcm2835_mbox.h
index 57f95cc35e..d8c8017f4e 100644
--- a/include/hw/misc/bcm2835_mbox.h
+++ b/include/hw/misc/bcm2835_mbox.h
@@ -10,10 +10,12 @@
 
 #include "bcm2835_mbox_defs.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_BCM2835_MBOX "bcm2835-mbox"
-#define BCM2835_MBOX(obj) \
-        OBJECT_CHECK(BCM2835MboxState, (obj), TYPE_BCM2835_MBOX)
+typedef struct BCM2835MboxState BCM2835MboxState;
+DECLARE_INSTANCE_CHECKER(BCM2835MboxState, BCM2835_MBOX,
+                         TYPE_BCM2835_MBOX)
 
 typedef struct {
     uint32_t reg[MBOX_SIZE];
@@ -22,7 +24,7 @@ typedef struct {
     uint32_t config;
 } BCM2835Mbox;
 
-typedef struct {
+struct BCM2835MboxState {
     /*< private >*/
     SysBusDevice busdev;
     /*< public >*/
@@ -34,6 +36,6 @@ typedef struct {
     bool mbox_irq_disabled;
     bool available[MBOX_CHAN_COUNT];
     BCM2835Mbox mbox[2];
-} BCM2835MboxState;
+};
 
 #endif
diff --git a/include/hw/misc/bcm2835_mphi.h b/include/hw/misc/bcm2835_mphi.h
index e084314d0f..249511182e 100644
--- a/include/hw/misc/bcm2835_mphi.h
+++ b/include/hw/misc/bcm2835_mphi.h
@@ -19,6 +19,7 @@
 
 #include "hw/irq.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define MPHI_MMIO_SIZE      0x1000
 
@@ -38,7 +39,7 @@ struct BCM2835MphiState {
 
 #define TYPE_BCM2835_MPHI   "bcm2835-mphi"
 
-#define BCM2835_MPHI(obj) \
-    OBJECT_CHECK(BCM2835MphiState, (obj), TYPE_BCM2835_MPHI)
+DECLARE_INSTANCE_CHECKER(BCM2835MphiState, BCM2835_MPHI,
+                         TYPE_BCM2835_MPHI)
 
 #endif
diff --git a/include/hw/misc/bcm2835_property.h b/include/hw/misc/bcm2835_property.h
index b321f22499..5c827a1900 100644
--- a/include/hw/misc/bcm2835_property.h
+++ b/include/hw/misc/bcm2835_property.h
@@ -11,12 +11,14 @@
 #include "hw/sysbus.h"
 #include "net/net.h"
 #include "hw/display/bcm2835_fb.h"
+#include "qom/object.h"
 
 #define TYPE_BCM2835_PROPERTY "bcm2835-property"
-#define BCM2835_PROPERTY(obj) \
-        OBJECT_CHECK(BCM2835PropertyState, (obj), TYPE_BCM2835_PROPERTY)
+typedef struct BCM2835PropertyState BCM2835PropertyState;
+DECLARE_INSTANCE_CHECKER(BCM2835PropertyState, BCM2835_PROPERTY,
+                         TYPE_BCM2835_PROPERTY)
 
-typedef struct {
+struct BCM2835PropertyState {
     /*< private >*/
     SysBusDevice busdev;
     /*< public >*/
@@ -31,6 +33,6 @@ typedef struct {
     uint32_t board_rev;
     uint32_t addr;
     bool pending;
-} BCM2835PropertyState;
+};
 
 #endif
diff --git a/include/hw/misc/bcm2835_rng.h b/include/hw/misc/bcm2835_rng.h
index 41a531bce7..fec76eef8e 100644
--- a/include/hw/misc/bcm2835_rng.h
+++ b/include/hw/misc/bcm2835_rng.h
@@ -11,17 +11,19 @@
 #define BCM2835_RNG_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_BCM2835_RNG "bcm2835-rng"
-#define BCM2835_RNG(obj) \
-        OBJECT_CHECK(BCM2835RngState, (obj), TYPE_BCM2835_RNG)
+typedef struct BCM2835RngState BCM2835RngState;
+DECLARE_INSTANCE_CHECKER(BCM2835RngState, BCM2835_RNG,
+                         TYPE_BCM2835_RNG)
 
-typedef struct {
+struct BCM2835RngState {
     SysBusDevice busdev;
     MemoryRegion iomem;
 
     uint32_t rng_ctrl;
     uint32_t rng_status;
-} BCM2835RngState;
+};
 
 #endif
diff --git a/include/hw/misc/bcm2835_thermal.h b/include/hw/misc/bcm2835_thermal.h
index c3651b27ec..5b827c970e 100644
--- a/include/hw/misc/bcm2835_thermal.h
+++ b/include/hw/misc/bcm2835_thermal.h
@@ -10,18 +10,20 @@
 #define HW_MISC_BCM2835_THERMAL_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_BCM2835_THERMAL "bcm2835-thermal"
 
-#define BCM2835_THERMAL(obj) \
-    OBJECT_CHECK(Bcm2835ThermalState, (obj), TYPE_BCM2835_THERMAL)
+typedef struct Bcm2835ThermalState Bcm2835ThermalState;
+DECLARE_INSTANCE_CHECKER(Bcm2835ThermalState, BCM2835_THERMAL,
+                         TYPE_BCM2835_THERMAL)
 
-typedef struct {
+struct Bcm2835ThermalState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
     MemoryRegion iomem;
     uint32_t ctl;
-} Bcm2835ThermalState;
+};
 
 #endif
diff --git a/include/hw/misc/grlib_ahb_apb_pnp.h b/include/hw/misc/grlib_ahb_apb_pnp.h
index a0f6dcfda7..34b18e3193 100644
--- a/include/hw/misc/grlib_ahb_apb_pnp.h
+++ b/include/hw/misc/grlib_ahb_apb_pnp.h
@@ -23,16 +23,17 @@
 
 #ifndef GRLIB_AHB_APB_PNP_H
 #define GRLIB_AHB_APB_PNP_H
+#include "qom/object.h"
 
 #define TYPE_GRLIB_AHB_PNP "grlib,ahbpnp"
-#define GRLIB_AHB_PNP(obj) \
-    OBJECT_CHECK(AHBPnp, (obj), TYPE_GRLIB_AHB_PNP)
 typedef struct AHBPnp AHBPnp;
+DECLARE_INSTANCE_CHECKER(AHBPnp, GRLIB_AHB_PNP,
+                         TYPE_GRLIB_AHB_PNP)
 
 #define TYPE_GRLIB_APB_PNP "grlib,apbpnp"
-#define GRLIB_APB_PNP(obj) \
-    OBJECT_CHECK(APBPnp, (obj), TYPE_GRLIB_APB_PNP)
 typedef struct APBPnp APBPnp;
+DECLARE_INSTANCE_CHECKER(APBPnp, GRLIB_APB_PNP,
+                         TYPE_GRLIB_APB_PNP)
 
 void grlib_ahb_pnp_add_entry(AHBPnp *dev, uint32_t address, uint32_t mask,
                              uint8_t vendor, uint16_t device, int slave,
diff --git a/include/hw/misc/imx25_ccm.h b/include/hw/misc/imx25_ccm.h
index 296321c612..55c5db8815 100644
--- a/include/hw/misc/imx25_ccm.h
+++ b/include/hw/misc/imx25_ccm.h
@@ -12,6 +12,7 @@
 #define IMX25_CCM_H
 
 #include "hw/misc/imx_ccm.h"
+#include "qom/object.h"
 
 #define IMX25_CCM_MPCTL_REG  0
 #define IMX25_CCM_UPCTL_REG  1
@@ -63,9 +64,11 @@
                              CCTL_##name##_SHIFT)
 
 #define TYPE_IMX25_CCM "imx25.ccm"
-#define IMX25_CCM(obj) OBJECT_CHECK(IMX25CCMState, (obj), TYPE_IMX25_CCM)
+typedef struct IMX25CCMState IMX25CCMState;
+DECLARE_INSTANCE_CHECKER(IMX25CCMState, IMX25_CCM,
+                         TYPE_IMX25_CCM)
 
-typedef struct IMX25CCMState {
+struct IMX25CCMState {
     /* <private> */
     IMXCCMState parent_obj;
 
@@ -74,6 +77,6 @@ typedef struct IMX25CCMState {
 
     uint32_t reg[IMX25_CCM_MAX_REG];
 
-} IMX25CCMState;
+};
 
 #endif /* IMX25_CCM_H */
diff --git a/include/hw/misc/imx31_ccm.h b/include/hw/misc/imx31_ccm.h
index c376fad14c..25e280e976 100644
--- a/include/hw/misc/imx31_ccm.h
+++ b/include/hw/misc/imx31_ccm.h
@@ -12,6 +12,7 @@
 #define IMX31_CCM_H
 
 #include "hw/misc/imx_ccm.h"
+#include "qom/object.h"
 
 #define IMX31_CCM_CCMR_REG  0
 #define IMX31_CCM_PDR0_REG  1
@@ -72,9 +73,11 @@
                              PDR0_##name##_PODF_SHIFT)
 
 #define TYPE_IMX31_CCM "imx31.ccm"
-#define IMX31_CCM(obj) OBJECT_CHECK(IMX31CCMState, (obj), TYPE_IMX31_CCM)
+typedef struct IMX31CCMState IMX31CCMState;
+DECLARE_INSTANCE_CHECKER(IMX31CCMState, IMX31_CCM,
+                         TYPE_IMX31_CCM)
 
-typedef struct IMX31CCMState {
+struct IMX31CCMState {
     /* <private> */
     IMXCCMState parent_obj;
 
@@ -83,6 +86,6 @@ typedef struct IMX31CCMState {
 
     uint32_t reg[IMX31_CCM_MAX_REG];
 
-} IMX31CCMState;
+};
 
 #endif /* IMX31_CCM_H */
diff --git a/include/hw/misc/imx6_ccm.h b/include/hw/misc/imx6_ccm.h
index 80505809b4..85f32417d6 100644
--- a/include/hw/misc/imx6_ccm.h
+++ b/include/hw/misc/imx6_ccm.h
@@ -13,6 +13,7 @@
 
 #include "hw/misc/imx_ccm.h"
 #include "qemu/bitops.h"
+#include "qom/object.h"
 
 #define CCM_CCR 0
 #define CCM_CCDR 1
@@ -178,9 +179,11 @@
 #define EXTRACT(value, name) extract32(value, name##_SHIFT, name##_LENGTH)
 
 #define TYPE_IMX6_CCM "imx6.ccm"
-#define IMX6_CCM(obj) OBJECT_CHECK(IMX6CCMState, (obj), TYPE_IMX6_CCM)
+typedef struct IMX6CCMState IMX6CCMState;
+DECLARE_INSTANCE_CHECKER(IMX6CCMState, IMX6_CCM,
+                         TYPE_IMX6_CCM)
 
-typedef struct IMX6CCMState {
+struct IMX6CCMState {
     /* <private> */
     IMXCCMState parent_obj;
 
@@ -192,6 +195,6 @@ typedef struct IMX6CCMState {
     uint32_t ccm[CCM_MAX];
     uint32_t analog[CCM_ANALOG_MAX];
 
-} IMX6CCMState;
+};
 
 #endif /* IMX6_CCM_H */
diff --git a/include/hw/misc/imx6_src.h b/include/hw/misc/imx6_src.h
index eb3640732e..15b51757ba 100644
--- a/include/hw/misc/imx6_src.h
+++ b/include/hw/misc/imx6_src.h
@@ -13,6 +13,7 @@
 
 #include "hw/sysbus.h"
 #include "qemu/bitops.h"
+#include "qom/object.h"
 
 #define SRC_SCR 0
 #define SRC_SBMR1 1
@@ -57,9 +58,11 @@
 #define EXTRACT(value, name) extract32(value, name##_SHIFT, name##_LENGTH)
 
 #define TYPE_IMX6_SRC "imx6.src"
-#define IMX6_SRC(obj) OBJECT_CHECK(IMX6SRCState, (obj), TYPE_IMX6_SRC)
+typedef struct IMX6SRCState IMX6SRCState;
+DECLARE_INSTANCE_CHECKER(IMX6SRCState, IMX6_SRC,
+                         TYPE_IMX6_SRC)
 
-typedef struct IMX6SRCState {
+struct IMX6SRCState {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -68,6 +71,6 @@ typedef struct IMX6SRCState {
 
     uint32_t regs[SRC_MAX];
 
-} IMX6SRCState;
+};
 
 #endif /* IMX6_SRC_H */
diff --git a/include/hw/misc/imx6ul_ccm.h b/include/hw/misc/imx6ul_ccm.h
index 377ddca244..d614de0edd 100644
--- a/include/hw/misc/imx6ul_ccm.h
+++ b/include/hw/misc/imx6ul_ccm.h
@@ -12,6 +12,7 @@
 
 #include "hw/misc/imx_ccm.h"
 #include "qemu/bitops.h"
+#include "qom/object.h"
 
 #define CCM_CCR 0
 #define CCM_CCDR 1
@@ -207,9 +208,11 @@
 #define CCM_ANALOG_PLL_LOCK      (1 << 31);
 
 #define TYPE_IMX6UL_CCM "imx6ul.ccm"
-#define IMX6UL_CCM(obj) OBJECT_CHECK(IMX6ULCCMState, (obj), TYPE_IMX6UL_CCM)
+typedef struct IMX6ULCCMState IMX6ULCCMState;
+DECLARE_INSTANCE_CHECKER(IMX6ULCCMState, IMX6UL_CCM,
+                         TYPE_IMX6UL_CCM)
 
-typedef struct IMX6ULCCMState {
+struct IMX6ULCCMState {
     /* <private> */
     IMXCCMState parent_obj;
 
@@ -221,6 +224,6 @@ typedef struct IMX6ULCCMState {
     uint32_t ccm[CCM_MAX];
     uint32_t analog[CCM_ANALOG_MAX];
 
-} IMX6ULCCMState;
+};
 
 #endif /* IMX6UL_CCM_H */
diff --git a/include/hw/misc/imx7_ccm.h b/include/hw/misc/imx7_ccm.h
index 9538f37d98..e2757622d0 100644
--- a/include/hw/misc/imx7_ccm.h
+++ b/include/hw/misc/imx7_ccm.h
@@ -14,6 +14,7 @@
 
 #include "hw/misc/imx_ccm.h"
 #include "qemu/bitops.h"
+#include "qom/object.h"
 
 enum IMX7AnalogRegisters {
     ANALOG_PLL_ARM,
@@ -104,9 +105,11 @@ enum IMX7PMURegisters {
 };
 
 #define TYPE_IMX7_CCM "imx7.ccm"
-#define IMX7_CCM(obj) OBJECT_CHECK(IMX7CCMState, (obj), TYPE_IMX7_CCM)
+typedef struct IMX7CCMState IMX7CCMState;
+DECLARE_INSTANCE_CHECKER(IMX7CCMState, IMX7_CCM,
+                         TYPE_IMX7_CCM)
 
-typedef struct IMX7CCMState {
+struct IMX7CCMState {
     /* <private> */
     IMXCCMState parent_obj;
 
@@ -114,13 +117,15 @@ typedef struct IMX7CCMState {
     MemoryRegion iomem;
 
     uint32_t ccm[CCM_MAX];
-} IMX7CCMState;
+};
 
 
 #define TYPE_IMX7_ANALOG "imx7.analog"
-#define IMX7_ANALOG(obj) OBJECT_CHECK(IMX7AnalogState, (obj), TYPE_IMX7_ANALOG)
+typedef struct IMX7AnalogState IMX7AnalogState;
+DECLARE_INSTANCE_CHECKER(IMX7AnalogState, IMX7_ANALOG,
+                         TYPE_IMX7_ANALOG)
 
-typedef struct IMX7AnalogState {
+struct IMX7AnalogState {
     /* <private> */
     IMXCCMState parent_obj;
 
@@ -134,6 +139,6 @@ typedef struct IMX7AnalogState {
 
     uint32_t analog[ANALOG_MAX];
     uint32_t pmu[PMU_MAX];
-} IMX7AnalogState;
+};
 
 #endif /* IMX7_CCM_H */
diff --git a/include/hw/misc/imx7_gpr.h b/include/hw/misc/imx7_gpr.h
index e19373d274..f80b3ed28c 100644
--- a/include/hw/misc/imx7_gpr.h
+++ b/include/hw/misc/imx7_gpr.h
@@ -14,15 +14,18 @@
 
 #include "qemu/bitops.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_IMX7_GPR "imx7.gpr"
-#define IMX7_GPR(obj) OBJECT_CHECK(IMX7GPRState, (obj), TYPE_IMX7_GPR)
+typedef struct IMX7GPRState IMX7GPRState;
+DECLARE_INSTANCE_CHECKER(IMX7GPRState, IMX7_GPR,
+                         TYPE_IMX7_GPR)
 
-typedef struct IMX7GPRState {
+struct IMX7GPRState {
     /* <private> */
     SysBusDevice parent_obj;
 
     MemoryRegion mmio;
-} IMX7GPRState;
+};
 
 #endif /* IMX7_GPR_H */
diff --git a/include/hw/misc/imx7_snvs.h b/include/hw/misc/imx7_snvs.h
index 255f8f26f9..ea5395c107 100644
--- a/include/hw/misc/imx7_snvs.h
+++ b/include/hw/misc/imx7_snvs.h
@@ -14,6 +14,7 @@
 
 #include "qemu/bitops.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 
 enum IMX7SNVSRegisters {
@@ -23,13 +24,15 @@ enum IMX7SNVSRegisters {
 };
 
 #define TYPE_IMX7_SNVS "imx7.snvs"
-#define IMX7_SNVS(obj) OBJECT_CHECK(IMX7SNVSState, (obj), TYPE_IMX7_SNVS)
+typedef struct IMX7SNVSState IMX7SNVSState;
+DECLARE_INSTANCE_CHECKER(IMX7SNVSState, IMX7_SNVS,
+                         TYPE_IMX7_SNVS)
 
-typedef struct IMX7SNVSState {
+struct IMX7SNVSState {
     /* <private> */
     SysBusDevice parent_obj;
 
     MemoryRegion mmio;
-} IMX7SNVSState;
+};
 
 #endif /* IMX7_SNVS_H */
diff --git a/include/hw/misc/imx_ccm.h b/include/hw/misc/imx_ccm.h
index efdc451eb0..e9d82a2a50 100644
--- a/include/hw/misc/imx_ccm.h
+++ b/include/hw/misc/imx_ccm.h
@@ -12,6 +12,7 @@
 #define IMX_CCM_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define CKIL_FREQ 32768 /* nominal 32khz clock */
 
@@ -27,20 +28,18 @@
 #define PLL_MFN(x)              (((x) & 0x3ff) << 0)
 
 #define TYPE_IMX_CCM "imx.ccm"
-#define IMX_CCM(obj) \
-     OBJECT_CHECK(IMXCCMState, (obj), TYPE_IMX_CCM)
-#define IMX_CCM_CLASS(klass) \
-     OBJECT_CLASS_CHECK(IMXCCMClass, (klass), TYPE_IMX_CCM)
-#define IMX_CCM_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(IMXCCMClass, (obj), TYPE_IMX_CCM)
+typedef struct IMXCCMClass IMXCCMClass;
+typedef struct IMXCCMState IMXCCMState;
+DECLARE_OBJ_CHECKERS(IMXCCMState, IMXCCMClass,
+                     IMX_CCM, TYPE_IMX_CCM)
 
-typedef struct IMXCCMState {
+struct IMXCCMState {
     /* <private> */
     SysBusDevice parent_obj;
 
     /* <public> */
 
-} IMXCCMState;
+};
 
 typedef enum  {
     CLK_NONE,
@@ -52,13 +51,13 @@ typedef enum  {
     CLK_HIGH,
 } IMXClk;
 
-typedef struct IMXCCMClass {
+struct IMXCCMClass {
     /* <private> */
     SysBusDeviceClass parent_class;
 
     /* <public> */
     uint32_t (*get_clock_frequency)(IMXCCMState *s, IMXClk clk);
-} IMXCCMClass;
+};
 
 uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq);
 
diff --git a/include/hw/misc/imx_rngc.h b/include/hw/misc/imx_rngc.h
index f0d2b44d4f..f7b569cac5 100644
--- a/include/hw/misc/imx_rngc.h
+++ b/include/hw/misc/imx_rngc.h
@@ -11,11 +11,14 @@
 #define IMX_RNGC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_IMX_RNGC "imx.rngc"
-#define IMX_RNGC(obj) OBJECT_CHECK(IMXRNGCState, (obj), TYPE_IMX_RNGC)
+typedef struct IMXRNGCState IMXRNGCState;
+DECLARE_INSTANCE_CHECKER(IMXRNGCState, IMX_RNGC,
+                         TYPE_IMX_RNGC)
 
-typedef struct IMXRNGCState {
+struct IMXRNGCState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -30,6 +33,6 @@ typedef struct IMXRNGCState {
     QEMUBH *self_test_bh;
     QEMUBH *seed_bh;
     qemu_irq irq;
-} IMXRNGCState;
+};
 
 #endif /* IMX_RNGC_H */
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
index bcb0437be5..d062ed43e7 100644
--- a/include/hw/misc/iotkit-secctl.h
+++ b/include/hw/misc/iotkit-secctl.h
@@ -56,9 +56,12 @@
 #define IOTKIT_SECCTL_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_IOTKIT_SECCTL "iotkit-secctl"
-#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
+typedef struct IoTKitSecCtl IoTKitSecCtl;
+DECLARE_INSTANCE_CHECKER(IoTKitSecCtl, IOTKIT_SECCTL,
+                         TYPE_IOTKIT_SECCTL)
 
 #define IOTS_APB_PPC0_NUM_PORTS 3
 #define IOTS_APB_PPC1_NUM_PORTS 1
@@ -70,7 +73,6 @@
 #define IOTS_NUM_MPC 4
 #define IOTS_NUM_EXP_MSC 16
 
-typedef struct IoTKitSecCtl IoTKitSecCtl;
 
 /* State and IRQ lines relating to a PPC. For the
  * PPCs in the IoTKit not all the IRQ lines are used.
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
index 601c8ecc0d..22ceb5d76d 100644
--- a/include/hw/misc/iotkit-sysctl.h
+++ b/include/hw/misc/iotkit-sysctl.h
@@ -28,12 +28,14 @@
 #define HW_MISC_IOTKIT_SYSCTL_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_IOTKIT_SYSCTL "iotkit-sysctl"
-#define IOTKIT_SYSCTL(obj) OBJECT_CHECK(IoTKitSysCtl, (obj), \
-                                        TYPE_IOTKIT_SYSCTL)
+typedef struct IoTKitSysCtl IoTKitSysCtl;
+DECLARE_INSTANCE_CHECKER(IoTKitSysCtl, IOTKIT_SYSCTL,
+                         TYPE_IOTKIT_SYSCTL)
 
-typedef struct IoTKitSysCtl {
+struct IoTKitSysCtl {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -67,6 +69,6 @@ typedef struct IoTKitSysCtl {
     uint32_t initsvtor1_rst;
 
     bool is_sse200;
-} IoTKitSysCtl;
+};
 
 #endif
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
index d84eb203b9..23ae43e549 100644
--- a/include/hw/misc/iotkit-sysinfo.h
+++ b/include/hw/misc/iotkit-sysinfo.h
@@ -23,12 +23,14 @@
 #define HW_MISC_IOTKIT_SYSINFO_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_IOTKIT_SYSINFO "iotkit-sysinfo"
-#define IOTKIT_SYSINFO(obj) OBJECT_CHECK(IoTKitSysInfo, (obj), \
-                                        TYPE_IOTKIT_SYSINFO)
+typedef struct IoTKitSysInfo IoTKitSysInfo;
+DECLARE_INSTANCE_CHECKER(IoTKitSysInfo, IOTKIT_SYSINFO,
+                         TYPE_IOTKIT_SYSINFO)
 
-typedef struct IoTKitSysInfo {
+struct IoTKitSysInfo {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -38,6 +40,6 @@ typedef struct IoTKitSysInfo {
     /* Properties */
     uint32_t sys_version;
     uint32_t sys_config;
-} IoTKitSysInfo;
+};
 
 #endif
diff --git a/include/hw/misc/mac_via.h b/include/hw/misc/mac_via.h
index 0be05d649b..862cbba3ab 100644
--- a/include/hw/misc/mac_via.h
+++ b/include/hw/misc/mac_via.h
@@ -12,6 +12,7 @@
 #include "exec/memory.h"
 #include "hw/sysbus.h"
 #include "hw/misc/mos6522.h"
+#include "qom/object.h"
 
 
 /* VIA 1 */
@@ -31,10 +32,11 @@
 
 
 #define TYPE_MOS6522_Q800_VIA1 "mos6522-q800-via1"
-#define MOS6522_Q800_VIA1(obj)  OBJECT_CHECK(MOS6522Q800VIA1State, (obj), \
-                                    TYPE_MOS6522_Q800_VIA1)
+typedef struct MOS6522Q800VIA1State MOS6522Q800VIA1State;
+DECLARE_INSTANCE_CHECKER(MOS6522Q800VIA1State, MOS6522_Q800_VIA1,
+                         TYPE_MOS6522_Q800_VIA1)
 
-typedef struct MOS6522Q800VIA1State {
+struct MOS6522Q800VIA1State {
     /*< private >*/
     MOS6522State parent_obj;
 
@@ -47,7 +49,7 @@ typedef struct MOS6522Q800VIA1State {
     int64_t next_second;
     QEMUTimer *VBL_timer;
     int64_t next_VBL;
-} MOS6522Q800VIA1State;
+};
 
 
 /* VIA 2 */
@@ -66,19 +68,22 @@ typedef struct MOS6522Q800VIA1State {
 #define VIA2_IRQ_ASC        (1 << VIA2_IRQ_ASC_BIT)
 
 #define TYPE_MOS6522_Q800_VIA2 "mos6522-q800-via2"
-#define MOS6522_Q800_VIA2(obj)  OBJECT_CHECK(MOS6522Q800VIA2State, (obj), \
-                                    TYPE_MOS6522_Q800_VIA2)
+typedef struct MOS6522Q800VIA2State MOS6522Q800VIA2State;
+DECLARE_INSTANCE_CHECKER(MOS6522Q800VIA2State, MOS6522_Q800_VIA2,
+                         TYPE_MOS6522_Q800_VIA2)
 
-typedef struct MOS6522Q800VIA2State {
+struct MOS6522Q800VIA2State {
     /*< private >*/
     MOS6522State parent_obj;
-} MOS6522Q800VIA2State;
+};
 
 
 #define TYPE_MAC_VIA "mac_via"
-#define MAC_VIA(obj)   OBJECT_CHECK(MacVIAState, (obj), TYPE_MAC_VIA)
+typedef struct MacVIAState MacVIAState;
+DECLARE_INSTANCE_CHECKER(MacVIAState, MAC_VIA,
+                         TYPE_MAC_VIA)
 
-typedef struct MacVIAState {
+struct MacVIAState {
     SysBusDevice busdev;
 
     VMChangeStateEntry *vmstate;
@@ -113,6 +118,6 @@ typedef struct MacVIAState {
     uint8_t adb_data_in[128];
     uint8_t adb_data_out[16];
     uint8_t adb_autopoll_cmd;
-} MacVIAState;
+};
 
 #endif
diff --git a/include/hw/misc/macio/cuda.h b/include/hw/misc/macio/cuda.h
index a8cf0be1ec..e738b6376f 100644
--- a/include/hw/misc/macio/cuda.h
+++ b/include/hw/misc/macio/cuda.h
@@ -27,6 +27,7 @@
 #define CUDA_H
 
 #include "hw/misc/mos6522.h"
+#include "qom/object.h"
 
 /* CUDA commands (2nd byte) */
 #define CUDA_WARM_START                0x0
@@ -58,20 +59,23 @@
 
 
 /* MOS6522 CUDA */
-typedef struct MOS6522CUDAState {
+struct MOS6522CUDAState {
     /*< private >*/
     MOS6522State parent_obj;
-} MOS6522CUDAState;
+};
+typedef struct MOS6522CUDAState MOS6522CUDAState;
 
 #define TYPE_MOS6522_CUDA "mos6522-cuda"
-#define MOS6522_CUDA(obj) OBJECT_CHECK(MOS6522CUDAState, (obj), \
-                                       TYPE_MOS6522_CUDA)
+DECLARE_INSTANCE_CHECKER(MOS6522CUDAState, MOS6522_CUDA,
+                         TYPE_MOS6522_CUDA)
 
 /* Cuda */
 #define TYPE_CUDA "cuda"
-#define CUDA(obj) OBJECT_CHECK(CUDAState, (obj), TYPE_CUDA)
+typedef struct CUDAState CUDAState;
+DECLARE_INSTANCE_CHECKER(CUDAState, CUDA,
+                         TYPE_CUDA)
 
-typedef struct CUDAState {
+struct CUDAState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -97,6 +101,6 @@ typedef struct CUDAState {
     qemu_irq irq;
     uint8_t data_in[128];
     uint8_t data_out[16];
-} CUDAState;
+};
 
 #endif /* CUDA_H */
diff --git a/include/hw/misc/macio/gpio.h b/include/hw/misc/macio/gpio.h
index 24a4364b39..1d0c8434ae 100644
--- a/include/hw/misc/macio/gpio.h
+++ b/include/hw/misc/macio/gpio.h
@@ -28,11 +28,14 @@
 
 #include "hw/ppc/openpic.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_MACIO_GPIO "macio-gpio"
-#define MACIO_GPIO(obj) OBJECT_CHECK(MacIOGPIOState, (obj), TYPE_MACIO_GPIO)
+typedef struct MacIOGPIOState MacIOGPIOState;
+DECLARE_INSTANCE_CHECKER(MacIOGPIOState, MACIO_GPIO,
+                         TYPE_MACIO_GPIO)
 
-typedef struct MacIOGPIOState {
+struct MacIOGPIOState {
     /*< private >*/
     SysBusDevice parent;
     /*< public >*/
@@ -43,7 +46,7 @@ typedef struct MacIOGPIOState {
     qemu_irq gpio_extirqs[10];
     uint8_t gpio_levels[8];
     uint8_t gpio_regs[36]; /* XXX Check count */
-} MacIOGPIOState;
+};
 
 void macio_set_gpio(MacIOGPIOState *s, uint32_t gpio, bool state);
 
diff --git a/include/hw/misc/macio/macio.h b/include/hw/misc/macio/macio.h
index 87335a991c..02dbf37630 100644
--- a/include/hw/misc/macio/macio.h
+++ b/include/hw/misc/macio/macio.h
@@ -36,21 +36,26 @@
 #include "hw/ppc/mac.h"
 #include "hw/ppc/mac_dbdma.h"
 #include "hw/ppc/openpic.h"
+#include "qom/object.h"
 
 /* MacIO virtual bus */
 #define TYPE_MACIO_BUS "macio-bus"
-#define MACIO_BUS(obj) OBJECT_CHECK(MacIOBusState, (obj), TYPE_MACIO_BUS)
+typedef struct MacIOBusState MacIOBusState;
+DECLARE_INSTANCE_CHECKER(MacIOBusState, MACIO_BUS,
+                         TYPE_MACIO_BUS)
 
-typedef struct MacIOBusState {
+struct MacIOBusState {
     /*< private >*/
     BusState parent_obj;
-} MacIOBusState;
+};
 
 /* MacIO IDE */
 #define TYPE_MACIO_IDE "macio-ide"
-#define MACIO_IDE(obj) OBJECT_CHECK(MACIOIDEState, (obj), TYPE_MACIO_IDE)
+typedef struct MACIOIDEState MACIOIDEState;
+DECLARE_INSTANCE_CHECKER(MACIOIDEState, MACIO_IDE,
+                         TYPE_MACIO_IDE)
 
-typedef struct MACIOIDEState {
+struct MACIOIDEState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -68,15 +73,17 @@ typedef struct MACIOIDEState {
     bool dma_active;
     uint32_t timing_reg;
     uint32_t irq_reg;
-} MACIOIDEState;
+};
 
 void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table);
 void macio_ide_register_dma(MACIOIDEState *ide);
 
 #define TYPE_MACIO "macio"
-#define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO)
+typedef struct MacIOState MacIOState;
+DECLARE_INSTANCE_CHECKER(MacIOState, MACIO,
+                         TYPE_MACIO)
 
-typedef struct MacIOState {
+struct MacIOState {
     /*< private >*/
     PCIDevice parent;
     /*< public >*/
@@ -88,13 +95,14 @@ typedef struct MacIOState {
     DBDMAState dbdma;
     ESCCState escc;
     uint64_t frequency;
-} MacIOState;
+};
 
 #define TYPE_OLDWORLD_MACIO "macio-oldworld"
-#define OLDWORLD_MACIO(obj) \
-    OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO)
+typedef struct OldWorldMacIOState OldWorldMacIOState;
+DECLARE_INSTANCE_CHECKER(OldWorldMacIOState, OLDWORLD_MACIO,
+                         TYPE_OLDWORLD_MACIO)
 
-typedef struct OldWorldMacIOState {
+struct OldWorldMacIOState {
     /*< private >*/
     MacIOState parent_obj;
     /*< public >*/
@@ -103,13 +111,14 @@ typedef struct OldWorldMacIOState {
 
     MacIONVRAMState nvram;
     MACIOIDEState ide[2];
-} OldWorldMacIOState;
+};
 
 #define TYPE_NEWWORLD_MACIO "macio-newworld"
-#define NEWWORLD_MACIO(obj) \
-    OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO)
+typedef struct NewWorldMacIOState NewWorldMacIOState;
+DECLARE_INSTANCE_CHECKER(NewWorldMacIOState, NEWWORLD_MACIO,
+                         TYPE_NEWWORLD_MACIO)
 
-typedef struct NewWorldMacIOState {
+struct NewWorldMacIOState {
     /*< private >*/
     MacIOState parent_obj;
     /*< public >*/
@@ -119,6 +128,6 @@ typedef struct NewWorldMacIOState {
     OpenPICState *pic;
     MACIOIDEState ide[2];
     MacIOGPIOState gpio;
-} NewWorldMacIOState;
+};
 
 #endif /* MACIO_H */
diff --git a/include/hw/misc/macio/pmu.h b/include/hw/misc/macio/pmu.h
index 72f75612b6..0d1a5c1406 100644
--- a/include/hw/misc/macio/pmu.h
+++ b/include/hw/misc/macio/pmu.h
@@ -12,6 +12,7 @@
 
 #include "hw/misc/mos6522.h"
 #include "hw/misc/macio/gpio.h"
+#include "qom/object.h"
 
 /*
  * PMU commands
@@ -173,20 +174,21 @@ typedef enum {
 } PMUCmdState;
 
 /* MOS6522 PMU */
-typedef struct MOS6522PMUState {
+struct MOS6522PMUState {
     /*< private >*/
     MOS6522State parent_obj;
-} MOS6522PMUState;
+};
+typedef struct MOS6522PMUState MOS6522PMUState;
 
 #define TYPE_MOS6522_PMU "mos6522-pmu"
-#define MOS6522_PMU(obj) OBJECT_CHECK(MOS6522PMUState, (obj), \
-                                      TYPE_MOS6522_PMU)
+DECLARE_INSTANCE_CHECKER(MOS6522PMUState, MOS6522_PMU,
+                         TYPE_MOS6522_PMU)
 /**
  * PMUState:
  * @last_b: last value of B register
  */
 
-typedef struct PMUState {
+struct PMUState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -228,9 +230,11 @@ typedef struct PMUState {
 
     /* GPIO */
     MacIOGPIOState *gpio;
-} PMUState;
+};
+typedef struct PMUState PMUState;
 
 #define TYPE_VIA_PMU "via-pmu"
-#define VIA_PMU(obj) OBJECT_CHECK(PMUState, (obj), TYPE_VIA_PMU)
+DECLARE_INSTANCE_CHECKER(PMUState, VIA_PMU,
+                         TYPE_VIA_PMU)
 
 #endif /* PMU_H */
diff --git a/include/hw/misc/max111x.h b/include/hw/misc/max111x.h
index af7f1017ef..6350a3f7c0 100644
--- a/include/hw/misc/max111x.h
+++ b/include/hw/misc/max111x.h
@@ -14,6 +14,7 @@
 #define HW_MISC_MAX111X_H
 
 #include "hw/ssi/ssi.h"
+#include "qom/object.h"
 
 /*
  * This is a model of the Maxim MAX1110/1111 ADC chip, which for QEMU
@@ -31,7 +32,7 @@
  *  + the interrupt line is not correctly implemented, and will never
  *    be lowered once it has been asserted.
  */
-typedef struct {
+struct MAX111xState {
     SSISlave parent_obj;
 
     qemu_irq interrupt;
@@ -43,12 +44,13 @@ typedef struct {
 
     uint8_t input[8];
     int inputs, com;
-} MAX111xState;
+};
+typedef struct MAX111xState MAX111xState;
 
 #define TYPE_MAX_111X "max111x"
 
-#define MAX_111X(obj) \
-    OBJECT_CHECK(MAX111xState, (obj), TYPE_MAX_111X)
+DECLARE_INSTANCE_CHECKER(MAX111xState, MAX_111X,
+                         TYPE_MAX_111X)
 
 #define TYPE_MAX_1110 "max1110"
 #define TYPE_MAX_1111 "max1111"
diff --git a/include/hw/misc/mips_cmgcr.h b/include/hw/misc/mips_cmgcr.h
index 3e6e223273..923df4f112 100644
--- a/include/hw/misc/mips_cmgcr.h
+++ b/include/hw/misc/mips_cmgcr.h
@@ -11,9 +11,12 @@
 #define MIPS_CMGCR_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_MIPS_GCR "mips-gcr"
-#define MIPS_GCR(obj) OBJECT_CHECK(MIPSGCRState, (obj), TYPE_MIPS_GCR)
+typedef struct MIPSGCRState MIPSGCRState;
+DECLARE_INSTANCE_CHECKER(MIPSGCRState, MIPS_GCR,
+                         TYPE_MIPS_GCR)
 
 #define GCR_BASE_ADDR           0x1fbf8000ULL
 #define GCR_ADDRSPACE_SZ        0x8000
@@ -70,7 +73,6 @@ struct MIPSGCRVPState {
     uint64_t reset_base;
 };
 
-typedef struct MIPSGCRState MIPSGCRState;
 struct MIPSGCRState {
     SysBusDevice parent_obj;
 
diff --git a/include/hw/misc/mips_cpc.h b/include/hw/misc/mips_cpc.h
index 3f670578b0..7dc188e8a2 100644
--- a/include/hw/misc/mips_cpc.h
+++ b/include/hw/misc/mips_cpc.h
@@ -21,6 +21,7 @@
 #define MIPS_CPC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define CPC_ADDRSPACE_SZ    0x6000
 
@@ -34,9 +35,11 @@
 #define CPC_VP_RUNNING_OFS  0x30
 
 #define TYPE_MIPS_CPC "mips-cpc"
-#define MIPS_CPC(obj) OBJECT_CHECK(MIPSCPCState, (obj), TYPE_MIPS_CPC)
+typedef struct MIPSCPCState MIPSCPCState;
+DECLARE_INSTANCE_CHECKER(MIPSCPCState, MIPS_CPC,
+                         TYPE_MIPS_CPC)
 
-typedef struct MIPSCPCState {
+struct MIPSCPCState {
     SysBusDevice parent_obj;
 
     uint32_t num_vp;
@@ -44,6 +47,6 @@ typedef struct MIPSCPCState {
 
     MemoryRegion mr;
     uint64_t vp_running; /* Indicates which VPs are in the run state */
-} MIPSCPCState;
+};
 
 #endif /* MIPS_CPC_H */
diff --git a/include/hw/misc/mips_itu.h b/include/hw/misc/mips_itu.h
index c44e7672b6..7c19f61fbb 100644
--- a/include/hw/misc/mips_itu.h
+++ b/include/hw/misc/mips_itu.h
@@ -21,9 +21,12 @@
 #define MIPS_ITU_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_MIPS_ITU "mips-itu"
-#define MIPS_ITU(obj) OBJECT_CHECK(MIPSITUState, (obj), TYPE_MIPS_ITU)
+typedef struct MIPSITUState MIPSITUState;
+DECLARE_INSTANCE_CHECKER(MIPSITUState, MIPS_ITU,
+                         TYPE_MIPS_ITU)
 
 #define ITC_CELL_DEPTH_SHIFT 2
 #define ITC_CELL_DEPTH (1u << ITC_CELL_DEPTH_SHIFT)
@@ -51,7 +54,7 @@ typedef struct ITCStorageCell {
 
 #define ITC_ADDRESSMAP_NUM 2
 
-typedef struct MIPSITUState {
+struct MIPSITUState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -74,7 +77,7 @@ typedef struct MIPSITUState {
     bool saar_present;
     void *saar;
 
-} MIPSITUState;
+};
 
 /* Get ITC Configuration Tag memory region. */
 MemoryRegion *mips_itu_get_tag_region(MIPSITUState *itu);
diff --git a/include/hw/misc/mos6522.h b/include/hw/misc/mos6522.h
index 6b25ffd439..f73271ba67 100644
--- a/include/hw/misc/mos6522.h
+++ b/include/hw/misc/mos6522.h
@@ -30,6 +30,7 @@
 #include "exec/memory.h"
 #include "hw/sysbus.h"
 #include "hw/input/adb.h"
+#include "qom/object.h"
 
 /* Bits in ACR */
 #define SR_CTRL            0x1c    /* Shift register control bits */
@@ -99,7 +100,7 @@ typedef struct MOS6522Timer {
  * @last_b: last value of B register
  * @last_acr: last value of ACR register
  */
-typedef struct MOS6522State {
+struct MOS6522State {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -120,12 +121,15 @@ typedef struct MOS6522State {
     uint64_t frequency;
 
     qemu_irq irq;
-} MOS6522State;
+};
+typedef struct MOS6522State MOS6522State;
 
 #define TYPE_MOS6522 "mos6522"
-#define MOS6522(obj) OBJECT_CHECK(MOS6522State, (obj), TYPE_MOS6522)
+typedef struct MOS6522DeviceClass MOS6522DeviceClass;
+DECLARE_OBJ_CHECKERS(MOS6522State, MOS6522DeviceClass,
+                     MOS6522, TYPE_MOS6522)
 
-typedef struct MOS6522DeviceClass {
+struct MOS6522DeviceClass {
     DeviceClass parent_class;
 
     DeviceReset parent_reset;
@@ -138,12 +142,8 @@ typedef struct MOS6522DeviceClass {
     uint64_t (*get_timer2_counter_value)(MOS6522State *dev, MOS6522Timer *ti);
     uint64_t (*get_timer1_load_time)(MOS6522State *dev, MOS6522Timer *ti);
     uint64_t (*get_timer2_load_time)(MOS6522State *dev, MOS6522Timer *ti);
-} MOS6522DeviceClass;
+};
 
-#define MOS6522_CLASS(cls) \
-    OBJECT_CLASS_CHECK(MOS6522DeviceClass, (cls), TYPE_MOS6522)
-#define MOS6522_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(MOS6522DeviceClass, (obj), TYPE_MOS6522)
 
 extern const VMStateDescription vmstate_mos6522;
 
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
index 69e265cd4b..991f5b731e 100644
--- a/include/hw/misc/mps2-fpgaio.h
+++ b/include/hw/misc/mps2-fpgaio.h
@@ -22,11 +22,14 @@
 #define MPS2_FPGAIO_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_MPS2_FPGAIO "mps2-fpgaio"
-#define MPS2_FPGAIO(obj) OBJECT_CHECK(MPS2FPGAIO, (obj), TYPE_MPS2_FPGAIO)
+typedef struct MPS2FPGAIO MPS2FPGAIO;
+DECLARE_INSTANCE_CHECKER(MPS2FPGAIO, MPS2_FPGAIO,
+                         TYPE_MPS2_FPGAIO)
 
-typedef struct {
+struct MPS2FPGAIO {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -48,6 +51,6 @@ typedef struct {
     /* These hold the CLOCK_VIRTUAL ns tick when the CLK1HZ/CLK100HZ was zero */
     int64_t clk1hz_tick_offset;
     int64_t clk100hz_tick_offset;
-} MPS2FPGAIO;
+};
 
 #endif
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
index 7045473788..445e268b1f 100644
--- a/include/hw/misc/mps2-scc.h
+++ b/include/hw/misc/mps2-scc.h
@@ -13,13 +13,16 @@
 #define MPS2_SCC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_MPS2_SCC "mps2-scc"
-#define MPS2_SCC(obj) OBJECT_CHECK(MPS2SCC, (obj), TYPE_MPS2_SCC)
+typedef struct MPS2SCC MPS2SCC;
+DECLARE_INSTANCE_CHECKER(MPS2SCC, MPS2_SCC,
+                         TYPE_MPS2_SCC)
 
 #define NUM_OSCCLK 3
 
-typedef struct {
+struct MPS2SCC {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -38,6 +41,6 @@ typedef struct {
     uint32_t id;
     uint32_t oscclk[NUM_OSCCLK];
     uint32_t oscclk_reset[NUM_OSCCLK];
-} MPS2SCC;
+};
 
 #endif
diff --git a/include/hw/misc/msf2-sysreg.h b/include/hw/misc/msf2-sysreg.h
index 5993f67b4e..625932354a 100644
--- a/include/hw/misc/msf2-sysreg.h
+++ b/include/hw/misc/msf2-sysreg.h
@@ -26,6 +26,7 @@
 #define HW_MSF2_SYSREG_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 enum {
     ESRAM_CR        = 0x00 / 4,
@@ -61,9 +62,11 @@ enum {
 #define MSF2_SYSREG_MMIO_SIZE     0x300
 
 #define TYPE_MSF2_SYSREG          "msf2-sysreg"
-#define MSF2_SYSREG(obj)  OBJECT_CHECK(MSF2SysregState, (obj), TYPE_MSF2_SYSREG)
+typedef struct MSF2SysregState MSF2SysregState;
+DECLARE_INSTANCE_CHECKER(MSF2SysregState, MSF2_SYSREG,
+                         TYPE_MSF2_SYSREG)
 
-typedef struct MSF2SysregState {
+struct MSF2SysregState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -72,6 +75,6 @@ typedef struct MSF2SysregState {
     uint8_t apb1div;
 
     uint32_t regs[MSF2_SYSREG_MMIO_SIZE / 4];
-} MSF2SysregState;
+};
 
 #endif /* HW_MSF2_SYSREG_H */
diff --git a/include/hw/misc/nrf51_rng.h b/include/hw/misc/nrf51_rng.h
index b0133bf665..7f2263a906 100644
--- a/include/hw/misc/nrf51_rng.h
+++ b/include/hw/misc/nrf51_rng.h
@@ -36,8 +36,11 @@
 
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
+#include "qom/object.h"
 #define TYPE_NRF51_RNG "nrf51_soc.rng"
-#define NRF51_RNG(obj) OBJECT_CHECK(NRF51RNGState, (obj), TYPE_NRF51_RNG)
+typedef struct NRF51RNGState NRF51RNGState;
+DECLARE_INSTANCE_CHECKER(NRF51RNGState, NRF51_RNG,
+                         TYPE_NRF51_RNG)
 
 #define NRF51_RNG_SIZE         0x1000
 
@@ -54,7 +57,7 @@
 #define NRF51_RNG_REG_CONFIG_DECEN 0
 #define NRF51_RNG_REG_VALUE    0x508
 
-typedef struct {
+struct NRF51RNGState {
     SysBusDevice parent_obj;
 
     MemoryRegion mmio;
@@ -78,7 +81,7 @@ typedef struct {
     uint32_t interrupt_enabled;
     uint32_t filter_enabled;
 
-} NRF51RNGState;
+};
 
 
 #endif /* NRF51_RNG_H */
diff --git a/include/hw/misc/pca9552.h b/include/hw/misc/pca9552.h
index 600356fbf9..b6f4e264fe 100644
--- a/include/hw/misc/pca9552.h
+++ b/include/hw/misc/pca9552.h
@@ -10,15 +10,18 @@
 #define PCA9552_H
 
 #include "hw/i2c/i2c.h"
+#include "qom/object.h"
 
 #define TYPE_PCA9552 "pca9552"
 #define TYPE_PCA955X "pca955x"
-#define PCA955X(obj) OBJECT_CHECK(PCA955xState, (obj), TYPE_PCA955X)
+typedef struct PCA955xState PCA955xState;
+DECLARE_INSTANCE_CHECKER(PCA955xState, PCA955X,
+                         TYPE_PCA955X)
 
 #define PCA955X_NR_REGS 10
 #define PCA955X_PIN_COUNT_MAX 16
 
-typedef struct PCA955xState {
+struct PCA955xState {
     /*< private >*/
     I2CSlave i2c;
     /*< public >*/
@@ -29,6 +32,6 @@ typedef struct PCA955xState {
     uint8_t regs[PCA955X_NR_REGS];
     qemu_irq gpio[PCA955X_PIN_COUNT_MAX];
     char *description; /* For debugging purpose only */
-} PCA955xState;
+};
 
 #endif
diff --git a/include/hw/misc/stm32f2xx_syscfg.h b/include/hw/misc/stm32f2xx_syscfg.h
index 84e06fdecf..82ccd7cc24 100644
--- a/include/hw/misc/stm32f2xx_syscfg.h
+++ b/include/hw/misc/stm32f2xx_syscfg.h
@@ -26,6 +26,7 @@
 #define HW_STM32F2XX_SYSCFG_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define SYSCFG_MEMRMP  0x00
 #define SYSCFG_PMC     0x04
@@ -36,10 +37,11 @@
 #define SYSCFG_CMPCR   0x20
 
 #define TYPE_STM32F2XX_SYSCFG "stm32f2xx-syscfg"
-#define STM32F2XX_SYSCFG(obj) \
-    OBJECT_CHECK(STM32F2XXSyscfgState, (obj), TYPE_STM32F2XX_SYSCFG)
+typedef struct STM32F2XXSyscfgState STM32F2XXSyscfgState;
+DECLARE_INSTANCE_CHECKER(STM32F2XXSyscfgState, STM32F2XX_SYSCFG,
+                         TYPE_STM32F2XX_SYSCFG)
 
-typedef struct {
+struct STM32F2XXSyscfgState {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -55,6 +57,6 @@ typedef struct {
     uint32_t syscfg_cmpcr;
 
     qemu_irq irq;
-} STM32F2XXSyscfgState;
+};
 
 #endif /* HW_STM32F2XX_SYSCFG_H */
diff --git a/include/hw/misc/stm32f4xx_exti.h b/include/hw/misc/stm32f4xx_exti.h
index 707036a41b..4987c286ed 100644
--- a/include/hw/misc/stm32f4xx_exti.h
+++ b/include/hw/misc/stm32f4xx_exti.h
@@ -27,6 +27,7 @@
 
 #include "hw/sysbus.h"
 #include "hw/hw.h"
+#include "qom/object.h"
 
 #define EXTI_IMR   0x00
 #define EXTI_EMR   0x04
@@ -36,13 +37,14 @@
 #define EXTI_PR    0x14
 
 #define TYPE_STM32F4XX_EXTI "stm32f4xx-exti"
-#define STM32F4XX_EXTI(obj) \
-    OBJECT_CHECK(STM32F4xxExtiState, (obj), TYPE_STM32F4XX_EXTI)
+typedef struct STM32F4xxExtiState STM32F4xxExtiState;
+DECLARE_INSTANCE_CHECKER(STM32F4xxExtiState, STM32F4XX_EXTI,
+                         TYPE_STM32F4XX_EXTI)
 
 #define NUM_GPIO_EVENT_IN_LINES 16
 #define NUM_INTERRUPT_OUT_LINES 16
 
-typedef struct {
+struct STM32F4xxExtiState {
     SysBusDevice parent_obj;
 
     MemoryRegion mmio;
@@ -55,6 +57,6 @@ typedef struct {
     uint32_t exti_pr;
 
     qemu_irq irq[NUM_INTERRUPT_OUT_LINES];
-} STM32F4xxExtiState;
+};
 
 #endif
diff --git a/include/hw/misc/stm32f4xx_syscfg.h b/include/hw/misc/stm32f4xx_syscfg.h
index c62c6629e5..c3d89d4536 100644
--- a/include/hw/misc/stm32f4xx_syscfg.h
+++ b/include/hw/misc/stm32f4xx_syscfg.h
@@ -27,6 +27,7 @@
 
 #include "hw/sysbus.h"
 #include "hw/hw.h"
+#include "qom/object.h"
 
 #define SYSCFG_MEMRMP  0x00
 #define SYSCFG_PMC     0x04
@@ -37,12 +38,13 @@
 #define SYSCFG_CMPCR   0x20
 
 #define TYPE_STM32F4XX_SYSCFG "stm32f4xx-syscfg"
-#define STM32F4XX_SYSCFG(obj) \
-    OBJECT_CHECK(STM32F4xxSyscfgState, (obj), TYPE_STM32F4XX_SYSCFG)
+typedef struct STM32F4xxSyscfgState STM32F4xxSyscfgState;
+DECLARE_INSTANCE_CHECKER(STM32F4xxSyscfgState, STM32F4XX_SYSCFG,
+                         TYPE_STM32F4XX_SYSCFG)
 
 #define SYSCFG_NUM_EXTICR 4
 
-typedef struct {
+struct STM32F4xxSyscfgState {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -56,6 +58,6 @@ typedef struct {
 
     qemu_irq irq;
     qemu_irq gpio_out[16];
-} STM32F4xxSyscfgState;
+};
 
 #endif
diff --git a/include/hw/misc/tz-mpc.h b/include/hw/misc/tz-mpc.h
index 6f15945410..34e45fdb97 100644
--- a/include/hw/misc/tz-mpc.h
+++ b/include/hw/misc/tz-mpc.h
@@ -32,15 +32,17 @@
 #define TZ_MPC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_TZ_MPC "tz-mpc"
-#define TZ_MPC(obj) OBJECT_CHECK(TZMPC, (obj), TYPE_TZ_MPC)
+typedef struct TZMPC TZMPC;
+DECLARE_INSTANCE_CHECKER(TZMPC, TZ_MPC,
+                         TYPE_TZ_MPC)
 
 #define TZ_NUM_PORTS 16
 
 #define TYPE_TZ_MPC_IOMMU_MEMORY_REGION "tz-mpc-iommu-memory-region"
 
-typedef struct TZMPC TZMPC;
 
 struct TZMPC {
     /*< private >*/
diff --git a/include/hw/misc/tz-msc.h b/include/hw/misc/tz-msc.h
index 116b96ae9b..7169f330ff 100644
--- a/include/hw/misc/tz-msc.h
+++ b/include/hw/misc/tz-msc.h
@@ -52,11 +52,14 @@
 
 #include "hw/sysbus.h"
 #include "target/arm/idau.h"
+#include "qom/object.h"
 
 #define TYPE_TZ_MSC "tz-msc"
-#define TZ_MSC(obj) OBJECT_CHECK(TZMSC, (obj), TYPE_TZ_MSC)
+typedef struct TZMSC TZMSC;
+DECLARE_INSTANCE_CHECKER(TZMSC, TZ_MSC,
+                         TYPE_TZ_MSC)
 
-typedef struct TZMSC {
+struct TZMSC {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -74,6 +77,6 @@ typedef struct TZMSC {
     AddressSpace downstream_as;
     MemoryRegion upstream;
     IDAUInterface *idau;
-} TZMSC;
+};
 
 #endif
diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h
index 080d6e2ec1..b5251b715e 100644
--- a/include/hw/misc/tz-ppc.h
+++ b/include/hw/misc/tz-ppc.h
@@ -66,13 +66,15 @@
 #define TZ_PPC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_TZ_PPC "tz-ppc"
-#define TZ_PPC(obj) OBJECT_CHECK(TZPPC, (obj), TYPE_TZ_PPC)
+typedef struct TZPPC TZPPC;
+DECLARE_INSTANCE_CHECKER(TZPPC, TZ_PPC,
+                         TYPE_TZ_PPC)
 
 #define TZ_NUM_PORTS 16
 
-typedef struct TZPPC TZPPC;
 
 typedef struct TZPPCPort {
     TZPPC *ppc;
diff --git a/include/hw/misc/unimp.h b/include/hw/misc/unimp.h
index c63968a2cd..7c724bab94 100644
--- a/include/hw/misc/unimp.h
+++ b/include/hw/misc/unimp.h
@@ -11,19 +11,21 @@
 #include "hw/qdev-properties.h"
 #include "hw/sysbus.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 #define TYPE_UNIMPLEMENTED_DEVICE "unimplemented-device"
 
-#define UNIMPLEMENTED_DEVICE(obj) \
-    OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
+typedef struct UnimplementedDeviceState UnimplementedDeviceState;
+DECLARE_INSTANCE_CHECKER(UnimplementedDeviceState, UNIMPLEMENTED_DEVICE,
+                         TYPE_UNIMPLEMENTED_DEVICE)
 
-typedef struct {
+struct UnimplementedDeviceState {
     SysBusDevice parent_obj;
     MemoryRegion iomem;
     unsigned offset_fmt_width;
     char *name;
     uint64_t size;
-} UnimplementedDeviceState;
+};
 
 /**
  * create_unimplemented_device: create and map a dummy device
diff --git a/include/hw/misc/vmcoreinfo.h b/include/hw/misc/vmcoreinfo.h
index d4f3d3a91c..ebada6617a 100644
--- a/include/hw/misc/vmcoreinfo.h
+++ b/include/hw/misc/vmcoreinfo.h
@@ -14,18 +14,21 @@
 
 #include "hw/qdev-core.h"
 #include "standard-headers/linux/qemu_fw_cfg.h"
+#include "qom/object.h"
 
 #define VMCOREINFO_DEVICE "vmcoreinfo"
-#define VMCOREINFO(obj) OBJECT_CHECK(VMCoreInfoState, (obj), VMCOREINFO_DEVICE)
+typedef struct VMCoreInfoState VMCoreInfoState;
+DECLARE_INSTANCE_CHECKER(VMCoreInfoState, VMCOREINFO,
+                         VMCOREINFO_DEVICE)
 
 typedef struct fw_cfg_vmcoreinfo FWCfgVMCoreInfo;
 
-typedef struct VMCoreInfoState {
+struct VMCoreInfoState {
     DeviceClass parent_obj;
 
     bool has_vmcoreinfo;
     FWCfgVMCoreInfo vmcoreinfo;
-} VMCoreInfoState;
+};
 
 /* returns NULL unless there is exactly one device */
 static inline VMCoreInfoState *vmcoreinfo_find(void)
diff --git a/include/hw/misc/zynq-xadc.h b/include/hw/misc/zynq-xadc.h
index f1a410a376..052f47954f 100644
--- a/include/hw/misc/zynq-xadc.h
+++ b/include/hw/misc/zynq-xadc.h
@@ -16,6 +16,7 @@
 #define ZYNQ_XADC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define ZYNQ_XADC_MMIO_SIZE     0x0020
 #define ZYNQ_XADC_NUM_IO_REGS   (ZYNQ_XADC_MMIO_SIZE / 4)
@@ -23,10 +24,11 @@
 #define ZYNQ_XADC_FIFO_DEPTH    15
 
 #define TYPE_ZYNQ_XADC          "xlnx,zynq-xadc"
-#define ZYNQ_XADC(obj) \
-    OBJECT_CHECK(ZynqXADCState, (obj), TYPE_ZYNQ_XADC)
+typedef struct ZynqXADCState ZynqXADCState;
+DECLARE_INSTANCE_CHECKER(ZynqXADCState, ZYNQ_XADC,
+                         TYPE_ZYNQ_XADC)
 
-typedef struct ZynqXADCState {
+struct ZynqXADCState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -41,6 +43,6 @@ typedef struct ZynqXADCState {
 
     struct IRQState *qemu_irq;
 
-} ZynqXADCState;
+};
 
 #endif /* ZYNQ_XADC_H */
diff --git a/include/hw/net/allwinner-sun8i-emac.h b/include/hw/net/allwinner-sun8i-emac.h
index dd1d7b96cd..89e56b815b 100644
--- a/include/hw/net/allwinner-sun8i-emac.h
+++ b/include/hw/net/allwinner-sun8i-emac.h
@@ -30,15 +30,16 @@
  */
 
 #define TYPE_AW_SUN8I_EMAC "allwinner-sun8i-emac"
-#define AW_SUN8I_EMAC(obj) \
-    OBJECT_CHECK(AwSun8iEmacState, (obj), TYPE_AW_SUN8I_EMAC)
+typedef struct AwSun8iEmacState AwSun8iEmacState;
+DECLARE_INSTANCE_CHECKER(AwSun8iEmacState, AW_SUN8I_EMAC,
+                         TYPE_AW_SUN8I_EMAC)
 
 /** @} */
 
 /**
  * Allwinner Sun8i EMAC object instance state
  */
-typedef struct AwSun8iEmacState {
+struct AwSun8iEmacState {
     /*< private >*/
     SysBusDevice  parent_obj;
     /*< public >*/
@@ -100,6 +101,6 @@ typedef struct AwSun8iEmacState {
 
     /** @} */
 
-} AwSun8iEmacState;
+};
 
 #endif /* HW_NET_ALLWINNER_SUN8I_H */
diff --git a/include/hw/net/allwinner_emac.h b/include/hw/net/allwinner_emac.h
index 5013207d15..f5f5b67939 100644
--- a/include/hw/net/allwinner_emac.h
+++ b/include/hw/net/allwinner_emac.h
@@ -28,9 +28,12 @@
 #include "qemu/fifo8.h"
 #include "hw/net/mii.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_AW_EMAC "allwinner-emac"
-#define AW_EMAC(obj) OBJECT_CHECK(AwEmacState, (obj), TYPE_AW_EMAC)
+typedef struct AwEmacState AwEmacState;
+DECLARE_INSTANCE_CHECKER(AwEmacState, AW_EMAC,
+                         TYPE_AW_EMAC)
 
 /*
  * Allwinner EMAC register list
@@ -144,7 +147,7 @@ typedef struct RTL8201CPState {
     uint16_t anlpar;
 } RTL8201CPState;
 
-typedef struct AwEmacState {
+struct AwEmacState {
     /*< private >*/
     SysBusDevice  parent_obj;
     /*< public >*/
@@ -171,6 +174,6 @@ typedef struct AwEmacState {
     Fifo8          tx_fifo[NUM_TX_FIFOS];
     uint32_t       tx_length[NUM_TX_FIFOS];
     uint32_t       tx_channel;
-} AwEmacState;
+};
 
 #endif
diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h
index 01c6189a24..89d2dab513 100644
--- a/include/hw/net/cadence_gem.h
+++ b/include/hw/net/cadence_gem.h
@@ -24,9 +24,12 @@
 
 #ifndef CADENCE_GEM_H
 #define CADENCE_GEM_H
+#include "qom/object.h"
 
 #define TYPE_CADENCE_GEM "cadence_gem"
-#define CADENCE_GEM(obj) OBJECT_CHECK(CadenceGEMState, (obj), TYPE_CADENCE_GEM)
+typedef struct CadenceGEMState CadenceGEMState;
+DECLARE_INSTANCE_CHECKER(CadenceGEMState, CADENCE_GEM,
+                         TYPE_CADENCE_GEM)
 
 #include "net/net.h"
 #include "hw/sysbus.h"
@@ -43,7 +46,7 @@
 #define MAX_JUMBO_FRAME_SIZE_MASK 0x3FFF
 #define MAX_FRAME_SIZE MAX_JUMBO_FRAME_SIZE_MASK
 
-typedef struct CadenceGEMState {
+struct CadenceGEMState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -91,6 +94,6 @@ typedef struct CadenceGEMState {
     uint32_t rx_desc[MAX_PRIORITY_QUEUES][DESC_MAX_NUM_WORDS];
 
     bool sar_active[4];
-} CadenceGEMState;
+};
 
 #endif
diff --git a/include/hw/net/ftgmac100.h b/include/hw/net/ftgmac100.h
index ab37e7b2b8..c6b1c11fca 100644
--- a/include/hw/net/ftgmac100.h
+++ b/include/hw/net/ftgmac100.h
@@ -9,9 +9,12 @@
 
 #ifndef FTGMAC100_H
 #define FTGMAC100_H
+#include "qom/object.h"
 
 #define TYPE_FTGMAC100 "ftgmac100"
-#define FTGMAC100(obj) OBJECT_CHECK(FTGMAC100State, (obj), TYPE_FTGMAC100)
+typedef struct FTGMAC100State FTGMAC100State;
+DECLARE_INSTANCE_CHECKER(FTGMAC100State, FTGMAC100,
+                         TYPE_FTGMAC100)
 
 #include "hw/sysbus.h"
 #include "net/net.h"
@@ -21,7 +24,7 @@
  */
 #define FTGMAC100_MAX_FRAME_SIZE    9220
 
-typedef struct FTGMAC100State {
+struct FTGMAC100State {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -64,15 +67,17 @@ typedef struct FTGMAC100State {
     bool aspeed;
     uint32_t txdes0_edotr;
     uint32_t rxdes0_edorr;
-} FTGMAC100State;
+};
 
 #define TYPE_ASPEED_MII "aspeed-mmi"
-#define ASPEED_MII(obj) OBJECT_CHECK(AspeedMiiState, (obj), TYPE_ASPEED_MII)
+typedef struct AspeedMiiState AspeedMiiState;
+DECLARE_INSTANCE_CHECKER(AspeedMiiState, ASPEED_MII,
+                         TYPE_ASPEED_MII)
 
 /*
  * AST2600 MII controller
  */
-typedef struct AspeedMiiState {
+struct AspeedMiiState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -81,6 +86,6 @@ typedef struct AspeedMiiState {
     MemoryRegion iomem;
     uint32_t phycr;
     uint32_t phydata;
-} AspeedMiiState;
+};
 
 #endif
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
index 9f03034b89..ffdbc304b6 100644
--- a/include/hw/net/imx_fec.h
+++ b/include/hw/net/imx_fec.h
@@ -23,9 +23,12 @@
 
 #ifndef IMX_FEC_H
 #define IMX_FEC_H
+#include "qom/object.h"
 
 #define TYPE_IMX_FEC "imx.fec"
-#define IMX_FEC(obj) OBJECT_CHECK(IMXFECState, (obj), TYPE_IMX_FEC)
+typedef struct IMXFECState IMXFECState;
+DECLARE_INSTANCE_CHECKER(IMXFECState, IMX_FEC,
+                         TYPE_IMX_FEC)
 
 #define TYPE_IMX_ENET "imx.enet"
 
@@ -247,7 +250,7 @@ typedef struct {
 
 #define FSL_IMX25_FEC_SIZE      0x4000
 
-typedef struct IMXFECState {
+struct IMXFECState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -274,6 +277,6 @@ typedef struct IMXFECState {
 
     /* Buffer used to assemble a Tx frame */
     uint8_t frame[ENET_MAX_FRAME_SIZE];
-} IMXFECState;
+};
 
 #endif
diff --git a/include/hw/net/lance.h b/include/hw/net/lance.h
index 0357f5f65c..f645d6af67 100644
--- a/include/hw/net/lance.h
+++ b/include/hw/net/lance.h
@@ -32,15 +32,17 @@
 #include "net/net.h"
 #include "hw/net/pcnet.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_LANCE "lance"
-#define SYSBUS_PCNET(obj) \
-    OBJECT_CHECK(SysBusPCNetState, (obj), TYPE_LANCE)
+typedef struct SysBusPCNetState SysBusPCNetState;
+DECLARE_INSTANCE_CHECKER(SysBusPCNetState, SYSBUS_PCNET,
+                         TYPE_LANCE)
 
-typedef struct {
+struct SysBusPCNetState {
     SysBusDevice parent_obj;
 
     PCNetState state;
-} SysBusPCNetState;
+};
 
 #endif
diff --git a/include/hw/net/lasi_82596.h b/include/hw/net/lasi_82596.h
index e76ef8308e..7b62b04833 100644
--- a/include/hw/net/lasi_82596.h
+++ b/include/hw/net/lasi_82596.h
@@ -10,18 +10,20 @@
 
 #include "net/net.h"
 #include "hw/net/i82596.h"
+#include "qom/object.h"
 
 #define TYPE_LASI_82596 "lasi_82596"
-#define SYSBUS_I82596(obj) \
-    OBJECT_CHECK(SysBusI82596State, (obj), TYPE_LASI_82596)
+typedef struct SysBusI82596State SysBusI82596State;
+DECLARE_INSTANCE_CHECKER(SysBusI82596State, SYSBUS_I82596,
+                         TYPE_LASI_82596)
 
-typedef struct {
+struct SysBusI82596State {
     SysBusDevice parent_obj;
 
     I82596State state;
     uint16_t last_val;
     int val_index:1;
-} SysBusI82596State;
+};
 
 SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space,
                                     hwaddr hpa, qemu_irq irq);
diff --git a/include/hw/net/msf2-emac.h b/include/hw/net/msf2-emac.h
index 37966d3a81..68194d798c 100644
--- a/include/hw/net/msf2-emac.h
+++ b/include/hw/net/msf2-emac.h
@@ -26,15 +26,17 @@
 #include "exec/memory.h"
 #include "net/net.h"
 #include "net/eth.h"
+#include "qom/object.h"
 
 #define TYPE_MSS_EMAC "msf2-emac"
-#define MSS_EMAC(obj) \
-    OBJECT_CHECK(MSF2EmacState, (obj), TYPE_MSS_EMAC)
+typedef struct MSF2EmacState MSF2EmacState;
+DECLARE_INSTANCE_CHECKER(MSF2EmacState, MSS_EMAC,
+                         TYPE_MSS_EMAC)
 
 #define R_MAX         (0x1a0 / 4)
 #define PHY_MAX_REGS  32
 
-typedef struct MSF2EmacState {
+struct MSF2EmacState {
     SysBusDevice parent;
 
     MemoryRegion mmio;
@@ -50,4 +52,4 @@ typedef struct MSF2EmacState {
     uint16_t phy_regs[PHY_MAX_REGS];
 
     uint32_t regs[R_MAX];
-} MSF2EmacState;
+};
diff --git a/include/hw/nmi.h b/include/hw/nmi.h
index fe37ce3ad8..fff41bebc6 100644
--- a/include/hw/nmi.h
+++ b/include/hw/nmi.h
@@ -26,20 +26,19 @@
 
 #define TYPE_NMI "nmi"
 
-#define NMI_CLASS(klass) \
-     OBJECT_CLASS_CHECK(NMIClass, (klass), TYPE_NMI)
-#define NMI_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(NMIClass, (obj), TYPE_NMI)
+typedef struct NMIClass NMIClass;
+DECLARE_CLASS_CHECKERS(NMIClass, NMI,
+                       TYPE_NMI)
 #define NMI(obj) \
      INTERFACE_CHECK(NMIState, (obj), TYPE_NMI)
 
 typedef struct NMIState NMIState;
 
-typedef struct NMIClass {
+struct NMIClass {
     InterfaceClass parent_class;
 
     void (*nmi_monitor_handler)(NMIState *n, int cpu_index, Error **errp);
-} NMIClass;
+};
 
 void nmi_monitor_handle(int cpu_index, Error **errp);
 
diff --git a/include/hw/nubus/mac-nubus-bridge.h b/include/hw/nubus/mac-nubus-bridge.h
index ce9c789d99..6856d7e095 100644
--- a/include/hw/nubus/mac-nubus-bridge.h
+++ b/include/hw/nubus/mac-nubus-bridge.h
@@ -10,15 +10,17 @@
 #define HW_NUBUS_MAC_H
 
 #include "hw/nubus/nubus.h"
+#include "qom/object.h"
 
 #define TYPE_MAC_NUBUS_BRIDGE "mac-nubus-bridge"
-#define MAC_NUBUS_BRIDGE(obj) OBJECT_CHECK(MacNubusState, (obj), \
-                                           TYPE_MAC_NUBUS_BRIDGE)
+typedef struct MacNubusState MacNubusState;
+DECLARE_INSTANCE_CHECKER(MacNubusState, MAC_NUBUS_BRIDGE,
+                         TYPE_MAC_NUBUS_BRIDGE)
 
-typedef struct MacNubusState {
+struct MacNubusState {
     SysBusDevice sysbus_dev;
 
     NubusBus *bus;
-} MacNubusState;
+};
 
 #endif
diff --git a/include/hw/nubus/nubus.h b/include/hw/nubus/nubus.h
index c350948262..9370f0d8f0 100644
--- a/include/hw/nubus/nubus.h
+++ b/include/hw/nubus/nubus.h
@@ -11,6 +11,7 @@
 
 #include "hw/qdev-properties.h"
 #include "exec/address-spaces.h"
+#include "qom/object.h"
 
 #define NUBUS_SUPER_SLOT_SIZE 0x10000000U
 #define NUBUS_SUPER_SLOT_NB   0x9
@@ -22,24 +23,27 @@
 #define NUBUS_LAST_SLOT       0xF
 
 #define TYPE_NUBUS_DEVICE "nubus-device"
-#define NUBUS_DEVICE(obj) \
-     OBJECT_CHECK(NubusDevice, (obj), TYPE_NUBUS_DEVICE)
+typedef struct NubusDevice NubusDevice;
+DECLARE_INSTANCE_CHECKER(NubusDevice, NUBUS_DEVICE,
+                         TYPE_NUBUS_DEVICE)
 
 #define TYPE_NUBUS_BUS "nubus-bus"
-#define NUBUS_BUS(obj) OBJECT_CHECK(NubusBus, (obj), TYPE_NUBUS_BUS)
+typedef struct NubusBus NubusBus;
+DECLARE_INSTANCE_CHECKER(NubusBus, NUBUS_BUS,
+                         TYPE_NUBUS_BUS)
 
 #define TYPE_NUBUS_BRIDGE "nubus-bridge"
 
-typedef struct NubusBus {
+struct NubusBus {
     BusState qbus;
 
     MemoryRegion super_slot_io;
     MemoryRegion slot_io;
 
     int current_slot;
-} NubusBus;
+};
 
-typedef struct NubusDevice {
+struct NubusDevice {
     DeviceState qdev;
 
     int slot_nb;
@@ -60,7 +64,7 @@ typedef struct NubusDevice {
 
     MemoryRegion rom_io;
     const uint8_t *rom;
-} NubusDevice;
+};
 
 void nubus_register_rom(NubusDevice *dev, const uint8_t *rom, uint32_t size,
                         int revision, int format, uint8_t byte_lanes);
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index f190c428e8..f85393400c 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -5,24 +5,25 @@
 #include "standard-headers/linux/qemu_fw_cfg.h"
 #include "hw/sysbus.h"
 #include "sysemu/dma.h"
+#include "qom/object.h"
 
 #define TYPE_FW_CFG     "fw_cfg"
 #define TYPE_FW_CFG_IO  "fw_cfg_io"
 #define TYPE_FW_CFG_MEM "fw_cfg_mem"
 #define TYPE_FW_CFG_DATA_GENERATOR_INTERFACE "fw_cfg-data-generator"
 
-#define FW_CFG(obj)     OBJECT_CHECK(FWCfgState,    (obj), TYPE_FW_CFG)
-#define FW_CFG_IO(obj)  OBJECT_CHECK(FWCfgIoState,  (obj), TYPE_FW_CFG_IO)
-#define FW_CFG_MEM(obj) OBJECT_CHECK(FWCfgMemState, (obj), TYPE_FW_CFG_MEM)
+DECLARE_INSTANCE_CHECKER(FWCfgState, FW_CFG,
+                         TYPE_FW_CFG)
+DECLARE_INSTANCE_CHECKER(FWCfgIoState, FW_CFG_IO,
+                         TYPE_FW_CFG_IO)
+DECLARE_INSTANCE_CHECKER(FWCfgMemState, FW_CFG_MEM,
+                         TYPE_FW_CFG_MEM)
 
-#define FW_CFG_DATA_GENERATOR_CLASS(class) \
-    OBJECT_CLASS_CHECK(FWCfgDataGeneratorClass, (class), \
+typedef struct FWCfgDataGeneratorClass FWCfgDataGeneratorClass;
+DECLARE_CLASS_CHECKERS(FWCfgDataGeneratorClass, FW_CFG_DATA_GENERATOR,
                        TYPE_FW_CFG_DATA_GENERATOR_INTERFACE)
-#define FW_CFG_DATA_GENERATOR_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(FWCfgDataGeneratorClass, (obj), \
-                     TYPE_FW_CFG_DATA_GENERATOR_INTERFACE)
 
-typedef struct FWCfgDataGeneratorClass {
+struct FWCfgDataGeneratorClass {
     /*< private >*/
     InterfaceClass parent_class;
     /*< public >*/
@@ -39,7 +40,7 @@ typedef struct FWCfgDataGeneratorClass {
      * required.
      */
     GByteArray *(*get_data)(Object *obj, Error **errp);
-} FWCfgDataGeneratorClass;
+};
 
 typedef struct fw_cfg_file FWCfgFile;
 
diff --git a/include/hw/nvram/nrf51_nvm.h b/include/hw/nvram/nrf51_nvm.h
index 3792e4a9fe..ab99b09206 100644
--- a/include/hw/nvram/nrf51_nvm.h
+++ b/include/hw/nvram/nrf51_nvm.h
@@ -23,8 +23,11 @@
 #define NRF51_NVM_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 #define TYPE_NRF51_NVM "nrf51_soc.nvm"
-#define NRF51_NVM(obj) OBJECT_CHECK(NRF51NVMState, (obj), TYPE_NRF51_NVM)
+typedef struct NRF51NVMState NRF51NVMState;
+DECLARE_INSTANCE_CHECKER(NRF51NVMState, NRF51_NVM,
+                         TYPE_NRF51_NVM)
 
 #define NRF51_UICR_FIXTURE_SIZE 64
 
@@ -44,7 +47,7 @@
 
 #define NRF51_UICR_SIZE         0x100
 
-typedef struct NRF51NVMState {
+struct NRF51NVMState {
     SysBusDevice parent_obj;
 
     MemoryRegion mmio;
@@ -58,7 +61,7 @@ typedef struct NRF51NVMState {
 
     uint32_t config;
 
-} NRF51NVMState;
+};
 
 
 #endif
diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h
index 0038bfbe3d..f2f0a27381 100644
--- a/include/hw/or-irq.h
+++ b/include/hw/or-irq.h
@@ -37,7 +37,8 @@
 
 typedef struct OrIRQState qemu_or_irq;
 
-#define OR_IRQ(obj) OBJECT_CHECK(qemu_or_irq, (obj), TYPE_OR_IRQ)
+DECLARE_INSTANCE_CHECKER(qemu_or_irq, OR_IRQ,
+                         TYPE_OR_IRQ)
 
 struct OrIRQState {
     DeviceState parent_obj;
diff --git a/include/hw/pci-bridge/simba.h b/include/hw/pci-bridge/simba.h
index d8649973ee..675aa5a990 100644
--- a/include/hw/pci-bridge/simba.h
+++ b/include/hw/pci-bridge/simba.h
@@ -28,15 +28,17 @@
 #define HW_PCI_BRIDGE_SIMBA_H
 
 #include "hw/pci/pci_bridge.h"
+#include "qom/object.h"
 
 
-typedef struct SimbaPCIBridge {
+struct SimbaPCIBridge {
     /*< private >*/
     PCIBridge parent_obj;
-} SimbaPCIBridge;
+};
+typedef struct SimbaPCIBridge SimbaPCIBridge;
 
 #define TYPE_SIMBA_PCI_BRIDGE "pbm-bridge"
-#define SIMBA_PCI_BRIDGE(obj) \
-    OBJECT_CHECK(SimbaPCIBridge, (obj), TYPE_SIMBA_PCI_BRIDGE)
+DECLARE_INSTANCE_CHECKER(SimbaPCIBridge, SIMBA_PCI_BRIDGE,
+                         TYPE_SIMBA_PCI_BRIDGE)
 
 #endif
diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h
index 31c41231b1..551eec3107 100644
--- a/include/hw/pci-host/designware.h
+++ b/include/hw/pci-host/designware.h
@@ -26,17 +26,19 @@
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pcie_host.h"
 #include "hw/pci/pci_bridge.h"
+#include "qom/object.h"
 
 #define TYPE_DESIGNWARE_PCIE_HOST "designware-pcie-host"
-#define DESIGNWARE_PCIE_HOST(obj) \
-     OBJECT_CHECK(DesignwarePCIEHost, (obj), TYPE_DESIGNWARE_PCIE_HOST)
+typedef struct DesignwarePCIEHost DesignwarePCIEHost;
+DECLARE_INSTANCE_CHECKER(DesignwarePCIEHost, DESIGNWARE_PCIE_HOST,
+                         TYPE_DESIGNWARE_PCIE_HOST)
 
 #define TYPE_DESIGNWARE_PCIE_ROOT "designware-pcie-root"
-#define DESIGNWARE_PCIE_ROOT(obj) \
-     OBJECT_CHECK(DesignwarePCIERoot, (obj), TYPE_DESIGNWARE_PCIE_ROOT)
+typedef struct DesignwarePCIERoot DesignwarePCIERoot;
+DECLARE_INSTANCE_CHECKER(DesignwarePCIERoot, DESIGNWARE_PCIE_ROOT,
+                         TYPE_DESIGNWARE_PCIE_ROOT)
 
 struct DesignwarePCIERoot;
-typedef struct DesignwarePCIERoot DesignwarePCIERoot;
 
 typedef struct DesignwarePCIEViewport {
     DesignwarePCIERoot *root;
@@ -80,7 +82,7 @@ struct DesignwarePCIERoot {
     DesignwarePCIEMSI msi;
 };
 
-typedef struct DesignwarePCIEHost {
+struct DesignwarePCIEHost {
     PCIHostState parent_obj;
 
     DesignwarePCIERoot root;
@@ -96,6 +98,6 @@ typedef struct DesignwarePCIEHost {
     } pci;
 
     MemoryRegion mmio;
-} DesignwarePCIEHost;
+};
 
 #endif /* DESIGNWARE_H */
diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h
index faea040a93..2f4e852eee 100644
--- a/include/hw/pci-host/gpex.h
+++ b/include/hw/pci-host/gpex.h
@@ -23,24 +23,27 @@
 #include "hw/sysbus.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pcie_host.h"
+#include "qom/object.h"
 
 #define TYPE_GPEX_HOST "gpex-pcihost"
-#define GPEX_HOST(obj) \
-     OBJECT_CHECK(GPEXHost, (obj), TYPE_GPEX_HOST)
+typedef struct GPEXHost GPEXHost;
+DECLARE_INSTANCE_CHECKER(GPEXHost, GPEX_HOST,
+                         TYPE_GPEX_HOST)
 
 #define TYPE_GPEX_ROOT_DEVICE "gpex-root"
-#define MCH_PCI_DEVICE(obj) \
-     OBJECT_CHECK(GPEXRootState, (obj), TYPE_GPEX_ROOT_DEVICE)
+typedef struct GPEXRootState GPEXRootState;
+DECLARE_INSTANCE_CHECKER(GPEXRootState, GPEX_ROOT_DEVICE,
+                         TYPE_GPEX_ROOT_DEVICE)
 
 #define GPEX_NUM_IRQS 4
 
-typedef struct GPEXRootState {
+struct GPEXRootState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
-} GPEXRootState;
+};
 
-typedef struct GPEXHost {
+struct GPEXHost {
     /*< private >*/
     PCIExpressHost parent_obj;
     /*< public >*/
@@ -51,7 +54,7 @@ typedef struct GPEXHost {
     MemoryRegion io_mmio;
     qemu_irq irq[GPEX_NUM_IRQS];
     int irq_num[GPEX_NUM_IRQS];
-} GPEXHost;
+};
 
 int gpex_set_irq_num(GPEXHost *s, int index, int gsi);
 
diff --git a/include/hw/pci-host/i440fx.h b/include/hw/pci-host/i440fx.h
index cc58d82ed4..046c64576d 100644
--- a/include/hw/pci-host/i440fx.h
+++ b/include/hw/pci-host/i440fx.h
@@ -14,14 +14,16 @@
 #include "hw/hw.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci-host/pam.h"
+#include "qom/object.h"
 
 #define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost"
 #define TYPE_I440FX_PCI_DEVICE "i440FX"
 
-#define I440FX_PCI_DEVICE(obj) \
-    OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE)
+typedef struct PCII440FXState PCII440FXState;
+DECLARE_INSTANCE_CHECKER(PCII440FXState, I440FX_PCI_DEVICE,
+                         TYPE_I440FX_PCI_DEVICE)
 
-typedef struct PCII440FXState {
+struct PCII440FXState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
@@ -32,7 +34,7 @@ typedef struct PCII440FXState {
     PAMMemoryRegion pam_regions[13];
     MemoryRegion smram_region;
     MemoryRegion smram, low_smram;
-} PCII440FXState;
+};
 
 #define TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE "igd-passthrough-i440FX"
 
diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h
index 75b787867a..182f29d681 100644
--- a/include/hw/pci-host/pnv_phb3.h
+++ b/include/hw/pci-host/pnv_phb3.h
@@ -13,6 +13,7 @@
 #include "hw/pci/pcie_host.h"
 #include "hw/pci/pcie_port.h"
 #include "hw/ppc/xics.h"
+#include "qom/object.h"
 
 typedef struct PnvPHB3 PnvPHB3;
 
@@ -20,18 +21,20 @@ typedef struct PnvPHB3 PnvPHB3;
  * PHB3 XICS Source for MSIs
  */
 #define TYPE_PHB3_MSI "phb3-msi"
-#define PHB3_MSI(obj) OBJECT_CHECK(Phb3MsiState, (obj), TYPE_PHB3_MSI)
+typedef struct Phb3MsiState Phb3MsiState;
+DECLARE_INSTANCE_CHECKER(Phb3MsiState, PHB3_MSI,
+                         TYPE_PHB3_MSI)
 
 #define PHB3_MAX_MSI     2048
 
-typedef struct Phb3MsiState {
+struct Phb3MsiState {
     ICSState ics;
     qemu_irq *qirqs;
 
     PnvPHB3 *phb;
     uint64_t rba[PHB3_MAX_MSI / 64];
     uint32_t rba_sum;
-} Phb3MsiState;
+};
 
 void pnv_phb3_msi_update_config(Phb3MsiState *msis, uint32_t base,
                                 uint32_t count);
@@ -69,9 +72,11 @@ typedef struct PnvPhb3DMASpace {
  * PHB3 Power Bus Common Queue
  */
 #define TYPE_PNV_PBCQ "pnv-pbcq"
-#define PNV_PBCQ(obj) OBJECT_CHECK(PnvPBCQState, (obj), TYPE_PNV_PBCQ)
+typedef struct PnvPBCQState PnvPBCQState;
+DECLARE_INSTANCE_CHECKER(PnvPBCQState, PNV_PBCQ,
+                         TYPE_PNV_PBCQ)
 
-typedef struct PnvPBCQState {
+struct PnvPBCQState {
     DeviceState parent;
 
     uint32_t nest_xbase;
@@ -96,7 +101,7 @@ typedef struct PnvPBCQState {
     MemoryRegion xscom_nest_regs;
     MemoryRegion xscom_pci_regs;
     MemoryRegion xscom_spci_regs;
-} PnvPBCQState;
+};
 
 /*
  * PHB3 PCIe Root port
@@ -113,7 +118,8 @@ typedef struct PnvPHB3RootPort {
  * PHB3 PCIe Host Bridge for PowerNV machines (POWER8)
  */
 #define TYPE_PNV_PHB3 "pnv-phb3"
-#define PNV_PHB3(obj) OBJECT_CHECK(PnvPHB3, (obj), TYPE_PNV_PHB3)
+DECLARE_INSTANCE_CHECKER(PnvPHB3, PNV_PHB3,
+                         TYPE_PNV_PHB3)
 
 #define PNV_PHB3_NUM_M64      16
 #define PNV_PHB3_NUM_REGS     (0x1000 >> 3)
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index c882bfd0aa..15a4633178 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -13,6 +13,7 @@
 #include "hw/pci/pcie_host.h"
 #include "hw/pci/pcie_port.h"
 #include "hw/ppc/xive.h"
+#include "qom/object.h"
 
 typedef struct PnvPhb4PecState PnvPhb4PecState;
 typedef struct PnvPhb4PecStack PnvPhb4PecStack;
@@ -57,7 +58,8 @@ typedef struct PnvPHB4RootPort {
  * PHB4 PCIe Host Bridge for PowerNV machines (POWER9)
  */
 #define TYPE_PNV_PHB4 "pnv-phb4"
-#define PNV_PHB4(obj) OBJECT_CHECK(PnvPHB4, (obj), TYPE_PNV_PHB4)
+DECLARE_INSTANCE_CHECKER(PnvPHB4, PNV_PHB4,
+                         TYPE_PNV_PHB4)
 
 #define PNV_PHB4_MAX_LSIs          8
 #define PNV_PHB4_MAX_INTs          4096
@@ -140,12 +142,13 @@ extern const MemoryRegionOps pnv_phb4_xscom_ops;
  * PHB4 PEC (PCI Express Controller)
  */
 #define TYPE_PNV_PHB4_PEC "pnv-phb4-pec"
-#define PNV_PHB4_PEC(obj) \
-    OBJECT_CHECK(PnvPhb4PecState, (obj), TYPE_PNV_PHB4_PEC)
+typedef struct PnvPhb4PecClass PnvPhb4PecClass;
+DECLARE_OBJ_CHECKERS(PnvPhb4PecState, PnvPhb4PecClass,
+                     PNV_PHB4_PEC, TYPE_PNV_PHB4_PEC)
 
 #define TYPE_PNV_PHB4_PEC_STACK "pnv-phb4-pec-stack"
-#define PNV_PHB4_PEC_STACK(obj) \
-    OBJECT_CHECK(PnvPhb4PecStack, (obj), TYPE_PNV_PHB4_PEC_STACK)
+DECLARE_INSTANCE_CHECKER(PnvPhb4PecStack, PNV_PHB4_PEC_STACK,
+                         TYPE_PNV_PHB4_PEC_STACK)
 
 /* Per-stack data */
 struct PnvPhb4PecStack {
@@ -209,12 +212,8 @@ struct PnvPhb4PecState {
     PnvPhb4PecStack stacks[PHB4_PEC_MAX_STACKS];
 };
 
-#define PNV_PHB4_PEC_CLASS(klass) \
-     OBJECT_CLASS_CHECK(PnvPhb4PecClass, (klass), TYPE_PNV_PHB4_PEC)
-#define PNV_PHB4_PEC_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PnvPhb4PecClass, (obj), TYPE_PNV_PHB4_PEC)
 
-typedef struct PnvPhb4PecClass {
+struct PnvPhb4PecClass {
     DeviceClass parent_class;
 
     uint32_t (*xscom_nest_base)(PnvPhb4PecState *pec);
@@ -225,6 +224,6 @@ typedef struct PnvPhb4PecClass {
     int compat_size;
     const char *stk_compat;
     int stk_compat_size;
-} PnvPhb4PecClass;
+};
 
 #endif /* PCI_HOST_PNV_PHB4_H */
diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h
index 070305f83d..0f5a534f77 100644
--- a/include/hw/pci-host/q35.h
+++ b/include/hw/pci-host/q35.h
@@ -27,16 +27,19 @@
 #include "hw/pci-host/pam.h"
 #include "qemu/units.h"
 #include "qemu/range.h"
+#include "qom/object.h"
 
 #define TYPE_Q35_HOST_DEVICE "q35-pcihost"
-#define Q35_HOST_DEVICE(obj) \
-     OBJECT_CHECK(Q35PCIHost, (obj), TYPE_Q35_HOST_DEVICE)
+typedef struct Q35PCIHost Q35PCIHost;
+DECLARE_INSTANCE_CHECKER(Q35PCIHost, Q35_HOST_DEVICE,
+                         TYPE_Q35_HOST_DEVICE)
 
 #define TYPE_MCH_PCI_DEVICE "mch"
-#define MCH_PCI_DEVICE(obj) \
-     OBJECT_CHECK(MCHPCIState, (obj), TYPE_MCH_PCI_DEVICE)
+typedef struct MCHPCIState MCHPCIState;
+DECLARE_INSTANCE_CHECKER(MCHPCIState, MCH_PCI_DEVICE,
+                         TYPE_MCH_PCI_DEVICE)
 
-typedef struct MCHPCIState {
+struct MCHPCIState {
     /*< private >*/
     PCIDevice parent_obj;
     /*< public >*/
@@ -57,16 +60,16 @@ typedef struct MCHPCIState {
     uint64_t pci_hole64_size;
     uint32_t short_root_bus;
     uint16_t ext_tseg_mbytes;
-} MCHPCIState;
+};
 
-typedef struct Q35PCIHost {
+struct Q35PCIHost {
     /*< private >*/
     PCIExpressHost parent_obj;
     /*< public >*/
 
     bool pci_hole64_fix;
     MCHPCIState mch;
-} Q35PCIHost;
+};
 
 #define Q35_MASK(bit, ms_bit, ls_bit) \
 ((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
diff --git a/include/hw/pci-host/sabre.h b/include/hw/pci-host/sabre.h
index 99b5aefbec..7a76de4b9e 100644
--- a/include/hw/pci-host/sabre.h
+++ b/include/hw/pci-host/sabre.h
@@ -4,6 +4,7 @@
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_host.h"
 #include "hw/sparc/sun4u_iommu.h"
+#include "qom/object.h"
 
 #define MAX_IVEC 0x40
 
@@ -16,15 +17,16 @@
 #define OBIO_MSE_IRQ         0x2a
 #define OBIO_SER_IRQ         0x2b
 
-typedef struct SabrePCIState {
+struct SabrePCIState {
     PCIDevice parent_obj;
-} SabrePCIState;
+};
+typedef struct SabrePCIState SabrePCIState;
 
 #define TYPE_SABRE_PCI_DEVICE "sabre-pci"
-#define SABRE_PCI_DEVICE(obj) \
-    OBJECT_CHECK(SabrePCIState, (obj), TYPE_SABRE_PCI_DEVICE)
+DECLARE_INSTANCE_CHECKER(SabrePCIState, SABRE_PCI_DEVICE,
+                         TYPE_SABRE_PCI_DEVICE)
 
-typedef struct SabreState {
+struct SabreState {
     PCIHostState parent_obj;
 
     hwaddr special_base;
@@ -45,10 +47,11 @@ typedef struct SabreState {
     unsigned int irq_request;
     uint32_t reset_control;
     unsigned int nr_resets;
-} SabreState;
+};
+typedef struct SabreState SabreState;
 
 #define TYPE_SABRE "sabre"
-#define SABRE_DEVICE(obj) \
-    OBJECT_CHECK(SabreState, (obj), TYPE_SABRE)
+DECLARE_INSTANCE_CHECKER(SabreState, SABRE,
+                         TYPE_SABRE)
 
 #endif
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 600eb55c34..0431ce1048 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -24,15 +24,16 @@
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_host.h"
 #include "hw/ppc/xics.h"
+#include "qom/object.h"
 
 #define TYPE_SPAPR_PCI_HOST_BRIDGE "spapr-pci-host-bridge"
 
-#define SPAPR_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(SpaprPhbState, (obj), TYPE_SPAPR_PCI_HOST_BRIDGE)
+typedef struct SpaprPhbState SpaprPhbState;
+DECLARE_INSTANCE_CHECKER(SpaprPhbState, SPAPR_PCI_HOST_BRIDGE,
+                         TYPE_SPAPR_PCI_HOST_BRIDGE)
 
 #define SPAPR_PCI_DMA_MAX_WINDOWS    2
 
-typedef struct SpaprPhbState SpaprPhbState;
 
 typedef struct SpaprPciMsi {
     uint32_t first_irq;
diff --git a/include/hw/pci-host/uninorth.h b/include/hw/pci-host/uninorth.h
index 72d2a97355..d10c598298 100644
--- a/include/hw/pci-host/uninorth.h
+++ b/include/hw/pci-host/uninorth.h
@@ -27,6 +27,7 @@
 
 #include "hw/pci/pci_host.h"
 #include "hw/ppc/openpic.h"
+#include "qom/object.h"
 
 /* UniNorth version */
 #define UNINORTH_VERSION_10A    0x7
@@ -36,16 +37,17 @@
 #define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost"
 #define TYPE_U3_AGP_HOST_BRIDGE "u3-agp-pcihost"
 
-#define UNI_NORTH_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(UNINHostState, (obj), TYPE_UNI_NORTH_PCI_HOST_BRIDGE)
-#define UNI_NORTH_AGP_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(UNINHostState, (obj), TYPE_UNI_NORTH_AGP_HOST_BRIDGE)
-#define UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(UNINHostState, (obj), TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE)
-#define U3_AGP_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(UNINHostState, (obj), TYPE_U3_AGP_HOST_BRIDGE)
+typedef struct UNINHostState UNINHostState;
+DECLARE_INSTANCE_CHECKER(UNINHostState, UNI_NORTH_PCI_HOST_BRIDGE,
+                         TYPE_UNI_NORTH_PCI_HOST_BRIDGE)
+DECLARE_INSTANCE_CHECKER(UNINHostState, UNI_NORTH_AGP_HOST_BRIDGE,
+                         TYPE_UNI_NORTH_AGP_HOST_BRIDGE)
+DECLARE_INSTANCE_CHECKER(UNINHostState, UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE,
+                         TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE)
+DECLARE_INSTANCE_CHECKER(UNINHostState, U3_AGP_HOST_BRIDGE,
+                         TYPE_U3_AGP_HOST_BRIDGE)
 
-typedef struct UNINHostState {
+struct UNINHostState {
     PCIHostState parent_obj;
 
     uint32_t ofw_addr;
@@ -54,16 +56,17 @@ typedef struct UNINHostState {
     MemoryRegion pci_mmio;
     MemoryRegion pci_hole;
     MemoryRegion pci_io;
-} UNINHostState;
+};
 
-typedef struct UNINState {
+struct UNINState {
     SysBusDevice parent_obj;
 
     MemoryRegion mem;
-} UNINState;
+};
+typedef struct UNINState UNINState;
 
 #define TYPE_UNI_NORTH "uni-north"
-#define UNI_NORTH(obj) \
-    OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH)
+DECLARE_INSTANCE_CHECKER(UNINState, UNI_NORTH,
+                         TYPE_UNI_NORTH)
 
 #endif /* UNINORTH_H */
diff --git a/include/hw/pci-host/xilinx-pcie.h b/include/hw/pci-host/xilinx-pcie.h
index c0f15314be..6058c8c9e2 100644
--- a/include/hw/pci-host/xilinx-pcie.h
+++ b/include/hw/pci-host/xilinx-pcie.h
@@ -24,25 +24,28 @@
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bridge.h"
 #include "hw/pci/pcie_host.h"
+#include "qom/object.h"
 
 #define TYPE_XILINX_PCIE_HOST "xilinx-pcie-host"
-#define XILINX_PCIE_HOST(obj) \
-     OBJECT_CHECK(XilinxPCIEHost, (obj), TYPE_XILINX_PCIE_HOST)
+typedef struct XilinxPCIEHost XilinxPCIEHost;
+DECLARE_INSTANCE_CHECKER(XilinxPCIEHost, XILINX_PCIE_HOST,
+                         TYPE_XILINX_PCIE_HOST)
 
 #define TYPE_XILINX_PCIE_ROOT "xilinx-pcie-root"
-#define XILINX_PCIE_ROOT(obj) \
-     OBJECT_CHECK(XilinxPCIERoot, (obj), TYPE_XILINX_PCIE_ROOT)
+typedef struct XilinxPCIERoot XilinxPCIERoot;
+DECLARE_INSTANCE_CHECKER(XilinxPCIERoot, XILINX_PCIE_ROOT,
+                         TYPE_XILINX_PCIE_ROOT)
 
-typedef struct XilinxPCIERoot {
+struct XilinxPCIERoot {
     PCIBridge parent_obj;
-} XilinxPCIERoot;
+};
 
 typedef struct XilinxPCIEInt {
     uint32_t fifo_reg1;
     uint32_t fifo_reg2;
 } XilinxPCIEInt;
 
-typedef struct XilinxPCIEHost {
+struct XilinxPCIEHost {
     PCIExpressHost parent_obj;
 
     char name[16];
@@ -62,6 +65,6 @@ typedef struct XilinxPCIEHost {
     XilinxPCIEInt intr_fifo[16];
     unsigned int intr_fifo_r, intr_fifo_w;
     uint32_t rpscr;
-} XilinxPCIEHost;
+};
 
 #endif /* HW_XILINX_PCIE_H */
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 4ca7258b5b..c13ae1f858 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -8,6 +8,7 @@
 #include "hw/isa/isa.h"
 
 #include "hw/pci/pcie.h"
+#include "qom/object.h"
 
 extern bool pci_available;
 
@@ -195,12 +196,9 @@ enum {
 };
 
 #define TYPE_PCI_DEVICE "pci-device"
-#define PCI_DEVICE(obj) \
-     OBJECT_CHECK(PCIDevice, (obj), TYPE_PCI_DEVICE)
-#define PCI_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(PCIDeviceClass, (klass), TYPE_PCI_DEVICE)
-#define PCI_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE)
+typedef struct PCIDeviceClass PCIDeviceClass;
+DECLARE_OBJ_CHECKERS(PCIDevice, PCIDeviceClass,
+                     PCI_DEVICE, TYPE_PCI_DEVICE)
 
 /* Implemented by devices that can be plugged on PCI Express buses */
 #define INTERFACE_PCIE_DEVICE "pci-express-device"
@@ -217,7 +215,7 @@ typedef struct PCIINTxRoute {
     int irq;
 } PCIINTxRoute;
 
-typedef struct PCIDeviceClass {
+struct PCIDeviceClass {
     DeviceClass parent_class;
 
     void (*realize)(PCIDevice *dev, Error **errp);
@@ -241,7 +239,7 @@ typedef struct PCIDeviceClass {
 
     /* rom bar */
     const char *romfile;
-} PCIDeviceClass;
+};
 
 typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev);
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
@@ -397,9 +395,8 @@ typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
 
 #define TYPE_PCI_BUS "PCI"
 typedef struct PCIBusClass PCIBusClass;
-#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
-#define PCI_BUS_CLASS(klass) OBJECT_CLASS_CHECK(PCIBusClass, (klass), TYPE_PCI_BUS)
-#define PCI_BUS_GET_CLASS(obj) OBJECT_GET_CLASS(PCIBusClass, (obj), TYPE_PCI_BUS)
+DECLARE_OBJ_CHECKERS(PCIBus, PCIBusClass,
+                     PCI_BUS, TYPE_PCI_BUS)
 #define TYPE_PCIE_BUS "PCIE"
 
 bool pci_bus_is_express(PCIBus *bus);
diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h
index 99c674e949..7ab145955a 100644
--- a/include/hw/pci/pci_bridge.h
+++ b/include/hw/pci/pci_bridge.h
@@ -28,6 +28,7 @@
 
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bus.h"
+#include "qom/object.h"
 
 typedef struct PCIBridgeWindows PCIBridgeWindows;
 
@@ -50,7 +51,8 @@ struct PCIBridgeWindows {
 };
 
 #define TYPE_PCI_BRIDGE "base-pci-bridge"
-#define PCI_BRIDGE(obj) OBJECT_CHECK(PCIBridge, (obj), TYPE_PCI_BRIDGE)
+DECLARE_INSTANCE_CHECKER(PCIBridge, PCI_BRIDGE,
+                         TYPE_PCI_BRIDGE)
 
 struct PCIBridge {
     /*< private >*/
diff --git a/include/hw/pci/pci_host.h b/include/hw/pci/pci_host.h
index 6210a7e14d..d1fc1c3604 100644
--- a/include/hw/pci/pci_host.h
+++ b/include/hw/pci/pci_host.h
@@ -29,14 +29,12 @@
 #define PCI_HOST_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_PCI_HOST_BRIDGE "pci-host-bridge"
-#define PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(PCIHostState, (obj), TYPE_PCI_HOST_BRIDGE)
-#define PCI_HOST_BRIDGE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(PCIHostBridgeClass, (klass), TYPE_PCI_HOST_BRIDGE)
-#define PCI_HOST_BRIDGE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PCIHostBridgeClass, (obj), TYPE_PCI_HOST_BRIDGE)
+typedef struct PCIHostBridgeClass PCIHostBridgeClass;
+DECLARE_OBJ_CHECKERS(PCIHostState, PCIHostBridgeClass,
+                     PCI_HOST_BRIDGE, TYPE_PCI_HOST_BRIDGE)
 
 struct PCIHostState {
     SysBusDevice busdev;
@@ -51,11 +49,11 @@ struct PCIHostState {
     QLIST_ENTRY(PCIHostState) next;
 };
 
-typedef struct PCIHostBridgeClass {
+struct PCIHostBridgeClass {
     SysBusDeviceClass parent_class;
 
     const char *(*root_bus_path)(PCIHostState *, PCIBus *);
-} PCIHostBridgeClass;
+};
 
 /* common internal helpers for PCI/PCIe hosts, cut off overflows */
 void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h
index 3f7b9886d1..f512646c0c 100644
--- a/include/hw/pci/pcie_host.h
+++ b/include/hw/pci/pcie_host.h
@@ -23,10 +23,11 @@
 
 #include "hw/pci/pci_host.h"
 #include "exec/memory.h"
+#include "qom/object.h"
 
 #define TYPE_PCIE_HOST_BRIDGE "pcie-host-bridge"
-#define PCIE_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(PCIExpressHost, (obj), TYPE_PCIE_HOST_BRIDGE)
+DECLARE_INSTANCE_CHECKER(PCIExpressHost, PCIE_HOST_BRIDGE,
+                         TYPE_PCIE_HOST_BRIDGE)
 
 #define PCIE_HOST_MCFG_BASE "MCFG"
 #define PCIE_HOST_MCFG_SIZE "mcfg_size"
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
index caae57573b..2463c07fa7 100644
--- a/include/hw/pci/pcie_port.h
+++ b/include/hw/pci/pcie_port.h
@@ -23,9 +23,11 @@
 
 #include "hw/pci/pci_bridge.h"
 #include "hw/pci/pci_bus.h"
+#include "qom/object.h"
 
 #define TYPE_PCIE_PORT "pcie-port"
-#define PCIE_PORT(obj) OBJECT_CHECK(PCIEPort, (obj), TYPE_PCIE_PORT)
+DECLARE_INSTANCE_CHECKER(PCIEPort, PCIE_PORT,
+                         TYPE_PCIE_PORT)
 
 struct PCIEPort {
     /*< private >*/
@@ -39,7 +41,8 @@ struct PCIEPort {
 void pcie_port_init_reg(PCIDevice *d);
 
 #define TYPE_PCIE_SLOT "pcie-slot"
-#define PCIE_SLOT(obj) OBJECT_CHECK(PCIESlot, (obj), TYPE_PCIE_SLOT)
+DECLARE_INSTANCE_CHECKER(PCIESlot, PCIE_SLOT,
+                         TYPE_PCIE_SLOT)
 
 struct PCIESlot {
     /*< private >*/
@@ -67,12 +70,11 @@ int pcie_chassis_add_slot(struct PCIESlot *slot);
 void pcie_chassis_del_slot(PCIESlot *s);
 
 #define TYPE_PCIE_ROOT_PORT         "pcie-root-port-base"
-#define PCIE_ROOT_PORT_CLASS(klass) \
-     OBJECT_CLASS_CHECK(PCIERootPortClass, (klass), TYPE_PCIE_ROOT_PORT)
-#define PCIE_ROOT_PORT_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PCIERootPortClass, (obj), TYPE_PCIE_ROOT_PORT)
+typedef struct PCIERootPortClass PCIERootPortClass;
+DECLARE_CLASS_CHECKERS(PCIERootPortClass, PCIE_ROOT_PORT,
+                       TYPE_PCIE_ROOT_PORT)
 
-typedef struct PCIERootPortClass {
+struct PCIERootPortClass {
     PCIDeviceClass parent_class;
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
@@ -86,6 +88,6 @@ typedef struct PCIERootPortClass {
     int ssvid_offset;
     int acs_offset;    /* If nonzero, optional ACS capability offset */
     int ssid;
-} PCIERootPortClass;
+};
 
 #endif /* QEMU_PCIE_PORT_H */
diff --git a/include/hw/pcmcia.h b/include/hw/pcmcia.h
index ebad7bc504..fb40ae7e09 100644
--- a/include/hw/pcmcia.h
+++ b/include/hw/pcmcia.h
@@ -4,6 +4,7 @@
 /* PCMCIA/Cardbus */
 
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 typedef struct PCMCIASocket {
     qemu_irq irq;
@@ -11,22 +12,20 @@ typedef struct PCMCIASocket {
 } PCMCIASocket;
 
 #define TYPE_PCMCIA_CARD "pcmcia-card"
-#define PCMCIA_CARD(obj) \
-    OBJECT_CHECK(PCMCIACardState, (obj), TYPE_PCMCIA_CARD)
-#define PCMCIA_CARD_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(PCMCIACardClass, obj, TYPE_PCMCIA_CARD)
-#define PCMCIA_CARD_CLASS(cls) \
-    OBJECT_CLASS_CHECK(PCMCIACardClass, cls, TYPE_PCMCIA_CARD)
+typedef struct PCMCIACardClass PCMCIACardClass;
+typedef struct PCMCIACardState PCMCIACardState;
+DECLARE_OBJ_CHECKERS(PCMCIACardState, PCMCIACardClass,
+                     PCMCIA_CARD, TYPE_PCMCIA_CARD)
 
-typedef struct PCMCIACardState {
+struct PCMCIACardState {
     /*< private >*/
     DeviceState parent_obj;
     /*< public >*/
 
     PCMCIASocket *slot;
-} PCMCIACardState;
+};
 
-typedef struct PCMCIACardClass {
+struct PCMCIACardClass {
     /*< private >*/
     DeviceClass parent_class;
     /*< public >*/
@@ -45,7 +44,7 @@ typedef struct PCMCIACardClass {
                          uint32_t address, uint16_t value);
     uint16_t (*io_read)(PCMCIACardState *card, uint32_t address);
     void (*io_write)(PCMCIACardState *card, uint32_t address, uint16_t value);
-} PCMCIACardClass;
+};
 
 #define CISTPL_DEVICE		0x01	/* 5V Device Information Tuple */
 #define CISTPL_NO_LINK		0x14	/* No Link Tuple */
diff --git a/include/hw/platform-bus.h b/include/hw/platform-bus.h
index 33745a418e..0d035e1b71 100644
--- a/include/hw/platform-bus.h
+++ b/include/hw/platform-bus.h
@@ -23,12 +23,13 @@
  */
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 typedef struct PlatformBusDevice PlatformBusDevice;
 
 #define TYPE_PLATFORM_BUS_DEVICE "platform-bus-device"
-#define PLATFORM_BUS_DEVICE(obj) \
-     OBJECT_CHECK(PlatformBusDevice, (obj), TYPE_PLATFORM_BUS_DEVICE)
+DECLARE_INSTANCE_CHECKER(PlatformBusDevice, PLATFORM_BUS_DEVICE,
+                         TYPE_PLATFORM_BUS_DEVICE)
 
 struct PlatformBusDevice {
     /*< private >*/
diff --git a/include/hw/ppc/mac_dbdma.h b/include/hw/ppc/mac_dbdma.h
index 26cc469de4..9166d5f758 100644
--- a/include/hw/ppc/mac_dbdma.h
+++ b/include/hw/ppc/mac_dbdma.h
@@ -27,6 +27,7 @@
 #include "qemu/iov.h"
 #include "sysemu/dma.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 typedef struct DBDMA_io DBDMA_io;
 
@@ -160,13 +161,14 @@ typedef struct DBDMA_channel {
     dbdma_cmd current;
 } DBDMA_channel;
 
-typedef struct {
+struct DBDMAState {
     SysBusDevice parent_obj;
 
     MemoryRegion mem;
     DBDMA_channel channels[DBDMA_CHANNELS];
     QEMUBH *bh;
-} DBDMAState;
+};
+typedef struct DBDMAState DBDMAState;
 
 /* Externally callable functions */
 
@@ -176,6 +178,7 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
 void DBDMA_kick(DBDMAState *dbdma);
 
 #define TYPE_MAC_DBDMA "mac-dbdma"
-#define MAC_DBDMA(obj) OBJECT_CHECK(DBDMAState, (obj), TYPE_MAC_DBDMA)
+DECLARE_INSTANCE_CHECKER(DBDMAState, MAC_DBDMA,
+                         TYPE_MAC_DBDMA)
 
 #endif
diff --git a/include/hw/ppc/openpic.h b/include/hw/ppc/openpic.h
index db0d29e6c2..61908c7858 100644
--- a/include/hw/ppc/openpic.h
+++ b/include/hw/ppc/openpic.h
@@ -3,6 +3,7 @@
 
 #include "hw/sysbus.h"
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #define MAX_CPU     32
 #define MAX_MSI     8
@@ -136,9 +137,11 @@ typedef struct IRQDest {
 } IRQDest;
 
 #define TYPE_OPENPIC "openpic"
-#define OPENPIC(obj) OBJECT_CHECK(OpenPICState, (obj), TYPE_OPENPIC)
+typedef struct OpenPICState OpenPICState;
+DECLARE_INSTANCE_CHECKER(OpenPICState, OPENPIC,
+                         TYPE_OPENPIC)
 
-typedef struct OpenPICState {
+struct OpenPICState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -183,6 +186,6 @@ typedef struct OpenPICState {
     uint32_t irq_ipi0;
     uint32_t irq_tim0;
     uint32_t irq_msi;
-} OpenPICState;
+};
 
 #endif /* OPENPIC_H */
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index d4b0b0e2ff..b4b2b24d80 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -32,15 +32,13 @@
 #include "hw/ppc/pnv_core.h"
 #include "hw/pci-host/pnv_phb3.h"
 #include "hw/pci-host/pnv_phb4.h"
+#include "qom/object.h"
 
 #define TYPE_PNV_CHIP "pnv-chip"
-#define PNV_CHIP(obj) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP)
-#define PNV_CHIP_CLASS(klass) \
-     OBJECT_CLASS_CHECK(PnvChipClass, (klass), TYPE_PNV_CHIP)
-#define PNV_CHIP_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PnvChipClass, (obj), TYPE_PNV_CHIP)
+OBJECT_DECLARE_TYPE(PnvChip, PnvChipClass,
+                    pnv_chip, PNV_CHIP)
 
-typedef struct PnvChip {
+struct PnvChip {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -61,12 +59,14 @@ typedef struct PnvChip {
     AddressSpace xscom_as;
 
     gchar        *dt_isa_nodename;
-} PnvChip;
+};
 
 #define TYPE_PNV8_CHIP "pnv8-chip"
-#define PNV8_CHIP(obj) OBJECT_CHECK(Pnv8Chip, (obj), TYPE_PNV8_CHIP)
+typedef struct Pnv8Chip Pnv8Chip;
+DECLARE_INSTANCE_CHECKER(Pnv8Chip, PNV8_CHIP,
+                         TYPE_PNV8_CHIP)
 
-typedef struct Pnv8Chip {
+struct Pnv8Chip {
     /*< private >*/
     PnvChip      parent_obj;
 
@@ -82,12 +82,14 @@ typedef struct Pnv8Chip {
     PnvPHB3      phbs[PNV8_CHIP_PHB3_MAX];
 
     XICSFabric    *xics;
-} Pnv8Chip;
+};
 
 #define TYPE_PNV9_CHIP "pnv9-chip"
-#define PNV9_CHIP(obj) OBJECT_CHECK(Pnv9Chip, (obj), TYPE_PNV9_CHIP)
+typedef struct Pnv9Chip Pnv9Chip;
+DECLARE_INSTANCE_CHECKER(Pnv9Chip, PNV9_CHIP,
+                         TYPE_PNV9_CHIP)
 
-typedef struct Pnv9Chip {
+struct Pnv9Chip {
     /*< private >*/
     PnvChip      parent_obj;
 
@@ -103,7 +105,7 @@ typedef struct Pnv9Chip {
 
 #define PNV9_CHIP_MAX_PEC 3
     PnvPhb4PecState pecs[PNV9_CHIP_MAX_PEC];
-} Pnv9Chip;
+};
 
 /*
  * A SMT8 fused core is a pair of SMT4 cores.
@@ -112,18 +114,20 @@ typedef struct Pnv9Chip {
 #define PNV9_PIR2CHIP(pir)      (((pir) >> 8) & 0x7f)
 
 #define TYPE_PNV10_CHIP "pnv10-chip"
-#define PNV10_CHIP(obj) OBJECT_CHECK(Pnv10Chip, (obj), TYPE_PNV10_CHIP)
+typedef struct Pnv10Chip Pnv10Chip;
+DECLARE_INSTANCE_CHECKER(Pnv10Chip, PNV10_CHIP,
+                         TYPE_PNV10_CHIP)
 
-typedef struct Pnv10Chip {
+struct Pnv10Chip {
     /*< private >*/
     PnvChip      parent_obj;
 
     /*< public >*/
     Pnv9Psi      psi;
     PnvLpcController lpc;
-} Pnv10Chip;
+};
 
-typedef struct PnvChipClass {
+struct PnvChipClass {
     /*< private >*/
     SysBusDeviceClass parent_class;
 
@@ -144,30 +148,30 @@ typedef struct PnvChipClass {
     void (*pic_print_info)(PnvChip *chip, Monitor *mon);
     uint64_t (*xscom_core_base)(PnvChip *chip, uint32_t core_id);
     uint32_t (*xscom_pcba)(PnvChip *chip, uint64_t addr);
-} PnvChipClass;
+};
 
 #define PNV_CHIP_TYPE_SUFFIX "-" TYPE_PNV_CHIP
 #define PNV_CHIP_TYPE_NAME(cpu_model) cpu_model PNV_CHIP_TYPE_SUFFIX
 
 #define TYPE_PNV_CHIP_POWER8E PNV_CHIP_TYPE_NAME("power8e_v2.1")
-#define PNV_CHIP_POWER8E(obj) \
-    OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8E)
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8E,
+                         TYPE_PNV_CHIP_POWER8E)
 
 #define TYPE_PNV_CHIP_POWER8 PNV_CHIP_TYPE_NAME("power8_v2.0")
-#define PNV_CHIP_POWER8(obj) \
-    OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8)
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8,
+                         TYPE_PNV_CHIP_POWER8)
 
 #define TYPE_PNV_CHIP_POWER8NVL PNV_CHIP_TYPE_NAME("power8nvl_v1.0")
-#define PNV_CHIP_POWER8NVL(obj) \
-    OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8NVL)
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8NVL,
+                         TYPE_PNV_CHIP_POWER8NVL)
 
 #define TYPE_PNV_CHIP_POWER9 PNV_CHIP_TYPE_NAME("power9_v2.0")
-#define PNV_CHIP_POWER9(obj) \
-    OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER9)
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER9,
+                         TYPE_PNV_CHIP_POWER9)
 
 #define TYPE_PNV_CHIP_POWER10 PNV_CHIP_TYPE_NAME("power10_v1.0")
-#define PNV_CHIP_POWER10(obj) \
-    OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER10)
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10,
+                         TYPE_PNV_CHIP_POWER10)
 
 /*
  * This generates a HW chip id depending on an index, as found on a
@@ -191,16 +195,13 @@ typedef struct PnvChipClass {
 PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir);
 
 #define TYPE_PNV_MACHINE       MACHINE_TYPE_NAME("powernv")
-#define PNV_MACHINE(obj) \
-    OBJECT_CHECK(PnvMachineState, (obj), TYPE_PNV_MACHINE)
-#define PNV_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(PnvMachineClass, obj, TYPE_PNV_MACHINE)
-#define PNV_MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(PnvMachineClass, klass, TYPE_PNV_MACHINE)
-
+typedef struct PnvMachineClass PnvMachineClass;
 typedef struct PnvMachineState PnvMachineState;
+DECLARE_OBJ_CHECKERS(PnvMachineState, PnvMachineClass,
+                     PNV_MACHINE, TYPE_PNV_MACHINE)
 
-typedef struct PnvMachineClass {
+
+struct PnvMachineClass {
     /*< private >*/
     MachineClass parent_class;
 
@@ -209,7 +210,7 @@ typedef struct PnvMachineClass {
     int compat_size;
 
     void (*dt_power_mgt)(PnvMachineState *pnv, void *fdt);
-} PnvMachineClass;
+};
 
 struct PnvMachineState {
     /*< private >*/
diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index 113550eb7f..5cb22c2fa9 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -22,18 +22,15 @@
 
 #include "hw/cpu/core.h"
 #include "target/ppc/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_PNV_CORE "powernv-cpu-core"
-#define PNV_CORE(obj) \
-    OBJECT_CHECK(PnvCore, (obj), TYPE_PNV_CORE)
-#define PNV_CORE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(PnvCoreClass, (klass), TYPE_PNV_CORE)
-#define PNV_CORE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PnvCoreClass, (obj), TYPE_PNV_CORE)
+OBJECT_DECLARE_TYPE(PnvCore, PnvCoreClass,
+                    pnv_core, PNV_CORE)
 
 typedef struct PnvChip PnvChip;
 
-typedef struct PnvCore {
+struct PnvCore {
     /*< private >*/
     CPUCore parent_obj;
 
@@ -44,13 +41,13 @@ typedef struct PnvCore {
     PnvChip *chip;
 
     MemoryRegion xscom_regs;
-} PnvCore;
+};
 
-typedef struct PnvCoreClass {
+struct PnvCoreClass {
     DeviceClass parent_class;
 
     const MemoryRegionOps *xscom_ops;
-} PnvCoreClass;
+};
 
 #define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE
 #define PNV_CORE_TYPE_NAME(cpu_model) cpu_model PNV_CORE_TYPE_SUFFIX
@@ -65,13 +62,14 @@ static inline PnvCPUState *pnv_cpu_state(PowerPCCPU *cpu)
 }
 
 #define TYPE_PNV_QUAD "powernv-cpu-quad"
-#define PNV_QUAD(obj) \
-    OBJECT_CHECK(PnvQuad, (obj), TYPE_PNV_QUAD)
+typedef struct PnvQuad PnvQuad;
+DECLARE_INSTANCE_CHECKER(PnvQuad, PNV_QUAD,
+                         TYPE_PNV_QUAD)
 
-typedef struct PnvQuad {
+struct PnvQuad {
     DeviceState parent_obj;
 
     uint32_t id;
     MemoryRegion xscom_regs;
-} PnvQuad;
+};
 #endif /* PPC_PNV_CORE_H */
diff --git a/include/hw/ppc/pnv_homer.h b/include/hw/ppc/pnv_homer.h
index 1e91c950f6..0978812713 100644
--- a/include/hw/ppc/pnv_homer.h
+++ b/include/hw/ppc/pnv_homer.h
@@ -21,28 +21,28 @@
 #define PPC_PNV_HOMER_H
 
 #include "hw/ppc/pnv.h"
+#include "qom/object.h"
 
 #define TYPE_PNV_HOMER "pnv-homer"
-#define PNV_HOMER(obj) OBJECT_CHECK(PnvHomer, (obj), TYPE_PNV_HOMER)
+OBJECT_DECLARE_TYPE(PnvHomer, PnvHomerClass,
+                    pnv_homer, PNV_HOMER)
 #define TYPE_PNV8_HOMER TYPE_PNV_HOMER "-POWER8"
-#define PNV8_HOMER(obj) OBJECT_CHECK(PnvHomer, (obj), TYPE_PNV8_HOMER)
+DECLARE_INSTANCE_CHECKER(PnvHomer, PNV8_HOMER,
+                         TYPE_PNV8_HOMER)
 #define TYPE_PNV9_HOMER TYPE_PNV_HOMER "-POWER9"
-#define PNV9_HOMER(obj) OBJECT_CHECK(PnvHomer, (obj), TYPE_PNV9_HOMER)
+DECLARE_INSTANCE_CHECKER(PnvHomer, PNV9_HOMER,
+                         TYPE_PNV9_HOMER)
 
-typedef struct PnvHomer {
+struct PnvHomer {
     DeviceState parent;
 
     struct PnvChip *chip;
     MemoryRegion pba_regs;
     MemoryRegion regs;
-} PnvHomer;
+};
 
-#define PNV_HOMER_CLASS(klass)   \
-     OBJECT_CLASS_CHECK(PnvHomerClass, (klass), TYPE_PNV_HOMER)
-#define PNV_HOMER_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PnvHomerClass, (obj), TYPE_PNV_HOMER)
 
-typedef struct PnvHomerClass {
+struct PnvHomerClass {
     DeviceClass parent_class;
 
     int pba_size;
@@ -51,6 +51,6 @@ typedef struct PnvHomerClass {
     const MemoryRegionOps *homer_ops;
 
     hwaddr core_max_base;
-} PnvHomerClass;
+};
 
 #endif /* PPC_PNV_HOMER_H */
diff --git a/include/hw/ppc/pnv_lpc.h b/include/hw/ppc/pnv_lpc.h
index c1ec85d5e2..cd3c13c2a8 100644
--- a/include/hw/ppc/pnv_lpc.h
+++ b/include/hw/ppc/pnv_lpc.h
@@ -21,20 +21,26 @@
 #define PPC_PNV_LPC_H
 
 #include "hw/ppc/pnv_psi.h"
+#include "qom/object.h"
 
 #define TYPE_PNV_LPC "pnv-lpc"
-#define PNV_LPC(obj) \
-     OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV_LPC)
+typedef struct PnvLpcClass PnvLpcClass;
+typedef struct PnvLpcController PnvLpcController;
+DECLARE_OBJ_CHECKERS(PnvLpcController, PnvLpcClass,
+                     PNV_LPC, TYPE_PNV_LPC)
 #define TYPE_PNV8_LPC TYPE_PNV_LPC "-POWER8"
-#define PNV8_LPC(obj) OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV8_LPC)
+DECLARE_INSTANCE_CHECKER(PnvLpcController, PNV8_LPC,
+                         TYPE_PNV8_LPC)
 
 #define TYPE_PNV9_LPC TYPE_PNV_LPC "-POWER9"
-#define PNV9_LPC(obj) OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV9_LPC)
+DECLARE_INSTANCE_CHECKER(PnvLpcController, PNV9_LPC,
+                         TYPE_PNV9_LPC)
 
 #define TYPE_PNV10_LPC TYPE_PNV_LPC "-POWER10"
-#define PNV10_LPC(obj) OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV10_LPC)
+DECLARE_INSTANCE_CHECKER(PnvLpcController, PNV10_LPC,
+                         TYPE_PNV10_LPC)
 
-typedef struct PnvLpcController {
+struct PnvLpcController {
     DeviceState parent;
 
     uint64_t eccb_stat_reg;
@@ -79,20 +85,16 @@ typedef struct PnvLpcController {
 
     /* PSI to generate interrupts */
     PnvPsi *psi;
-} PnvLpcController;
+};
 
-#define PNV_LPC_CLASS(klass) \
-     OBJECT_CLASS_CHECK(PnvLpcClass, (klass), TYPE_PNV_LPC)
-#define PNV_LPC_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PnvLpcClass, (obj), TYPE_PNV_LPC)
 
-typedef struct PnvLpcClass {
+struct PnvLpcClass {
     DeviceClass parent_class;
 
     int psi_irq;
 
     DeviceRealize parent_realize;
-} PnvLpcClass;
+};
 
 /*
  * Old compilers error on typdef forward declarations. Keep them happy.
diff --git a/include/hw/ppc/pnv_occ.h b/include/hw/ppc/pnv_occ.h
index f8d3061419..b79e3440be 100644
--- a/include/hw/ppc/pnv_occ.h
+++ b/include/hw/ppc/pnv_occ.h
@@ -21,18 +21,22 @@
 #define PPC_PNV_OCC_H
 
 #include "hw/ppc/pnv_psi.h"
+#include "qom/object.h"
 
 #define TYPE_PNV_OCC "pnv-occ"
-#define PNV_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV_OCC)
+OBJECT_DECLARE_TYPE(PnvOCC, PnvOCCClass,
+                    pnv_occ, PNV_OCC)
 #define TYPE_PNV8_OCC TYPE_PNV_OCC "-POWER8"
-#define PNV8_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV8_OCC)
+DECLARE_INSTANCE_CHECKER(PnvOCC, PNV8_OCC,
+                         TYPE_PNV8_OCC)
 #define TYPE_PNV9_OCC TYPE_PNV_OCC "-POWER9"
-#define PNV9_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV9_OCC)
+DECLARE_INSTANCE_CHECKER(PnvOCC, PNV9_OCC,
+                         TYPE_PNV9_OCC)
 
 #define PNV_OCC_SENSOR_DATA_BLOCK_OFFSET 0x00580000
 #define PNV_OCC_SENSOR_DATA_BLOCK_SIZE   0x00025800
 
-typedef struct PnvOCC {
+struct PnvOCC {
     DeviceState xd;
 
     /* OCC Misc interrupt */
@@ -42,20 +46,16 @@ typedef struct PnvOCC {
 
     MemoryRegion xscom_regs;
     MemoryRegion sram_regs;
-} PnvOCC;
+};
 
-#define PNV_OCC_CLASS(klass) \
-     OBJECT_CLASS_CHECK(PnvOCCClass, (klass), TYPE_PNV_OCC)
-#define PNV_OCC_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PnvOCCClass, (obj), TYPE_PNV_OCC)
 
-typedef struct PnvOCCClass {
+struct PnvOCCClass {
     DeviceClass parent_class;
 
     int xscom_size;
     const MemoryRegionOps *xscom_ops;
     int psi_irq;
-} PnvOCCClass;
+};
 
 #define PNV_OCC_SENSOR_DATA_BLOCK_BASE(i)                               \
     (PNV_OCC_SENSOR_DATA_BLOCK_OFFSET + (i) * PNV_OCC_SENSOR_DATA_BLOCK_SIZE)
diff --git a/include/hw/ppc/pnv_pnor.h b/include/hw/ppc/pnv_pnor.h
index 4f96abdfb4..1ec4098bb9 100644
--- a/include/hw/ppc/pnv_pnor.h
+++ b/include/hw/ppc/pnv_pnor.h
@@ -8,6 +8,7 @@
  */
 #ifndef _PPC_PNV_PNOR_H
 #define _PPC_PNV_PNOR_H
+#include "qom/object.h"
 
 /*
  * PNOR offset on the LPC FW address space
@@ -15,9 +16,11 @@
 #define PNOR_SPI_OFFSET         0x0c000000UL
 
 #define TYPE_PNV_PNOR  "pnv-pnor"
-#define PNV_PNOR(obj)  OBJECT_CHECK(PnvPnor, (obj), TYPE_PNV_PNOR)
+typedef struct PnvPnor PnvPnor;
+DECLARE_INSTANCE_CHECKER(PnvPnor, PNV_PNOR,
+                         TYPE_PNV_PNOR)
 
-typedef struct PnvPnor {
+struct PnvPnor {
     SysBusDevice   parent_obj;
 
     BlockBackend   *blk;
@@ -25,6 +28,6 @@ typedef struct PnvPnor {
     uint8_t        *storage;
     int64_t        size;
     MemoryRegion   mmio;
-} PnvPnor;
+};
 
 #endif /* _PPC_PNV_PNOR_H */
diff --git a/include/hw/ppc/pnv_psi.h b/include/hw/ppc/pnv_psi.h
index 979fc59f33..0034db44c3 100644
--- a/include/hw/ppc/pnv_psi.h
+++ b/include/hw/ppc/pnv_psi.h
@@ -23,14 +23,15 @@
 #include "hw/sysbus.h"
 #include "hw/ppc/xics.h"
 #include "hw/ppc/xive.h"
+#include "qom/object.h"
 
 #define TYPE_PNV_PSI "pnv-psi"
-#define PNV_PSI(obj) \
-     OBJECT_CHECK(PnvPsi, (obj), TYPE_PNV_PSI)
+OBJECT_DECLARE_TYPE(PnvPsi, PnvPsiClass,
+                    pnv_psi, PNV_PSI)
 
 #define PSIHB_XSCOM_MAX         0x20
 
-typedef struct PnvPsi {
+struct PnvPsi {
     DeviceState parent;
 
     MemoryRegion regs_mr;
@@ -47,36 +48,34 @@ typedef struct PnvPsi {
     uint64_t regs[PSIHB_XSCOM_MAX];
 
     MemoryRegion xscom_regs;
-} PnvPsi;
+};
 
 #define TYPE_PNV8_PSI TYPE_PNV_PSI "-POWER8"
-#define PNV8_PSI(obj) \
-    OBJECT_CHECK(Pnv8Psi, (obj), TYPE_PNV8_PSI)
+typedef struct Pnv8Psi Pnv8Psi;
+DECLARE_INSTANCE_CHECKER(Pnv8Psi, PNV8_PSI,
+                         TYPE_PNV8_PSI)
 
-typedef struct Pnv8Psi {
+struct Pnv8Psi {
     PnvPsi   parent;
 
     ICSState ics;
-} Pnv8Psi;
+};
 
 #define TYPE_PNV9_PSI TYPE_PNV_PSI "-POWER9"
-#define PNV9_PSI(obj) \
-    OBJECT_CHECK(Pnv9Psi, (obj), TYPE_PNV9_PSI)
+typedef struct Pnv9Psi Pnv9Psi;
+DECLARE_INSTANCE_CHECKER(Pnv9Psi, PNV9_PSI,
+                         TYPE_PNV9_PSI)
 
-typedef struct Pnv9Psi {
+struct Pnv9Psi {
     PnvPsi   parent;
 
     XiveSource source;
-} Pnv9Psi;
+};
 
 #define TYPE_PNV10_PSI TYPE_PNV_PSI "-POWER10"
 
-#define PNV_PSI_CLASS(klass) \
-     OBJECT_CLASS_CHECK(PnvPsiClass, (klass), TYPE_PNV_PSI)
-#define PNV_PSI_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PnvPsiClass, (obj), TYPE_PNV_PSI)
 
-typedef struct PnvPsiClass {
+struct PnvPsiClass {
     SysBusDeviceClass parent_class;
 
     uint32_t xscom_pcba;
@@ -86,7 +85,7 @@ typedef struct PnvPsiClass {
     int compat_size;
 
     void (*irq_set)(PnvPsi *psi, int, bool state);
-} PnvPsiClass;
+};
 
 /* The PSI and FSP interrupts are muxed on the same IRQ number */
 typedef enum PnvPsiIrq {
diff --git a/include/hw/ppc/pnv_xive.h b/include/hw/ppc/pnv_xive.h
index 76cf16f644..29d5debd1c 100644
--- a/include/hw/ppc/pnv_xive.h
+++ b/include/hw/ppc/pnv_xive.h
@@ -11,15 +11,13 @@
 #define PPC_PNV_XIVE_H
 
 #include "hw/ppc/xive.h"
+#include "qom/object.h"
 
 struct PnvChip;
 
 #define TYPE_PNV_XIVE "pnv-xive"
-#define PNV_XIVE(obj) OBJECT_CHECK(PnvXive, (obj), TYPE_PNV_XIVE)
-#define PNV_XIVE_CLASS(klass)                                   \
-    OBJECT_CLASS_CHECK(PnvXiveClass, (klass), TYPE_PNV_XIVE)
-#define PNV_XIVE_GET_CLASS(obj)                                 \
-    OBJECT_GET_CLASS(PnvXiveClass, (obj), TYPE_PNV_XIVE)
+OBJECT_DECLARE_TYPE(PnvXive, PnvXiveClass,
+                    pnv_xive, PNV_XIVE)
 
 #define XIVE_BLOCK_MAX      16
 
@@ -28,7 +26,7 @@ struct PnvChip;
 #define XIVE_TABLE_VDT_MAX  16  /* VDT Domain Table (0-15) */
 #define XIVE_TABLE_EDT_MAX  64  /* EDT Domain Table (0-63) */
 
-typedef struct PnvXive {
+struct PnvXive {
     XiveRouter    parent_obj;
 
     /* Owning chip */
@@ -87,13 +85,13 @@ typedef struct PnvXive {
     uint64_t      mig[XIVE_TABLE_MIG_MAX];
     uint64_t      vdt[XIVE_TABLE_VDT_MAX];
     uint64_t      edt[XIVE_TABLE_EDT_MAX];
-} PnvXive;
+};
 
-typedef struct PnvXiveClass {
+struct PnvXiveClass {
     XiveRouterClass parent_class;
 
     DeviceRealize parent_realize;
-} PnvXiveClass;
+};
 
 void pnv_xive_pic_print_info(PnvXive *xive, Monitor *mon);
 
diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h
index 09156a5a7a..7e3b189c07 100644
--- a/include/hw/ppc/pnv_xscom.h
+++ b/include/hw/ppc/pnv_xscom.h
@@ -27,16 +27,14 @@ typedef struct PnvXScomInterface PnvXScomInterface;
 #define TYPE_PNV_XSCOM_INTERFACE "pnv-xscom-interface"
 #define PNV_XSCOM_INTERFACE(obj) \
     INTERFACE_CHECK(PnvXScomInterface, (obj), TYPE_PNV_XSCOM_INTERFACE)
-#define PNV_XSCOM_INTERFACE_CLASS(klass)                \
-    OBJECT_CLASS_CHECK(PnvXScomInterfaceClass, (klass), \
+typedef struct PnvXScomInterfaceClass PnvXScomInterfaceClass;
+DECLARE_CLASS_CHECKERS(PnvXScomInterfaceClass, PNV_XSCOM_INTERFACE,
                        TYPE_PNV_XSCOM_INTERFACE)
-#define PNV_XSCOM_INTERFACE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PnvXScomInterfaceClass, (obj), TYPE_PNV_XSCOM_INTERFACE)
 
-typedef struct PnvXScomInterfaceClass {
+struct PnvXScomInterfaceClass {
     InterfaceClass parent;
     int (*dt_xscom)(PnvXScomInterface *dev, void *fdt, int offset);
-} PnvXScomInterfaceClass;
+};
 
 /*
  * Layout of the XSCOM PCB addresses of EX core 1 (POWER 8)
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index e50a2672e3..c8cd63bc06 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -8,6 +8,7 @@
 #include "hw/mem/pc-dimm.h"
 #include "hw/ppc/spapr_ovec.h"
 #include "hw/ppc/spapr_irq.h"
+#include "qom/object.h"
 #include "hw/ppc/spapr_xive.h"  /* For SpaprXive */
 #include "hw/ppc/xics.h"        /* For ICSState */
 #include "hw/ppc/spapr_tpm_proxy.h"
@@ -27,10 +28,10 @@ typedef struct SpaprPendingHpt SpaprPendingHpt;
 
 #define TYPE_SPAPR_RTC "spapr-rtc"
 
-#define SPAPR_RTC(obj)                                  \
-    OBJECT_CHECK(SpaprRtcState, (obj), TYPE_SPAPR_RTC)
-
 typedef struct SpaprRtcState SpaprRtcState;
+DECLARE_INSTANCE_CHECKER(SpaprRtcState, SPAPR_RTC,
+                         TYPE_SPAPR_RTC)
+
 struct SpaprRtcState {
     /*< private >*/
     DeviceState parent_obj;
@@ -42,12 +43,8 @@ typedef struct SpaprMachineClass SpaprMachineClass;
 
 #define TYPE_SPAPR_MACHINE      "spapr-machine"
 typedef struct SpaprMachineState SpaprMachineState;
-#define SPAPR_MACHINE(obj) \
-    OBJECT_CHECK(SpaprMachineState, (obj), TYPE_SPAPR_MACHINE)
-#define SPAPR_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(SpaprMachineClass, obj, TYPE_SPAPR_MACHINE)
-#define SPAPR_MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(SpaprMachineClass, klass, TYPE_SPAPR_MACHINE)
+DECLARE_OBJ_CHECKERS(SpaprMachineState, SpaprMachineClass,
+                     SPAPR_MACHINE, TYPE_SPAPR_MACHINE)
 
 typedef enum {
     SPAPR_RESIZE_HPT_DEFAULT = 0,
@@ -790,12 +787,12 @@ static inline void spapr_dt_irq(uint32_t *intspec, int irq, bool is_lsi)
 typedef struct SpaprTceTable SpaprTceTable;
 
 #define TYPE_SPAPR_TCE_TABLE "spapr-tce-table"
-#define SPAPR_TCE_TABLE(obj) \
-    OBJECT_CHECK(SpaprTceTable, (obj), TYPE_SPAPR_TCE_TABLE)
+DECLARE_INSTANCE_CHECKER(SpaprTceTable, SPAPR_TCE_TABLE,
+                         TYPE_SPAPR_TCE_TABLE)
 
 #define TYPE_SPAPR_IOMMU_MEMORY_REGION "spapr-iommu-memory-region"
-#define SPAPR_IOMMU_MEMORY_REGION(obj) \
-        OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_SPAPR_IOMMU_MEMORY_REGION)
+DECLARE_INSTANCE_CHECKER(IOMMUMemoryRegion, SPAPR_IOMMU_MEMORY_REGION,
+                         TYPE_SPAPR_IOMMU_MEMORY_REGION)
 
 struct SpaprTceTable {
     DeviceState parent;
diff --git a/include/hw/ppc/spapr_cpu_core.h b/include/hw/ppc/spapr_cpu_core.h
index 7aed8f555b..4022917168 100644
--- a/include/hw/ppc/spapr_cpu_core.h
+++ b/include/hw/ppc/spapr_cpu_core.h
@@ -13,18 +13,15 @@
 #include "hw/qdev-core.h"
 #include "target/ppc/cpu-qom.h"
 #include "target/ppc/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_SPAPR_CPU_CORE "spapr-cpu-core"
-#define SPAPR_CPU_CORE(obj) \
-    OBJECT_CHECK(SpaprCpuCore, (obj), TYPE_SPAPR_CPU_CORE)
-#define SPAPR_CPU_CORE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(SpaprCpuCoreClass, (klass), TYPE_SPAPR_CPU_CORE)
-#define SPAPR_CPU_CORE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(SpaprCpuCoreClass, (obj), TYPE_SPAPR_CPU_CORE)
+OBJECT_DECLARE_TYPE(SpaprCpuCore, SpaprCpuCoreClass,
+                    spapr_cpu_core, SPAPR_CPU_CORE)
 
 #define SPAPR_CPU_CORE_TYPE_NAME(model) model "-" TYPE_SPAPR_CPU_CORE
 
-typedef struct SpaprCpuCore {
+struct SpaprCpuCore {
     /*< private >*/
     CPUCore parent_obj;
 
@@ -32,12 +29,12 @@ typedef struct SpaprCpuCore {
     PowerPCCPU **threads;
     int node_id;
     bool pre_3_0_migration; /* older machine don't know about SpaprCpuState */
-} SpaprCpuCore;
+};
 
-typedef struct SpaprCpuCoreClass {
+struct SpaprCpuCoreClass {
     DeviceClass parent_class;
     const char *cpu_type;
-} SpaprCpuCoreClass;
+};
 
 const char *spapr_get_cpu_core_type(const char *cpu_type);
 void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip,
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index b161ccebc2..c22a72c9e2 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -11,6 +11,7 @@
 #define HW_SPAPR_IRQ_H
 
 #include "target/ppc/cpu-qom.h"
+#include "qom/object.h"
 
 /*
  * IRQ range offsets per device type
@@ -35,12 +36,11 @@ typedef struct SpaprInterruptController SpaprInterruptController;
 #define TYPE_SPAPR_INTC "spapr-interrupt-controller"
 #define SPAPR_INTC(obj)                                     \
     INTERFACE_CHECK(SpaprInterruptController, (obj), TYPE_SPAPR_INTC)
-#define SPAPR_INTC_CLASS(klass)                                     \
-    OBJECT_CLASS_CHECK(SpaprInterruptControllerClass, (klass), TYPE_SPAPR_INTC)
-#define SPAPR_INTC_GET_CLASS(obj)                                   \
-    OBJECT_GET_CLASS(SpaprInterruptControllerClass, (obj), TYPE_SPAPR_INTC)
+typedef struct SpaprInterruptControllerClass SpaprInterruptControllerClass;
+DECLARE_CLASS_CHECKERS(SpaprInterruptControllerClass, SPAPR_INTC,
+                       TYPE_SPAPR_INTC)
 
-typedef struct SpaprInterruptControllerClass {
+struct SpaprInterruptControllerClass {
     InterfaceClass parent;
 
     int (*activate)(SpaprInterruptController *intc, uint32_t nr_servers,
@@ -65,7 +65,7 @@ typedef struct SpaprInterruptControllerClass {
     void (*dt)(SpaprInterruptController *intc, uint32_t nr_servers,
                void *fdt, uint32_t phandle);
     int (*post_load)(SpaprInterruptController *intc, int version_id);
-} SpaprInterruptControllerClass;
+};
 
 void spapr_irq_update_active_intc(struct SpaprMachineState *spapr);
 
diff --git a/include/hw/ppc/spapr_tpm_proxy.h b/include/hw/ppc/spapr_tpm_proxy.h
index c574e22ba4..300c81b1f0 100644
--- a/include/hw/ppc/spapr_tpm_proxy.h
+++ b/include/hw/ppc/spapr_tpm_proxy.h
@@ -17,15 +17,16 @@
 #include "hw/qdev-core.h"
 
 #define TYPE_SPAPR_TPM_PROXY "spapr-tpm-proxy"
-#define SPAPR_TPM_PROXY(obj) OBJECT_CHECK(SpaprTpmProxy, (obj), \
-                                          TYPE_SPAPR_TPM_PROXY)
+typedef struct SpaprTpmProxy SpaprTpmProxy;
+DECLARE_INSTANCE_CHECKER(SpaprTpmProxy, SPAPR_TPM_PROXY,
+                         TYPE_SPAPR_TPM_PROXY)
 
-typedef struct SpaprTpmProxy {
+struct SpaprTpmProxy {
     /*< private >*/
     DeviceState parent;
 
     char *host_path;
     int host_fd;
-} SpaprTpmProxy;
+};
 
 #endif /* HW_SPAPR_TPM_PROXY_H */
diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
index bed7df60e3..6c40da72ff 100644
--- a/include/hw/ppc/spapr_vio.h
+++ b/include/hw/ppc/spapr_vio.h
@@ -25,17 +25,16 @@
 #include "hw/ppc/spapr.h"
 #include "sysemu/dma.h"
 #include "hw/irq.h"
+#include "qom/object.h"
 
 #define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device"
-#define VIO_SPAPR_DEVICE(obj) \
-     OBJECT_CHECK(SpaprVioDevice, (obj), TYPE_VIO_SPAPR_DEVICE)
-#define VIO_SPAPR_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(SpaprVioDeviceClass, (klass), TYPE_VIO_SPAPR_DEVICE)
-#define VIO_SPAPR_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(SpaprVioDeviceClass, (obj), TYPE_VIO_SPAPR_DEVICE)
+OBJECT_DECLARE_TYPE(SpaprVioDevice, SpaprVioDeviceClass,
+                    vio_spapr_device, VIO_SPAPR_DEVICE)
 
 #define TYPE_SPAPR_VIO_BUS "spapr-vio-bus"
-#define SPAPR_VIO_BUS(obj) OBJECT_CHECK(SpaprVioBus, (obj), TYPE_SPAPR_VIO_BUS)
+typedef struct SpaprVioBus SpaprVioBus;
+DECLARE_INSTANCE_CHECKER(SpaprVioBus, SPAPR_VIO_BUS,
+                         TYPE_SPAPR_VIO_BUS)
 
 #define TYPE_SPAPR_VIO_BRIDGE "spapr-vio-bridge"
 
@@ -46,10 +45,8 @@ typedef struct SpaprVioCrq {
     int(*SendFunc)(struct SpaprVioDevice *vdev, uint8_t *crq);
 } SpaprVioCrq;
 
-typedef struct SpaprVioDevice SpaprVioDevice;
-typedef struct SpaprVioBus SpaprVioBus;
 
-typedef struct SpaprVioDeviceClass {
+struct SpaprVioDeviceClass {
     DeviceClass parent_class;
 
     const char *dt_name, *dt_type, *dt_compatible;
@@ -59,7 +56,7 @@ typedef struct SpaprVioDeviceClass {
     void (*reset)(SpaprVioDevice *dev);
     int (*devnode)(SpaprVioDevice *dev, void *fdt, int node_off);
     const char *(*get_dt_compatible)(SpaprVioDevice *dev);
-} SpaprVioDeviceClass;
+};
 
 struct SpaprVioDevice {
     DeviceState qdev;
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 9ed58ec7e9..c5a3cdcadc 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -30,6 +30,7 @@
 
 #include "exec/memory.h"
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 #define XICS_IPI        0x2
 #define XICS_BUID       0x1
@@ -40,8 +41,6 @@
  * (the kernel implementation supports more but we don't exploit
  *  that yet)
  */
-typedef struct ICPStateClass ICPStateClass;
-typedef struct ICPState ICPState;
 typedef struct PnvICPState PnvICPState;
 typedef struct ICSStateClass ICSStateClass;
 typedef struct ICSState ICSState;
@@ -49,15 +48,13 @@ typedef struct ICSIRQState ICSIRQState;
 typedef struct XICSFabric XICSFabric;
 
 #define TYPE_ICP "icp"
-#define ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_ICP)
+OBJECT_DECLARE_TYPE(ICPState, ICPStateClass,
+                    icp, ICP)
 
 #define TYPE_PNV_ICP "pnv-icp"
-#define PNV_ICP(obj) OBJECT_CHECK(PnvICPState, (obj), TYPE_PNV_ICP)
+DECLARE_INSTANCE_CHECKER(PnvICPState, PNV_ICP,
+                         TYPE_PNV_ICP)
 
-#define ICP_CLASS(klass) \
-     OBJECT_CLASS_CHECK(ICPStateClass, (klass), TYPE_ICP)
-#define ICP_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(ICPStateClass, (obj), TYPE_ICP)
 
 struct ICPStateClass {
     DeviceClass parent_class;
@@ -90,12 +87,9 @@ struct PnvICPState {
 };
 
 #define TYPE_ICS "ics"
-#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
+DECLARE_OBJ_CHECKERS(ICSState, ICSStateClass,
+                     ICS, TYPE_ICS)
 
-#define ICS_CLASS(klass) \
-     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS)
-#define ICS_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS)
 
 struct ICSStateClass {
     DeviceClass parent_class;
@@ -145,17 +139,16 @@ struct ICSIRQState {
 #define TYPE_XICS_FABRIC "xics-fabric"
 #define XICS_FABRIC(obj)                                     \
     INTERFACE_CHECK(XICSFabric, (obj), TYPE_XICS_FABRIC)
-#define XICS_FABRIC_CLASS(klass)                                     \
-    OBJECT_CLASS_CHECK(XICSFabricClass, (klass), TYPE_XICS_FABRIC)
-#define XICS_FABRIC_GET_CLASS(obj)                                   \
-    OBJECT_GET_CLASS(XICSFabricClass, (obj), TYPE_XICS_FABRIC)
+typedef struct XICSFabricClass XICSFabricClass;
+DECLARE_CLASS_CHECKERS(XICSFabricClass, XICS_FABRIC,
+                       TYPE_XICS_FABRIC)
 
-typedef struct XICSFabricClass {
+struct XICSFabricClass {
     InterfaceClass parent;
     ICSState *(*ics_get)(XICSFabric *xi, int irq);
     void (*ics_resend)(XICSFabric *xi);
     ICPState *(*icp_get)(XICSFabric *xi, int server);
-} XICSFabricClass;
+};
 
 ICPState *xics_icp_get(XICSFabric *xi, int server);
 
diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h
index 1c65c96e3c..0b8182e40b 100644
--- a/include/hw/ppc/xics_spapr.h
+++ b/include/hw/ppc/xics_spapr.h
@@ -28,9 +28,12 @@
 #define XICS_SPAPR_H
 
 #include "hw/ppc/spapr.h"
+#include "qom/object.h"
 
 #define TYPE_ICS_SPAPR "ics-spapr"
-#define ICS_SPAPR(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SPAPR)
+/* This is reusing the ICSState typedef from TYPE_ICS */
+DECLARE_INSTANCE_CHECKER(ICSState, ICS_SPAPR,
+                         TYPE_ICS_SPAPR)
 
 int xics_kvm_connect(SpaprInterruptController *intc, uint32_t nr_servers,
                      Error **errp);
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index 2c42ae92d2..482fafccfd 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -143,6 +143,7 @@
 #include "sysemu/kvm.h"
 #include "hw/sysbus.h"
 #include "hw/ppc/xive_regs.h"
+#include "qom/object.h"
 
 /*
  * XIVE Notifier (Interface between Source and Router)
@@ -153,22 +154,23 @@ typedef struct XiveNotifier XiveNotifier;
 #define TYPE_XIVE_NOTIFIER "xive-notifier"
 #define XIVE_NOTIFIER(obj)                                     \
     INTERFACE_CHECK(XiveNotifier, (obj), TYPE_XIVE_NOTIFIER)
-#define XIVE_NOTIFIER_CLASS(klass)                                     \
-    OBJECT_CLASS_CHECK(XiveNotifierClass, (klass), TYPE_XIVE_NOTIFIER)
-#define XIVE_NOTIFIER_GET_CLASS(obj)                                   \
-    OBJECT_GET_CLASS(XiveNotifierClass, (obj), TYPE_XIVE_NOTIFIER)
+typedef struct XiveNotifierClass XiveNotifierClass;
+DECLARE_CLASS_CHECKERS(XiveNotifierClass, XIVE_NOTIFIER,
+                       TYPE_XIVE_NOTIFIER)
 
-typedef struct XiveNotifierClass {
+struct XiveNotifierClass {
     InterfaceClass parent;
     void (*notify)(XiveNotifier *xn, uint32_t lisn);
-} XiveNotifierClass;
+};
 
 /*
  * XIVE Interrupt Source
  */
 
 #define TYPE_XIVE_SOURCE "xive-source"
-#define XIVE_SOURCE(obj) OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE)
+typedef struct XiveSource XiveSource;
+DECLARE_INSTANCE_CHECKER(XiveSource, XIVE_SOURCE,
+                         TYPE_XIVE_SOURCE)
 
 /*
  * XIVE Interrupt Source characteristics, which define how the ESB are
@@ -177,7 +179,7 @@ typedef struct XiveNotifierClass {
 #define XIVE_SRC_H_INT_ESB     0x1 /* ESB managed with hcall H_INT_ESB */
 #define XIVE_SRC_STORE_EOI     0x2 /* Store EOI supported */
 
-typedef struct XiveSource {
+struct XiveSource {
     DeviceState parent;
 
     /* IRQs */
@@ -198,7 +200,7 @@ typedef struct XiveSource {
     MemoryRegion    esb_mmio_kvm;
 
     XiveNotifier    *xive;
-} XiveSource;
+};
 
 /*
  * ESB MMIO setting. Can be one page, for both source triggering and
@@ -304,7 +306,9 @@ void xive_source_set_irq(void *opaque, int srcno, int val);
  */
 
 #define TYPE_XIVE_TCTX "xive-tctx"
-#define XIVE_TCTX(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX)
+typedef struct XiveTCTX XiveTCTX;
+DECLARE_INSTANCE_CHECKER(XiveTCTX, XIVE_TCTX,
+                         TYPE_XIVE_TCTX)
 
 /*
  * XIVE Thread interrupt Management register rings :
@@ -319,7 +323,7 @@ void xive_source_set_irq(void *opaque, int srcno, int val);
 
 typedef struct XivePresenter XivePresenter;
 
-typedef struct XiveTCTX {
+struct XiveTCTX {
     DeviceState parent_obj;
 
     CPUState    *cs;
@@ -329,28 +333,24 @@ typedef struct XiveTCTX {
     uint8_t     regs[XIVE_TM_RING_COUNT * XIVE_TM_RING_SIZE];
 
     XivePresenter *xptr;
-} XiveTCTX;
+};
 
 /*
  * XIVE Router
  */
 typedef struct XiveFabric XiveFabric;
 
-typedef struct XiveRouter {
+struct XiveRouter {
     SysBusDevice    parent;
 
     XiveFabric *xfb;
-} XiveRouter;
+};
 
 #define TYPE_XIVE_ROUTER "xive-router"
-#define XIVE_ROUTER(obj)                                \
-    OBJECT_CHECK(XiveRouter, (obj), TYPE_XIVE_ROUTER)
-#define XIVE_ROUTER_CLASS(klass)                                        \
-    OBJECT_CLASS_CHECK(XiveRouterClass, (klass), TYPE_XIVE_ROUTER)
-#define XIVE_ROUTER_GET_CLASS(obj)                              \
-    OBJECT_GET_CLASS(XiveRouterClass, (obj), TYPE_XIVE_ROUTER)
-
-typedef struct XiveRouterClass {
+OBJECT_DECLARE_TYPE(XiveRouter, XiveRouterClass,
+                    xive_router, XIVE_ROUTER)
+
+struct XiveRouterClass {
     SysBusDeviceClass parent;
 
     /* XIVE table accessors */
@@ -365,7 +365,7 @@ typedef struct XiveRouterClass {
     int (*write_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx,
                      XiveNVT *nvt, uint8_t word_number);
     uint8_t (*get_block_id)(XiveRouter *xrtr);
-} XiveRouterClass;
+};
 
 int xive_router_get_eas(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
                         XiveEAS *eas);
@@ -391,19 +391,18 @@ typedef struct XiveTCTXMatch {
 #define TYPE_XIVE_PRESENTER "xive-presenter"
 #define XIVE_PRESENTER(obj)                                     \
     INTERFACE_CHECK(XivePresenter, (obj), TYPE_XIVE_PRESENTER)
-#define XIVE_PRESENTER_CLASS(klass)                                     \
-    OBJECT_CLASS_CHECK(XivePresenterClass, (klass), TYPE_XIVE_PRESENTER)
-#define XIVE_PRESENTER_GET_CLASS(obj)                                   \
-    OBJECT_GET_CLASS(XivePresenterClass, (obj), TYPE_XIVE_PRESENTER)
+typedef struct XivePresenterClass XivePresenterClass;
+DECLARE_CLASS_CHECKERS(XivePresenterClass, XIVE_PRESENTER,
+                       TYPE_XIVE_PRESENTER)
 
-typedef struct XivePresenterClass {
+struct XivePresenterClass {
     InterfaceClass parent;
     int (*match_nvt)(XivePresenter *xptr, uint8_t format,
                      uint8_t nvt_blk, uint32_t nvt_idx,
                      bool cam_ignore, uint8_t priority,
                      uint32_t logic_serv, XiveTCTXMatch *match);
     bool (*in_kernel)(const XivePresenter *xptr);
-} XivePresenterClass;
+};
 
 int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx,
                               uint8_t format,
@@ -417,28 +416,28 @@ int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx,
 #define TYPE_XIVE_FABRIC "xive-fabric"
 #define XIVE_FABRIC(obj)                                     \
     INTERFACE_CHECK(XiveFabric, (obj), TYPE_XIVE_FABRIC)
-#define XIVE_FABRIC_CLASS(klass)                                     \
-    OBJECT_CLASS_CHECK(XiveFabricClass, (klass), TYPE_XIVE_FABRIC)
-#define XIVE_FABRIC_GET_CLASS(obj)                                   \
-    OBJECT_GET_CLASS(XiveFabricClass, (obj), TYPE_XIVE_FABRIC)
+typedef struct XiveFabricClass XiveFabricClass;
+DECLARE_CLASS_CHECKERS(XiveFabricClass, XIVE_FABRIC,
+                       TYPE_XIVE_FABRIC)
 
-typedef struct XiveFabricClass {
+struct XiveFabricClass {
     InterfaceClass parent;
     int (*match_nvt)(XiveFabric *xfb, uint8_t format,
                      uint8_t nvt_blk, uint32_t nvt_idx,
                      bool cam_ignore, uint8_t priority,
                      uint32_t logic_serv, XiveTCTXMatch *match);
-} XiveFabricClass;
+};
 
 /*
  * XIVE END ESBs
  */
 
 #define TYPE_XIVE_END_SOURCE "xive-end-source"
-#define XIVE_END_SOURCE(obj) \
-    OBJECT_CHECK(XiveENDSource, (obj), TYPE_XIVE_END_SOURCE)
+typedef struct XiveENDSource XiveENDSource;
+DECLARE_INSTANCE_CHECKER(XiveENDSource, XIVE_END_SOURCE,
+                         TYPE_XIVE_END_SOURCE)
 
-typedef struct XiveENDSource {
+struct XiveENDSource {
     DeviceState parent;
 
     uint32_t        nr_ends;
@@ -448,7 +447,7 @@ typedef struct XiveENDSource {
     MemoryRegion    esb_mmio;
 
     XiveRouter      *xrtr;
-} XiveENDSource;
+};
 
 /*
  * For legacy compatibility, the exceptions define up to 256 different
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index ea3f73a282..e025ba9653 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -12,9 +12,9 @@ enum {
 };
 
 #define TYPE_DEVICE "device"
-#define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE)
-#define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE)
-#define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE)
+typedef struct DeviceClass DeviceClass;
+DECLARE_OBJ_CHECKERS(DeviceState, DeviceClass,
+                     DEVICE, TYPE_DEVICE)
 
 typedef enum DeviceCategory {
     DEVICE_CATEGORY_BRIDGE,
@@ -93,7 +93,7 @@ typedef void (*BusUnrealize)(BusState *bus);
  * until it was marked don't hide and qdev_device_add called again.
  *
  */
-typedef struct DeviceClass {
+struct DeviceClass {
     /*< private >*/
     ObjectClass parent_class;
     /*< public >*/
@@ -137,7 +137,7 @@ typedef struct DeviceClass {
 
     /* Private to qdev / bus.  */
     const char *bus_type;
-} DeviceClass;
+};
 
 typedef struct NamedGPIOList NamedGPIOList;
 
@@ -203,9 +203,8 @@ struct DeviceListener {
 };
 
 #define TYPE_BUS "bus"
-#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS)
-#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS)
-#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS)
+DECLARE_OBJ_CHECKERS(BusState, BusClass,
+                     BUS, TYPE_BUS)
 
 struct BusClass {
     ObjectClass parent_class;
diff --git a/include/hw/rdma/rdma.h b/include/hw/rdma/rdma.h
index fd3d70103d..e77e43a170 100644
--- a/include/hw/rdma/rdma.h
+++ b/include/hw/rdma/rdma.h
@@ -19,22 +19,19 @@
 
 #define INTERFACE_RDMA_PROVIDER "rdma"
 
-#define RDMA_PROVIDER_CLASS(klass) \
-    OBJECT_CLASS_CHECK(RdmaProviderClass, (klass), \
+typedef struct RdmaProviderClass RdmaProviderClass;
+DECLARE_CLASS_CHECKERS(RdmaProviderClass, RDMA_PROVIDER,
                        INTERFACE_RDMA_PROVIDER)
-#define RDMA_PROVIDER_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(RdmaProviderClass, (obj), \
-                     INTERFACE_RDMA_PROVIDER)
 #define RDMA_PROVIDER(obj) \
     INTERFACE_CHECK(RdmaProvider, (obj), \
                     INTERFACE_RDMA_PROVIDER)
 
 typedef struct RdmaProvider RdmaProvider;
 
-typedef struct RdmaProviderClass {
+struct RdmaProviderClass {
     InterfaceClass parent;
 
     void (*print_statistics)(Monitor *mon, RdmaProvider *obj);
-} RdmaProviderClass;
+};
 
 #endif
diff --git a/include/hw/register.h b/include/hw/register.h
index fdac5e69b5..03c8926d27 100644
--- a/include/hw/register.h
+++ b/include/hw/register.h
@@ -14,6 +14,7 @@
 #include "hw/qdev-core.h"
 #include "exec/memory.h"
 #include "hw/registerfields.h"
+#include "qom/object.h"
 
 typedef struct RegisterInfo RegisterInfo;
 typedef struct RegisterAccessInfo RegisterAccessInfo;
@@ -87,7 +88,8 @@ struct RegisterInfo {
 };
 
 #define TYPE_REGISTER "qemu,register"
-#define REGISTER(obj) OBJECT_CHECK(RegisterInfo, (obj), TYPE_REGISTER)
+DECLARE_INSTANCE_CHECKER(RegisterInfo, REGISTER,
+                         TYPE_REGISTER)
 
 /**
  * This structure is used to group all of the individual registers which are
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
index f4c4bab0ef..bdcd1276b6 100644
--- a/include/hw/resettable.h
+++ b/include/hw/resettable.h
@@ -17,11 +17,10 @@
 
 #define TYPE_RESETTABLE_INTERFACE "resettable"
 
-#define RESETTABLE_CLASS(class) \
-    OBJECT_CLASS_CHECK(ResettableClass, (class), TYPE_RESETTABLE_INTERFACE)
+typedef struct ResettableClass ResettableClass;
+DECLARE_CLASS_CHECKERS(ResettableClass, RESETTABLE,
+                       TYPE_RESETTABLE_INTERFACE)
 
-#define RESETTABLE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(ResettableClass, (obj), TYPE_RESETTABLE_INTERFACE)
 
 typedef struct ResettableState ResettableState;
 
@@ -119,7 +118,7 @@ typedef struct ResettablePhases {
     ResettableHoldPhase hold;
     ResettableExitPhase exit;
 } ResettablePhases;
-typedef struct ResettableClass {
+struct ResettableClass {
     InterfaceClass parent_class;
 
     /* Phase methods */
@@ -133,7 +132,7 @@ typedef struct ResettableClass {
 
     /* Hierarchy handling method */
     ResettableChildForeach child_foreach;
-} ResettableClass;
+};
 
 /**
  * ResettableState:
diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h
index 835a80f896..8c15b6325f 100644
--- a/include/hw/riscv/opentitan.h
+++ b/include/hw/riscv/opentitan.h
@@ -22,12 +22,14 @@
 #include "hw/riscv/riscv_hart.h"
 #include "hw/intc/ibex_plic.h"
 #include "hw/char/ibex_uart.h"
+#include "qom/object.h"
 
 #define TYPE_RISCV_IBEX_SOC "riscv.lowrisc.ibex.soc"
-#define RISCV_IBEX_SOC(obj) \
-    OBJECT_CHECK(LowRISCIbexSoCState, (obj), TYPE_RISCV_IBEX_SOC)
+typedef struct LowRISCIbexSoCState LowRISCIbexSoCState;
+DECLARE_INSTANCE_CHECKER(LowRISCIbexSoCState, RISCV_IBEX_SOC,
+                         TYPE_RISCV_IBEX_SOC)
 
-typedef struct LowRISCIbexSoCState {
+struct LowRISCIbexSoCState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -38,7 +40,7 @@ typedef struct LowRISCIbexSoCState {
 
     MemoryRegion flash_mem;
     MemoryRegion rom;
-} LowRISCIbexSoCState;
+};
 
 typedef struct OpenTitanState {
     /*< private >*/
diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h
index 77aa4bc948..ac2cb62e1b 100644
--- a/include/hw/riscv/riscv_hart.h
+++ b/include/hw/riscv/riscv_hart.h
@@ -23,13 +23,15 @@
 
 #include "hw/sysbus.h"
 #include "target/riscv/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_RISCV_HART_ARRAY "riscv.hart_array"
 
-#define RISCV_HART_ARRAY(obj) \
-    OBJECT_CHECK(RISCVHartArrayState, (obj), TYPE_RISCV_HART_ARRAY)
+typedef struct RISCVHartArrayState RISCVHartArrayState;
+DECLARE_INSTANCE_CHECKER(RISCVHartArrayState, RISCV_HART_ARRAY,
+                         TYPE_RISCV_HART_ARRAY)
 
-typedef struct RISCVHartArrayState {
+struct RISCVHartArrayState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -39,6 +41,6 @@ typedef struct RISCVHartArrayState {
     char *cpu_type;
     uint64_t resetvec;
     RISCVCPU *harts;
-} RISCVHartArrayState;
+};
 
 #endif
diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h
index b0a18a9c94..cddeca2e77 100644
--- a/include/hw/riscv/spike.h
+++ b/include/hw/riscv/spike.h
@@ -21,15 +21,17 @@
 
 #include "hw/riscv/riscv_hart.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define SPIKE_CPUS_MAX 8
 #define SPIKE_SOCKETS_MAX 8
 
 #define TYPE_SPIKE_MACHINE MACHINE_TYPE_NAME("spike")
-#define SPIKE_MACHINE(obj) \
-    OBJECT_CHECK(SpikeState, (obj), TYPE_SPIKE_MACHINE)
+typedef struct SpikeState SpikeState;
+DECLARE_INSTANCE_CHECKER(SpikeState, SPIKE_MACHINE,
+                         TYPE_SPIKE_MACHINE)
 
-typedef struct {
+struct SpikeState {
     /*< private >*/
     MachineState parent;
 
@@ -37,7 +39,7 @@ typedef struct {
     RISCVHartArrayState soc[SPIKE_SOCKETS_MAX];
     void *fdt;
     int fdt_size;
-} SpikeState;
+};
 
 enum {
     SPIKE_MROM,
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index 1beacd7666..b4ed9a32eb 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -22,15 +22,17 @@
 #include "hw/riscv/riscv_hart.h"
 #include "hw/sysbus.h"
 #include "hw/block/flash.h"
+#include "qom/object.h"
 
 #define VIRT_CPUS_MAX 8
 #define VIRT_SOCKETS_MAX 8
 
 #define TYPE_RISCV_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
-#define RISCV_VIRT_MACHINE(obj) \
-    OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_MACHINE)
+typedef struct RISCVVirtState RISCVVirtState;
+DECLARE_INSTANCE_CHECKER(RISCVVirtState, RISCV_VIRT_MACHINE,
+                         TYPE_RISCV_VIRT_MACHINE)
 
-typedef struct {
+struct RISCVVirtState {
     /*< private >*/
     MachineState parent;
 
@@ -41,7 +43,7 @@ typedef struct {
 
     void *fdt;
     int fdt_size;
-} RISCVVirtState;
+};
 
 enum {
     VIRT_DEBUG,
diff --git a/include/hw/rtc/allwinner-rtc.h b/include/hw/rtc/allwinner-rtc.h
index 7893f74795..5a6e9fff32 100644
--- a/include/hw/rtc/allwinner-rtc.h
+++ b/include/hw/rtc/allwinner-rtc.h
@@ -60,19 +60,17 @@
  * @{
  */
 
-#define AW_RTC(obj) \
-    OBJECT_CHECK(AwRtcState, (obj), TYPE_AW_RTC)
-#define AW_RTC_CLASS(klass) \
-     OBJECT_CLASS_CHECK(AwRtcClass, (klass), TYPE_AW_RTC)
-#define AW_RTC_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(AwRtcClass, (obj), TYPE_AW_RTC)
+typedef struct AwRtcClass AwRtcClass;
+typedef struct AwRtcState AwRtcState;
+DECLARE_OBJ_CHECKERS(AwRtcState, AwRtcClass,
+                     AW_RTC, TYPE_AW_RTC)
 
 /** @} */
 
 /**
  * Allwinner RTC per-object instance state.
  */
-typedef struct AwRtcState {
+struct AwRtcState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -92,7 +90,7 @@ typedef struct AwRtcState {
     /** Array of hardware registers */
     uint32_t regs[AW_RTC_REGS_NUM];
 
-} AwRtcState;
+};
 
 /**
  * Allwinner RTC class-level struct.
@@ -101,7 +99,7 @@ typedef struct AwRtcState {
  * such that the generic code can use this struct to support
  * all devices.
  */
-typedef struct AwRtcClass {
+struct AwRtcClass {
     /*< private >*/
     SysBusDeviceClass parent_class;
     /*< public >*/
@@ -129,6 +127,6 @@ typedef struct AwRtcClass {
      */
     bool (*write)(AwRtcState *s, uint32_t offset, uint32_t data);
 
-} AwRtcClass;
+};
 
 #endif /* HW_MISC_ALLWINNER_RTC_H */
diff --git a/include/hw/rtc/aspeed_rtc.h b/include/hw/rtc/aspeed_rtc.h
index b94a710268..d7691ab88f 100644
--- a/include/hw/rtc/aspeed_rtc.h
+++ b/include/hw/rtc/aspeed_rtc.h
@@ -9,8 +9,9 @@
 #define HW_RTC_ASPEED_RTC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
-typedef struct AspeedRtcState {
+struct AspeedRtcState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -19,9 +20,11 @@ typedef struct AspeedRtcState {
     uint32_t reg[0x18];
     int offset;
 
-} AspeedRtcState;
+};
+typedef struct AspeedRtcState AspeedRtcState;
 
 #define TYPE_ASPEED_RTC "aspeed.rtc"
-#define ASPEED_RTC(obj) OBJECT_CHECK(AspeedRtcState, (obj), TYPE_ASPEED_RTC)
+DECLARE_INSTANCE_CHECKER(AspeedRtcState, ASPEED_RTC,
+                         TYPE_ASPEED_RTC)
 
 #endif /* HW_RTC_ASPEED_RTC_H */
diff --git a/include/hw/rtc/goldfish_rtc.h b/include/hw/rtc/goldfish_rtc.h
index 9bd8924f5f..b710c21c94 100644
--- a/include/hw/rtc/goldfish_rtc.h
+++ b/include/hw/rtc/goldfish_rtc.h
@@ -23,12 +23,14 @@
 #define HW_RTC_GOLDFISH_RTC_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_GOLDFISH_RTC "goldfish_rtc"
-#define GOLDFISH_RTC(obj) \
-    OBJECT_CHECK(GoldfishRTCState, (obj), TYPE_GOLDFISH_RTC)
+typedef struct GoldfishRTCState GoldfishRTCState;
+DECLARE_INSTANCE_CHECKER(GoldfishRTCState, GOLDFISH_RTC,
+                         TYPE_GOLDFISH_RTC)
 
-typedef struct GoldfishRTCState {
+struct GoldfishRTCState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -42,6 +44,6 @@ typedef struct GoldfishRTCState {
     uint32_t irq_pending;
     uint32_t irq_enabled;
     uint32_t time_high;
-} GoldfishRTCState;
+};
 
 #endif
diff --git a/include/hw/rtc/m48t59.h b/include/hw/rtc/m48t59.h
index e7ea4e8761..04abedf3b2 100644
--- a/include/hw/rtc/m48t59.h
+++ b/include/hw/rtc/m48t59.h
@@ -31,22 +31,21 @@
 
 #define TYPE_NVRAM "nvram"
 
-#define NVRAM_CLASS(klass) \
-    OBJECT_CLASS_CHECK(NvramClass, (klass), TYPE_NVRAM)
-#define NVRAM_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(NvramClass, (obj), TYPE_NVRAM)
+typedef struct NvramClass NvramClass;
+DECLARE_CLASS_CHECKERS(NvramClass, NVRAM,
+                       TYPE_NVRAM)
 #define NVRAM(obj) \
     INTERFACE_CHECK(Nvram, (obj), TYPE_NVRAM)
 
 typedef struct Nvram Nvram;
 
-typedef struct NvramClass {
+struct NvramClass {
     InterfaceClass parent;
 
     uint32_t (*read)(Nvram *obj, uint32_t addr);
     void (*write)(Nvram *obj, uint32_t addr, uint32_t val);
     void (*toggle_lock)(Nvram *obj, int lock);
-} NvramClass;
+};
 
 Nvram *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
                        int base_year, int type);
diff --git a/include/hw/rtc/mc146818rtc.h b/include/hw/rtc/mc146818rtc.h
index 3713181b56..e58e006d0d 100644
--- a/include/hw/rtc/mc146818rtc.h
+++ b/include/hw/rtc/mc146818rtc.h
@@ -13,11 +13,14 @@
 #include "qemu/queue.h"
 #include "qemu/timer.h"
 #include "hw/isa/isa.h"
+#include "qom/object.h"
 
 #define TYPE_MC146818_RTC "mc146818rtc"
-#define MC146818_RTC(obj) OBJECT_CHECK(RTCState, (obj), TYPE_MC146818_RTC)
+typedef struct RTCState RTCState;
+DECLARE_INSTANCE_CHECKER(RTCState, MC146818_RTC,
+                         TYPE_MC146818_RTC)
 
-typedef struct RTCState {
+struct RTCState {
     ISADevice parent_obj;
 
     MemoryRegion io;
@@ -44,7 +47,7 @@ typedef struct RTCState {
     LostTickPolicy lost_tick_policy;
     Notifier suspend_notifier;
     QLIST_ENTRY(RTCState) link;
-} RTCState;
+};
 
 #define RTC_ISA_IRQ 8
 #define RTC_ISA_BASE 0x70
diff --git a/include/hw/rtc/pl031.h b/include/hw/rtc/pl031.h
index e3cb1d646f..3897b424d4 100644
--- a/include/hw/rtc/pl031.h
+++ b/include/hw/rtc/pl031.h
@@ -16,11 +16,14 @@
 
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
+#include "qom/object.h"
 
 #define TYPE_PL031 "pl031"
-#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
+typedef struct PL031State PL031State;
+DECLARE_INSTANCE_CHECKER(PL031State, PL031,
+                         TYPE_PL031)
 
-typedef struct PL031State {
+struct PL031State {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -42,6 +45,6 @@ typedef struct PL031State {
     uint32_t cr;
     uint32_t im;
     uint32_t is;
-} PL031State;
+};
 
 #endif
diff --git a/include/hw/rtc/xlnx-zynqmp-rtc.h b/include/hw/rtc/xlnx-zynqmp-rtc.h
index 6fa1cb2f43..209de85ae6 100644
--- a/include/hw/rtc/xlnx-zynqmp-rtc.h
+++ b/include/hw/rtc/xlnx-zynqmp-rtc.h
@@ -29,11 +29,13 @@
 
 #include "hw/register.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_XLNX_ZYNQMP_RTC "xlnx-zynmp.rtc"
 
-#define XLNX_ZYNQMP_RTC(obj) \
-     OBJECT_CHECK(XlnxZynqMPRTC, (obj), TYPE_XLNX_ZYNQMP_RTC)
+typedef struct XlnxZynqMPRTC XlnxZynqMPRTC;
+DECLARE_INSTANCE_CHECKER(XlnxZynqMPRTC, XLNX_ZYNQMP_RTC,
+                         TYPE_XLNX_ZYNQMP_RTC)
 
 REG32(SET_TIME_WRITE, 0x0)
 REG32(SET_TIME_READ, 0x4)
@@ -77,7 +79,7 @@ REG32(SAFETY_CHK, 0x50)
 
 #define XLNX_ZYNQMP_RTC_R_MAX (R_SAFETY_CHK + 1)
 
-typedef struct XlnxZynqMPRTC {
+struct XlnxZynqMPRTC {
     SysBusDevice parent_obj;
     MemoryRegion iomem;
     qemu_irq irq_rtc_int;
@@ -87,6 +89,6 @@ typedef struct XlnxZynqMPRTC {
 
     uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
     RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
-} XlnxZynqMPRTC;
+};
 
 #endif
diff --git a/include/hw/rx/rx62n.h b/include/hw/rx/rx62n.h
index aa94758c27..3ed80dba0d 100644
--- a/include/hw/rx/rx62n.h
+++ b/include/hw/rx/rx62n.h
@@ -30,9 +30,12 @@
 #include "hw/timer/renesas_cmt.h"
 #include "hw/char/renesas_sci.h"
 #include "qemu/units.h"
+#include "qom/object.h"
 
 #define TYPE_RX62N_MCU "rx62n-mcu"
-#define RX62N_MCU(obj) OBJECT_CHECK(RX62NState, (obj), TYPE_RX62N_MCU)
+typedef struct RX62NState RX62NState;
+DECLARE_INSTANCE_CHECKER(RX62NState, RX62N_MCU,
+                         TYPE_RX62N_MCU)
 
 #define TYPE_R5F562N7_MCU "r5f562n7-mcu"
 #define TYPE_R5F562N8_MCU "r5f562n8-mcu"
@@ -45,7 +48,7 @@
 #define RX62N_NR_CMT    2
 #define RX62N_NR_SCI    6
 
-typedef struct RX62NState {
+struct RX62NState {
     /*< private >*/
     DeviceState parent_obj;
     /*< public >*/
@@ -71,6 +74,6 @@ typedef struct RX62NState {
     uint32_t xtal_freq_hz;
     /* Peripheral Module Clock frequency */
     uint32_t pclk_freq_hz;
-} RX62NState;
+};
 
 #endif
diff --git a/include/hw/s390x/3270-ccw.h b/include/hw/s390x/3270-ccw.h
index 9d1d18e2bd..9a11093192 100644
--- a/include/hw/s390x/3270-ccw.h
+++ b/include/hw/s390x/3270-ccw.h
@@ -16,6 +16,7 @@
 #include "hw/sysbus.h"
 #include "hw/s390x/css.h"
 #include "hw/s390x/ccw-device.h"
+#include "qom/object.h"
 
 #define EMULATED_CCW_3270_CU_TYPE 0x3270
 #define EMULATED_CCW_3270_CHPID_TYPE 0x1a
@@ -30,23 +31,21 @@
 #define TC_EWRITEA 0x0d         /* Erase write alternate */
 #define TC_WRITESF 0x11         /* Write structured field */
 
-#define EMULATED_CCW_3270(obj) \
-     OBJECT_CHECK(EmulatedCcw3270Device, (obj), TYPE_EMULATED_CCW_3270)
-#define EMULATED_CCW_3270_CLASS(klass) \
-     OBJECT_CLASS_CHECK(EmulatedCcw3270Class, (klass), TYPE_EMULATED_CCW_3270)
-#define EMULATED_CCW_3270_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(EmulatedCcw3270Class, (obj), TYPE_EMULATED_CCW_3270)
+typedef struct EmulatedCcw3270Class EmulatedCcw3270Class;
+typedef struct EmulatedCcw3270Device EmulatedCcw3270Device;
+DECLARE_OBJ_CHECKERS(EmulatedCcw3270Device, EmulatedCcw3270Class,
+                     EMULATED_CCW_3270, TYPE_EMULATED_CCW_3270)
 
-typedef struct EmulatedCcw3270Device {
+struct EmulatedCcw3270Device {
     CcwDevice parent_obj;
-} EmulatedCcw3270Device;
+};
 
-typedef struct EmulatedCcw3270Class {
+struct EmulatedCcw3270Class {
     CCWDeviceClass parent_class;
 
     void (*init)(EmulatedCcw3270Device *, Error **);
     int (*read_payload_3270)(EmulatedCcw3270Device *);
     int (*write_payload_3270)(EmulatedCcw3270Device *, uint8_t);
-} EmulatedCcw3270Class;
+};
 
 #endif
diff --git a/include/hw/s390x/ap-device.h b/include/hw/s390x/ap-device.h
index 8df9cd2954..e502745de5 100644
--- a/include/hw/s390x/ap-device.h
+++ b/include/hw/s390x/ap-device.h
@@ -12,14 +12,16 @@
 #define HW_S390X_AP_DEVICE_H
 
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
-#define AP_DEVICE_TYPE       "ap-device"
+#define TYPE_AP_DEVICE       "ap-device"
 
-typedef struct APDevice {
+struct APDevice {
     DeviceState parent_obj;
-} APDevice;
+};
+typedef struct APDevice APDevice;
 
-#define AP_DEVICE(obj) \
-    OBJECT_CHECK(APDevice, (obj), AP_DEVICE_TYPE)
+DECLARE_INSTANCE_CHECKER(APDevice, AP_DEVICE,
+                         TYPE_AP_DEVICE)
 
 #endif /* HW_S390X_AP_DEVICE_H */
diff --git a/include/hw/s390x/css-bridge.h b/include/hw/s390x/css-bridge.h
index f7ed2d9a03..9fd4484204 100644
--- a/include/hw/s390x/css-bridge.h
+++ b/include/hw/s390x/css-bridge.h
@@ -17,23 +17,25 @@
 #include "hw/sysbus.h"
 
 /* virtual css bridge */
-typedef struct VirtualCssBridge {
+struct VirtualCssBridge {
     SysBusDevice sysbus_dev;
     bool css_dev_path;
-} VirtualCssBridge;
+};
+typedef struct VirtualCssBridge VirtualCssBridge;
 
 #define TYPE_VIRTUAL_CSS_BRIDGE "virtual-css-bridge"
-#define VIRTUAL_CSS_BRIDGE(obj) \
-    OBJECT_CHECK(VirtualCssBridge, (obj), TYPE_VIRTUAL_CSS_BRIDGE)
+DECLARE_INSTANCE_CHECKER(VirtualCssBridge, VIRTUAL_CSS_BRIDGE,
+                         TYPE_VIRTUAL_CSS_BRIDGE)
 
 /* virtual css bus type */
-typedef struct VirtualCssBus {
+struct VirtualCssBus {
     BusState parent_obj;
-} VirtualCssBus;
+};
+typedef struct VirtualCssBus VirtualCssBus;
 
 #define TYPE_VIRTUAL_CSS_BUS "virtual-css-bus"
-#define VIRTUAL_CSS_BUS(obj) \
-     OBJECT_CHECK(VirtualCssBus, (obj), TYPE_VIRTUAL_CSS_BUS)
+DECLARE_INSTANCE_CHECKER(VirtualCssBus, VIRTUAL_CSS_BUS,
+                         TYPE_VIRTUAL_CSS_BUS)
 VirtualCssBus *virtual_css_bus_init(void);
 
 #endif
diff --git a/include/hw/s390x/event-facility.h b/include/hw/s390x/event-facility.h
index e61c4651d7..051c1c6576 100644
--- a/include/hw/s390x/event-facility.h
+++ b/include/hw/s390x/event-facility.h
@@ -18,6 +18,7 @@
 #include "qemu/thread.h"
 #include "hw/qdev-core.h"
 #include "hw/s390x/sclp.h"
+#include "qom/object.h"
 
 /* SCLP event types */
 #define SCLP_EVENT_OPRTNS_COMMAND               0x01
@@ -41,12 +42,8 @@
 #define SCLP_SELECTIVE_READ                     0x01
 
 #define TYPE_SCLP_EVENT "s390-sclp-event-type"
-#define SCLP_EVENT(obj) \
-     OBJECT_CHECK(SCLPEvent, (obj), TYPE_SCLP_EVENT)
-#define SCLP_EVENT_CLASS(klass) \
-     OBJECT_CLASS_CHECK(SCLPEventClass, (klass), TYPE_SCLP_EVENT)
-#define SCLP_EVENT_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(SCLPEventClass, (obj), TYPE_SCLP_EVENT)
+OBJECT_DECLARE_TYPE(SCLPEvent, SCLPEventClass,
+                    sclp_event, SCLP_EVENT)
 
 #define TYPE_SCLP_CPU_HOTPLUG "sclp-cpu-hotplug"
 #define TYPE_SCLP_QUIESCE "sclpquiesce"
@@ -169,13 +166,13 @@ typedef struct ReadEventData {
     };
 } QEMU_PACKED ReadEventData;
 
-typedef struct SCLPEvent {
+struct SCLPEvent {
     DeviceState qdev;
     bool event_pending;
     char *name;
-} SCLPEvent;
+};
 
-typedef struct SCLPEventClass {
+struct SCLPEventClass {
     DeviceClass parent_class;
     int (*init)(SCLPEvent *event);
 
@@ -192,24 +189,19 @@ typedef struct SCLPEventClass {
 
     /* can we handle this event type? */
     bool (*can_handle_event)(uint8_t type);
-} SCLPEventClass;
+};
 
 #define TYPE_SCLP_EVENT_FACILITY "s390-sclp-event-facility"
 typedef struct SCLPEventFacility SCLPEventFacility;
-#define EVENT_FACILITY(obj) \
-     OBJECT_CHECK(SCLPEventFacility, (obj), TYPE_SCLP_EVENT_FACILITY)
-#define EVENT_FACILITY_CLASS(klass) \
-     OBJECT_CLASS_CHECK(SCLPEventFacilityClass, (klass), \
-                        TYPE_SCLP_EVENT_FACILITY)
-#define EVENT_FACILITY_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(SCLPEventFacilityClass, (obj), \
-                      TYPE_SCLP_EVENT_FACILITY)
-
-typedef struct SCLPEventFacilityClass {
+typedef struct SCLPEventFacilityClass SCLPEventFacilityClass;
+DECLARE_OBJ_CHECKERS(SCLPEventFacility, SCLPEventFacilityClass,
+                     EVENT_FACILITY, TYPE_SCLP_EVENT_FACILITY)
+
+struct SCLPEventFacilityClass {
     SysBusDeviceClass parent_class;
     void (*command_handler)(SCLPEventFacility *ef, SCCB *sccb, uint64_t code);
     bool (*event_pending)(SCLPEventFacility *ef);
-} SCLPEventFacilityClass;
+};
 
 BusState *sclp_get_event_facility_bus(void);
 
diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h
index d8e08b5f4c..2c807ee3a1 100644
--- a/include/hw/s390x/s390-ccw.h
+++ b/include/hw/s390x/s390-ccw.h
@@ -14,23 +14,22 @@
 #define HW_S390_CCW_H
 
 #include "hw/s390x/ccw-device.h"
+#include "qom/object.h"
 
 #define TYPE_S390_CCW "s390-ccw"
-#define S390_CCW_DEVICE(obj) \
-    OBJECT_CHECK(S390CCWDevice, (obj), TYPE_S390_CCW)
-#define S390_CCW_DEVICE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(S390CCWDeviceClass, (klass), TYPE_S390_CCW)
-#define S390_CCW_DEVICE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(S390CCWDeviceClass, (obj), TYPE_S390_CCW)
+typedef struct S390CCWDevice S390CCWDevice;
+typedef struct S390CCWDeviceClass S390CCWDeviceClass;
+DECLARE_OBJ_CHECKERS(S390CCWDevice, S390CCWDeviceClass,
+                     S390_CCW_DEVICE, TYPE_S390_CCW)
 
-typedef struct S390CCWDevice {
+struct S390CCWDevice {
     CcwDevice parent_obj;
     CssDevId hostid;
     char *mdevid;
     int32_t bootindex;
-} S390CCWDevice;
+};
 
-typedef struct S390CCWDeviceClass {
+struct S390CCWDeviceClass {
     CCWDeviceClass parent_class;
     void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp);
     void (*unrealize)(S390CCWDevice *dev);
@@ -38,6 +37,6 @@ typedef struct S390CCWDeviceClass {
     int (*handle_halt) (SubchDev *sch);
     int (*handle_clear) (SubchDev *sch);
     IOInstEnding (*handle_store) (SubchDev *sch);
-} S390CCWDeviceClass;
+};
 
 #endif
diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h
index caf4962d29..54d14da0a6 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -12,16 +12,17 @@
 #define HW_S390X_S390_VIRTIO_CCW_H
 
 #include "hw/boards.h"
+#include "qom/object.h"
 
 #define TYPE_S390_CCW_MACHINE               "s390-ccw-machine"
 
-#define S390_CCW_MACHINE(obj) \
-    OBJECT_CHECK(S390CcwMachineState, (obj), TYPE_S390_CCW_MACHINE)
+typedef struct S390CcwMachineClass S390CcwMachineClass;
+typedef struct S390CcwMachineState S390CcwMachineState;
+DECLARE_OBJ_CHECKERS(S390CcwMachineState, S390CcwMachineClass,
+                     S390_CCW_MACHINE, TYPE_S390_CCW_MACHINE)
 
-#define S390_CCW_MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(S390CcwMachineClass, (klass), TYPE_S390_CCW_MACHINE)
 
-typedef struct S390CcwMachineState {
+struct S390CcwMachineState {
     /*< private >*/
     MachineState parent_obj;
 
@@ -30,9 +31,9 @@ typedef struct S390CcwMachineState {
     bool dea_key_wrap;
     bool pv;
     uint8_t loadparm[8];
-} S390CcwMachineState;
+};
 
-typedef struct S390CcwMachineClass {
+struct S390CcwMachineClass {
     /*< private >*/
     MachineClass parent_class;
 
@@ -41,7 +42,7 @@ typedef struct S390CcwMachineClass {
     bool cpu_model_allowed;
     bool css_migration_enabled;
     bool hpage_1m_allowed;
-} S390CcwMachineClass;
+};
 
 /* runtime-instrumentation allowed by the machine */
 bool ri_allowed(void);
diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
index df11de9b20..4b718c8ebf 100644
--- a/include/hw/s390x/s390_flic.h
+++ b/include/hw/s390x/s390_flic.h
@@ -17,6 +17,7 @@
 #include "hw/s390x/adapter.h"
 #include "hw/virtio/virtio.h"
 #include "qemu/queue.h"
+#include "qom/object.h"
 
 /*
  * Reserve enough gsis to accommodate all virtio devices.
@@ -38,22 +39,18 @@ extern const VMStateDescription vmstate_adapter_routes;
     VMSTATE_STRUCT(_f, _s, 1, vmstate_adapter_routes, AdapterRoutes)
 
 #define TYPE_S390_FLIC_COMMON "s390-flic"
-#define S390_FLIC_COMMON(obj) \
-    OBJECT_CHECK(S390FLICState, (obj), TYPE_S390_FLIC_COMMON)
+OBJECT_DECLARE_TYPE(S390FLICState, S390FLICStateClass,
+                    s390_flic_common, S390_FLIC_COMMON)
 
-typedef struct S390FLICState {
+struct S390FLICState {
     SysBusDevice parent_obj;
     /* to limit AdapterRoutes.num_routes for compat */
     uint32_t adapter_routes_max_batch;
     bool ais_supported;
-} S390FLICState;
+};
 
-#define S390_FLIC_COMMON_CLASS(klass) \
-    OBJECT_CLASS_CHECK(S390FLICStateClass, (klass), TYPE_S390_FLIC_COMMON)
-#define S390_FLIC_COMMON_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(S390FLICStateClass, (obj), TYPE_S390_FLIC_COMMON)
 
-typedef struct S390FLICStateClass {
+struct S390FLICStateClass {
     DeviceClass parent_class;
 
     int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc,
@@ -72,16 +69,17 @@ typedef struct S390FLICStateClass {
                       uint16_t subchannel_nr, uint32_t io_int_parm,
                       uint32_t io_int_word);
     void (*inject_crw_mchk)(S390FLICState *fs);
-} S390FLICStateClass;
+};
 
 #define TYPE_KVM_S390_FLIC "s390-flic-kvm"
 typedef struct KVMS390FLICState KVMS390FLICState;
-#define KVM_S390_FLIC(obj) \
-    OBJECT_CHECK(KVMS390FLICState, (obj), TYPE_KVM_S390_FLIC)
+DECLARE_INSTANCE_CHECKER(KVMS390FLICState, KVM_S390_FLIC,
+                         TYPE_KVM_S390_FLIC)
 
 #define TYPE_QEMU_S390_FLIC "s390-flic-qemu"
-#define QEMU_S390_FLIC(obj) \
-    OBJECT_CHECK(QEMUS390FLICState, (obj), TYPE_QEMU_S390_FLIC)
+typedef struct QEMUS390FLICState QEMUS390FLICState;
+DECLARE_INSTANCE_CHECKER(QEMUS390FLICState, QEMU_S390_FLIC,
+                         TYPE_QEMU_S390_FLIC)
 
 #define SIC_IRQ_MODE_ALL 0
 #define SIC_IRQ_MODE_SINGLE 1
@@ -115,14 +113,14 @@ typedef struct QEMUS390FlicIO {
     QLIST_ENTRY(QEMUS390FlicIO) next;
 } QEMUS390FlicIO;
 
-typedef struct QEMUS390FLICState {
+struct QEMUS390FLICState {
     S390FLICState parent_obj;
     uint32_t pending;
     uint32_t service_param;
     uint8_t simm;
     uint8_t nimm;
     QLIST_HEAD(, QEMUS390FlicIO) io[8];
-} QEMUS390FLICState;
+};
 
 uint32_t qemu_s390_flic_dequeue_service(QEMUS390FLICState *flic);
 QEMUS390FlicIO *qemu_s390_flic_dequeue_io(QEMUS390FLICState *flic,
diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h
index a87ed2a0ab..e9f0f7e67c 100644
--- a/include/hw/s390x/sclp.h
+++ b/include/hw/s390x/sclp.h
@@ -16,6 +16,7 @@
 
 #include "hw/sysbus.h"
 #include "target/s390x/cpu-qom.h"
+#include "qom/object.h"
 
 #define SCLP_CMD_CODE_MASK                      0xffff00ff
 
@@ -181,22 +182,21 @@ typedef struct SCCB {
  } QEMU_PACKED SCCB;
 
 #define TYPE_SCLP "sclp"
-#define SCLP(obj) OBJECT_CHECK(SCLPDevice, (obj), TYPE_SCLP)
-#define SCLP_CLASS(oc) OBJECT_CLASS_CHECK(SCLPDeviceClass, (oc), TYPE_SCLP)
-#define SCLP_GET_CLASS(obj) OBJECT_GET_CLASS(SCLPDeviceClass, (obj), TYPE_SCLP)
+OBJECT_DECLARE_TYPE(SCLPDevice, SCLPDeviceClass,
+                    sclp, SCLP)
 
 struct SCLPEventFacility;
 
-typedef struct SCLPDevice {
+struct SCLPDevice {
     /* private */
     DeviceState parent_obj;
     struct SCLPEventFacility *event_facility;
     int increment_size;
 
     /* public */
-} SCLPDevice;
+};
 
-typedef struct SCLPDeviceClass {
+struct SCLPDeviceClass {
     /* private */
     DeviceClass parent_class;
     void (*read_SCP_info)(SCLPDevice *sclp, SCCB *sccb);
@@ -205,7 +205,7 @@ typedef struct SCLPDeviceClass {
     /* public */
     void (*execute)(SCLPDevice *sclp, SCCB *sccb, uint32_t code);
     void (*service_interrupt)(SCLPDevice *sclp, uint32_t sccb);
-} SCLPDeviceClass;
+};
 
 static inline int sccb_data_len(SCCB *sccb)
 {
diff --git a/include/hw/s390x/storage-attributes.h b/include/hw/s390x/storage-attributes.h
index 4f7c6c0877..efb28c48be 100644
--- a/include/hw/s390x/storage-attributes.h
+++ b/include/hw/s390x/storage-attributes.h
@@ -14,26 +14,25 @@
 
 #include "hw/qdev-core.h"
 #include "monitor/monitor.h"
+#include "qom/object.h"
 
 #define TYPE_S390_STATTRIB "s390-storage_attributes"
 #define TYPE_QEMU_S390_STATTRIB "s390-storage_attributes-qemu"
 #define TYPE_KVM_S390_STATTRIB "s390-storage_attributes-kvm"
 
-#define S390_STATTRIB(obj) \
-    OBJECT_CHECK(S390StAttribState, (obj), TYPE_S390_STATTRIB)
+typedef struct S390StAttribClass S390StAttribClass;
+typedef struct S390StAttribState S390StAttribState;
+DECLARE_OBJ_CHECKERS(S390StAttribState, S390StAttribClass,
+                     S390_STATTRIB, TYPE_S390_STATTRIB)
 
-typedef struct S390StAttribState {
+struct S390StAttribState {
     DeviceState parent_obj;
     uint64_t migration_cur_gfn;
     bool migration_enabled;
-} S390StAttribState;
+};
 
-#define S390_STATTRIB_CLASS(klass) \
-    OBJECT_CLASS_CHECK(S390StAttribClass, (klass), TYPE_S390_STATTRIB)
-#define S390_STATTRIB_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(S390StAttribClass, (obj), TYPE_S390_STATTRIB)
 
-typedef struct S390StAttribClass {
+struct S390StAttribClass {
     DeviceClass parent_class;
     /* Return value: < 0 on error, or new count */
     int (*get_stattr)(S390StAttribState *sa, uint64_t *start_gfn,
@@ -46,23 +45,25 @@ typedef struct S390StAttribClass {
     int (*set_migrationmode)(S390StAttribState *sa, bool value);
     int (*get_active)(S390StAttribState *sa);
     long long (*get_dirtycount)(S390StAttribState *sa);
-} S390StAttribClass;
+};
 
-#define QEMU_S390_STATTRIB(obj) \
-    OBJECT_CHECK(QEMUS390StAttribState, (obj), TYPE_QEMU_S390_STATTRIB)
+typedef struct QEMUS390StAttribState QEMUS390StAttribState;
+DECLARE_INSTANCE_CHECKER(QEMUS390StAttribState, QEMU_S390_STATTRIB,
+                         TYPE_QEMU_S390_STATTRIB)
 
-typedef struct QEMUS390StAttribState {
+struct QEMUS390StAttribState {
     S390StAttribState parent_obj;
-} QEMUS390StAttribState;
+};
 
-#define KVM_S390_STATTRIB(obj) \
-    OBJECT_CHECK(KVMS390StAttribState, (obj), TYPE_KVM_S390_STATTRIB)
+typedef struct KVMS390StAttribState KVMS390StAttribState;
+DECLARE_INSTANCE_CHECKER(KVMS390StAttribState, KVM_S390_STATTRIB,
+                         TYPE_KVM_S390_STATTRIB)
 
-typedef struct KVMS390StAttribState {
+struct KVMS390StAttribState {
     S390StAttribState parent_obj;
     uint64_t still_dirty;
     uint8_t *incoming_buffer;
-} KVMS390StAttribState;
+};
 
 void s390_stattrib_init(void);
 
diff --git a/include/hw/s390x/storage-keys.h b/include/hw/s390x/storage-keys.h
index 3f1ae7e778..40f042f54e 100644
--- a/include/hw/s390x/storage-keys.h
+++ b/include/hw/s390x/storage-keys.h
@@ -14,41 +14,41 @@
 
 #include "hw/qdev-core.h"
 #include "monitor/monitor.h"
+#include "qom/object.h"
 
 #define TYPE_S390_SKEYS "s390-skeys"
-#define S390_SKEYS(obj) \
-    OBJECT_CHECK(S390SKeysState, (obj), TYPE_S390_SKEYS)
+typedef struct S390SKeysClass S390SKeysClass;
+typedef struct S390SKeysState S390SKeysState;
+DECLARE_OBJ_CHECKERS(S390SKeysState, S390SKeysClass,
+                     S390_SKEYS, TYPE_S390_SKEYS)
 
-typedef struct S390SKeysState {
+struct S390SKeysState {
     DeviceState parent_obj;
     bool migration_enabled;
 
-} S390SKeysState;
+};
 
-#define S390_SKEYS_CLASS(klass) \
-    OBJECT_CLASS_CHECK(S390SKeysClass, (klass), TYPE_S390_SKEYS)
-#define S390_SKEYS_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(S390SKeysClass, (obj), TYPE_S390_SKEYS)
 
-typedef struct S390SKeysClass {
+struct S390SKeysClass {
     DeviceClass parent_class;
     int (*skeys_enabled)(S390SKeysState *ks);
     int (*get_skeys)(S390SKeysState *ks, uint64_t start_gfn, uint64_t count,
                      uint8_t *keys);
     int (*set_skeys)(S390SKeysState *ks, uint64_t start_gfn, uint64_t count,
                      uint8_t *keys);
-} S390SKeysClass;
+};
 
 #define TYPE_KVM_S390_SKEYS "s390-skeys-kvm"
 #define TYPE_QEMU_S390_SKEYS "s390-skeys-qemu"
-#define QEMU_S390_SKEYS(obj) \
-    OBJECT_CHECK(QEMUS390SKeysState, (obj), TYPE_QEMU_S390_SKEYS)
+typedef struct QEMUS390SKeysState QEMUS390SKeysState;
+DECLARE_INSTANCE_CHECKER(QEMUS390SKeysState, QEMU_S390_SKEYS,
+                         TYPE_QEMU_S390_SKEYS)
 
-typedef struct QEMUS390SKeysState {
+struct QEMUS390SKeysState {
     S390SKeysState parent_obj;
     uint8_t *keydata;
     uint32_t key_count;
-} QEMUS390SKeysState;
+};
 
 void s390_skeys_init(void);
 
diff --git a/include/hw/s390x/tod.h b/include/hw/s390x/tod.h
index 4251623f7f..c02498f65e 100644
--- a/include/hw/s390x/tod.h
+++ b/include/hw/s390x/tod.h
@@ -13,6 +13,7 @@
 
 #include "hw/qdev-core.h"
 #include "target/s390x/s390-tod.h"
+#include "qom/object.h"
 
 typedef struct S390TOD {
     uint8_t high;
@@ -20,15 +21,14 @@ typedef struct S390TOD {
 } S390TOD;
 
 #define TYPE_S390_TOD "s390-tod"
-#define S390_TOD(obj) OBJECT_CHECK(S390TODState, (obj), TYPE_S390_TOD)
-#define S390_TOD_CLASS(oc) OBJECT_CLASS_CHECK(S390TODClass, (oc), \
-                                              TYPE_S390_TOD)
-#define S390_TOD_GET_CLASS(obj) OBJECT_GET_CLASS(S390TODClass, (obj), \
-                                                 TYPE_S390_TOD)
+typedef struct S390TODClass S390TODClass;
+typedef struct S390TODState S390TODState;
+DECLARE_OBJ_CHECKERS(S390TODState, S390TODClass,
+                     S390_TOD, TYPE_S390_TOD)
 #define TYPE_KVM_S390_TOD TYPE_S390_TOD "-kvm"
 #define TYPE_QEMU_S390_TOD TYPE_S390_TOD "-qemu"
 
-typedef struct S390TODState {
+struct S390TODState {
     /* private */
     DeviceState parent_obj;
 
@@ -39,9 +39,9 @@ typedef struct S390TODState {
     S390TOD base;
     /* Used by KVM to remember if the TOD is stopped and base is valid. */
     bool stopped;
-} S390TODState;
+};
 
-typedef struct S390TODClass {
+struct S390TODClass {
     /* private */
     DeviceClass parent_class;
     void (*parent_realize)(DeviceState *dev, Error **errp);
@@ -49,7 +49,7 @@ typedef struct S390TODClass {
     /* public */
     void (*get)(const S390TODState *td, S390TOD *tod, Error **errp);
     void (*set)(S390TODState *td, const S390TOD *tod, Error **errp);
-} S390TODClass;
+};
 
 void s390_init_tod(void);
 S390TODState *s390_get_todstate(void);
diff --git a/include/hw/s390x/vfio-ccw.h b/include/hw/s390x/vfio-ccw.h
index ee5250d0d7..9c9c8944ad 100644
--- a/include/hw/s390x/vfio-ccw.h
+++ b/include/hw/s390x/vfio-ccw.h
@@ -17,12 +17,13 @@
 #include "hw/vfio/vfio-common.h"
 #include "hw/s390x/s390-ccw.h"
 #include "hw/s390x/ccw-device.h"
+#include "qom/object.h"
 
 #define TYPE_VFIO_CCW "vfio-ccw"
-#define VFIO_CCW(obj) \
-        OBJECT_CHECK(VFIOCCWDevice, (obj), TYPE_VFIO_CCW)
+typedef struct VFIOCCWDevice VFIOCCWDevice;
+DECLARE_INSTANCE_CHECKER(VFIOCCWDevice, VFIO_CCW,
+                         TYPE_VFIO_CCW)
 
 #define TYPE_VFIO_CCW "vfio-ccw"
-typedef struct VFIOCCWDevice VFIOCCWDevice;
 
 #endif
diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h
index 6ba47dac41..20800dbf5b 100644
--- a/include/hw/scsi/esp.h
+++ b/include/hw/scsi/esp.h
@@ -3,6 +3,7 @@
 
 #include "hw/scsi/scsi.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 /* esp.c */
 #define ESP_MAX_DEVS 7
@@ -65,9 +66,11 @@ struct ESPState {
 };
 
 #define TYPE_ESP "esp"
-#define ESP_STATE(obj) OBJECT_CHECK(SysBusESPState, (obj), TYPE_ESP)
+typedef struct SysBusESPState SysBusESPState;
+DECLARE_INSTANCE_CHECKER(SysBusESPState, ESP,
+                         TYPE_ESP)
 
-typedef struct {
+struct SysBusESPState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -76,7 +79,7 @@ typedef struct {
     MemoryRegion pdma;
     uint32_t it_shift;
     ESPState esp;
-} SysBusESPState;
+};
 
 #define ESP_TCLO   0x0
 #define ESP_TCMID  0x1
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index 2fc23e44ba..3818e3fa46 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -6,6 +6,7 @@
 #include "hw/qdev-core.h"
 #include "scsi/utils.h"
 #include "qemu/notify.h"
+#include "qom/object.h"
 
 #define MAX_SCSI_DEVS	255
 
@@ -49,14 +50,11 @@ struct SCSIRequest {
 };
 
 #define TYPE_SCSI_DEVICE "scsi-device"
-#define SCSI_DEVICE(obj) \
-     OBJECT_CHECK(SCSIDevice, (obj), TYPE_SCSI_DEVICE)
-#define SCSI_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(SCSIDeviceClass, (klass), TYPE_SCSI_DEVICE)
-#define SCSI_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(SCSIDeviceClass, (obj), TYPE_SCSI_DEVICE)
-
-typedef struct SCSIDeviceClass {
+typedef struct SCSIDeviceClass SCSIDeviceClass;
+DECLARE_OBJ_CHECKERS(SCSIDevice, SCSIDeviceClass,
+                     SCSI_DEVICE, TYPE_SCSI_DEVICE)
+
+struct SCSIDeviceClass {
     DeviceClass parent_class;
     void (*realize)(SCSIDevice *dev, Error **errp);
     void (*unrealize)(SCSIDevice *dev);
@@ -65,7 +63,7 @@ typedef struct SCSIDeviceClass {
     SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
                               uint8_t *buf, void *hba_private);
     void (*unit_attention_reported)(SCSIDevice *s);
-} SCSIDeviceClass;
+};
 
 struct SCSIDevice
 {
@@ -136,7 +134,8 @@ struct SCSIBusInfo {
 };
 
 #define TYPE_SCSI_BUS "SCSI"
-#define SCSI_BUS(obj) OBJECT_CHECK(SCSIBus, (obj), TYPE_SCSI_BUS)
+DECLARE_INSTANCE_CHECKER(SCSIBus, SCSI_BUS,
+                         TYPE_SCSI_BUS)
 
 struct SCSIBus {
     BusState qbus;
diff --git a/include/hw/sd/allwinner-sdhost.h b/include/hw/sd/allwinner-sdhost.h
index 839732ebf3..7bccc06d1c 100644
--- a/include/hw/sd/allwinner-sdhost.h
+++ b/include/hw/sd/allwinner-sdhost.h
@@ -45,19 +45,17 @@
  * @{
  */
 
-#define AW_SDHOST(obj) \
-    OBJECT_CHECK(AwSdHostState, (obj), TYPE_AW_SDHOST)
-#define AW_SDHOST_CLASS(klass) \
-     OBJECT_CLASS_CHECK(AwSdHostClass, (klass), TYPE_AW_SDHOST)
-#define AW_SDHOST_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(AwSdHostClass, (obj), TYPE_AW_SDHOST)
+typedef struct AwSdHostClass AwSdHostClass;
+typedef struct AwSdHostState AwSdHostState;
+DECLARE_OBJ_CHECKERS(AwSdHostState, AwSdHostClass,
+                     AW_SDHOST, TYPE_AW_SDHOST)
 
 /** @} */
 
 /**
  * Allwinner SD Host Controller object instance state.
  */
-typedef struct AwSdHostState {
+struct AwSdHostState {
     /*< private >*/
     SysBusDevice busdev;
     /*< public >*/
@@ -119,7 +117,7 @@ typedef struct AwSdHostState {
 
     /** @} */
 
-} AwSdHostState;
+};
 
 /**
  * Allwinner SD Host Controller class-level struct.
@@ -128,7 +126,7 @@ typedef struct AwSdHostState {
  * such that the generic code can use this struct to support
  * all devices.
  */
-typedef struct AwSdHostClass {
+struct AwSdHostClass {
     /*< private >*/
     SysBusDeviceClass parent_class;
     /*< public >*/
@@ -136,6 +134,6 @@ typedef struct AwSdHostClass {
     /** Maximum buffer size in bytes per DMA descriptor */
     size_t max_desc_size;
 
-} AwSdHostClass;
+};
 
 #endif /* HW_SD_ALLWINNER_SDHOST_H */
diff --git a/include/hw/sd/aspeed_sdhci.h b/include/hw/sd/aspeed_sdhci.h
index dffbb46946..783ccc2956 100644
--- a/include/hw/sd/aspeed_sdhci.h
+++ b/include/hw/sd/aspeed_sdhci.h
@@ -10,17 +10,19 @@
 #define ASPEED_SDHCI_H
 
 #include "hw/sd/sdhci.h"
+#include "qom/object.h"
 
 #define TYPE_ASPEED_SDHCI "aspeed.sdhci"
-#define ASPEED_SDHCI(obj) OBJECT_CHECK(AspeedSDHCIState, (obj), \
-                                       TYPE_ASPEED_SDHCI)
+typedef struct AspeedSDHCIState AspeedSDHCIState;
+DECLARE_INSTANCE_CHECKER(AspeedSDHCIState, ASPEED_SDHCI,
+                         TYPE_ASPEED_SDHCI)
 
 #define ASPEED_SDHCI_CAPABILITIES 0x01E80080
 #define ASPEED_SDHCI_NUM_SLOTS    2
 #define ASPEED_SDHCI_NUM_REGS     (ASPEED_SDHCI_REG_SIZE / sizeof(uint32_t))
 #define ASPEED_SDHCI_REG_SIZE     0x100
 
-typedef struct AspeedSDHCIState {
+struct AspeedSDHCIState {
     SysBusDevice parent;
 
     SDHCIState slots[ASPEED_SDHCI_NUM_SLOTS];
@@ -30,6 +32,6 @@ typedef struct AspeedSDHCIState {
     qemu_irq irq;
 
     uint32_t regs[ASPEED_SDHCI_NUM_REGS];
-} AspeedSDHCIState;
+};
 
 #endif /* ASPEED_SDHCI_H */
diff --git a/include/hw/sd/bcm2835_sdhost.h b/include/hw/sd/bcm2835_sdhost.h
index 7520dd6507..751ba531d6 100644
--- a/include/hw/sd/bcm2835_sdhost.h
+++ b/include/hw/sd/bcm2835_sdhost.h
@@ -16,14 +16,16 @@
 
 #include "hw/sysbus.h"
 #include "hw/sd/sd.h"
+#include "qom/object.h"
 
 #define TYPE_BCM2835_SDHOST "bcm2835-sdhost"
-#define BCM2835_SDHOST(obj) \
-        OBJECT_CHECK(BCM2835SDHostState, (obj), TYPE_BCM2835_SDHOST)
+typedef struct BCM2835SDHostState BCM2835SDHostState;
+DECLARE_INSTANCE_CHECKER(BCM2835SDHostState, BCM2835_SDHOST,
+                         TYPE_BCM2835_SDHOST)
 
 #define BCM2835_SDHOST_FIFO_LEN 16
 
-typedef struct {
+struct BCM2835SDHostState {
     SysBusDevice busdev;
     SDBus sdbus;
     MemoryRegion iomem;
@@ -43,6 +45,6 @@ typedef struct {
     uint32_t datacnt;
 
     qemu_irq irq;
-} BCM2835SDHostState;
+};
 
 #endif
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index ac02d61a7a..54f97a07cd 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -31,6 +31,7 @@
 #define HW_SD_H
 
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 #define OUT_OF_RANGE		(1 << 31)
 #define ADDRESS_ERROR		(1 << 30)
@@ -89,16 +90,13 @@ typedef struct {
 } SDRequest;
 
 typedef struct SDState SDState;
-typedef struct SDBus SDBus;
 
 #define TYPE_SD_CARD "sd-card"
-#define SD_CARD(obj) OBJECT_CHECK(SDState, (obj), TYPE_SD_CARD)
-#define SD_CARD_CLASS(klass) \
-    OBJECT_CLASS_CHECK(SDCardClass, (klass), TYPE_SD_CARD)
-#define SD_CARD_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(SDCardClass, (obj), TYPE_SD_CARD)
+typedef struct SDCardClass SDCardClass;
+DECLARE_OBJ_CHECKERS(SDState, SDCardClass,
+                     SD_CARD, TYPE_SD_CARD)
 
-typedef struct {
+struct SDCardClass {
     /*< private >*/
     DeviceClass parent_class;
     /*< public >*/
@@ -128,18 +126,17 @@ typedef struct {
     void (*enable)(SDState *sd, bool enable);
     bool (*get_inserted)(SDState *sd);
     bool (*get_readonly)(SDState *sd);
-} SDCardClass;
+};
 
 #define TYPE_SD_BUS "sd-bus"
-#define SD_BUS(obj) OBJECT_CHECK(SDBus, (obj), TYPE_SD_BUS)
-#define SD_BUS_CLASS(klass) OBJECT_CLASS_CHECK(SDBusClass, (klass), TYPE_SD_BUS)
-#define SD_BUS_GET_CLASS(obj) OBJECT_GET_CLASS(SDBusClass, (obj), TYPE_SD_BUS)
+OBJECT_DECLARE_TYPE(SDBus, SDBusClass,
+                    sd_bus, SD_BUS)
 
 struct SDBus {
     BusState qbus;
 };
 
-typedef struct {
+struct SDBusClass {
     /*< private >*/
     BusClass parent_class;
     /*< public >*/
@@ -149,7 +146,7 @@ typedef struct {
      */
     void (*set_inserted)(DeviceState *dev, bool inserted);
     void (*set_readonly)(DeviceState *dev, bool readonly);
-} SDBusClass;
+};
 
 /* Functions to be used by qdevified callers (working via
  * an SDBus rather than directly with SDState)
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 5d9275f3d6..01a64c5442 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -28,9 +28,10 @@
 #include "hw/pci/pci.h"
 #include "hw/sysbus.h"
 #include "hw/sd/sd.h"
+#include "qom/object.h"
 
 /* SD/MMC host controller state */
-typedef struct SDHCIState {
+struct SDHCIState {
     /*< private >*/
     union {
         PCIDevice pcidev;
@@ -98,7 +99,8 @@ typedef struct SDHCIState {
     uint8_t sd_spec_version;
     uint8_t uhs_mode;
     uint8_t vendor;        /* For vendor specific functionality */
-} SDHCIState;
+};
+typedef struct SDHCIState SDHCIState;
 
 #define SDHCI_VENDOR_NONE       0
 #define SDHCI_VENDOR_IMX        1
@@ -113,11 +115,12 @@ typedef struct SDHCIState {
 #define SDHCI_QUIRK_NO_BUSY_IRQ    BIT(14)
 
 #define TYPE_PCI_SDHCI "sdhci-pci"
-#define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI)
+DECLARE_INSTANCE_CHECKER(SDHCIState, PCI_SDHCI,
+                         TYPE_PCI_SDHCI)
 
 #define TYPE_SYSBUS_SDHCI "generic-sdhci"
-#define SYSBUS_SDHCI(obj)                               \
-     OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI)
+DECLARE_INSTANCE_CHECKER(SDHCIState, SYSBUS_SDHCI,
+                         TYPE_SYSBUS_SDHCI)
 
 #define TYPE_IMX_USDHC "imx-usdhc"
 
diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
index ac1d04ddc2..6387f2b612 100644
--- a/include/hw/southbridge/piix.h
+++ b/include/hw/southbridge/piix.h
@@ -13,6 +13,7 @@
 #define HW_SOUTHBRIDGE_PIIX_H
 
 #include "hw/pci/pci.h"
+#include "qom/object.h"
 
 #define TYPE_PIIX4_PM "PIIX4_PM"
 
@@ -35,7 +36,7 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 #define PIIX_NUM_PIC_IRQS       16      /* i8259 * 2 */
 #define PIIX_NUM_PIRQS          4ULL    /* PIRQ[A-D] */
 
-typedef struct PIIXState {
+struct PIIXState {
     PCIDevice dev;
 
     /*
@@ -62,11 +63,12 @@ typedef struct PIIXState {
 
     /* IO memory region for Reset Control Register (PIIX_RCR_IOPORT) */
     MemoryRegion rcr_mem;
-} PIIX3State;
+};
+typedef struct PIIXState PIIX3State;
 
 #define TYPE_PIIX3_PCI_DEVICE "pci-piix3"
-#define PIIX3_PCI_DEVICE(obj) \
-    OBJECT_CHECK(PIIX3State, (obj), TYPE_PIIX3_PCI_DEVICE)
+DECLARE_INSTANCE_CHECKER(PIIX3State, PIIX3_PCI_DEVICE,
+                         TYPE_PIIX3_PCI_DEVICE)
 
 extern PCIDevice *piix4_dev;
 
diff --git a/include/hw/sparc/sparc32_dma.h b/include/hw/sparc/sparc32_dma.h
index ab42c5421b..a402665a9c 100644
--- a/include/hw/sparc/sparc32_dma.h
+++ b/include/hw/sparc/sparc32_dma.h
@@ -4,14 +4,15 @@
 #include "hw/sysbus.h"
 #include "hw/scsi/esp.h"
 #include "hw/net/lance.h"
+#include "qom/object.h"
 
 #define DMA_REGS 4
 
 #define TYPE_SPARC32_DMA_DEVICE "sparc32-dma-device"
-#define SPARC32_DMA_DEVICE(obj) OBJECT_CHECK(DMADeviceState, (obj), \
-                                             TYPE_SPARC32_DMA_DEVICE)
-
 typedef struct DMADeviceState DMADeviceState;
+DECLARE_INSTANCE_CHECKER(DMADeviceState, SPARC32_DMA_DEVICE,
+                         TYPE_SPARC32_DMA_DEVICE)
+
 
 struct DMADeviceState {
     SysBusDevice parent_obj;
@@ -24,37 +25,40 @@ struct DMADeviceState {
 };
 
 #define TYPE_SPARC32_ESPDMA_DEVICE "sparc32-espdma"
-#define SPARC32_ESPDMA_DEVICE(obj) OBJECT_CHECK(ESPDMADeviceState, (obj), \
-                                                TYPE_SPARC32_ESPDMA_DEVICE)
+typedef struct ESPDMADeviceState ESPDMADeviceState;
+DECLARE_INSTANCE_CHECKER(ESPDMADeviceState, SPARC32_ESPDMA_DEVICE,
+                         TYPE_SPARC32_ESPDMA_DEVICE)
 
-typedef struct ESPDMADeviceState {
+struct ESPDMADeviceState {
     DMADeviceState parent_obj;
 
     SysBusESPState *esp;
-} ESPDMADeviceState;
+};
 
 #define TYPE_SPARC32_LEDMA_DEVICE "sparc32-ledma"
-#define SPARC32_LEDMA_DEVICE(obj) OBJECT_CHECK(LEDMADeviceState, (obj), \
-                                               TYPE_SPARC32_LEDMA_DEVICE)
+typedef struct LEDMADeviceState LEDMADeviceState;
+DECLARE_INSTANCE_CHECKER(LEDMADeviceState, SPARC32_LEDMA_DEVICE,
+                         TYPE_SPARC32_LEDMA_DEVICE)
 
-typedef struct LEDMADeviceState {
+struct LEDMADeviceState {
     DMADeviceState parent_obj;
 
     SysBusPCNetState *lance;
-} LEDMADeviceState;
+};
 
 #define TYPE_SPARC32_DMA "sparc32-dma"
-#define SPARC32_DMA(obj) OBJECT_CHECK(SPARC32DMAState, (obj), \
-                                      TYPE_SPARC32_DMA)
+typedef struct SPARC32DMAState SPARC32DMAState;
+DECLARE_INSTANCE_CHECKER(SPARC32DMAState, SPARC32_DMA,
+                         TYPE_SPARC32_DMA)
 
-typedef struct SPARC32DMAState {
+struct SPARC32DMAState {
     SysBusDevice parent_obj;
 
     MemoryRegion dmamem;
     MemoryRegion ledma_alias;
     ESPDMADeviceState *espdma;
     LEDMADeviceState *ledma;
-} SPARC32DMAState;
+};
 
 /* sparc32_dma.c */
 void ledma_memory_read(void *opaque, hwaddr addr,
diff --git a/include/hw/sparc/sun4m_iommu.h b/include/hw/sparc/sun4m_iommu.h
index 482266c6a7..4e2ab34cde 100644
--- a/include/hw/sparc/sun4m_iommu.h
+++ b/include/hw/sparc/sun4m_iommu.h
@@ -26,10 +26,11 @@
 #define SUN4M_IOMMU_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define IOMMU_NREGS         (4 * 4096 / 4)
 
-typedef struct IOMMUState {
+struct IOMMUState {
     SysBusDevice parent_obj;
 
     AddressSpace iommu_as;
@@ -40,10 +41,12 @@ typedef struct IOMMUState {
     hwaddr iostart;
     qemu_irq irq;
     uint32_t version;
-} IOMMUState;
+};
+typedef struct IOMMUState IOMMUState;
 
 #define TYPE_SUN4M_IOMMU "sun4m-iommu"
-#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU)
+DECLARE_INSTANCE_CHECKER(IOMMUState, SUN4M_IOMMU,
+                         TYPE_SUN4M_IOMMU)
 
 #define TYPE_SUN4M_IOMMU_MEMORY_REGION "sun4m-iommu-memory-region"
 
diff --git a/include/hw/sparc/sun4u_iommu.h b/include/hw/sparc/sun4u_iommu.h
index 5472d489cf..f94566a72c 100644
--- a/include/hw/sparc/sun4u_iommu.h
+++ b/include/hw/sparc/sun4u_iommu.h
@@ -28,10 +28,11 @@
 #define SUN4U_IOMMU_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define IOMMU_NREGS             3
 
-typedef struct IOMMUState {
+struct IOMMUState {
     SysBusDevice parent_obj;
 
     AddressSpace iommu_as;
@@ -39,10 +40,12 @@ typedef struct IOMMUState {
 
     MemoryRegion iomem;
     uint64_t regs[IOMMU_NREGS];
-} IOMMUState;
+};
+typedef struct IOMMUState IOMMUState;
 
 #define TYPE_SUN4U_IOMMU "sun4u-iommu"
-#define SUN4U_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4U_IOMMU)
+DECLARE_INSTANCE_CHECKER(IOMMUState, SUN4U_IOMMU,
+                         TYPE_SUN4U_IOMMU)
 
 #define TYPE_SUN4U_IOMMU_MEMORY_REGION "sun4u-iommu-memory-region"
 
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
index 6fbbb238f1..8e023d8ff6 100644
--- a/include/hw/ssi/aspeed_smc.h
+++ b/include/hw/ssi/aspeed_smc.h
@@ -27,6 +27,7 @@
 
 #include "hw/ssi/ssi.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 typedef struct AspeedSegments {
     hwaddr addr;
@@ -67,20 +68,19 @@ typedef struct AspeedSMCFlash {
 } AspeedSMCFlash;
 
 #define TYPE_ASPEED_SMC "aspeed.smc"
-#define ASPEED_SMC(obj) OBJECT_CHECK(AspeedSMCState, (obj), TYPE_ASPEED_SMC)
-#define ASPEED_SMC_CLASS(klass) \
-     OBJECT_CLASS_CHECK(AspeedSMCClass, (klass), TYPE_ASPEED_SMC)
-#define ASPEED_SMC_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(AspeedSMCClass, (obj), TYPE_ASPEED_SMC)
+typedef struct AspeedSMCClass AspeedSMCClass;
+typedef struct AspeedSMCState AspeedSMCState;
+DECLARE_OBJ_CHECKERS(AspeedSMCState, AspeedSMCClass,
+                     ASPEED_SMC, TYPE_ASPEED_SMC)
 
-typedef struct  AspeedSMCClass {
+struct AspeedSMCClass {
     SysBusDevice parent_obj;
     const AspeedSMCController *ctrl;
-}  AspeedSMCClass;
+};
 
 #define ASPEED_SMC_R_MAX        (0x100 / 4)
 
-typedef struct AspeedSMCState {
+struct AspeedSMCState {
     SysBusDevice parent_obj;
 
     const AspeedSMCController *ctrl;
@@ -117,6 +117,6 @@ typedef struct AspeedSMCState {
 
     uint8_t snoop_index;
     uint8_t snoop_dummies;
-} AspeedSMCState;
+};
 
 #endif /* ASPEED_SMC_H */
diff --git a/include/hw/ssi/imx_spi.h b/include/hw/ssi/imx_spi.h
index 7103953581..874fea492d 100644
--- a/include/hw/ssi/imx_spi.h
+++ b/include/hw/ssi/imx_spi.h
@@ -14,6 +14,7 @@
 #include "hw/ssi/ssi.h"
 #include "qemu/bitops.h"
 #include "qemu/fifo32.h"
+#include "qom/object.h"
 
 #define ECSPI_FIFO_SIZE 64
 
@@ -77,9 +78,11 @@
 #define EXTRACT(value, name) extract32(value, name##_SHIFT, name##_LENGTH)
 
 #define TYPE_IMX_SPI "imx.spi"
-#define IMX_SPI(obj) OBJECT_CHECK(IMXSPIState, (obj), TYPE_IMX_SPI)
+typedef struct IMXSPIState IMXSPIState;
+DECLARE_INSTANCE_CHECKER(IMXSPIState, IMX_SPI,
+                         TYPE_IMX_SPI)
 
-typedef struct IMXSPIState {
+struct IMXSPIState {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -98,6 +101,6 @@ typedef struct IMXSPIState {
     Fifo32 tx_fifo;
 
     int16_t burst_length;
-} IMXSPIState;
+};
 
 #endif /* IMX_SPI_H */
diff --git a/include/hw/ssi/mss-spi.h b/include/hw/ssi/mss-spi.h
index f0cf3243e0..7c16cf6b49 100644
--- a/include/hw/ssi/mss-spi.h
+++ b/include/hw/ssi/mss-spi.h
@@ -28,13 +28,16 @@
 #include "hw/sysbus.h"
 #include "hw/ssi/ssi.h"
 #include "qemu/fifo32.h"
+#include "qom/object.h"
 
 #define TYPE_MSS_SPI   "mss-spi"
-#define MSS_SPI(obj)   OBJECT_CHECK(MSSSpiState, (obj), TYPE_MSS_SPI)
+typedef struct MSSSpiState MSSSpiState;
+DECLARE_INSTANCE_CHECKER(MSSSpiState, MSS_SPI,
+                         TYPE_MSS_SPI)
 
 #define R_SPI_MAX             16
 
-typedef struct MSSSpiState {
+struct MSSSpiState {
     SysBusDevice parent_obj;
 
     MemoryRegion mmio;
@@ -53,6 +56,6 @@ typedef struct MSSSpiState {
     bool enabled;
 
     uint32_t regs[R_SPI_MAX];
-} MSSSpiState;
+};
 
 #endif /* HW_MSS_SPI_H */
diff --git a/include/hw/ssi/pl022.h b/include/hw/ssi/pl022.h
index a080519366..1f5da7cc44 100644
--- a/include/hw/ssi/pl022.h
+++ b/include/hw/ssi/pl022.h
@@ -22,11 +22,14 @@
 #define HW_SSI_PL022_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_PL022 "pl022"
-#define PL022(obj) OBJECT_CHECK(PL022State, (obj), TYPE_PL022)
+typedef struct PL022State PL022State;
+DECLARE_INSTANCE_CHECKER(PL022State, PL022,
+                         TYPE_PL022)
 
-typedef struct PL022State {
+struct PL022State {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -46,6 +49,6 @@ typedef struct PL022State {
     uint16_t rx_fifo[8];
     qemu_irq irq;
     SSIBus *ssi;
-} PL022State;
+};
 
 #endif
diff --git a/include/hw/ssi/ssi.h b/include/hw/ssi/ssi.h
index eac168aa1d..4fe1d85136 100644
--- a/include/hw/ssi/ssi.h
+++ b/include/hw/ssi/ssi.h
@@ -12,18 +12,13 @@
 #define QEMU_SSI_H
 
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
-typedef struct SSISlave SSISlave;
-typedef struct SSISlaveClass SSISlaveClass;
 typedef enum SSICSMode SSICSMode;
 
 #define TYPE_SSI_SLAVE "ssi-slave"
-#define SSI_SLAVE(obj) \
-     OBJECT_CHECK(SSISlave, (obj), TYPE_SSI_SLAVE)
-#define SSI_SLAVE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(SSISlaveClass, (klass), TYPE_SSI_SLAVE)
-#define SSI_SLAVE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(SSISlaveClass, (obj), TYPE_SSI_SLAVE)
+OBJECT_DECLARE_TYPE(SSISlave, SSISlaveClass,
+                    ssi_slave, SSI_SLAVE)
 
 #define SSI_GPIO_CS "ssi-gpio-cs"
 
diff --git a/include/hw/ssi/stm32f2xx_spi.h b/include/hw/ssi/stm32f2xx_spi.h
index e24b007abf..4bb36d04ed 100644
--- a/include/hw/ssi/stm32f2xx_spi.h
+++ b/include/hw/ssi/stm32f2xx_spi.h
@@ -27,6 +27,7 @@
 
 #include "hw/sysbus.h"
 #include "hw/ssi/ssi.h"
+#include "qom/object.h"
 
 #define STM_SPI_CR1     0x00
 #define STM_SPI_CR2     0x04
@@ -44,10 +45,11 @@
 #define STM_SPI_SR_RXNE   1
 
 #define TYPE_STM32F2XX_SPI "stm32f2xx-spi"
-#define STM32F2XX_SPI(obj) \
-    OBJECT_CHECK(STM32F2XXSPIState, (obj), TYPE_STM32F2XX_SPI)
+typedef struct STM32F2XXSPIState STM32F2XXSPIState;
+DECLARE_INSTANCE_CHECKER(STM32F2XXSPIState, STM32F2XX_SPI,
+                         TYPE_STM32F2XX_SPI)
 
-typedef struct {
+struct STM32F2XXSPIState {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -66,6 +68,6 @@ typedef struct {
 
     qemu_irq irq;
     SSIBus *ssi;
-} STM32F2XXSPIState;
+};
 
 #endif /* HW_STM32F2XX_SPI_H */
diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
index 6a39b55a7b..b1ab347617 100644
--- a/include/hw/ssi/xilinx_spips.h
+++ b/include/hw/ssi/xilinx_spips.h
@@ -29,6 +29,7 @@
 #include "qemu/fifo32.h"
 #include "hw/stream.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 typedef struct XilinxSPIPS XilinxSPIPS;
 
@@ -85,16 +86,17 @@ struct XilinxSPIPS {
     bool man_start_com;
 };
 
-typedef struct {
+struct XilinxQSPIPS {
     XilinxSPIPS parent_obj;
 
     uint8_t lqspi_buf[LQSPI_CACHE_SIZE];
     hwaddr lqspi_cached_addr;
     Error *migration_blocker;
     bool mmio_execution_enabled;
-} XilinxQSPIPS;
+};
+typedef struct XilinxQSPIPS XilinxQSPIPS;
 
-typedef struct {
+struct XlnxZynqMPQSPIPS {
     XilinxQSPIPS parent_obj;
 
     StreamSlave *dma;
@@ -117,32 +119,30 @@ typedef struct {
     bool man_start_com_g;
     uint32_t dma_burst_size;
     uint8_t dma_buf[QSPI_DMA_MAX_BURST_SIZE];
-} XlnxZynqMPQSPIPS;
+};
+typedef struct XlnxZynqMPQSPIPS XlnxZynqMPQSPIPS;
 
-typedef struct XilinxSPIPSClass {
+struct XilinxSPIPSClass {
     SysBusDeviceClass parent_class;
 
     const MemoryRegionOps *reg_ops;
 
     uint32_t rx_fifo_size;
     uint32_t tx_fifo_size;
-} XilinxSPIPSClass;
+};
+typedef struct XilinxSPIPSClass XilinxSPIPSClass;
 
 #define TYPE_XILINX_SPIPS "xlnx.ps7-spi"
 #define TYPE_XILINX_QSPIPS "xlnx.ps7-qspi"
 #define TYPE_XLNX_ZYNQMP_QSPIPS "xlnx.usmp-gqspi"
 
-#define XILINX_SPIPS(obj) \
-     OBJECT_CHECK(XilinxSPIPS, (obj), TYPE_XILINX_SPIPS)
-#define XILINX_SPIPS_CLASS(klass) \
-     OBJECT_CLASS_CHECK(XilinxSPIPSClass, (klass), TYPE_XILINX_SPIPS)
-#define XILINX_SPIPS_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(XilinxSPIPSClass, (obj), TYPE_XILINX_SPIPS)
+DECLARE_OBJ_CHECKERS(XilinxSPIPS, XilinxSPIPSClass,
+                     XILINX_SPIPS, TYPE_XILINX_SPIPS)
 
-#define XILINX_QSPIPS(obj) \
-     OBJECT_CHECK(XilinxQSPIPS, (obj), TYPE_XILINX_QSPIPS)
+DECLARE_INSTANCE_CHECKER(XilinxQSPIPS, XILINX_QSPIPS,
+                         TYPE_XILINX_QSPIPS)
 
-#define XLNX_ZYNQMP_QSPIPS(obj) \
-     OBJECT_CHECK(XlnxZynqMPQSPIPS, (obj), TYPE_XLNX_ZYNQMP_QSPIPS)
+DECLARE_INSTANCE_CHECKER(XlnxZynqMPQSPIPS, XLNX_ZYNQMP_QSPIPS,
+                         TYPE_XLNX_ZYNQMP_QSPIPS)
 
 #endif /* XILINX_SPIPS_H */
diff --git a/include/hw/stream.h b/include/hw/stream.h
index ed09e83683..e39d5a5b55 100644
--- a/include/hw/stream.h
+++ b/include/hw/stream.h
@@ -6,10 +6,9 @@
 /* stream slave. Used until qdev provides a generic way.  */
 #define TYPE_STREAM_SLAVE "stream-slave"
 
-#define STREAM_SLAVE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(StreamSlaveClass, (klass), TYPE_STREAM_SLAVE)
-#define STREAM_SLAVE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(StreamSlaveClass, (obj), TYPE_STREAM_SLAVE)
+typedef struct StreamSlaveClass StreamSlaveClass;
+DECLARE_CLASS_CHECKERS(StreamSlaveClass, STREAM_SLAVE,
+                       TYPE_STREAM_SLAVE)
 #define STREAM_SLAVE(obj) \
      INTERFACE_CHECK(StreamSlave, (obj), TYPE_STREAM_SLAVE)
 
@@ -17,7 +16,7 @@ typedef struct StreamSlave StreamSlave;
 
 typedef void (*StreamCanPushNotifyFn)(void *opaque);
 
-typedef struct StreamSlaveClass {
+struct StreamSlaveClass {
     InterfaceClass parent;
     /**
      * can push - determine if a stream slave is capable of accepting at least
@@ -42,7 +41,7 @@ typedef struct StreamSlaveClass {
      * @eop: End of packet flag
      */
     size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len, bool eop);
-} StreamSlaveClass;
+};
 
 size_t
 stream_push(StreamSlave *sink, uint8_t *buf, size_t len, bool eop);
diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h
index da9f85c58c..28a9b0f634 100644
--- a/include/hw/sysbus.h
+++ b/include/hw/sysbus.h
@@ -5,22 +5,19 @@
 
 #include "hw/qdev-core.h"
 #include "exec/memory.h"
+#include "qom/object.h"
 
 #define QDEV_MAX_MMIO 32
 #define QDEV_MAX_PIO 32
 
 #define TYPE_SYSTEM_BUS "System"
-#define SYSTEM_BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_SYSTEM_BUS)
+DECLARE_INSTANCE_CHECKER(BusState, SYSTEM_BUS,
+                         TYPE_SYSTEM_BUS)
 
-typedef struct SysBusDevice SysBusDevice;
 
 #define TYPE_SYS_BUS_DEVICE "sys-bus-device"
-#define SYS_BUS_DEVICE(obj) \
-     OBJECT_CHECK(SysBusDevice, (obj), TYPE_SYS_BUS_DEVICE)
-#define SYS_BUS_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(SysBusDeviceClass, (klass), TYPE_SYS_BUS_DEVICE)
-#define SYS_BUS_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(SysBusDeviceClass, (obj), TYPE_SYS_BUS_DEVICE)
+OBJECT_DECLARE_TYPE(SysBusDevice, SysBusDeviceClass,
+                    sys_bus_device, SYS_BUS_DEVICE)
 
 /**
  * SysBusDeviceClass:
@@ -31,7 +28,7 @@ typedef struct SysBusDevice SysBusDevice;
 
 #define SYSBUS_DEVICE_GPIO_IRQ "sysbus-irq"
 
-typedef struct SysBusDeviceClass {
+struct SysBusDeviceClass {
     /*< private >*/
     DeviceClass parent_class;
 
@@ -52,7 +49,7 @@ typedef struct SysBusDeviceClass {
      */
     char *(*explicit_ofw_unit_address)(const SysBusDevice *dev);
     void (*connect_irq_notifier)(SysBusDevice *dev, qemu_irq irq);
-} SysBusDeviceClass;
+};
 
 struct SysBusDevice {
     /*< private >*/
diff --git a/include/hw/timer/a9gtimer.h b/include/hw/timer/a9gtimer.h
index 81c4388784..f6fcc4bfc6 100644
--- a/include/hw/timer/a9gtimer.h
+++ b/include/hw/timer/a9gtimer.h
@@ -24,11 +24,14 @@
 #define A9GTIMER_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define A9_GTIMER_MAX_CPUS 4
 
 #define TYPE_A9_GTIMER "arm.cortex-a9-global-timer"
-#define A9_GTIMER(obj) OBJECT_CHECK(A9GTimerState, (obj), TYPE_A9_GTIMER)
+typedef struct A9GTimerState A9GTimerState;
+DECLARE_INSTANCE_CHECKER(A9GTimerState, A9_GTIMER,
+                         TYPE_A9_GTIMER)
 
 #define R_COUNTER_LO                0x00
 #define R_COUNTER_HI                0x04
@@ -55,7 +58,6 @@
 #define R_AUTO_INCREMENT            0x18
 
 typedef struct A9GTimerPerCPU A9GTimerPerCPU;
-typedef struct A9GTimerState A9GTimerState;
 
 struct A9GTimerPerCPU {
     A9GTimerState *parent;
diff --git a/include/hw/timer/allwinner-a10-pit.h b/include/hw/timer/allwinner-a10-pit.h
index 871c95b512..9638e3c84c 100644
--- a/include/hw/timer/allwinner-a10-pit.h
+++ b/include/hw/timer/allwinner-a10-pit.h
@@ -3,9 +3,12 @@
 
 #include "hw/ptimer.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_AW_A10_PIT "allwinner-A10-timer"
-#define AW_A10_PIT(obj) OBJECT_CHECK(AwA10PITState, (obj), TYPE_AW_A10_PIT)
+typedef struct AwA10PITState AwA10PITState;
+DECLARE_INSTANCE_CHECKER(AwA10PITState, AW_A10_PIT,
+                         TYPE_AW_A10_PIT)
 
 #define AW_A10_PIT_TIMER_NR    6
 #define AW_A10_PIT_TIMER_IRQ   0x1
@@ -36,7 +39,6 @@
 
 #define AW_A10_PIT_DEFAULT_CLOCK   0x4
 
-typedef struct AwA10PITState AwA10PITState;
 
 typedef struct AwA10TimerContext {
     AwA10PITState *container;
diff --git a/include/hw/timer/arm_mptimer.h b/include/hw/timer/arm_mptimer.h
index c46d8d2309..47d5e51686 100644
--- a/include/hw/timer/arm_mptimer.h
+++ b/include/hw/timer/arm_mptimer.h
@@ -22,6 +22,7 @@
 #define HW_TIMER_ARM_MPTIMER_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define ARM_MPTIMER_MAX_CPUS 4
 
@@ -35,10 +36,11 @@ typedef struct {
 } TimerBlock;
 
 #define TYPE_ARM_MPTIMER "arm_mptimer"
-#define ARM_MPTIMER(obj) \
-    OBJECT_CHECK(ARMMPTimerState, (obj), TYPE_ARM_MPTIMER)
+typedef struct ARMMPTimerState ARMMPTimerState;
+DECLARE_INSTANCE_CHECKER(ARMMPTimerState, ARM_MPTIMER,
+                         TYPE_ARM_MPTIMER)
 
-typedef struct {
+struct ARMMPTimerState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -46,6 +48,6 @@ typedef struct {
     uint32_t num_cpu;
     TimerBlock timerblock[ARM_MPTIMER_MAX_CPUS];
     MemoryRegion iomem;
-} ARMMPTimerState;
+};
 
 #endif
diff --git a/include/hw/timer/armv7m_systick.h b/include/hw/timer/armv7m_systick.h
index 25e5ceacc8..b605688fee 100644
--- a/include/hw/timer/armv7m_systick.h
+++ b/include/hw/timer/armv7m_systick.h
@@ -13,12 +13,15 @@
 #define HW_TIMER_ARMV7M_SYSTICK_H
 
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_SYSTICK "armv7m_systick"
 
-#define SYSTICK(obj) OBJECT_CHECK(SysTickState, (obj), TYPE_SYSTICK)
+typedef struct SysTickState SysTickState;
+DECLARE_INSTANCE_CHECKER(SysTickState, SYSTICK,
+                         TYPE_SYSTICK)
 
-typedef struct SysTickState {
+struct SysTickState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -29,7 +32,7 @@ typedef struct SysTickState {
     QEMUTimer *timer;
     MemoryRegion iomem;
     qemu_irq irq;
-} SysTickState;
+};
 
 /*
  * Multiplication factor to convert from system clock ticks to qemu timer
diff --git a/include/hw/timer/aspeed_timer.h b/include/hw/timer/aspeed_timer.h
index d7c7d8ad28..4c76f955c9 100644
--- a/include/hw/timer/aspeed_timer.h
+++ b/include/hw/timer/aspeed_timer.h
@@ -24,10 +24,13 @@
 
 #include "qemu/timer.h"
 #include "hw/misc/aspeed_scu.h"
+#include "qom/object.h"
 
-#define ASPEED_TIMER(obj) \
-    OBJECT_CHECK(AspeedTimerCtrlState, (obj), TYPE_ASPEED_TIMER)
 #define TYPE_ASPEED_TIMER "aspeed.timer"
+typedef struct AspeedTimerClass AspeedTimerClass;
+typedef struct AspeedTimerCtrlState AspeedTimerCtrlState;
+DECLARE_OBJ_CHECKERS(AspeedTimerCtrlState, AspeedTimerClass,
+                     ASPEED_TIMER, TYPE_ASPEED_TIMER)
 #define TYPE_ASPEED_2400_TIMER TYPE_ASPEED_TIMER "-ast2400"
 #define TYPE_ASPEED_2500_TIMER TYPE_ASPEED_TIMER "-ast2500"
 #define TYPE_ASPEED_2600_TIMER TYPE_ASPEED_TIMER "-ast2600"
@@ -50,7 +53,7 @@ typedef struct AspeedTimer {
     uint64_t start;
 } AspeedTimer;
 
-typedef struct AspeedTimerCtrlState {
+struct AspeedTimerCtrlState {
     /*< private >*/
     SysBusDevice parent;
 
@@ -64,18 +67,14 @@ typedef struct AspeedTimerCtrlState {
     AspeedTimer timers[ASPEED_TIMER_NR_TIMERS];
 
     AspeedSCUState *scu;
-} AspeedTimerCtrlState;
+};
 
-#define ASPEED_TIMER_CLASS(klass) \
-     OBJECT_CLASS_CHECK(AspeedTimerClass, (klass), TYPE_ASPEED_TIMER)
-#define ASPEED_TIMER_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(AspeedTimerClass, (obj), TYPE_ASPEED_TIMER)
 
-typedef struct AspeedTimerClass {
+struct AspeedTimerClass {
     SysBusDeviceClass parent_class;
 
     uint64_t (*read)(AspeedTimerCtrlState *s, hwaddr offset);
     void (*write)(AspeedTimerCtrlState *s, hwaddr offset, uint64_t value);
-} AspeedTimerClass;
+};
 
 #endif /* ASPEED_TIMER_H */
diff --git a/include/hw/timer/avr_timer16.h b/include/hw/timer/avr_timer16.h
index 982019d242..d454bb31cb 100644
--- a/include/hw/timer/avr_timer16.h
+++ b/include/hw/timer/avr_timer16.h
@@ -31,6 +31,7 @@
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "hw/hw.h"
+#include "qom/object.h"
 
 enum NextInterrupt {
     OVERFLOW,
@@ -41,10 +42,11 @@ enum NextInterrupt {
 };
 
 #define TYPE_AVR_TIMER16 "avr-timer16"
-#define AVR_TIMER16(obj) \
-    OBJECT_CHECK(AVRTimer16State, (obj), TYPE_AVR_TIMER16)
+typedef struct AVRTimer16State AVRTimer16State;
+DECLARE_INSTANCE_CHECKER(AVRTimer16State, AVR_TIMER16,
+                         TYPE_AVR_TIMER16)
 
-typedef struct AVRTimer16State {
+struct AVRTimer16State {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -89,6 +91,6 @@ typedef struct AVRTimer16State {
     uint64_t period_ns;
     uint64_t reset_time_ns;
     enum NextInterrupt next_interrupt;
-} AVRTimer16State;
+};
 
 #endif /* HW_TIMER_AVR_TIMER16_H */
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
index c0bc5c8127..64166bd712 100644
--- a/include/hw/timer/bcm2835_systmr.h
+++ b/include/hw/timer/bcm2835_systmr.h
@@ -11,12 +11,14 @@
 
 #include "hw/sysbus.h"
 #include "hw/irq.h"
+#include "qom/object.h"
 
 #define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
-#define BCM2835_SYSTIMER(obj) \
-    OBJECT_CHECK(BCM2835SystemTimerState, (obj), TYPE_BCM2835_SYSTIMER)
+typedef struct BCM2835SystemTimerState BCM2835SystemTimerState;
+DECLARE_INSTANCE_CHECKER(BCM2835SystemTimerState, BCM2835_SYSTIMER,
+                         TYPE_BCM2835_SYSTIMER)
 
-typedef struct {
+struct BCM2835SystemTimerState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -28,6 +30,6 @@ typedef struct {
         uint32_t status;
         uint32_t compare[4];
     } reg;
-} BCM2835SystemTimerState;
+};
 
 #endif
diff --git a/include/hw/timer/cmsdk-apb-dualtimer.h b/include/hw/timer/cmsdk-apb-dualtimer.h
index 9843a9dbb1..7a5b9df5e5 100644
--- a/include/hw/timer/cmsdk-apb-dualtimer.h
+++ b/include/hw/timer/cmsdk-apb-dualtimer.h
@@ -28,12 +28,13 @@
 
 #include "hw/sysbus.h"
 #include "hw/ptimer.h"
+#include "qom/object.h"
 
 #define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer"
-#define CMSDK_APB_DUALTIMER(obj) OBJECT_CHECK(CMSDKAPBDualTimer, (obj), \
-                                              TYPE_CMSDK_APB_DUALTIMER)
-
 typedef struct CMSDKAPBDualTimer CMSDKAPBDualTimer;
+DECLARE_INSTANCE_CHECKER(CMSDKAPBDualTimer, CMSDK_APB_DUALTIMER,
+                         TYPE_CMSDK_APB_DUALTIMER)
+
 
 /* One of the two identical timer modules in the dual-timer module */
 typedef struct CMSDKAPBDualTimerModule {
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
index f24bda6a46..0912bc0f3c 100644
--- a/include/hw/timer/cmsdk-apb-timer.h
+++ b/include/hw/timer/cmsdk-apb-timer.h
@@ -15,12 +15,14 @@
 #include "hw/qdev-properties.h"
 #include "hw/sysbus.h"
 #include "hw/ptimer.h"
+#include "qom/object.h"
 
 #define TYPE_CMSDK_APB_TIMER "cmsdk-apb-timer"
-#define CMSDK_APB_TIMER(obj) OBJECT_CHECK(CMSDKAPBTIMER, (obj), \
-                                         TYPE_CMSDK_APB_TIMER)
+typedef struct CMSDKAPBTIMER CMSDKAPBTIMER;
+DECLARE_INSTANCE_CHECKER(CMSDKAPBTIMER, CMSDK_APB_TIMER,
+                         TYPE_CMSDK_APB_TIMER)
 
-typedef struct {
+struct CMSDKAPBTIMER {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -34,7 +36,7 @@ typedef struct {
     uint32_t value;
     uint32_t reload;
     uint32_t intstatus;
-} CMSDKAPBTIMER;
+};
 
 /**
  * cmsdk_apb_timer_create - convenience function to create TYPE_CMSDK_APB_TIMER
diff --git a/include/hw/timer/digic-timer.h b/include/hw/timer/digic-timer.h
index d9e67fe291..84a0ef473a 100644
--- a/include/hw/timer/digic-timer.h
+++ b/include/hw/timer/digic-timer.h
@@ -20,9 +20,12 @@
 
 #include "hw/sysbus.h"
 #include "hw/ptimer.h"
+#include "qom/object.h"
 
 #define TYPE_DIGIC_TIMER "digic-timer"
-#define DIGIC_TIMER(obj) OBJECT_CHECK(DigicTimerState, (obj), TYPE_DIGIC_TIMER)
+typedef struct DigicTimerState DigicTimerState;
+DECLARE_INSTANCE_CHECKER(DigicTimerState, DIGIC_TIMER,
+                         TYPE_DIGIC_TIMER)
 
 #define DIGIC_TIMER_CONTROL 0x00
 #define DIGIC_TIMER_CONTROL_RST 0x80000000
@@ -30,7 +33,7 @@
 #define DIGIC_TIMER_RELVALUE 0x08
 #define DIGIC_TIMER_VALUE 0x0c
 
-typedef struct DigicTimerState {
+struct DigicTimerState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -40,6 +43,6 @@ typedef struct DigicTimerState {
 
     uint32_t control;
     uint32_t relvalue;
-} DigicTimerState;
+};
 
 #endif /* HW_TIMER_DIGIC_TIMER_H */
diff --git a/include/hw/timer/i8254.h b/include/hw/timer/i8254.h
index 206b8f8464..1a522a2457 100644
--- a/include/hw/timer/i8254.h
+++ b/include/hw/timer/i8254.h
@@ -28,6 +28,7 @@
 #include "hw/qdev-properties.h"
 #include "hw/isa/isa.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 #define PIT_FREQ 1193182
 
@@ -41,12 +42,8 @@ typedef struct PITChannelInfo {
 #define TYPE_PIT_COMMON "pit-common"
 typedef struct PITCommonState PITCommonState;
 typedef struct PITCommonClass PITCommonClass;
-#define PIT_COMMON(obj) \
-     OBJECT_CHECK(PITCommonState, (obj), TYPE_PIT_COMMON)
-#define PIT_COMMON_CLASS(klass) \
-     OBJECT_CLASS_CHECK(PITCommonClass, (klass), TYPE_PIT_COMMON)
-#define PIT_COMMON_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PITCommonClass, (obj), TYPE_PIT_COMMON)
+DECLARE_OBJ_CHECKERS(PITCommonState, PITCommonClass,
+                     PIT_COMMON, TYPE_PIT_COMMON)
 
 #define TYPE_I8254 "isa-pit"
 #define TYPE_KVM_I8254 "kvm-pit"
diff --git a/include/hw/timer/imx_epit.h b/include/hw/timer/imx_epit.h
index 0730ac35e6..39bcf81331 100644
--- a/include/hw/timer/imx_epit.h
+++ b/include/hw/timer/imx_epit.h
@@ -32,6 +32,7 @@
 #include "hw/sysbus.h"
 #include "hw/ptimer.h"
 #include "hw/misc/imx_ccm.h"
+#include "qom/object.h"
 
 /*
  * EPIT: Enhanced periodic interrupt timer
@@ -55,9 +56,11 @@
 #define EPIT_TIMER_MAX  0XFFFFFFFFUL
 
 #define TYPE_IMX_EPIT "imx.epit"
-#define IMX_EPIT(obj) OBJECT_CHECK(IMXEPITState, (obj), TYPE_IMX_EPIT)
+typedef struct IMXEPITState IMXEPITState;
+DECLARE_INSTANCE_CHECKER(IMXEPITState, IMX_EPIT,
+                         TYPE_IMX_EPIT)
 
-typedef struct IMXEPITState{
+struct IMXEPITState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -75,6 +78,6 @@ typedef struct IMXEPITState{
 
     uint32_t freq;
     qemu_irq irq;
-} IMXEPITState;
+};
 
 #endif /* IMX_EPIT_H */
diff --git a/include/hw/timer/imx_gpt.h b/include/hw/timer/imx_gpt.h
index 20ccb327c4..ff5c8a351a 100644
--- a/include/hw/timer/imx_gpt.h
+++ b/include/hw/timer/imx_gpt.h
@@ -32,6 +32,7 @@
 #include "hw/sysbus.h"
 #include "hw/ptimer.h"
 #include "hw/misc/imx_ccm.h"
+#include "qom/object.h"
 
 /*
  * GPT : General purpose timer
@@ -81,9 +82,11 @@
 
 #define TYPE_IMX_GPT TYPE_IMX25_GPT
 
-#define IMX_GPT(obj) OBJECT_CHECK(IMXGPTState, (obj), TYPE_IMX_GPT)
+typedef struct IMXGPTState IMXGPTState;
+DECLARE_INSTANCE_CHECKER(IMXGPTState, IMX_GPT,
+                         TYPE_IMX_GPT)
 
-typedef struct IMXGPTState{
+struct IMXGPTState {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -111,6 +114,6 @@ typedef struct IMXGPTState{
     qemu_irq irq;
 
     const IMXClk *clocks;
-} IMXGPTState;
+};
 
 #endif /* IMX_GPT_H */
diff --git a/include/hw/timer/mss-timer.h b/include/hw/timer/mss-timer.h
index e5a784b27e..d207bae2c0 100644
--- a/include/hw/timer/mss-timer.h
+++ b/include/hw/timer/mss-timer.h
@@ -27,10 +27,12 @@
 
 #include "hw/sysbus.h"
 #include "hw/ptimer.h"
+#include "qom/object.h"
 
 #define TYPE_MSS_TIMER     "mss-timer"
-#define MSS_TIMER(obj)     OBJECT_CHECK(MSSTimerState, \
-                              (obj), TYPE_MSS_TIMER)
+typedef struct MSSTimerState MSSTimerState;
+DECLARE_INSTANCE_CHECKER(MSSTimerState, MSS_TIMER,
+                         TYPE_MSS_TIMER)
 
 /*
  * There are two 32-bit down counting timers.
@@ -52,12 +54,12 @@ struct Msf2Timer {
     qemu_irq irq;
 };
 
-typedef struct MSSTimerState {
+struct MSSTimerState {
     SysBusDevice parent_obj;
 
     MemoryRegion mmio;
     uint32_t freq_hz;
     struct Msf2Timer timers[NUM_TIMERS];
-} MSSTimerState;
+};
 
 #endif /* HW_MSS_TIMER_H */
diff --git a/include/hw/timer/nrf51_timer.h b/include/hw/timer/nrf51_timer.h
index eb6815f21d..4261a03b95 100644
--- a/include/hw/timer/nrf51_timer.h
+++ b/include/hw/timer/nrf51_timer.h
@@ -15,8 +15,11 @@
 
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
+#include "qom/object.h"
 #define TYPE_NRF51_TIMER "nrf51_soc.timer"
-#define NRF51_TIMER(obj) OBJECT_CHECK(NRF51TimerState, (obj), TYPE_NRF51_TIMER)
+typedef struct NRF51TimerState NRF51TimerState;
+DECLARE_INSTANCE_CHECKER(NRF51TimerState, NRF51_TIMER,
+                         TYPE_NRF51_TIMER)
 
 #define NRF51_TIMER_REG_COUNT 4
 
@@ -53,7 +56,7 @@
 #define NRF51_TIMER_REG_CC0 0x540
 #define NRF51_TIMER_REG_CC3 0x54C
 
-typedef struct NRF51TimerState {
+struct NRF51TimerState {
     SysBusDevice parent_obj;
 
     MemoryRegion iomem;
@@ -75,7 +78,7 @@ typedef struct NRF51TimerState {
     uint32_t bitmode;
     uint32_t prescaler;
 
-} NRF51TimerState;
+};
 
 
 #endif
diff --git a/include/hw/timer/renesas_cmt.h b/include/hw/timer/renesas_cmt.h
index e28a15cb38..1c0b65c1d5 100644
--- a/include/hw/timer/renesas_cmt.h
+++ b/include/hw/timer/renesas_cmt.h
@@ -11,16 +11,19 @@
 
 #include "qemu/timer.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_RENESAS_CMT "renesas-cmt"
-#define RCMT(obj) OBJECT_CHECK(RCMTState, (obj), TYPE_RENESAS_CMT)
+typedef struct RCMTState RCMTState;
+DECLARE_INSTANCE_CHECKER(RCMTState, RCMT,
+                         TYPE_RENESAS_CMT)
 
 enum {
     CMT_CH = 2,
     CMT_NR_IRQ = 1 * CMT_CH
 };
 
-typedef struct RCMTState {
+struct RCMTState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -35,6 +38,6 @@ typedef struct RCMTState {
     int64_t tick[CMT_CH];
     qemu_irq cmi[CMT_CH];
     QEMUTimer timer[CMT_CH];
-} RCMTState;
+};
 
 #endif
diff --git a/include/hw/timer/renesas_tmr.h b/include/hw/timer/renesas_tmr.h
index cf3baa7a28..caf7eec0dc 100644
--- a/include/hw/timer/renesas_tmr.h
+++ b/include/hw/timer/renesas_tmr.h
@@ -11,9 +11,12 @@
 
 #include "qemu/timer.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_RENESAS_TMR "renesas-tmr"
-#define RTMR(obj) OBJECT_CHECK(RTMRState, (obj), TYPE_RENESAS_TMR)
+typedef struct RTMRState RTMRState;
+DECLARE_INSTANCE_CHECKER(RTMRState, RTMR,
+                         TYPE_RENESAS_TMR)
 
 enum timer_event {
     cmia = 0,
@@ -28,7 +31,7 @@ enum {
     TMR_NR_IRQ = 3 * TMR_CH
 };
 
-typedef struct RTMRState {
+struct RTMRState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -50,6 +53,6 @@ typedef struct RTMRState {
     qemu_irq cmib[TMR_CH];
     qemu_irq ovi[TMR_CH];
     QEMUTimer timer[TMR_CH];
-} RTMRState;
+};
 
 #endif
diff --git a/include/hw/timer/stm32f2xx_timer.h b/include/hw/timer/stm32f2xx_timer.h
index a96bc08b1b..90f40f1746 100644
--- a/include/hw/timer/stm32f2xx_timer.h
+++ b/include/hw/timer/stm32f2xx_timer.h
@@ -27,6 +27,7 @@
 
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
+#include "qom/object.h"
 
 #define TIM_CR1      0x00
 #define TIM_CR2      0x04
@@ -61,10 +62,11 @@
 #define TIM_DIER_UIE  1
 
 #define TYPE_STM32F2XX_TIMER "stm32f2xx-timer"
-#define STM32F2XXTIMER(obj) OBJECT_CHECK(STM32F2XXTimerState, \
-                            (obj), TYPE_STM32F2XX_TIMER)
+typedef struct STM32F2XXTimerState STM32F2XXTimerState;
+DECLARE_INSTANCE_CHECKER(STM32F2XXTimerState, STM32F2XXTIMER,
+                         TYPE_STM32F2XX_TIMER)
 
-typedef struct STM32F2XXTimerState {
+struct STM32F2XXTimerState {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -95,6 +97,6 @@ typedef struct STM32F2XXTimerState {
     uint32_t tim_dcr;
     uint32_t tim_dmar;
     uint32_t tim_or;
-} STM32F2XXTimerState;
+};
 
 #endif /* HW_STM32F2XX_TIMER_H */
diff --git a/include/hw/usb.h b/include/hw/usb.h
index e29a37635b..5783635491 100644
--- a/include/hw/usb.h
+++ b/include/hw/usb.h
@@ -29,6 +29,7 @@
 #include "hw/qdev-core.h"
 #include "qemu/iov.h"
 #include "qemu/queue.h"
+#include "qom/object.h"
 
 /* Constants related to the USB / PCI interaction */
 #define USB_SBRN    0x60 /* Serial Bus Release Number Register */
@@ -264,17 +265,14 @@ struct USBDevice {
 };
 
 #define TYPE_USB_DEVICE "usb-device"
-#define USB_DEVICE(obj) \
-     OBJECT_CHECK(USBDevice, (obj), TYPE_USB_DEVICE)
-#define USB_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(USBDeviceClass, (klass), TYPE_USB_DEVICE)
-#define USB_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(USBDeviceClass, (obj), TYPE_USB_DEVICE)
+typedef struct USBDeviceClass USBDeviceClass;
+DECLARE_OBJ_CHECKERS(USBDevice, USBDeviceClass,
+                     USB_DEVICE, TYPE_USB_DEVICE)
 
 typedef void (*USBDeviceRealize)(USBDevice *dev, Error **errp);
 typedef void (*USBDeviceUnrealize)(USBDevice *dev);
 
-typedef struct USBDeviceClass {
+struct USBDeviceClass {
     DeviceClass parent_class;
 
     USBDeviceRealize realize;
@@ -346,7 +344,7 @@ typedef struct USBDeviceClass {
     const char *product_desc;
     const USBDesc *usb_desc;
     bool attached_settable;
-} USBDeviceClass;
+};
 
 typedef struct USBPortOps {
     void (*attach)(USBPort *port);
@@ -477,7 +475,8 @@ bool usb_host_dev_is_scsi_storage(USBDevice *usbdev);
 /* usb-bus.c */
 
 #define TYPE_USB_BUS "usb-bus"
-#define USB_BUS(obj) OBJECT_CHECK(USBBus, (obj), TYPE_USB_BUS)
+DECLARE_INSTANCE_CHECKER(USBBus, USB_BUS,
+                         TYPE_USB_BUS)
 
 struct USBBus {
     BusState qbus;
diff --git a/include/hw/usb/chipidea.h b/include/hw/usb/chipidea.h
index 1ec2e9dbda..f0303b8721 100644
--- a/include/hw/usb/chipidea.h
+++ b/include/hw/usb/chipidea.h
@@ -2,15 +2,18 @@
 #define CHIPIDEA_H
 
 #include "hw/usb/hcd-ehci.h"
+#include "qom/object.h"
 
-typedef struct ChipideaState {
+struct ChipideaState {
     /*< private >*/
     EHCISysBusState parent_obj;
 
     MemoryRegion iomem[3];
-} ChipideaState;
+};
+typedef struct ChipideaState ChipideaState;
 
 #define TYPE_CHIPIDEA "usb-chipidea"
-#define CHIPIDEA(obj) OBJECT_CHECK(ChipideaState, (obj), TYPE_CHIPIDEA)
+DECLARE_INSTANCE_CHECKER(ChipideaState, CHIPIDEA,
+                         TYPE_CHIPIDEA)
 
 #endif /* CHIPIDEA_H */
diff --git a/include/hw/usb/imx-usb-phy.h b/include/hw/usb/imx-usb-phy.h
index 07f0235d10..f7f92fc462 100644
--- a/include/hw/usb/imx-usb-phy.h
+++ b/include/hw/usb/imx-usb-phy.h
@@ -3,6 +3,7 @@
 
 #include "hw/sysbus.h"
 #include "qemu/bitops.h"
+#include "qom/object.h"
 
 enum IMXUsbPhyRegisters {
     USBPHY_PWD,
@@ -38,9 +39,11 @@ enum IMXUsbPhyRegisters {
 #define USBPHY_CTRL_SFTRST BIT(31)
 
 #define TYPE_IMX_USBPHY "imx.usbphy"
-#define IMX_USBPHY(obj) OBJECT_CHECK(IMXUSBPHYState, (obj), TYPE_IMX_USBPHY)
+typedef struct IMXUSBPHYState IMXUSBPHYState;
+DECLARE_INSTANCE_CHECKER(IMXUSBPHYState, IMX_USBPHY,
+                         TYPE_IMX_USBPHY)
 
-typedef struct IMXUSBPHYState {
+struct IMXUSBPHYState {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -48,6 +51,6 @@ typedef struct IMXUSBPHYState {
     MemoryRegion iomem;
 
     uint32_t usbphy[USBPHY_MAX];
-} IMXUSBPHYState;
+};
 
 #endif /* IMX_USB_PHY_H */
diff --git a/include/hw/vfio/vfio-amd-xgbe.h b/include/hw/vfio/vfio-amd-xgbe.h
index 9fff65e99d..a894546c02 100644
--- a/include/hw/vfio/vfio-amd-xgbe.h
+++ b/include/hw/vfio/vfio-amd-xgbe.h
@@ -15,6 +15,7 @@
 #define HW_VFIO_VFIO_AMD_XGBE_H
 
 #include "hw/vfio/vfio-platform.h"
+#include "qom/object.h"
 
 #define TYPE_VFIO_AMD_XGBE "vfio-amd-xgbe"
 
@@ -39,13 +40,7 @@ struct VFIOAmdXgbeDeviceClass {
 
 typedef struct VFIOAmdXgbeDeviceClass VFIOAmdXgbeDeviceClass;
 
-#define VFIO_AMD_XGBE_DEVICE(obj) \
-     OBJECT_CHECK(VFIOAmdXgbeDevice, (obj), TYPE_VFIO_AMD_XGBE)
-#define VFIO_AMD_XGBE_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(VFIOAmdXgbeDeviceClass, (klass), \
-                        TYPE_VFIO_AMD_XGBE)
-#define VFIO_AMD_XGBE_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(VFIOAmdXgbeDeviceClass, (obj), \
-                      TYPE_VFIO_AMD_XGBE)
+DECLARE_OBJ_CHECKERS(VFIOAmdXgbeDevice, VFIOAmdXgbeDeviceClass,
+                     VFIO_AMD_XGBE_DEVICE, TYPE_VFIO_AMD_XGBE)
 
 #endif
diff --git a/include/hw/vfio/vfio-calxeda-xgmac.h b/include/hw/vfio/vfio-calxeda-xgmac.h
index f994775c09..8482f151dd 100644
--- a/include/hw/vfio/vfio-calxeda-xgmac.h
+++ b/include/hw/vfio/vfio-calxeda-xgmac.h
@@ -15,6 +15,7 @@
 #define HW_VFIO_VFIO_CALXEDA_XGMAC_H
 
 #include "hw/vfio/vfio-platform.h"
+#include "qom/object.h"
 
 #define TYPE_VFIO_CALXEDA_XGMAC "vfio-calxeda-xgmac"
 
@@ -23,24 +24,20 @@
  * - a single MMIO region corresponding to its register space
  * - 3 IRQS (main and 2 power related IRQs)
  */
-typedef struct VFIOCalxedaXgmacDevice {
+struct VFIOCalxedaXgmacDevice {
     VFIOPlatformDevice vdev;
-} VFIOCalxedaXgmacDevice;
+};
+typedef struct VFIOCalxedaXgmacDevice VFIOCalxedaXgmacDevice;
 
-typedef struct VFIOCalxedaXgmacDeviceClass {
+struct VFIOCalxedaXgmacDeviceClass {
     /*< private >*/
     VFIOPlatformDeviceClass parent_class;
     /*< public >*/
     DeviceRealize parent_realize;
-} VFIOCalxedaXgmacDeviceClass;
+};
+typedef struct VFIOCalxedaXgmacDeviceClass VFIOCalxedaXgmacDeviceClass;
 
-#define VFIO_CALXEDA_XGMAC_DEVICE(obj) \
-     OBJECT_CHECK(VFIOCalxedaXgmacDevice, (obj), TYPE_VFIO_CALXEDA_XGMAC)
-#define VFIO_CALXEDA_XGMAC_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(VFIOCalxedaXgmacDeviceClass, (klass), \
-                        TYPE_VFIO_CALXEDA_XGMAC)
-#define VFIO_CALXEDA_XGMAC_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(VFIOCalxedaXgmacDeviceClass, (obj), \
-                      TYPE_VFIO_CALXEDA_XGMAC)
+DECLARE_OBJ_CHECKERS(VFIOCalxedaXgmacDevice, VFIOCalxedaXgmacDeviceClass,
+                     VFIO_CALXEDA_XGMAC_DEVICE, TYPE_VFIO_CALXEDA_XGMAC)
 
 #endif
diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h
index 4ec70c813a..c414c3dffc 100644
--- a/include/hw/vfio/vfio-platform.h
+++ b/include/hw/vfio/vfio-platform.h
@@ -20,6 +20,7 @@
 #include "hw/vfio/vfio-common.h"
 #include "qemu/event_notifier.h"
 #include "qemu/queue.h"
+#include "qom/object.h"
 
 #define TYPE_VFIO_PLATFORM "vfio-platform"
 
@@ -46,7 +47,7 @@ typedef struct VFIOINTp {
 /* function type for user side eventfd handler */
 typedef void (*eventfd_user_side_handler_t)(VFIOINTp *intp);
 
-typedef struct VFIOPlatformDevice {
+struct VFIOPlatformDevice {
     SysBusDevice sbdev;
     VFIODevice vbasedev; /* not a QOM object */
     VFIORegion **regions;
@@ -59,19 +60,17 @@ typedef struct VFIOPlatformDevice {
     QEMUTimer *mmap_timer; /* allows fast-path resume after IRQ hit */
     QemuMutex intp_mutex; /* protect the intp_list IRQ state */
     bool irqfd_allowed; /* debug option to force irqfd on/off */
-} VFIOPlatformDevice;
+};
+typedef struct VFIOPlatformDevice VFIOPlatformDevice;
 
-typedef struct VFIOPlatformDeviceClass {
+struct VFIOPlatformDeviceClass {
     /*< private >*/
     SysBusDeviceClass parent_class;
     /*< public >*/
-} VFIOPlatformDeviceClass;
+};
+typedef struct VFIOPlatformDeviceClass VFIOPlatformDeviceClass;
 
-#define VFIO_PLATFORM_DEVICE(obj) \
-     OBJECT_CHECK(VFIOPlatformDevice, (obj), TYPE_VFIO_PLATFORM)
-#define VFIO_PLATFORM_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(VFIOPlatformDeviceClass, (klass), TYPE_VFIO_PLATFORM)
-#define VFIO_PLATFORM_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(VFIOPlatformDeviceClass, (obj), TYPE_VFIO_PLATFORM)
+DECLARE_OBJ_CHECKERS(VFIOPlatformDevice, VFIOPlatformDeviceClass,
+                     VFIO_PLATFORM_DEVICE, TYPE_VFIO_PLATFORM)
 
 #endif /* HW_VFIO_VFIO_PLATFORM_H */
diff --git a/include/hw/virtio/vhost-scsi-common.h b/include/hw/virtio/vhost-scsi-common.h
index 16bf1a73c1..5f0bf73d9d 100644
--- a/include/hw/virtio/vhost-scsi-common.h
+++ b/include/hw/virtio/vhost-scsi-common.h
@@ -17,12 +17,14 @@
 #include "hw/virtio/virtio-scsi.h"
 #include "hw/virtio/vhost.h"
 #include "hw/fw-path-provider.h"
+#include "qom/object.h"
 
 #define TYPE_VHOST_SCSI_COMMON "vhost-scsi-common"
-#define VHOST_SCSI_COMMON(obj) \
-        OBJECT_CHECK(VHostSCSICommon, (obj), TYPE_VHOST_SCSI_COMMON)
+typedef struct VHostSCSICommon VHostSCSICommon;
+DECLARE_INSTANCE_CHECKER(VHostSCSICommon, VHOST_SCSI_COMMON,
+                         TYPE_VHOST_SCSI_COMMON)
 
-typedef struct VHostSCSICommon {
+struct VHostSCSICommon {
     VirtIOSCSICommon parent_obj;
 
     Error *migration_blocker;
@@ -35,7 +37,7 @@ typedef struct VHostSCSICommon {
     int lun;
     uint64_t host_features;
     bool migratable;
-} VHostSCSICommon;
+};
 
 int vhost_scsi_common_start(VHostSCSICommon *vsc);
 void vhost_scsi_common_stop(VHostSCSICommon *vsc);
diff --git a/include/hw/virtio/vhost-scsi.h b/include/hw/virtio/vhost-scsi.h
index 23252153ff..7a77644150 100644
--- a/include/hw/virtio/vhost-scsi.h
+++ b/include/hw/virtio/vhost-scsi.h
@@ -17,6 +17,7 @@
 #include "hw/virtio/virtio-scsi.h"
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/vhost-scsi-common.h"
+#include "qom/object.h"
 
 enum vhost_scsi_vq_list {
     VHOST_SCSI_VQ_CONTROL = 0,
@@ -25,11 +26,12 @@ enum vhost_scsi_vq_list {
 };
 
 #define TYPE_VHOST_SCSI "vhost-scsi"
-#define VHOST_SCSI(obj) \
-        OBJECT_CHECK(VHostSCSI, (obj), TYPE_VHOST_SCSI)
+typedef struct VHostSCSI VHostSCSI;
+DECLARE_INSTANCE_CHECKER(VHostSCSI, VHOST_SCSI,
+                         TYPE_VHOST_SCSI)
 
-typedef struct VHostSCSI {
+struct VHostSCSI {
     VHostSCSICommon parent_obj;
-} VHostSCSI;
+};
 
 #endif
diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h
index 292d17147c..dc40ab6f11 100644
--- a/include/hw/virtio/vhost-user-blk.h
+++ b/include/hw/virtio/vhost-user-blk.h
@@ -20,14 +20,16 @@
 #include "chardev/char-fe.h"
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/vhost-user.h"
+#include "qom/object.h"
 
 #define TYPE_VHOST_USER_BLK "vhost-user-blk"
-#define VHOST_USER_BLK(obj) \
-        OBJECT_CHECK(VHostUserBlk, (obj), TYPE_VHOST_USER_BLK)
+typedef struct VHostUserBlk VHostUserBlk;
+DECLARE_INSTANCE_CHECKER(VHostUserBlk, VHOST_USER_BLK,
+                         TYPE_VHOST_USER_BLK)
 
 #define VHOST_USER_BLK_AUTO_NUM_QUEUES UINT16_MAX
 
-typedef struct VHostUserBlk {
+struct VHostUserBlk {
     VirtIODevice parent_obj;
     CharBackend chardev;
     int32_t bootindex;
@@ -41,6 +43,6 @@ typedef struct VHostUserBlk {
     struct vhost_virtqueue *vhost_vqs;
     VirtQueue **virtqs;
     bool connected;
-} VHostUserBlk;
+};
 
 #endif
diff --git a/include/hw/virtio/vhost-user-fs.h b/include/hw/virtio/vhost-user-fs.h
index 6f3030d288..9033e6f902 100644
--- a/include/hw/virtio/vhost-user-fs.h
+++ b/include/hw/virtio/vhost-user-fs.h
@@ -18,10 +18,12 @@
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/vhost-user.h"
 #include "chardev/char-fe.h"
+#include "qom/object.h"
 
 #define TYPE_VHOST_USER_FS "vhost-user-fs-device"
-#define VHOST_USER_FS(obj) \
-        OBJECT_CHECK(VHostUserFS, (obj), TYPE_VHOST_USER_FS)
+typedef struct VHostUserFS VHostUserFS;
+DECLARE_INSTANCE_CHECKER(VHostUserFS, VHOST_USER_FS,
+                         TYPE_VHOST_USER_FS)
 
 typedef struct {
     CharBackend chardev;
@@ -30,7 +32,7 @@ typedef struct {
     uint16_t queue_size;
 } VHostUserFSConf;
 
-typedef struct {
+struct VHostUserFS {
     /*< private >*/
     VirtIODevice parent;
     VHostUserFSConf conf;
@@ -41,6 +43,6 @@ typedef struct {
     VirtQueue *hiprio_vq;
 
     /*< public >*/
-} VHostUserFS;
+};
 
 #endif /* _QEMU_VHOST_USER_FS_H */
diff --git a/include/hw/virtio/vhost-user-scsi.h b/include/hw/virtio/vhost-user-scsi.h
index 99ab2f2cc4..342d67ee9e 100644
--- a/include/hw/virtio/vhost-user-scsi.h
+++ b/include/hw/virtio/vhost-user-scsi.h
@@ -21,14 +21,16 @@
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/vhost-user.h"
 #include "hw/virtio/vhost-scsi-common.h"
+#include "qom/object.h"
 
 #define TYPE_VHOST_USER_SCSI "vhost-user-scsi"
-#define VHOST_USER_SCSI(obj) \
-        OBJECT_CHECK(VHostUserSCSI, (obj), TYPE_VHOST_USER_SCSI)
+typedef struct VHostUserSCSI VHostUserSCSI;
+DECLARE_INSTANCE_CHECKER(VHostUserSCSI, VHOST_USER_SCSI,
+                         TYPE_VHOST_USER_SCSI)
 
-typedef struct VHostUserSCSI {
+struct VHostUserSCSI {
     VHostSCSICommon parent_obj;
     VhostUserState vhost_user;
-} VHostUserSCSI;
+};
 
 #endif /* VHOST_USER_SCSI_H */
diff --git a/include/hw/virtio/vhost-user-vsock.h b/include/hw/virtio/vhost-user-vsock.h
index 4e128a4b9f..b3c40c16a3 100644
--- a/include/hw/virtio/vhost-user-vsock.h
+++ b/include/hw/virtio/vhost-user-vsock.h
@@ -14,16 +14,18 @@
 #include "hw/virtio/vhost-vsock-common.h"
 #include "hw/virtio/vhost-user.h"
 #include "standard-headers/linux/virtio_vsock.h"
+#include "qom/object.h"
 
 #define TYPE_VHOST_USER_VSOCK "vhost-user-vsock-device"
-#define VHOST_USER_VSOCK(obj) \
-        OBJECT_CHECK(VHostUserVSock, (obj), TYPE_VHOST_USER_VSOCK)
+typedef struct VHostUserVSock VHostUserVSock;
+DECLARE_INSTANCE_CHECKER(VHostUserVSock, VHOST_USER_VSOCK,
+                         TYPE_VHOST_USER_VSOCK)
 
 typedef struct {
     CharBackend chardev;
 } VHostUserVSockConf;
 
-typedef struct {
+struct VHostUserVSock {
     /*< private >*/
     VHostVSockCommon parent;
     VhostUserState vhost_user;
@@ -31,6 +33,6 @@ typedef struct {
     struct virtio_vsock_config vsockcfg;
 
     /*< public >*/
-} VHostUserVSock;
+};
 
 #endif /* _QEMU_VHOST_USER_VSOCK_H */
diff --git a/include/hw/virtio/vhost-vsock-common.h b/include/hw/virtio/vhost-vsock-common.h
index f8b4aaae00..60bfb68db1 100644
--- a/include/hw/virtio/vhost-vsock-common.h
+++ b/include/hw/virtio/vhost-vsock-common.h
@@ -13,10 +13,12 @@
 
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/vhost.h"
+#include "qom/object.h"
 
 #define TYPE_VHOST_VSOCK_COMMON "vhost-vsock-common"
-#define VHOST_VSOCK_COMMON(obj) \
-        OBJECT_CHECK(VHostVSockCommon, (obj), TYPE_VHOST_VSOCK_COMMON)
+typedef struct VHostVSockCommon VHostVSockCommon;
+DECLARE_INSTANCE_CHECKER(VHostVSockCommon, VHOST_VSOCK_COMMON,
+                         TYPE_VHOST_VSOCK_COMMON)
 
 enum {
     VHOST_VSOCK_SAVEVM_VERSION = 0,
@@ -24,7 +26,7 @@ enum {
     VHOST_VSOCK_QUEUE_SIZE = 128,
 };
 
-typedef struct {
+struct VHostVSockCommon {
     VirtIODevice parent;
 
     struct vhost_virtqueue vhost_vqs[2];
@@ -35,7 +37,7 @@ typedef struct {
     VirtQueue *trans_vq;
 
     QEMUTimer *post_load_timer;
-} VHostVSockCommon;
+};
 
 int vhost_vsock_common_start(VirtIODevice *vdev);
 void vhost_vsock_common_stop(VirtIODevice *vdev);
diff --git a/include/hw/virtio/vhost-vsock.h b/include/hw/virtio/vhost-vsock.h
index 8cbb7b90f9..c561cc427a 100644
--- a/include/hw/virtio/vhost-vsock.h
+++ b/include/hw/virtio/vhost-vsock.h
@@ -15,22 +15,24 @@
 #define QEMU_VHOST_VSOCK_H
 
 #include "hw/virtio/vhost-vsock-common.h"
+#include "qom/object.h"
 
 #define TYPE_VHOST_VSOCK "vhost-vsock-device"
-#define VHOST_VSOCK(obj) \
-        OBJECT_CHECK(VHostVSock, (obj), TYPE_VHOST_VSOCK)
+typedef struct VHostVSock VHostVSock;
+DECLARE_INSTANCE_CHECKER(VHostVSock, VHOST_VSOCK,
+                         TYPE_VHOST_VSOCK)
 
 typedef struct {
     uint64_t guest_cid;
     char *vhostfd;
 } VHostVSockConf;
 
-typedef struct {
+struct VHostVSock {
     /*< private >*/
     VHostVSockCommon parent;
     VHostVSockConf conf;
 
     /*< public >*/
-} VHostVSock;
+};
 
 #endif /* QEMU_VHOST_VSOCK_H */
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
index 28fd2b3960..0d08f496d9 100644
--- a/include/hw/virtio/virtio-balloon.h
+++ b/include/hw/virtio/virtio-balloon.h
@@ -18,10 +18,12 @@
 #include "standard-headers/linux/virtio_balloon.h"
 #include "hw/virtio/virtio.h"
 #include "sysemu/iothread.h"
+#include "qom/object.h"
 
 #define TYPE_VIRTIO_BALLOON "virtio-balloon-device"
-#define VIRTIO_BALLOON(obj) \
-        OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON)
+typedef struct VirtIOBalloon VirtIOBalloon;
+DECLARE_INSTANCE_CHECKER(VirtIOBalloon, VIRTIO_BALLOON,
+                         TYPE_VIRTIO_BALLOON)
 
 #define VIRTIO_BALLOON_FREE_PAGE_HINT_CMD_ID_MIN 0x80000000
 
@@ -40,7 +42,7 @@ enum virtio_balloon_free_page_hint_status {
     FREE_PAGE_HINT_S_DONE = 3,
 };
 
-typedef struct VirtIOBalloon {
+struct VirtIOBalloon {
     VirtIODevice parent_obj;
     VirtQueue *ivq, *dvq, *svq, *free_page_vq, *reporting_vq;
     uint32_t free_page_hint_status;
@@ -71,6 +73,6 @@ typedef struct VirtIOBalloon {
 
     bool qemu_4_0_config_size;
     uint32_t poison_val;
-} VirtIOBalloon;
+};
 
 #endif
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index 7539c2b848..29c9f32353 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -19,10 +19,12 @@
 #include "hw/block/block.h"
 #include "sysemu/iothread.h"
 #include "sysemu/block-backend.h"
+#include "qom/object.h"
 
 #define TYPE_VIRTIO_BLK "virtio-blk-device"
-#define VIRTIO_BLK(obj) \
-        OBJECT_CHECK(VirtIOBlock, (obj), TYPE_VIRTIO_BLK)
+typedef struct VirtIOBlock VirtIOBlock;
+DECLARE_INSTANCE_CHECKER(VirtIOBlock, VIRTIO_BLK,
+                         TYPE_VIRTIO_BLK)
 
 /* This is the last element of the write scatter-gather list */
 struct virtio_blk_inhdr
@@ -49,7 +51,7 @@ struct VirtIOBlkConf
 struct VirtIOBlockDataPlane;
 
 struct VirtIOBlockReq;
-typedef struct VirtIOBlock {
+struct VirtIOBlock {
     VirtIODevice parent_obj;
     BlockBackend *blk;
     void *rq;
@@ -63,7 +65,7 @@ typedef struct VirtIOBlock {
     struct VirtIOBlockDataPlane *dataplane;
     uint64_t host_features;
     size_t config_size;
-} VirtIOBlock;
+};
 
 typedef struct VirtIOBlockReq {
     VirtQueueElement elem;
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index 0f6f215925..ef8abe49c5 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -27,17 +27,16 @@
 
 #include "hw/qdev-core.h"
 #include "hw/virtio/virtio.h"
+#include "qom/object.h"
 
 #define TYPE_VIRTIO_BUS "virtio-bus"
-#define VIRTIO_BUS_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(VirtioBusClass, obj, TYPE_VIRTIO_BUS)
-#define VIRTIO_BUS_CLASS(klass) \
-        OBJECT_CLASS_CHECK(VirtioBusClass, klass, TYPE_VIRTIO_BUS)
-#define VIRTIO_BUS(obj) OBJECT_CHECK(VirtioBusState, (obj), TYPE_VIRTIO_BUS)
-
+typedef struct VirtioBusClass VirtioBusClass;
 typedef struct VirtioBusState VirtioBusState;
+DECLARE_OBJ_CHECKERS(VirtioBusState, VirtioBusClass,
+                     VIRTIO_BUS, TYPE_VIRTIO_BUS)
+
 
-typedef struct VirtioBusClass {
+struct VirtioBusClass {
     /* This is what a VirtioBus must implement */
     BusClass parent;
     void (*notify)(DeviceState *d, uint16_t vector);
@@ -94,7 +93,7 @@ typedef struct VirtioBusClass {
      */
     bool has_variable_vring_alignment;
     AddressSpace *(*get_dma_as)(DeviceState *d);
-} VirtioBusClass;
+};
 
 struct VirtioBusState {
     BusState parent_obj;
diff --git a/include/hw/virtio/virtio-crypto.h b/include/hw/virtio/virtio-crypto.h
index ffe2391ece..7969695983 100644
--- a/include/hw/virtio/virtio-crypto.h
+++ b/include/hw/virtio/virtio-crypto.h
@@ -18,6 +18,7 @@
 #include "hw/virtio/virtio.h"
 #include "sysemu/iothread.h"
 #include "sysemu/cryptodev.h"
+#include "qom/object.h"
 
 
 #define DEBUG_VIRTIO_CRYPTO 0
@@ -31,8 +32,9 @@ do { \
 
 
 #define TYPE_VIRTIO_CRYPTO "virtio-crypto-device"
-#define VIRTIO_CRYPTO(obj) \
-        OBJECT_CHECK(VirtIOCrypto, (obj), TYPE_VIRTIO_CRYPTO)
+typedef struct VirtIOCrypto VirtIOCrypto;
+DECLARE_INSTANCE_CHECKER(VirtIOCrypto, VIRTIO_CRYPTO,
+                         TYPE_VIRTIO_CRYPTO)
 #define VIRTIO_CRYPTO_GET_PARENT_CLASS(obj) \
         OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_CRYPTO)
 
@@ -82,7 +84,7 @@ typedef struct VirtIOCryptoQueue {
     struct VirtIOCrypto *vcrypto;
 } VirtIOCryptoQueue;
 
-typedef struct VirtIOCrypto {
+struct VirtIOCrypto {
     VirtIODevice parent_obj;
 
     VirtQueue *ctrl_vq;
@@ -97,6 +99,6 @@ typedef struct VirtIOCrypto {
     uint32_t curr_queues;
     size_t config_size;
     uint8_t vhost_started;
-} VirtIOCrypto;
+};
 
 #endif /* QEMU_VIRTIO_CRYPTO_H */
diff --git a/include/hw/virtio/virtio-gpu-pci.h b/include/hw/virtio/virtio-gpu-pci.h
index 2f69b5a9cc..5201792ede 100644
--- a/include/hw/virtio/virtio-gpu-pci.h
+++ b/include/hw/virtio/virtio-gpu-pci.h
@@ -16,6 +16,7 @@
 
 #include "hw/virtio/virtio-pci.h"
 #include "hw/virtio/virtio-gpu.h"
+#include "qom/object.h"
 
 typedef struct VirtIOGPUPCIBase VirtIOGPUPCIBase;
 
@@ -23,8 +24,8 @@ typedef struct VirtIOGPUPCIBase VirtIOGPUPCIBase;
  * virtio-gpu-pci-base: This extends VirtioPCIProxy.
  */
 #define TYPE_VIRTIO_GPU_PCI_BASE "virtio-gpu-pci-base"
-#define VIRTIO_GPU_PCI_BASE(obj)                                    \
-    OBJECT_CHECK(VirtIOGPUPCIBase, (obj), TYPE_VIRTIO_GPU_PCI_BASE)
+DECLARE_INSTANCE_CHECKER(VirtIOGPUPCIBase, VIRTIO_GPU_PCI_BASE,
+                         TYPE_VIRTIO_GPU_PCI_BASE)
 
 struct VirtIOGPUPCIBase {
     VirtIOPCIProxy parent_obj;
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7517438e10..f334b78085 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -22,22 +22,21 @@
 #include "sysemu/vhost-user-backend.h"
 
 #include "standard-headers/linux/virtio_gpu.h"
+#include "qom/object.h"
 
 #define TYPE_VIRTIO_GPU_BASE "virtio-gpu-base"
-#define VIRTIO_GPU_BASE(obj)                                                \
-    OBJECT_CHECK(VirtIOGPUBase, (obj), TYPE_VIRTIO_GPU_BASE)
-#define VIRTIO_GPU_BASE_GET_CLASS(obj)                                      \
-    OBJECT_GET_CLASS(VirtIOGPUBaseClass, obj, TYPE_VIRTIO_GPU_BASE)
-#define VIRTIO_GPU_BASE_CLASS(klass)                                        \
-    OBJECT_CLASS_CHECK(VirtIOGPUBaseClass, klass, TYPE_VIRTIO_GPU_BASE)
+OBJECT_DECLARE_TYPE(VirtIOGPUBase, VirtIOGPUBaseClass,
+                    virtio_gpu_base, VIRTIO_GPU_BASE)
 
 #define TYPE_VIRTIO_GPU "virtio-gpu-device"
-#define VIRTIO_GPU(obj)                                        \
-        OBJECT_CHECK(VirtIOGPU, (obj), TYPE_VIRTIO_GPU)
+typedef struct VirtIOGPU VirtIOGPU;
+DECLARE_INSTANCE_CHECKER(VirtIOGPU, VIRTIO_GPU,
+                         TYPE_VIRTIO_GPU)
 
 #define TYPE_VHOST_USER_GPU "vhost-user-gpu"
-#define VHOST_USER_GPU(obj)                                    \
-    OBJECT_CHECK(VhostUserGPU, (obj), TYPE_VHOST_USER_GPU)
+typedef struct VhostUserGPU VhostUserGPU;
+DECLARE_INSTANCE_CHECKER(VhostUserGPU, VHOST_USER_GPU,
+                         TYPE_VHOST_USER_GPU)
 
 #define VIRTIO_ID_GPU 16
 
@@ -100,7 +99,7 @@ struct virtio_gpu_ctrl_command {
     QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
 };
 
-typedef struct VirtIOGPUBase {
+struct VirtIOGPUBase {
     VirtIODevice parent_obj;
 
     Error *migration_blocker;
@@ -116,13 +115,13 @@ typedef struct VirtIOGPUBase {
 
     int enabled_output_bitmask;
     struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUTS];
-} VirtIOGPUBase;
+};
 
-typedef struct VirtIOGPUBaseClass {
+struct VirtIOGPUBaseClass {
     VirtioDeviceClass parent;
 
     void (*gl_unblock)(VirtIOGPUBase *g);
-} VirtIOGPUBaseClass;
+};
 
 #define VIRTIO_GPU_BASE_PROPERTIES(_state, _conf)                       \
     DEFINE_PROP_UINT32("max_outputs", _state, _conf.max_outputs, 1),    \
@@ -131,7 +130,7 @@ typedef struct VirtIOGPUBaseClass {
     DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1024), \
     DEFINE_PROP_UINT32("yres", _state, _conf.yres, 768)
 
-typedef struct VirtIOGPU {
+struct VirtIOGPU {
     VirtIOGPUBase parent_obj;
 
     uint64_t conf_max_hostmem;
@@ -160,9 +159,9 @@ typedef struct VirtIOGPU {
         uint32_t req_3d;
         uint32_t bytes_3d;
     } stats;
-} VirtIOGPU;
+};
 
-typedef struct VhostUserGPU {
+struct VhostUserGPU {
     VirtIOGPUBase parent_obj;
 
     VhostUserBackend *vhost;
@@ -170,7 +169,7 @@ typedef struct VhostUserGPU {
     CharBackend vhost_chr;
     QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
     bool backend_blocked;
-} VhostUserGPU;
+};
 
 extern const GraphicHwOps virtio_gpu_ops;
 
diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h
index 4fca03e796..5eb9e7745e 100644
--- a/include/hw/virtio/virtio-input.h
+++ b/include/hw/virtio/virtio-input.h
@@ -9,6 +9,7 @@
 
 #include "standard-headers/linux/virtio_ids.h"
 #include "standard-headers/linux/virtio_input.h"
+#include "qom/object.h"
 
 typedef struct virtio_input_absinfo virtio_input_absinfo;
 typedef struct virtio_input_config virtio_input_config;
@@ -18,43 +19,37 @@ typedef struct virtio_input_event virtio_input_event;
 /* qemu internals                                                    */
 
 #define TYPE_VIRTIO_INPUT "virtio-input-device"
-#define VIRTIO_INPUT(obj) \
-        OBJECT_CHECK(VirtIOInput, (obj), TYPE_VIRTIO_INPUT)
+OBJECT_DECLARE_TYPE(VirtIOInput, VirtIOInputClass,
+                    virtio_input, VIRTIO_INPUT)
 #define VIRTIO_INPUT_GET_PARENT_CLASS(obj) \
         OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT)
-#define VIRTIO_INPUT_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(VirtIOInputClass, obj, TYPE_VIRTIO_INPUT)
-#define VIRTIO_INPUT_CLASS(klass) \
-        OBJECT_CLASS_CHECK(VirtIOInputClass, klass, TYPE_VIRTIO_INPUT)
 
 #define TYPE_VIRTIO_INPUT_HID "virtio-input-hid-device"
 #define TYPE_VIRTIO_KEYBOARD  "virtio-keyboard-device"
 #define TYPE_VIRTIO_MOUSE     "virtio-mouse-device"
 #define TYPE_VIRTIO_TABLET    "virtio-tablet-device"
 
-#define VIRTIO_INPUT_HID(obj) \
-        OBJECT_CHECK(VirtIOInputHID, (obj), TYPE_VIRTIO_INPUT_HID)
+typedef struct VirtIOInputHID VirtIOInputHID;
+DECLARE_INSTANCE_CHECKER(VirtIOInputHID, VIRTIO_INPUT_HID,
+                         TYPE_VIRTIO_INPUT_HID)
 #define VIRTIO_INPUT_HID_GET_PARENT_CLASS(obj) \
         OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT_HID)
 
 #define TYPE_VIRTIO_INPUT_HOST   "virtio-input-host-device"
-#define VIRTIO_INPUT_HOST(obj) \
-        OBJECT_CHECK(VirtIOInputHost, (obj), TYPE_VIRTIO_INPUT_HOST)
+typedef struct VirtIOInputHost VirtIOInputHost;
+DECLARE_INSTANCE_CHECKER(VirtIOInputHost, VIRTIO_INPUT_HOST,
+                         TYPE_VIRTIO_INPUT_HOST)
 #define VIRTIO_INPUT_HOST_GET_PARENT_CLASS(obj) \
         OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT_HOST)
 
 #define TYPE_VHOST_USER_INPUT   "vhost-user-input"
-#define VHOST_USER_INPUT(obj)                              \
-    OBJECT_CHECK(VHostUserInput, (obj), TYPE_VHOST_USER_INPUT)
+typedef struct VHostUserInput VHostUserInput;
+DECLARE_INSTANCE_CHECKER(VHostUserInput, VHOST_USER_INPUT,
+                         TYPE_VHOST_USER_INPUT)
 #define VHOST_USER_INPUT_GET_PARENT_CLASS(obj)             \
     OBJECT_GET_PARENT_CLASS(obj, TYPE_VHOST_USER_INPUT)
 
-typedef struct VirtIOInput VirtIOInput;
-typedef struct VirtIOInputClass VirtIOInputClass;
 typedef struct VirtIOInputConfig VirtIOInputConfig;
-typedef struct VirtIOInputHID VirtIOInputHID;
-typedef struct VirtIOInputHost VirtIOInputHost;
-typedef struct VHostUserInput VHostUserInput;
 
 struct VirtIOInputConfig {
     virtio_input_config               config;
diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h
index 49eb105cd8..ae9dc566c7 100644
--- a/include/hw/virtio/virtio-iommu.h
+++ b/include/hw/virtio/virtio-iommu.h
@@ -23,11 +23,13 @@
 #include "standard-headers/linux/virtio_iommu.h"
 #include "hw/virtio/virtio.h"
 #include "hw/pci/pci.h"
+#include "qom/object.h"
 
 #define TYPE_VIRTIO_IOMMU "virtio-iommu-device"
 #define TYPE_VIRTIO_IOMMU_PCI "virtio-iommu-device-base"
-#define VIRTIO_IOMMU(obj) \
-        OBJECT_CHECK(VirtIOIOMMU, (obj), TYPE_VIRTIO_IOMMU)
+typedef struct VirtIOIOMMU VirtIOIOMMU;
+DECLARE_INSTANCE_CHECKER(VirtIOIOMMU, VIRTIO_IOMMU,
+                         TYPE_VIRTIO_IOMMU)
 
 #define TYPE_VIRTIO_IOMMU_MEMORY_REGION "virtio-iommu-memory-region"
 
@@ -44,7 +46,7 @@ typedef struct IOMMUPciBus {
     IOMMUDevice  *pbdev[]; /* Parent array is sparse, so dynamically alloc */
 } IOMMUPciBus;
 
-typedef struct VirtIOIOMMU {
+struct VirtIOIOMMU {
     VirtIODevice parent_obj;
     VirtQueue *req_vq;
     VirtQueue *event_vq;
@@ -58,6 +60,6 @@ typedef struct VirtIOIOMMU {
     GTree *domains;
     QemuMutex mutex;
     GTree *endpoints;
-} VirtIOIOMMU;
+};
 
 #endif
diff --git a/include/hw/virtio/virtio-mem.h b/include/hw/virtio/virtio-mem.h
index 0778224964..dfc72e14b1 100644
--- a/include/hw/virtio/virtio-mem.h
+++ b/include/hw/virtio/virtio-mem.h
@@ -17,15 +17,12 @@
 #include "hw/virtio/virtio.h"
 #include "qapi/qapi-types-misc.h"
 #include "sysemu/hostmem.h"
+#include "qom/object.h"
 
 #define TYPE_VIRTIO_MEM "virtio-mem"
 
-#define VIRTIO_MEM(obj) \
-        OBJECT_CHECK(VirtIOMEM, (obj), TYPE_VIRTIO_MEM)
-#define VIRTIO_MEM_CLASS(oc) \
-        OBJECT_CLASS_CHECK(VirtIOMEMClass, (oc), TYPE_VIRTIO_MEM)
-#define VIRTIO_MEM_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(VirtIOMEMClass, (obj), TYPE_VIRTIO_MEM)
+OBJECT_DECLARE_TYPE(VirtIOMEM, VirtIOMEMClass,
+                    virtio_mem, VIRTIO_MEM)
 
 #define VIRTIO_MEM_MEMDEV_PROP "memdev"
 #define VIRTIO_MEM_NODE_PROP "node"
@@ -34,7 +31,7 @@
 #define VIRTIO_MEM_BLOCK_SIZE_PROP "block-size"
 #define VIRTIO_MEM_ADDR_PROP "memaddr"
 
-typedef struct VirtIOMEM {
+struct VirtIOMEM {
     VirtIODevice parent_obj;
 
     /* guest -> host request queue */
@@ -70,9 +67,9 @@ typedef struct VirtIOMEM {
 
     /* don't migrate unplugged memory */
     NotifierWithReturn precopy_notifier;
-} VirtIOMEM;
+};
 
-typedef struct VirtIOMEMClass {
+struct VirtIOMEMClass {
     /* private */
     VirtIODevice parent;
 
@@ -81,6 +78,6 @@ typedef struct VirtIOMEMClass {
     MemoryRegion *(*get_memory_region)(VirtIOMEM *vmem, Error **errp);
     void (*add_size_change_notifier)(VirtIOMEM *vmem, Notifier *notifier);
     void (*remove_size_change_notifier)(VirtIOMEM *vmem, Notifier *notifier);
-} VirtIOMEMClass;
+};
 
 #endif
diff --git a/include/hw/virtio/virtio-mmio.h b/include/hw/virtio/virtio-mmio.h
index 7dbfd03dcf..6a1c2c20d4 100644
--- a/include/hw/virtio/virtio-mmio.h
+++ b/include/hw/virtio/virtio-mmio.h
@@ -23,21 +23,20 @@
 #define HW_VIRTIO_MMIO_H
 
 #include "hw/virtio/virtio-bus.h"
+#include "qom/object.h"
 
 /* QOM macros */
 /* virtio-mmio-bus */
 #define TYPE_VIRTIO_MMIO_BUS "virtio-mmio-bus"
-#define VIRTIO_MMIO_BUS(obj) \
-        OBJECT_CHECK(VirtioBusState, (obj), TYPE_VIRTIO_MMIO_BUS)
-#define VIRTIO_MMIO_BUS_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(VirtioBusClass, (obj), TYPE_VIRTIO_MMIO_BUS)
-#define VIRTIO_MMIO_BUS_CLASS(klass) \
-        OBJECT_CLASS_CHECK(VirtioBusClass, (klass), TYPE_VIRTIO_MMIO_BUS)
+/* This is reusing the VirtioBusState typedef from TYPE_VIRTIO_BUS */
+DECLARE_OBJ_CHECKERS(VirtioBusState, VirtioBusClass,
+                     VIRTIO_MMIO_BUS, TYPE_VIRTIO_MMIO_BUS)
 
 /* virtio-mmio */
 #define TYPE_VIRTIO_MMIO "virtio-mmio"
-#define VIRTIO_MMIO(obj) \
-        OBJECT_CHECK(VirtIOMMIOProxy, (obj), TYPE_VIRTIO_MMIO)
+typedef struct VirtIOMMIOProxy VirtIOMMIOProxy;
+DECLARE_INSTANCE_CHECKER(VirtIOMMIOProxy, VIRTIO_MMIO,
+                         TYPE_VIRTIO_MMIO)
 
 #define VIRT_MAGIC 0x74726976 /* 'virt' */
 #define VIRT_VERSION 2
@@ -52,7 +51,7 @@ typedef struct VirtIOMMIOQueue {
     uint32_t used[2];
 } VirtIOMMIOQueue;
 
-typedef struct {
+struct VirtIOMMIOProxy {
     /* Generic */
     SysBusDevice parent_obj;
     MemoryRegion iomem;
@@ -68,6 +67,6 @@ typedef struct {
     /* Fields only used for non-legacy (v2) devices */
     uint32_t guest_features[2];
     VirtIOMMIOQueue vqs[VIRTIO_QUEUE_MAX];
-} VirtIOMMIOProxy;
+};
 
 #endif
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index a45ef8278e..929ed232dd 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -19,10 +19,12 @@
 #include "hw/virtio/virtio.h"
 #include "net/announce.h"
 #include "qemu/option_int.h"
+#include "qom/object.h"
 
 #define TYPE_VIRTIO_NET "virtio-net-device"
-#define VIRTIO_NET(obj) \
-        OBJECT_CHECK(VirtIONet, (obj), TYPE_VIRTIO_NET)
+typedef struct VirtIONet VirtIONet;
+DECLARE_INSTANCE_CHECKER(VirtIONet, VIRTIO_NET,
+                         TYPE_VIRTIO_NET)
 
 #define TX_TIMER_INTERVAL 150000 /* 150 us */
 
@@ -109,7 +111,6 @@ typedef struct VirtioNetRscSeg {
     NetClientState *nc;
 } VirtioNetRscSeg;
 
-typedef struct VirtIONet VirtIONet;
 
 /* Chain is divided by protocol(ipv4/v6) and NetClientInfo */
 typedef struct VirtioNetRscChain {
diff --git a/include/hw/virtio/virtio-pmem.h b/include/hw/virtio/virtio-pmem.h
index 33f1999320..56df9a03ce 100644
--- a/include/hw/virtio/virtio-pmem.h
+++ b/include/hw/virtio/virtio-pmem.h
@@ -16,34 +16,31 @@
 
 #include "hw/virtio/virtio.h"
 #include "qapi/qapi-types-misc.h"
+#include "qom/object.h"
 
 #define TYPE_VIRTIO_PMEM "virtio-pmem"
 
-#define VIRTIO_PMEM(obj) \
-        OBJECT_CHECK(VirtIOPMEM, (obj), TYPE_VIRTIO_PMEM)
-#define VIRTIO_PMEM_CLASS(oc) \
-        OBJECT_CLASS_CHECK(VirtIOPMEMClass, (oc), TYPE_VIRTIO_PMEM)
-#define VIRTIO_PMEM_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(VirtIOPMEMClass, (obj), TYPE_VIRTIO_PMEM)
+OBJECT_DECLARE_TYPE(VirtIOPMEM, VirtIOPMEMClass,
+                    virtio_pmem, VIRTIO_PMEM)
 
 #define VIRTIO_PMEM_ADDR_PROP "memaddr"
 #define VIRTIO_PMEM_MEMDEV_PROP "memdev"
 
-typedef struct VirtIOPMEM {
+struct VirtIOPMEM {
     VirtIODevice parent_obj;
 
     VirtQueue *rq_vq;
     uint64_t start;
     HostMemoryBackend *memdev;
-} VirtIOPMEM;
+};
 
-typedef struct VirtIOPMEMClass {
+struct VirtIOPMEMClass {
     /* private */
     VirtIODevice parent;
 
     /* public */
     void (*fill_device_info)(const VirtIOPMEM *pmem, VirtioPMEMDeviceInfo *vi);
     MemoryRegion *(*get_memory_region)(VirtIOPMEM *pmem, Error **errp);
-} VirtIOPMEMClass;
+};
 
 #endif
diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h
index bd05d734b8..3671c9ba19 100644
--- a/include/hw/virtio/virtio-rng.h
+++ b/include/hw/virtio/virtio-rng.h
@@ -15,10 +15,12 @@
 #include "hw/virtio/virtio.h"
 #include "sysemu/rng.h"
 #include "standard-headers/linux/virtio_rng.h"
+#include "qom/object.h"
 
 #define TYPE_VIRTIO_RNG "virtio-rng-device"
-#define VIRTIO_RNG(obj) \
-        OBJECT_CHECK(VirtIORNG, (obj), TYPE_VIRTIO_RNG)
+typedef struct VirtIORNG VirtIORNG;
+DECLARE_INSTANCE_CHECKER(VirtIORNG, VIRTIO_RNG,
+                         TYPE_VIRTIO_RNG)
 #define VIRTIO_RNG_GET_PARENT_CLASS(obj) \
         OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_RNG)
 
@@ -28,7 +30,7 @@ struct VirtIORNGConf {
     uint32_t period_ms;
 };
 
-typedef struct VirtIORNG {
+struct VirtIORNG {
     VirtIODevice parent_obj;
 
     /* Only one vq - guest puts buffer(s) on it when it needs entropy */
@@ -46,6 +48,6 @@ typedef struct VirtIORNG {
     bool activate_timer;
 
     VMChangeStateEntry *vmstate;
-} VirtIORNG;
+};
 
 #endif
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index c0b8e4dd7e..9a8a06fdd1 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -13,6 +13,7 @@
 
 #ifndef QEMU_VIRTIO_SCSI_H
 #define QEMU_VIRTIO_SCSI_H
+#include "qom/object.h"
 
 /* Override CDB/sense data size: they are dynamic (guest controlled) in QEMU */
 #define VIRTIO_SCSI_CDB_SIZE 0
@@ -25,12 +26,14 @@
 #include "sysemu/iothread.h"
 
 #define TYPE_VIRTIO_SCSI_COMMON "virtio-scsi-common"
-#define VIRTIO_SCSI_COMMON(obj) \
-        OBJECT_CHECK(VirtIOSCSICommon, (obj), TYPE_VIRTIO_SCSI_COMMON)
+typedef struct VirtIOSCSICommon VirtIOSCSICommon;
+DECLARE_INSTANCE_CHECKER(VirtIOSCSICommon, VIRTIO_SCSI_COMMON,
+                         TYPE_VIRTIO_SCSI_COMMON)
 
 #define TYPE_VIRTIO_SCSI "virtio-scsi-device"
-#define VIRTIO_SCSI(obj) \
-        OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI)
+typedef struct VirtIOSCSI VirtIOSCSI;
+DECLARE_INSTANCE_CHECKER(VirtIOSCSI, VIRTIO_SCSI,
+                         TYPE_VIRTIO_SCSI)
 
 #define VIRTIO_SCSI_MAX_CHANNEL 0
 #define VIRTIO_SCSI_MAX_TARGET  255
@@ -67,7 +70,7 @@ struct VirtIOSCSIConf {
 
 struct VirtIOSCSI;
 
-typedef struct VirtIOSCSICommon {
+struct VirtIOSCSICommon {
     VirtIODevice parent_obj;
     VirtIOSCSIConf conf;
 
@@ -76,9 +79,9 @@ typedef struct VirtIOSCSICommon {
     VirtQueue *ctrl_vq;
     VirtQueue *event_vq;
     VirtQueue **cmd_vqs;
-} VirtIOSCSICommon;
+};
 
-typedef struct VirtIOSCSI {
+struct VirtIOSCSI {
     VirtIOSCSICommon parent_obj;
 
     SCSIBus bus;
@@ -93,7 +96,7 @@ typedef struct VirtIOSCSI {
     bool dataplane_stopping;
     bool dataplane_fenced;
     uint32_t host_features;
-} VirtIOSCSI;
+};
 
 typedef struct VirtIOSCSIReq {
     /* Note:
diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h
index 448615a6b3..0b7f963611 100644
--- a/include/hw/virtio/virtio-serial.h
+++ b/include/hw/virtio/virtio-serial.h
@@ -18,6 +18,7 @@
 
 #include "standard-headers/linux/virtio_console.h"
 #include "hw/virtio/virtio.h"
+#include "qom/object.h"
 
 struct virtio_serial_conf {
     /* Max. number of ports we can have for a virtio-serial device */
@@ -25,23 +26,18 @@ struct virtio_serial_conf {
 };
 
 #define TYPE_VIRTIO_SERIAL_PORT "virtio-serial-port"
-#define VIRTIO_SERIAL_PORT(obj) \
-     OBJECT_CHECK(VirtIOSerialPort, (obj), TYPE_VIRTIO_SERIAL_PORT)
-#define VIRTIO_SERIAL_PORT_CLASS(klass) \
-     OBJECT_CLASS_CHECK(VirtIOSerialPortClass, (klass), TYPE_VIRTIO_SERIAL_PORT)
-#define VIRTIO_SERIAL_PORT_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(VirtIOSerialPortClass, (obj), TYPE_VIRTIO_SERIAL_PORT)
+OBJECT_DECLARE_TYPE(VirtIOSerialPort, VirtIOSerialPortClass,
+                    virtio_serial_port, VIRTIO_SERIAL_PORT)
 
 typedef struct VirtIOSerial VirtIOSerial;
 
 #define TYPE_VIRTIO_SERIAL_BUS "virtio-serial-bus"
 typedef struct VirtIOSerialBus VirtIOSerialBus;
-#define VIRTIO_SERIAL_BUS(obj) \
-      OBJECT_CHECK(VirtIOSerialBus, (obj), TYPE_VIRTIO_SERIAL_BUS)
+DECLARE_INSTANCE_CHECKER(VirtIOSerialBus, VIRTIO_SERIAL_BUS,
+                         TYPE_VIRTIO_SERIAL_BUS)
 
-typedef struct VirtIOSerialPort VirtIOSerialPort;
 
-typedef struct VirtIOSerialPortClass {
+struct VirtIOSerialPortClass {
     DeviceClass parent_class;
 
     /* Is this a device that binds with hvc in the guest? */
@@ -86,7 +82,7 @@ typedef struct VirtIOSerialPortClass {
      */
     ssize_t (*have_data)(VirtIOSerialPort *port, const uint8_t *buf,
                          ssize_t len);
-} VirtIOSerialPortClass;
+};
 
 /*
  * This is the state that's shared between all the ports.  Some of the
@@ -228,7 +224,7 @@ size_t virtio_serial_guest_ready(VirtIOSerialPort *port);
 void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle);
 
 #define TYPE_VIRTIO_SERIAL "virtio-serial-device"
-#define VIRTIO_SERIAL(obj) \
-        OBJECT_CHECK(VirtIOSerial, (obj), TYPE_VIRTIO_SERIAL)
+DECLARE_INSTANCE_CHECKER(VirtIOSerial, VIRTIO_SERIAL,
+                         TYPE_VIRTIO_SERIAL)
 
 #endif
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index e424df12cf..807280451b 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -21,6 +21,7 @@
 #include "qemu/event_notifier.h"
 #include "standard-headers/linux/virtio_config.h"
 #include "standard-headers/linux/virtio_ring.h"
+#include "qom/object.h"
 
 /* A guest should never accept this.  It implies negotiation is broken. */
 #define VIRTIO_F_BAD_FEATURE		30
@@ -67,12 +68,9 @@ typedef struct VirtQueueElement
 #define VIRTIO_NO_VECTOR 0xffff
 
 #define TYPE_VIRTIO_DEVICE "virtio-device"
-#define VIRTIO_DEVICE_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(VirtioDeviceClass, obj, TYPE_VIRTIO_DEVICE)
-#define VIRTIO_DEVICE_CLASS(klass) \
-        OBJECT_CLASS_CHECK(VirtioDeviceClass, klass, TYPE_VIRTIO_DEVICE)
-#define VIRTIO_DEVICE(obj) \
-        OBJECT_CHECK(VirtIODevice, (obj), TYPE_VIRTIO_DEVICE)
+typedef struct VirtioDeviceClass VirtioDeviceClass;
+DECLARE_OBJ_CHECKERS(VirtIODevice, VirtioDeviceClass,
+                     VIRTIO_DEVICE, TYPE_VIRTIO_DEVICE)
 
 enum virtio_device_endian {
     VIRTIO_DEVICE_ENDIAN_UNKNOWN,
@@ -113,7 +111,7 @@ struct VirtIODevice
     QLIST_HEAD(, VirtQueue) *vector_queues;
 };
 
-typedef struct VirtioDeviceClass {
+struct VirtioDeviceClass {
     /*< private >*/
     DeviceClass parent;
     /*< public >*/
@@ -163,7 +161,7 @@ typedef struct VirtioDeviceClass {
     int (*post_load)(VirtIODevice *vdev);
     const VMStateDescription *vmsd;
     bool (*primary_unplug_pending)(void *opaque);
-} VirtioDeviceClass;
+};
 
 void virtio_instance_init_common(Object *proxy_obj, void *data,
                                  size_t vdev_size, const char *vdev_name);
diff --git a/include/hw/vmstate-if.h b/include/hw/vmstate-if.h
index 8ff7f0f292..52df571d17 100644
--- a/include/hw/vmstate-if.h
+++ b/include/hw/vmstate-if.h
@@ -13,20 +13,19 @@
 
 #define TYPE_VMSTATE_IF "vmstate-if"
 
-#define VMSTATE_IF_CLASS(klass)                                     \
-    OBJECT_CLASS_CHECK(VMStateIfClass, (klass), TYPE_VMSTATE_IF)
-#define VMSTATE_IF_GET_CLASS(obj)                           \
-    OBJECT_GET_CLASS(VMStateIfClass, (obj), TYPE_VMSTATE_IF)
+typedef struct VMStateIfClass VMStateIfClass;
+DECLARE_CLASS_CHECKERS(VMStateIfClass, VMSTATE_IF,
+                       TYPE_VMSTATE_IF)
 #define VMSTATE_IF(obj)                             \
     INTERFACE_CHECK(VMStateIf, (obj), TYPE_VMSTATE_IF)
 
 typedef struct VMStateIf VMStateIf;
 
-typedef struct VMStateIfClass {
+struct VMStateIfClass {
     InterfaceClass parent_class;
 
     char * (*get_id)(VMStateIf *obj);
-} VMStateIfClass;
+};
 
 static inline char *vmstate_if_get_id(VMStateIf *vmif)
 {
diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.h
index 6ae9531370..63f4becf86 100644
--- a/include/hw/watchdog/cmsdk-apb-watchdog.h
+++ b/include/hw/watchdog/cmsdk-apb-watchdog.h
@@ -33,10 +33,12 @@
 
 #include "hw/sysbus.h"
 #include "hw/ptimer.h"
+#include "qom/object.h"
 
 #define TYPE_CMSDK_APB_WATCHDOG "cmsdk-apb-watchdog"
-#define CMSDK_APB_WATCHDOG(obj) OBJECT_CHECK(CMSDKAPBWatchdog, (obj), \
-                                              TYPE_CMSDK_APB_WATCHDOG)
+typedef struct CMSDKAPBWatchdog CMSDKAPBWatchdog;
+DECLARE_INSTANCE_CHECKER(CMSDKAPBWatchdog, CMSDK_APB_WATCHDOG,
+                         TYPE_CMSDK_APB_WATCHDOG)
 
 /*
  * This shares the same struct (and cast macro) as the base
@@ -44,7 +46,7 @@
  */
 #define TYPE_LUMINARY_WATCHDOG "luminary-watchdog"
 
-typedef struct CMSDKAPBWatchdog {
+struct CMSDKAPBWatchdog {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -62,6 +64,6 @@ typedef struct CMSDKAPBWatchdog {
     uint32_t itop;
     uint32_t resetstatus;
     const uint32_t *id;
-} CMSDKAPBWatchdog;
+};
 
 #endif
diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h
index 819c22993a..2ca1eb5432 100644
--- a/include/hw/watchdog/wdt_aspeed.h
+++ b/include/hw/watchdog/wdt_aspeed.h
@@ -12,17 +12,20 @@
 
 #include "hw/misc/aspeed_scu.h"
 #include "hw/sysbus.h"
+#include "qom/object.h"
 
 #define TYPE_ASPEED_WDT "aspeed.wdt"
-#define ASPEED_WDT(obj) \
-    OBJECT_CHECK(AspeedWDTState, (obj), TYPE_ASPEED_WDT)
+typedef struct AspeedWDTClass AspeedWDTClass;
+typedef struct AspeedWDTState AspeedWDTState;
+DECLARE_OBJ_CHECKERS(AspeedWDTState, AspeedWDTClass,
+                     ASPEED_WDT, TYPE_ASPEED_WDT)
 #define TYPE_ASPEED_2400_WDT TYPE_ASPEED_WDT "-ast2400"
 #define TYPE_ASPEED_2500_WDT TYPE_ASPEED_WDT "-ast2500"
 #define TYPE_ASPEED_2600_WDT TYPE_ASPEED_WDT "-ast2600"
 
 #define ASPEED_WDT_REGS_MAX        (0x20 / 4)
 
-typedef struct AspeedWDTState {
+struct AspeedWDTState {
     /*< private >*/
     SysBusDevice parent_obj;
     QEMUTimer *timer;
@@ -33,14 +36,10 @@ typedef struct AspeedWDTState {
 
     AspeedSCUState *scu;
     uint32_t pclk_freq;
-} AspeedWDTState;
+};
 
-#define ASPEED_WDT_CLASS(klass) \
-     OBJECT_CLASS_CHECK(AspeedWDTClass, (klass), TYPE_ASPEED_WDT)
-#define ASPEED_WDT_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(AspeedWDTClass, (obj), TYPE_ASPEED_WDT)
 
-typedef struct AspeedWDTClass {
+struct AspeedWDTClass {
     SysBusDeviceClass parent_class;
 
     uint32_t offset;
@@ -48,6 +47,6 @@ typedef struct AspeedWDTClass {
     uint32_t reset_ctrl_reg;
     void (*reset_pulse)(AspeedWDTState *s, uint32_t property);
     void (*wdt_reload)(AspeedWDTState *s);
-}  AspeedWDTClass;
+};
 
 #endif /* WDT_ASPEED_H */
diff --git a/include/hw/watchdog/wdt_diag288.h b/include/hw/watchdog/wdt_diag288.h
index 19d83a0937..f72c1d3318 100644
--- a/include/hw/watchdog/wdt_diag288.h
+++ b/include/hw/watchdog/wdt_diag288.h
@@ -2,35 +2,34 @@
 #define WDT_DIAG288_H
 
 #include "hw/qdev-core.h"
+#include "qom/object.h"
 
 #define TYPE_WDT_DIAG288 "diag288"
-#define DIAG288(obj) \
-    OBJECT_CHECK(DIAG288State, (obj), TYPE_WDT_DIAG288)
-#define DIAG288_CLASS(klass) \
-    OBJECT_CLASS_CHECK(DIAG288Class, (klass), TYPE_WDT_DIAG288)
-#define DIAG288_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(DIAG288Class, (obj), TYPE_WDT_DIAG288)
+typedef struct DIAG288Class DIAG288Class;
+typedef struct DIAG288State DIAG288State;
+DECLARE_OBJ_CHECKERS(DIAG288State, DIAG288Class,
+                     DIAG288, TYPE_WDT_DIAG288)
 
 #define WDT_DIAG288_INIT      0
 #define WDT_DIAG288_CHANGE    1
 #define WDT_DIAG288_CANCEL    2
 
-typedef struct DIAG288State {
+struct DIAG288State {
     /*< private >*/
     DeviceState parent_obj;
     QEMUTimer *timer;
     bool enabled;
 
     /*< public >*/
-} DIAG288State;
+};
 
-typedef struct DIAG288Class {
+struct DIAG288Class {
     /*< private >*/
     DeviceClass parent_class;
 
     /*< public >*/
     int (*handle_timer)(DIAG288State *dev,
                         uint64_t func, uint64_t timeout);
-} DIAG288Class;
+};
 
 #endif /* WDT_DIAG288_H */
diff --git a/include/hw/watchdog/wdt_imx2.h b/include/hw/watchdog/wdt_imx2.h
index f9af6be4b6..7665d93640 100644
--- a/include/hw/watchdog/wdt_imx2.h
+++ b/include/hw/watchdog/wdt_imx2.h
@@ -16,9 +16,12 @@
 #include "hw/sysbus.h"
 #include "hw/irq.h"
 #include "hw/ptimer.h"
+#include "qom/object.h"
 
 #define TYPE_IMX2_WDT "imx2.wdt"
-#define IMX2_WDT(obj) OBJECT_CHECK(IMX2WdtState, (obj), TYPE_IMX2_WDT)
+typedef struct IMX2WdtState IMX2WdtState;
+DECLARE_INSTANCE_CHECKER(IMX2WdtState, IMX2_WDT,
+                         TYPE_IMX2_WDT)
 
 enum IMX2WdtRegisters {
     IMX2_WDT_WCR  = 0x0000, /* Control Register */
@@ -62,7 +65,7 @@ enum IMX2WdtRegisters {
 /* Misc Control Register definitions */
 #define IMX2_WDT_WMCR_PDE       BIT(0)      /* Power-Down Enable */
 
-typedef struct IMX2WdtState {
+struct IMX2WdtState {
     /* <private> */
     SysBusDevice parent_obj;
 
@@ -85,6 +88,6 @@ typedef struct IMX2WdtState {
     bool wcr_locked;            /* affects WDZST, WDBG, and WDW */
     bool wcr_wde_locked;        /* affects WDE */
     bool wcr_wdt_locked;        /* affects WDT (never cleared) */
-} IMX2WdtState;
+};
 
 #endif /* IMX2_WDT_H */
diff --git a/include/hw/xen/xen-block.h b/include/hw/xen/xen-block.h
index 2cd2fc2701..8ff5421dc3 100644
--- a/include/hw/xen/xen-block.h
+++ b/include/hw/xen/xen-block.h
@@ -12,6 +12,7 @@
 #include "hw/block/block.h"
 #include "hw/block/dataplane/xen-block.h"
 #include "sysemu/iothread.h"
+#include "qom/object.h"
 
 typedef enum XenBlockVdevType {
     XEN_BLOCK_VDEV_TYPE_INVALID,
@@ -46,7 +47,7 @@ typedef struct XenBlockIOThread {
     char *id;
 } XenBlockIOThread;
 
-typedef struct XenBlockDevice {
+struct XenBlockDevice {
     XenDevice xendev;
     XenBlockProperties props;
     const char *device_type;
@@ -54,41 +55,41 @@ typedef struct XenBlockDevice {
     XenBlockDataPlane *dataplane;
     XenBlockDrive *drive;
     XenBlockIOThread *iothread;
-} XenBlockDevice;
+};
+typedef struct XenBlockDevice XenBlockDevice;
 
 typedef void (*XenBlockDeviceRealize)(XenBlockDevice *blockdev, Error **errp);
 typedef void (*XenBlockDeviceUnrealize)(XenBlockDevice *blockdev);
 
-typedef struct XenBlockDeviceClass {
+struct XenBlockDeviceClass {
     /*< private >*/
     XenDeviceClass parent_class;
     /*< public >*/
     XenBlockDeviceRealize realize;
     XenBlockDeviceUnrealize unrealize;
-} XenBlockDeviceClass;
+};
+typedef struct XenBlockDeviceClass XenBlockDeviceClass;
 
 #define TYPE_XEN_BLOCK_DEVICE  "xen-block"
-#define XEN_BLOCK_DEVICE(obj) \
-     OBJECT_CHECK(XenBlockDevice, (obj), TYPE_XEN_BLOCK_DEVICE)
-#define XEN_BLOCK_DEVICE_CLASS(class) \
-     OBJECT_CLASS_CHECK(XenBlockDeviceClass, (class), TYPE_XEN_BLOCK_DEVICE)
-#define XEN_BLOCK_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(XenBlockDeviceClass, (obj), TYPE_XEN_BLOCK_DEVICE)
-
-typedef struct XenDiskDevice {
+DECLARE_OBJ_CHECKERS(XenBlockDevice, XenBlockDeviceClass,
+                     XEN_BLOCK_DEVICE, TYPE_XEN_BLOCK_DEVICE)
+
+struct XenDiskDevice {
     XenBlockDevice blockdev;
-} XenDiskDevice;
+};
+typedef struct XenDiskDevice XenDiskDevice;
 
 #define TYPE_XEN_DISK_DEVICE  "xen-disk"
-#define XEN_DISK_DEVICE(obj) \
-     OBJECT_CHECK(XenDiskDevice, (obj), TYPE_XEN_DISK_DEVICE)
+DECLARE_INSTANCE_CHECKER(XenDiskDevice, XEN_DISK_DEVICE,
+                         TYPE_XEN_DISK_DEVICE)
 
-typedef struct XenCDRomDevice {
+struct XenCDRomDevice {
     XenBlockDevice blockdev;
-} XenCDRomDevice;
+};
+typedef struct XenCDRomDevice XenCDRomDevice;
 
 #define TYPE_XEN_CDROM_DEVICE  "xen-cdrom"
-#define XEN_CDROM_DEVICE(obj) \
-     OBJECT_CHECK(XenCDRomDevice, (obj), TYPE_XEN_CDROM_DEVICE)
+DECLARE_INSTANCE_CHECKER(XenCDRomDevice, XEN_CDROM_DEVICE,
+                         TYPE_XEN_CDROM_DEVICE)
 
 #endif /* HW_XEN_BLOCK_H */
diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h
index 4ec0bb072f..e0e67505b8 100644
--- a/include/hw/xen/xen-bus.h
+++ b/include/hw/xen/xen-bus.h
@@ -11,6 +11,7 @@
 #include "hw/xen/xen_common.h"
 #include "hw/sysbus.h"
 #include "qemu/notify.h"
+#include "qom/object.h"
 
 typedef void (*XenWatchHandler)(void *opaque);
 
@@ -18,7 +19,7 @@ typedef struct XenWatchList XenWatchList;
 typedef struct XenWatch XenWatch;
 typedef struct XenEventChannel XenEventChannel;
 
-typedef struct XenDevice {
+struct XenDevice {
     DeviceState qdev;
     domid_t frontend_id;
     char *name;
@@ -35,7 +36,8 @@ typedef struct XenDevice {
     bool inactive;
     QLIST_HEAD(, XenEventChannel) event_channels;
     QLIST_ENTRY(XenDevice) list;
-} XenDevice;
+};
+typedef struct XenDevice XenDevice;
 
 typedef char *(*XenDeviceGetName)(XenDevice *xendev, Error **errp);
 typedef void (*XenDeviceRealize)(XenDevice *xendev, Error **errp);
@@ -44,7 +46,7 @@ typedef void (*XenDeviceFrontendChanged)(XenDevice *xendev,
                                          Error **errp);
 typedef void (*XenDeviceUnrealize)(XenDevice *xendev);
 
-typedef struct XenDeviceClass {
+struct XenDeviceClass {
     /*< private >*/
     DeviceClass parent_class;
     /*< public >*/
@@ -54,37 +56,30 @@ typedef struct XenDeviceClass {
     XenDeviceRealize realize;
     XenDeviceFrontendChanged frontend_changed;
     XenDeviceUnrealize unrealize;
-} XenDeviceClass;
+};
+typedef struct XenDeviceClass XenDeviceClass;
 
 #define TYPE_XEN_DEVICE "xen-device"
-#define XEN_DEVICE(obj) \
-     OBJECT_CHECK(XenDevice, (obj), TYPE_XEN_DEVICE)
-#define XEN_DEVICE_CLASS(class) \
-     OBJECT_CLASS_CHECK(XenDeviceClass, (class), TYPE_XEN_DEVICE)
-#define XEN_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(XenDeviceClass, (obj), TYPE_XEN_DEVICE)
-
-typedef struct XenBus {
+DECLARE_OBJ_CHECKERS(XenDevice, XenDeviceClass,
+                     XEN_DEVICE, TYPE_XEN_DEVICE)
+
+struct XenBus {
     BusState qbus;
     domid_t backend_id;
     struct xs_handle *xsh;
     XenWatchList *watch_list;
     XenWatch *backend_watch;
     QLIST_HEAD(, XenDevice) inactive_devices;
-} XenBus;
+};
 
-typedef struct XenBusClass {
+struct XenBusClass {
     /*< private >*/
     BusClass parent_class;
-} XenBusClass;
+};
 
 #define TYPE_XEN_BUS "xen-bus"
-#define XEN_BUS(obj) \
-    OBJECT_CHECK(XenBus, (obj), TYPE_XEN_BUS)
-#define XEN_BUS_CLASS(class) \
-    OBJECT_CLASS_CHECK(XenBusClass, (class), TYPE_XEN_BUS)
-#define XEN_BUS_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(XenBusClass, (obj), TYPE_XEN_BUS)
+OBJECT_DECLARE_TYPE(XenBus, XenBusClass,
+                    xen_bus, XEN_BUS)
 
 void xen_bus_init(void);
 
diff --git a/include/hw/xen/xen-legacy-backend.h b/include/hw/xen/xen-legacy-backend.h
index 704bc7852b..ba7a3c59bb 100644
--- a/include/hw/xen/xen-legacy-backend.h
+++ b/include/hw/xen/xen-legacy-backend.h
@@ -4,14 +4,15 @@
 #include "hw/xen/xen_common.h"
 #include "hw/xen/xen_pvdev.h"
 #include "net/net.h"
+#include "qom/object.h"
 
 #define TYPE_XENSYSDEV "xen-sysdev"
 #define TYPE_XENSYSBUS "xen-sysbus"
 #define TYPE_XENBACKEND "xen-backend"
 
 typedef struct XenLegacyDevice XenLegacyDevice;
-#define XENBACKEND_DEVICE(obj) \
-    OBJECT_CHECK(XenLegacyDevice, (obj), TYPE_XENBACKEND)
+DECLARE_INSTANCE_CHECKER(XenLegacyDevice, XENBACKEND_DEVICE,
+                         TYPE_XENBACKEND)
 
 /* variables */
 extern struct xs_handle *xenstore;
diff --git a/include/io/channel-buffer.h b/include/io/channel-buffer.h
index 3f4b3f29e1..89632ef437 100644
--- a/include/io/channel-buffer.h
+++ b/include/io/channel-buffer.h
@@ -22,12 +22,13 @@
 #define QIO_CHANNEL_BUFFER_H
 
 #include "io/channel.h"
+#include "qom/object.h"
 
 #define TYPE_QIO_CHANNEL_BUFFER "qio-channel-buffer"
-#define QIO_CHANNEL_BUFFER(obj)                                     \
-    OBJECT_CHECK(QIOChannelBuffer, (obj), TYPE_QIO_CHANNEL_BUFFER)
-
 typedef struct QIOChannelBuffer QIOChannelBuffer;
+DECLARE_INSTANCE_CHECKER(QIOChannelBuffer, QIO_CHANNEL_BUFFER,
+                         TYPE_QIO_CHANNEL_BUFFER)
+
 
 /**
  * QIOChannelBuffer:
diff --git a/include/io/channel-command.h b/include/io/channel-command.h
index 336d47fa5c..4b64ff011b 100644
--- a/include/io/channel-command.h
+++ b/include/io/channel-command.h
@@ -22,12 +22,13 @@
 #define QIO_CHANNEL_COMMAND_H
 
 #include "io/channel.h"
+#include "qom/object.h"
 
 #define TYPE_QIO_CHANNEL_COMMAND "qio-channel-command"
-#define QIO_CHANNEL_COMMAND(obj)                                     \
-    OBJECT_CHECK(QIOChannelCommand, (obj), TYPE_QIO_CHANNEL_COMMAND)
-
 typedef struct QIOChannelCommand QIOChannelCommand;
+DECLARE_INSTANCE_CHECKER(QIOChannelCommand, QIO_CHANNEL_COMMAND,
+                         TYPE_QIO_CHANNEL_COMMAND)
+
 
 
 /**
diff --git a/include/io/channel-file.h b/include/io/channel-file.h
index ebfe54ec70..c6caf179d9 100644
--- a/include/io/channel-file.h
+++ b/include/io/channel-file.h
@@ -22,12 +22,13 @@
 #define QIO_CHANNEL_FILE_H
 
 #include "io/channel.h"
+#include "qom/object.h"
 
 #define TYPE_QIO_CHANNEL_FILE "qio-channel-file"
-#define QIO_CHANNEL_FILE(obj)                                     \
-    OBJECT_CHECK(QIOChannelFile, (obj), TYPE_QIO_CHANNEL_FILE)
-
 typedef struct QIOChannelFile QIOChannelFile;
+DECLARE_INSTANCE_CHECKER(QIOChannelFile, QIO_CHANNEL_FILE,
+                         TYPE_QIO_CHANNEL_FILE)
+
 
 /**
  * QIOChannelFile:
diff --git a/include/io/channel-socket.h b/include/io/channel-socket.h
index 777ff5954e..62e3e2e970 100644
--- a/include/io/channel-socket.h
+++ b/include/io/channel-socket.h
@@ -24,12 +24,13 @@
 #include "io/channel.h"
 #include "io/task.h"
 #include "qemu/sockets.h"
+#include "qom/object.h"
 
 #define TYPE_QIO_CHANNEL_SOCKET "qio-channel-socket"
-#define QIO_CHANNEL_SOCKET(obj)                                     \
-    OBJECT_CHECK(QIOChannelSocket, (obj), TYPE_QIO_CHANNEL_SOCKET)
-
 typedef struct QIOChannelSocket QIOChannelSocket;
+DECLARE_INSTANCE_CHECKER(QIOChannelSocket, QIO_CHANNEL_SOCKET,
+                         TYPE_QIO_CHANNEL_SOCKET)
+
 
 /**
  * QIOChannelSocket:
diff --git a/include/io/channel-tls.h b/include/io/channel-tls.h
index fdbdf12feb..036bf54195 100644
--- a/include/io/channel-tls.h
+++ b/include/io/channel-tls.h
@@ -24,12 +24,13 @@
 #include "io/channel.h"
 #include "io/task.h"
 #include "crypto/tlssession.h"
+#include "qom/object.h"
 
 #define TYPE_QIO_CHANNEL_TLS "qio-channel-tls"
-#define QIO_CHANNEL_TLS(obj)                                     \
-    OBJECT_CHECK(QIOChannelTLS, (obj), TYPE_QIO_CHANNEL_TLS)
-
 typedef struct QIOChannelTLS QIOChannelTLS;
+DECLARE_INSTANCE_CHECKER(QIOChannelTLS, QIO_CHANNEL_TLS,
+                         TYPE_QIO_CHANNEL_TLS)
+
 
 /**
  * QIOChannelTLS
diff --git a/include/io/channel-websock.h b/include/io/channel-websock.h
index a7e5e92e61..b07eddabe1 100644
--- a/include/io/channel-websock.h
+++ b/include/io/channel-websock.h
@@ -24,12 +24,13 @@
 #include "io/channel.h"
 #include "qemu/buffer.h"
 #include "io/task.h"
+#include "qom/object.h"
 
 #define TYPE_QIO_CHANNEL_WEBSOCK "qio-channel-websock"
-#define QIO_CHANNEL_WEBSOCK(obj)                                     \
-    OBJECT_CHECK(QIOChannelWebsock, (obj), TYPE_QIO_CHANNEL_WEBSOCK)
-
 typedef struct QIOChannelWebsock QIOChannelWebsock;
+DECLARE_INSTANCE_CHECKER(QIOChannelWebsock, QIO_CHANNEL_WEBSOCK,
+                         TYPE_QIO_CHANNEL_WEBSOCK)
+
 typedef union QIOChannelWebsockMask QIOChannelWebsockMask;
 
 union QIOChannelWebsockMask {
diff --git a/include/io/channel.h b/include/io/channel.h
index d4557f0930..245479548a 100644
--- a/include/io/channel.h
+++ b/include/io/channel.h
@@ -26,15 +26,9 @@
 #include "block/aio.h"
 
 #define TYPE_QIO_CHANNEL "qio-channel"
-#define QIO_CHANNEL(obj)                                    \
-    OBJECT_CHECK(QIOChannel, (obj), TYPE_QIO_CHANNEL)
-#define QIO_CHANNEL_CLASS(klass)                                    \
-    OBJECT_CLASS_CHECK(QIOChannelClass, klass, TYPE_QIO_CHANNEL)
-#define QIO_CHANNEL_GET_CLASS(obj)                                  \
-    OBJECT_GET_CLASS(QIOChannelClass, obj, TYPE_QIO_CHANNEL)
-
-typedef struct QIOChannel QIOChannel;
-typedef struct QIOChannelClass QIOChannelClass;
+OBJECT_DECLARE_TYPE(QIOChannel, QIOChannelClass,
+                    qio_channel, QIO_CHANNEL)
+
 
 #define QIO_CHANNEL_ERR_BLOCK -2
 
diff --git a/include/io/dns-resolver.h b/include/io/dns-resolver.h
index a475e978c8..e248fba5bd 100644
--- a/include/io/dns-resolver.h
+++ b/include/io/dns-resolver.h
@@ -26,15 +26,9 @@
 #include "io/task.h"
 
 #define TYPE_QIO_DNS_RESOLVER "qio-dns-resolver"
-#define QIO_DNS_RESOLVER(obj)                                    \
-    OBJECT_CHECK(QIODNSResolver, (obj), TYPE_QIO_DNS_RESOLVER)
-#define QIO_DNS_RESOLVER_CLASS(klass)                                    \
-    OBJECT_CLASS_CHECK(QIODNSResolverClass, klass, TYPE_QIO_DNS_RESOLVER)
-#define QIO_DNS_RESOLVER_GET_CLASS(obj)                                  \
-    OBJECT_GET_CLASS(QIODNSResolverClass, obj, TYPE_QIO_DNS_RESOLVER)
+OBJECT_DECLARE_SIMPLE_TYPE(QIODNSResolver, qio_dns_resolver,
+                           QIO_DNS_RESOLVER, ObjectClass)
 
-typedef struct QIODNSResolver QIODNSResolver;
-typedef struct QIODNSResolverClass QIODNSResolverClass;
 
 /**
  * QIODNSResolver:
@@ -139,9 +133,6 @@ struct QIODNSResolver {
     Object parent;
 };
 
-struct QIODNSResolverClass {
-    ObjectClass parent;
-};
 
 
 /**
diff --git a/include/io/net-listener.h b/include/io/net-listener.h
index fb101703e3..60fad29ff4 100644
--- a/include/io/net-listener.h
+++ b/include/io/net-listener.h
@@ -22,17 +22,12 @@
 #define QIO_NET_LISTENER_H
 
 #include "io/channel-socket.h"
+#include "qom/object.h"
 
 #define TYPE_QIO_NET_LISTENER "qio-net-listener"
-#define QIO_NET_LISTENER(obj)                                    \
-    OBJECT_CHECK(QIONetListener, (obj), TYPE_QIO_NET_LISTENER)
-#define QIO_NET_LISTENER_CLASS(klass)                                    \
-    OBJECT_CLASS_CHECK(QIONetListenerClass, klass, TYPE_QIO_NET_LISTENER)
-#define QIO_NET_LISTENER_GET_CLASS(obj)                                  \
-    OBJECT_GET_CLASS(QIONetListenerClass, obj, TYPE_QIO_NET_LISTENER)
+OBJECT_DECLARE_SIMPLE_TYPE(QIONetListener, qio_net_listener,
+                           QIO_NET_LISTENER, ObjectClass)
 
-typedef struct QIONetListener QIONetListener;
-typedef struct QIONetListenerClass QIONetListenerClass;
 
 typedef void (*QIONetListenerClientFunc)(QIONetListener *listener,
                                          QIOChannelSocket *sioc,
@@ -63,9 +58,6 @@ struct QIONetListener {
     GDestroyNotify io_notify;
 };
 
-struct QIONetListenerClass {
-    ObjectClass parent;
-};
 
 
 /**
diff --git a/include/net/can_emu.h b/include/net/can_emu.h
index 7e90fd8a45..150f91a657 100644
--- a/include/net/can_emu.h
+++ b/include/net/can_emu.h
@@ -100,8 +100,8 @@ struct CanBusClientState {
 };
 
 #define TYPE_CAN_BUS "can-bus"
-#define CAN_BUS(obj) \
-     OBJECT_CHECK(CanBusState, (obj), TYPE_CAN_BUS)
+DECLARE_INSTANCE_CHECKER(CanBusState, CAN_BUS,
+                         TYPE_CAN_BUS)
 
 int can_bus_filter_match(struct qemu_can_filter *filter, qemu_canid_t can_id);
 
diff --git a/include/net/can_host.h b/include/net/can_host.h
index d79676746b..18979c2e2d 100644
--- a/include/net/can_host.h
+++ b/include/net/can_host.h
@@ -29,27 +29,26 @@
 #define NET_CAN_HOST_H
 
 #include "net/can_emu.h"
+#include "qom/object.h"
 
 #define TYPE_CAN_HOST "can-host"
-#define CAN_HOST_CLASS(klass) \
-     OBJECT_CLASS_CHECK(CanHostClass, (klass), TYPE_CAN_HOST)
-#define CAN_HOST_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(CanHostClass, (obj), TYPE_CAN_HOST)
-#define CAN_HOST(obj) \
-     OBJECT_CHECK(CanHostState, (obj), TYPE_CAN_HOST)
-
-typedef struct CanHostState {
+typedef struct CanHostClass CanHostClass;
+typedef struct CanHostState CanHostState;
+DECLARE_OBJ_CHECKERS(CanHostState, CanHostClass,
+                     CAN_HOST, TYPE_CAN_HOST)
+
+struct CanHostState {
     ObjectClass oc;
 
     CanBusState *bus;
     CanBusClientState bus_client;
-} CanHostState;
+};
 
-typedef struct CanHostClass {
+struct CanHostClass {
     ObjectClass oc;
 
     void (*connect)(CanHostState *ch, Error **errp);
     void (*disconnect)(CanHostState *ch);
-} CanHostClass;
+};
 
 #endif
diff --git a/include/net/filter.h b/include/net/filter.h
index 9393c59192..e7e593128a 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -15,12 +15,9 @@
 #include "net/queue.h"
 
 #define TYPE_NETFILTER "netfilter"
-#define NETFILTER(obj) \
-    OBJECT_CHECK(NetFilterState, (obj), TYPE_NETFILTER)
-#define NETFILTER_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(NetFilterClass, (obj), TYPE_NETFILTER)
-#define NETFILTER_CLASS(klass) \
-    OBJECT_CLASS_CHECK(NetFilterClass, (klass), TYPE_NETFILTER)
+typedef struct NetFilterClass NetFilterClass;
+DECLARE_OBJ_CHECKERS(NetFilterState, NetFilterClass,
+                     NETFILTER, TYPE_NETFILTER)
 
 typedef void (FilterSetup) (NetFilterState *nf, Error **errp);
 typedef void (FilterCleanup) (NetFilterState *nf);
@@ -40,7 +37,7 @@ typedef void (FilterStatusChanged) (NetFilterState *nf, Error **errp);
 
 typedef void (FilterHandleEvent) (NetFilterState *nf, int event, Error **errp);
 
-typedef struct NetFilterClass {
+struct NetFilterClass {
     ObjectClass parent_class;
 
     /* optional */
@@ -50,7 +47,7 @@ typedef struct NetFilterClass {
     FilterHandleEvent *handle_event;
     /* mandatory */
     FilterReceiveIOV *receive_iov;
-} NetFilterClass;
+};
 
 
 struct NetFilterState {
diff --git a/include/qemu-common.h b/include/qemu-common.h
index bb9496bd80..9cfd62669b 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -138,7 +138,8 @@ int os_parse_cmd_args(int index, const char *optarg);
  * Hexdump a buffer to a file. An optional string prefix is added to every line
  */
 
-void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size);
+void qemu_hexdump(FILE *fp, const char *prefix,
+                  const void *bufptr, size_t size);
 
 /*
  * helper to parse debug environment variables
diff --git a/include/qom/object.h b/include/qom/object.h
index 0f3a60617c..056f67ab3b 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -16,6 +16,7 @@
 
 #include "qapi/qapi-builtin-types.h"
 #include "qemu/module.h"
+#include "qom/object.h"
 
 struct TypeImpl;
 typedef struct TypeImpl *Type;
@@ -304,6 +305,119 @@ typedef struct InterfaceInfo InterfaceInfo;
  *
  * The first example of such a QOM method was #CPUClass.reset,
  * another example is #DeviceClass.realize.
+ *
+ * # Standard type declaration and definition macros #
+ *
+ * A lot of the code outlined above follows a standard pattern and naming
+ * convention. To reduce the amount of boilerplate code that needs to be
+ * written for a new type there are two sets of macros to generate the
+ * common parts in a standard format.
+ *
+ * A type is declared using the OBJECT_DECLARE macro family. In types
+ * which do not require any virtual functions in the class, the
+ * OBJECT_DECLARE_SIMPLE_TYPE macro is suitable, and is commonly placed
+ * in the header file:
+ *
+ * <example>
+ *   <title>Declaring a simple type</title>
+ *   <programlisting>
+ *     OBJECT_DECLARE_SIMPLE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)
+ *   </programlisting>
+ * </example>
+ *
+ * This is equivalent to the following:
+ *
+ * <example>
+ *   <title>Expansion from declaring a simple type</title>
+ *   <programlisting>
+ *     typedef struct MyDevice MyDevice;
+ *     typedef struct MyDeviceClass MyDeviceClass;
+ *
+ *     G_DEFINE_AUTOPTR_CLEANUP_FUNC(MyDeviceClass, object_unref)
+ *
+ *     #define MY_DEVICE_GET_CLASS(void *obj) \
+ *             OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE)
+ *     #define MY_DEVICE_CLASS(void *klass) \
+ *             OBJECT_CLASS_CHECK(MyDeviceClass, klass, TYPE_MY_DEVICE)
+ *     #define MY_DEVICE(void *obj)
+ *             OBJECT_CHECK(MyDevice, obj, TYPE_MY_DEVICE)
+ *
+ *     struct MyDeviceClass {
+ *         DeviceClass parent_class;
+ *     };
+ *   </programlisting>
+ * </example>
+ *
+ * The 'struct MyDevice' needs to be declared separately.
+ * If the type requires virtual functions to be declared in the class
+ * struct, then the alternative OBJECT_DECLARE_TYPE() macro can be
+ * used. This does the same as OBJECT_DECLARE_SIMPLE_TYPE(), but without
+ * the 'struct MyDeviceClass' definition.
+ *
+ * To implement the type, the OBJECT_DEFINE macro family is available.
+ * In the simple case the OBJECT_DEFINE_TYPE macro is suitable:
+ *
+ * <example>
+ *   <title>Defining a simple type</title>
+ *   <programlisting>
+ *     OBJECT_DEFINE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)
+ *   </programlisting>
+ * </example>
+ *
+ * This is equivalent to the following:
+ *
+ * <example>
+ *   <title>Expansion from defining a simple type</title>
+ *   <programlisting>
+ *     static void my_device_finalize(Object *obj);
+ *     static void my_device_class_init(ObjectClass *oc, void *data);
+ *     static void my_device_init(Object *obj);
+ *
+ *     static const TypeInfo my_device_info = {
+ *         .parent = TYPE_DEVICE,
+ *         .name = TYPE_MY_DEVICE,
+ *         .instance_size = sizeof(MyDevice),
+ *         .instance_init = my_device_init,
+ *         .instance_finalize = my_device_finalize,
+ *         .class_size = sizeof(MyDeviceClass),
+ *         .class_init = my_device_class_init,
+ *     };
+ *
+ *     static void
+ *     my_device_register_types(void)
+ *     {
+ *         type_register_static(&my_device_info);
+ *     }
+ *     type_init(my_device_register_types);
+ *   </programlisting>
+ * </example>
+ *
+ * This is sufficient to get the type registered with the type
+ * system, and the three standard methods now need to be implemented
+ * along with any other logic required for the type.
+ *
+ * If the type needs to implement one or more interfaces, then the
+ * OBJECT_DEFINE_TYPE_WITH_INTERFACES() macro can be used instead.
+ * This accepts an array of interface type names.
+ *
+ * <example>
+ *   <title>Defining a simple type implementing interfaces</title>
+ *   <programlisting>
+ *     OBJECT_DEFINE_TYPE_WITH_INTERFACES(MyDevice, my_device,
+ *                                        MY_DEVICE, DEVICE,
+ *                                        { TYPE_USER_CREATABLE }, { NULL })
+ *   </programlisting>
+ * </example>
+ *
+ * If the type is not intended to be instantiated, then then
+ * the OBJECT_DEFINE_ABSTRACT_TYPE() macro can be used instead:
+ *
+ * <example>
+ *   <title>Defining a simple type</title>
+ *   <programlisting>
+ *     OBJECT_DEFINE_ABSTRACT_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)
+ *   </programlisting>
+ * </example>
  */
 
 
@@ -441,6 +555,215 @@ struct Object
 };
 
 /**
+ * DECLARE_INSTANCE_CHECKER:
+ * @InstanceType: instance struct name
+ * @OBJ_NAME: the object name in uppercase with underscore separators
+ * @TYPENAME: type name
+ *
+ * Direct usage of this macro should be avoided, and the complete
+ * OBJECT_DECLARE_TYPE macro is recommended instead.
+ *
+ * This macro will provide the three standard type cast functions for a
+ * QOM type.
+ */
+#define DECLARE_INSTANCE_CHECKER(InstanceType, OBJ_NAME, TYPENAME) \
+    static inline G_GNUC_UNUSED InstanceType * \
+    OBJ_NAME(const void *obj) \
+    { return OBJECT_CHECK(InstanceType, obj, TYPENAME); }
+
+/**
+ * DECLARE_CLASS_CHECKERS:
+ * @ClassType: class struct name
+ * @OBJ_NAME: the object name in uppercase with underscore separators
+ * @TYPENAME: type name
+ *
+ * Direct usage of this macro should be avoided, and the complete
+ * OBJECT_DECLARE_TYPE macro is recommended instead.
+ *
+ * This macro will provide the three standard type cast functions for a
+ * QOM type.
+ */
+#define DECLARE_CLASS_CHECKERS(ClassType, OBJ_NAME, TYPENAME) \
+    static inline G_GNUC_UNUSED ClassType * \
+    OBJ_NAME##_GET_CLASS(const void *obj) \
+    { return OBJECT_GET_CLASS(ClassType, obj, TYPENAME); } \
+    \
+    static inline G_GNUC_UNUSED ClassType * \
+    OBJ_NAME##_CLASS(const void *klass) \
+    { return OBJECT_CLASS_CHECK(ClassType, klass, TYPENAME); }
+
+/**
+ * DECLARE_OBJ_CHECKERS:
+ * @InstanceType: instance struct name
+ * @ClassType: class struct name
+ * @OBJ_NAME: the object name in uppercase with underscore separators
+ * @TYPENAME: type name
+ *
+ * Direct usage of this macro should be avoided, and the complete
+ * OBJECT_DECLARE_TYPE macro is recommended instead.
+ *
+ * This macro will provide the three standard type cast functions for a
+ * QOM type.
+ */
+#define DECLARE_OBJ_CHECKERS(InstanceType, ClassType, OBJ_NAME, TYPENAME) \
+    DECLARE_INSTANCE_CHECKER(InstanceType, OBJ_NAME, TYPENAME) \
+    \
+    DECLARE_CLASS_CHECKERS(ClassType, OBJ_NAME, TYPENAME)
+
+/**
+ * OBJECT_DECLARE_TYPE:
+ * @InstanceType: instance struct name
+ * @ClassType: class struct name
+ * @module_obj_name: the object name in lowercase with underscore separators
+ * @MODULE_OBJ_NAME: the object name in uppercase with underscore separators
+ *
+ * This macro is typically used in a header file, and will:
+ *
+ *   - create the typedefs for the object and class structs
+ *   - register the type for use with g_autoptr
+ *   - provide three standard type cast functions
+ *
+ * The object struct and class struct need to be declared manually.
+ */
+#define OBJECT_DECLARE_TYPE(InstanceType, ClassType, module_obj_name, MODULE_OBJ_NAME) \
+    typedef struct InstanceType InstanceType; \
+    typedef struct ClassType ClassType; \
+    \
+    G_DEFINE_AUTOPTR_CLEANUP_FUNC(InstanceType, object_unref) \
+    \
+    DECLARE_OBJ_CHECKERS(InstanceType, ClassType, \
+                         MODULE_OBJ_NAME, TYPE_##MODULE_OBJ_NAME)
+
+/**
+ * OBJECT_DECLARE_SIMPLE_TYPE:
+ * @InstanceType: instance struct name
+ * @module_obj_name: the object name in lowercase with underscore separators
+ * @MODULE_OBJ_NAME: the object name in uppercase with underscore separators
+ * @ParentClassType: class struct name of parent type
+ *
+ * This does the same as OBJECT_DECLARE_TYPE(), but also declares
+ * the class struct, thus only the object struct needs to be declare
+ * manually.
+ *
+ * This macro should be used unless the class struct needs to have
+ * virtual methods declared.
+ */
+#define OBJECT_DECLARE_SIMPLE_TYPE(InstanceType, module_obj_name, \
+                                   MODULE_OBJ_NAME, ParentClassType) \
+    OBJECT_DECLARE_TYPE(InstanceType, InstanceType##Class, module_obj_name, MODULE_OBJ_NAME) \
+    struct InstanceType##Class { ParentClassType parent_class; };
+
+
+/**
+ * OBJECT_DEFINE_TYPE_EXTENDED:
+ * @ModuleObjName: the object name with initial caps
+ * @module_obj_name: the object name in lowercase with underscore separators
+ * @MODULE_OBJ_NAME: the object name in uppercase with underscore separators
+ * @PARENT_MODULE_OBJ_NAME: the parent object name in uppercase with underscore
+ *                          separators
+ * @ABSTRACT: boolean flag to indicate whether the object can be instantiated
+ * @...: list of initializers for "InterfaceInfo" to declare implemented interfaces
+ *
+ * This macro is typically used in a source file, and will:
+ *
+ *   - declare prototypes for _finalize, _class_init and _init methods
+ *   - declare the TypeInfo struct instance
+ *   - provide the constructor to register the type
+ *
+ * After using this macro, implementations of the _finalize, _class_init,
+ * and _init methods need to be written. Any of these can be zero-line
+ * no-op impls if no special logic is required for a given type.
+ *
+ * This macro should rarely be used, instead one of the more specialized
+ * macros is usually a better choice.
+ */
+#define OBJECT_DEFINE_TYPE_EXTENDED(ModuleObjName, module_obj_name, \
+                                    MODULE_OBJ_NAME, PARENT_MODULE_OBJ_NAME, \
+                                    ABSTRACT, ...) \
+    static void \
+    module_obj_name##_finalize(Object *obj); \
+    static void \
+    module_obj_name##_class_init(ObjectClass *oc, void *data); \
+    static void \
+    module_obj_name##_init(Object *obj); \
+    \
+    static const TypeInfo module_obj_name##_info = { \
+        .parent = TYPE_##PARENT_MODULE_OBJ_NAME, \
+        .name = TYPE_##MODULE_OBJ_NAME, \
+        .instance_size = sizeof(ModuleObjName), \
+        .instance_init = module_obj_name##_init, \
+        .instance_finalize = module_obj_name##_finalize, \
+        .class_size = sizeof(ModuleObjName##Class), \
+        .class_init = module_obj_name##_class_init, \
+        .abstract = ABSTRACT, \
+        .interfaces = (InterfaceInfo[]) { __VA_ARGS__ } , \
+    }; \
+    \
+    static void \
+    module_obj_name##_register_types(void) \
+    { \
+        type_register_static(&module_obj_name##_info); \
+    } \
+    type_init(module_obj_name##_register_types);
+
+/**
+ * OBJECT_DEFINE_TYPE:
+ * @ModuleObjName: the object name with initial caps
+ * @module_obj_name: the object name in lowercase with underscore separators
+ * @MODULE_OBJ_NAME: the object name in uppercase with underscore separators
+ * @PARENT_MODULE_OBJ_NAME: the parent object name in uppercase with underscore
+ *                          separators
+ *
+ * This is a specialization of OBJECT_DEFINE_TYPE_EXTENDED, which is suitable
+ * for the common case of a non-abstract type, without any interfaces.
+ */
+#define OBJECT_DEFINE_TYPE(ModuleObjName, module_obj_name, MODULE_OBJ_NAME, \
+                           PARENT_MODULE_OBJ_NAME) \
+    OBJECT_DEFINE_TYPE_EXTENDED(ModuleObjName, module_obj_name, \
+                                MODULE_OBJ_NAME, PARENT_MODULE_OBJ_NAME, \
+                                false, { NULL })
+
+/**
+ * OBJECT_DEFINE_TYPE_WITH_INTERFACES:
+ * @ModuleObjName: the object name with initial caps
+ * @module_obj_name: the object name in lowercase with underscore separators
+ * @MODULE_OBJ_NAME: the object name in uppercase with underscore separators
+ * @PARENT_MODULE_OBJ_NAME: the parent object name in uppercase with underscore
+ *                          separators
+ * @...: list of initializers for "InterfaceInfo" to declare implemented interfaces
+ *
+ * This is a specialization of OBJECT_DEFINE_TYPE_EXTENDED, which is suitable
+ * for the common case of a non-abstract type, with one or more implemented
+ * interfaces.
+ *
+ * Note when passing the list of interfaces, be sure to include the final
+ * NULL entry, e.g.  { TYPE_USER_CREATABLE }, { NULL }
+ */
+#define OBJECT_DEFINE_TYPE_WITH_INTERFACES(ModuleObjName, module_obj_name, \
+                                           MODULE_OBJ_NAME, \
+                                           PARENT_MODULE_OBJ_NAME, ...) \
+    OBJECT_DEFINE_TYPE_EXTENDED(ModuleObjName, module_obj_name, \
+                                MODULE_OBJ_NAME, PARENT_MODULE_OBJ_NAME, \
+                                false, __VA_ARGS__)
+
+/**
+ * OBJECT_DEFINE_ABSTRACT_TYPE:
+ * @ModuleObjName: the object name with initial caps
+ * @module_obj_name: the object name in lowercase with underscore separators
+ * @MODULE_OBJ_NAME: the object name in uppercase with underscore separators
+ * @PARENT_MODULE_OBJ_NAME: the parent object name in uppercase with underscore
+ *                          separators
+ *
+ * This is a specialization of OBJECT_DEFINE_TYPE_EXTENDED, which is suitable
+ * for defining an abstract type, without any interfaces.
+ */
+#define OBJECT_DEFINE_ABSTRACT_TYPE(ModuleObjName, module_obj_name, \
+                                    MODULE_OBJ_NAME, PARENT_MODULE_OBJ_NAME) \
+    OBJECT_DEFINE_TYPE_EXTENDED(ModuleObjName, module_obj_name, \
+                                MODULE_OBJ_NAME, PARENT_MODULE_OBJ_NAME, \
+                                true, { NULL })
+
+/**
  * TypeInfo:
  * @name: The name of the type.
  * @parent: The name of the parent type.
@@ -1035,7 +1358,7 @@ GSList *object_class_get_list_sorted(const char *implements_type,
  * as its reference count is greater than zero.
  * Returns: @obj
  */
-Object *object_ref(Object *obj);
+Object *object_ref(void *obj);
 
 /**
  * object_unref:
@@ -1044,7 +1367,7 @@ Object *object_ref(Object *obj);
  * Decrease the reference count of a object.  A object cannot be freed as long
  * as its reference count is greater than zero.
  */
-void object_unref(Object *obj);
+void object_unref(void *obj);
 
 /**
  * object_property_try_add:
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
index 7035829337..f118fb516b 100644
--- a/include/qom/object_interfaces.h
+++ b/include/qom/object_interfaces.h
@@ -6,12 +6,9 @@
 
 #define TYPE_USER_CREATABLE "user-creatable"
 
-#define USER_CREATABLE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(UserCreatableClass, (klass), \
-                        TYPE_USER_CREATABLE)
-#define USER_CREATABLE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(UserCreatableClass, (obj), \
-                      TYPE_USER_CREATABLE)
+typedef struct UserCreatableClass UserCreatableClass;
+DECLARE_CLASS_CHECKERS(UserCreatableClass, USER_CREATABLE,
+                       TYPE_USER_CREATABLE)
 #define USER_CREATABLE(obj) \
      INTERFACE_CHECK(UserCreatable, (obj), \
                      TYPE_USER_CREATABLE)
@@ -40,14 +37,14 @@ typedef struct UserCreatable UserCreatable;
  * object's type implements USER_CREATABLE interface and needs
  * complete() callback to be called.
  */
-typedef struct UserCreatableClass {
+struct UserCreatableClass {
     /* <private> */
     InterfaceClass parent_class;
 
     /* <public> */
     void (*complete)(UserCreatable *uc, Error **errp);
     bool (*can_be_deleted)(UserCreatable *uc);
-} UserCreatableClass;
+};
 
 /**
  * user_creatable_complete:
diff --git a/include/scsi/pr-manager.h b/include/scsi/pr-manager.h
index 6ad5fd1ff7..26bd134531 100644
--- a/include/scsi/pr-manager.h
+++ b/include/scsi/pr-manager.h
@@ -9,33 +9,29 @@
 
 #define TYPE_PR_MANAGER "pr-manager"
 
-#define PR_MANAGER_CLASS(klass) \
-     OBJECT_CLASS_CHECK(PRManagerClass, (klass), TYPE_PR_MANAGER)
-#define PR_MANAGER_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PRManagerClass, (obj), TYPE_PR_MANAGER)
-#define PR_MANAGER(obj) \
-     OBJECT_CHECK(PRManager, (obj), TYPE_PR_MANAGER)
+OBJECT_DECLARE_TYPE(PRManager, PRManagerClass,
+                    pr_manager, PR_MANAGER)
 
 struct sg_io_hdr;
 
-typedef struct PRManager {
+struct PRManager {
     /* <private> */
     Object parent;
-} PRManager;
+};
 
 /**
  * PRManagerClass:
  * @parent_class: the base class
  * @run: callback invoked in thread pool context
  */
-typedef struct PRManagerClass {
+struct PRManagerClass {
     /* <private> */
     ObjectClass parent_class;
 
     /* <public> */
     int (*run)(PRManager *pr_mgr, int fd, struct sg_io_hdr *hdr);
     bool (*is_connected)(PRManager *pr_mgr);
-} PRManagerClass;
+};
 
 bool pr_manager_is_connected(PRManager *pr_mgr);
 int coroutine_fn pr_manager_execute(PRManager *pr_mgr, AioContext *ctx, int fd,
diff --git a/include/sysemu/cryptodev.h b/include/sysemu/cryptodev.h
index 35eab06d0e..06726f7014 100644
--- a/include/sysemu/cryptodev.h
+++ b/include/sysemu/cryptodev.h
@@ -37,15 +37,8 @@
 
 #define TYPE_CRYPTODEV_BACKEND "cryptodev-backend"
 
-#define CRYPTODEV_BACKEND(obj) \
-    OBJECT_CHECK(CryptoDevBackend, \
-                 (obj), TYPE_CRYPTODEV_BACKEND)
-#define CRYPTODEV_BACKEND_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(CryptoDevBackendClass, \
-                 (obj), TYPE_CRYPTODEV_BACKEND)
-#define CRYPTODEV_BACKEND_CLASS(klass) \
-    OBJECT_CLASS_CHECK(CryptoDevBackendClass, \
-                (klass), TYPE_CRYPTODEV_BACKEND)
+OBJECT_DECLARE_TYPE(CryptoDevBackend, CryptoDevBackendClass,
+                    cryptodev_backend, CRYPTODEV_BACKEND)
 
 
 #define MAX_CRYPTO_QUEUE_NUM  64
@@ -54,7 +47,6 @@ typedef struct CryptoDevBackendConf CryptoDevBackendConf;
 typedef struct CryptoDevBackendPeers CryptoDevBackendPeers;
 typedef struct CryptoDevBackendClient
                      CryptoDevBackendClient;
-typedef struct CryptoDevBackend CryptoDevBackend;
 
 enum CryptoDevBackendAlgType {
     CRYPTODEV_BACKEND_ALG_SYM,
@@ -146,7 +138,7 @@ typedef struct CryptoDevBackendSymOpInfo {
     uint8_t data[];
 } CryptoDevBackendSymOpInfo;
 
-typedef struct CryptoDevBackendClass {
+struct CryptoDevBackendClass {
     ObjectClass parent_class;
 
     void (*init)(CryptoDevBackend *backend, Error **errp);
@@ -161,7 +153,7 @@ typedef struct CryptoDevBackendClass {
     int (*do_sym_op)(CryptoDevBackend *backend,
                      CryptoDevBackendSymOpInfo *op_info,
                      uint32_t queue_index, Error **errp);
-} CryptoDevBackendClass;
+};
 
 typedef enum CryptoDevBackendOptionsType {
     CRYPTODEV_BACKEND_TYPE_NONE = 0,
diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h
index 8276e53683..e5b7a152d3 100644
--- a/include/sysemu/hostmem.h
+++ b/include/sysemu/hostmem.h
@@ -20,12 +20,8 @@
 #include "qemu/bitmap.h"
 
 #define TYPE_MEMORY_BACKEND "memory-backend"
-#define MEMORY_BACKEND(obj) \
-    OBJECT_CHECK(HostMemoryBackend, (obj), TYPE_MEMORY_BACKEND)
-#define MEMORY_BACKEND_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(HostMemoryBackendClass, (obj), TYPE_MEMORY_BACKEND)
-#define MEMORY_BACKEND_CLASS(klass) \
-    OBJECT_CLASS_CHECK(HostMemoryBackendClass, (klass), TYPE_MEMORY_BACKEND)
+OBJECT_DECLARE_TYPE(HostMemoryBackend, HostMemoryBackendClass,
+                    memory_backend, MEMORY_BACKEND)
 
 /* hostmem-ram.c */
 /**
@@ -42,8 +38,6 @@
  */
 #define TYPE_MEMORY_BACKEND_FILE "memory-backend-file"
 
-typedef struct HostMemoryBackend HostMemoryBackend;
-typedef struct HostMemoryBackendClass HostMemoryBackendClass;
 
 /**
  * HostMemoryBackendClass:
diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h
index 760d6c79a2..1398679458 100644
--- a/include/sysemu/hvf.h
+++ b/include/sysemu/hvf.h
@@ -14,6 +14,7 @@
 #define HVF_H
 
 #include "sysemu/accel.h"
+#include "qom/object.h"
 
 #ifdef CONFIG_HVF
 uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
@@ -36,7 +37,7 @@ void hvf_vcpu_destroy(CPUState *);
 #define TYPE_HVF_ACCEL ACCEL_CLASS_NAME("hvf")
 
 typedef struct HVFState HVFState;
-#define HVF_STATE(obj) \
-    OBJECT_CHECK(HVFState, (obj), TYPE_HVF_ACCEL)
+DECLARE_INSTANCE_CHECKER(HVFState, HVF_STATE,
+                         TYPE_HVF_ACCEL)
 
 #endif
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
index 6181486401..0c5284dbbc 100644
--- a/include/sysemu/iothread.h
+++ b/include/sysemu/iothread.h
@@ -20,7 +20,7 @@
 
 #define TYPE_IOTHREAD "iothread"
 
-typedef struct {
+struct IOThread {
     Object parent_obj;
 
     QemuThread thread;
@@ -37,10 +37,11 @@ typedef struct {
     int64_t poll_max_ns;
     int64_t poll_grow;
     int64_t poll_shrink;
-} IOThread;
+};
+typedef struct IOThread IOThread;
 
-#define IOTHREAD(obj) \
-   OBJECT_CHECK(IOThread, obj, TYPE_IOTHREAD)
+DECLARE_INSTANCE_CHECKER(IOThread, IOTHREAD,
+                         TYPE_IOTHREAD)
 
 char *iothread_get_id(IOThread *iothread);
 IOThread *iothread_by_id(const char *id);
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 8445a88db1..5bbea53883 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -18,6 +18,7 @@
 #include "hw/core/cpu.h"
 #include "exec/memattrs.h"
 #include "sysemu/accel.h"
+#include "qom/object.h"
 
 #ifdef NEED_CPU_H
 # ifdef CONFIG_KVM
@@ -203,8 +204,8 @@ struct KVMState;
 
 #define TYPE_KVM_ACCEL ACCEL_CLASS_NAME("kvm")
 typedef struct KVMState KVMState;
-#define KVM_STATE(obj) \
-    OBJECT_CHECK(KVMState, (obj), TYPE_KVM_ACCEL)
+DECLARE_INSTANCE_CHECKER(KVMState, KVM_STATE,
+                         TYPE_KVM_ACCEL)
 
 extern KVMState *kvm_state;
 typedef struct Notifier Notifier;
diff --git a/include/sysemu/rng-random.h b/include/sysemu/rng-random.h
index 38186fe83d..58033ac3fe 100644
--- a/include/sysemu/rng-random.h
+++ b/include/sysemu/rng-random.h
@@ -15,8 +15,9 @@
 #include "qom/object.h"
 
 #define TYPE_RNG_RANDOM "rng-random"
-#define RNG_RANDOM(obj) OBJECT_CHECK(RngRandom, (obj), TYPE_RNG_RANDOM)
-
 typedef struct RngRandom RngRandom;
+DECLARE_INSTANCE_CHECKER(RngRandom, RNG_RANDOM,
+                         TYPE_RNG_RANDOM)
+
 
 #endif
diff --git a/include/sysemu/rng.h b/include/sysemu/rng.h
index fa6eada78c..cee45a4787 100644
--- a/include/sysemu/rng.h
+++ b/include/sysemu/rng.h
@@ -17,18 +17,12 @@
 #include "qom/object.h"
 
 #define TYPE_RNG_BACKEND "rng-backend"
-#define RNG_BACKEND(obj) \
-    OBJECT_CHECK(RngBackend, (obj), TYPE_RNG_BACKEND)
-#define RNG_BACKEND_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(RngBackendClass, (obj), TYPE_RNG_BACKEND)
-#define RNG_BACKEND_CLASS(klass) \
-    OBJECT_CLASS_CHECK(RngBackendClass, (klass), TYPE_RNG_BACKEND)
+OBJECT_DECLARE_TYPE(RngBackend, RngBackendClass,
+                    rng_backend, RNG_BACKEND)
 
 #define TYPE_RNG_BUILTIN "rng-builtin"
 
 typedef struct RngRequest RngRequest;
-typedef struct RngBackendClass RngBackendClass;
-typedef struct RngBackend RngBackend;
 
 typedef void (EntropyReceiveFunc)(void *opaque,
                                   const void *data,
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 730c61ac97..1a85564e47 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -26,22 +26,21 @@ typedef enum TPMVersion {
 } TPMVersion;
 
 #define TYPE_TPM_IF "tpm-if"
-#define TPM_IF_CLASS(klass)                                 \
-    OBJECT_CLASS_CHECK(TPMIfClass, (klass), TYPE_TPM_IF)
-#define TPM_IF_GET_CLASS(obj)                           \
-    OBJECT_GET_CLASS(TPMIfClass, (obj), TYPE_TPM_IF)
+typedef struct TPMIfClass TPMIfClass;
+DECLARE_CLASS_CHECKERS(TPMIfClass, TPM_IF,
+                       TYPE_TPM_IF)
 #define TPM_IF(obj)                             \
     INTERFACE_CHECK(TPMIf, (obj), TYPE_TPM_IF)
 
 typedef struct TPMIf TPMIf;
 
-typedef struct TPMIfClass {
+struct TPMIfClass {
     InterfaceClass parent_class;
 
     enum TpmModel model;
     void (*request_completed)(TPMIf *obj, int ret);
     enum TPMVersion (*get_version)(TPMIf *obj);
-} TPMIfClass;
+};
 
 #define TYPE_TPM_TIS_ISA            "tpm-tis"
 #define TYPE_TPM_TIS_SYSBUS         "tpm-tis-device"
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index 9e7451fb52..7e8a014031 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -19,15 +19,9 @@
 #include "qapi/error.h"
 
 #define TYPE_TPM_BACKEND "tpm-backend"
-#define TPM_BACKEND(obj) \
-    OBJECT_CHECK(TPMBackend, (obj), TYPE_TPM_BACKEND)
-#define TPM_BACKEND_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(TPMBackendClass, (obj), TYPE_TPM_BACKEND)
-#define TPM_BACKEND_CLASS(klass) \
-    OBJECT_CLASS_CHECK(TPMBackendClass, (klass), TYPE_TPM_BACKEND)
-
-typedef struct TPMBackendClass TPMBackendClass;
-typedef struct TPMBackend TPMBackend;
+OBJECT_DECLARE_TYPE(TPMBackend, TPMBackendClass,
+                    tpm_backend, TPM_BACKEND)
+
 
 typedef struct TPMBackendCmd {
     uint8_t locty;
diff --git a/include/sysemu/vhost-user-backend.h b/include/sysemu/vhost-user-backend.h
index 9abf8f06a1..23205edeb8 100644
--- a/include/sysemu/vhost-user-backend.h
+++ b/include/sysemu/vhost-user-backend.h
@@ -22,19 +22,10 @@
 #include "io/channel.h"
 
 #define TYPE_VHOST_USER_BACKEND "vhost-user-backend"
-#define VHOST_USER_BACKEND(obj) \
-    OBJECT_CHECK(VhostUserBackend, (obj), TYPE_VHOST_USER_BACKEND)
-#define VHOST_USER_BACKEND_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(VhostUserBackendClass, (obj), TYPE_VHOST_USER_BACKEND)
-#define VHOST_USER_BACKEND_CLASS(klass) \
-    OBJECT_CLASS_CHECK(VhostUserBackendClass, (klass), TYPE_VHOST_USER_BACKEND)
-
-typedef struct VhostUserBackend VhostUserBackend;
-typedef struct VhostUserBackendClass VhostUserBackendClass;
-
-struct VhostUserBackendClass {
-    ObjectClass parent_class;
-};
+OBJECT_DECLARE_SIMPLE_TYPE(VhostUserBackend, vhost_user_backend,
+                           VHOST_USER_BACKEND, ObjectClass)
+
+
 
 struct VhostUserBackend {
     /* private */
diff --git a/include/ui/console.h b/include/ui/console.h
index f35b4fc082..8602203523 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -106,14 +106,10 @@ void kbd_put_keysym(int keysym);
 /* consoles */
 
 #define TYPE_QEMU_CONSOLE "qemu-console"
-#define QEMU_CONSOLE(obj) \
-    OBJECT_CHECK(QemuConsole, (obj), TYPE_QEMU_CONSOLE)
-#define QEMU_CONSOLE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(QemuConsoleClass, (obj), TYPE_QEMU_CONSOLE)
-#define QEMU_CONSOLE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(QemuConsoleClass, (klass), TYPE_QEMU_CONSOLE)
-
 typedef struct QemuConsoleClass QemuConsoleClass;
+DECLARE_OBJ_CHECKERS(QemuConsole, QemuConsoleClass,
+                     QEMU_CONSOLE, TYPE_QEMU_CONSOLE)
+
 
 struct QemuConsoleClass {
     ObjectClass parent_class;
diff --git a/iothread.c b/iothread.c
index 263ec6e5bc..3a3860a09c 100644
--- a/iothread.c
+++ b/iothread.c
@@ -26,10 +26,8 @@
 
 typedef ObjectClass IOThreadClass;
 
-#define IOTHREAD_GET_CLASS(obj) \
-   OBJECT_GET_CLASS(IOThreadClass, obj, TYPE_IOTHREAD)
-#define IOTHREAD_CLASS(klass) \
-   OBJECT_CLASS_CHECK(IOThreadClass, klass, TYPE_IOTHREAD)
+DECLARE_CLASS_CHECKERS(IOThreadClass, IOTHREAD,
+                       TYPE_IOTHREAD)
 
 #ifdef CONFIG_POSIX
 /* Benchmark results from 2016 on NVMe SSD drives show max polling times around
diff --git a/meson.build b/meson.build
index bc869c676a..690723b470 100644
--- a/meson.build
+++ b/meson.build
@@ -273,8 +273,8 @@ if sdl.found()
                          method: 'pkg-config', static: enable_static)
 else
   if get_option('sdl_image').enabled()
-    error('sdl-image required, but SDL was @0@',
-          get_option('sdl').disabled() ? 'disabled' : 'not found')
+    error('sdl-image required, but SDL was @0@'.format(
+          get_option('sdl').disabled() ? 'disabled' : 'not found'))
   endif
   sdl_image = not_found
 endif
@@ -775,6 +775,7 @@ if have_system
     'hw/gpio',
     'migration',
     'net',
+    'softmmu',
     'ui',
   ]
 endif
diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c
index 549e14daba..5bef793ac0 100644
--- a/migration/block-dirty-bitmap.c
+++ b/migration/block-dirty-bitmap.c
@@ -615,13 +615,7 @@ static int init_dirty_bitmap_migration(DBMSaveState *s)
             while (bs && bs->drv && bs->drv->is_filter &&
                    !bdrv_has_named_bitmaps(bs))
             {
-                if (bs->backing) {
-                    bs = bs->backing->bs;
-                } else if (bs->file) {
-                    bs = bs->file->bs;
-                } else {
-                    bs = NULL;
-                }
+                bs = bdrv_filter_bs(bs);
             }
 
             if (bs && bs->drv && !bs->drv->is_filter) {
diff --git a/migration/migration.h b/migration/migration.h
index ae497bd45a..bdc7450da3 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -21,6 +21,7 @@
 #include "qemu/coroutine_int.h"
 #include "io/channel.h"
 #include "net/announce.h"
+#include "qom/object.h"
 
 struct PostcopyBlocktimeContext;
 
@@ -114,17 +115,14 @@ void fill_destination_postcopy_migration_info(MigrationInfo *info);
 
 #define TYPE_MIGRATION "migration"
 
-#define MIGRATION_OBJ_CLASS(klass) \
-    OBJECT_CLASS_CHECK(MigrationClass, (klass), TYPE_MIGRATION)
-#define MIGRATION_OBJ(obj) \
-    OBJECT_CHECK(MigrationState, (obj), TYPE_MIGRATION)
-#define MIGRATION_OBJ_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(MigrationClass, (obj), TYPE_MIGRATION)
+typedef struct MigrationClass MigrationClass;
+DECLARE_OBJ_CHECKERS(MigrationState, MigrationClass,
+                     MIGRATION_OBJ, TYPE_MIGRATION)
 
-typedef struct MigrationClass {
+struct MigrationClass {
     /*< private >*/
     DeviceClass parent_class;
-} MigrationClass;
+};
 
 struct MigrationState
 {
diff --git a/migration/rdma.c b/migration/rdma.c
index bea6532813..1dc563ec3f 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -35,6 +35,7 @@
 #include <arpa/inet.h>
 #include <rdma/rdma_cma.h>
 #include "trace.h"
+#include "qom/object.h"
 
 /*
  * Print and error on both the Monitor and the Log file.
@@ -397,10 +398,10 @@ typedef struct RDMAContext {
 } RDMAContext;
 
 #define TYPE_QIO_CHANNEL_RDMA "qio-channel-rdma"
-#define QIO_CHANNEL_RDMA(obj)                                     \
-    OBJECT_CHECK(QIOChannelRDMA, (obj), TYPE_QIO_CHANNEL_RDMA)
-
 typedef struct QIOChannelRDMA QIOChannelRDMA;
+DECLARE_INSTANCE_CHECKER(QIOChannelRDMA, QIO_CHANNEL_RDMA,
+                         TYPE_QIO_CHANNEL_RDMA)
+
 
 
 struct QIOChannelRDMA {
diff --git a/migration/trace-events b/migration/trace-events
index 4ab0a503d2..7ba2fa6644 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -91,24 +91,6 @@ migration_bitmap_sync_start(void) ""
 migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64
 migration_bitmap_clear_dirty(char *str, uint64_t start, uint64_t size, unsigned long page) "rb %s start 0x%"PRIx64" size 0x%"PRIx64" page 0x%lx"
 migration_throttle(void) ""
-multifd_new_send_channel_async(uint8_t id) "channel %d"
-multifd_recv(uint8_t id, uint64_t packet_num, uint32_t used, uint32_t flags, uint32_t next_packet_size) "channel %d packet_num %" PRIu64 " pages %d flags 0x%x next packet size %d"
-multifd_recv_new_channel(uint8_t id) "channel %d"
-multifd_recv_sync_main(long packet_num) "packet num %ld"
-multifd_recv_sync_main_signal(uint8_t id) "channel %d"
-multifd_recv_sync_main_wait(uint8_t id) "channel %d"
-multifd_recv_terminate_threads(bool error) "error %d"
-multifd_recv_thread_end(uint8_t id, uint64_t packets, uint64_t pages) "channel %d packets %" PRIu64 " pages %" PRIu64
-multifd_recv_thread_start(uint8_t id) "%d"
-multifd_save_setup_wait(uint8_t id) "%d"
-multifd_send(uint8_t id, uint64_t packet_num, uint32_t used, uint32_t flags, uint32_t next_packet_size) "channel %d packet_num %" PRIu64 " pages %d flags 0x%x next packet size %d"
-multifd_send_error(uint8_t id) "channel %d"
-multifd_send_sync_main(long packet_num) "packet num %ld"
-multifd_send_sync_main_signal(uint8_t id) "channel %d"
-multifd_send_sync_main_wait(uint8_t id) "channel %d"
-multifd_send_terminate_threads(bool error) "error %d"
-multifd_send_thread_end(uint8_t id, uint64_t packets, uint64_t pages) "channel %d packets %" PRIu64 " pages %"  PRIu64
-multifd_send_thread_start(uint8_t id) "%d"
 ram_discard_range(const char *rbname, uint64_t start, size_t len) "%s: start: %" PRIx64 " %zx"
 ram_load_loop(const char *rbname, uint64_t addr, int flags, void *host) "%s: addr: 0x%" PRIx64 " flags: 0x%x host: %p"
 ram_load_postcopy_loop(uint64_t addr, int flags) "@%" PRIx64 " %x"
@@ -129,6 +111,25 @@ save_xbzrle_page_overflow(void) ""
 ram_save_iterate_big_wait(uint64_t milliconds, int iterations) "big wait: %" PRIu64 " milliseconds, %d iterations"
 ram_load_complete(int ret, uint64_t seq_iter) "exit_code %d seq iteration %" PRIu64
 
+# multifd.c
+multifd_new_send_channel_async(uint8_t id) "channel %d"
+multifd_recv(uint8_t id, uint64_t packet_num, uint32_t used, uint32_t flags, uint32_t next_packet_size) "channel %d packet_num %" PRIu64 " pages %d flags 0x%x next packet size %d"
+multifd_recv_new_channel(uint8_t id) "channel %d"
+multifd_recv_sync_main(long packet_num) "packet num %ld"
+multifd_recv_sync_main_signal(uint8_t id) "channel %d"
+multifd_recv_sync_main_wait(uint8_t id) "channel %d"
+multifd_recv_terminate_threads(bool error) "error %d"
+multifd_recv_thread_end(uint8_t id, uint64_t packets, uint64_t pages) "channel %d packets %" PRIu64 " pages %" PRIu64
+multifd_recv_thread_start(uint8_t id) "%d"
+multifd_send(uint8_t id, uint64_t packet_num, uint32_t used, uint32_t flags, uint32_t next_packet_size) "channel %d packet_num %" PRIu64 " pages %d flags 0x%x next packet size %d"
+multifd_send_error(uint8_t id) "channel %d"
+multifd_send_sync_main(long packet_num) "packet num %ld"
+multifd_send_sync_main_signal(uint8_t id) "channel %d"
+multifd_send_sync_main_wait(uint8_t id) "channel %d"
+multifd_send_terminate_threads(bool error) "error %d"
+multifd_send_thread_end(uint8_t id, uint64_t packets, uint64_t pages) "channel %d packets %" PRIu64 " pages %"  PRIu64
+multifd_send_thread_start(uint8_t id) "%d"
+
 # migration.c
 await_return_path_close_on_source_close(void) ""
 await_return_path_close_on_source_joining(void) ""
diff --git a/nbd/server.c b/nbd/server.c
index c5d71cff10..982de67816 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -1567,13 +1567,13 @@ NBDExport *nbd_export_new(BlockDriverState *bs, uint64_t dev_offset,
     if (bitmap) {
         BdrvDirtyBitmap *bm = NULL;
 
-        while (true) {
+        while (bs) {
             bm = bdrv_find_dirty_bitmap(bs, bitmap);
-            if (bm != NULL || bs->backing == NULL) {
+            if (bm != NULL) {
                 break;
             }
 
-            bs = bs->backing->bs;
+            bs = bdrv_filter_or_cow_bs(bs);
         }
 
         if (bm == NULL) {
diff --git a/net/can/can_socketcan.c b/net/can/can_socketcan.c
index b7ef63ec0e..f933bd2db2 100644
--- a/net/can/can_socketcan.c
+++ b/net/can/can_socketcan.c
@@ -40,17 +40,19 @@
 #include <net/if.h>
 #include <linux/can.h>
 #include <linux/can/raw.h>
+#include "qom/object.h"
 
 #ifndef DEBUG_CAN
 #define DEBUG_CAN 0
 #endif /*DEBUG_CAN*/
 
 #define TYPE_CAN_HOST_SOCKETCAN "can-host-socketcan"
-#define CAN_HOST_SOCKETCAN(obj) \
-     OBJECT_CHECK(CanHostSocketCAN, (obj), TYPE_CAN_HOST_SOCKETCAN)
+typedef struct CanHostSocketCAN CanHostSocketCAN;
+DECLARE_INSTANCE_CHECKER(CanHostSocketCAN, CAN_HOST_SOCKETCAN,
+                         TYPE_CAN_HOST_SOCKETCAN)
 
 #define CAN_READ_BUF_LEN  5
-typedef struct CanHostSocketCAN {
+struct CanHostSocketCAN {
     CanHostState       parent;
     char               *ifname;
 
@@ -63,7 +65,7 @@ typedef struct CanHostSocketCAN {
     int                bufptr;
 
     int                fd;
-} CanHostSocketCAN;
+};
 
 /* Check that QEMU and Linux kernel flags encoding and structure matches */
 QEMU_BUILD_BUG_ON(QEMU_CAN_EFF_FLAG != CAN_EFF_FLAG);
diff --git a/net/colo-compare.c b/net/colo-compare.c
index 2c20de1537..3a45d64175 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -36,8 +36,9 @@
 #include "qemu/coroutine.h"
 
 #define TYPE_COLO_COMPARE "colo-compare"
-#define COLO_COMPARE(obj) \
-    OBJECT_CHECK(CompareState, (obj), TYPE_COLO_COMPARE)
+typedef struct CompareState CompareState;
+DECLARE_INSTANCE_CHECKER(CompareState, COLO_COMPARE,
+                         TYPE_COLO_COMPARE)
 
 static QTAILQ_HEAD(, CompareState) net_compares =
        QTAILQ_HEAD_INITIALIZER(net_compares);
@@ -54,6 +55,8 @@ static NotifierList colo_compare_notifiers =
 #define REGULAR_PACKET_CHECK_MS 3000
 #define DEFAULT_TIME_OUT_MS 3000
 
+/* #define DEBUG_COLO_PACKETS */
+
 static QemuMutex colo_compare_mutex;
 static bool colo_compare_active;
 static QemuMutex event_mtx;
@@ -100,7 +103,7 @@ typedef struct SendEntry {
     uint8_t *buf;
 } SendEntry;
 
-typedef struct CompareState {
+struct CompareState {
     Object parent;
 
     char *pri_indev;
@@ -136,7 +139,7 @@ typedef struct CompareState {
     enum colo_event event;
 
     QTAILQ_ENTRY(CompareState) next;
-} CompareState;
+};
 
 typedef struct CompareClass {
     ObjectClass parent_class;
@@ -328,7 +331,7 @@ static int colo_compare_packet_payload(Packet *ppkt,
                                        uint16_t len)
 
 {
-    if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
+    if (trace_event_get_state_backends(TRACE_COLO_COMPARE_IP_INFO)) {
         char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
 
         strcpy(pri_ip_src, inet_ntoa(ppkt->ip->ip_src));
@@ -493,12 +496,10 @@ sec:
         g_queue_push_head(&conn->primary_list, ppkt);
         g_queue_push_head(&conn->secondary_list, spkt);
 
-        if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
-            qemu_hexdump((char *)ppkt->data, stderr,
-                        "colo-compare ppkt", ppkt->size);
-            qemu_hexdump((char *)spkt->data, stderr,
-                        "colo-compare spkt", spkt->size);
-        }
+#ifdef DEBUG_COLO_PACKETS
+        qemu_hexdump(stderr, "colo-compare ppkt", ppkt->data, ppkt->size);
+        qemu_hexdump(stderr, "colo-compare spkt", spkt->data, spkt->size);
+#endif
 
         colo_compare_inconsistency_notify(s);
     }
@@ -534,12 +535,10 @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt)
                                     ppkt->size - offset)) {
         trace_colo_compare_udp_miscompare("primary pkt size", ppkt->size);
         trace_colo_compare_udp_miscompare("Secondary pkt size", spkt->size);
-        if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
-            qemu_hexdump((char *)ppkt->data, stderr, "colo-compare pri pkt",
-                         ppkt->size);
-            qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt",
-                         spkt->size);
-        }
+#ifdef DEBUG_COLO_PACKETS
+        qemu_hexdump(stderr, "colo-compare pri pkt", ppkt->data, ppkt->size);
+        qemu_hexdump(stderr, "colo-compare sec pkt", spkt->data, spkt->size);
+#endif
         return -1;
     } else {
         return 0;
@@ -577,12 +576,10 @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt)
                                            ppkt->size);
         trace_colo_compare_icmp_miscompare("Secondary pkt size",
                                            spkt->size);
-        if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
-            qemu_hexdump((char *)ppkt->data, stderr, "colo-compare pri pkt",
-                         ppkt->size);
-            qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt",
-                         spkt->size);
-        }
+#ifdef DEBUG_COLO_PACKETS
+        qemu_hexdump(stderr, "colo-compare pri pkt", ppkt->data, ppkt->size);
+        qemu_hexdump(stderr, "colo-compare sec pkt", spkt->data, spkt->size);
+#endif
         return -1;
     } else {
         return 0;
@@ -598,7 +595,7 @@ static int colo_packet_compare_other(Packet *spkt, Packet *ppkt)
     uint16_t offset = ppkt->vnet_hdr_len;
 
     trace_colo_compare_main("compare other");
-    if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) {
+    if (trace_event_get_state_backends(TRACE_COLO_COMPARE_IP_INFO)) {
         char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20];
 
         strcpy(pri_ip_src, inet_ntoa(ppkt->ip->ip_src));
diff --git a/net/dump.c b/net/dump.c
index 11a737a4bc..42e64a6f29 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -33,6 +33,7 @@
 #include "qemu/timer.h"
 #include "qapi/visitor.h"
 #include "net/filter.h"
+#include "qom/object.h"
 
 typedef struct DumpState {
     int64_t start_ts;
@@ -139,8 +140,9 @@ static int net_dump_state_init(DumpState *s, const char *filename,
 
 #define TYPE_FILTER_DUMP "filter-dump"
 
-#define FILTER_DUMP(obj) \
-    OBJECT_CHECK(NetFilterDumpState, (obj), TYPE_FILTER_DUMP)
+typedef struct NetFilterDumpState NetFilterDumpState;
+DECLARE_INSTANCE_CHECKER(NetFilterDumpState, FILTER_DUMP,
+                         TYPE_FILTER_DUMP)
 
 struct NetFilterDumpState {
     NetFilterState nfs;
@@ -148,7 +150,6 @@ struct NetFilterDumpState {
     char *filename;
     uint32_t maxlen;
 };
-typedef struct NetFilterDumpState NetFilterDumpState;
 
 static ssize_t filter_dump_receive_iov(NetFilterState *nf, NetClientState *sndr,
                                        unsigned flags, const struct iovec *iov,
diff --git a/net/filter-buffer.c b/net/filter-buffer.c
index dfa211794b..6ade7a19b8 100644
--- a/net/filter-buffer.c
+++ b/net/filter-buffer.c
@@ -18,16 +18,17 @@
 
 #define TYPE_FILTER_BUFFER "filter-buffer"
 
-#define FILTER_BUFFER(obj) \
-    OBJECT_CHECK(FilterBufferState, (obj), TYPE_FILTER_BUFFER)
+typedef struct FilterBufferState FilterBufferState;
+DECLARE_INSTANCE_CHECKER(FilterBufferState, FILTER_BUFFER,
+                         TYPE_FILTER_BUFFER)
 
-typedef struct FilterBufferState {
+struct FilterBufferState {
     NetFilterState parent_obj;
 
     NetQueue *incoming_queue;
     uint32_t interval;
     QEMUTimer release_timer;
-} FilterBufferState;
+};
 
 static void filter_buffer_flush(NetFilterState *nf)
 {
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index e9379ce248..088d4dcace 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -21,17 +21,18 @@
 #include "qemu/iov.h"
 #include "qemu/sockets.h"
 
-#define FILTER_MIRROR(obj) \
-    OBJECT_CHECK(MirrorState, (obj), TYPE_FILTER_MIRROR)
-
-#define FILTER_REDIRECTOR(obj) \
-    OBJECT_CHECK(MirrorState, (obj), TYPE_FILTER_REDIRECTOR)
-
 #define TYPE_FILTER_MIRROR "filter-mirror"
+typedef struct MirrorState MirrorState;
+DECLARE_INSTANCE_CHECKER(MirrorState, FILTER_MIRROR,
+                         TYPE_FILTER_MIRROR)
+
 #define TYPE_FILTER_REDIRECTOR "filter-redirector"
+DECLARE_INSTANCE_CHECKER(MirrorState, FILTER_REDIRECTOR,
+                         TYPE_FILTER_REDIRECTOR)
+
 #define REDIRECTOR_MAX_LEN NET_BUFSIZE
 
-typedef struct MirrorState {
+struct MirrorState {
     NetFilterState parent_obj;
     char *indev;
     char *outdev;
@@ -39,7 +40,7 @@ typedef struct MirrorState {
     CharBackend chr_out;
     SocketReadState rs;
     bool vnet_hdr;
-} MirrorState;
+};
 
 static int filter_send(MirrorState *s,
                        const struct iovec *iov,
diff --git a/net/filter-replay.c b/net/filter-replay.c
index 9dda193928..78696c162e 100644
--- a/net/filter-replay.c
+++ b/net/filter-replay.c
@@ -19,17 +19,18 @@
 #include "qapi/visitor.h"
 #include "net/filter.h"
 #include "sysemu/replay.h"
+#include "qom/object.h"
 
 #define TYPE_FILTER_REPLAY "filter-replay"
 
-#define FILTER_REPLAY(obj) \
-    OBJECT_CHECK(NetFilterReplayState, (obj), TYPE_FILTER_REPLAY)
+typedef struct NetFilterReplayState NetFilterReplayState;
+DECLARE_INSTANCE_CHECKER(NetFilterReplayState, FILTER_REPLAY,
+                         TYPE_FILTER_REPLAY)
 
 struct NetFilterReplayState {
     NetFilterState nfs;
     ReplayNetState *rns;
 };
-typedef struct NetFilterReplayState NetFilterReplayState;
 
 static ssize_t filter_replay_receive_iov(NetFilterState *nf,
                                          NetClientState *sndr,
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
index 1aaad101b6..3070b6d59e 100644
--- a/net/filter-rewriter.c
+++ b/net/filter-rewriter.c
@@ -23,21 +23,22 @@
 #include "migration/colo.h"
 #include "util.h"
 
-#define FILTER_COLO_REWRITER(obj) \
-    OBJECT_CHECK(RewriterState, (obj), TYPE_FILTER_REWRITER)
-
 #define TYPE_FILTER_REWRITER "filter-rewriter"
+typedef struct RewriterState RewriterState;
+DECLARE_INSTANCE_CHECKER(RewriterState, FILTER_REWRITER,
+                         TYPE_FILTER_REWRITER)
+
 #define FAILOVER_MODE_ON  true
 #define FAILOVER_MODE_OFF false
 
-typedef struct RewriterState {
+struct RewriterState {
     NetFilterState parent_obj;
     NetQueue *incoming_queue;
     /* hashtable to save connection */
     GHashTable *connection_track_table;
     bool vnet_hdr;
     bool failover_mode;
-} RewriterState;
+};
 
 static void filter_rewriter_failover_mode(RewriterState *s)
 {
@@ -46,7 +47,7 @@ static void filter_rewriter_failover_mode(RewriterState *s)
 
 static void filter_rewriter_flush(NetFilterState *nf)
 {
-    RewriterState *s = FILTER_COLO_REWRITER(nf);
+    RewriterState *s = FILTER_REWRITER(nf);
 
     if (!qemu_net_queue_flush(s->incoming_queue)) {
         /* Unable to empty the queue, purge remaining packets */
@@ -76,11 +77,14 @@ static int handle_primary_tcp_pkt(RewriterState *rf,
     struct tcp_hdr *tcp_pkt;
 
     tcp_pkt = (struct tcp_hdr *)pkt->transport_header;
-    if (trace_event_get_state_backends(TRACE_COLO_FILTER_REWRITER_DEBUG)) {
+    if (trace_event_get_state_backends(TRACE_COLO_FILTER_REWRITER_PKT_INFO)) {
         trace_colo_filter_rewriter_pkt_info(__func__,
                     inet_ntoa(pkt->ip->ip_src), inet_ntoa(pkt->ip->ip_dst),
                     ntohl(tcp_pkt->th_seq), ntohl(tcp_pkt->th_ack),
                     tcp_pkt->th_flags);
+    }
+    if (trace_event_get_state_backends(
+          TRACE_COLO_FILTER_REWRITER_CONN_OFFSET)) {
         trace_colo_filter_rewriter_conn_offset(conn->offset);
     }
 
@@ -180,11 +184,14 @@ static int handle_secondary_tcp_pkt(RewriterState *rf,
 
     tcp_pkt = (struct tcp_hdr *)pkt->transport_header;
 
-    if (trace_event_get_state_backends(TRACE_COLO_FILTER_REWRITER_DEBUG)) {
+    if (trace_event_get_state_backends(TRACE_COLO_FILTER_REWRITER_PKT_INFO)) {
         trace_colo_filter_rewriter_pkt_info(__func__,
                     inet_ntoa(pkt->ip->ip_src), inet_ntoa(pkt->ip->ip_dst),
                     ntohl(tcp_pkt->th_seq), ntohl(tcp_pkt->th_ack),
                     tcp_pkt->th_flags);
+    }
+    if (trace_event_get_state_backends(
+          TRACE_COLO_FILTER_REWRITER_CONN_OFFSET)) {
         trace_colo_filter_rewriter_conn_offset(conn->offset);
     }
 
@@ -251,7 +258,7 @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
                                          int iovcnt,
                                          NetPacketSent *sent_cb)
 {
-    RewriterState *s = FILTER_COLO_REWRITER(nf);
+    RewriterState *s = FILTER_REWRITER(nf);
     Connection *conn;
     ConnectionKey key;
     Packet *pkt;
@@ -349,7 +356,7 @@ static gboolean offset_is_nonzero(gpointer key,
 static void colo_rewriter_handle_event(NetFilterState *nf, int event,
                                        Error **errp)
 {
-    RewriterState *rs = FILTER_COLO_REWRITER(nf);
+    RewriterState *rs = FILTER_REWRITER(nf);
 
     switch (event) {
     case COLO_EVENT_CHECKPOINT:
@@ -369,7 +376,7 @@ static void colo_rewriter_handle_event(NetFilterState *nf, int event,
 
 static void colo_rewriter_cleanup(NetFilterState *nf)
 {
-    RewriterState *s = FILTER_COLO_REWRITER(nf);
+    RewriterState *s = FILTER_REWRITER(nf);
 
     /* flush packets */
     if (s->incoming_queue) {
@@ -380,7 +387,7 @@ static void colo_rewriter_cleanup(NetFilterState *nf)
 
 static void colo_rewriter_setup(NetFilterState *nf, Error **errp)
 {
-    RewriterState *s = FILTER_COLO_REWRITER(nf);
+    RewriterState *s = FILTER_REWRITER(nf);
 
     s->connection_track_table = g_hash_table_new_full(connection_key_hash,
                                                       connection_key_equal,
@@ -391,7 +398,7 @@ static void colo_rewriter_setup(NetFilterState *nf, Error **errp)
 
 static bool filter_rewriter_get_vnet_hdr(Object *obj, Error **errp)
 {
-    RewriterState *s = FILTER_COLO_REWRITER(obj);
+    RewriterState *s = FILTER_REWRITER(obj);
 
     return s->vnet_hdr;
 }
@@ -400,14 +407,14 @@ static void filter_rewriter_set_vnet_hdr(Object *obj,
                                          bool value,
                                          Error **errp)
 {
-    RewriterState *s = FILTER_COLO_REWRITER(obj);
+    RewriterState *s = FILTER_REWRITER(obj);
 
     s->vnet_hdr = value;
 }
 
 static void filter_rewriter_init(Object *obj)
 {
-    RewriterState *s = FILTER_COLO_REWRITER(obj);
+    RewriterState *s = FILTER_REWRITER(obj);
 
     s->vnet_hdr = false;
     s->failover_mode = FAILOVER_MODE_OFF;
diff --git a/net/net.c b/net/net.c
index bbaedb3c7a..7a2a0fb5ac 100644
--- a/net/net.c
+++ b/net/net.c
@@ -636,7 +636,7 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
 
 #ifdef DEBUG_NET
     printf("qemu_send_packet_async:\n");
-    qemu_hexdump((const char *)buf, stdout, "net", size);
+    qemu_hexdump(stdout, "net", buf, size);
 #endif
 
     if (sender->link_down || !sender->peer) {
diff --git a/net/trace-events b/net/trace-events
index fa49c71533..bfaff7891d 100644
--- a/net/trace-events
+++ b/net/trace-events
@@ -17,10 +17,8 @@ colo_compare_udp_miscompare(const char *sta, int size) ": %s = %d"
 colo_compare_icmp_miscompare(const char *sta, int size) ": %s = %d"
 colo_compare_ip_info(int psize, const char *sta, const char *stb, int ssize, const char *stc, const char *std) "ppkt size = %d, ip_src = %s, ip_dst = %s, spkt size = %d, ip_src = %s, ip_dst = %s"
 colo_old_packet_check_found(int64_t old_time) "%" PRId64
-colo_compare_miscompare(void) ""
 colo_compare_tcp_info(const char *pkt, uint32_t seq, uint32_t ack, int hdlen, int pdlen, int offset, int flags) "%s: seq/ack= %u/%u hdlen= %d pdlen= %d offset= %d flags=%d"
 
 # filter-rewriter.c
-colo_filter_rewriter_debug(void) ""
 colo_filter_rewriter_pkt_info(const char *func, const char *src, const char *dst, uint32_t seq, uint32_t ack, uint32_t flag) "%s: src/dst: %s/%s p: seq/ack=%u/%u  flags=0x%x"
 colo_filter_rewriter_conn_offset(uint32_t offset) ": offset=%u"
diff --git a/qapi/block-core.json b/qapi/block-core.json
index c5ac22d246..2d94873ca0 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1569,6 +1569,18 @@
 # Live commit of data from overlay image nodes into backing nodes - i.e.,
 # writes data between 'top' and 'base' into 'base'.
 #
+# If top == base, that is an error.
+# If top has no overlays on top of it, or if it is in use by a writer,
+# the job will not be completed by itself.  The user needs to complete
+# the job with the block-job-complete command after getting the ready
+# event. (Since 2.0)
+#
+# If the base image is smaller than top, then the base image will be
+# resized to be the same size as top.  If top is smaller than the base
+# image, the base will not be truncated.  If you want the base image
+# size to match the size of the smaller top, you can safely truncate
+# it yourself once the commit operation successfully completes.
+#
 # @job-id: identifier for the newly-created block job. If
 #          omitted, the device name will be used. (Since 2.7)
 #
@@ -1593,14 +1605,15 @@
 #       accepted
 #
 # @backing-file: The backing file string to write into the overlay
-#                image of 'top'.  If 'top' is the active layer,
-#                specifying a backing file string is an error. This
-#                filename is not validated.
+#                image of 'top'.  If 'top' does not have an overlay
+#                image, or if 'top' is in use by a writer, specifying
+#                a backing file string is an error.
 #
-#                If a pathname string is such that it cannot be
-#                resolved by QEMU, that means that subsequent QMP or
-#                HMP commands must use node-names for the image in
-#                question, as filename lookup methods will fail.
+#                This filename is not validated.  If a pathname string
+#                is such that it cannot be resolved by QEMU, that
+#                means that subsequent QMP or HMP commands must use
+#                node-names for the image in question, as filename
+#                lookup methods will fail.
 #
 #                If not specified, QEMU will automatically determine
 #                the backing file string to use, or error out if
@@ -1609,18 +1622,6 @@
 #                filename or protocol.
 #                (Since 2.1)
 #
-#                If top == base, that is an error.
-#                If top == active, the job will not be completed by itself,
-#                user needs to complete the job with the block-job-complete
-#                command after getting the ready event. (Since 2.0)
-#
-#                If the base image is smaller than top, then the base image
-#                will be resized to be the same size as top.  If top is
-#                smaller than the base image, the base will not be
-#                truncated.  If you want the base image size to match the
-#                size of the smaller top, you can safely truncate it
-#                yourself once the commit operation successfully completes.
-#
 # @speed: the maximum speed, in bytes per second
 #
 # @on-error: the action to take on an error. 'ignore' means that the request
@@ -1948,7 +1949,8 @@
 #
 # @replaces: with sync=full graph node name to be replaced by the new
 #            image when a whole image copy is done. This can be used to repair
-#            broken Quorum files. (Since 2.1)
+#            broken Quorum files.  By default, @device is replaced, although
+#            implicitly created filters on it are kept. (Since 2.1)
 #
 # @mode: whether and how QEMU should create a new image, default is
 #        'absolute-paths'.
@@ -2259,7 +2261,8 @@
 #
 # @replaces: with sync=full graph node name to be replaced by the new
 #            image when a whole image copy is done. This can be used to repair
-#            broken Quorum files.
+#            broken Quorum files.  By default, @device is replaced, although
+#            implicitly created filters on it are kept.
 #
 # @speed:  the maximum speed, in bytes per second
 #
@@ -2484,13 +2487,20 @@
 # of 'device'.
 #
 # If a base file is specified then sectors are not copied from that base file and
-# its backing chain.  When streaming completes the image file will have the base
-# file as its backing file.  This can be used to stream a subset of the backing
-# file chain instead of flattening the entire image.
+# its backing chain.  This can be used to stream a subset of the backing file
+# chain instead of flattening the entire image.
+# When streaming completes the image file will have the base file as its backing
+# file, unless that node was changed while the job was running.  In that case,
+# base's parent's backing (or filtered, whichever exists) child (i.e., base at
+# the beginning of the job) will be the new backing file.
 #
 # On successful completion the image file is updated to drop the backing file
 # and the BLOCK_JOB_COMPLETED event is emitted.
 #
+# In case @device is a filter node, block-stream modifies the first non-filter
+# overlay node below it to point to the new backing node instead of modifying
+# @device itself.
+#
 # @job-id: identifier for the newly-created block job. If
 #          omitted, the device name will be used. (Since 2.7)
 #
diff --git a/qemu-img.c b/qemu-img.c
index eb2fc1f862..d0b1c97562 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1085,7 +1085,7 @@ static int img_commit(int argc, char **argv)
         /* This is different from QMP, which by default uses the deepest file in
          * the backing chain (i.e., the very base); however, the traditional
          * behavior of qemu-img commit is using the immediate backing file. */
-        base_bs = backing_bs(bs);
+        base_bs = bdrv_backing_chain_next(bs);
         if (!base_bs) {
             error_setg(&local_err, "Image does not have a backing file");
             goto done;
@@ -1732,18 +1732,20 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
     if (s->sector_next_status <= sector_num) {
         uint64_t offset = (sector_num - src_cur_offset) * BDRV_SECTOR_SIZE;
         int64_t count;
+        BlockDriverState *src_bs = blk_bs(s->src[src_cur]);
+        BlockDriverState *base;
+
+        if (s->target_has_backing) {
+            base = bdrv_cow_bs(bdrv_skip_filters(src_bs));
+        } else {
+            base = NULL;
+        }
 
         do {
             count = n * BDRV_SECTOR_SIZE;
 
-            if (s->target_has_backing) {
-                ret = bdrv_block_status(blk_bs(s->src[src_cur]), offset,
-                                        count, &count, NULL, NULL);
-            } else {
-                ret = bdrv_block_status_above(blk_bs(s->src[src_cur]), NULL,
-                                              offset, count, &count, NULL,
-                                              NULL);
-            }
+            ret = bdrv_block_status_above(src_bs, base, offset, count, &count,
+                                          NULL, NULL);
 
             if (ret < 0) {
                 if (s->salvage) {
@@ -2665,7 +2667,8 @@ static int img_convert(int argc, char **argv)
          * s.target_backing_sectors has to be negative, which it will
          * be automatically).  The backing file length is used only
          * for optimizations, so such a case is not fatal. */
-        s.target_backing_sectors = bdrv_nb_sectors(out_bs->backing->bs);
+        s.target_backing_sectors =
+            bdrv_nb_sectors(bdrv_backing_chain_next(out_bs));
     } else {
         s.target_backing_sectors = -1;
     }
@@ -3035,6 +3038,7 @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
 
     depth = 0;
     for (;;) {
+        bs = bdrv_skip_filters(bs);
         ret = bdrv_block_status(bs, offset, bytes, &bytes, &map, &file);
         if (ret < 0) {
             return ret;
@@ -3043,7 +3047,7 @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
         if (ret & (BDRV_BLOCK_ZERO|BDRV_BLOCK_DATA)) {
             break;
         }
-        bs = backing_bs(bs);
+        bs = bdrv_cow_bs(bs);
         if (bs == NULL) {
             ret = 0;
             break;
@@ -3425,6 +3429,7 @@ static int img_rebase(int argc, char **argv)
     uint8_t *buf_old = NULL;
     uint8_t *buf_new = NULL;
     BlockDriverState *bs = NULL, *prefix_chain_bs = NULL;
+    BlockDriverState *unfiltered_bs;
     char *filename;
     const char *fmt, *cache, *src_cache, *out_basefmt, *out_baseimg;
     int c, flags, src_flags, ret;
@@ -3559,6 +3564,8 @@ static int img_rebase(int argc, char **argv)
     }
     bs = blk_bs(blk);
 
+    unfiltered_bs = bdrv_skip_filters(bs);
+
     if (out_basefmt != NULL) {
         if (bdrv_find_format(out_basefmt) == NULL) {
             error_report("Invalid format name: '%s'", out_basefmt);
@@ -3570,7 +3577,7 @@ static int img_rebase(int argc, char **argv)
     /* For safe rebasing we need to compare old and new backing file */
     if (!unsafe) {
         QDict *options = NULL;
-        BlockDriverState *base_bs = backing_bs(bs);
+        BlockDriverState *base_bs = bdrv_cow_bs(unfiltered_bs);
 
         if (base_bs) {
             blk_old_backing = blk_new(qemu_get_aio_context(),
@@ -3711,7 +3718,7 @@ static int img_rebase(int argc, char **argv)
             n = MIN(IO_BUF_SIZE, size - offset);
 
             /* If the cluster is allocated, we don't need to take action */
-            ret = bdrv_is_allocated(bs, offset, n, &n);
+            ret = bdrv_is_allocated(unfiltered_bs, offset, n, &n);
             if (ret < 0) {
                 error_report("error while reading image metadata: %s",
                              strerror(-ret));
@@ -3726,8 +3733,9 @@ static int img_rebase(int argc, char **argv)
                  * If cluster wasn't changed since prefix_chain, we don't need
                  * to take action
                  */
-                ret = bdrv_is_allocated_above(backing_bs(bs), prefix_chain_bs,
-                                              false, offset, n, &n);
+                ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs),
+                                              prefix_chain_bs, false,
+                                              offset, n, &n);
                 if (ret < 0) {
                     error_report("error while reading image metadata: %s",
                                  strerror(-ret));
@@ -3805,9 +3813,10 @@ static int img_rebase(int argc, char **argv)
      * doesn't change when we switch the backing file.
      */
     if (out_baseimg && *out_baseimg) {
-        ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt, true);
+        ret = bdrv_change_backing_file(unfiltered_bs, out_baseimg, out_basefmt,
+                                       true);
     } else {
-        ret = bdrv_change_backing_file(bs, NULL, NULL, false);
+        ret = bdrv_change_backing_file(unfiltered_bs, NULL, NULL, false);
     }
 
     if (ret == -ENOSPC) {
diff --git a/qom/object.c b/qom/object.c
index 00fdf89b3b..b1822a2ef4 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1124,8 +1124,9 @@ GSList *object_class_get_list_sorted(const char *implements_type,
                         object_class_cmp);
 }
 
-Object *object_ref(Object *obj)
+Object *object_ref(void *objptr)
 {
+    Object *obj = OBJECT(objptr);
     if (!obj) {
         return NULL;
     }
@@ -1133,8 +1134,9 @@ Object *object_ref(Object *obj)
     return obj;
 }
 
-void object_unref(Object *obj)
+void object_unref(void *objptr)
 {
+    Object *obj = OBJECT(objptr);
     if (!obj) {
         return;
     }
diff --git a/scripts/cleanup-trace-events.pl b/scripts/cleanup-trace-events.pl
index d4f0e4cab5..c40d2fcc50 100755
--- a/scripts/cleanup-trace-events.pl
+++ b/scripts/cleanup-trace-events.pl
@@ -15,12 +15,15 @@ use warnings;
 use strict;
 use File::Basename;
 
-my $buf = '';
+my @files = ();
+my $events = '';
 my %seen = ();
 
 sub out {
-    print $buf;
-    $buf = '';
+    print sort @files;
+    print $events;
+    @files = ();
+    $events = '';
     %seen = ();
 }
 
@@ -31,16 +34,18 @@ open(IN, $in) or die "open $in: $!";
 chdir($dir) or die "chdir $dir: $!";
 
 while (<IN>) {
-    if (/^(disable |(tcg) |vcpu )*([a-z_0-9]+)\(/i) {
-        my $pat = "trace_$3";
-        $pat .= '_tcg' if (defined $2);
-        open GREP, '-|', 'git', 'grep', '-lw', '--max-depth', '1', $pat
+    if (/^(disable |(tcg) |(vcpu) )*([a-z_0-9]+)\(/i) {
+        my $pat = "trace_$4";
+        $pat .= '_tcg' if defined $2;
+        open GREP, '-|', 'git', 'grep', '-lw',
+	    defined $3 ? () : ('--max-depth', '1'),
+	    $pat
             or die "run git grep: $!";
         while (my $fname = <GREP>) {
             chomp $fname;
             next if $seen{$fname} || $fname eq 'trace-events';
             $seen{$fname} = 1;
-            $buf = "# $fname\n" . $buf;
+            push @files, "# $fname\n";
         }
         unless (close GREP) {
             die "close git grep: $!"
@@ -53,7 +58,7 @@ while (<IN>) {
     } elsif (!/^#|^$/) {
         warn "unintelligible line";
     }
-    $buf .= $_;
+    $events .= $_;
 }
 
 out;
diff --git a/scripts/codeconverter/codeconverter/__init__.py b/scripts/codeconverter/codeconverter/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/scripts/codeconverter/codeconverter/__init__.py
diff --git a/scripts/codeconverter/codeconverter/patching.py b/scripts/codeconverter/codeconverter/patching.py
new file mode 100644
index 0000000000..627a1a1b04
--- /dev/null
+++ b/scripts/codeconverter/codeconverter/patching.py
@@ -0,0 +1,397 @@
+# Copyright (C) 2020 Red Hat Inc.
+#
+# Authors:
+#  Eduardo Habkost <ehabkost@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+from typing import IO, Match, NamedTuple, Optional, Literal, Iterable, Type, Dict, List, Any, TypeVar, NewType, Tuple
+from pathlib import Path
+from itertools import chain
+from tempfile import NamedTemporaryFile
+import os
+import re
+import subprocess
+from io import StringIO
+
+import logging
+logger = logging.getLogger(__name__)
+DBG = logger.debug
+INFO = logger.info
+WARN = logger.warning
+ERROR = logger.error
+
+from .utils import *
+
+T = TypeVar('T')
+
+class Patch(NamedTuple):
+    # start inside file.original_content
+    start: int
+    # end position inside file.original_content
+    end: int
+    # replacement string for file.original_content[start:end]
+    replacement: str
+
+IdentifierType = Literal['type', 'symbol', 'include', 'constant']
+class RequiredIdentifier(NamedTuple):
+    type: IdentifierType
+    name: str
+
+class FileMatch:
+    """Base class for regex matches
+
+    Subclasses just need to set the `regexp` class attribute
+    """
+    regexp: Optional[str] = None
+
+    def __init__(self, f: 'FileInfo', m: Match) -> None:
+        self.file: 'FileInfo' = f
+        self.match: Match = m
+
+    @property
+    def name(self) -> str:
+        if 'name' not in self.match.groupdict():
+            return '[no name]'
+        return self.group('name')
+
+    @classmethod
+    def compiled_re(klass):
+        return re.compile(klass.regexp, re.MULTILINE)
+
+    def start(self) -> int:
+        return self.match.start()
+
+    def end(self) -> int:
+        return self.match.end()
+
+    def line_col(self) -> LineAndColumn:
+        return self.file.line_col(self.start())
+
+    def group(self, *args):
+        return self.match.group(*args)
+
+    def log(self, level, fmt, *args) -> None:
+        pos = self.line_col()
+        logger.log(level, '%s:%d:%d: '+fmt, self.file.filename, pos.line, pos.col, *args)
+
+    def debug(self, fmt, *args) -> None:
+        self.log(logging.DEBUG, fmt, *args)
+
+    def info(self, fmt, *args) -> None:
+        self.log(logging.INFO, fmt, *args)
+
+    def warn(self, fmt, *args) -> None:
+        self.log(logging.WARNING, fmt, *args)
+
+    def error(self, fmt, *args) -> None:
+        self.log(logging.ERROR, fmt, *args)
+
+    def sub(self, original: str, replacement: str) -> str:
+        """Replace content
+
+        XXX: this won't use the match position, but will just
+        replace all strings that look like the original match.
+        This should be enough for all the patterns used in this
+        script.
+        """
+        return original.replace(self.group(0), replacement)
+
+    def sanity_check(self) -> None:
+        """Sanity check match, and print warnings if necessary"""
+        pass
+
+    def replacement(self) -> Optional[str]:
+        """Return replacement text for pattern, to use new code conventions"""
+        return None
+
+    def make_patch(self, replacement: str) -> 'Patch':
+        """Make patch replacing the content of this match"""
+        return Patch(self.start(), self.end(), replacement)
+
+    def make_subpatch(self, start: int, end: int, replacement: str) -> 'Patch':
+        return Patch(self.start() + start, self.start() + end, replacement)
+
+    def make_removal_patch(self) -> 'Patch':
+        """Make patch removing contents of match completely"""
+        return self.make_patch('')
+
+    def append(self, s: str) -> 'Patch':
+        """Make patch appending string after this match"""
+        return Patch(self.end(), self.end(), s)
+
+    def prepend(self, s: str) -> 'Patch':
+        """Make patch prepending string before this match"""
+        return Patch(self.start(), self.start(), s)
+
+    def gen_patches(self) -> Iterable['Patch']:
+        """Patch source code contents to use new code patterns"""
+        replacement = self.replacement()
+        if replacement is not None:
+            yield self.make_patch(replacement)
+
+    @classmethod
+    def has_replacement_rule(klass) -> bool:
+        return (klass.gen_patches is not FileMatch.gen_patches
+                or klass.replacement is not FileMatch.replacement)
+
+    def contains(self, other: 'FileMatch') -> bool:
+        return other.start() >= self.start() and other.end() <= self.end()
+
+    def __repr__(self) -> str:
+        start = self.file.line_col(self.start())
+        end = self.file.line_col(self.end() - 1)
+        return '<%s %s at %d:%d-%d:%d: %r>' % (self.__class__.__name__,
+                                                    self.name,
+                                                    start.line, start.col,
+                                                    end.line, end.col, self.group(0)[:100])
+
+    def required_identifiers(self) -> Iterable[RequiredIdentifier]:
+        """Can be implemented by subclasses to keep track of identifier references
+
+        This method will be used by the code that moves declarations around the file,
+        to make sure we find the right spot for them.
+        """
+        raise NotImplementedError()
+
+    def provided_identifiers(self) -> Iterable[RequiredIdentifier]:
+        """Can be implemented by subclasses to keep track of identifier references
+
+        This method will be used by the code that moves declarations around the file,
+        to make sure we find the right spot for them.
+        """
+        raise NotImplementedError()
+
+    @classmethod
+    def find_matches(klass, content: str) -> Iterable[Match]:
+        """Generate match objects for class
+
+        Might be reimplemented by subclasses if they
+        intend to look for matches using a different method.
+        """
+        return klass.compiled_re().finditer(content)
+
+    @property
+    def allfiles(self) -> 'FileList':
+        return self.file.allfiles
+
+def all_subclasses(c: Type[FileMatch]) -> Iterable[Type[FileMatch]]:
+    for sc in c.__subclasses__():
+        yield sc
+        yield from all_subclasses(sc)
+
+def match_class_dict() -> Dict[str, Type[FileMatch]]:
+    d = dict((t.__name__, t) for t in all_subclasses(FileMatch))
+    return d
+
+def names(matches: Iterable[FileMatch]) -> Iterable[str]:
+    return [m.name for m in matches]
+
+class PatchingError(Exception):
+    pass
+
+class OverLappingPatchesError(PatchingError):
+    pass
+
+def apply_patches(s: str, patches: Iterable[Patch]) -> str:
+    """Apply a sequence of patches to string
+
+    >>> apply_patches('abcdefg', [Patch(2,2,'xxx'), Patch(0, 1, 'yy')])
+    'yybxxxcdefg'
+    """
+    r = StringIO()
+    last = 0
+    for p in sorted(patches):
+        DBG("Applying patch at position %d (%s) - %d (%s): %r",
+            p.start, line_col(s, p.start),
+            p.end, line_col(s, p.end),
+            p.replacement)
+        if last > p.start:
+            raise OverLappingPatchesError("Overlapping patch at position %d (%s), last patch at %d (%s)" % \
+                (p.start, line_col(s, p.start), last, line_col(s, last)))
+        r.write(s[last:p.start])
+        r.write(p.replacement)
+        last = p.end
+    r.write(s[last:])
+    return r.getvalue()
+
+class RegexpScanner:
+    def __init__(self) -> None:
+        self.match_index: Dict[Type[Any], List[FileMatch]] = {}
+        self.match_name_index: Dict[Tuple[Type[Any], str, str], Optional[FileMatch]] = {}
+
+    def _find_matches(self, klass: Type[Any]) -> Iterable[FileMatch]:
+        raise NotImplementedError()
+
+    def matches_of_type(self, t: Type[T]) -> List[T]:
+        if t not in self.match_index:
+            self.match_index[t] = list(self._find_matches(t))
+        return  self.match_index[t] # type: ignore
+
+    def find_match(self, t: Type[T], name: str, group: str='name') -> Optional[T]:
+        indexkey = (t, name, group)
+        if indexkey in self.match_name_index:
+            return self.match_name_index[indexkey] # type: ignore
+        r: Optional[T] = None
+        for m in self.matches_of_type(t):
+            assert isinstance(m, FileMatch)
+            if m.group(group) == name:
+                r = m # type: ignore
+        self.match_name_index[indexkey] = r # type: ignore
+        return r
+
+    def reset_index(self) -> None:
+        self.match_index.clear()
+        self.match_name_index.clear()
+
+class FileInfo(RegexpScanner):
+    filename: Path
+    original_content: Optional[str] = None
+
+    def __init__(self, files: 'FileList', filename: os.PathLike, force:bool=False) -> None:
+        super().__init__()
+        self.allfiles = files
+        self.filename = Path(filename)
+        self.patches: List[Patch] = []
+        self.force = force
+
+    def __repr__(self) -> str:
+        return f'<FileInfo {repr(self.filename)}>'
+
+    def line_col(self, start: int) -> LineAndColumn:
+        """Return line and column for a match object inside original_content"""
+        return line_col(self.original_content, start)
+
+    def _find_matches(self, klass: Type[Any]) -> List[FileMatch]:
+        """Build FileMatch objects for each match of regexp"""
+        if not hasattr(klass, 'regexp') or klass.regexp is None:
+            return []
+        assert hasattr(klass, 'regexp')
+        DBG("%s: scanning for %s", self.filename, klass.__name__)
+        DBG("regexp: %s", klass.regexp)
+        matches = [klass(self, m) for m in klass.find_matches(self.original_content)]
+        DBG('%s: %d matches found for %s: %s', self.filename, len(matches),
+            klass.__name__,' '.join(names(matches)))
+        return matches
+
+    def find_match(self, t: Type[T], name: str, group: str='name') -> Optional[T]:
+        for m in self.matches_of_type(t):
+            assert isinstance(m, FileMatch)
+            if m.group(group) == name:
+                return m # type: ignore
+        return None
+
+    def reset_content(self, s:str):
+        self.original_content = s
+        self.patches.clear()
+        self.reset_index()
+        self.allfiles.reset_index()
+
+    def load(self) -> None:
+        if self.original_content is not None:
+            return
+        with open(self.filename, 'rt') as f:
+            self.reset_content(f.read())
+
+    @property
+    def all_matches(self) -> Iterable[FileMatch]:
+        lists = list(self.match_index.values())
+        return (m for l in lists
+                  for m in l)
+
+    def scan_for_matches(self, class_names: Optional[List[str]]=None) -> None:
+        DBG("class names: %r", class_names)
+        class_dict = match_class_dict()
+        if class_names is None:
+            DBG("default class names")
+            class_names = list(name for name,klass in class_dict.items()
+                               if klass.has_replacement_rule())
+        DBG("class_names: %r", class_names)
+        for cn in class_names:
+            matches = self.matches_of_type(class_dict[cn])
+            if len(matches) > 0:
+                DBG('%s: %d matches found for %s: %s', self.filename,
+                     len(matches), cn, ' '.join(names(matches)))
+
+    def gen_patches(self) -> None:
+        for m in self.all_matches:
+            for i,p in enumerate(m.gen_patches()):
+                DBG("patch %d generated by %r:", i, m)
+                DBG("replace contents at %s-%s with %r",
+                    self.line_col(p.start), self.line_col(p.end), p.replacement)
+                self.patches.append(p)
+
+    def patch_content(self, max_passes=0, class_names: Optional[List[str]]=None) -> None:
+        """Multi-pass content patching loop
+
+        We run multiple passes because there are rules that will
+        delete init functions once they become empty.
+        """
+        passes = 0
+        total_patches  = 0
+        DBG("max_passes: %r", max_passes)
+        while not max_passes or max_passes <= 0 or passes < max_passes:
+            passes += 1
+            self.scan_for_matches(class_names)
+            self.gen_patches()
+            DBG("patch content: pass %d: %d patches generated", passes, len(self.patches))
+            total_patches += len(self.patches)
+            if not self.patches:
+                break
+            try:
+                self.apply_patches()
+            except PatchingError:
+                logger.exception("%s: failed to patch file", self.filename)
+        DBG("%s: %d patches applied total in %d passes", self.filename, total_patches, passes)
+
+    def apply_patches(self) -> None:
+        """Replace self.original_content after applying patches from self.patches"""
+        self.reset_content(self.get_patched_content())
+
+    def get_patched_content(self) -> str:
+        assert self.original_content is not None
+        return apply_patches(self.original_content, self.patches)
+
+    def write_to_file(self, f: IO[str]) -> None:
+        f.write(self.get_patched_content())
+
+    def write_to_filename(self, filename: os.PathLike) -> None:
+        with open(filename, 'wt') as of:
+            self.write_to_file(of)
+
+    def patch_inplace(self) -> None:
+        newfile = self.filename.with_suffix('.changed')
+        self.write_to_filename(newfile)
+        os.rename(newfile, self.filename)
+
+    def show_diff(self) -> None:
+        with NamedTemporaryFile('wt') as f:
+            self.write_to_file(f)
+            f.flush()
+            subprocess.call(['diff', '-u', self.filename, f.name])
+
+    def ref(self):
+        return TypeInfoReference
+
+class FileList(RegexpScanner):
+    def __init__(self):
+        super().__init__()
+        self.files: List[FileInfo] = []
+
+    def extend(self, *args, **kwargs):
+        self.files.extend(*args, **kwargs)
+
+    def __iter__(self):
+        return iter(self.files)
+
+    def _find_matches(self, klass: Type[Any]) -> Iterable[FileMatch]:
+        return chain(*(f._find_matches(klass) for f in self.files))
+
+    def find_file(self, name) -> Optional[FileInfo]:
+        """Get file with path ending with @name"""
+        nameparts = Path(name).parts
+        for f in self.files:
+            if f.filename.parts[:len(nameparts)] == nameparts:
+                return f
+        else:
+            return None
\ No newline at end of file
diff --git a/scripts/codeconverter/codeconverter/qom_macros.py b/scripts/codeconverter/codeconverter/qom_macros.py
new file mode 100644
index 0000000000..68a33d5c6f
--- /dev/null
+++ b/scripts/codeconverter/codeconverter/qom_macros.py
@@ -0,0 +1,652 @@
+# Copyright (C) 2020 Red Hat Inc.
+#
+# Authors:
+#  Eduardo Habkost <ehabkost@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+import re
+from itertools import chain
+from typing import *
+
+from .regexps import *
+from .patching import *
+from .utils import *
+
+import logging
+logger = logging.getLogger(__name__)
+DBG = logger.debug
+INFO = logger.info
+WARN = logger.warning
+
+# simple expressions:
+
+RE_CONSTANT = OR(RE_STRING, RE_NUMBER)
+
+class ConstantDefine(FileMatch):
+    """Simple #define preprocessor directive for a constant"""
+    # if the macro contents are very simple, it might be included
+    # in the match group 'value'
+    regexp = S(r'^[ \t]*#[ \t]*define', CPP_SPACE, NAMED('name', RE_IDENTIFIER),
+               CPP_SPACE, NAMED('value', RE_CONSTANT), r'[ \t]*\n')
+
+    def provided_identifiers(self) -> Iterable[RequiredIdentifier]:
+        yield RequiredIdentifier('constant', self.group('name'))
+
+class TypeIdentifiers(NamedTuple):
+    """Type names found in type declarations"""
+    # TYPE_MYDEVICE
+    typename: Optional[str]
+    # MYDEVICE
+    uppercase: Optional[str] = None
+    # MyDevice
+    instancetype: Optional[str] = None
+    # MyDeviceClass
+    classtype: Optional[str] = None
+    # my_device
+    lowercase: Optional[str] = None
+
+    def allfields(self):
+        return tuple(getattr(self, f) for f in self._fields)
+
+    def merge(self, other: 'TypeIdentifiers') -> Optional['TypeIdentifiers']:
+        """Check if identifiers match, return new identifier with complete list"""
+        if any(not opt_compare(a, b) for a,b in zip(self, other)):
+            return None
+        return TypeIdentifiers(*(merge(a, b) for a,b in zip(self, other)))
+
+    def __str__(self) -> str:
+        values = ((f, getattr(self, f)) for f in self._fields)
+        s = ', '.join('%s=%s' % (f,v) for f,v in values if v is not None)
+        return f'{s}'
+
+    def check_consistency(self) -> List[str]:
+        """Check if identifiers are consistent with each other,
+        return list of problems (or empty list if everything seems consistent)
+        """
+        r = []
+        if self.typename is None:
+            r.append("typename (TYPE_MYDEVICE) is unavailable")
+
+        if self.uppercase is None:
+            r.append("uppercase name is unavailable")
+
+        if (self.instancetype is not None
+            and self.classtype is not None
+            and self.classtype != f'{self.instancetype}Class'):
+                r.append("class typedef %s doesn't match instance typedef %s" %
+                         (self.classtype, self.instancetype))
+
+        if (self.uppercase is not None
+            and self.typename is not None
+            and f'TYPE_{self.uppercase}' != self.typename):
+            r.append("uppercase name (%s) doesn't match type name (%s)" %
+                     (self.uppercase, self.typename))
+
+        return r
+
+class TypedefMatch(FileMatch):
+    """typedef declaration"""
+    def provided_identifiers(self) -> Iterable[RequiredIdentifier]:
+        yield RequiredIdentifier('type', self.group('name'))
+
+class SimpleTypedefMatch(TypedefMatch):
+    """Simple typedef declaration
+    (no replacement rules)"""
+    regexp = S(r'^[ \t]*typedef', SP,
+               NAMED('typedef_type', RE_TYPE), SP,
+               NAMED('name', RE_IDENTIFIER), r'\s*;[ \t]*\n')
+
+RE_MACRO_DEFINE = S(r'^[ \t]*#\s*define\s+', NAMED('name', RE_IDENTIFIER),
+                    r'\s*\(\s*', RE_IDENTIFIER, r'\s*\)', CPP_SPACE)
+
+RE_STRUCT_ATTRIBUTE = r'QEMU_PACKED'
+
+# This doesn't parse the struct definitions completely, it just assumes
+# the closing brackets are going to be in an unindented line:
+RE_FULL_STRUCT = S('struct', SP, M(RE_IDENTIFIER, n='?', name='structname'), SP,
+                   NAMED('body', r'{\n',
+                         # acceptable inside the struct body:
+                         # - lines starting with space or tab
+                         # - empty lines
+                         # - preprocessor directives
+                         # - comments
+                         OR(r'[ \t][^\n]*\n',
+                            r'#[^\n]*\n',
+                            r'\n',
+                            S(r'[ \t]*', RE_COMMENT, r'[ \t]*\n'),
+                            repeat='*?'),
+                         r'}', M(RE_STRUCT_ATTRIBUTE, SP, n='*')))
+RE_STRUCT_TYPEDEF = S(r'^[ \t]*typedef', SP, RE_FULL_STRUCT, SP,
+                      NAMED('name', RE_IDENTIFIER), r'\s*;[ \t]*\n')
+
+class FullStructTypedefMatch(TypedefMatch):
+    """typedef struct [SomeStruct] { ...} SomeType
+    Will be replaced by separate struct declaration + typedef
+    """
+    regexp = RE_STRUCT_TYPEDEF
+
+    def make_structname(self) -> str:
+        """Make struct name for struct+typedef split"""
+        name = self.group('structname')
+        if not name:
+            name = self.name
+        return name
+
+    def strip_typedef(self) -> Patch:
+        """generate patch that will strip typedef from the struct declartion
+
+        The caller is responsible for readding the typedef somewhere else.
+        """
+        name = self.make_structname()
+        body = self.group('body')
+        return self.make_patch(f'struct {name} {body};\n')
+
+    def make_simple_typedef(self) -> str:
+        structname = self.make_structname()
+        name = self.name
+        return f'typedef struct {structname} {name};\n'
+
+    def move_typedef(self, position) -> Iterator[Patch]:
+        """Generate patches to move typedef elsewhere"""
+        yield self.strip_typedef()
+        yield Patch(position, position, self.make_simple_typedef())
+
+    def split_typedef(self) -> Iterator[Patch]:
+        """Split into struct definition + typedef in-place"""
+        yield self.strip_typedef()
+        yield self.append(self.make_simple_typedef())
+
+class StructTypedefSplit(FullStructTypedefMatch):
+    """split struct+typedef declaration"""
+    def gen_patches(self) -> Iterator[Patch]:
+        if self.group('structname'):
+            yield from self.split_typedef()
+
+class DuplicatedTypedefs(SimpleTypedefMatch):
+    """Delete ALL duplicate typedefs (unsafe)"""
+    def gen_patches(self) -> Iterable[Patch]:
+        other_td = [td for td in chain(self.file.matches_of_type(SimpleTypedefMatch),
+                                       self.file.matches_of_type(FullStructTypedefMatch))
+                    if td.name == self.name]
+        DBG("other_td: %r", other_td)
+        if any(td.start() < self.start() for td in other_td):
+            # patch only if handling the first typedef
+            return
+        for td in other_td:
+            if isinstance(td, SimpleTypedefMatch):
+                DBG("other td: %r", td.match.groupdict())
+                if td.group('typedef_type') != self.group('typedef_type'):
+                    yield td.make_removal_patch()
+            elif isinstance(td, FullStructTypedefMatch):
+                DBG("other td: %r", td.match.groupdict())
+                if self.group('typedef_type') == 'struct '+td.group('structname'):
+                    yield td.strip_typedef()
+
+class QOMDuplicatedTypedefs(DuplicatedTypedefs):
+    """Delete duplicate typedefs if used by QOM type"""
+    def gen_patches(self) -> Iterable[Patch]:
+        qom_macros = [TypeCheckMacro, DeclareInstanceChecker, DeclareClassCheckers, DeclareObjCheckers]
+        qom_matches = chain(*(self.file.matches_of_type(t) for t in qom_macros))
+        in_use = any(RequiredIdentifier('type', self.name) in m.required_identifiers()
+                     for m in qom_matches)
+        if in_use:
+            yield from DuplicatedTypedefs.gen_patches(self)
+
+class QOMStructTypedefSplit(FullStructTypedefMatch):
+    """split struct+typedef declaration if used by QOM type"""
+    def gen_patches(self) -> Iterator[Patch]:
+        qom_macros = [TypeCheckMacro, DeclareInstanceChecker, DeclareClassCheckers, DeclareObjCheckers]
+        qom_matches = chain(*(self.file.matches_of_type(t) for t in qom_macros))
+        in_use = any(RequiredIdentifier('type', self.name) in m.required_identifiers()
+                     for m in qom_matches)
+        if in_use:
+            yield from self.split_typedef()
+
+def typedefs(file: FileInfo) -> Iterable[TypedefMatch]:
+    return (cast(TypedefMatch, m)
+            for m in chain(file.matches_of_type(SimpleTypedefMatch),
+                           file.matches_of_type(FullStructTypedefMatch)))
+
+def find_typedef(f: FileInfo, name: Optional[str]) -> Optional[TypedefMatch]:
+    if not name:
+        return None
+    for td in typedefs(f):
+        if td.name == name:
+            return td
+    return None
+
+CHECKER_MACROS = ['OBJECT_CHECK', 'OBJECT_CLASS_CHECK', 'OBJECT_GET_CLASS']
+CheckerMacroName = Literal['OBJECT_CHECK', 'OBJECT_CLASS_CHECK', 'OBJECT_GET_CLASS']
+
+RE_CHECK_MACRO = \
+    S(RE_MACRO_DEFINE,
+      OR(*CHECKER_MACROS, name='checker'),
+      M(r'\s*\(\s*', OR(NAMED('typedefname', RE_IDENTIFIER), RE_TYPE, name='c_type'), r'\s*,', CPP_SPACE,
+        OPTIONAL_PARS(RE_IDENTIFIER), r',', CPP_SPACE,
+        NAMED('qom_typename', RE_IDENTIFIER), r'\s*\)\n',
+        n='?', name='check_args'))
+
+EXPECTED_CHECKER_SUFFIXES: List[Tuple[CheckerMacroName, str]] = [
+    ('OBJECT_GET_CLASS', '_GET_CLASS'),
+    ('OBJECT_CLASS_CHECK', '_CLASS'),
+]
+
+class TypeCheckMacro(FileMatch):
+    """OBJECT_CHECK/OBJECT_CLASS_CHECK/OBJECT_GET_CLASS macro definitions
+    Will be replaced by DECLARE_*_CHECKERS macro
+    """
+    #TODO: handle and convert INTERFACE_CHECK macros
+    regexp = RE_CHECK_MACRO
+
+    @property
+    def checker(self) -> CheckerMacroName:
+        """Name of checker macro being used"""
+        return self.group('checker')
+
+    @property
+    def typedefname(self) -> Optional[str]:
+        return self.group('typedefname')
+
+    def find_typedef(self) -> Optional[TypedefMatch]:
+        return find_typedef(self.file, self.typedefname)
+
+    def sanity_check(self) -> None:
+        DBG("groups: %r", self.match.groups())
+        if not self.group('check_args'):
+            self.warn("type check macro not parsed completely: %s", self.name)
+            return
+        DBG("type identifiers: %r", self.type_identifiers)
+        if self.typedefname and self.find_typedef() is None:
+            self.warn("typedef used by %s not found", self.name)
+
+    def find_matching_macros(self) -> List['TypeCheckMacro']:
+        """Find other check macros that generate the same macro names
+
+        The returned list will always be sorted.
+        """
+        my_ids = self.type_identifiers
+        assert my_ids
+        return [m for m in self.file.matches_of_type(TypeCheckMacro)
+                if m.type_identifiers is not None
+                   and my_ids.uppercase is not None
+                   and (my_ids.uppercase == m.type_identifiers.uppercase
+                        or my_ids.typename == m.type_identifiers.typename)]
+
+    def merge_ids(self, matches: List['TypeCheckMacro']) -> Optional[TypeIdentifiers]:
+        """Try to merge info about type identifiers from all matches in a list"""
+        if not matches:
+            return None
+        r = matches[0].type_identifiers
+        if r is None:
+            return None
+        for m in matches[1:]:
+            assert m.type_identifiers
+            new = r.merge(m.type_identifiers)
+            if new is None:
+                self.warn("macro %s identifiers (%s) don't match macro %s (%s)",
+                          matches[0].name, r, m.name, m.type_identifiers)
+                return None
+            r = new
+        return r
+
+    def required_identifiers(self) -> Iterable[RequiredIdentifier]:
+        yield RequiredIdentifier('include', '"qom/object.h"')
+        if self.type_identifiers is None:
+            return
+        # to make sure typedefs will be moved above all related macros,
+        # return dependencies from all of them, not just this match
+        for m in self.find_matching_macros():
+            yield RequiredIdentifier('type', m.group('c_type'))
+            yield RequiredIdentifier('constant', m.group('qom_typename'))
+
+    @property
+    def type_identifiers(self) -> Optional[TypeIdentifiers]:
+        """Extract type identifier information from match"""
+        typename = self.group('qom_typename')
+        c_type = self.group('c_type')
+        if not typename or not c_type:
+            return None
+        typedef = self.group('typedefname')
+        classtype = None
+        instancetype = None
+        uppercase = None
+        expected_suffix = dict(EXPECTED_CHECKER_SUFFIXES).get(self.checker)
+
+        # here the available data depends on the checker macro being called:
+        # - we need to remove the suffix from the macro name
+        # - depending on the macro type, we know the class type name, or
+        #   the instance type name
+        if self.checker in ('OBJECT_GET_CLASS', 'OBJECT_CLASS_CHECK'):
+            classtype = c_type
+        elif self.checker == 'OBJECT_CHECK':
+            instancetype = c_type
+            uppercase = self.name
+        else:
+            assert False
+        if expected_suffix and self.name.endswith(expected_suffix):
+            uppercase = self.name[:-len(expected_suffix)]
+        return TypeIdentifiers(typename=typename, classtype=classtype,
+                               instancetype=instancetype, uppercase=uppercase)
+
+    def gen_patches(self) -> Iterable[Patch]:
+        if self.type_identifiers is None:
+            self.warn("couldn't extract type information from macro %s", self.name)
+            return
+
+        if self.name == 'INTERFACE_CLASS':
+            # INTERFACE_CLASS is special and won't be patched
+            return
+
+        for checker,suffix in EXPECTED_CHECKER_SUFFIXES:
+            if self.name.endswith(suffix):
+                if self.checker != checker:
+                    self.warn("macro %s is using macro %s instead of %s", self.name, self.checker, checker)
+                    return
+                break
+
+        matches = self.find_matching_macros()
+        DBG("found %d matching macros: %s", len(matches), ' '.join(m.name for m in matches))
+        # we will generate patches only when processing the first macro:
+        if matches[0].start != self.start:
+            DBG("skipping %s (will patch when handling %s)", self.name, matches[0].name)
+            return
+
+
+        ids = self.merge_ids(matches)
+        if ids is None:
+            DBG("type identifier mismatch, won't patch %s", self.name)
+            return
+
+        if not ids.uppercase:
+            self.warn("macro %s doesn't follow the expected name pattern", self.name)
+            return
+        if not ids.typename:
+            self.warn("macro %s: couldn't extract type name", self.name)
+            return
+
+        #issues = ids.check_consistency()
+        #if issues:
+        #    for i in issues:
+        #        self.warn("inconsistent identifiers: %s", i)
+
+        names = [n for n in (ids.instancetype, ids.classtype, ids.uppercase, ids.typename)
+                 if n is not None]
+        if len(set(names)) != len(names):
+            self.warn("duplicate names used by macro: %r", ids)
+            return
+
+        assert ids.classtype or ids.instancetype
+        assert ids.typename
+        assert ids.uppercase
+        if ids.classtype and ids.instancetype:
+            new_decl = (f'DECLARE_OBJ_CHECKERS({ids.instancetype}, {ids.classtype},\n'
+                        f'                     {ids.uppercase}, {ids.typename})\n')
+        elif ids.classtype:
+            new_decl = (f'DECLARE_CLASS_CHECKERS({ids.classtype}, {ids.uppercase},\n'
+                        f'                       {ids.typename})\n')
+        elif ids.instancetype:
+            new_decl = (f'DECLARE_INSTANCE_CHECKER({ids.instancetype}, {ids.uppercase},\n'
+                        f'                         {ids.typename})\n')
+        else:
+            assert False
+
+        # we need to ensure the typedefs are already available
+        issues = []
+        for t in [ids.instancetype, ids.classtype]:
+            if not t:
+                continue
+            if re.fullmatch(RE_STRUCT_TYPE, t):
+                self.info("type %s is not a typedef", t)
+                continue
+            td = find_typedef(self.file, t)
+            #if not td and self.allfiles.find_file('include/qemu/typedefs.h'):
+            #
+            if not td:
+                # it is OK if the typedef is in typedefs.h
+                f = self.allfiles.find_file('include/qemu/typedefs.h')
+                if f and find_typedef(f, t):
+                    self.info("typedef %s found in typedefs.h", t)
+                    continue
+
+                issues.append("couldn't find typedef %s" % (t))
+            elif td.start() > self.start():
+                issues.append("typedef %s need to be moved earlier in the file" % (td.name))
+
+        for issue in issues:
+            self.warn(issue)
+
+        if issues and not self.file.force:
+            return
+
+        # delete all matching macros and add new declaration:
+        for m in matches:
+            yield m.make_patch('')
+        for issue in issues:
+            yield self.prepend("/* FIXME: %s */\n" % (issue))
+        yield self.append(new_decl)
+
+class DeclareInstanceChecker(FileMatch):
+    """DECLARE_INSTANCE_CHECKER use
+    Will be replaced with DECLARE_OBJ_CHECKERS if possible
+    """
+    #TODO: replace lonely DECLARE_INSTANCE_CHECKER with DECLARE_OBJ_CHECKERS
+    #      if all types are found.
+    #      This will require looking up the correct class type in the TypeInfo
+    #      structs in another file
+    regexp = S(r'^[ \t]*DECLARE_INSTANCE_CHECKER\s*\(\s*',
+               NAMED('instancetype', RE_TYPE), r'\s*,\s*',
+               NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*',
+               OR(RE_IDENTIFIER, RE_STRING, RE_MACRO_CONCAT, RE_FUN_CALL, name='typename'), SP,
+               r'\)[ \t]*;?[ \t]*\n')
+
+    def required_identifiers(self) -> Iterable[RequiredIdentifier]:
+        yield RequiredIdentifier('include', '"qom/object.h"')
+        yield RequiredIdentifier('constant', self.group('typename'))
+        yield RequiredIdentifier('type', self.group('instancetype'))
+
+class DeclareClassCheckers(FileMatch):
+    """DECLARE_INSTANCE_CHECKER use"""
+    regexp = S(r'^[ \t]*DECLARE_CLASS_CHECKERS\s*\(\s*',
+               NAMED('classtype', RE_TYPE), r'\s*,\s*',
+               NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*',
+               OR(RE_IDENTIFIER, RE_STRING, RE_MACRO_CONCAT, RE_FUN_CALL, name='typename'), SP,
+               r'\)[ \t]*;?[ \t]*\n')
+
+    def required_identifiers(self) -> Iterable[RequiredIdentifier]:
+        yield RequiredIdentifier('include', '"qom/object.h"')
+        yield RequiredIdentifier('constant', self.group('typename'))
+        yield RequiredIdentifier('type', self.group('classtype'))
+
+class DeclareObjCheckers(FileMatch):
+    """DECLARE_OBJ_CHECKERS use
+    Will be replaced with OBJECT_DECLARE_TYPE if possible
+    """
+    #TODO: detect when OBJECT_DECLARE_SIMPLE_TYPE can be used
+    regexp = S(r'^[ \t]*DECLARE_OBJ_CHECKERS\s*\(\s*',
+               NAMED('instancetype', RE_TYPE), r'\s*,\s*',
+               NAMED('classtype', RE_TYPE), r'\s*,\s*',
+               NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*',
+               OR(RE_IDENTIFIER, RE_STRING, RE_MACRO_CONCAT, RE_FUN_CALL, name='typename'), SP,
+               r'\)[ \t]*;?[ \t]*\n')
+
+    def required_identifiers(self) -> Iterable[RequiredIdentifier]:
+        yield RequiredIdentifier('include', '"qom/object.h"')
+        yield RequiredIdentifier('constant', self.group('typename'))
+        yield RequiredIdentifier('type', self.group('classtype'))
+        yield RequiredIdentifier('type', self.group('instancetype'))
+
+    def gen_patches(self):
+        ids = TypeIdentifiers(uppercase=self.group('uppercase'),
+                              typename=self.group('typename'),
+                              classtype=self.group('classtype'),
+                              instancetype=self.group('instancetype'))
+        issues = ids.check_consistency()
+        if issues:
+            for i in issues:
+                self.warn("inconsistent identifiers: %s", i)
+            return
+
+        if self.group('typename') != 'TYPE_'+self.group('uppercase'):
+            self.warn("type %s mismatch with uppercase name %s", ids.typename, ids.uppercase)
+            return
+
+        typedefs = [(t,self.file.find_match(SimpleTypedefMatch, t))
+                    for t in (ids.instancetype, ids.classtype)]
+        for t,td in typedefs:
+            if td is None:
+                self.warn("typedef %s not found", t)
+                break
+            if td.start() > self.start():
+                self.warn("typedef %s needs to be move earlier in the file", t)
+                break
+            #HACK: check if typedef is used between its definition and the macro
+            #TODO: check if the only match is inside the "struct { ... }" declaration
+            if re.search(r'\b'+t+r'\b', self.file.original_content[td.end():self.start()]):
+                self.warn("typedef %s can't be moved, it is used before the macro", t)
+                break
+        else:
+            for t,td in typedefs:
+                yield td.make_removal_patch()
+
+            lowercase = ids.uppercase.lower()
+            # all is OK, we can replace the macro!
+            c = (f'OBJECT_DECLARE_TYPE({ids.instancetype}, {ids.classtype},\n'
+                 f'                    {lowercase}, {ids.uppercase})\n')
+            yield self.make_patch(c)
+
+class TrivialClassStruct(FileMatch):
+    """Trivial class struct"""
+    regexp = S(r'^[ \t]*struct\s*', NAMED('name', RE_IDENTIFIER),
+               r'\s*{\s*', NAMED('parent_struct', RE_IDENTIFIER), r'\s*parent(_class)?\s*;\s*};\n')
+
+class DeclareTypeName(FileMatch):
+    """DECLARE_TYPE_NAME usage"""
+    regexp = S(r'^[ \t]*DECLARE_TYPE_NAME\s*\(',
+               NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*',
+               OR(RE_IDENTIFIER, RE_STRING, RE_MACRO_CONCAT, RE_FUN_CALL, name='typename'),
+               r'\s*\);?[ \t]*\n')
+
+class ObjectDeclareType(FileMatch):
+    """OBJECT_DECLARE_TYPE usage
+    Will be replaced with OBJECT_DECLARE_SIMPLE_TYPE if possible
+    """
+    regexp = S(r'^[ \t]*OBJECT_DECLARE_TYPE\s*\(',
+               NAMED('instancetype', RE_TYPE), r'\s*,\s*',
+               NAMED('classtype', RE_TYPE), r'\s*,\s*',
+               NAMED('lowercase', RE_IDENTIFIER), r'\s*,\s*',
+               NAMED('uppercase', RE_IDENTIFIER), SP,
+               r'\)[ \t]*;?[ \t]*\n')
+
+    def gen_patches(self):
+        DBG("groups: %r", self.match.groupdict())
+        trivial_struct = self.file.find_match(TrivialClassStruct, self.group('classtype'))
+        if trivial_struct:
+            d = self.match.groupdict().copy()
+            d['parent_struct'] = trivial_struct.group("parent_struct")
+            yield trivial_struct.make_removal_patch()
+            c = ("OBJECT_DECLARE_SIMPLE_TYPE(%(instancetype)s, %(lowercase)s,\n"
+                 "                           %(uppercase)s, %(parent_struct)s)\n" % d)
+            yield self.make_patch(c)
+
+def find_type_declaration(files: FileList, typename: str) -> Optional[FileMatch]:
+    """Find usage of DECLARE*CHECKER macro"""
+    for c in (DeclareInstanceChecker, DeclareClassCheckers, DeclareObjCheckers, DeclareTypeName):
+        d = files.find_match(c, name=typename, group='typename')
+        if d:
+            return d
+    return None
+
+
+class Include(FileMatch):
+    """#include directive"""
+    regexp = RE_INCLUDE
+    def provided_identifiers(self) -> Iterable[RequiredIdentifier]:
+        yield RequiredIdentifier('include', self.group('includepath'))
+
+class InitialIncludes(FileMatch):
+    """Initial #include block"""
+    regexp = S(RE_FILE_BEGIN,
+               M(SP, RE_COMMENTS,
+                 r'^[ \t]*#[ \t]*ifndef[ \t]+', RE_IDENTIFIER, r'[ \t]*\n',
+                 n='?', name='ifndef_block'),
+               M(SP, RE_COMMENTS,
+                 OR(RE_INCLUDE, RE_SIMPLEDEFINE),
+                 n='*', name='includes'))
+
+class SymbolUserList(NamedTuple):
+    definitions: List[FileMatch]
+    users: List[FileMatch]
+
+class MoveSymbols(FileMatch):
+    """Handle missing symbols
+    - Move typedefs and defines when necessary
+    - Add missing #include lines when necessary
+    """
+    regexp = RE_FILE_BEGIN
+
+    def gen_patches(self) -> Iterator[Patch]:
+        index: Dict[RequiredIdentifier, SymbolUserList] = {}
+        definition_classes = [SimpleTypedefMatch, FullStructTypedefMatch, ConstantDefine, Include]
+        user_classes = [TypeCheckMacro, DeclareObjCheckers, DeclareInstanceChecker, DeclareClassCheckers]
+
+        # first we scan for all symbol definitions and usage:
+        for dc in definition_classes:
+            defs = self.file.matches_of_type(dc)
+            for d in defs:
+                DBG("scanning %r", d)
+                for i in d.provided_identifiers():
+                    index.setdefault(i, SymbolUserList([], [])).definitions.append(d)
+        DBG("index: %r", list(index.keys()))
+        for uc in user_classes:
+            users = self.file.matches_of_type(uc)
+            for u in users:
+                for i in u.required_identifiers():
+                    index.setdefault(i, SymbolUserList([], [])).users.append(u)
+
+        # validate all symbols:
+        for i,ul in index.items():
+            if not ul.users:
+                # unused symbol
+                continue
+
+            # symbol not defined
+            if len(ul.definitions) == 0:
+                if i.type == 'include':
+                   includes, = self.file.matches_of_type(InitialIncludes)
+                   #FIXME: don't do this if we're already inside qom/object.h
+                   yield includes.append(f'#include {i.name}\n')
+                else:
+                    u.warn("definition of %s %s not found in file", i.type, i.name)
+                continue
+
+            # symbol defined twice:
+            if len(ul.definitions) > 1:
+                ul.definitions[1].warn("%s defined twice", i.name)
+                ul.definitions[0].warn("previously defined here")
+                continue
+
+            # symbol defined.  check if all users are after its definition:
+            assert len(ul.definitions) == 1
+            definition = ul.definitions[0]
+            DBG("handling repositioning of %r", definition)
+            earliest = min(ul.users, key=lambda u: u.start())
+            if earliest.start() > definition.start():
+                DBG("%r is OK", definition)
+                continue
+
+            DBG("%r needs to be moved", definition)
+            if isinstance(definition, SimpleTypedefMatch) \
+               or isinstance(definition, ConstantDefine):
+                # simple typedef or define can be moved directly:
+                yield definition.make_removal_patch()
+                yield earliest.prepend(definition.group(0))
+            elif isinstance(definition, FullStructTypedefMatch) \
+                 and definition.group('structname'):
+                # full struct typedef is more complex: we need to remove
+                # the typedef
+                yield from definition.move_typedef(earliest.start())
+            else:
+                definition.warn("definition of %s %s needs to be moved earlier in the file", i.type, i.name)
+                earliest.warn("definition of %s %s is used here", i.type, i.name)
+
diff --git a/scripts/codeconverter/codeconverter/qom_type_info.py b/scripts/codeconverter/codeconverter/qom_type_info.py
new file mode 100644
index 0000000000..fc02058739
--- /dev/null
+++ b/scripts/codeconverter/codeconverter/qom_type_info.py
@@ -0,0 +1,434 @@
+# Copyright (C) 2020 Red Hat Inc.
+#
+# Authors:
+#  Eduardo Habkost <ehabkost@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+import re
+from .regexps import *
+from .patching import *
+from .utils import *
+from .qom_macros import *
+
+TI_FIELDS = [ 'name', 'parent', 'abstract', 'interfaces',
+    'instance_size', 'instance_init', 'instance_post_init', 'instance_finalize',
+    'class_size', 'class_init', 'class_base_init', 'class_data']
+
+RE_TI_FIELD_NAME = OR(*TI_FIELDS)
+
+RE_TI_FIELD_INIT = S(r'[ \t]*', NAMED('comments', RE_COMMENTS),
+                     r'\.', NAMED('field', RE_TI_FIELD_NAME), r'\s*=\s*',
+                     NAMED('value', RE_EXPRESSION), r'[ \t]*,?[ \t]*\n')
+RE_TI_FIELDS = M(RE_TI_FIELD_INIT)
+
+RE_TYPEINFO_START = S(r'^[ \t]*', M(r'(static|const)\s+', name='modifiers'), r'TypeInfo\s+',
+                      NAMED('name', RE_IDENTIFIER), r'\s*=\s*{[ \t]*\n')
+RE_TYPEINFO_DEF = S(RE_TYPEINFO_START,
+                    M(NAMED('fields', RE_TI_FIELDS),
+                      SP, NAMED('endcomments', RE_COMMENTS),
+                      r'};?\n',
+                      n='?', name='fullspec'))
+
+ParsedArray = List[str]
+ParsedInitializerValue = Union[str, ParsedArray]
+class InitializerValue(NamedTuple):
+    raw: str
+    parsed: Optional[ParsedInitializerValue]
+    match: Optional[Match]
+TypeInfoInitializers = Dict[str, InitializerValue]
+
+def parse_array(m: Match) -> ParsedArray:
+    #DBG('parse_array: %r', m.group(0))
+    return [m.group('arrayitem') for m in re.finditer(RE_ARRAY_ITEM, m.group('arrayitems'))]
+
+def parse_initializer_value(m: Match, s: str) -> InitializerValue:
+    parsed: Optional[ParsedInitializerValue] = None
+    #DBG("parse_initializer_value: %r", s)
+    array = re.match(RE_ARRAY, s)
+    if array:
+        parsed = parse_array(array)
+    return InitializerValue(s, parsed, m)
+
+class TypeInfoVar(FileMatch):
+    """TypeInfo variable declaration with initializer
+    Will be replaced by OBJECT_DEFINE_TYPE_EXTENDED macro
+    (not implemented yet)
+    """
+    regexp = RE_TYPEINFO_DEF
+
+    @property
+    def initializers(self) -> Optional[TypeInfoInitializers]:
+        if getattr(self, '_inititalizers', None):
+            self._initializers: TypeInfoInitializers
+            return self._initializers
+        fields = self.group('fields')
+        if fields is None:
+            return None
+        d = dict((fm.group('field'), parse_initializer_value(fm, fm.group('value')))
+                  for fm in re.finditer(RE_TI_FIELD_INIT, fields))
+        self._initializers = d
+        return d
+
+    def is_static(self) -> bool:
+        return 'static' in self.group('modifiers')
+
+    def is_full(self) -> bool:
+        return bool(self.group('fullspec'))
+
+    def get_initializers(self) -> TypeInfoInitializers:
+        """Helper for code that needs to deal with missing initializer info"""
+        if self.initializers is None:
+            return {}
+        return self.initializers
+
+    def get_initializer_value(self, field: str) -> InitializerValue:
+        return self.get_initializers().get(field, InitializerValue('', '', None))
+
+    #def extract_identifiers(self) -> Optional[TypeIdentifiers]:
+    #    """Try to extract identifiers from names being used"""
+    #    DBG("extracting idenfiers from %s", self.name)
+        #uppercase = None
+        #if typename and re.fullmatch(RE_IDENTIFIER, typename) and typename.startswith("TYPE_"):
+        #    uppercase = typename[len('TYPE_'):]
+        #lowercase = None
+        #funcs = set()
+        #prefixes = set()
+        #for field,suffix in [('instance_init', '_init'),
+        #                     ('instance_finalize', '_finalize'),
+        #                     ('class_init', '_class_init')]:
+        #    if field not in values:
+        #        continue
+        #    func = values[field].raw
+        #    funcs.add(func)
+        #    if func.endswith(suffix):
+        #        prefixes.add(func[:-len(suffix)])
+        #    else:
+        #        self.warn("function name %s doesn't have expected %s suffix",
+        #                  func, suffix)
+        #if len(prefixes) == 1:
+        #    lowercase = prefixes.pop()
+        #elif len(prefixes) > 1:
+        #    self.warn("inconsistent function names: %s", ' '.join(funcs))
+
+        #.parent = TYPE_##PARENT_MODULE_OBJ_NAME, \
+        #return TypeIdentifiers(typename=typename,
+        #                       uppercase=uppercase, lowercase=lowercase,
+        #                       instancetype=instancetype, classtype=classtype)
+
+    def append_field(self, field, value) -> Patch:
+        """Generate patch appending a field initializer"""
+        content = f'    .{field} = {value},\n'
+        return Patch(self.match.end('fields'), self.match.end('fields'),
+                     content)
+
+    def patch_field(self, field: str, replacement: str) -> Patch:
+        """Generate patch replacing a field initializer"""
+        values = self.initializers
+        assert values
+        value = values.get(field)
+        assert value
+        fm = value.match
+        assert fm
+        fstart = self.match.start('fields') + fm.start()
+        fend = self.match.start('fields') + fm.end()
+        return Patch(fstart, fend, replacement)
+
+    def gen_patches(self) -> Iterable[Patch]:
+        values = self.initializers
+        if values is None:
+            return
+        if 'name' not in values:
+            self.warn("name not set in TypeInfo variable %s", self.name)
+            return
+        typename = values['name'].raw
+        if 'parent' not in values:
+            self.warn("parent not set in TypeInfo variable %s", self.name)
+            return
+        parent_typename = values['parent'].raw
+
+        instancetype = None
+        if 'instance_size' in values:
+            m = re.fullmatch(RE_SIZEOF, values['instance_size'].raw)
+            if m:
+                instancetype = m.group('sizeoftype')
+            else:
+                self.warn("can't extract instance type in TypeInfo variable %s", self.name)
+                self.warn("instance_size is set to: %r", values['instance_size'].raw)
+                return
+
+        classtype = None
+        if 'class_size' in values:
+            m = re.fullmatch(RE_SIZEOF, values['class_size'].raw)
+            if m:
+                classtype = m.group('sizeoftype')
+            else:
+                self.warn("can't extract class type in TypeInfo variable %s", self.name)
+                self.warn("class_size is set to: %r", values['class_size'].raw)
+                return
+
+        #NOTE: this will NOT work after declarations are converted
+        #      to OBJECT_DECLARE*
+
+        # Now, the challenge is to find out the right MODULE_OBJ_NAME for the
+        # type and for the parent type
+        instance_decl = find_type_declaration(self.allfiles, typename)
+        parent_decl = find_type_declaration(self.allfiles, parent_typename)
+
+        self.info("TypeInfo variable for %s is here", typename)
+        if instance_decl:
+            instance_decl.info("instance type declaration (%s) is here", instance_decl.match.group('uppercase'))
+        if parent_decl:
+            parent_decl.info("parent type declaration (%s) is here", parent_decl.match.group('uppercase'))
+
+        ok = True
+        if (instance_decl is None and (instancetype or classtype)):
+            self.warn("Can't find where type checkers for %s are declared.  We need them to validate sizes of %s", typename, self.name)
+            ok = False
+
+        if (instance_decl is not None
+            and 'instancetype' in instance_decl.match.groupdict()
+            and instancetype != instance_decl.group('instancetype')):
+            self.warn("type at instance_size is %r.  Should instance_size be set to sizeof(%s) ?",
+                      instancetype, instance_decl.group('instancetype'))
+            instance_decl.warn("Type checker declaration for %s is here", typename)
+            ok = False
+        if (instance_decl is not None
+            and 'classtype' in instance_decl.match.groupdict()
+            and classtype != instance_decl.group('classtype')):
+            self.warn("type at class_size is %r.  Should class_size be set to sizeof(%s) ?",
+                      classtype, instance_decl.group('classtype'))
+            instance_decl.warn("Type checker declaration for %s is here", typename)
+            ok = False
+
+        if not ok:
+            return
+
+        #if parent_decl is None:
+        #    self.warn("Can't find where parent type %s is declared", parent_typename)
+
+        self.info("%s can be patched!", self.name)
+        return
+        yield
+
+class RedundantTypeSizes(TypeInfoVar):
+    """Remove redundant instance_size/class_size from TypeInfo vars"""
+    def gen_patches(self) -> Iterable[Patch]:
+        values = self.initializers
+        if values is None:
+            return
+        if 'name' not in values:
+            self.warn("name not set in TypeInfo variable %s", self.name)
+            return
+        typename = values['name'].raw
+        if 'parent' not in values:
+            self.warn("parent not set in TypeInfo variable %s", self.name)
+            return
+        parent_typename = values['parent'].raw
+
+        if 'instance_size' not in values and 'class_size' not in values:
+            self.debug("no need to validate %s", self.name)
+            return
+
+        instance_decl = find_type_declaration(self.allfiles, typename)
+        if instance_decl:
+            self.debug("won't touch TypeInfo var that has type checkers")
+            return
+
+        parent = find_type_info(self.allfiles, parent_typename)
+        if not parent:
+            self.warn("Can't find TypeInfo for %s", parent_typename)
+            return
+
+        if 'instance_size' in values and parent.get_initializer_value('instance_size').raw != values['instance_size'].raw:
+            self.info("instance_size mismatch")
+            parent.info("parent type declared here")
+            return
+
+        if 'class_size' in values and parent.get_initializer_value('class_size').raw != values['class_size'].raw:
+            self.info("class_size mismatch")
+            parent.info("parent type declared here")
+            return
+
+        self.debug("will patch variable %s", self.name)
+
+        if 'instance_size' in values:
+            self.debug("deleting instance_size")
+            yield self.patch_field('instance_size', '')
+
+        if 'class_size' in values:
+            self.debug("deleting class_size")
+            yield self.patch_field('class_size', '')
+
+
+#class TypeInfoVarInitFuncs(TypeInfoVar):
+#    """TypeInfo variable
+#    Will create missing init functions
+#    """
+#    def gen_patches(self) -> Iterable[Patch]:
+#        values = self.initializers
+#        if values is None:
+#            self.warn("type not parsed completely: %s", self.name)
+#            return
+#
+#        macro = self.file.find_match(TypeInfoVar, self.name)
+#        if macro is None:
+#            self.warn("No TYPE_INFO macro for %s", self.name)
+#            return
+#
+#        ids = self.extract_identifiers()
+#        if ids is None:
+#            return
+#
+#        DBG("identifiers extracted: %r", ids)
+#        fields = set(values.keys())
+#        if ids.lowercase:
+#            if 'instance_init' not in fields:
+#                yield self.prepend(('static void %s_init(Object *obj)\n'
+#                                    '{\n'
+#                                    '}\n\n') % (ids.lowercase))
+#                yield self.append_field('instance_init', ids.lowercase+'_init')
+#
+#            if 'instance_finalize' not in fields:
+#                yield self.prepend(('static void %s_finalize(Object *obj)\n'
+#                                    '{\n'
+#                                    '}\n\n') % (ids.lowercase))
+#                yield self.append_field('instance_finalize', ids.lowercase+'_finalize')
+#
+#
+#            if 'class_init' not in fields:
+#                yield self.prepend(('static void %s_class_init(ObjectClass *oc, void *data)\n'
+#                                    '{\n'
+#                                    '}\n\n') % (ids.lowercase))
+#                yield self.append_field('class_init', ids.lowercase+'_class_init')
+
+class TypeInitMacro(FileMatch):
+    """type_init(...) macro use
+    Will be deleted if function is empty
+    """
+    regexp = S(r'^[ \t]*type_init\s*\(\s*', NAMED('name', RE_IDENTIFIER), r'\s*\);?[ \t]*\n')
+    def gen_patches(self) -> Iterable[Patch]:
+        fn = self.file.find_match(StaticVoidFunction, self.name)
+        DBG("function for %s: %s", self.name, fn)
+        if fn and fn.body == '':
+            yield fn.make_patch('')
+            yield self.make_patch('')
+
+class StaticVoidFunction(FileMatch):
+    """simple static void function
+    (no replacement rules)
+    """
+    #NOTE: just like RE_FULL_STRUCT, this doesn't parse any of the body contents
+    #      of the function.  Tt will just look for "}" in the beginning of a line
+    regexp = S(r'static\s+void\s+', NAMED('name', RE_IDENTIFIER), r'\s*\(\s*void\s*\)\n',
+               r'{\n',
+               NAMED('body',
+                     # acceptable inside the function body:
+                     # - lines starting with space or tab
+                     # - empty lines
+                     # - preprocessor directives
+                     OR(r'[ \t][^\n]*\n',
+                        r'#[^\n]*\n',
+                        r'\n',
+                        repeat='*')),
+               r'}\n')
+
+    @property
+    def body(self) -> str:
+        return self.group('body')
+
+    def has_preprocessor_directive(self) -> bool:
+        return bool(re.search(r'^[ \t]*#', self.body, re.MULTILINE))
+
+class TypeRegisterCall(FileMatch):
+    """type_register_static() call
+    Will be replaced by TYPE_INFO() macro
+    """
+    regexp = S(r'^[ \t]*type_register_static\s*\(&\s*', NAMED('name', RE_IDENTIFIER), r'\s*\);[ \t]*\n')
+
+    def function(self) -> Optional['StaticVoidFunction']:
+        """Return function containing this call"""
+        for m in self.file.matches_of_type(StaticVoidFunction):
+            if m.contains(self):
+                return m
+        return None
+
+    def gen_patches(self) -> Iterable[Patch]:
+        fn = self.function()
+        if fn is None:
+            self.warn("can't find function where type_register_static(&%s) is called", self.name)
+            return
+
+        #if fn.has_preprocessor_directive() and not self.file.force:
+        #    self.warn("function %s has preprocessor directives, this requires --force", fn.name)
+        #    return
+
+        type_init = self.file.find_match(TypeInitMacro, fn.name)
+        if type_init is None:
+            self.warn("can't find type_init(%s) line", fn.name)
+            return
+
+        var = self.file.find_match(TypeInfoVar, self.name)
+        if var is None:
+            self.warn("can't find TypeInfo var declaration for %s", self.name)
+            return
+
+        if not var.is_full():
+            self.warn("variable declaration %s wasn't parsed fully", var.name)
+            return
+
+        if fn.contains(var):
+            self.warn("TypeInfo %s variable is inside a function", self.name)
+            return
+
+        # delete type_register_static() call:
+        yield self.make_patch('')
+        # append TYPE_REGISTER(...) after variable declaration:
+        yield var.append(f'TYPE_INFO({self.name})\n')
+
+class TypeInfoMacro(FileMatch):
+    """TYPE_INFO macro usage"""
+    regexp = S(r'^[ \t]*TYPE_INFO\s*\(\s*', NAMED('name', RE_IDENTIFIER), r'\s*\)[ \t]*;?[ \t]*\n')
+
+def find_type_info(files: RegexpScanner, name: str) -> Optional[TypeInfoVar]:
+    ti = [ti for ti in files.matches_of_type(TypeInfoVar)
+            if ti.get_initializer_value('name').raw == name]
+    DBG("type info vars: %r", ti)
+    if len(ti) > 1:
+        DBG("multiple TypeInfo vars found for %s", name)
+        return None
+    if len(ti) == 0:
+        DBG("no TypeInfo var found for %s", name)
+        return None
+    return ti[0]
+
+class CreateClassStruct(DeclareInstanceChecker):
+    """Replace DECLARE_INSTANCE_CHECKER with OBJECT_DECLARE_SIMPLE_TYPE"""
+    def gen_patches(self) -> Iterable[Patch]:
+        typename = self.group('typename')
+        DBG("looking for TypeInfo variable for %s", typename)
+        var = find_type_info(self.allfiles, typename)
+        if var is None:
+            self.warn("no TypeInfo var found for %s", typename)
+            return
+        assert var.initializers
+        if 'class_size' in var.initializers:
+            self.warn("class size already set for TypeInfo %s", var.name)
+            return
+        classtype = self.group('instancetype')+'Class'
+        return
+        yield
+        #TODO: need to find out what's the parent class type...
+        #yield var.append_field('class_size', f'sizeof({classtype})')
+        #c = (f'OBJECT_DECLARE_SIMPLE_TYPE({instancetype}, {lowercase},\n'
+        #     f'                           MODULE_OBJ_NAME, ParentClassType)\n')
+        #yield self.make_patch(c)
+
+def type_infos(file: FileInfo) -> Iterable[TypeInfoVar]:
+    return file.matches_of_type(TypeInfoVar)
+
+def full_types(file: FileInfo) -> Iterable[TypeInfoVar]:
+    return [t for t in type_infos(file) if t.is_full()]
+
+def partial_types(file: FileInfo) -> Iterable[TypeInfoVar]:
+    return [t for t in type_infos(file) if not t.is_full()]
diff --git a/scripts/codeconverter/codeconverter/regexps.py b/scripts/codeconverter/codeconverter/regexps.py
new file mode 100644
index 0000000000..77993cc3b9
--- /dev/null
+++ b/scripts/codeconverter/codeconverter/regexps.py
@@ -0,0 +1,118 @@
+# Copyright (C) 2020 Red Hat Inc.
+#
+# Authors:
+#  Eduardo Habkost <ehabkost@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+"""Helpers for creation of regular expressions"""
+import re
+
+import logging
+logger = logging.getLogger(__name__)
+DBG = logger.debug
+INFO = logger.info
+WARN = logger.warning
+
+def S(*regexps) -> str:
+    """Just a shortcut to concatenate multiple regexps more easily"""
+    return ''.join(regexps)
+
+def P(*regexps, name=None, capture=False, repeat='') -> str:
+    """Just add parenthesis around regexp(s), with optional name or repeat suffix"""
+    s = S(*regexps)
+    if name:
+        return f'(?P<{name}>{s}){repeat}'
+    elif capture:
+        return f'({s}){repeat}'
+    else:
+        return f'(?:{s}){repeat}'
+
+def NAMED(name, *regexps) -> str:
+    """Make named group using <P<name>...) syntax
+
+    >>> NAMED('mygroup', 'xyz', 'abc')
+    '(?P<mygroup>xyzabc)'
+    """
+    return P(*regexps, name=name)
+
+def OR(*regexps, **kwargs) -> str:
+    """Build (a|b|c) regexp"""
+    return P('|'.join(regexps), **kwargs)
+
+def M(*regexps, n='*', name=None) -> str:
+    """Add repetition qualifier to regexp(s)
+
+    >>> M('a', 'b')
+    '(?:ab)*'
+    >>> M('a' , 'b', n='+')
+    '(?:ab)+'
+    >>> M('a' , 'b', n='{2,3}', name='name')
+    '(?P<name>(?:ab){2,3})'
+    """
+    r = P(*regexps, repeat=n)
+    if name:
+        r = NAMED(name, r)
+    return r
+
+# helper to make parenthesis optional around regexp
+OPTIONAL_PARS = lambda R: OR(S(r'\(\s*', R, r'\s*\)'), R)
+def test_optional_pars():
+    r = OPTIONAL_PARS('abc')+'$'
+    assert re.match(r, 'abc')
+    assert re.match(r, '(abc)')
+    assert not re.match(r, '(abcd)')
+    assert not re.match(r, '(abc')
+    assert not re.match(r, 'abc)')
+
+
+# this disables the MULTILINE flag, so it will match at the
+# beginning of the file:
+RE_FILE_BEGIN = r'(?-m:^)'
+
+# C primitives:
+
+SP = r'\s*'
+
+RE_COMMENT = r'//[^\n]*$|/\*([^*]|\*[^/])*\*/'
+RE_COMMENTS = M(RE_COMMENT + SP)
+
+RE_IDENTIFIER = r'[a-zA-Z_][a-zA-Z0-9_]*(?![a-zA-Z0-9])'
+RE_STRING = r'\"([^\"\\]|\\[a-z\"])*\"'
+RE_NUMBER = r'[0-9]+|0x[0-9a-fA-F]+'
+
+# space or escaped newlines:
+CPP_SPACE = OR(r'\s', r'\\\n', repeat='+')
+
+RE_PATH = '[a-zA-Z0-9/_.-]+'
+
+RE_INCLUDEPATH = OR(S(r'\"', RE_PATH, r'\"'),
+                    S(r'<', RE_PATH, r'>'))
+
+RE_INCLUDE = S(r'^[ \t]*#[ \t]*include[ \t]+', NAMED('includepath', RE_INCLUDEPATH), r'[ \t]*\n')
+RE_SIMPLEDEFINE = S(r'^[ \t]*#[ \t]*define[ \t]+', RE_IDENTIFIER, r'[ \t]*\n')
+
+RE_STRUCT_TYPE = S(r'struct\s+', RE_IDENTIFIER)
+RE_TYPE = OR(RE_IDENTIFIER, RE_STRUCT_TYPE)
+
+RE_MACRO_CONCAT = M(S(OR(RE_IDENTIFIER, RE_STRING), SP), n='{2,}')
+
+RE_SIMPLE_VALUE = OR(RE_IDENTIFIER, RE_STRING, RE_NUMBER)
+
+RE_FUN_CALL = S(RE_IDENTIFIER, r'\s*\(\s*', RE_SIMPLE_VALUE, r'\s*\)')
+RE_SIZEOF = S(r'sizeof\s*\(\s*', NAMED('sizeoftype', RE_TYPE), r'\s*\)')
+
+RE_ADDRESS = S(r'&\s*', RE_IDENTIFIER)
+
+RE_ARRAY_ITEM = S(r'{\s*', NAMED('arrayitem', M(RE_SIMPLE_VALUE, n='?')), r'\s*}\s*,?')
+RE_ARRAY_CAST = S(r'\(\s*', RE_IDENTIFIER, r'\s*\[\s*\]\)')
+RE_ARRAY_ITEMS = M(S(RE_ARRAY_ITEM, SP))
+RE_ARRAY = S(M(RE_ARRAY_CAST, n='?'), r'\s*{\s*',
+             NAMED('arrayitems', RE_ARRAY_ITEMS),
+             r'}')
+
+# NOTE: this covers a very small subset of valid expressions
+
+RE_EXPRESSION = OR(RE_SIZEOF, RE_FUN_CALL, RE_MACRO_CONCAT, RE_SIMPLE_VALUE,
+                   RE_ARRAY, RE_ADDRESS)
+
diff --git a/scripts/codeconverter/codeconverter/test_patching.py b/scripts/codeconverter/codeconverter/test_patching.py
new file mode 100644
index 0000000000..5998af81c9
--- /dev/null
+++ b/scripts/codeconverter/codeconverter/test_patching.py
@@ -0,0 +1,105 @@
+# Copyright (C) 2020 Red Hat Inc.
+#
+# Authors:
+#  Eduardo Habkost <ehabkost@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+from tempfile import NamedTemporaryFile
+from .patching import FileInfo, FileMatch, Patch, FileList
+from .regexps import *
+
+class BasicPattern(FileMatch):
+    regexp = '[abc]{3}'
+
+    @property
+    def name(self):
+        return self.group(0)
+
+    def replacement(self) -> str:
+        # replace match with the middle character repeated 5 times
+        return self.group(0)[1].upper()*5
+
+def test_pattern_patching():
+    of = NamedTemporaryFile('wt')
+    of.writelines(['one line\n',
+                  'this pattern will be patched: defbbahij\n',
+                  'third line\n',
+                  'another pattern: jihaabfed'])
+    of.flush()
+
+    files = FileList()
+    f = FileInfo(files, of.name)
+    f.load()
+    f.scan_for_matches()
+    matches = f.matches_of_type(BasicPattern)
+    assert len(matches) == 2
+    p2 = matches[1]
+
+    # manually add patch, to see if .append() works:
+    f.patches.append(p2.append('XXX'))
+
+    # apply all patches:
+    f.gen_patches()
+    patched = f.get_patched_content()
+    assert patched == ('one line\n'+
+                       'this pattern will be patched: defBBBBBhij\n'+
+                       'third line\n'+
+                       'another pattern: jihAAAAAXXXfed')
+
+class Function(FileMatch):
+    regexp = S(r'BEGIN\s+', NAMED('name', RE_IDENTIFIER), r'\n',
+               r'(.*\n)*?END\n')
+
+class Statement(FileMatch):
+    regexp = S(r'^\s*', NAMED('name', RE_IDENTIFIER), r'\(\)\n')
+
+def test_container_match():
+    of = NamedTemporaryFile('wt')
+    of.writelines(['statement1()\n',
+                   'statement2()\n',
+                   'BEGIN function1\n',
+                   '  statement3()\n',
+                   '  statement4()\n',
+                   'END\n',
+                   'BEGIN function2\n',
+                   '  statement5()\n',
+                   '  statement6()\n',
+                   'END\n',
+                   'statement7()\n'])
+    of.flush()
+
+    files = FileList()
+    f = FileInfo(files, of.name)
+    f.load()
+    assert len(f.matches_of_type(Function)) == 2
+    print(' '.join(m.name for m in f.matches_of_type(Statement)))
+    assert len(f.matches_of_type(Statement)) == 7
+
+    f1 = f.find_match(Function, 'function1')
+    f2 = f.find_match(Function, 'function2')
+    st1 = f.find_match(Statement, 'statement1')
+    st2 = f.find_match(Statement, 'statement2')
+    st3 = f.find_match(Statement, 'statement3')
+    st4 = f.find_match(Statement, 'statement4')
+    st5 = f.find_match(Statement, 'statement5')
+    st6 = f.find_match(Statement, 'statement6')
+    st7 = f.find_match(Statement, 'statement7')
+
+    assert not f1.contains(st1)
+    assert not f1.contains(st2)
+    assert not f1.contains(st2)
+    assert f1.contains(st3)
+    assert f1.contains(st4)
+    assert not f1.contains(st5)
+    assert not f1.contains(st6)
+    assert not f1.contains(st7)
+
+    assert not f2.contains(st1)
+    assert not f2.contains(st2)
+    assert not f2.contains(st2)
+    assert not f2.contains(st3)
+    assert not f2.contains(st4)
+    assert f2.contains(st5)
+    assert f2.contains(st6)
+    assert not f2.contains(st7)
diff --git a/scripts/codeconverter/codeconverter/test_regexps.py b/scripts/codeconverter/codeconverter/test_regexps.py
new file mode 100644
index 0000000000..9b84d689a6
--- /dev/null
+++ b/scripts/codeconverter/codeconverter/test_regexps.py
@@ -0,0 +1,282 @@
+# Copyright (C) 2020 Red Hat Inc.
+#
+# Authors:
+#  Eduardo Habkost <ehabkost@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+from .regexps import *
+from .qom_macros import *
+from .qom_type_info import *
+
+def test_res():
+    def fullmatch(regexp, s):
+        return re.fullmatch(regexp, s, re.MULTILINE)
+
+    assert fullmatch(RE_IDENTIFIER, 'sizeof')
+    assert fullmatch(RE_IDENTIFIER, 'X86CPU')
+    assert fullmatch(RE_FUN_CALL, 'sizeof(X86CPU)')
+    assert fullmatch(RE_IDENTIFIER, 'X86_CPU_TYPE_NAME')
+    assert fullmatch(RE_SIMPLE_VALUE, '"base"')
+    print(RE_FUN_CALL)
+    assert fullmatch(RE_FUN_CALL, 'X86_CPU_TYPE_NAME("base")')
+    print(RE_TI_FIELD_INIT)
+    assert fullmatch(RE_TI_FIELD_INIT, '.name = X86_CPU_TYPE_NAME("base"),\n')
+
+
+    assert fullmatch(RE_MACRO_CONCAT, 'TYPE_ASPEED_GPIO "-ast2600"')
+    assert fullmatch(RE_EXPRESSION, 'TYPE_ASPEED_GPIO "-ast2600"')
+
+    print(RE_MACRO_DEFINE)
+    assert re.search(RE_MACRO_DEFINE, r'''
+    #define OFFSET_CHECK(c)                     \
+    do {                                        \
+        if (!(c)) {                             \
+            goto bad_offset;                    \
+        }                                       \
+    } while (0)
+    ''', re.MULTILINE)
+
+    print(RE_CHECK_MACRO)
+    print(CPP_SPACE)
+    assert not re.match(RE_CHECK_MACRO, r'''
+    #define OFFSET_CHECK(c)                     \
+    do {                                        \
+        if (!(c)) {                             \
+            goto bad_offset;                    \
+        }                                       \
+    } while (0)''', re.MULTILINE)
+
+    print(RE_CHECK_MACRO)
+    assert fullmatch(RE_CHECK_MACRO, r'''#define PCI_DEVICE(obj) \
+                     OBJECT_CHECK(PCIDevice, (obj), TYPE_PCI_DEVICE)
+''')
+    assert fullmatch(RE_CHECK_MACRO, r'''#define COLLIE_MACHINE(obj) \
+                     OBJECT_CHECK(CollieMachineState, obj, TYPE_COLLIE_MACHINE)
+''')
+
+    print(RE_TYPEINFO_START)
+    assert re.search(RE_TYPEINFO_START, r'''
+    cc->open = qmp_chardev_open_file;
+}
+
+static const TypeInfo char_file_type_info = {
+    .name = TYPE_CHARDEV_FILE,
+#ifdef _WIN32
+    .parent = TYPE_CHARDEV_WIN,
+''', re.MULTILINE)
+    assert re.search(RE_TYPEINFO_START, r'''
+        TypeInfo ti = {
+            .name = armsse_variants[i].name,
+            .parent = TYPE_ARMSSE,
+            .class_init = armsse_class_init,
+            .class_data = (void *)&armsse_variants[i],
+        };''', re.MULTILINE)
+
+    print(RE_ARRAY_ITEM)
+    assert fullmatch(RE_ARRAY_ITEM, '{ TYPE_HOTPLUG_HANDLER },')
+    assert fullmatch(RE_ARRAY_ITEM, '{ TYPE_ACPI_DEVICE_IF },')
+    assert fullmatch(RE_ARRAY_ITEM, '{ }')
+    assert fullmatch(RE_ARRAY_CAST, '(InterfaceInfo[])')
+    assert fullmatch(RE_ARRAY, '''(InterfaceInfo[]) {
+            { TYPE_HOTPLUG_HANDLER },
+            { TYPE_ACPI_DEVICE_IF },
+            { }
+    }''')
+    print(RE_COMMENT)
+    assert fullmatch(RE_COMMENT, r'''/* multi-line
+                                      * comment
+                                      */''')
+
+    print(RE_TI_FIELDS)
+    assert fullmatch(RE_TI_FIELDS,
+    r'''/* could be TYPE_SYS_BUS_DEVICE (or LPC etc) */
+        .parent = TYPE_DEVICE,
+''')
+    assert fullmatch(RE_TI_FIELDS, r'''.name = TYPE_TPM_CRB,
+        /* could be TYPE_SYS_BUS_DEVICE (or LPC etc) */
+        .parent = TYPE_DEVICE,
+        .instance_size = sizeof(CRBState),
+        .class_init  = tpm_crb_class_init,
+        .interfaces = (InterfaceInfo[]) {
+            { TYPE_TPM_IF },
+            { }
+        }
+''')
+    assert fullmatch(RE_TI_FIELDS + SP + RE_COMMENTS,
+        r'''.name = TYPE_PALM_MISC_GPIO,
+            .parent = TYPE_SYS_BUS_DEVICE,
+            .instance_size = sizeof(PalmMiscGPIOState),
+            .instance_init = palm_misc_gpio_init,
+            /*
+             * No class init required: device has no internal state so does not
+             * need to set up reset or vmstate, and has no realize method.
+             */''')
+
+    print(RE_TYPEINFO_DEF)
+    test_empty = 'static const TypeInfo x86_base_cpu_type_info = {\n'+\
+                 '};\n';
+    assert fullmatch(RE_TYPEINFO_DEF, test_empty)
+
+    test_simple = r'''
+    static const TypeInfo x86_base_cpu_type_info = {
+        .name = X86_CPU_TYPE_NAME("base"),
+        .parent = TYPE_X86_CPU,
+        .class_init = x86_cpu_base_class_init,
+    };
+    '''
+    assert re.search(RE_TYPEINFO_DEF, test_simple, re.MULTILINE)
+
+    test_interfaces = r'''
+    static const TypeInfo acpi_ged_info = {
+        .name          = TYPE_ACPI_GED,
+        .parent        = TYPE_SYS_BUS_DEVICE,
+        .instance_size = sizeof(AcpiGedState),
+        .instance_init  = acpi_ged_initfn,
+        .class_init    = acpi_ged_class_init,
+        .interfaces = (InterfaceInfo[]) {
+            { TYPE_HOTPLUG_HANDLER },
+            { TYPE_ACPI_DEVICE_IF },
+            { }
+        }
+    };
+    '''
+    assert re.search(RE_TYPEINFO_DEF, test_interfaces, re.MULTILINE)
+
+    test_comments = r'''
+    static const TypeInfo palm_misc_gpio_info = {
+        .name = TYPE_PALM_MISC_GPIO,
+        .parent = TYPE_SYS_BUS_DEVICE,
+        .instance_size = sizeof(PalmMiscGPIOState),
+        .instance_init = palm_misc_gpio_init,
+        /*
+         * No class init required: device has no internal state so does not
+         * need to set up reset or vmstate, and has no realize method.
+         */
+    };
+    '''
+    assert re.search(RE_TYPEINFO_DEF, test_comments, re.MULTILINE)
+
+    test_comments = r'''
+    static const TypeInfo tpm_crb_info = {
+        .name = TYPE_TPM_CRB,
+        /* could be TYPE_SYS_BUS_DEVICE (or LPC etc) */
+        .parent = TYPE_DEVICE,
+        .instance_size = sizeof(CRBState),
+        .class_init  = tpm_crb_class_init,
+        .interfaces = (InterfaceInfo[]) {
+            { TYPE_TPM_IF },
+            { }
+        }
+    };
+    '''
+    assert re.search(RE_TYPEINFO_DEF, test_comments, re.MULTILINE)
+
+def test_struct_re():
+    print('---')
+    print(RE_STRUCT_TYPEDEF)
+    assert re.search(RE_STRUCT_TYPEDEF, r'''
+typedef struct TCGState {
+    AccelState parent_obj;
+
+    bool mttcg_enabled;
+    unsigned long tb_size;
+} TCGState;
+''', re.MULTILINE)
+
+    assert re.search(RE_STRUCT_TYPEDEF, r'''
+typedef struct {
+    ISADevice parent_obj;
+
+    QEMUSoundCard card;
+    uint32_t freq;
+    uint32_t port;
+    int ticking[2];
+    int enabled;
+    int active;
+    int bufpos;
+#ifdef DEBUG
+    int64_t exp[2];
+#endif
+    int16_t *mixbuf;
+    uint64_t dexp[2];
+    SWVoiceOut *voice;
+    int left, pos, samples;
+    QEMUAudioTimeStamp ats;
+    FM_OPL *opl;
+    PortioList port_list;
+} AdlibState;
+''', re.MULTILINE)
+
+    false_positive = r'''
+typedef struct dma_pagetable_entry {
+    int32_t frame;
+    int32_t owner;
+} A B C D E;
+struct foo {
+    int x;
+} some_variable;
+'''
+    assert not re.search(RE_STRUCT_TYPEDEF, false_positive, re.MULTILINE)
+
+def test_initial_includes():
+    print(InitialIncludes.regexp)
+    c = '''
+#ifndef HW_FLASH_H
+#define HW_FLASH_H
+
+/* NOR flash devices */
+
+#include "qom/object.h"
+#include "exec/hwaddr.h"
+
+/* pflash_cfi01.c */
+'''
+    print(repr(list(m.groupdict() for m in re.finditer(InitialIncludes.regexp, c, re.MULTILINE))))
+    m = re.match(InitialIncludes.regexp, c, re.MULTILINE)
+    assert m
+    print(repr(m.group(0)))
+    assert m.group(0).endswith('#include "exec/hwaddr.h"\n')
+
+    c = '''#ifndef QEMU_VIRTIO_9P_H
+#define QEMU_VIRTIO_9P_H
+
+#include "standard-headers/linux/virtio_9p.h"
+#include "hw/virtio/virtio.h"
+#include "9p.h"
+
+
+'''
+    print(repr(list(m.groupdict() for m in re.finditer(InitialIncludes.regexp, c, re.MULTILINE))))
+    m = re.match(InitialIncludes.regexp, c, re.MULTILINE)
+    assert m
+    print(repr(m.group(0)))
+    assert m.group(0).endswith('#include "9p.h"\n')
+
+    c = '''#include "qom/object.h"
+/*
+ * QEMU ES1370 emulation
+...
+ */
+
+/* #define DEBUG_ES1370 */
+/* #define VERBOSE_ES1370 */
+#define SILENT_ES1370
+
+#include "qemu/osdep.h"
+#include "hw/audio/soundhw.h"
+#include "audio/audio.h"
+#include "hw/pci/pci.h"
+#include "migration/vmstate.h"
+#include "qemu/module.h"
+#include "sysemu/dma.h"
+
+/* Missing stuff:
+   SCTRL_P[12](END|ST)INC
+'''
+    print(repr(list(m.groupdict() for m in re.finditer(InitialIncludes.regexp, c, re.MULTILINE))))
+    m = re.match(InitialIncludes.regexp, c, re.MULTILINE)
+    assert m
+    print(repr(m.group(0)))
+    assert m.group(0).endswith('#include "sysemu/dma.h"\n')
+
diff --git a/scripts/codeconverter/codeconverter/utils.py b/scripts/codeconverter/codeconverter/utils.py
new file mode 100644
index 0000000000..760ab7eecd
--- /dev/null
+++ b/scripts/codeconverter/codeconverter/utils.py
@@ -0,0 +1,72 @@
+# Copyright (C) 2020 Red Hat Inc.
+#
+# Authors:
+#  Eduardo Habkost <ehabkost@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+from typing import *
+
+import logging
+logger = logging.getLogger(__name__)
+DBG = logger.debug
+INFO = logger.info
+WARN = logger.warning
+
+T = TypeVar('T')
+def opt_compare(a: T, b: T) -> bool:
+    """Compare two values, ignoring mismatches if one of them is None"""
+    return (a is None) or (b is None) or (a == b)
+
+def merge(a: T, b: T) -> T:
+    """Merge two values if they matched using opt_compare()"""
+    assert opt_compare(a, b)
+    if a is None:
+        return b
+    else:
+        return a
+
+def test_comp_merge():
+    assert opt_compare(None, 1) == True
+    assert opt_compare(2, None) == True
+    assert opt_compare(1, 1) == True
+    assert opt_compare(1, 2) == False
+
+    assert merge(None, None) is None
+    assert merge(None, 10) == 10
+    assert merge(10, None) == 10
+    assert merge(10, 10) == 10
+
+
+LineNumber = NewType('LineNumber', int)
+ColumnNumber = NewType('ColumnNumber', int)
+class LineAndColumn(NamedTuple):
+    line: int
+    col: int
+
+    def __str__(self):
+        return '%d:%d' % (self.line, self.col)
+
+def line_col(s, position: int) -> LineAndColumn:
+    """Return line and column for a char position in string
+
+    Character position starts in 0, but lines and columns start in 1.
+    """
+    before = s[:position]
+    lines = before.split('\n')
+    line = len(lines)
+    col = len(lines[-1]) + 1
+    return LineAndColumn(line, col)
+
+def test_line_col():
+    assert line_col('abc\ndefg\nhijkl', 0) == (1, 1)
+    assert line_col('abc\ndefg\nhijkl', 2) == (1, 3)
+    assert line_col('abc\ndefg\nhijkl', 3) == (1, 4)
+    assert line_col('abc\ndefg\nhijkl', 4) == (2, 1)
+    assert line_col('abc\ndefg\nhijkl', 10) == (3, 2)
+
+def not_optional(arg: Optional[T]) -> T:
+    assert arg is not None
+    return arg
+
+__all__ = ['not_optional', 'opt_compare', 'merge', 'line_col', 'LineAndColumn']
\ No newline at end of file
diff --git a/scripts/codeconverter/converter.py b/scripts/codeconverter/converter.py
new file mode 100755
index 0000000000..ebaf9b57ce
--- /dev/null
+++ b/scripts/codeconverter/converter.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python3
+# QEMU library
+#
+# Copyright (C) 2020 Red Hat Inc.
+#
+# Authors:
+#  Eduardo Habkost <ehabkost@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+#
+import sys
+import argparse
+import os
+import os.path
+import re
+from typing import *
+
+from codeconverter.patching import FileInfo, match_class_dict, FileList
+import codeconverter.qom_macros
+from codeconverter.qom_type_info import TI_FIELDS, type_infos, TypeInfoVar
+
+import logging
+logger = logging.getLogger(__name__)
+DBG = logger.debug
+INFO = logger.info
+WARN = logger.warning
+
+def process_all_files(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None:
+    DBG("filenames: %r", args.filenames)
+
+    files = FileList()
+    files.extend(FileInfo(files, fn, args.force) for fn in args.filenames)
+    for f in files:
+        DBG('opening %s', f.filename)
+        f.load()
+
+    if args.table:
+        fields = ['filename', 'variable_name'] + TI_FIELDS
+        print('\t'.join(fields))
+        for f in files:
+            for t in f.matches_of_type(TypeInfoVar):
+                assert isinstance(t, TypeInfoVar)
+                values = [f.filename, t.name] + \
+                         [t.get_initializer_value(f).raw
+                          for f in TI_FIELDS]
+                DBG('values: %r', values)
+                assert all('\t' not in v for v in values)
+                values = [v.replace('\n', ' ').replace('"', '') for v in values]
+                print('\t'.join(values))
+        return
+
+    match_classes = match_class_dict()
+    if not args.patterns:
+        parser.error("--pattern is required")
+
+    classes = [p for arg in args.patterns
+                for p in re.split(r'[\s,]', arg)]
+    for c in classes:
+        if c not in match_classes:
+            print("Invalid pattern name: %s" % (c), file=sys.stderr)
+            print("Valid patterns:", file=sys.stderr)
+            print(PATTERN_HELP, file=sys.stderr)
+            sys.exit(1)
+
+    DBG("classes: %r", classes)
+    for f in files:
+        DBG("patching contents of %s", f.filename)
+        f.patch_content(max_passes=args.passes, class_names=classes)
+
+    for f in files:
+        #alltypes.extend(f.type_infos)
+        #full_types.extend(f.full_types())
+
+        if not args.dry_run:
+            if args.inplace:
+                f.patch_inplace()
+            if args.diff:
+                f.show_diff()
+            if not args.diff and not args.inplace:
+                f.write_to_file(sys.stdout)
+                sys.stdout.flush()
+
+
+PATTERN_HELP = ('\n'.join("  %s: %s" % (n, str(c.__doc__).strip())
+                for (n,c) in sorted(match_class_dict().items())
+                if c.has_replacement_rule()))
+
+def main() -> None:
+    p = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
+    p.add_argument('filenames', nargs='+')
+    p.add_argument('--passes', type=int, default=1,
+                   help="Number of passes (0 means unlimited)")
+    p.add_argument('--pattern', required=True, action='append',
+                   default=[], dest='patterns',
+                   help="Pattern to scan for")
+    p.add_argument('--inplace', '-i', action='store_true',
+                   help="Patch file in place")
+    p.add_argument('--dry-run', action='store_true',
+                   help="Don't patch files or print patching results")
+    p.add_argument('--force', '-f', action='store_true',
+                   help="Perform changes even if not completely safe")
+    p.add_argument('--diff', action='store_true',
+                   help="Print diff output on stdout")
+    p.add_argument('--debug', '-d', action='store_true',
+                   help="Enable debugging")
+    p.add_argument('--verbose', '-v', action='store_true',
+                   help="Verbose logging on stderr")
+    p.add_argument('--table', action='store_true',
+                   help="Print CSV table of type information")
+    p.add_argument_group("Valid pattern names",
+                         PATTERN_HELP)
+    args = p.parse_args()
+
+    loglevel = (logging.DEBUG if args.debug
+             else logging.INFO if args.verbose
+             else logging.WARN)
+    logging.basicConfig(format='%(levelname)s: %(message)s', level=loglevel)
+    DBG("args: %r", args)
+    process_all_files(p, args)
+
+if __name__ == '__main__':
+    main()
\ No newline at end of file
diff --git a/scripts/tracetool/format/d.py b/scripts/tracetool/format/d.py
index 0afb5f3f47..353722f89c 100644
--- a/scripts/tracetool/format/d.py
+++ b/scripts/tracetool/format/d.py
@@ -13,6 +13,7 @@ __email__      = "stefanha@redhat.com"
 
 
 from tracetool import out
+from sys import platform
 
 
 # Reserved keywords from
@@ -34,7 +35,8 @@ def generate(events, backend, group):
 
     # SystemTap's dtrace(1) warns about empty "provider qemu {}" but is happy
     # with an empty file.  Avoid the warning.
-    if not events:
+    # But dtrace on macOS can't deal with empty files.
+    if not events and platform != "darwin":
         return
 
     out('/* This file is autogenerated by tracetool, do not edit. */'
@@ -44,6 +46,17 @@ def generate(events, backend, group):
     for e in events:
         args = []
         for type_, name in e.args:
+            if platform == "darwin":
+                # macOS dtrace accepts only C99 _Bool
+                if type_ == 'bool':
+                    type_ = '_Bool'
+                if type_ == 'bool *':
+                    type_ = '_Bool *'
+                # It converts int8_t * in probe points to char * in header
+                # files and introduces [-Wpointer-sign] warning.
+                # Avoid it by changing probe type to signed char * beforehand.
+                if type_ == 'int8_t *':
+                    type_ = 'signed char *'
             if name in RESERVED_WORDS:
                 name += '_'
             args.append(type_ + ' ' + name)
diff --git a/scripts/tracetool/vcpu.py b/scripts/tracetool/vcpu.py
index b54e4f4e7a..868b4cb04c 100644
--- a/scripts/tracetool/vcpu.py
+++ b/scripts/tracetool/vcpu.py
@@ -24,7 +24,7 @@ def transform_event(event):
         assert "tcg-trans" not in event.properties
         assert "tcg-exec" not in event.properties
 
-        event.args = Arguments([("CPUState *", "__cpu"), event.args])
+        event.args = Arguments([("void *", "__cpu"), event.args])
         if "tcg" in event.properties:
             fmt = "\"cpu=%p \""
             event.fmt = [fmt + event.fmt[0],
diff --git a/scsi/pr-manager-helper.c b/scsi/pr-manager-helper.c
index 5acccfb4e3..d735b1e7f6 100644
--- a/scsi/pr-manager-helper.c
+++ b/scsi/pr-manager-helper.c
@@ -21,16 +21,17 @@
 #include "qemu/module.h"
 
 #include <scsi/sg.h>
+#include "qom/object.h"
 
 #define PR_MAX_RECONNECT_ATTEMPTS 5
 
 #define TYPE_PR_MANAGER_HELPER "pr-manager-helper"
 
-#define PR_MANAGER_HELPER(obj) \
-     OBJECT_CHECK(PRManagerHelper, (obj), \
-                  TYPE_PR_MANAGER_HELPER)
+typedef struct PRManagerHelper PRManagerHelper;
+DECLARE_INSTANCE_CHECKER(PRManagerHelper, PR_MANAGER_HELPER,
+                         TYPE_PR_MANAGER_HELPER)
 
-typedef struct PRManagerHelper {
+struct PRManagerHelper {
     /* <private> */
     PRManager parent;
 
@@ -38,7 +39,7 @@ typedef struct PRManagerHelper {
 
     QemuMutex lock;
     QIOChannel *ioc;
-} PRManagerHelper;
+};
 
 static void pr_manager_send_status_changed_event(PRManagerHelper *pr_mgr)
 {
diff --git a/softmmu/balloon.c b/softmmu/balloon.c
index b89646f85d..23452295cd 100644
--- a/softmmu/balloon.c
+++ b/softmmu/balloon.c
@@ -28,10 +28,10 @@
 #include "qemu/atomic.h"
 #include "sysemu/kvm.h"
 #include "sysemu/balloon.h"
-#include "trace/trace-root.h"
 #include "qapi/error.h"
 #include "qapi/qapi-commands-misc.h"
 #include "qapi/qmp/qerror.h"
+#include "trace.h"
 
 static QEMUBalloonEvent *balloon_event_fn;
 static QEMUBalloonStatus *balloon_stat_fn;
diff --git a/softmmu/ioport.c b/softmmu/ioport.c
index a799697c5d..cb8adb0b93 100644
--- a/softmmu/ioport.c
+++ b/softmmu/ioport.c
@@ -28,9 +28,9 @@
 #include "qemu/osdep.h"
 #include "cpu.h"
 #include "exec/ioport.h"
-#include "trace/trace-root.h"
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
+#include "trace.h"
 
 typedef struct MemoryRegionPortioList {
     MemoryRegion mr;
diff --git a/softmmu/memory.c b/softmmu/memory.c
index 70b93104e8..d030eb6f7c 100644
--- a/softmmu/memory.c
+++ b/softmmu/memory.c
@@ -24,7 +24,7 @@
 #include "qemu/main-loop.h"
 #include "qemu/qemu-print.h"
 #include "qom/object.h"
-#include "trace/trace-root.h"
+#include "trace.h"
 
 #include "exec/memory-internal.h"
 #include "exec/ram_addr.h"
diff --git a/softmmu/trace-events b/softmmu/trace-events
new file mode 100644
index 0000000000..b80ca042e1
--- /dev/null
+++ b/softmmu/trace-events
@@ -0,0 +1,28 @@
+# See docs/devel/tracing.txt for syntax documentation.
+
+# balloon.c
+# Since requests are raised via monitor, not many tracepoints are needed.
+balloon_event(void *opaque, unsigned long addr) "opaque %p addr %lu"
+
+# ioport.c
+cpu_in(unsigned int addr, char size, unsigned int val) "addr 0x%x(%c) value %u"
+cpu_out(unsigned int addr, char size, unsigned int val) "addr 0x%x(%c) value %u"
+
+# memory.c
+memory_region_ops_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
+memory_region_ops_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
+memory_region_subpage_read(int cpu_index, void *mr, uint64_t offset, uint64_t value, unsigned size) "cpu %d mr %p offset 0x%"PRIx64" value 0x%"PRIx64" size %u"
+memory_region_subpage_write(int cpu_index, void *mr, uint64_t offset, uint64_t value, unsigned size) "cpu %d mr %p offset 0x%"PRIx64" value 0x%"PRIx64" size %u"
+memory_region_ram_device_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
+memory_region_ram_device_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
+flatview_new(void *view, void *root) "%p (root %p)"
+flatview_destroy(void *view, void *root) "%p (root %p)"
+flatview_destroy_rcu(void *view, void *root) "%p (root %p)"
+
+# vl.c
+vm_state_notify(int running, int reason, const char *reason_str) "running %d reason %d (%s)"
+load_file(const char *name, const char *path) "name %s location %s"
+runstate_set(int current_state, const char *current_state_str, int new_state, const char *new_state_str) "current_run_state %d (%s) new_state %d (%s)"
+system_wakeup_request(int reason) "reason=%d"
+qemu_system_shutdown_request(int reason) "reason=%d"
+qemu_system_powerdown_request(void) ""
diff --git a/softmmu/trace.h b/softmmu/trace.h
new file mode 100644
index 0000000000..2ad1011572
--- /dev/null
+++ b/softmmu/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-softmmu.h"
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 0cc86b0766..f7b103467c 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -90,7 +90,7 @@
 
 #include "disas/disas.h"
 
-#include "trace/trace-root.h"
+#include "trace.h"
 #include "trace/control.h"
 #include "qemu/plugin.h"
 #include "qemu/queue.h"
diff --git a/target/alpha/cpu-qom.h b/target/alpha/cpu-qom.h
index 08832fa767..568fe3fb77 100644
--- a/target/alpha/cpu-qom.h
+++ b/target/alpha/cpu-qom.h
@@ -21,15 +21,12 @@
 #define QEMU_ALPHA_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_ALPHA_CPU "alpha-cpu"
 
-#define ALPHA_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(AlphaCPUClass, (klass), TYPE_ALPHA_CPU)
-#define ALPHA_CPU(obj) \
-    OBJECT_CHECK(AlphaCPU, (obj), TYPE_ALPHA_CPU)
-#define ALPHA_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(AlphaCPUClass, (obj), TYPE_ALPHA_CPU)
+OBJECT_DECLARE_TYPE(AlphaCPU, AlphaCPUClass,
+                    alpha_cpu, ALPHA_CPU)
 
 /**
  * AlphaCPUClass:
@@ -38,15 +35,14 @@
  *
  * An Alpha CPU model.
  */
-typedef struct AlphaCPUClass {
+struct AlphaCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} AlphaCPUClass;
+};
 
-typedef struct AlphaCPU AlphaCPU;
 
 #endif
diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
index fdef05cacf..94bbbd4473 100644
--- a/target/arm/cpu-qom.h
+++ b/target/arm/cpu-qom.h
@@ -21,17 +21,14 @@
 #define QEMU_ARM_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 struct arm_boot_info;
 
 #define TYPE_ARM_CPU "arm-cpu"
 
-#define ARM_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(ARMCPUClass, (klass), TYPE_ARM_CPU)
-#define ARM_CPU(obj) \
-    OBJECT_CHECK(ARMCPU, (obj), TYPE_ARM_CPU)
-#define ARM_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(ARMCPUClass, (obj), TYPE_ARM_CPU)
+OBJECT_DECLARE_TYPE(ARMCPU, ARMCPUClass,
+                    arm_cpu, ARM_CPU)
 
 #define TYPE_ARM_MAX_CPU "max-" TYPE_ARM_CPU
 
@@ -51,7 +48,7 @@ void aarch64_cpu_register(const ARMCPUInfo *info);
  *
  * An ARM CPU model.
  */
-typedef struct ARMCPUClass {
+struct ARMCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
@@ -59,21 +56,19 @@ typedef struct ARMCPUClass {
     const ARMCPUInfo *info;
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} ARMCPUClass;
+};
 
-typedef struct ARMCPU ARMCPU;
 
 #define TYPE_AARCH64_CPU "aarch64-cpu"
-#define AARCH64_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(AArch64CPUClass, (klass), TYPE_AARCH64_CPU)
-#define AARCH64_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(AArch64CPUClass, (obj), TYPE_AARCH64_CPU)
+typedef struct AArch64CPUClass AArch64CPUClass;
+DECLARE_CLASS_CHECKERS(AArch64CPUClass, AARCH64_CPU,
+                       TYPE_AARCH64_CPU)
 
-typedef struct AArch64CPUClass {
+struct AArch64CPUClass {
     /*< private >*/
     ARMCPUClass parent_class;
     /*< public >*/
-} AArch64CPUClass;
+};
 
 void register_cp_regs_for_features(ARMCPU *cpu);
 void init_cpreg_list(ARMCPU *cpu);
diff --git a/target/arm/idau.h b/target/arm/idau.h
index 7c0e4e3776..0ef5251971 100644
--- a/target/arm/idau.h
+++ b/target/arm/idau.h
@@ -33,16 +33,15 @@
 #define TYPE_IDAU_INTERFACE "idau-interface"
 #define IDAU_INTERFACE(obj) \
     INTERFACE_CHECK(IDAUInterface, (obj), TYPE_IDAU_INTERFACE)
-#define IDAU_INTERFACE_CLASS(class) \
-    OBJECT_CLASS_CHECK(IDAUInterfaceClass, (class), TYPE_IDAU_INTERFACE)
-#define IDAU_INTERFACE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(IDAUInterfaceClass, (obj), TYPE_IDAU_INTERFACE)
+typedef struct IDAUInterfaceClass IDAUInterfaceClass;
+DECLARE_CLASS_CHECKERS(IDAUInterfaceClass, IDAU_INTERFACE,
+                       TYPE_IDAU_INTERFACE)
 
 typedef struct IDAUInterface IDAUInterface;
 
 #define IREGION_NOTVALID -1
 
-typedef struct IDAUInterfaceClass {
+struct IDAUInterfaceClass {
     InterfaceClass parent;
 
     /* Check the specified address and return the IDAU security information
@@ -54,6 +53,6 @@ typedef struct IDAUInterfaceClass {
      */
     void (*check)(IDAUInterface *ii, uint32_t address, int *iregion,
                   bool *exempt, bool *ns, bool *nsc);
-} IDAUInterfaceClass;
+};
 
 #endif
diff --git a/target/avr/cpu-qom.h b/target/avr/cpu-qom.h
index d23ad43a99..49d63faad2 100644
--- a/target/avr/cpu-qom.h
+++ b/target/avr/cpu-qom.h
@@ -22,15 +22,12 @@
 #define QEMU_AVR_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_AVR_CPU "avr-cpu"
 
-#define AVR_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(AVRCPUClass, (klass), TYPE_AVR_CPU)
-#define AVR_CPU(obj) \
-    OBJECT_CHECK(AVRCPU, (obj), TYPE_AVR_CPU)
-#define AVR_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(AVRCPUClass, (obj), TYPE_AVR_CPU)
+OBJECT_DECLARE_TYPE(AVRCPU, AVRCPUClass,
+                    avr_cpu, AVR_CPU)
 
 /**
  *  AVRCPUClass:
@@ -40,14 +37,13 @@
  *
  *  A AVR CPU model.
  */
-typedef struct AVRCPUClass {
+struct AVRCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} AVRCPUClass;
+};
 
-typedef struct AVRCPU AVRCPU;
 
 #endif /* !defined (QEMU_AVR_CPU_QOM_H) */
diff --git a/target/cris/cpu-qom.h b/target/cris/cpu-qom.h
index f1de6041dc..2b0328113c 100644
--- a/target/cris/cpu-qom.h
+++ b/target/cris/cpu-qom.h
@@ -21,15 +21,12 @@
 #define QEMU_CRIS_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_CRIS_CPU "cris-cpu"
 
-#define CRIS_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(CRISCPUClass, (klass), TYPE_CRIS_CPU)
-#define CRIS_CPU(obj) \
-    OBJECT_CHECK(CRISCPU, (obj), TYPE_CRIS_CPU)
-#define CRIS_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(CRISCPUClass, (obj), TYPE_CRIS_CPU)
+OBJECT_DECLARE_TYPE(CRISCPU, CRISCPUClass,
+                    cris_cpu, CRIS_CPU)
 
 /**
  * CRISCPUClass:
@@ -39,7 +36,7 @@
  *
  * A CRIS CPU model.
  */
-typedef struct CRISCPUClass {
+struct CRISCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
@@ -48,8 +45,7 @@ typedef struct CRISCPUClass {
     DeviceReset parent_reset;
 
     uint32_t vr;
-} CRISCPUClass;
+};
 
-typedef struct CRISCPU CRISCPU;
 
 #endif
diff --git a/target/hppa/cpu-qom.h b/target/hppa/cpu-qom.h
index b1f6045495..58158f374b 100644
--- a/target/hppa/cpu-qom.h
+++ b/target/hppa/cpu-qom.h
@@ -21,15 +21,12 @@
 #define QEMU_HPPA_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_HPPA_CPU "hppa-cpu"
 
-#define HPPA_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(HPPACPUClass, (klass), TYPE_HPPA_CPU)
-#define HPPA_CPU(obj) \
-    OBJECT_CHECK(HPPACPU, (obj), TYPE_HPPA_CPU)
-#define HPPA_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(HPPACPUClass, (obj), TYPE_HPPA_CPU)
+OBJECT_DECLARE_TYPE(HPPACPU, HPPACPUClass,
+                    hppa_cpu, HPPA_CPU)
 
 /**
  * HPPACPUClass:
@@ -38,15 +35,14 @@
  *
  * An HPPA CPU model.
  */
-typedef struct HPPACPUClass {
+struct HPPACPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} HPPACPUClass;
+};
 
-typedef struct HPPACPU HPPACPU;
 
 #endif
diff --git a/target/i386/cpu-qom.h b/target/i386/cpu-qom.h
index 3e96f8d668..0505472e86 100644
--- a/target/i386/cpu-qom.h
+++ b/target/i386/cpu-qom.h
@@ -22,6 +22,7 @@
 
 #include "hw/core/cpu.h"
 #include "qemu/notify.h"
+#include "qom/object.h"
 
 #ifdef TARGET_X86_64
 #define TYPE_X86_CPU "x86_64-cpu"
@@ -29,12 +30,8 @@
 #define TYPE_X86_CPU "i386-cpu"
 #endif
 
-#define X86_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(X86CPUClass, (klass), TYPE_X86_CPU)
-#define X86_CPU(obj) \
-    OBJECT_CHECK(X86CPU, (obj), TYPE_X86_CPU)
-#define X86_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(X86CPUClass, (obj), TYPE_X86_CPU)
+OBJECT_DECLARE_TYPE(X86CPU, X86CPUClass,
+                    x86_cpu, X86_CPU)
 
 typedef struct X86CPUModel X86CPUModel;
 
@@ -50,7 +47,7 @@ typedef struct X86CPUModel X86CPUModel;
  *
  * An x86 CPU model or family.
  */
-typedef struct X86CPUClass {
+struct X86CPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
@@ -72,8 +69,7 @@ typedef struct X86CPUClass {
     DeviceRealize parent_realize;
     DeviceUnrealize parent_unrealize;
     DeviceReset parent_reset;
-} X86CPUClass;
+};
 
-typedef struct X86CPU X86CPU;
 
 #endif
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 205b68bc0c..d87af57a23 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -302,7 +302,7 @@ static int get_para_features(KVMState *s)
     return features;
 }
 
-static bool host_tsx_blacklisted(void)
+static bool host_tsx_broken(void)
 {
     int family, model, stepping;\
     char vendor[CPUID_VENDOR_SZ + 1];
@@ -408,7 +408,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
     } else if (function == 6 && reg == R_EAX) {
         ret |= CPUID_6_EAX_ARAT; /* safe to allow because of emulated APIC */
     } else if (function == 7 && index == 0 && reg == R_EBX) {
-        if (host_tsx_blacklisted()) {
+        if (host_tsx_broken()) {
             ret &= ~(CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_HLE);
         }
     } else if (function == 7 && index == 0 && reg == R_EDX) {
@@ -1568,6 +1568,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
             if (env->nr_dies < 2) {
                 break;
             }
+            /* fallthrough */
         case 4:
         case 0xb:
         case 0xd:
diff --git a/target/i386/sev.c b/target/i386/sev.c
index de4818da6d..d976634b8f 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -28,12 +28,13 @@
 #include "sysemu/runstate.h"
 #include "trace.h"
 #include "migration/blocker.h"
+#include "qom/object.h"
 
 #define TYPE_SEV_GUEST "sev-guest"
-#define SEV_GUEST(obj)                                          \
-    OBJECT_CHECK(SevGuestState, (obj), TYPE_SEV_GUEST)
-
 typedef struct SevGuestState SevGuestState;
+DECLARE_INSTANCE_CHECKER(SevGuestState, SEV_GUEST,
+                         TYPE_SEV_GUEST)
+
 
 /**
  * SevGuestState:
diff --git a/target/lm32/cpu-qom.h b/target/lm32/cpu-qom.h
index bdedb3759a..e9eb495bf0 100644
--- a/target/lm32/cpu-qom.h
+++ b/target/lm32/cpu-qom.h
@@ -21,15 +21,12 @@
 #define QEMU_LM32_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_LM32_CPU "lm32-cpu"
 
-#define LM32_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(LM32CPUClass, (klass), TYPE_LM32_CPU)
-#define LM32_CPU(obj) \
-    OBJECT_CHECK(LM32CPU, (obj), TYPE_LM32_CPU)
-#define LM32_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(LM32CPUClass, (obj), TYPE_LM32_CPU)
+OBJECT_DECLARE_TYPE(LM32CPU, LM32CPUClass,
+                    lm32_cpu, LM32_CPU)
 
 /**
  * LM32CPUClass:
@@ -38,15 +35,14 @@
  *
  * A LatticeMico32 CPU model.
  */
-typedef struct LM32CPUClass {
+struct LM32CPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} LM32CPUClass;
+};
 
-typedef struct LM32CPU LM32CPU;
 
 #endif
diff --git a/target/m68k/cpu-qom.h b/target/m68k/cpu-qom.h
index 88b11b60f1..a10429cf67 100644
--- a/target/m68k/cpu-qom.h
+++ b/target/m68k/cpu-qom.h
@@ -21,15 +21,12 @@
 #define QEMU_M68K_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_M68K_CPU "m68k-cpu"
 
-#define M68K_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(M68kCPUClass, (klass), TYPE_M68K_CPU)
-#define M68K_CPU(obj) \
-    OBJECT_CHECK(M68kCPU, (obj), TYPE_M68K_CPU)
-#define M68K_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(M68kCPUClass, (obj), TYPE_M68K_CPU)
+OBJECT_DECLARE_TYPE(M68kCPU, M68kCPUClass,
+                    m68k_cpu, M68K_CPU)
 
 /*
  * M68kCPUClass:
@@ -38,15 +35,14 @@
  *
  * A Motorola 68k CPU model.
  */
-typedef struct M68kCPUClass {
+struct M68kCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} M68kCPUClass;
+};
 
-typedef struct M68kCPU M68kCPU;
 
 #endif
diff --git a/target/microblaze/cpu-qom.h b/target/microblaze/cpu-qom.h
index 053ba44ee8..82734b9b2b 100644
--- a/target/microblaze/cpu-qom.h
+++ b/target/microblaze/cpu-qom.h
@@ -21,15 +21,12 @@
 #define QEMU_MICROBLAZE_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_MICROBLAZE_CPU "microblaze-cpu"
 
-#define MICROBLAZE_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(MicroBlazeCPUClass, (klass), TYPE_MICROBLAZE_CPU)
-#define MICROBLAZE_CPU(obj) \
-    OBJECT_CHECK(MicroBlazeCPU, (obj), TYPE_MICROBLAZE_CPU)
-#define MICROBLAZE_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(MicroBlazeCPUClass, (obj), TYPE_MICROBLAZE_CPU)
+OBJECT_DECLARE_TYPE(MicroBlazeCPU, MicroBlazeCPUClass,
+                    microblaze_cpu, MICROBLAZE_CPU)
 
 /**
  * MicroBlazeCPUClass:
@@ -38,15 +35,14 @@
  *
  * A MicroBlaze CPU model.
  */
-typedef struct MicroBlazeCPUClass {
+struct MicroBlazeCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} MicroBlazeCPUClass;
+};
 
-typedef struct MicroBlazeCPU MicroBlazeCPU;
 
 #endif
diff --git a/target/mips/cpu-qom.h b/target/mips/cpu-qom.h
index 9d0df6c034..93fbbdca1b 100644
--- a/target/mips/cpu-qom.h
+++ b/target/mips/cpu-qom.h
@@ -21,6 +21,7 @@
 #define QEMU_MIPS_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #ifdef TARGET_MIPS64
 #define TYPE_MIPS_CPU "mips64-cpu"
@@ -28,12 +29,8 @@
 #define TYPE_MIPS_CPU "mips-cpu"
 #endif
 
-#define MIPS_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(MIPSCPUClass, (klass), TYPE_MIPS_CPU)
-#define MIPS_CPU(obj) \
-    OBJECT_CHECK(MIPSCPU, (obj), TYPE_MIPS_CPU)
-#define MIPS_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(MIPSCPUClass, (obj), TYPE_MIPS_CPU)
+OBJECT_DECLARE_TYPE(MIPSCPU, MIPSCPUClass,
+                    mips_cpu, MIPS_CPU)
 
 /**
  * MIPSCPUClass:
@@ -42,7 +39,7 @@
  *
  * A MIPS CPU model.
  */
-typedef struct MIPSCPUClass {
+struct MIPSCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
@@ -50,8 +47,7 @@ typedef struct MIPSCPUClass {
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
     const struct mips_def_t *cpu_def;
-} MIPSCPUClass;
+};
 
-typedef struct MIPSCPU MIPSCPU;
 
 #endif
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 899b90ae0f..398edf7289 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -20028,8 +20028,7 @@ static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
                                    int rt, int32_t imm, int32_t offset)
 {
-    TCGCond cond;
-    int bcond_compute = 0;
+    TCGCond cond = TCG_COND_ALWAYS;
     TCGv t0 = tcg_temp_new();
     TCGv t1 = tcg_temp_new();
 
@@ -20046,7 +20045,6 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
             /* Treat as NOP */
             goto out;
         } else {
-            bcond_compute = 1;
             cond = TCG_COND_EQ;
         }
         break;
@@ -20065,7 +20063,6 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
             tcg_gen_shri_tl(t0, t0, imm);
             tcg_gen_andi_tl(t0, t0, 1);
             tcg_gen_movi_tl(t1, 0);
-            bcond_compute = 1;
             if (opc == NM_BBEQZC) {
                 cond = TCG_COND_EQ;
             } else {
@@ -20080,7 +20077,6 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
         } else if (rt == 0 && imm != 0) {
             /* Unconditional branch */
         } else {
-            bcond_compute = 1;
             cond = TCG_COND_NE;
         }
         break;
@@ -20088,24 +20084,20 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
         if (rt == 0 && imm == 0) {
             /* Unconditional branch */
         } else  {
-            bcond_compute = 1;
             cond = TCG_COND_GE;
         }
         break;
     case NM_BLTIC:
-        bcond_compute = 1;
         cond = TCG_COND_LT;
         break;
     case NM_BGEIUC:
         if (rt == 0 && imm == 0) {
             /* Unconditional branch */
         } else  {
-            bcond_compute = 1;
             cond = TCG_COND_GEU;
         }
         break;
     case NM_BLTIUC:
-        bcond_compute = 1;
         cond = TCG_COND_LTU;
         break;
     default:
@@ -20118,7 +20110,7 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
     clear_branch_hflags(ctx);
     ctx->base.is_jmp = DISAS_NORETURN;
 
-    if (bcond_compute == 0) {
+    if (cond == TCG_COND_ALWAYS) {
         /* Uncoditional compact branch */
         gen_goto_tb(ctx, 0, ctx->btarget);
     } else {
diff --git a/target/moxie/cpu.h b/target/moxie/cpu.h
index 455553b794..d58761ccb1 100644
--- a/target/moxie/cpu.h
+++ b/target/moxie/cpu.h
@@ -21,6 +21,7 @@
 #define MOXIE_CPU_H
 
 #include "exec/cpu-defs.h"
+#include "qom/object.h"
 
 #define MOXIE_EX_DIV0        0
 #define MOXIE_EX_BAD         1
@@ -50,12 +51,8 @@ typedef struct CPUMoxieState {
 
 #define TYPE_MOXIE_CPU "moxie-cpu"
 
-#define MOXIE_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(MoxieCPUClass, (klass), TYPE_MOXIE_CPU)
-#define MOXIE_CPU(obj) \
-    OBJECT_CHECK(MoxieCPU, (obj), TYPE_MOXIE_CPU)
-#define MOXIE_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(MoxieCPUClass, (obj), TYPE_MOXIE_CPU)
+OBJECT_DECLARE_TYPE(MoxieCPU, MoxieCPUClass,
+                    moxie_cpu, MOXIE_CPU)
 
 /**
  * MoxieCPUClass:
@@ -63,14 +60,14 @@ typedef struct CPUMoxieState {
  *
  * A Moxie CPU model.
  */
-typedef struct MoxieCPUClass {
+struct MoxieCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} MoxieCPUClass;
+};
 
 /**
  * MoxieCPU:
@@ -78,14 +75,14 @@ typedef struct MoxieCPUClass {
  *
  * A Moxie CPU.
  */
-typedef struct MoxieCPU {
+struct MoxieCPU {
     /*< private >*/
     CPUState parent_obj;
     /*< public >*/
 
     CPUNegativeOffsetState neg;
     CPUMoxieState env;
-} MoxieCPU;
+};
 
 
 void moxie_cpu_do_interrupt(CPUState *cs);
diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
index 4dddf9c3a1..1fa0fdaa35 100644
--- a/target/nios2/cpu.h
+++ b/target/nios2/cpu.h
@@ -23,6 +23,7 @@
 
 #include "exec/cpu-defs.h"
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 typedef struct CPUNios2State CPUNios2State;
 #if !defined(CONFIG_USER_ONLY)
@@ -31,12 +32,8 @@ typedef struct CPUNios2State CPUNios2State;
 
 #define TYPE_NIOS2_CPU "nios2-cpu"
 
-#define NIOS2_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(Nios2CPUClass, (klass), TYPE_NIOS2_CPU)
-#define NIOS2_CPU(obj) \
-    OBJECT_CHECK(Nios2CPU, (obj), TYPE_NIOS2_CPU)
-#define NIOS2_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(Nios2CPUClass, (obj), TYPE_NIOS2_CPU)
+OBJECT_DECLARE_TYPE(Nios2CPU, Nios2CPUClass,
+                    nios2_cpu, NIOS2_CPU)
 
 /**
  * Nios2CPUClass:
@@ -44,14 +41,14 @@ typedef struct CPUNios2State CPUNios2State;
  *
  * A Nios2 CPU model.
  */
-typedef struct Nios2CPUClass {
+struct Nios2CPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} Nios2CPUClass;
+};
 
 #define TARGET_HAS_ICE 1
 
@@ -174,7 +171,7 @@ struct CPUNios2State {
  *
  * A Nios2 CPU.
  */
-typedef struct Nios2CPU {
+struct Nios2CPU {
     /*< private >*/
     CPUState parent_obj;
     /*< public >*/
@@ -191,7 +188,7 @@ typedef struct Nios2CPU {
     uint32_t reset_addr;
     uint32_t exception_addr;
     uint32_t fast_tlb_miss_addr;
-} Nios2CPU;
+};
 
 
 void nios2_tcg_init(void);
diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index f37a52e153..d0a8ee657a 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -22,18 +22,15 @@
 
 #include "exec/cpu-defs.h"
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 /* cpu_openrisc_map_address_* in CPUOpenRISCTLBContext need this decl.  */
 struct OpenRISCCPU;
 
 #define TYPE_OPENRISC_CPU "or1k-cpu"
 
-#define OPENRISC_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU)
-#define OPENRISC_CPU(obj) \
-    OBJECT_CHECK(OpenRISCCPU, (obj), TYPE_OPENRISC_CPU)
-#define OPENRISC_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(OpenRISCCPUClass, (obj), TYPE_OPENRISC_CPU)
+OBJECT_DECLARE_TYPE(OpenRISCCPU, OpenRISCCPUClass,
+                    openrisc_cpu, OPENRISC_CPU)
 
 /**
  * OpenRISCCPUClass:
@@ -42,14 +39,14 @@ struct OpenRISCCPU;
  *
  * A OpenRISC CPU model.
  */
-typedef struct OpenRISCCPUClass {
+struct OpenRISCCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} OpenRISCCPUClass;
+};
 
 #define TARGET_INSN_START_EXTRA_WORDS 1
 
@@ -305,14 +302,14 @@ typedef struct CPUOpenRISCState {
  *
  * A OpenRISC CPU.
  */
-typedef struct OpenRISCCPU {
+struct OpenRISCCPU {
     /*< private >*/
     CPUState parent_obj;
     /*< public >*/
 
     CPUNegativeOffsetState neg;
     CPUOpenRISCState env;
-} OpenRISCCPU;
+};
 
 
 void cpu_openrisc_list(void);
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index 000c7d405b..5cf806a3a6 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -21,6 +21,7 @@
 #define QEMU_PPC_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #ifdef TARGET_PPC64
 #define TYPE_POWERPC_CPU "powerpc64-cpu"
@@ -28,14 +29,9 @@
 #define TYPE_POWERPC_CPU "powerpc-cpu"
 #endif
 
-#define POWERPC_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(PowerPCCPUClass, (klass), TYPE_POWERPC_CPU)
-#define POWERPC_CPU(obj) \
-    OBJECT_CHECK(PowerPCCPU, (obj), TYPE_POWERPC_CPU)
-#define POWERPC_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(PowerPCCPUClass, (obj), TYPE_POWERPC_CPU)
+OBJECT_DECLARE_TYPE(PowerPCCPU, PowerPCCPUClass,
+                    powerpc_cpu, POWERPC_CPU)
 
-typedef struct PowerPCCPU PowerPCCPU;
 typedef struct CPUPPCState CPUPPCState;
 typedef struct ppc_tb_t ppc_tb_t;
 typedef struct ppc_dcr_t ppc_dcr_t;
@@ -159,7 +155,7 @@ typedef struct PPCHash64Options PPCHash64Options;
  *
  * A PowerPC CPU model.
  */
-typedef struct PowerPCCPUClass {
+struct PowerPCCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
@@ -197,7 +193,7 @@ typedef struct PowerPCCPUClass {
     int  (*check_pow)(CPUPPCState *env);
     int (*handle_mmu_fault)(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx);
     bool (*interrupts_big_endian)(PowerPCCPU *cpu);
-} PowerPCCPUClass;
+};
 
 #ifndef CONFIG_USER_ONLY
 typedef struct PPCTimebase {
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 3c4e1b3475..766e9c5c26 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -23,6 +23,7 @@
 #include "qemu/int128.h"
 #include "exec/cpu-defs.h"
 #include "cpu-qom.h"
+#include "qom/object.h"
 
 #define TCG_GUEST_DEFAULT_MO 0
 
@@ -1221,14 +1222,8 @@ struct PPCVirtualHypervisorClass {
 };
 
 #define TYPE_PPC_VIRTUAL_HYPERVISOR "ppc-virtual-hypervisor"
-#define PPC_VIRTUAL_HYPERVISOR(obj)                 \
-    OBJECT_CHECK(PPCVirtualHypervisor, (obj), TYPE_PPC_VIRTUAL_HYPERVISOR)
-#define PPC_VIRTUAL_HYPERVISOR_CLASS(klass)         \
-    OBJECT_CLASS_CHECK(PPCVirtualHypervisorClass, (klass), \
-                       TYPE_PPC_VIRTUAL_HYPERVISOR)
-#define PPC_VIRTUAL_HYPERVISOR_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(PPCVirtualHypervisorClass, (obj), \
-                     TYPE_PPC_VIRTUAL_HYPERVISOR)
+DECLARE_OBJ_CHECKERS(PPCVirtualHypervisor, PPCVirtualHypervisorClass,
+                     PPC_VIRTUAL_HYPERVISOR, TYPE_PPC_VIRTUAL_HYPERVISOR)
 #endif /* CONFIG_USER_ONLY */
 
 void ppc_cpu_do_interrupt(CPUState *cpu);
diff --git a/target/ppc/trace-events b/target/ppc/trace-events
index 6d15aa90b4..bc0d4e6f8b 100644
--- a/target/ppc/trace-events
+++ b/target/ppc/trace-events
@@ -20,7 +20,6 @@ kvm_failed_dtl_set(const char *msg) "Unable to set dispatch trace log state to K
 kvm_failed_null_vpa_addr_set(const char *msg) "Unable to set VPA address to KVM: %s"
 kvm_failed_put_vpa(void) "Warning: Unable to set VPA information to KVM"
 kvm_failed_get_vpa(void) "Warning: Unable to get VPA information from KVM"
-kvm_injected_interrupt(int irq) "injected interrupt %d"
 kvm_handle_dcr_write(void) "handle dcr write"
 kvm_handle_dcr_read(void) "handle dcr read"
 kvm_handle_halt(void) "handle halt"
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 65daa73675..4c00d35ccd 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -24,6 +24,7 @@
 #include "hw/registerfields.h"
 #include "exec/cpu-defs.h"
 #include "fpu/softfloat-types.h"
+#include "qom/object.h"
 
 #define TCG_GUEST_DEFAULT_MO 0
 
@@ -232,12 +233,8 @@ struct CPURISCVState {
     QEMUTimer *timer; /* Internal timer */
 };
 
-#define RISCV_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(RISCVCPUClass, (klass), TYPE_RISCV_CPU)
-#define RISCV_CPU(obj) \
-    OBJECT_CHECK(RISCVCPU, (obj), TYPE_RISCV_CPU)
-#define RISCV_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(RISCVCPUClass, (obj), TYPE_RISCV_CPU)
+OBJECT_DECLARE_TYPE(RISCVCPU, RISCVCPUClass,
+                    riscv_cpu, RISCV_CPU)
 
 /**
  * RISCVCPUClass:
@@ -246,13 +243,13 @@ struct CPURISCVState {
  *
  * A RISCV CPU model.
  */
-typedef struct RISCVCPUClass {
+struct RISCVCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} RISCVCPUClass;
+};
 
 /**
  * RISCVCPU:
@@ -260,7 +257,7 @@ typedef struct RISCVCPUClass {
  *
  * A RISCV CPU.
  */
-typedef struct RISCVCPU {
+struct RISCVCPU {
     /*< private >*/
     CPUState parent_obj;
     /*< public >*/
@@ -294,7 +291,7 @@ typedef struct RISCVCPU {
         bool pmp;
         uint64_t resetvec;
     } cfg;
-} RISCVCPU;
+};
 
 static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
 {
diff --git a/target/riscv/trace-events b/target/riscv/trace-events
index 4b6c652ae9..b7e371ee97 100644
--- a/target/riscv/trace-events
+++ b/target/riscv/trace-events
@@ -1,4 +1,4 @@
-# target/riscv/cpu_helper.c
+# cpu_helper.c
 riscv_trap(uint64_t hartid, bool async, uint64_t cause, uint64_t epc, uint64_t tval, const char *desc) "hart:%"PRId64", async:%d, cause:%"PRId64", epc:0x%"PRIx64", tval:0x%"PRIx64", desc=%s"
 
 # pmp.c
diff --git a/target/rx/cpu-qom.h b/target/rx/cpu-qom.h
index 9054762326..6c5321078d 100644
--- a/target/rx/cpu-qom.h
+++ b/target/rx/cpu-qom.h
@@ -20,18 +20,14 @@
 #define RX_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_RX_CPU "rx-cpu"
 
 #define TYPE_RX62N_CPU RX_CPU_TYPE_NAME("rx62n")
 
-typedef struct RXCPU RXCPU;
-#define RX_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(RXCPUClass, (klass), TYPE_RX_CPU)
-#define RX_CPU(obj) \
-    OBJECT_CHECK(RXCPU, (obj), TYPE_RX_CPU)
-#define RX_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(RXCPUClass, (obj), TYPE_RX_CPU)
+OBJECT_DECLARE_TYPE(RXCPU, RXCPUClass,
+                    rx_cpu, RX_CPU)
 
 /*
  * RXCPUClass:
@@ -40,14 +36,14 @@ typedef struct RXCPU RXCPU;
  *
  * A RX CPU model.
  */
-typedef struct RXCPUClass {
+struct RXCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} RXCPUClass;
+};
 
 #define CPUArchState struct CPURXState
 
diff --git a/target/s390x/cpu-qom.h b/target/s390x/cpu-qom.h
index 1630818c28..e2b2513711 100644
--- a/target/s390x/cpu-qom.h
+++ b/target/s390x/cpu-qom.h
@@ -21,15 +21,12 @@
 #define QEMU_S390_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_S390_CPU "s390x-cpu"
 
-#define S390_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(S390CPUClass, (klass), TYPE_S390_CPU)
-#define S390_CPU(obj) \
-    OBJECT_CHECK(S390CPU, (obj), TYPE_S390_CPU)
-#define S390_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(S390CPUClass, (obj), TYPE_S390_CPU)
+OBJECT_DECLARE_TYPE(S390CPU, S390CPUClass,
+                    s390_cpu, S390_CPU)
 
 typedef struct S390CPUModel S390CPUModel;
 typedef struct S390CPUDef S390CPUDef;
@@ -50,7 +47,7 @@ typedef enum cpu_reset_type {
  *
  * An S/390 CPU model.
  */
-typedef struct S390CPUClass {
+struct S390CPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
@@ -64,9 +61,8 @@ typedef struct S390CPUClass {
     DeviceReset parent_reset;
     void (*load_normal)(CPUState *cpu);
     void (*reset)(CPUState *cpu, cpu_reset_type type);
-} S390CPUClass;
+};
 
-typedef struct S390CPU S390CPU;
 typedef struct CPUS390XState CPUS390XState;
 
 #endif
diff --git a/target/sh4/cpu-qom.h b/target/sh4/cpu-qom.h
index 72a63f3fd3..595814b8cb 100644
--- a/target/sh4/cpu-qom.h
+++ b/target/sh4/cpu-qom.h
@@ -21,6 +21,7 @@
 #define QEMU_SUPERH_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_SUPERH_CPU "superh-cpu"
 
@@ -28,12 +29,8 @@
 #define TYPE_SH7751R_CPU SUPERH_CPU_TYPE_NAME("sh7751r")
 #define TYPE_SH7785_CPU  SUPERH_CPU_TYPE_NAME("sh7785")
 
-#define SUPERH_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(SuperHCPUClass, (klass), TYPE_SUPERH_CPU)
-#define SUPERH_CPU(obj) \
-    OBJECT_CHECK(SuperHCPU, (obj), TYPE_SUPERH_CPU)
-#define SUPERH_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(SuperHCPUClass, (obj), TYPE_SUPERH_CPU)
+OBJECT_DECLARE_TYPE(SuperHCPU, SuperHCPUClass,
+                    superh_cpu, SUPERH_CPU)
 
 /**
  * SuperHCPUClass:
@@ -45,7 +42,7 @@
  *
  * A SuperH CPU model.
  */
-typedef struct SuperHCPUClass {
+struct SuperHCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
@@ -56,8 +53,7 @@ typedef struct SuperHCPUClass {
     uint32_t pvr;
     uint32_t prr;
     uint32_t cvr;
-} SuperHCPUClass;
+};
 
-typedef struct SuperHCPU SuperHCPU;
 
 #endif
diff --git a/target/sparc/cpu-qom.h b/target/sparc/cpu-qom.h
index 8b4d33c21e..5d7fb727bc 100644
--- a/target/sparc/cpu-qom.h
+++ b/target/sparc/cpu-qom.h
@@ -21,6 +21,7 @@
 #define QEMU_SPARC_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #ifdef TARGET_SPARC64
 #define TYPE_SPARC_CPU "sparc64-cpu"
@@ -28,12 +29,8 @@
 #define TYPE_SPARC_CPU "sparc-cpu"
 #endif
 
-#define SPARC_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(SPARCCPUClass, (klass), TYPE_SPARC_CPU)
-#define SPARC_CPU(obj) \
-    OBJECT_CHECK(SPARCCPU, (obj), TYPE_SPARC_CPU)
-#define SPARC_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(SPARCCPUClass, (obj), TYPE_SPARC_CPU)
+OBJECT_DECLARE_TYPE(SPARCCPU, SPARCCPUClass,
+                    sparc_cpu, SPARC_CPU)
 
 typedef struct sparc_def_t sparc_def_t;
 /**
@@ -43,7 +40,7 @@ typedef struct sparc_def_t sparc_def_t;
  *
  * A SPARC CPU model.
  */
-typedef struct SPARCCPUClass {
+struct SPARCCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
@@ -51,8 +48,7 @@ typedef struct SPARCCPUClass {
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
     sparc_def_t *cpu_def;
-} SPARCCPUClass;
+};
 
-typedef struct SPARCCPU SPARCCPU;
 
 #endif
diff --git a/target/tilegx/cpu.h b/target/tilegx/cpu.h
index 193b6bbccb..d251ff80b8 100644
--- a/target/tilegx/cpu.h
+++ b/target/tilegx/cpu.h
@@ -21,6 +21,7 @@
 #define TILEGX_CPU_H
 
 #include "exec/cpu-defs.h"
+#include "qom/object.h"
 
 /* TILE-Gx common register alias */
 #define TILEGX_R_RE    0   /*  0 register, for function/syscall return value */
@@ -98,12 +99,8 @@ typedef struct CPUTLGState {
 
 #define TYPE_TILEGX_CPU "tilegx-cpu"
 
-#define TILEGX_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(TileGXCPUClass, (klass), TYPE_TILEGX_CPU)
-#define TILEGX_CPU(obj) \
-    OBJECT_CHECK(TileGXCPU, (obj), TYPE_TILEGX_CPU)
-#define TILEGX_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(TileGXCPUClass, (obj), TYPE_TILEGX_CPU)
+OBJECT_DECLARE_TYPE(TileGXCPU, TileGXCPUClass,
+                    tilegx_cpu, TILEGX_CPU)
 
 /**
  * TileGXCPUClass:
@@ -112,14 +109,14 @@ typedef struct CPUTLGState {
  *
  * A Tile-Gx CPU model.
  */
-typedef struct TileGXCPUClass {
+struct TileGXCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} TileGXCPUClass;
+};
 
 /**
  * TileGXCPU:
@@ -127,14 +124,14 @@ typedef struct TileGXCPUClass {
  *
  * A Tile-GX CPU.
  */
-typedef struct TileGXCPU {
+struct TileGXCPU {
     /*< private >*/
     CPUState parent_obj;
     /*< public >*/
 
     CPUNegativeOffsetState neg;
     CPUTLGState env;
-} TileGXCPU;
+};
 
 
 /* TILE-Gx memory attributes */
diff --git a/target/tricore/cpu-qom.h b/target/tricore/cpu-qom.h
index cd819e6f24..9e588c4c34 100644
--- a/target/tricore/cpu-qom.h
+++ b/target/tricore/cpu-qom.h
@@ -19,26 +19,22 @@
 #define QEMU_TRICORE_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 
 #define TYPE_TRICORE_CPU "tricore-cpu"
 
-#define TRICORE_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(TriCoreCPUClass, (klass), TYPE_TRICORE_CPU)
-#define TRICORE_CPU(obj) \
-    OBJECT_CHECK(TriCoreCPU, (obj), TYPE_TRICORE_CPU)
-#define TRICORE_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(TriCoreCPUClass, (obj), TYPE_TRICORE_CPU)
+OBJECT_DECLARE_TYPE(TriCoreCPU, TriCoreCPUClass,
+                    tricore_cpu, TRICORE_CPU)
 
-typedef struct TriCoreCPUClass {
+struct TriCoreCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
     DeviceReset parent_reset;
-} TriCoreCPUClass;
+};
 
-typedef struct TriCoreCPU TriCoreCPU;
 
 #endif /* QEMU_TRICORE_CPU_QOM_H */
diff --git a/target/unicore32/cpu-qom.h b/target/unicore32/cpu-qom.h
index 7dd04515cb..c914273058 100644
--- a/target/unicore32/cpu-qom.h
+++ b/target/unicore32/cpu-qom.h
@@ -12,15 +12,12 @@
 #define QEMU_UC32_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_UNICORE32_CPU "unicore32-cpu"
 
-#define UNICORE32_CPU_CLASS(klass) \
-    OBJECT_CLASS_CHECK(UniCore32CPUClass, (klass), TYPE_UNICORE32_CPU)
-#define UNICORE32_CPU(obj) \
-    OBJECT_CHECK(UniCore32CPU, (obj), TYPE_UNICORE32_CPU)
-#define UNICORE32_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(UniCore32CPUClass, (obj), TYPE_UNICORE32_CPU)
+OBJECT_DECLARE_TYPE(UniCore32CPU, UniCore32CPUClass,
+                    unicore32_cpu, UNICORE32_CPU)
 
 /**
  * UniCore32CPUClass:
@@ -28,14 +25,13 @@
  *
  * A UniCore32 CPU model.
  */
-typedef struct UniCore32CPUClass {
+struct UniCore32CPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
 
     DeviceRealize parent_realize;
-} UniCore32CPUClass;
+};
 
-typedef struct UniCore32CPU UniCore32CPU;
 
 #endif
diff --git a/target/xtensa/cpu-qom.h b/target/xtensa/cpu-qom.h
index 3ea93ce1f9..299ce3e63c 100644
--- a/target/xtensa/cpu-qom.h
+++ b/target/xtensa/cpu-qom.h
@@ -30,15 +30,12 @@
 #define QEMU_XTENSA_CPU_QOM_H
 
 #include "hw/core/cpu.h"
+#include "qom/object.h"
 
 #define TYPE_XTENSA_CPU "xtensa-cpu"
 
-#define XTENSA_CPU_CLASS(class) \
-    OBJECT_CLASS_CHECK(XtensaCPUClass, (class), TYPE_XTENSA_CPU)
-#define XTENSA_CPU(obj) \
-    OBJECT_CHECK(XtensaCPU, (obj), TYPE_XTENSA_CPU)
-#define XTENSA_CPU_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(XtensaCPUClass, (obj), TYPE_XTENSA_CPU)
+OBJECT_DECLARE_TYPE(XtensaCPU, XtensaCPUClass,
+                    xtensa_cpu, XTENSA_CPU)
 
 typedef struct XtensaConfig XtensaConfig;
 
@@ -50,7 +47,7 @@ typedef struct XtensaConfig XtensaConfig;
  *
  * An Xtensa CPU model.
  */
-typedef struct XtensaCPUClass {
+struct XtensaCPUClass {
     /*< private >*/
     CPUClass parent_class;
     /*< public >*/
@@ -59,8 +56,7 @@ typedef struct XtensaCPUClass {
     DeviceReset parent_reset;
 
     const XtensaConfig *config;
-} XtensaCPUClass;
+};
 
-typedef struct XtensaCPU XtensaCPU;
 
 #endif
diff --git a/tests/Makefile.include b/tests/Makefile.include
index f93e611220..40d909badc 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -50,7 +50,7 @@ RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TARGET_DIRS))
 $(foreach PROBE_TARGET,$(TARGET_DIRS), 				\
 	$(eval -include $(SRC_PATH)/tests/tcg/Makefile.prereqs))
 
-build-tcg-tests-%: $(if $(CONFIG_PLUGIN),plugins)
+build-tcg-tests-%: $(if $(CONFIG_PLUGIN),test-plugins)
 	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) \
 		-f $(SRC_PATH)/tests/tcg/Makefile.qemu \
 		SRC_PATH=$(SRC_PATH) \
@@ -127,7 +127,7 @@ check-acceptance: check-venv $(TESTS_RESULTS_DIR) get-vm-images
             --show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \
             --filter-by-tags-include-empty --filter-by-tags-include-empty-key \
             $(AVOCADO_TAGS) \
-            $(if $(GITLAB_CI),,--failfast=on) tests/acceptance, \
+            $(if $(GITLAB_CI),,--failfast) tests/acceptance, \
             "AVOCADO", "tests/acceptance")
 
 # Consolidated targets
diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py
index db9c0f5d79..4cda037187 100644
--- a/tests/acceptance/avocado_qemu/__init__.py
+++ b/tests/acceptance/avocado_qemu/__init__.py
@@ -192,3 +192,15 @@ class Test(avocado.Test):
     def tearDown(self):
         for vm in self._vms.values():
             vm.shutdown()
+
+    def fetch_asset(self, name,
+                    asset_hash=None, algorithm=None,
+                    locations=None, expire=None,
+                    find_only=False, cancel_on_missing=True):
+        return super(Test, self).fetch_asset(name,
+                        asset_hash=asset_hash,
+                        algorithm=algorithm,
+                        locations=locations,
+                        expire=expire,
+                        find_only=find_only,
+                        cancel_on_missing=cancel_on_missing)
diff --git a/tests/benchmark-crypto-cipher.c b/tests/benchmark-crypto-cipher.c
index 1936aa4ae0..c04f0a0fba 100644
--- a/tests/benchmark-crypto-cipher.c
+++ b/tests/benchmark-crypto-cipher.c
@@ -70,8 +70,10 @@ static void test_cipher_speed(size_t chunk_size,
     }
     g_test_timer_elapsed();
 
-    g_test_message("Enc chunk %zu bytes ", chunk_size);
-    g_test_message("%.2f MB/sec ", (double)total / MiB / g_test_timer_last());
+    g_test_message("enc(%s-%s) chunk %zu bytes %.2f MB/sec ",
+                   QCryptoCipherAlgorithm_str(alg),
+                   QCryptoCipherMode_str(mode),
+                   chunk_size, (double)total / MiB / g_test_timer_last());
 
     g_test_timer_start();
     remain = total;
@@ -85,8 +87,10 @@ static void test_cipher_speed(size_t chunk_size,
     }
     g_test_timer_elapsed();
 
-    g_test_message("Dec chunk %zu bytes ", chunk_size);
-    g_test_message("%.2f MB/sec ", (double)total / MiB / g_test_timer_last());
+    g_test_message("dec(%s-%s) chunk %zu bytes %.2f MB/sec ",
+                   QCryptoCipherAlgorithm_str(alg),
+                   QCryptoCipherMode_str(mode),
+                   chunk_size, (double)total / MiB / g_test_timer_last());
 
     qcrypto_cipher_free(cipher);
     g_free(plaintext);
diff --git a/tests/benchmark-crypto-hash.c b/tests/benchmark-crypto-hash.c
index 598111e75a..927b00bb4d 100644
--- a/tests/benchmark-crypto-hash.c
+++ b/tests/benchmark-crypto-hash.c
@@ -48,7 +48,9 @@ static void test_hash_speed(const void *opaque)
     }
     g_test_timer_elapsed();
 
-    g_test_message("%.2f MB/sec ", (double)total / MiB / g_test_timer_last());
+    g_test_message("hash(%s): chunk %zu bytes %.2f MB/sec",
+                   QCryptoHashAlgorithm_str(opts->alg),
+                   opts->chunk_size, total / g_test_timer_last());
 
     g_free(out);
     g_free(in);
diff --git a/tests/benchmark-crypto-hmac.c b/tests/benchmark-crypto-hmac.c
index f9fa22df95..5cca636789 100644
--- a/tests/benchmark-crypto-hmac.c
+++ b/tests/benchmark-crypto-hmac.c
@@ -55,10 +55,9 @@ static void test_hmac_speed(const void *opaque)
     } while (g_test_timer_elapsed() < 5.0);
 
     total /= MiB;
-    g_test_message("hmac(sha256): ");
-    g_test_message("Testing chunk_size %zu bytes ", chunk_size);
-    g_test_message("done: %.2f MB in %.2f secs: ", total, g_test_timer_last());
-    g_test_message("%.2f MB/sec\n", total / g_test_timer_last());
+    g_test_message("hmac(%s): chunk %zu bytes %.2f MB/sec",
+                   QCryptoHashAlgorithm_str(QCRYPTO_HASH_ALG_SHA256),
+                   chunk_size, total / g_test_timer_last());
 
     g_free(out);
     g_free(in);
diff --git a/tests/check-qom-interface.c b/tests/check-qom-interface.c
index 2177f0dce5..c99be97ed8 100644
--- a/tests/check-qom-interface.c
+++ b/tests/check-qom-interface.c
@@ -16,20 +16,19 @@
 
 
 #define TYPE_TEST_IF "test-interface"
-#define TEST_IF_CLASS(klass) \
-     OBJECT_CLASS_CHECK(TestIfClass, (klass), TYPE_TEST_IF)
-#define TEST_IF_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(TestIfClass, (obj), TYPE_TEST_IF)
+typedef struct TestIfClass TestIfClass;
+DECLARE_CLASS_CHECKERS(TestIfClass, TEST_IF,
+                       TYPE_TEST_IF)
 #define TEST_IF(obj) \
      INTERFACE_CHECK(TestIf, (obj), TYPE_TEST_IF)
 
 typedef struct TestIf TestIf;
 
-typedef struct TestIfClass {
+struct TestIfClass {
     InterfaceClass parent_class;
 
     uint32_t test;
-} TestIfClass;
+};
 
 static const TypeInfo test_if_info = {
     .name          = TYPE_TEST_IF,
diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
index e1e0a96661..1571606c1c 100644
--- a/tests/check-qom-proplist.c
+++ b/tests/check-qom-proplist.c
@@ -33,8 +33,8 @@
 typedef struct DummyObject DummyObject;
 typedef struct DummyObjectClass DummyObjectClass;
 
-#define DUMMY_OBJECT(obj)                               \
-    OBJECT_CHECK(DummyObject, (obj), TYPE_DUMMY)
+DECLARE_INSTANCE_CHECKER(DummyObject, DUMMY_OBJECT,
+                         TYPE_DUMMY)
 
 typedef enum DummyAnimal DummyAnimal;
 
@@ -196,12 +196,12 @@ typedef struct DummyBackendClass DummyBackendClass;
 #define TYPE_DUMMY_BUS "qemu-dummy-bus"
 #define TYPE_DUMMY_BACKEND "qemu-dummy-backend"
 
-#define DUMMY_DEV(obj)                               \
-    OBJECT_CHECK(DummyDev, (obj), TYPE_DUMMY_DEV)
-#define DUMMY_BUS(obj)                               \
-    OBJECT_CHECK(DummyBus, (obj), TYPE_DUMMY_BUS)
-#define DUMMY_BACKEND(obj)                               \
-    OBJECT_CHECK(DummyBackend, (obj), TYPE_DUMMY_BACKEND)
+DECLARE_INSTANCE_CHECKER(DummyDev, DUMMY_DEV,
+                         TYPE_DUMMY_DEV)
+DECLARE_INSTANCE_CHECKER(DummyBus, DUMMY_BUS,
+                         TYPE_DUMMY_BUS)
+DECLARE_INSTANCE_CHECKER(DummyBackend, DUMMY_BACKEND,
+                         TYPE_DUMMY_BACKEND)
 
 struct DummyDev {
     Object parent_obj;
diff --git a/tests/meson.build b/tests/meson.build
index 998e4c48f9..dae8a77df1 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -259,8 +259,9 @@ test('decodetree', sh,
      workdir: meson.current_source_dir() / 'decode',
      suite: 'decodetree')
 
+subdir('fp')
+
 if 'CONFIG_TCG' in config_host
-  subdir('fp')
   if 'CONFIG_PLUGIN' in config_host
     subdir('plugin')
   endif
diff --git a/tests/plugin/meson.build b/tests/plugin/meson.build
index dbbdcbaa67..1eacfa6e35 100644
--- a/tests/plugin/meson.build
+++ b/tests/plugin/meson.build
@@ -1,7 +1,7 @@
 t = []
-foreach i : ['bb', 'empty', 'insn', 'mem', 'hotblocks', 'howvec', 'hotpages', 'lockstep']
+foreach i : ['bb', 'empty', 'insn', 'mem']
   t += shared_module(i, files(i + '.c'),
                      include_directories: '../../include/qemu',
                      dependencies: glib)
 endforeach
-alias_target('plugins', t)
+alias_target('test-plugins', t)
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
index a0782937b0..596505be2d 100755
--- a/tests/qemu-iotests/020
+++ b/tests/qemu-iotests/020
@@ -31,6 +31,11 @@ _cleanup()
     _cleanup_test_img
     _rm_test_img "$TEST_IMG.base"
     _rm_test_img "$TEST_IMG.orig"
+
+    _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.base"
+    _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.mid"
+    _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT"
+    rmdir "$TEST_DIR/subdir" &> /dev/null
 }
 trap "_cleanup; exit \$status" 0 1 2 3 15
 
@@ -139,6 +144,45 @@ $QEMU_IO -c 'writev 0 64k' "$TEST_IMG" | _filter_qemu_io
 $QEMU_IMG commit "$TEST_IMG"
 _cleanup
 
+
+echo
+echo 'Testing commit in sub-directory with relative filenames'
+echo
+
+pushd "$TEST_DIR" > /dev/null
+
+mkdir subdir
+
+TEST_IMG="subdir/t.$IMGFMT.base" _make_test_img 1M
+TEST_IMG="subdir/t.$IMGFMT.mid" _make_test_img -b "t.$IMGFMT.base" -F $IMGFMT
+TEST_IMG="subdir/t.$IMGFMT" _make_test_img -b "t.$IMGFMT.mid" -F $IMGFMT
+
+# Should work
+$QEMU_IMG commit -b "t.$IMGFMT.mid" "subdir/t.$IMGFMT"
+
+# Might theoretically work, but does not in practice (we have to
+# decide between this and the above; and since we always represent
+# backing file names as relative to the overlay, we go for the above)
+$QEMU_IMG commit -b "subdir/t.$IMGFMT.mid" "subdir/t.$IMGFMT" 2>&1 | \
+    _filter_imgfmt
+
+# This should work as well
+$QEMU_IMG commit -b "$TEST_DIR/subdir/t.$IMGFMT.mid" "subdir/t.$IMGFMT"
+
+popd > /dev/null
+
+# Now let's try with just absolute filenames
+# (This will not work with external data files, though, because when
+# using relative paths for those, qemu will always resolve them
+# relative to its CWD.  Therefore, it cannot find those data files now
+# that we left $TEST_DIR.)
+if _get_data_file '' > /dev/null; then
+    echo 'Image committed.' # Skip test
+else
+    $QEMU_IMG commit -b "$TEST_DIR/subdir/t.$IMGFMT.mid" \
+        "$TEST_DIR/subdir/t.$IMGFMT"
+fi
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/020.out b/tests/qemu-iotests/020.out
index 5936bc1cae..a5db1962ad 100644
--- a/tests/qemu-iotests/020.out
+++ b/tests/qemu-iotests/020.out
@@ -1083,4 +1083,14 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=json:{'driv
 wrote 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-img: Block job failed: No space left on device
+
+Testing commit in sub-directory with relative filenames
+
+Formatting 'subdir/t.IMGFMT.base', fmt=IMGFMT size=1048576
+Formatting 'subdir/t.IMGFMT.mid', fmt=IMGFMT size=1048576 backing_file=t.IMGFMT.base backing_fmt=IMGFMT
+Formatting 'subdir/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=t.IMGFMT.mid backing_fmt=IMGFMT
+Image committed.
+qemu-img: Did not find 'subdir/t.IMGFMT.mid' in the backing chain of 'subdir/t.IMGFMT'
+Image committed.
+Image committed.
 *** done
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
index f58f50d023..caf286571a 100755
--- a/tests/qemu-iotests/040
+++ b/tests/qemu-iotests/040
@@ -734,6 +734,244 @@ class TestErrorHandling(iotests.QMPTestCase):
         self.assertTrue(iotests.compare_images(mid_img, backing_img, fmt2='raw'),
                         'target image does not match source after commit')
 
+class TestCommitWithFilters(iotests.QMPTestCase):
+    img0 = os.path.join(iotests.test_dir, '0.img')
+    img1 = os.path.join(iotests.test_dir, '1.img')
+    img2 = os.path.join(iotests.test_dir, '2.img')
+    img3 = os.path.join(iotests.test_dir, '3.img')
+
+    def do_test_io(self, read_or_write):
+        for index, pattern_file in enumerate(self.pattern_files):
+            result = qemu_io('-f', iotests.imgfmt,
+                             '-c',
+                             f'{read_or_write} -P {index + 1} {index}M 1M',
+                             pattern_file)
+            self.assertFalse('Pattern verification failed' in result)
+
+    def setUp(self):
+        qemu_img('create', '-f', iotests.imgfmt, self.img0, '64M')
+        qemu_img('create', '-f', iotests.imgfmt, self.img1, '64M')
+        qemu_img('create', '-f', iotests.imgfmt, self.img2, '64M')
+        qemu_img('create', '-f', iotests.imgfmt, self.img3, '64M')
+
+        # Distributions of the patterns in the files; this is checked
+        # by tearDown() and should be changed by the test cases as is
+        # necessary
+        self.pattern_files = [self.img0, self.img1, self.img2, self.img3]
+
+        self.do_test_io('write')
+
+        self.vm = iotests.VM().add_device('virtio-scsi,id=vio-scsi')
+        self.vm.launch()
+
+        result = self.vm.qmp('object-add', qom_type='throttle-group', id='tg')
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('blockdev-add', **{
+                'node-name': 'top-filter',
+                'driver': 'throttle',
+                'throttle-group': 'tg',
+                'file': {
+                    'node-name': 'cow-3',
+                    'driver': iotests.imgfmt,
+                    'file': {
+                        'driver': 'file',
+                        'filename': self.img3
+                    },
+                    'backing': {
+                        'node-name': 'cow-2',
+                        'driver': iotests.imgfmt,
+                        'file': {
+                            'driver': 'file',
+                            'filename': self.img2
+                        },
+                        'backing': {
+                            'node-name': 'cow-1',
+                            'driver': iotests.imgfmt,
+                            'file': {
+                                'driver': 'file',
+                                'filename': self.img1
+                            },
+                            'backing': {
+                                'node-name': 'bottom-filter',
+                                'driver': 'throttle',
+                                'throttle-group': 'tg',
+                                'file': {
+                                    'node-name': 'cow-0',
+                                    'driver': iotests.imgfmt,
+                                    'file': {
+                                        'driver': 'file',
+                                        'filename': self.img0
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            })
+        self.assert_qmp(result, 'return', {})
+
+    def tearDown(self):
+        self.vm.shutdown()
+        self.do_test_io('read')
+
+        os.remove(self.img3)
+        os.remove(self.img2)
+        os.remove(self.img1)
+        os.remove(self.img0)
+
+    # Filters make for funny filenames, so we cannot just use
+    # self.imgX to get them
+    def get_filename(self, node):
+        return self.vm.node_info(node)['image']['filename']
+
+    def test_filterless_commit(self):
+        result = self.vm.qmp('block-commit',
+                             job_id='commit',
+                             device='top-filter',
+                             top_node='cow-2',
+                             base_node='cow-1')
+        self.assert_qmp(result, 'return', {})
+        self.wait_until_completed(drive='commit')
+
+        self.assertIsNotNone(self.vm.node_info('cow-3'))
+        self.assertIsNone(self.vm.node_info('cow-2'))
+        self.assertIsNotNone(self.vm.node_info('cow-1'))
+
+        # 2 has been comitted into 1
+        self.pattern_files[2] = self.img1
+
+    def test_commit_through_filter(self):
+        result = self.vm.qmp('block-commit',
+                             job_id='commit',
+                             device='top-filter',
+                             top_node='cow-1',
+                             base_node='cow-0')
+        self.assert_qmp(result, 'return', {})
+        self.wait_until_completed(drive='commit')
+
+        self.assertIsNotNone(self.vm.node_info('cow-2'))
+        self.assertIsNone(self.vm.node_info('cow-1'))
+        self.assertIsNone(self.vm.node_info('bottom-filter'))
+        self.assertIsNotNone(self.vm.node_info('cow-0'))
+
+        # 1 has been comitted into 0
+        self.pattern_files[1] = self.img0
+
+    def test_filtered_active_commit_with_filter(self):
+        # Add a device, so the commit job finds a parent it can change
+        # to point to the base node (so we can test that top-filter is
+        # dropped from the graph)
+        result = self.vm.qmp('device_add', id='drv0', driver='scsi-hd',
+                             bus='vio-scsi.0', drive='top-filter')
+        self.assert_qmp(result, 'return', {})
+
+        # Try to release our reference to top-filter; that should not
+        # work because drv0 uses it
+        result = self.vm.qmp('blockdev-del', node_name='top-filter')
+        self.assert_qmp(result, 'error/class', 'GenericError')
+        self.assert_qmp(result, 'error/desc', 'Node top-filter is in use')
+
+        result = self.vm.qmp('block-commit',
+                             job_id='commit',
+                             device='top-filter',
+                             base_node='cow-2')
+        self.assert_qmp(result, 'return', {})
+        self.complete_and_wait(drive='commit')
+
+        # Try to release our reference to top-filter again
+        result = self.vm.qmp('blockdev-del', node_name='top-filter')
+        self.assert_qmp(result, 'return', {})
+
+        self.assertIsNone(self.vm.node_info('top-filter'))
+        self.assertIsNone(self.vm.node_info('cow-3'))
+        self.assertIsNotNone(self.vm.node_info('cow-2'))
+
+        # Check that drv0 is now connected to cow-2
+        blockdevs = self.vm.qmp('query-block')['return']
+        drv0 = next(dev for dev in blockdevs if dev['qdev'] == 'drv0')
+        self.assertEqual(drv0['inserted']['node-name'], 'cow-2')
+
+        # 3 has been comitted into 2
+        self.pattern_files[3] = self.img2
+
+    def test_filtered_active_commit_without_filter(self):
+        result = self.vm.qmp('block-commit',
+                             job_id='commit',
+                             device='top-filter',
+                             top_node='cow-3',
+                             base_node='cow-2')
+        self.assert_qmp(result, 'return', {})
+        self.complete_and_wait(drive='commit')
+
+        self.assertIsNotNone(self.vm.node_info('top-filter'))
+        self.assertIsNone(self.vm.node_info('cow-3'))
+        self.assertIsNotNone(self.vm.node_info('cow-2'))
+
+        # 3 has been comitted into 2
+        self.pattern_files[3] = self.img2
+
+class TestCommitWithOverriddenBacking(iotests.QMPTestCase):
+    img_base_a = os.path.join(iotests.test_dir, 'base_a.img')
+    img_base_b = os.path.join(iotests.test_dir, 'base_b.img')
+    img_top = os.path.join(iotests.test_dir, 'top.img')
+
+    def setUp(self):
+        qemu_img('create', '-f', iotests.imgfmt, self.img_base_a, '1M')
+        qemu_img('create', '-f', iotests.imgfmt, self.img_base_b, '1M')
+        qemu_img('create', '-f', iotests.imgfmt, '-b', self.img_base_a, \
+                 self.img_top)
+
+        self.vm = iotests.VM()
+        self.vm.launch()
+
+        # Use base_b instead of base_a as the backing of top
+        result = self.vm.qmp('blockdev-add', **{
+                                'node-name': 'top',
+                                'driver': iotests.imgfmt,
+                                'file': {
+                                    'driver': 'file',
+                                    'filename': self.img_top
+                                },
+                                'backing': {
+                                    'node-name': 'base',
+                                    'driver': iotests.imgfmt,
+                                    'file': {
+                                        'driver': 'file',
+                                        'filename': self.img_base_b
+                                    }
+                                }
+                            })
+        self.assert_qmp(result, 'return', {})
+
+    def tearDown(self):
+        self.vm.shutdown()
+        os.remove(self.img_top)
+        os.remove(self.img_base_a)
+        os.remove(self.img_base_b)
+
+    def test_commit_to_a(self):
+        # Try committing to base_a (which should fail, as top's
+        # backing image is base_b instead)
+        result = self.vm.qmp('block-commit',
+                             job_id='commit',
+                             device='top',
+                             base=self.img_base_a)
+        self.assert_qmp(result, 'error/class', 'GenericError')
+
+    def test_commit_to_b(self):
+        # Try committing to base_b (which should work, since that is
+        # actually top's backing image)
+        result = self.vm.qmp('block-commit',
+                             job_id='commit',
+                             device='top',
+                             base=self.img_base_b)
+        self.assert_qmp(result, 'return', {})
+
+        self.vm.event_wait('BLOCK_JOB_READY')
+        self.vm.qmp('block-job-complete', device='commit')
+        self.vm.event_wait('BLOCK_JOB_COMPLETED')
+
 if __name__ == '__main__':
     iotests.main(supported_fmts=['qcow2', 'qed'],
                  supported_protocols=['file'])
diff --git a/tests/qemu-iotests/040.out b/tests/qemu-iotests/040.out
index 6a917130b6..1bb1dc5f0e 100644
--- a/tests/qemu-iotests/040.out
+++ b/tests/qemu-iotests/040.out
@@ -1,5 +1,5 @@
-...........................................................
+.................................................................
 ----------------------------------------------------------------------
-Ran 59 tests
+Ran 65 tests
 
 OK
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index f0a7bf6650..a7780853cd 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -21,8 +21,9 @@
 import time
 import os
 import re
+import json
 import iotests
-from iotests import qemu_img, qemu_io
+from iotests import qemu_img, qemu_img_pipe, qemu_io
 
 backing_img = os.path.join(iotests.test_dir, 'backing.img')
 target_backing_img = os.path.join(iotests.test_dir, 'target-backing.img')
@@ -1288,6 +1289,149 @@ class TestReplaces(iotests.QMPTestCase):
 
         self.vm.assert_block_path('filter0', '/file', 'target')
 
+# Tests for mirror with filters (and how the mirror filter behaves, as
+# an example for an implicit filter)
+class TestFilters(iotests.QMPTestCase):
+    def setUp(self):
+        qemu_img('create', '-f', iotests.imgfmt, backing_img, '1M')
+        qemu_img('create', '-f', iotests.imgfmt, '-b', backing_img, test_img)
+        qemu_img('create', '-f', iotests.imgfmt, '-b', backing_img, target_img)
+
+        qemu_io('-c', 'write -P 1 0 512k', backing_img)
+        qemu_io('-c', 'write -P 2 512k 512k', test_img)
+
+        self.vm = iotests.VM().add_device('virtio-scsi,id=vio-scsi')
+        self.vm.launch()
+
+        result = self.vm.qmp('blockdev-add', **{
+                                'node-name': 'target',
+                                'driver': iotests.imgfmt,
+                                'file': {
+                                    'driver': 'file',
+                                    'filename': target_img
+                                },
+                                'backing': None
+                            })
+        self.assert_qmp(result, 'return', {})
+
+        self.filterless_chain = {
+                'node-name': 'source',
+                'driver': iotests.imgfmt,
+                'file': {
+                    'driver': 'file',
+                    'filename': test_img
+                },
+                'backing': {
+                    'node-name': 'backing',
+                    'driver': iotests.imgfmt,
+                    'file': {
+                        'driver': 'file',
+                        'filename': backing_img
+                    }
+                }
+            }
+
+    def tearDown(self):
+        self.vm.shutdown()
+
+        os.remove(test_img)
+        os.remove(target_img)
+        os.remove(backing_img)
+
+    def test_cor(self):
+        result = self.vm.qmp('blockdev-add', **{
+                                'node-name': 'filter',
+                                'driver': 'copy-on-read',
+                                'file': self.filterless_chain
+                            })
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('blockdev-mirror',
+                             job_id='mirror',
+                             device='filter',
+                             target='target',
+                             sync='top')
+        self.assert_qmp(result, 'return', {})
+
+        self.complete_and_wait('mirror')
+
+        self.vm.qmp('blockdev-del', node_name='target')
+
+        target_map = qemu_img_pipe('map', '--output=json', target_img)
+        target_map = json.loads(target_map)
+
+        assert target_map[0]['start'] == 0
+        assert target_map[0]['length'] == 512 * 1024
+        assert target_map[0]['depth'] == 1
+
+        assert target_map[1]['start'] == 512 * 1024
+        assert target_map[1]['length'] == 512 * 1024
+        assert target_map[1]['depth'] == 0
+
+    def test_implicit_mirror_filter(self):
+        result = self.vm.qmp('blockdev-add', **self.filterless_chain)
+        self.assert_qmp(result, 'return', {})
+
+        # We need this so we can query from above the mirror node
+        result = self.vm.qmp('device_add',
+                             driver='scsi-hd',
+                             id='virtio',
+                             bus='vio-scsi.0',
+                             drive='source')
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('blockdev-mirror',
+                             job_id='mirror',
+                             device='source',
+                             target='target',
+                             sync='top')
+        self.assert_qmp(result, 'return', {})
+
+        # The mirror filter is now an implicit node, so it should be
+        # invisible when querying the backing chain
+        blockdevs = self.vm.qmp('query-block')['return']
+        device_info = next(dev for dev in blockdevs if dev['qdev'] == 'virtio')
+
+        assert device_info['inserted']['node-name'] == 'source'
+
+        image_info = device_info['inserted']['image']
+        assert image_info['filename'] == test_img
+        assert image_info['backing-image']['filename'] == backing_img
+
+        self.complete_and_wait('mirror')
+
+    def test_explicit_mirror_filter(self):
+        # Same test as above, but this time we give the mirror filter
+        # a node-name so it will not be invisible
+        result = self.vm.qmp('blockdev-add', **self.filterless_chain)
+        self.assert_qmp(result, 'return', {})
+
+        # We need this so we can query from above the mirror node
+        result = self.vm.qmp('device_add',
+                             driver='scsi-hd',
+                             id='virtio',
+                             bus='vio-scsi.0',
+                             drive='source')
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('blockdev-mirror',
+                             job_id='mirror',
+                             device='source',
+                             target='target',
+                             sync='top',
+                             filter_node_name='mirror-filter')
+        self.assert_qmp(result, 'return', {})
+
+        # With a node-name given to it, the mirror filter should now
+        # be visible
+        blockdevs = self.vm.qmp('query-block')['return']
+        device_info = next(dev for dev in blockdevs if dev['qdev'] == 'virtio')
+
+        assert device_info['inserted']['node-name'] == 'mirror-filter'
+
+        self.complete_and_wait('mirror')
+
+
 if __name__ == '__main__':
     iotests.main(supported_fmts=['qcow2', 'qed'],
                  supported_protocols=['file'],
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
index 53abe11d73..46651953e8 100644
--- a/tests/qemu-iotests/041.out
+++ b/tests/qemu-iotests/041.out
@@ -1,5 +1,5 @@
-........................................................................................................
+...........................................................................................................
 ----------------------------------------------------------------------
-Ran 104 tests
+Ran 107 tests
 
 OK
diff --git a/tests/qemu-iotests/049 b/tests/qemu-iotests/049
index 051a1c79e0..82b1e6c202 100755
--- a/tests/qemu-iotests/049
+++ b/tests/qemu-iotests/049
@@ -119,6 +119,10 @@ test_qemu_img create -f $IMGFMT -o compat=1.1,lazy_refcounts=on "$TEST_IMG" 64M
 test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=off "$TEST_IMG" 64M
 test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=on "$TEST_IMG" 64M
 
+echo "== Expect error when backing file name is empty string =="
+echo
+test_qemu_img create -f $IMGFMT -b '' $TEST_IMG 1M
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
index a7e220830d..b1d8fd9107 100644
--- a/tests/qemu-iotests/049.out
+++ b/tests/qemu-iotests/049.out
@@ -209,4 +209,9 @@ qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M
 Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=on refcount_bits=16
 qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)
 
+== Expect error when backing file name is empty string ==
+
+qemu-img create -f qcow2 -b  TEST_DIR/t.qcow2 1M
+qemu-img: TEST_DIR/t.qcow2: Expected backing file name, got empty string
+
 *** done
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
index 8a79e1ee87..fcaa71aeee 100644
--- a/tests/qemu-iotests/153.out
+++ b/tests/qemu-iotests/153.out
@@ -464,7 +464,7 @@ No conflict:
 image: null-co://
 file format: null-co
 virtual size: 1 GiB (1073741824 bytes)
-disk size: unavailable
+disk size: 0 B
 
 Conflict:
 qemu-img: --force-share/-U conflicts with image options
diff --git a/tests/qemu-iotests/184 b/tests/qemu-iotests/184
index 33dd8d2a4f..eebb53faed 100755
--- a/tests/qemu-iotests/184
+++ b/tests/qemu-iotests/184
@@ -45,8 +45,7 @@ do_run_qemu()
 run_qemu()
 {
     do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp\
-                          | _filter_qemu_io | _filter_generated_node_ids \
-                          | _filter_actual_image_size
+                          | _filter_qemu_io | _filter_generated_node_ids
 }
 
 test_throttle=$($QEMU_IMG --help|grep throttle)
diff --git a/tests/qemu-iotests/184.out b/tests/qemu-iotests/184.out
index 3deb3cfb94..87c73070e3 100644
--- a/tests/qemu-iotests/184.out
+++ b/tests/qemu-iotests/184.out
@@ -27,14 +27,21 @@ Testing:
             "iops_rd": 0,
             "detect_zeroes": "off",
             "image": {
+                "backing-image": {
+                    "virtual-size": 1073741824,
+                    "filename": "null-co://",
+                    "format": "null-co",
+                    "actual-size": 0
+                },
                 "virtual-size": 1073741824,
                 "filename": "json:{\"throttle-group\": \"group0\", \"driver\": \"throttle\", \"file\": {\"driver\": \"null-co\"}}",
-                "format": "throttle"
+                "format": "throttle",
+                "actual-size": 0
             },
             "iops_wr": 0,
             "ro": false,
             "node-name": "throttle0",
-            "backing_file_depth": 0,
+            "backing_file_depth": 1,
             "drv": "throttle",
             "iops": 0,
             "bps_wr": 0,
@@ -56,7 +63,8 @@ Testing:
             "image": {
                 "virtual-size": 1073741824,
                 "filename": "null-co://",
-                "format": "null-co"
+                "format": "null-co",
+                "actual-size": 0
             },
             "iops_wr": 0,
             "ro": false,
diff --git a/tests/qemu-iotests/204.out b/tests/qemu-iotests/204.out
index 457f72df8f..4d903d20ea 100644
--- a/tests/qemu-iotests/204.out
+++ b/tests/qemu-iotests/204.out
@@ -59,5 +59,6 @@ Offset          Length          File
 0x900000        0x2400000       TEST_DIR/t.IMGFMT
 0x3c00000       0x1100000       TEST_DIR/t.IMGFMT
 0x6a00000       0x400000        TEST_DIR/t.IMGFMT
+0x6e00000       0x1200000       TEST_DIR/t.IMGFMT.base
 No errors were found on the image.
 *** done
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
index 60db986d84..266fce6cda 100755
--- a/tests/qemu-iotests/228
+++ b/tests/qemu-iotests/228
@@ -36,7 +36,7 @@ def log_node_info(node):
 
     log('bs->filename: ' + node['image']['filename'],
         filters=[filter_testfiles, filter_imgfmt])
-    log('bs->backing_file: ' + node['backing_file'],
+    log('bs->backing_file: ' + node['image']['full-backing-filename'],
         filters=[filter_testfiles, filter_imgfmt])
 
     if 'backing-image' in node['image']:
@@ -73,8 +73,8 @@ with iotests.FilePath('base.img') as base_img_path, \
                 },
                 filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
 
-    # Filename should be plain, and the backing filename should not
-    # contain the "file:" prefix
+    # Filename should be plain, and the backing node filename should
+    # not contain the "file:" prefix
     log_node_info(vm.node_info('node0'))
 
     vm.qmp_log('blockdev-del', node_name='node0')
diff --git a/tests/qemu-iotests/228.out b/tests/qemu-iotests/228.out
index 4217df24fe..8c82009abe 100644
--- a/tests/qemu-iotests/228.out
+++ b/tests/qemu-iotests/228.out
@@ -4,7 +4,7 @@
 {"return": {}}
 
 bs->filename: TEST_DIR/PID-top.img
-bs->backing_file: TEST_DIR/PID-base.img
+bs->backing_file: file:TEST_DIR/PID-base.img
 bs->backing->bs->filename: TEST_DIR/PID-base.img
 
 {"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
@@ -41,7 +41,7 @@ bs->backing->bs->filename: TEST_DIR/PID-base.img
 {"return": {}}
 
 bs->filename: TEST_DIR/PID-top.img
-bs->backing_file: TEST_DIR/PID-base.img
+bs->backing_file: file:TEST_DIR/PID-base.img
 bs->backing->bs->filename: TEST_DIR/PID-base.img
 
 {"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
@@ -55,7 +55,7 @@ bs->backing->bs->filename: TEST_DIR/PID-base.img
 {"return": {}}
 
 bs->filename: json:{"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
-bs->backing_file: null-co://
+bs->backing_file: TEST_DIR/PID-base.img
 bs->backing->bs->filename: null-co://
 
 {"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
index efe3c0428b..f2b2dddf1c 100755
--- a/tests/qemu-iotests/244
+++ b/tests/qemu-iotests/244
@@ -217,6 +217,55 @@ $QEMU_IMG amend -f $IMGFMT -o "data_file=blkdebug::$TEST_IMG.data" "$TEST_IMG"
 $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG"
 $QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG"
 
+echo
+echo "=== Flushing should flush the data file ==="
+echo
+
+# We are going to flush a qcow2 file with a blkdebug node inserted
+# between the qcow2 node and its data file node.  The blkdebug node
+# will return an error for all flushes and so we if the data file is
+# flushed, we will see qemu-io return an error.
+
+# We need to write something or the flush will not do anything; we
+# also need -t writeback so the write is not done as a FUA write
+# (which would then fail thanks to the implicit flush)
+$QEMU_IO -c 'write 0 512' -c flush \
+    -t writeback \
+    "json:{
+         'driver': 'qcow2',
+         'file': {
+             'driver': 'file',
+             'filename': '$TEST_IMG'
+         },
+         'data-file': {
+             'driver': 'blkdebug',
+             'inject-error': [{
+                 'event': 'none',
+                 'iotype': 'flush'
+             }],
+             'image': {
+                 'driver': 'file',
+                 'filename': '$TEST_IMG.data'
+             }
+         }
+     }" \
+    | _filter_qemu_io
+
+result=${PIPESTATUS[0]}
+echo
+
+case $result in
+    0)
+        echo "ERROR: qemu-io succeeded, so the data file was not flushed"
+        ;;
+    1)
+        echo "Success: qemu-io failed, so the data file was flushed"
+        ;;
+    *)
+        echo "ERROR: qemu-io returned unknown exit code $result"
+        ;;
+esac
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/244.out b/tests/qemu-iotests/244.out
index dbab7359a9..7269b4295a 100644
--- a/tests/qemu-iotests/244.out
+++ b/tests/qemu-iotests/244.out
@@ -131,4 +131,11 @@ Offset          Length          Mapped to       File
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data
 Images are identical.
 Images are identical.
+
+=== Flushing should flush the data file ===
+
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+Success: qemu-io failed, so the data file was flushed
 *** done
diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
index ad91a6f5b4..e60c8326d3 100755
--- a/tests/qemu-iotests/245
+++ b/tests/qemu-iotests/245
@@ -725,7 +725,9 @@ class TestBlockdevReopen(iotests.QMPTestCase):
 
         # Detach hd2 from hd0.
         self.reopen(opts, {'backing': None})
-        self.reopen(opts, {}, "backing is missing for 'hd0'")
+
+        # Without a backing file, we can omit 'backing' again
+        self.reopen(opts)
 
         # Remove both hd0 and hd2
         result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd0')
diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out
index 87d4758503..8247cbaea1 100644
--- a/tests/qemu-iotests/273.out
+++ b/tests/qemu-iotests/273.out
@@ -32,7 +32,7 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
                         "actual-size": SIZE,
                         "dirty-flag": false
                     },
-                    "backing-filename-format": "file",
+                    "backing-filename-format": "IMGFMT",
                     "virtual-size": 67108864,
                     "filename": "TEST_DIR/t.IMGFMT.mid",
                     "cluster-size": 65536,
@@ -112,7 +112,7 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
                     "actual-size": SIZE,
                     "dirty-flag": false
                 },
-                "backing-filename-format": "file",
+                "backing-filename-format": "IMGFMT",
                 "virtual-size": 67108864,
                 "filename": "TEST_DIR/t.IMGFMT.mid",
                 "cluster-size": 65536,
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
index 3ab859ac1a..e14a1f354d 100755
--- a/tests/qemu-iotests/check
+++ b/tests/qemu-iotests/check
@@ -44,7 +44,7 @@ then
         _init_error "failed to obtain source tree name from check symlink"
     fi
     source_iotests=$(cd "$source_iotests"; pwd) || _init_error "failed to enter source tree"
-    build_iotests=$PWD
+    build_iotests=$(readlink -f $(dirname "$0"))
 else
     # called from the source tree
     source_iotests=$PWD
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index e197c73ca5..64ccaf9061 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -972,8 +972,12 @@ class QMPTestCase(unittest.TestCase):
 
     def wait_ready(self, drive='drive0'):
         """Wait until a BLOCK_JOB_READY event, and return the event."""
-        f = {'data': {'type': 'mirror', 'device': drive}}
-        return self.vm.event_wait(name='BLOCK_JOB_READY', match=f)
+        return self.vm.events_wait([
+            ('BLOCK_JOB_READY',
+             {'data': {'type': 'mirror', 'device': drive}}),
+            ('BLOCK_JOB_READY',
+             {'data': {'type': 'commit', 'device': drive}})
+        ])
 
     def wait_ready_and_cancel(self, drive='drive0'):
         self.wait_ready(drive=drive)
@@ -992,7 +996,7 @@ class QMPTestCase(unittest.TestCase):
         self.assert_qmp(result, 'return', {})
 
         event = self.wait_until_completed(drive=drive, error=completion_error)
-        self.assert_qmp(event, 'data/type', 'mirror')
+        self.assertTrue(event['data']['type'] in ['mirror', 'commit'])
 
     def pause_wait(self, job_id='job0'):
         with Timeout(3, "Timeout waiting for job to pause"):
diff --git a/tests/requirements.txt b/tests/requirements.txt
index f9c84b4ba1..036691c922 100644
--- a/tests/requirements.txt
+++ b/tests/requirements.txt
@@ -1,5 +1,5 @@
 # Add Python module requirements, one per line, to be installed
 # in the tests/venv Python virtual environment. For more info,
 # refer to: https://pip.pypa.io/en/stable/user_guide/#id1
-avocado-framework==76.0
+avocado-framework==81.0
 pycdlib==1.9.0
diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target
index 4b2b696fce..2ae86776cd 100644
--- a/tests/tcg/Makefile.target
+++ b/tests/tcg/Makefile.target
@@ -129,8 +129,7 @@ ifeq ($(CONFIG_PLUGIN),y)
 PLUGIN_SRC=$(SRC_PATH)/tests/plugin
 PLUGIN_LIB=../../plugin
 VPATH+=$(PLUGIN_LIB)
-PLUGINS=$(filter-out liblockstep.so,\
-		$(patsubst %.c, lib%.so, $(notdir $(wildcard $(PLUGIN_SRC)/*.c))))
+PLUGINS=$(patsubst %.c, lib%.so, $(notdir $(wildcard $(PLUGIN_SRC)/*.c)))
 
 # We need to ensure expand the run-plugin-TEST-with-PLUGIN
 # pre-requistes manually here as we can't use stems to handle it. We
diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c
index 1e6b0f33ff..8a3c14d92c 100644
--- a/tests/test-qdev-global-props.c
+++ b/tests/test-qdev-global-props.c
@@ -31,19 +31,20 @@
 
 
 #define TYPE_STATIC_PROPS "static_prop_type"
-#define STATIC_TYPE(obj) \
-    OBJECT_CHECK(MyType, (obj), TYPE_STATIC_PROPS)
+typedef struct MyType MyType;
+DECLARE_INSTANCE_CHECKER(MyType, STATIC_TYPE,
+                         TYPE_STATIC_PROPS)
 
 #define TYPE_SUBCLASS "static_prop_subtype"
 
 #define PROP_DEFAULT 100
 
-typedef struct MyType {
+struct MyType {
     DeviceState parent_obj;
 
     uint32_t prop1;
     uint32_t prop2;
-} MyType;
+};
 
 static Property static_props[] = {
     DEFINE_PROP_UINT32("prop1", MyType, prop1, PROP_DEFAULT),
@@ -127,8 +128,8 @@ static void test_static_globalprop(void)
 }
 
 #define TYPE_DYNAMIC_PROPS "dynamic-prop-type"
-#define DYNAMIC_TYPE(obj) \
-    OBJECT_CHECK(MyType, (obj), TYPE_DYNAMIC_PROPS)
+DECLARE_INSTANCE_CHECKER(MyType, DYNAMIC_TYPE,
+                         TYPE_DYNAMIC_PROPS)
 
 #define TYPE_UNUSED_HOTPLUG   "hotplug-type"
 #define TYPE_UNUSED_NOHOTPLUG "nohotplug-type"
diff --git a/tests/test-vmstate.c b/tests/test-vmstate.c
index f8de709a0b..1c763015d0 100644
--- a/tests/test-vmstate.c
+++ b/tests/test-vmstate.c
@@ -1055,9 +1055,6 @@ static gboolean match_interval_mapping_node(gpointer key,
     TestGTreeMapping *map_a, *map_b;
     TestGTreeInterval *a, *b;
     struct match_node_data *d = (struct match_node_data *)data;
-    char *str = g_strdup_printf("dest");
-
-    g_free(str);
     a = (TestGTreeInterval *)key;
     b = (TestGTreeInterval *)d->key;
 
diff --git a/trace-events b/trace-events
index 42107ebc69..ac7cef9335 100644
--- a/trace-events
+++ b/trace-events
@@ -25,22 +25,6 @@
 #
 # The <format-string> should be a sprintf()-compatible format string.
 
-# ioport.c
-cpu_in(unsigned int addr, char size, unsigned int val) "addr 0x%x(%c) value %u"
-cpu_out(unsigned int addr, char size, unsigned int val) "addr 0x%x(%c) value %u"
-
-# balloon.c
-# Since requests are raised via monitor, not many tracepoints are needed.
-balloon_event(void *opaque, unsigned long addr) "opaque %p addr %lu"
-
-# vl.c
-vm_state_notify(int running, int reason, const char *reason_str) "running %d reason %d (%s)"
-load_file(const char *name, const char *path) "name %s location %s"
-runstate_set(int current_state, const char *current_state_str, int new_state, const char *new_state_str) "current_run_state %d (%s) new_state %d (%s)"
-system_wakeup_request(int reason) "reason=%d"
-qemu_system_shutdown_request(int reason) "reason=%d"
-qemu_system_powerdown_request(void) ""
-
 # dma-helpers.c
 dma_blk_io(void *dbs, void *bs, int64_t offset, bool to_dev) "dbs=%p bs=%p offset=%" PRId64 " to_dev=%d"
 dma_aio_cancel(void *dbs) "dbs=%p"
@@ -52,20 +36,11 @@ dma_map_wait(void *dbs) "dbs=%p"
 find_ram_offset(uint64_t size, uint64_t offset) "size: 0x%" PRIx64 " @ 0x%" PRIx64
 find_ram_offset_loop(uint64_t size, uint64_t candidate, uint64_t offset, uint64_t next, uint64_t mingap) "trying size: 0x%" PRIx64 " @ 0x%" PRIx64 ", offset: 0x%" PRIx64" next: 0x%" PRIx64 " mingap: 0x%" PRIx64
 ram_block_discard_range(const char *rbname, void *hva, size_t length, bool need_madvise, bool need_fallocate, int ret) "%s@%p + 0x%zx: madvise: %d fallocate: %d ret: %d"
+
+# accel/tcg/cputlb.c
 memory_notdirty_write_access(uint64_t vaddr, uint64_t ram_addr, unsigned size) "0x%" PRIx64 " ram_addr 0x%" PRIx64 " size %u"
 memory_notdirty_set_dirty(uint64_t vaddr) "0x%" PRIx64
 
-# memory.c
-memory_region_ops_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
-memory_region_ops_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
-memory_region_subpage_read(int cpu_index, void *mr, uint64_t offset, uint64_t value, unsigned size) "cpu %d mr %p offset 0x%"PRIx64" value 0x%"PRIx64" size %u"
-memory_region_subpage_write(int cpu_index, void *mr, uint64_t offset, uint64_t value, unsigned size) "cpu %d mr %p offset 0x%"PRIx64" value 0x%"PRIx64" size %u"
-memory_region_ram_device_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
-memory_region_ram_device_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
-flatview_new(void *view, void *root) "%p (root %p)"
-flatview_destroy(void *view, void *root) "%p (root %p)"
-flatview_destroy_rcu(void *view, void *root) "%p (root %p)"
-
 # gdbstub.c
 gdbstub_op_start(const char *device) "Starting gdbstub using device %s"
 gdbstub_op_exiting(uint8_t code) "notifying exit with code=0x%02x"
@@ -161,8 +136,7 @@ vcpu guest_cpu_reset(void)
 # Targets: TCG(all)
 vcpu tcg guest_mem_before(TCGv vaddr, uint16_t info) "info=%d", "vaddr=0x%016"PRIx64" info=%d"
 
-# linux-user/syscall.c
-# bsd-user/syscall.c
+# include/user/syscall-trace.h
 
 # @num: System call number.
 # @arg*: System call argument value.
diff --git a/ui/console.c b/ui/console.c
index 0579be792f..f8d7643fe4 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -34,6 +34,7 @@
 #include "trace.h"
 #include "exec/memory.h"
 #include "io/channel-file.h"
+#include "qom/object.h"
 
 #define DEFAULT_BACKSCROLL 512
 #define CONSOLE_CURSOR_PERIOD 500
@@ -1082,13 +1083,15 @@ void console_select(unsigned int index)
     }
 }
 
-typedef struct VCChardev {
+struct VCChardev {
     Chardev parent;
     QemuConsole *console;
-} VCChardev;
+};
+typedef struct VCChardev VCChardev;
 
 #define TYPE_CHARDEV_VC "chardev-vc"
-#define VC_CHARDEV(obj) OBJECT_CHECK(VCChardev, (obj), TYPE_CHARDEV_VC)
+DECLARE_INSTANCE_CHECKER(VCChardev, VC_CHARDEV,
+                         TYPE_CHARDEV_VC)
 
 static int vc_chr_write(Chardev *chr, const uint8_t *buf, int len)
 {
diff --git a/ui/gtk.c b/ui/gtk.c
index 7a717ce8e5..1c59de2af4 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -171,14 +171,16 @@ struct GtkDisplayState {
     DisplayOptions *opts;
 };
 
-typedef struct VCChardev {
+struct VCChardev {
     Chardev parent;
     VirtualConsole *console;
     bool echo;
-} VCChardev;
+};
+typedef struct VCChardev VCChardev;
 
 #define TYPE_CHARDEV_VC "chardev-vc"
-#define VC_CHARDEV(obj) OBJECT_CHECK(VCChardev, (obj), TYPE_CHARDEV_VC)
+DECLARE_INSTANCE_CHECKER(VCChardev, VC_CHARDEV,
+                         TYPE_CHARDEV_VC)
 
 bool gtk_use_gl_area;
 
diff --git a/ui/input-barrier.c b/ui/input-barrier.c
index 1cdf0c5f82..87543a3399 100644
--- a/ui/input-barrier.c
+++ b/ui/input-barrier.c
@@ -13,21 +13,16 @@
 #include "qom/object_interfaces.h"
 #include "io/channel-socket.h"
 #include "ui/input.h"
+#include "qom/object.h"
 #include "ui/vnc_keysym.h" /* use name2keysym from VNC as we use X11 values */
 #include "qemu/cutils.h"
 #include "qapi/qmp/qerror.h"
 #include "input-barrier.h"
 
 #define TYPE_INPUT_BARRIER "input-barrier"
-#define INPUT_BARRIER(obj) \
-    OBJECT_CHECK(InputBarrier, (obj), TYPE_INPUT_BARRIER)
-#define INPUT_BARRIER_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(InputBarrierClass, (obj), TYPE_INPUT_BARRIER)
-#define INPUT_BARRIER_CLASS(klass) \
-    OBJECT_CLASS_CHECK(InputBarrierClass, (klass), TYPE_INPUT_BARRIER)
+OBJECT_DECLARE_SIMPLE_TYPE(InputBarrier, input_barrier,
+                           INPUT_BARRIER, ObjectClass)
 
-typedef struct InputBarrier InputBarrier;
-typedef struct InputBarrierClass InputBarrierClass;
 
 #define MAX_HELLO_LENGTH 1024
 
@@ -49,9 +44,6 @@ struct InputBarrier {
     char buffer[MAX_HELLO_LENGTH];
 };
 
-struct InputBarrierClass {
-    ObjectClass parent_class;
-};
 
 static const char *cmd_names[] = {
     [barrierCmdCNoop]          = "CNOP",
diff --git a/ui/input-linux.c b/ui/input-linux.c
index 4925ce1af1..5d501c8360 100644
--- a/ui/input-linux.c
+++ b/ui/input-linux.c
@@ -17,6 +17,7 @@
 
 #include <sys/ioctl.h>
 #include "standard-headers/linux/input.h"
+#include "qom/object.h"
 
 static bool linux_is_button(unsigned int lnx)
 {
@@ -30,15 +31,9 @@ static bool linux_is_button(unsigned int lnx)
 }
 
 #define TYPE_INPUT_LINUX "input-linux"
-#define INPUT_LINUX(obj) \
-    OBJECT_CHECK(InputLinux, (obj), TYPE_INPUT_LINUX)
-#define INPUT_LINUX_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(InputLinuxClass, (obj), TYPE_INPUT_LINUX)
-#define INPUT_LINUX_CLASS(klass) \
-    OBJECT_CLASS_CHECK(InputLinuxClass, (klass), TYPE_INPUT_LINUX)
+OBJECT_DECLARE_SIMPLE_TYPE(InputLinux, input_linux,
+                           INPUT_LINUX, ObjectClass)
 
-typedef struct InputLinux InputLinux;
-typedef struct InputLinuxClass InputLinuxClass;
 
 struct InputLinux {
     Object parent;
@@ -70,9 +65,6 @@ struct InputLinux {
     QTAILQ_ENTRY(InputLinux) next;
 };
 
-struct InputLinuxClass {
-    ObjectClass parent_class;
-};
 
 static QTAILQ_HEAD(, InputLinux) inputs = QTAILQ_HEAD_INITIALIZER(inputs);
 
diff --git a/ui/spice-app.c b/ui/spice-app.c
index 40fb2ef573..93e105c6ee 100644
--- a/ui/spice-app.c
+++ b/ui/spice-app.c
@@ -35,17 +35,20 @@
 #include "io/channel-command.h"
 #include "chardev/spice.h"
 #include "sysemu/sysemu.h"
+#include "qom/object.h"
 
 static const char *tmp_dir;
 static char *app_dir;
 static char *sock_path;
 
-typedef struct VCChardev {
+struct VCChardev {
     SpiceChardev parent;
-} VCChardev;
+};
+typedef struct VCChardev VCChardev;
 
 #define TYPE_CHARDEV_VC "chardev-vc"
-#define VC_CHARDEV(obj) OBJECT_CHECK(VCChardev, (obj), TYPE_CHARDEV_VC)
+DECLARE_INSTANCE_CHECKER(VCChardev, VC_CHARDEV,
+                         TYPE_CHARDEV_VC)
 
 static ChardevBackend *
 chr_spice_backend_new(void)
diff --git a/ui/trace-events b/ui/trace-events
index 5367fd3f16..b7d7270c02 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -17,9 +17,9 @@ displaychangelistener_register(void *dcl, const char *name) "%p [ %s ]"
 displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]"
 ppm_save(int fd, void *display_surface) "fd=%d surface=%p"
 
-# gtk.c
-# gtk-gl-area.c
 # gtk-egl.c
+# gtk-gl-area.c
+# gtk.c
 gd_switch(const char *tab, int width, int height) "tab=%s, width=%d, height=%d"
 gd_update(const char *tab, int x, int y, int w, int h) "tab=%s, x=%d, y=%d, w=%d, h=%d"
 gd_key_event(const char *tab, int gdk_keycode, int qkeycode, const char *action) "tab=%s, translated GDK keycode %d to QKeyCode %d (%s)"
@@ -28,8 +28,8 @@ gd_ungrab(const char *tab, const char *device) "tab=%s, dev=%s"
 gd_keymap_windowing(const char *name) "backend=%s"
 
 # vnc-auth-sasl.c
-# vnc-ws.c
 # vnc-auth-vencrypt.c
+# vnc-ws.c
 # vnc.c
 vnc_key_guest_leds(bool caps, bool num, bool scroll) "caps %d, num %d, scroll %d"
 vnc_key_map_init(const char *layout) "%s"
diff --git a/util/hexdump.c b/util/hexdump.c
index f879ff0ad6..0b4662e701 100644
--- a/util/hexdump.c
+++ b/util/hexdump.c
@@ -16,8 +16,10 @@
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 
-void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size)
+void qemu_hexdump(FILE *fp, const char *prefix,
+                  const void *bufptr, size_t size)
 {
+    const char *buf = bufptr;
     unsigned int b, len, i, c;
 
     for (b = 0; b < size; b += 16) {
diff --git a/util/iov.c b/util/iov.c
index 45ef3043ee..ae61d696aa 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -237,7 +237,7 @@ void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt,
     size = size > limit ? limit : size;
     buf = g_malloc(size);
     iov_to_buf(iov, iov_cnt, 0, buf, size);
-    qemu_hexdump(buf, fp, prefix, size);
+    qemu_hexdump(fp, prefix, buf, size);
     g_free(buf);
 }
 
diff --git a/util/trace-events b/util/trace-events
index d9a0b4f8c6..4e894aa9c3 100644
--- a/util/trace-events
+++ b/util/trace-events
@@ -44,8 +44,8 @@ qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p"
 qemu_co_mutex_unlock_entry(void *mutex, void *self) "mutex %p self %p"
 qemu_co_mutex_unlock_return(void *mutex, void *self) "mutex %p self %p"
 
-# oslib-win32.c
 # oslib-posix.c
+# oslib-win32.c
 qemu_memalign(size_t alignment, size_t size, void *ptr) "alignment %zu size %zu ptr %p"
 qemu_anon_ram_alloc(size_t size, void *ptr) "size %zu ptr %p"
 qemu_vfree(void *ptr) "ptr %p"
@@ -70,6 +70,8 @@ lockcnt_futex_wake(const void *lockcnt) "lockcnt %p waking up one waiter"
 socket_listen(int num) "backlog: %d"
 
 # qemu-thread-common.h
+# qemu-thread-posix.c
+# qemu-thread-win32.c
 qemu_mutex_lock(void *mutex, const char *file, const int line) "waiting on mutex %p (%s:%d)"
 qemu_mutex_locked(void *mutex, const char *file, const int line) "taken mutex %p (%s:%d)"
 qemu_mutex_unlock(void *mutex, const char *file, const int line) "released mutex %p (%s:%d)"