diff options
84 files changed, 493 insertions, 183 deletions
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 93849c8d36..9e8a89c233 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -544,9 +544,13 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data) k->revision = 0x03; k->class_id = PCI_CLASS_BRIDGE_OTHER; dc->desc = "PM"; - dc->no_user = 1; dc->vmsd = &vmstate_acpi; dc->props = piix4_pm_properties; + /* + * Reason: part of PIIX4 southbridge, needs to be wired up, + * e.g. by mips_malta_init() + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo piix4_pm_info = { diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c index 59e1bb8388..71a5a37fdc 100644 --- a/hw/alpha/typhoon.c +++ b/hw/alpha/typhoon.c @@ -934,11 +934,9 @@ static int typhoon_pcihost_init(SysBusDevice *dev) static void typhoon_pcihost_class_init(ObjectClass *klass, void *data) { - DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); k->init = typhoon_pcihost_init; - dc->no_user = 1; } static const TypeInfo typhoon_pcihost_info = { diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c index f7e8b7e8fa..aef2bde0c4 100644 --- a/hw/arm/versatilepb.c +++ b/hw/arm/versatilepb.c @@ -390,7 +390,6 @@ static void vpb_sic_class_init(ObjectClass *klass, void *data) SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); k->init = vpb_sic_init; - dc->no_user = 1; dc->vmsd = &vmstate_vpb_sic; } diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c index 97194ce7ad..cdce238f55 100644 --- a/hw/audio/marvell_88w8618.c +++ b/hw/audio/marvell_88w8618.c @@ -288,6 +288,8 @@ static void mv88w8618_audio_class_init(ObjectClass *klass, void *data) dc->reset = mv88w8618_audio_reset; dc->vmsd = &mv88w8618_audio_vmsd; dc->props = mv88w8618_audio_properties; + /* Reason: pointer property "wm8750" */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo mv88w8618_audio_info = { diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index 9004ce3d1f..f980d66b2f 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -192,8 +192,9 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data) dc->realize = pcspk_realizefn; set_bit(DEVICE_CATEGORY_SOUND, dc->categories); - dc->no_user = 1; dc->props = pcspk_properties; + /* Reason: pointer property "pit", realize sets global pcspk_state */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo pcspk_info = { diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c index 5393b520b7..ed82be54e8 100644 --- a/hw/audio/pl041.c +++ b/hw/audio/pl041.c @@ -632,7 +632,6 @@ static void pl041_device_class_init(ObjectClass *klass, void *data) k->init = pl041_init; set_bit(DEVICE_CATEGORY_SOUND, dc->categories); - dc->no_user = 1; dc->reset = pl041_device_reset; dc->vmsd = &vmstate_pl041; dc->props = pl041_device_properties; diff --git a/hw/block/fdc.c b/hw/block/fdc.c index c5a6c21215..592b58f9b5 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -2234,7 +2234,6 @@ static void isabus_fdc_class_init(ObjectClass *klass, void *data) dc->realize = isabus_fdc_realize; dc->fw_name = "fdc"; - dc->no_user = 1; dc->reset = fdctrl_external_reset_isa; dc->vmsd = &vmstate_isa_fdc; dc->props = isa_fdc_properties; diff --git a/hw/core/qdev.c b/hw/core/qdev.c index e374a9399f..bbd780aad1 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -481,11 +481,6 @@ BusState *qbus_create(const char *typename, DeviceState *parent, const char *nam return bus; } -void qbus_free(BusState *bus) -{ - object_unparent(OBJECT(bus)); -} - static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev) { BusClass *bc = BUS_GET_CLASS(bus); @@ -794,7 +789,7 @@ static void device_unparent(Object *obj) while (dev->num_child_bus) { bus = QLIST_FIRST(&dev->child_bus); - qbus_free(bus); + object_unparent(OBJECT(bus)); } if (dev->realized) { object_property_set_bool(obj, false, "realized", NULL); diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c index 146f50aa15..f4e760d6eb 100644 --- a/hw/core/sysbus.c +++ b/hw/core/sysbus.c @@ -257,6 +257,13 @@ static void sysbus_device_class_init(ObjectClass *klass, void *data) DeviceClass *k = DEVICE_CLASS(klass); k->init = sysbus_device_init; k->bus_type = TYPE_SYSTEM_BUS; + /* + * device_add plugs devices into suitable bus. For "real" buses, + * that actually connects the device. For sysbus, the connections + * need to be made separately, and device_add can't do that. The + * device would be left unconnected, and could not possibly work. + */ + k->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo sysbus_device_type_info = { diff --git a/hw/cpu/icc_bus.c b/hw/cpu/icc_bus.c index 9a4ea7e2df..7f44c59b25 100644 --- a/hw/cpu/icc_bus.c +++ b/hw/cpu/icc_bus.c @@ -43,15 +43,13 @@ static const TypeInfo icc_bus_info = { static void icc_device_realize(DeviceState *dev, Error **errp) { - ICCDevice *id = ICC_DEVICE(dev); - ICCDeviceClass *idc = ICC_DEVICE_GET_CLASS(id); - - if (idc->init) { - if (idc->init(id) < 0) { - error_setg(errp, "%s initialization failed.", - object_get_typename(OBJECT(dev))); - } + ICCDeviceClass *idc = ICC_DEVICE_GET_CLASS(dev); + + /* convert to QOM */ + if (idc->realize) { + idc->realize(dev, errp); } + } static void icc_device_class_init(ObjectClass *oc, void *data) diff --git a/hw/display/pl110.c b/hw/display/pl110.c index 790e5108ed..ab689e9aae 100644 --- a/hw/display/pl110.c +++ b/hw/display/pl110.c @@ -496,7 +496,6 @@ static void pl110_class_init(ObjectClass *klass, void *data) k->init = pl110_initfn; set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); - dc->no_user = 1; dc->vmsd = &vmstate_pl110; } diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c index 35b90155a2..cb7bda9803 100644 --- a/hw/dma/pl080.c +++ b/hw/dma/pl080.c @@ -381,7 +381,6 @@ static void pl080_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - dc->no_user = 1; dc->vmsd = &vmstate_pl080; } diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index 2a92ffb82e..eac338f1bc 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -304,6 +304,8 @@ static void sparc32_dma_class_init(ObjectClass *klass, void *data) dc->reset = dma_reset; dc->vmsd = &vmstate_dma; dc->props = sparc32_dma_properties; + /* Reason: pointer property "iommu_opaque" */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo sparc32_dma_info = { diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c index b8f572bb70..938782a45d 100644 --- a/hw/gpio/omap_gpio.c +++ b/hw/gpio/omap_gpio.c @@ -759,6 +759,8 @@ static void omap_gpio_class_init(ObjectClass *klass, void *data) k->init = omap_gpio_init; dc->reset = omap_gpif_reset; dc->props = omap_gpio_properties; + /* Reason: pointer property "clk" */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo omap_gpio_info = { @@ -788,6 +790,8 @@ static void omap2_gpio_class_init(ObjectClass *klass, void *data) k->init = omap2_gpio_init; dc->reset = omap2_gpif_reset; dc->props = omap2_gpio_properties; + /* Reason: pointer properties "iclk", "fclk0", ..., "fclk5" */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo omap2_gpio_info = { diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c index f528b2b38e..2d8e2b7839 100644 --- a/hw/i2c/omap_i2c.c +++ b/hw/i2c/omap_i2c.c @@ -475,6 +475,8 @@ static void omap_i2c_class_init(ObjectClass *klass, void *data) k->init = omap_i2c_init; dc->props = omap_i2c_properties; dc->reset = omap_i2c_reset; + /* Reason: pointer properties "iclk", "fclk" */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo omap_i2c_info = { diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c index 0154283762..0218f8a0eb 100644 --- a/hw/i2c/smbus_eeprom.c +++ b/hw/i2c/smbus_eeprom.c @@ -121,6 +121,8 @@ static void smbus_eeprom_class_initfn(ObjectClass *klass, void *data) sc->write_data = eeprom_write_data; sc->read_data = eeprom_read_data; dc->props = smbus_eeprom_properties; + /* Reason: pointer property "data" */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo smbus_eeprom_info = { diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c index ca229789f4..8d47eaffc8 100644 --- a/hw/i2c/smbus_ich9.c +++ b/hw/i2c/smbus_ich9.c @@ -97,11 +97,15 @@ static void ich9_smb_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_INTEL_ICH9_6; k->revision = ICH9_A2_SMB_REVISION; k->class_id = PCI_CLASS_SERIAL_SMBUS; - dc->no_user = 1; dc->vmsd = &vmstate_ich9_smbus; dc->desc = "ICH9 SMBUS Bridge"; k->init = ich9_smbus_initfn; k->config_write = ich9_smbus_write_config; + /* + * Reason: part of ICH9 southbridge, needs to be wired up by + * pc_q35_init() + */ + dc->cannot_instantiate_with_device_add_yet = true; } i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base) diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c index 5609063120..e873b509a5 100644 --- a/hw/i386/kvm/apic.c +++ b/hw/i386/kvm/apic.c @@ -25,9 +25,9 @@ static inline uint32_t kvm_apic_get_reg(struct kvm_lapic_state *kapic, return *((uint32_t *)(kapic->regs + (reg_id << 4))); } -void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic) +void kvm_put_apic_state(DeviceState *dev, struct kvm_lapic_state *kapic) { - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); + APICCommonState *s = APIC_COMMON(dev); int i; memset(kapic, 0, sizeof(*kapic)); @@ -51,9 +51,9 @@ void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic) kvm_apic_set_reg(kapic, 0x3e, s->divide_conf); } -void kvm_get_apic_state(DeviceState *d, struct kvm_lapic_state *kapic) +void kvm_get_apic_state(DeviceState *dev, struct kvm_lapic_state *kapic) { - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); + APICCommonState *s = APIC_COMMON(dev); int i, v; s->id = kvm_apic_get_reg(kapic, 0x2) >> 24; @@ -171,8 +171,10 @@ static const MemoryRegionOps kvm_apic_io_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void kvm_apic_init(APICCommonState *s) +static void kvm_apic_realize(DeviceState *dev, Error **errp) { + APICCommonState *s = APIC_COMMON(dev); + memory_region_init_io(&s->io_memory, NULL, &kvm_apic_io_ops, s, "kvm-apic-msi", APIC_SPACE_SIZE); @@ -185,7 +187,7 @@ static void kvm_apic_class_init(ObjectClass *klass, void *data) { APICCommonClass *k = APIC_COMMON_CLASS(klass); - k->init = kvm_apic_init; + k->realize = kvm_apic_realize; k->set_base = kvm_apic_set_base; k->set_tpr = kvm_apic_set_tpr; k->get_tpr = kvm_apic_get_tpr; diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c index 383938d1bc..892aa025f4 100644 --- a/hw/i386/kvm/clock.c +++ b/hw/i386/kvm/clock.c @@ -114,7 +114,6 @@ static void kvmclock_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = kvmclock_realize; - dc->no_user = 1; dc->vmsd = &kvmclock_vmsd; } diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c index f11a540825..d2a6c4cf60 100644 --- a/hw/i386/kvm/ioapic.c +++ b/hw/i386/kvm/ioapic.c @@ -127,11 +127,13 @@ static void kvm_ioapic_set_irq(void *opaque, int irq, int level) apic_report_irq_delivered(delivered); } -static void kvm_ioapic_init(IOAPICCommonState *s, int instance_no) +static void kvm_ioapic_realize(DeviceState *dev, Error **errp) { + IOAPICCommonState *s = IOAPIC_COMMON(dev); + memory_region_init_reservation(&s->io_memory, NULL, "kvm-ioapic", 0x1000); - qdev_init_gpio_in(DEVICE(s), kvm_ioapic_set_irq, IOAPIC_NUM_PINS); + qdev_init_gpio_in(dev, kvm_ioapic_set_irq, IOAPIC_NUM_PINS); } static Property kvm_ioapic_properties[] = { @@ -144,7 +146,7 @@ static void kvm_ioapic_class_init(ObjectClass *klass, void *data) IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = kvm_ioapic_init; + k->realize = kvm_ioapic_realize; k->pre_save = kvm_ioapic_get; k->post_load = kvm_ioapic_put; dc->reset = kvm_ioapic_reset; diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c index 2d876009fc..44ee62a233 100644 --- a/hw/i386/kvmvapic.c +++ b/hw/i386/kvmvapic.c @@ -827,7 +827,6 @@ static void vapic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - dc->no_user = 1; dc->reset = vapic_reset; dc->vmsd = &vmstate_vapic; dc->realize = vapic_realize; diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 3cd8f383f3..e9831ca411 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -547,10 +547,15 @@ static void port92_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - dc->no_user = 1; dc->realize = port92_realizefn; dc->reset = port92_reset; dc->vmsd = &vmstate_port92_isa; + /* + * Reason: unlike ordinary ISA devices, this one needs additional + * wiring: its A20 output line needs to be wired up by + * port92_init(). + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo port92_info = { diff --git a/hw/ide/piix.c b/hw/ide/piix.c index ab36749417..9b5960b44e 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -248,7 +248,6 @@ static void piix3_ide_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; k->class_id = PCI_CLASS_STORAGE_IDE; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); - dc->no_user = 1; } static const TypeInfo piix3_ide_info = { @@ -267,7 +266,6 @@ static void piix3_ide_xen_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; k->class_id = PCI_CLASS_STORAGE_IDE; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); - dc->no_user = 1; dc->unplug = pci_piix3_xen_ide_unplug; } @@ -289,7 +287,6 @@ static void piix4_ide_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_INTEL_82371AB; k->class_id = PCI_CLASS_STORAGE_IDE; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); - dc->no_user = 1; } static const TypeInfo piix4_ide_info = { diff --git a/hw/ide/via.c b/hw/ide/via.c index 99468c773e..198123b026 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -225,7 +225,6 @@ static void via_ide_class_init(ObjectClass *klass, void *data) k->revision = 0x06; k->class_id = PCI_CLASS_STORAGE_IDE; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); - dc->no_user = 1; } static const TypeInfo via_ide_info = { diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c index ce86237cf3..655b8c5011 100644 --- a/hw/input/pckbd.c +++ b/hw/input/pckbd.c @@ -522,7 +522,6 @@ static void i8042_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = i8042_realizefn; - dc->no_user = 1; dc->vmsd = &vmstate_kbd_isa; } diff --git a/hw/input/vmmouse.c b/hw/input/vmmouse.c index abd032b794..6a5053352a 100644 --- a/hw/input/vmmouse.c +++ b/hw/input/vmmouse.c @@ -282,10 +282,11 @@ static void vmmouse_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = vmmouse_realizefn; - dc->no_user = 1; dc->reset = vmmouse_reset; dc->vmsd = &vmstate_vmmouse; dc->props = vmmouse_properties; + /* Reason: pointer property "ps2_mouse" */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo vmmouse_info = { diff --git a/hw/intc/apic.c b/hw/intc/apic.c index a913186ed0..3d3deb6298 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -171,9 +171,9 @@ static void apic_local_deliver(APICCommonState *s, int vector) } } -void apic_deliver_pic_intr(DeviceState *d, int level) +void apic_deliver_pic_intr(DeviceState *dev, int level) { - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); + APICCommonState *s = APIC_COMMON(dev); if (level) { apic_local_deliver(s, APIC_LVT_LINT0); @@ -376,9 +376,9 @@ static void apic_update_irq(APICCommonState *s) } } -void apic_poll_irq(DeviceState *d) +void apic_poll_irq(DeviceState *dev) { - APICCommonState *s = APIC_COMMON(d); + APICCommonState *s = APIC_COMMON(dev); apic_sync_vapic(s, SYNC_FROM_VAPIC); apic_update_irq(s); @@ -482,9 +482,9 @@ static void apic_startup(APICCommonState *s, int vector_num) cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI); } -void apic_sipi(DeviceState *d) +void apic_sipi(DeviceState *dev) { - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); + APICCommonState *s = APIC_COMMON(dev); cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI); @@ -494,11 +494,11 @@ void apic_sipi(DeviceState *d) s->wait_for_sipi = 0; } -static void apic_deliver(DeviceState *d, uint8_t dest, uint8_t dest_mode, +static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode) { - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); + APICCommonState *s = APIC_COMMON(dev); uint32_t deliver_bitmask[MAX_APIC_WORDS]; int dest_shorthand = (s->icr[0] >> 18) & 3; APICCommonState *apic_iter; @@ -551,9 +551,9 @@ static bool apic_check_pic(APICCommonState *s) return true; } -int apic_get_interrupt(DeviceState *d) +int apic_get_interrupt(DeviceState *dev) { - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); + APICCommonState *s = APIC_COMMON(dev); int intno; /* if the APIC is installed or enabled, we let the 8259 handle the @@ -585,9 +585,9 @@ int apic_get_interrupt(DeviceState *d) return intno; } -int apic_accept_pic_intr(DeviceState *d) +int apic_accept_pic_intr(DeviceState *dev) { - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); + APICCommonState *s = APIC_COMMON(dev); uint32_t lvt0; if (!s) @@ -657,16 +657,16 @@ static void apic_mem_writew(void *opaque, hwaddr addr, uint32_t val) static uint32_t apic_mem_readl(void *opaque, hwaddr addr) { - DeviceState *d; + DeviceState *dev; APICCommonState *s; uint32_t val; int index; - d = cpu_get_current_apic(); - if (!d) { + dev = cpu_get_current_apic(); + if (!dev) { return 0; } - s = DO_UPCAST(APICCommonState, busdev.qdev, d); + s = APIC_COMMON(dev); index = (addr >> 4) & 0xff; switch(index) { @@ -752,7 +752,7 @@ static void apic_send_msi(hwaddr addr, uint32_t data) static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val) { - DeviceState *d; + DeviceState *dev; APICCommonState *s; int index = (addr >> 4) & 0xff; if (addr > 0xfff || !index) { @@ -765,11 +765,11 @@ static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val) return; } - d = cpu_get_current_apic(); - if (!d) { + dev = cpu_get_current_apic(); + if (!dev) { return; } - s = DO_UPCAST(APICCommonState, busdev.qdev, d); + s = APIC_COMMON(dev); trace_apic_mem_writel(addr, val); @@ -810,7 +810,7 @@ static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val) break; case 0x30: s->icr[0] = val; - apic_deliver(d, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1, + apic_deliver(dev, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1, (s->icr[0] >> 8) & 7, (s->icr[0] & 0xff), (s->icr[0] >> 15) & 1); break; @@ -871,8 +871,10 @@ static const MemoryRegionOps apic_io_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void apic_init(APICCommonState *s) +static void apic_realize(DeviceState *dev, Error **errp) { + APICCommonState *s = APIC_COMMON(dev); + memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic-msi", APIC_SPACE_SIZE); @@ -886,7 +888,7 @@ static void apic_class_init(ObjectClass *klass, void *data) { APICCommonClass *k = APIC_COMMON_CLASS(klass); - k->init = apic_init; + k->realize = apic_realize; k->set_base = apic_set_base; k->set_tpr = apic_set_tpr; k->get_tpr = apic_get_tpr; diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index a0beb10863..c623fcc6d8 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -27,21 +27,21 @@ static int apic_irq_delivered; bool apic_report_tpr_access; -void cpu_set_apic_base(DeviceState *d, uint64_t val) +void cpu_set_apic_base(DeviceState *dev, uint64_t val) { trace_cpu_set_apic_base(val); - if (d) { - APICCommonState *s = APIC_COMMON(d); + if (dev) { + APICCommonState *s = APIC_COMMON(dev); APICCommonClass *info = APIC_COMMON_GET_CLASS(s); info->set_base(s, val); } } -uint64_t cpu_get_apic_base(DeviceState *d) +uint64_t cpu_get_apic_base(DeviceState *dev) { - if (d) { - APICCommonState *s = APIC_COMMON(d); + if (dev) { + APICCommonState *s = APIC_COMMON(dev); trace_cpu_get_apic_base((uint64_t)s->apicbase); return s->apicbase; } else { @@ -50,39 +50,39 @@ uint64_t cpu_get_apic_base(DeviceState *d) } } -void cpu_set_apic_tpr(DeviceState *d, uint8_t val) +void cpu_set_apic_tpr(DeviceState *dev, uint8_t val) { APICCommonState *s; APICCommonClass *info; - if (!d) { + if (!dev) { return; } - s = APIC_COMMON(d); + s = APIC_COMMON(dev); info = APIC_COMMON_GET_CLASS(s); info->set_tpr(s, val); } -uint8_t cpu_get_apic_tpr(DeviceState *d) +uint8_t cpu_get_apic_tpr(DeviceState *dev) { APICCommonState *s; APICCommonClass *info; - if (!d) { + if (!dev) { return 0; } - s = APIC_COMMON(d); + s = APIC_COMMON(dev); info = APIC_COMMON_GET_CLASS(s); return info->get_tpr(s); } -void apic_enable_tpr_access_reporting(DeviceState *d, bool enable) +void apic_enable_tpr_access_reporting(DeviceState *dev, bool enable) { - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); + APICCommonState *s = APIC_COMMON(dev); APICCommonClass *info = APIC_COMMON_GET_CLASS(s); apic_report_tpr_access = enable; @@ -91,19 +91,19 @@ void apic_enable_tpr_access_reporting(DeviceState *d, bool enable) } } -void apic_enable_vapic(DeviceState *d, hwaddr paddr) +void apic_enable_vapic(DeviceState *dev, hwaddr paddr) { - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); + APICCommonState *s = APIC_COMMON(dev); APICCommonClass *info = APIC_COMMON_GET_CLASS(s); s->vapic_paddr = paddr; info->vapic_base_update(s); } -void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, +void apic_handle_tpr_access_report(DeviceState *dev, target_ulong ip, TPRAccess access) { - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); + APICCommonState *s = APIC_COMMON(dev); vapic_report_tpr_access(s->vapic, CPU(s->cpu), ip, access); } @@ -129,9 +129,9 @@ int apic_get_irq_delivered(void) return apic_irq_delivered; } -void apic_deliver_nmi(DeviceState *d) +void apic_deliver_nmi(DeviceState *dev) { - APICCommonState *s = APIC_COMMON(d); + APICCommonState *s = APIC_COMMON(dev); APICCommonClass *info = APIC_COMMON_GET_CLASS(s); info->external_nmi(s); @@ -170,9 +170,9 @@ bool apic_next_timer(APICCommonState *s, int64_t current_time) return true; } -void apic_init_reset(DeviceState *d) +void apic_init_reset(DeviceState *dev) { - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); + APICCommonState *s = APIC_COMMON(dev); int i; if (!s) { @@ -203,19 +203,19 @@ void apic_init_reset(DeviceState *d) s->timer_expiry = -1; } -void apic_designate_bsp(DeviceState *d) +void apic_designate_bsp(DeviceState *dev) { - if (d == NULL) { + if (dev == NULL) { return; } - APICCommonState *s = APIC_COMMON(d); + APICCommonState *s = APIC_COMMON(dev); s->apicbase |= MSR_IA32_APICBASE_BSP; } -static void apic_reset_common(DeviceState *d) +static void apic_reset_common(DeviceState *dev) { - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); + APICCommonState *s = APIC_COMMON(dev); APICCommonClass *info = APIC_COMMON_GET_CLASS(s); bool bsp; @@ -226,7 +226,7 @@ static void apic_reset_common(DeviceState *d) s->vapic_paddr = 0; info->vapic_base_update(s); - apic_init_reset(d); + apic_init_reset(dev); if (bsp) { /* @@ -284,7 +284,7 @@ static int apic_load_old(QEMUFile *f, void *opaque, int version_id) return 0; } -static int apic_init_common(ICCDevice *dev) +static void apic_common_realize(DeviceState *dev, Error **errp) { APICCommonState *s = APIC_COMMON(dev); APICCommonClass *info; @@ -293,14 +293,16 @@ static int apic_init_common(ICCDevice *dev) static bool mmio_registered; if (apic_no >= MAX_APICS) { - return -1; + error_setg(errp, "%s initialization failed.", + object_get_typename(OBJECT(dev))); + return; } s->idx = apic_no++; info = APIC_COMMON_GET_CLASS(s); - info->init(s); + info->realize(dev, errp); if (!mmio_registered) { - ICCBus *b = ICC_BUS(qdev_get_parent_bus(DEVICE(dev))); + ICCBus *b = ICC_BUS(qdev_get_parent_bus(dev)); memory_region_add_subregion(b->apic_address_space, 0, &s->io_memory); mmio_registered = true; } @@ -315,7 +317,6 @@ static int apic_init_common(ICCDevice *dev) info->enable_tpr_reporting(s, true); } - return 0; } static void apic_dispatch_pre_save(void *opaque) @@ -386,9 +387,13 @@ static void apic_common_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_apic_common; dc->reset = apic_reset_common; - dc->no_user = 1; dc->props = apic_properties_common; - idc->init = apic_init_common; + idc->realize = apic_common_realize; + /* + * Reason: APIC and CPU need to be wired up by + * x86_cpu_apic_create() + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo apic_common_type = { @@ -400,9 +405,9 @@ static const TypeInfo apic_common_type = { .abstract = true, }; -static void register_types(void) +static void apic_common_register_types(void) { type_register_static(&apic_common_type); } -type_init(register_types) +type_init(apic_common_register_types) diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 6c5965093e..9409684ce8 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -709,7 +709,6 @@ static void arm_gic_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); ARMGICClass *agc = ARM_GIC_CLASS(klass); - dc->no_user = 1; agc->parent_realize = dc->realize; dc->realize = arm_gic_realize; } diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index 710607b044..e4fc65028a 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -156,7 +156,6 @@ static void arm_gic_common_class_init(ObjectClass *klass, void *data) dc->realize = arm_gic_common_realize; dc->props = arm_gic_common_properties; dc->vmsd = &vmstate_gic; - dc->no_user = 1; } static const TypeInfo arm_gic_common_type = { diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c index f71397542a..59a3da5a6b 100644 --- a/hw/intc/arm_gic_kvm.c +++ b/hw/intc/arm_gic_kvm.c @@ -150,7 +150,6 @@ static void kvm_arm_gic_class_init(ObjectClass *klass, void *data) kgc->parent_reset = dc->reset; dc->realize = kvm_arm_gic_realize; dc->reset = kvm_arm_gic_reset; - dc->no_user = 1; } static const TypeInfo kvm_arm_gic_info = { diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c index e02da533cb..636262b49f 100644 --- a/hw/intc/etraxfs_pic.c +++ b/hw/intc/etraxfs_pic.c @@ -170,6 +170,10 @@ static void etraxfs_pic_class_init(ObjectClass *klass, void *data) k->init = etraxfs_pic_init; dc->props = etraxfs_pic_properties; + /* + * Note: pointer property "interrupt_vector" may remain null, thus + * no need for dc->cannot_instantiate_with_device_add_yet = true; + */ } static const TypeInfo etraxfs_pic_info = { diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c index 42e00bc4b8..d1813f76b6 100644 --- a/hw/intc/grlib_irqmp.c +++ b/hw/intc/grlib_irqmp.c @@ -355,6 +355,8 @@ static void grlib_irqmp_class_init(ObjectClass *klass, void *data) k->init = grlib_irqmp_init; dc->reset = grlib_irqmp_reset; dc->props = grlib_irqmp_properties; + /* Reason: pointer properties "set_pil_in", "set_pil_in_opaque" */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo grlib_irqmp_info = { diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c index 803d037f68..9d293999be 100644 --- a/hw/intc/i8259_common.c +++ b/hw/intc/i8259_common.c @@ -135,9 +135,15 @@ static void pic_common_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->vmsd = &vmstate_pic_common; - dc->no_user = 1; dc->props = pic_properties_common; dc->realize = pic_common_realize; + /* + * Reason: unlike ordinary ISA devices, the PICs need additional + * wiring: its IRQ input lines are set up by board code, and the + * wiring of the slave to the master is hard-coded in device model + * code. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo pic_common_type = { diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c index d866e00297..652dd47a1c 100644 --- a/hw/intc/ioapic.c +++ b/hw/intc/ioapic.c @@ -36,6 +36,9 @@ static IOAPICCommonState *ioapics[MAX_IOAPICS]; +/* global variable from ioapic_common.c */ +extern int ioapic_no; + static void ioapic_service(IOAPICCommonState *s) { uint8_t i; @@ -225,14 +228,16 @@ static const MemoryRegionOps ioapic_io_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void ioapic_init(IOAPICCommonState *s, int instance_no) +static void ioapic_realize(DeviceState *dev, Error **errp) { + IOAPICCommonState *s = IOAPIC_COMMON(dev); + memory_region_init_io(&s->io_memory, OBJECT(s), &ioapic_io_ops, s, "ioapic", 0x1000); - qdev_init_gpio_in(DEVICE(s), ioapic_set_irq, IOAPIC_NUM_PINS); + qdev_init_gpio_in(dev, ioapic_set_irq, IOAPIC_NUM_PINS); - ioapics[instance_no] = s; + ioapics[ioapic_no] = s; } static void ioapic_class_init(ObjectClass *klass, void *data) @@ -240,7 +245,7 @@ static void ioapic_class_init(ObjectClass *klass, void *data) IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = ioapic_init; + k->realize = ioapic_realize; dc->reset = ioapic_reset_common; } diff --git a/hw/intc/ioapic_common.c b/hw/intc/ioapic_common.c index 6b705c1546..4d3d309b62 100644 --- a/hw/intc/ioapic_common.c +++ b/hw/intc/ioapic_common.c @@ -23,6 +23,14 @@ #include "hw/i386/ioapic_internal.h" #include "hw/sysbus.h" +/* ioapic_no count start from 0 to MAX_IOAPICS, + * remove as static variable from ioapic_common_init. + * now as a global variable, let child to increase the counter + * then we can drop the 'instance_no' argument + * and convert to our QOM's realize function + */ +int ioapic_no; + void ioapic_reset_common(DeviceState *dev) { IOAPICCommonState *s = IOAPIC_COMMON(dev); @@ -61,7 +69,6 @@ static void ioapic_common_realize(DeviceState *dev, Error **errp) { IOAPICCommonState *s = IOAPIC_COMMON(dev); IOAPICCommonClass *info; - static int ioapic_no; if (ioapic_no >= MAX_IOAPICS) { error_setg(errp, "Only %d ioapics allowed", MAX_IOAPICS); @@ -69,7 +76,7 @@ static void ioapic_common_realize(DeviceState *dev, Error **errp) } info = IOAPIC_COMMON_GET_CLASS(s); - info->init(s, ioapic_no); + info->realize(dev, errp); sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->io_memory); ioapic_no++; @@ -98,7 +105,6 @@ static void ioapic_common_class_init(ObjectClass *klass, void *data) dc->realize = ioapic_common_realize; dc->vmsd = &vmstate_ioapic_common; - dc->no_user = 1; } static const TypeInfo ioapic_common_type = { @@ -110,9 +116,9 @@ static const TypeInfo ioapic_common_type = { .abstract = true, }; -static void register_types(void) +static void ioapic_common_register_types(void) { type_register_static(&ioapic_common_type); } -type_init(register_types) +type_init(ioapic_common_register_types) diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c index 7dd63da802..ad3931c112 100644 --- a/hw/intc/omap_intc.c +++ b/hw/intc/omap_intc.c @@ -392,6 +392,8 @@ static void omap_intc_class_init(ObjectClass *klass, void *data) k->init = omap_intc_init; dc->reset = omap_inth_reset; dc->props = omap_intc_properties; + /* Reason: pointer property "clk" */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo omap_intc_info = { @@ -637,6 +639,8 @@ static void omap2_intc_class_init(ObjectClass *klass, void *data) k->init = omap2_intc_init; dc->reset = omap_inth_reset; dc->props = omap2_intc_properties; + /* Reason: pointer property "iclk", "fclk" */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo omap2_intc_info = { diff --git a/hw/intc/pl190.c b/hw/intc/pl190.c index 329680da3a..2bf359a76b 100644 --- a/hw/intc/pl190.c +++ b/hw/intc/pl190.c @@ -273,7 +273,6 @@ static void pl190_class_init(ObjectClass *klass, void *data) SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); k->init = pl190_init; - dc->no_user = 1; dc->reset = pl190_reset; dc->vmsd = &vmstate_pl190; } diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c index 9e104eb9a7..55d01008d3 100644 --- a/hw/isa/isa-bus.c +++ b/hw/isa/isa-bus.c @@ -197,7 +197,6 @@ static void isabus_bridge_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->fw_name = "isa"; - dc->no_user = 1; } static const TypeInfo isabus_bridge_info = { diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 19b2198fa6..51ce12dad6 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -644,14 +644,17 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data) dc->reset = ich9_lpc_reset; k->init = ich9_lpc_initfn; dc->vmsd = &vmstate_ich9_lpc; - dc->no_user = 1; k->config_write = ich9_lpc_config_write; dc->desc = "ICH9 LPC bridge"; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_ICH9_8; k->revision = ICH9_A2_LPC_REVISION; k->class_id = PCI_CLASS_BRIDGE_ISA; - + /* + * Reason: part of ICH9 southbridge, needs to be wired up by + * pc_q35_init() + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo ich9_lpc_info = { diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 1a1d4518ce..def6fe3a0f 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -113,8 +113,12 @@ static void piix4_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_INTEL_82371AB_0; k->class_id = PCI_CLASS_BRIDGE_ISA; dc->desc = "ISA bridge"; - dc->no_user = 1; dc->vmsd = &vmstate_piix4; + /* + * Reason: part of PIIX4 southbridge, needs to be wired up, + * e.g. by mips_malta_init() + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo piix4_info = { diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 5fb808630f..e639357db3 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -480,8 +480,12 @@ static void via_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_BRIDGE_ISA; k->revision = 0x40; dc->desc = "ISA bridge"; - dc->no_user = 1; dc->vmsd = &vmstate_via; + /* + * Reason: part of VIA VT82C686 southbridge, needs to be wired up, + * e.g. by mips_fulong2e_init() + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo via_info = { diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c index 3da2e67098..6398514c99 100644 --- a/hw/mips/gt64xxx_pci.c +++ b/hw/mips/gt64xxx_pci.c @@ -1151,12 +1151,18 @@ static int gt64120_pci_init(PCIDevice *d) static void gt64120_pci_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->init = gt64120_pci_init; k->vendor_id = PCI_VENDOR_ID_MARVELL; k->device_id = PCI_DEVICE_ID_MARVELL_GT6412X; k->revision = 0x10; k->class_id = PCI_CLASS_BRIDGE_HOST; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo gt64120_pci_info = { diff --git a/hw/misc/arm_l2x0.c b/hw/misc/arm_l2x0.c index 8e192cdf83..9e220c9a56 100644 --- a/hw/misc/arm_l2x0.c +++ b/hw/misc/arm_l2x0.c @@ -179,7 +179,6 @@ static void l2x0_class_init(ObjectClass *klass, void *data) k->init = l2x0_priv_init; dc->vmsd = &vmstate_l2x0; - dc->no_user = 1; dc->props = l2x0_properties; dc->reset = l2x0_priv_reset; } diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c index 0b5a5644e4..cd5716a46d 100644 --- a/hw/misc/vmport.c +++ b/hw/misc/vmport.c @@ -162,7 +162,8 @@ static void vmport_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = vmport_realizefn; - dc->no_user = 1; + /* Reason: realize sets global port_state */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo vmport_info = { diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c index 78ebbbca72..6a3c86db48 100644 --- a/hw/net/etraxfs_eth.c +++ b/hw/net/etraxfs_eth.c @@ -646,6 +646,8 @@ static void etraxfs_eth_class_init(ObjectClass *klass, void *data) k->init = fs_eth_init; dc->props = etraxfs_eth_properties; + /* Reason: pointer properties "dma_out", "dma_in" */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo etraxfs_eth_info = { diff --git a/hw/net/lance.c b/hw/net/lance.c index e339f029b7..fe18564e1e 100644 --- a/hw/net/lance.c +++ b/hw/net/lance.c @@ -161,6 +161,8 @@ static void lance_class_init(ObjectClass *klass, void *data) dc->reset = lance_reset; dc->vmsd = &vmstate_lance; dc->props = lance_properties; + /* Reason: pointer property "dma" */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo lance_info = { diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index f5dc3ea845..ee96c1681b 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -599,7 +599,6 @@ static void fw_cfg_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = fw_cfg_realize; - dc->no_user = 1; dc->reset = fw_cfg_reset; dc->vmsd = &vmstate_fw_cfg; dc->props = fw_cfg_properties; diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c index e5e3be829f..a6ca940d55 100644 --- a/hw/pci-bridge/dec.c +++ b/hw/pci-bridge/dec.c @@ -116,6 +116,7 @@ static int dec_21154_pci_host_init(PCIDevice *d) static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->init = dec_21154_pci_host_init; k->vendor_id = PCI_VENDOR_ID_DEC; @@ -123,6 +124,11 @@ static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data) k->revision = 0x02; k->class_id = PCI_CLASS_BRIDGE_PCI; k->is_bridge = 1; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo dec_21154_pci_host_info = { diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 92f289f8f9..1b399ddbc3 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -516,11 +516,17 @@ static int pbm_pci_host_init(PCIDevice *d) static void pbm_pci_host_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->init = pbm_pci_host_init; k->vendor_id = PCI_VENDOR_ID_SUN; k->device_id = PCI_DEVICE_ID_SUN_SABRE; k->class_id = PCI_CLASS_BRIDGE_HOST; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo pbm_pci_host_info = { diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index 5086d42c13..902441f10b 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -806,8 +806,12 @@ static void bonito_class_init(ObjectClass *klass, void *data) k->revision = 0x01; k->class_id = PCI_CLASS_BRIDGE_HOST; dc->desc = "Host bridge"; - dc->no_user = 1; dc->vmsd = &vmstate_bonito; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo bonito_info = { @@ -819,11 +823,9 @@ static const TypeInfo bonito_info = { static void bonito_pcihost_class_init(ObjectClass *klass, void *data) { - DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); k->init = bonito_pcihost_initfn; - dc->no_user = 1; } static const TypeInfo bonito_pcihost_info = { diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c index 75b60d36ac..6c7cfdbeb2 100644 --- a/hw/pci-host/grackle.c +++ b/hw/pci-host/grackle.c @@ -130,7 +130,11 @@ static void grackle_pci_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106; k->revision = 0x00; k->class_id = PCI_CLASS_BRIDGE_HOST; - dc->no_user = 1; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo grackle_pci_info = { @@ -143,10 +147,8 @@ static const TypeInfo grackle_pci_info = { static void pci_grackle_class_init(ObjectClass *klass, void *data) { SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); k->init = pci_grackle_init_device; - dc->no_user = 1; } static const TypeInfo grackle_pci_host_info = { diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index 63be7f6cee..cc97150a90 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -635,7 +635,6 @@ static void piix3_class_init(ObjectClass *klass, void *data) dc->desc = "ISA bridge"; dc->vmsd = &vmstate_piix3; - dc->no_user = 1, k->no_hotplug = 1; k->init = piix3_initfn; k->config_write = piix3_write_config; @@ -643,6 +642,11 @@ static void piix3_class_init(ObjectClass *klass, void *data) /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */ k->device_id = PCI_DEVICE_ID_INTEL_82371SB_0; k->class_id = PCI_CLASS_BRIDGE_ISA; + /* + * Reason: part of PIIX3 southbridge, needs to be wired up by + * pc_piix.c's pc_init1() + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo piix3_info = { @@ -659,7 +663,6 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data) dc->desc = "ISA bridge"; dc->vmsd = &vmstate_piix3; - dc->no_user = 1; k->no_hotplug = 1; k->init = piix3_initfn; k->config_write = piix3_write_config_xen; @@ -667,6 +670,11 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data) /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */ k->device_id = PCI_DEVICE_ID_INTEL_82371SB_0; k->class_id = PCI_CLASS_BRIDGE_ISA; + /* + * Reason: part of PIIX3 southbridge, needs to be wired up by + * pc_piix.c's pc_init1() + */ + dc->cannot_instantiate_with_device_add_yet = true; }; static const TypeInfo piix3_xen_info = { @@ -689,8 +697,12 @@ static void i440fx_class_init(ObjectClass *klass, void *data) k->revision = 0x02; k->class_id = PCI_CLASS_BRIDGE_HOST; dc->desc = "Host bridge"; - dc->no_user = 1; dc->vmsd = &vmstate_i440fx; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo i440fx_info = { @@ -727,7 +739,6 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) hc->root_bus_path = i440fx_pcihost_root_bus_path; dc->realize = i440fx_pcihost_realize; dc->fw_name = "pci"; - dc->no_user = 1; dc->props = i440fx_props; } diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c index f00793d819..c80b7cb2f5 100644 --- a/hw/pci-host/ppce500.c +++ b/hw/pci-host/ppce500.c @@ -387,6 +387,11 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_MPC8533E; k->class_id = PCI_CLASS_PROCESSOR_POWERPC; dc->desc = "Host bridge"; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo e500_host_bridge_info = { diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index 0e71fdbfb1..042dc8f225 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -198,7 +198,11 @@ static void raven_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_BRIDGE_HOST; dc->desc = "PReP Host Bridge - Motorola Raven"; dc->vmsd = &vmstate_raven; - dc->no_user = 1; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo raven_info = { @@ -215,7 +219,6 @@ static void raven_pcihost_class_init(ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->realize = raven_pcihost_realizefn; dc->fw_name = "pci"; - dc->no_user = 1; } static const TypeInfo raven_pcihost_info = { diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 81c82404d6..4bc2e0118e 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -403,6 +403,11 @@ static void mch_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_INTEL_Q35_MCH; k->revision = MCH_HOST_BRIDGE_REVISION_DEFAULT; k->class_id = PCI_CLASS_BRIDGE_HOST; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo mch_info = { diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c index adc1d89010..e72fe2a70b 100644 --- a/hw/pci-host/uninorth.c +++ b/hw/pci-host/uninorth.c @@ -351,12 +351,18 @@ static int unin_internal_pci_host_init(PCIDevice *d) static void unin_main_pci_host_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->init = unin_main_pci_host_init; k->vendor_id = PCI_VENDOR_ID_APPLE; k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI; k->revision = 0x00; k->class_id = PCI_CLASS_BRIDGE_HOST; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo unin_main_pci_host_info = { @@ -369,12 +375,18 @@ static const TypeInfo unin_main_pci_host_info = { static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->init = u3_agp_pci_host_init; k->vendor_id = PCI_VENDOR_ID_APPLE; k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP; k->revision = 0x00; k->class_id = PCI_CLASS_BRIDGE_HOST; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo u3_agp_pci_host_info = { @@ -387,12 +399,18 @@ static const TypeInfo u3_agp_pci_host_info = { static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->init = unin_agp_pci_host_init; k->vendor_id = PCI_VENDOR_ID_APPLE; k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP; k->revision = 0x00; k->class_id = PCI_CLASS_BRIDGE_HOST; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo unin_agp_pci_host_info = { @@ -405,12 +423,18 @@ static const TypeInfo unin_agp_pci_host_info = { static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->init = unin_internal_pci_host_init; k->vendor_id = PCI_VENDOR_ID_APPLE; k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI; k->revision = 0x00; k->class_id = PCI_CLASS_BRIDGE_HOST; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo unin_internal_pci_host_info = { diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c index 6b28929d26..71ff0de303 100644 --- a/hw/pci-host/versatile.c +++ b/hw/pci-host/versatile.c @@ -467,11 +467,17 @@ static int versatile_pci_host_init(PCIDevice *d) static void versatile_pci_host_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->init = versatile_pci_host_init; k->vendor_id = PCI_VENDOR_ID_XILINX; k->device_id = PCI_DEVICE_ID_XILINX_XC2VP30; k->class_id = PCI_CLASS_PROCESSOR_CO; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo versatile_pci_host_info = { diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index f72872ebcf..355c3e1b06 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -391,7 +391,7 @@ void pci_bridge_exitfn(PCIDevice *pci_dev) pci_bridge_region_cleanup(s, s->windows); memory_region_destroy(&s->address_space_mem); memory_region_destroy(&s->address_space_io); - /* qbus_free() is called automatically during device deletion */ + /* object_unparent() is called automatically during device deletion */ } /* diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index d2d6f65e6c..4cb78518a3 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -380,6 +380,11 @@ static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data) k->vendor_id = PCI_VENDOR_ID_IBM; k->device_id = PCI_DEVICE_ID_IBM_440GX; k->class_id = PCI_CLASS_BRIDGE_OTHER; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo ppc4xx_host_bridge_info = { diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index fee6195f95..4e33f462d9 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -528,11 +528,9 @@ static int spapr_vio_bridge_init(SysBusDevice *dev) static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data) { - DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); k->init = spapr_vio_bridge_init; - dc->no_user = 1; } static const TypeInfo spapr_vio_bridge_info = { diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index 65d39da314..1a6397b88e 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -182,7 +182,6 @@ static void s390_ipl_class_init(ObjectClass *klass, void *data) k->init = s390_ipl_init; dc->props = s390_ipl_properties; dc->reset = s390_ipl_reset; - dc->no_user = 1; } static const TypeInfo s390_ipl_info = { diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index 6a831114da..46c5ff1898 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -676,11 +676,9 @@ static int s390_virtio_bridge_init(SysBusDevice *dev) static void s390_virtio_bridge_class_init(ObjectClass *klass, void *data) { - DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); k->init = s390_virtio_bridge_init; - dc->no_user = 1; } static const TypeInfo s390_virtio_bridge_info = { diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index ecc80ecaf7..4b6250dda9 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -1283,11 +1283,9 @@ static int virtual_css_bridge_init(SysBusDevice *dev) static void virtual_css_bridge_class_init(ObjectClass *klass, void *data) { - DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); k->init = virtual_css_bridge_init; - dc->no_user = 1; } static const TypeInfo virtual_css_bridge_info = { diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c index c35896d28c..462558b76d 100644 --- a/hw/sd/pl181.c +++ b/hw/sd/pl181.c @@ -506,7 +506,6 @@ static void pl181_class_init(ObjectClass *klass, void *data) sdc->init = pl181_init; k->vmsd = &vmstate_pl181; k->reset = pl181_reset; - k->no_user = 1; } static const TypeInfo pl181_info = { diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c index e81176a11e..a2f6d9e0b6 100644 --- a/hw/sh4/sh_pci.c +++ b/hw/sh4/sh_pci.c @@ -162,10 +162,16 @@ static int sh_pci_host_init(PCIDevice *d) static void sh_pci_host_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->init = sh_pci_host_init; k->vendor_id = PCI_VENDOR_ID_HITACHI; k->device_id = PCI_DEVICE_ID_HITACHI_SH7751R; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo sh_pci_host_info = { diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c index d9f9494f26..35a0a2356f 100644 --- a/hw/timer/arm_mptimer.c +++ b/hw/timer/arm_mptimer.c @@ -274,7 +274,6 @@ static void arm_mptimer_class_init(ObjectClass *klass, void *data) dc->realize = arm_mptimer_realize; dc->vmsd = &vmstate_arm_mptimer; dc->reset = arm_mptimer_reset; - dc->no_user = 1; dc->props = arm_mptimer_properties; } diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index bb3bf98745..2fbbeb1735 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -765,7 +765,6 @@ static void hpet_device_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = hpet_realize; - dc->no_user = 1; dc->reset = hpet_reset; dc->vmsd = &vmstate_hpet; dc->props = hpet_device_properties; diff --git a/hw/timer/i8254_common.c b/hw/timer/i8254_common.c index e8fb971488..9db5c9d129 100644 --- a/hw/timer/i8254_common.c +++ b/hw/timer/i8254_common.c @@ -282,7 +282,12 @@ static void pit_common_class_init(ObjectClass *klass, void *data) dc->realize = pit_common_realize; dc->vmsd = &vmstate_pit_common; - dc->no_user = 1; + /* + * Reason: unlike ordinary ISA devices, the PIT may need to be + * wired to the HPET, and because of that, some wiring is always + * done by board code. + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo pit_common_type = { diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c index be0592b53d..3cfb18a8b3 100644 --- a/hw/timer/m48t59.c +++ b/hw/timer/m48t59.c @@ -750,9 +750,10 @@ static void m48t59_isa_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = m48t59_isa_realize; - dc->no_user = 1; dc->reset = m48t59_reset_isa; dc->props = m48t59_isa_properties; + /* Reason: needs to be wired up by m48t59_init_isa() */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo m48t59_isa_info = { diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index b0116381c0..6fb124fead 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -899,9 +899,10 @@ static void rtc_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = rtc_realizefn; - dc->no_user = 1; dc->vmsd = &vmstate_rtc; dc->props = mc146818rtc_properties; + /* Reason: needs to be wired up by rtc_init() */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo mc146818rtc_info = { diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c index 65928a4819..34d9b44e7e 100644 --- a/hw/timer/pl031.c +++ b/hw/timer/pl031.c @@ -251,7 +251,6 @@ static void pl031_class_init(ObjectClass *klass, void *data) SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); k->init = pl031_init; - dc->no_user = 1; dc->vmsd = &vmstate_pl031; } diff --git a/hw/xen/xen_apic.c b/hw/xen/xen_apic.c index 9f91e0f0c9..63bb7f77c6 100644 --- a/hw/xen/xen_apic.c +++ b/hw/xen/xen_apic.c @@ -36,8 +36,10 @@ static const MemoryRegionOps xen_apic_io_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void xen_apic_init(APICCommonState *s) +static void xen_apic_realize(DeviceState *dev, Error **errp) { + APICCommonState *s = APIC_COMMON(dev); + memory_region_init_io(&s->io_memory, OBJECT(s), &xen_apic_io_ops, s, "xen-apic-msi", APIC_SPACE_SIZE); @@ -72,7 +74,7 @@ static void xen_apic_class_init(ObjectClass *klass, void *data) { APICCommonClass *k = APIC_COMMON_CLASS(klass); - k->init = xen_apic_init; + k->realize = xen_apic_realize; k->set_base = xen_apic_set_base; k->set_tpr = xen_apic_set_tpr; k->get_tpr = xen_apic_get_tpr; diff --git a/include/hw/cpu/icc_bus.h b/include/hw/cpu/icc_bus.h index b5500708dc..98a979fa1c 100644 --- a/include/hw/cpu/icc_bus.h +++ b/include/hw/cpu/icc_bus.h @@ -66,7 +66,7 @@ typedef struct ICCDeviceClass { DeviceClass parent_class; /*< public >*/ - int (*init)(ICCDevice *dev); /* TODO replace with QOM realize */ + DeviceRealize realize; } ICCDeviceClass; #define TYPE_ICC_DEVICE "icc-device" diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h index 1b0a7fbfad..70542a6f43 100644 --- a/include/hw/i386/apic_internal.h +++ b/include/hw/i386/apic_internal.h @@ -80,7 +80,7 @@ typedef struct APICCommonClass { ICCDeviceClass parent_class; - void (*init)(APICCommonState *s); + DeviceRealize realize; void (*set_base)(APICCommonState *s, uint64_t val); void (*set_tpr)(APICCommonState *s, uint8_t val); uint8_t (*get_tpr)(APICCommonState *s); diff --git a/include/hw/i386/ioapic_internal.h b/include/hw/i386/ioapic_internal.h index 25576c819e..3be3352185 100644 --- a/include/hw/i386/ioapic_internal.h +++ b/include/hw/i386/ioapic_internal.h @@ -83,7 +83,8 @@ typedef struct IOAPICCommonState IOAPICCommonState; typedef struct IOAPICCommonClass { SysBusDeviceClass parent_class; - void (*init)(IOAPICCommonState *s, int instance_no); + + DeviceRealize realize; void (*pre_save)(IOAPICCommonState *s); void (*post_load)(IOAPICCommonState *s); } IOAPICCommonClass; diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index f2043a69c2..651c3e54ee 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -97,7 +97,18 @@ typedef struct DeviceClass { const char *fw_name; const char *desc; Property *props; - int no_user; + + /* + * Shall we hide this device model from -device / device_add? + * All devices should support instantiation with device_add, and + * this flag should not exist. But we're not there, yet. Some + * devices fail to instantiate with cryptic error messages. + * Others instantiate, but don't work. Exposing users to such + * behavior would be cruel; this flag serves to protect them. It + * should never be set without a comment explaining why it is set. + * TODO remove once we're there + */ + bool cannot_instantiate_with_device_add_yet; /* callbacks */ void (*reset)(DeviceState *dev); @@ -272,8 +283,6 @@ void qdev_reset_all(DeviceState *dev); void qbus_reset_all(BusState *bus); void qbus_reset_all_fn(void *opaque); -void qbus_free(BusState *bus); - /* This should go away once we get rid of the NULL bus hack */ BusState *sysbus_get_default(void); diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index 692f82e935..77c6f7c037 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -122,8 +122,25 @@ extern PropertyInfo qdev_prop_arraylen; #define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t) +/* + * Please avoid pointer properties. If you must use them, you must + * cover them in their device's class init function as follows: + * + * - If the property must be set, the device cannot be used with + * device_add, so add code like this: + * |* Reason: pointer property "NAME-OF-YOUR-PROP" *| + * DeviceClass *dc = DEVICE_CLASS(class); + * dc->cannot_instantiate_with_device_add_yet = true; + * + * - If the property may safely remain null, document it like this: + * |* + * * Note: pointer property "interrupt_vector" may remain null, thus + * * no need for dc->cannot_instantiate_with_device_add_yet = true; + * *| + */ #define DEFINE_PROP_PTR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*) + #define DEFINE_PROP_CHR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharDriverState*) #define DEFINE_PROP_STRING(_n, _s, _f) \ diff --git a/include/qom/object.h b/include/qom/object.h index a275db2092..e0ff212cb6 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -358,7 +358,8 @@ struct ObjectClass Type type; GSList *interfaces; - const char *cast_cache[OBJECT_CLASS_CAST_CACHE]; + const char *object_cast_cache[OBJECT_CLASS_CAST_CACHE]; + const char *class_cast_cache[OBJECT_CLASS_CAST_CACHE]; ObjectUnparent *unparent; }; @@ -535,6 +536,7 @@ struct InterfaceClass ObjectClass parent_class; /*< private >*/ ObjectClass *concrete_class; + Type interface_type; }; #define TYPE_INTERFACE "interface" diff --git a/qdev-monitor.c b/qdev-monitor.c index dc37a43dd9..ef63cbd7bb 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -87,7 +87,7 @@ static void qdev_print_devinfo(DeviceClass *dc) if (dc->desc) { error_printf(", desc \"%s\"", dc->desc); } - if (dc->no_user) { + if (dc->cannot_instantiate_with_device_add_yet) { error_printf(", no-user"); } error_printf("\n"); @@ -127,7 +127,8 @@ static void qdev_print_devinfos(bool show_no_user) if ((i < DEVICE_CATEGORY_MAX ? !test_bit(i, dc->categories) : !bitmap_empty(dc->categories, DEVICE_CATEGORY_MAX)) - || (!show_no_user && dc->no_user)) { + || (!show_no_user + && dc->cannot_instantiate_with_device_add_yet)) { continue; } if (!cat_printed) { @@ -477,8 +478,9 @@ DeviceState *qdev_device_add(QemuOpts *opts) } } - if (!oc) { - qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type"); + if (!object_class_dynamic_cast(oc, TYPE_DEVICE)) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "'%s' is not a valid device model name", driver); return NULL; } @@ -489,6 +491,11 @@ DeviceState *qdev_device_add(QemuOpts *opts) } dc = DEVICE_CLASS(oc); + if (dc->cannot_instantiate_with_device_add_yet) { + qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", + "pluggable device type"); + return NULL; + } /* find bus */ path = qemu_opt_get(opts, "bus"); @@ -254,7 +254,11 @@ static void cpu_class_init(ObjectClass *klass, void *data) k->gdb_read_register = cpu_common_gdb_read_register; k->gdb_write_register = cpu_common_gdb_write_register; dc->realize = cpu_common_realizefn; - dc->no_user = 1; + /* + * Reason: CPUs still need special care by board code: wiring up + * IRQs, adding reset handlers, halting non-first CPUs, ... + */ + dc->cannot_instantiate_with_device_add_yet = true; } static const TypeInfo cpu_type_info = { diff --git a/qom/object.c b/qom/object.c index fc19cf676a..2aab30b32f 100644 --- a/qom/object.c +++ b/qom/object.c @@ -78,8 +78,11 @@ static GHashTable *type_table_get(void) return type_table; } +static bool enumerating_types; + static void type_table_add(TypeImpl *ti) { + assert(!enumerating_types); g_hash_table_insert(type_table_get(), (void *)ti->name, ti); } @@ -88,7 +91,7 @@ static TypeImpl *type_table_lookup(const char *name) return g_hash_table_lookup(type_table_get(), name); } -static TypeImpl *type_register_internal(const TypeInfo *info) +static TypeImpl *type_new(const TypeInfo *info) { TypeImpl *ti = g_malloc0(sizeof(*ti)); int i; @@ -122,8 +125,15 @@ static TypeImpl *type_register_internal(const TypeInfo *info) } ti->num_interfaces = i; - type_table_add(ti); + return ti; +} + +static TypeImpl *type_register_internal(const TypeInfo *info) +{ + TypeImpl *ti; + ti = type_new(info); + type_table_add(ti); return ti; } @@ -206,22 +216,25 @@ static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type) static void type_initialize(TypeImpl *ti); -static void type_initialize_interface(TypeImpl *ti, const char *parent) +static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type, + TypeImpl *parent_type) { InterfaceClass *new_iface; TypeInfo info = { }; TypeImpl *iface_impl; - info.parent = parent; - info.name = g_strdup_printf("%s::%s", ti->name, info.parent); + info.parent = parent_type->name; + info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name); info.abstract = true; - iface_impl = type_register(&info); + iface_impl = type_new(&info); + iface_impl->parent_type = parent_type; type_initialize(iface_impl); g_free((char *)info.name); new_iface = (InterfaceClass *)iface_impl->class; new_iface->concrete_class = ti->class; + new_iface->interface_type = interface_type; ti->class->interfaces = g_slist_append(ti->class->interfaces, iface_impl->class); @@ -251,8 +264,10 @@ static void type_initialize(TypeImpl *ti) ti->class->interfaces = NULL; for (e = parent->class->interfaces; e; e = e->next) { - ObjectClass *iface = e->data; - type_initialize_interface(ti, object_class_get_name(iface)); + InterfaceClass *iface = e->data; + ObjectClass *klass = OBJECT_CLASS(iface); + + type_initialize_interface(ti, iface->interface_type, klass->type); } for (i = 0; i < ti->num_interfaces; i++) { @@ -269,7 +284,7 @@ static void type_initialize(TypeImpl *ti) continue; } - type_initialize_interface(ti, ti->interfaces[i].typename); + type_initialize_interface(ti, t, t); } } @@ -285,8 +300,6 @@ static void type_initialize(TypeImpl *ti) if (ti->class_init) { ti->class_init(ti->class, ti->class_data); } - - } static void object_init_with_type(Object *obj, TypeImpl *ti) @@ -458,7 +471,7 @@ Object *object_dynamic_cast_assert(Object *obj, const char *typename, Object *inst; for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) { - if (obj->class->cast_cache[i] == typename) { + if (obj->class->object_cast_cache[i] == typename) { goto out; } } @@ -475,9 +488,10 @@ Object *object_dynamic_cast_assert(Object *obj, const char *typename, if (obj && obj == inst) { for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { - obj->class->cast_cache[i - 1] = obj->class->cast_cache[i]; + obj->class->object_cast_cache[i - 1] = + obj->class->object_cast_cache[i]; } - obj->class->cast_cache[i - 1] = typename; + obj->class->object_cast_cache[i - 1] = typename; } out: @@ -547,7 +561,7 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, int i; for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) { - if (class->cast_cache[i] == typename) { + if (class->class_cast_cache[i] == typename) { ret = class; goto out; } @@ -568,9 +582,9 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, #ifdef CONFIG_QOM_CAST_DEBUG if (class && ret == class) { for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { - class->cast_cache[i - 1] = class->cast_cache[i]; + class->class_cast_cache[i - 1] = class->class_cast_cache[i]; } - class->cast_cache[i - 1] = typename; + class->class_cast_cache[i - 1] = typename; } out: #endif @@ -659,7 +673,9 @@ void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), { OCFData data = { fn, implements_type, include_abstract, opaque }; + enumerating_types = true; g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data); + enumerating_types = false; } int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), diff --git a/tests/Makefile b/tests/Makefile index 8d258781b7..0b85a34147 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -52,6 +52,8 @@ check-unit-y += tests/test-int128$(EXESUF) gcov-files-test-int128-y = check-unit-y += tests/test-bitops$(EXESUF) check-unit-y += tests/test-qdev-global-props$(EXESUF) +check-unit-y += tests/check-qom-interface$(EXESUF) +gcov-files-check-qom-interface-y = qom/object.c check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh @@ -138,6 +140,7 @@ test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o $(test-obj-y): QEMU_INCLUDES += -Itests QEMU_CFLAGS += -I$(SRC_PATH)/tests +qom-core-obj = qom/object.o qom/qom-qobject.o qom/container.o tests/test-x86-cpuid.o: QEMU_INCLUDES += -I$(SRC_PATH)/target-i386 @@ -147,6 +150,7 @@ tests/check-qdict$(EXESUF): tests/check-qdict.o libqemuutil.a tests/check-qlist$(EXESUF): tests/check-qlist.o libqemuutil.a tests/check-qfloat$(EXESUF): tests/check-qfloat.o libqemuutil.a tests/check-qjson$(EXESUF): tests/check-qjson.o libqemuutil.a libqemustub.a +tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(qom-core-obj) libqemuutil.a tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(block-obj-y) libqemuutil.a libqemustub.a tests/test-aio$(EXESUF): tests/test-aio.o $(block-obj-y) libqemuutil.a libqemustub.a tests/test-throttle$(EXESUF): tests/test-throttle.o $(block-obj-y) libqemuutil.a libqemustub.a @@ -160,7 +164,7 @@ tests/test-int128$(EXESUF): tests/test-int128.o tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \ hw/core/qdev.o hw/core/qdev-properties.o \ hw/core/irq.o \ - qom/object.o qom/container.o qom/qom-qobject.o \ + $(qom-core-obj) \ $(test-qapi-obj-y) \ libqemuutil.a libqemustub.a diff --git a/tests/check-qom-interface.c b/tests/check-qom-interface.c new file mode 100644 index 0000000000..f06380ef14 --- /dev/null +++ b/tests/check-qom-interface.c @@ -0,0 +1,105 @@ +/* + * QOM interface test. + * + * Copyright (C) 2013 Red Hat Inc. + * + * Authors: + * Igor Mammedov <imammedo@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + */ +#include <glib.h> + +#include "qom/object.h" +#include "qemu/module.h" + + +#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) +#define TEST_IF(obj) \ + INTERFACE_CHECK(TestIf, (obj), TYPE_TEST_IF) + +typedef struct TestIf { + Object parent_obj; +} TestIf; + +typedef struct TestIfClass { + InterfaceClass parent_class; + + uint32_t test; +} TestIfClass; + +static const TypeInfo test_if_info = { + .name = TYPE_TEST_IF, + .parent = TYPE_INTERFACE, + .class_size = sizeof(TestIfClass), +}; + +#define PATTERN 0xFAFBFCFD + +static void test_class_init(ObjectClass *oc, void *data) +{ + TestIfClass *tc = TEST_IF_CLASS(oc); + + g_assert(tc); + tc->test = PATTERN; +} + +#define TYPE_DIRECT_IMPL "direct-impl" + +static const TypeInfo direct_impl_info = { + .name = TYPE_DIRECT_IMPL, + .parent = TYPE_OBJECT, + .class_init = test_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_TEST_IF }, + { } + } +}; + +#define TYPE_INTERMEDIATE_IMPL "intermediate-impl" + +static const TypeInfo intermediate_impl_info = { + .name = TYPE_INTERMEDIATE_IMPL, + .parent = TYPE_DIRECT_IMPL, +}; + +static void test_interface_impl(const char *type) +{ + Object *obj = object_new(type); + TestIf *iobj = TEST_IF(obj); + TestIfClass *ioc = TEST_IF_GET_CLASS(iobj); + + g_assert(iobj); + g_assert(ioc->test == PATTERN); +} + +static void interface_direct_test(void) +{ + test_interface_impl(TYPE_DIRECT_IMPL); +} + +static void interface_intermediate_test(void) +{ + test_interface_impl(TYPE_INTERMEDIATE_IMPL); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + module_call_init(MODULE_INIT_QOM); + type_register_static(&test_if_info); + type_register_static(&direct_impl_info); + type_register_static(&intermediate_impl_info); + + g_test_add_func("/qom/interface/direct_impl", interface_direct_test); + g_test_add_func("/qom/interface/intermediate_impl", + interface_intermediate_test); + + return g_test_run(); +} |