aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/acpi/piix4.c2
-rw-r--r--hw/arm/spitz.c2
-rw-r--r--hw/audio/marvell_88w8618.c2
-rw-r--r--hw/audio/pcspk.c2
-rw-r--r--hw/core/or-irq.c2
-rw-r--r--hw/core/qdev.c1
-rw-r--r--hw/core/register.c2
-rw-r--r--hw/core/sysbus.c11
-rw-r--r--hw/dma/i8257.c2
-rw-r--r--hw/dma/sparc32_dma.c2
-rw-r--r--hw/gpio/omap_gpio.c4
-rw-r--r--hw/i2c/omap_i2c.c2
-rw-r--r--hw/i2c/smbus_eeprom.c2
-rw-r--r--hw/i2c/smbus_ich9.c2
-rw-r--r--hw/i386/amd_iommu.c2
-rw-r--r--hw/i386/intel_iommu.c2
-rw-r--r--hw/i386/pc.c2
-rw-r--r--hw/input/vmmouse.c2
-rw-r--r--hw/intc/apic_common.c2
-rw-r--r--hw/intc/etraxfs_pic.c2
-rw-r--r--hw/intc/grlib_irqmp.c2
-rw-r--r--hw/intc/i8259_common.c2
-rw-r--r--hw/intc/nios2_iic.c2
-rw-r--r--hw/intc/omap_intc.c4
-rw-r--r--hw/isa/lpc_ich9.c2
-rw-r--r--hw/isa/piix4.c2
-rw-r--r--hw/isa/vt82c686.c2
-rw-r--r--hw/mips/gt64xxx_pci.c2
-rw-r--r--hw/misc/vmport.c2
-rw-r--r--hw/net/dp8393x.c2
-rw-r--r--hw/net/etraxfs_eth.c2
-rw-r--r--hw/net/fsl_etsec/etsec.c2
-rw-r--r--hw/net/lance.c2
-rw-r--r--hw/pci-bridge/dec.c2
-rw-r--r--hw/pci-bridge/pci_expander_bridge.c2
-rw-r--r--hw/pci-host/apb.c2
-rw-r--r--hw/pci-host/bonito.c2
-rw-r--r--hw/pci-host/gpex.c2
-rw-r--r--hw/pci-host/grackle.c2
-rw-r--r--hw/pci-host/piix.c6
-rw-r--r--hw/pci-host/ppce500.c2
-rw-r--r--hw/pci-host/prep.c2
-rw-r--r--hw/pci-host/q35.c4
-rw-r--r--hw/pci-host/uninorth.c8
-rw-r--r--hw/pci-host/versatile.c2
-rw-r--r--hw/pci-host/xilinx-pcie.c2
-rw-r--r--hw/ppc/ppc4xx_pci.c2
-rw-r--r--hw/ppc/spapr_drc.c2
-rw-r--r--hw/ppc/spapr_pci.c2
-rw-r--r--hw/s390x/s390-pci-bus.c1
-rw-r--r--hw/sd/milkymist-memcard.c2
-rw-r--r--hw/sd/pl181.c2
-rw-r--r--hw/sh4/sh_pci.c2
-rw-r--r--hw/timer/i8254_common.c2
-rw-r--r--hw/timer/mc146818rtc.c2
-rw-r--r--hw/vfio/amd-xgbe.c2
-rw-r--r--hw/vfio/calxeda-xgmac.c2
-rw-r--r--hw/xen/xen_backend.c2
-rw-r--r--include/hw/qdev-core.h9
-rw-r--r--include/hw/qdev-properties.h4
-rw-r--r--monitor.c2
-rw-r--r--qdev-monitor.c6
-rw-r--r--qom/cpu.c2
-rw-r--r--target/i386/cpu.c2
-rw-r--r--tests/test-x86-cpuid-compat.c111
65 files changed, 206 insertions, 69 deletions
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index a553a7e110..f4fd5907b8 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -700,7 +700,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data)
* Reason: part of PIIX4 southbridge, needs to be wired up,
* e.g. by mips_malta_init()
*/
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
dc->hotpluggable = false;
hc->plug = piix4_device_plug_cb;
hc->unplug_request = piix4_device_unplug_request_cb;
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index fe2d5a764c..324626847c 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -1076,7 +1076,7 @@ static void sl_nand_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_sl_nand_info;
dc->props = sl_nand_properties;
/* Reason: init() method uses drive_get() */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo sl_nand_info = {
diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c
index 511b004287..4f65f8c199 100644
--- a/hw/audio/marvell_88w8618.c
+++ b/hw/audio/marvell_88w8618.c
@@ -292,7 +292,7 @@ static void mv88w8618_audio_class_init(ObjectClass *klass, void *data)
dc->vmsd = &mv88w8618_audio_vmsd;
dc->props = mv88w8618_audio_properties;
/* Reason: pointer property "wm8750" */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo mv88w8618_audio_info = {
diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
index 798002277b..9b99358d87 100644
--- a/hw/audio/pcspk.c
+++ b/hw/audio/pcspk.c
@@ -223,7 +223,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_spk;
dc->props = pcspk_properties;
/* Reason: realize sets global pcspk_state */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo pcspk_info = {
diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c
index 1485d5b285..f9d76c4641 100644
--- a/hw/core/or-irq.c
+++ b/hw/core/or-irq.c
@@ -91,7 +91,7 @@ static void or_irq_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_or_irq;
/* Reason: Needs to be wired up to work, e.g. see stm32f205_soc.c */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo or_irq_type_info = {
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 02b632f6b3..1863db9d0a 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -1118,6 +1118,7 @@ static void device_class_init(ObjectClass *class, void *data)
* should override it in their class_init()
*/
dc->hotpluggable = true;
+ dc->user_creatable = true;
}
void device_reset(DeviceState *dev)
diff --git a/hw/core/register.c b/hw/core/register.c
index dc335a79a9..da38ef3a54 100644
--- a/hw/core/register.c
+++ b/hw/core/register.c
@@ -288,7 +288,7 @@ static void register_class_init(ObjectClass *oc, void *data)
DeviceClass *dc = DEVICE_CLASS(oc);
/* Reason: needs to be wired up to work */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo register_info = {
diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c
index c0f560b289..5d0887f499 100644
--- a/hw/core/sysbus.c
+++ b/hw/core/sysbus.c
@@ -326,6 +326,17 @@ 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 a 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 will probably not work
+ *
+ * However, a few machines can handle device_add/-device with
+ * a few specific sysbus devices. In those cases, the device
+ * subclass needs to override it and set user_creatable=true.
+ */
+ k->user_creatable = false;
}
static const TypeInfo sysbus_device_type_info = {
diff --git a/hw/dma/i8257.c b/hw/dma/i8257.c
index 8bd82e8bc8..bd23e893bf 100644
--- a/hw/dma/i8257.c
+++ b/hw/dma/i8257.c
@@ -601,7 +601,7 @@ static void i8257_class_init(ObjectClass *klass, void *data)
idc->schedule = i8257_dma_schedule;
idc->register_channel = i8257_dma_register_channel;
/* Reason: needs to be wired up by isa_bus_dma() to work */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo i8257_info = {
diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c
index 9d545e412e..9c6bdc6295 100644
--- a/hw/dma/sparc32_dma.c
+++ b/hw/dma/sparc32_dma.c
@@ -305,7 +305,7 @@ static void sparc32_dma_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_dma;
dc->props = sparc32_dma_properties;
/* Reason: pointer property "iommu_opaque" */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo sparc32_dma_info = {
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
index dabef4a119..1df394eb12 100644
--- a/hw/gpio/omap_gpio.c
+++ b/hw/gpio/omap_gpio.c
@@ -773,7 +773,7 @@ static void omap_gpio_class_init(ObjectClass *klass, void *data)
dc->reset = omap_gpif_reset;
dc->props = omap_gpio_properties;
/* Reason: pointer property "clk" */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo omap_gpio_info = {
@@ -804,7 +804,7 @@ static void omap2_gpio_class_init(ObjectClass *klass, void *data)
dc->reset = omap2_gpif_reset;
dc->props = omap2_gpio_properties;
/* Reason: pointer properties "iclk", "fclk0", ..., "fclk5" */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo omap2_gpio_info = {
diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c
index f7c92ea00c..f6e80bee25 100644
--- a/hw/i2c/omap_i2c.c
+++ b/hw/i2c/omap_i2c.c
@@ -491,7 +491,7 @@ static void omap_i2c_class_init(ObjectClass *klass, void *data)
dc->props = omap_i2c_properties;
dc->reset = omap_i2c_reset;
/* Reason: pointer properties "iclk", "fclk" */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
dc->realize = omap_i2c_realize;
}
diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c
index 5b7bd891bc..b13ec0fe7a 100644
--- a/hw/i2c/smbus_eeprom.c
+++ b/hw/i2c/smbus_eeprom.c
@@ -123,7 +123,7 @@ static void smbus_eeprom_class_initfn(ObjectClass *klass, void *data)
sc->read_data = eeprom_read_data;
dc->props = smbus_eeprom_properties;
/* Reason: pointer property "data" */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo smbus_eeprom_info = {
diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c
index 48fab22625..ea51e09186 100644
--- a/hw/i2c/smbus_ich9.c
+++ b/hw/i2c/smbus_ich9.c
@@ -103,7 +103,7 @@ static void ich9_smb_class_init(ObjectClass *klass, void *data)
* Reason: part of ICH9 southbridge, needs to be wired up by
* pc_q35_init()
*/
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
I2CBus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base)
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index f86a40aa30..efcc93cbfd 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -1186,6 +1186,8 @@ static void amdvi_class_init(ObjectClass *klass, void* data)
dc->vmsd = &vmstate_amdvi;
dc->hotpluggable = false;
dc_class->realize = amdvi_realize;
+ /* Supported by the pc-q35-* machine types */
+ dc->user_creatable = true;
}
static const TypeInfo amdvi = {
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 02f047c8e3..327a46cd19 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3009,6 +3009,8 @@ static void vtd_class_init(ObjectClass *klass, void *data)
dc->hotpluggable = false;
x86_class->realize = vtd_realize;
x86_class->int_remap = vtd_int_remap;
+ /* Supported by the pc-q35-* machine types */
+ dc->user_creatable = true;
}
static const TypeInfo vtd_info = {
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e36a375683..95a5537a2c 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -597,7 +597,7 @@ static void port92_class_initfn(ObjectClass *klass, void *data)
* wiring: its A20 output line needs to be wired up by
* port92_init().
*/
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo port92_info = {
diff --git a/hw/input/vmmouse.c b/hw/input/vmmouse.c
index 6d15a887c6..4747da9a8d 100644
--- a/hw/input/vmmouse.c
+++ b/hw/input/vmmouse.c
@@ -286,7 +286,7 @@ static void vmmouse_class_initfn(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_vmmouse;
dc->props = vmmouse_properties;
/* Reason: pointer property "ps2_mouse" */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo vmmouse_info = {
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index c3829e31b5..1ef56f8d10 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -501,7 +501,7 @@ static void apic_common_class_init(ObjectClass *klass, void *data)
* Reason: APIC and CPU need to be wired up by
* x86_cpu_apic_create()
*/
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo apic_common_type = {
diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c
index 64a6f4b4ba..1bfde2f09e 100644
--- a/hw/intc/etraxfs_pic.c
+++ b/hw/intc/etraxfs_pic.c
@@ -173,7 +173,7 @@ static void etraxfs_pic_class_init(ObjectClass *klass, void *data)
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;
+ * no need for dc->user_creatable = false;
*/
}
diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c
index ac7e63f38b..94659ee256 100644
--- a/hw/intc/grlib_irqmp.c
+++ b/hw/intc/grlib_irqmp.c
@@ -360,7 +360,7 @@ static void grlib_irqmp_class_init(ObjectClass *klass, void *data)
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;
+ dc->user_creatable = false;
dc->realize = grlib_irqmp_realize;
}
diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c
index d9a5e8b217..c2fd563b5b 100644
--- a/hw/intc/i8259_common.c
+++ b/hw/intc/i8259_common.c
@@ -144,7 +144,7 @@ static void pic_common_class_init(ObjectClass *klass, void *data)
* wiring of the slave to the master is hard-coded in device model
* code.
*/
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo pic_common_type = {
diff --git a/hw/intc/nios2_iic.c b/hw/intc/nios2_iic.c
index 190b6fdbf3..016426f964 100644
--- a/hw/intc/nios2_iic.c
+++ b/hw/intc/nios2_iic.c
@@ -80,7 +80,7 @@ static void altera_iic_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
/* Reason: needs to be wired up, e.g. by nios2_10m50_ghrd_init() */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
dc->realize = altera_iic_realize;
}
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
index 877be67971..ccdda89dab 100644
--- a/hw/intc/omap_intc.c
+++ b/hw/intc/omap_intc.c
@@ -401,7 +401,7 @@ static void omap_intc_class_init(ObjectClass *klass, void *data)
dc->reset = omap_inth_reset;
dc->props = omap_intc_properties;
/* Reason: pointer property "clk" */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
dc->realize = omap_intc_realize;
}
@@ -656,7 +656,7 @@ static void omap2_intc_class_init(ObjectClass *klass, void *data)
dc->reset = omap_inth_reset;
dc->props = omap2_intc_properties;
/* Reason: pointer property "iclk", "fclk" */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
dc->realize = omap2_intc_realize;
}
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index a0866c3856..e2215dcf4d 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -805,7 +805,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data)
* Reason: part of ICH9 southbridge, needs to be wired up by
* pc_q35_init()
*/
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
hc->plug = ich9_pm_device_plug_cb;
hc->unplug_request = ich9_pm_device_unplug_request_cb;
hc->unplug = ich9_pm_device_unplug_cb;
diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c
index 5500fcc4d6..f811eba59d 100644
--- a/hw/isa/piix4.c
+++ b/hw/isa/piix4.c
@@ -123,7 +123,7 @@ static void piix4_class_init(ObjectClass *klass, void *data)
* Reason: part of PIIX4 southbridge, needs to be wired up,
* e.g. by mips_malta_init()
*/
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
dc->hotpluggable = false;
}
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index 41d5254f8e..50dc83df77 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -494,7 +494,7 @@ static void via_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo via_info = {
diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c
index 4811843ab6..e8b2eef688 100644
--- a/hw/mips/gt64xxx_pci.c
+++ b/hw/mips/gt64xxx_pci.c
@@ -1224,7 +1224,7 @@ static void gt64120_pci_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo gt64120_pci_info = {
diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index be40930b8b..165500223f 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -163,7 +163,7 @@ static void vmport_class_initfn(ObjectClass *klass, void *data)
dc->realize = vmport_realizefn;
/* Reason: realize sets global port_state */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo vmport_info = {
diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index efa33ad40a..b53fcaa8bc 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -934,7 +934,7 @@ static void dp8393x_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_dp8393x;
dc->props = dp8393x_properties;
/* Reason: dma_mr property can't be set */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo dp8393x_info = {
diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c
index efaa49faae..013c8d0a41 100644
--- a/hw/net/etraxfs_eth.c
+++ b/hw/net/etraxfs_eth.c
@@ -630,7 +630,7 @@ 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;
+ dc->user_creatable = false;
}
static const TypeInfo etraxfs_eth_info = {
diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c
index aa2b0d5a85..9da1932970 100644
--- a/hw/net/fsl_etsec/etsec.c
+++ b/hw/net/fsl_etsec/etsec.c
@@ -416,6 +416,8 @@ static void etsec_class_init(ObjectClass *klass, void *data)
dc->realize = etsec_realize;
dc->reset = etsec_reset;
dc->props = etsec_properties;
+ /* Supported by ppce500 machine */
+ dc->user_creatable = true;
}
static TypeInfo etsec_info = {
diff --git a/hw/net/lance.c b/hw/net/lance.c
index 573d724bcf..92b0c68274 100644
--- a/hw/net/lance.c
+++ b/hw/net/lance.c
@@ -165,7 +165,7 @@ static void lance_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_lance;
dc->props = lance_properties;
/* Reason: pointer property "dma" */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo lance_info = {
diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c
index 840c96198a..cca93620ac 100644
--- a/hw/pci-bridge/dec.c
+++ b/hw/pci-bridge/dec.c
@@ -128,7 +128,7 @@ static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo dec_21154_pci_host_info = {
diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c
index 6ac187fa32..ff59abf208 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -150,7 +150,7 @@ static void pxb_host_class_init(ObjectClass *class, void *data)
dc->fw_name = "pci";
/* Reason: Internal part of the pxb/pxb-pcie device, not usable by itself */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address;
hc->root_bus_path = pxb_host_root_bus_path;
}
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 653e711121..edc88f4c65 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -810,7 +810,7 @@ static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo pbm_pci_host_info = {
diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
index 1999ece590..85a3bb0dd2 100644
--- a/hw/pci-host/bonito.c
+++ b/hw/pci-host/bonito.c
@@ -825,7 +825,7 @@ static void bonito_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo bonito_info = {
diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c
index 66055ee5cc..e2629ce70d 100644
--- a/hw/pci-host/gpex.c
+++ b/hw/pci-host/gpex.c
@@ -136,7 +136,7 @@ static void gpex_root_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo gpex_root_info = {
diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c
index 2c8acdaaca..2e281f6155 100644
--- a/hw/pci-host/grackle.c
+++ b/hw/pci-host/grackle.c
@@ -134,7 +134,7 @@ static void grackle_pci_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo grackle_pci_info = {
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index bf4221d4bf..2d02de12d9 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -685,7 +685,7 @@ static void pci_piix3_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo piix3_pci_type_info = {
@@ -739,7 +739,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
dc->hotpluggable = false;
}
@@ -868,7 +868,7 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
dc->fw_name = "pci";
dc->props = i440fx_props;
/* Reason: needs to be wired up by pc_init1 */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo i440fx_pcihost_info = {
diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
index e502bc0505..becc0eeb76 100644
--- a/hw/pci-host/ppce500.c
+++ b/hw/pci-host/ppce500.c
@@ -508,7 +508,7 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo e500_host_bridge_info = {
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
index 260a119a9e..900a6edfcf 100644
--- a/hw/pci-host/prep.c
+++ b/hw/pci-host/prep.c
@@ -364,7 +364,7 @@ static void raven_class_init(ObjectClass *klass, void *data)
* Reason: 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;
+ dc->user_creatable = false;
}
static const TypeInfo raven_info = {
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 344f77b10c..cd5c49616e 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -156,7 +156,7 @@ static void q35_host_class_init(ObjectClass *klass, void *data)
dc->realize = q35_host_realize;
dc->props = mch_props;
/* Reason: needs to be wired up by pc_q35_init */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->fw_name = "pci";
}
@@ -549,7 +549,7 @@ static void mch_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo mch_info = {
diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c
index df342ac3cb..6cf5e59f86 100644
--- a/hw/pci-host/uninorth.c
+++ b/hw/pci-host/uninorth.c
@@ -366,7 +366,7 @@ static void unin_main_pci_host_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo unin_main_pci_host_info = {
@@ -390,7 +390,7 @@ static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo u3_agp_pci_host_info = {
@@ -414,7 +414,7 @@ static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo unin_agp_pci_host_info = {
@@ -438,7 +438,7 @@ static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo unin_internal_pci_host_info = {
diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
index 27fde46126..aa1fdf75fd 100644
--- a/hw/pci-host/versatile.c
+++ b/hw/pci-host/versatile.c
@@ -479,7 +479,7 @@ static void versatile_pci_host_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo versatile_pci_host_info = {
diff --git a/hw/pci-host/xilinx-pcie.c b/hw/pci-host/xilinx-pcie.c
index 8b71e2d950..a968cea2af 100644
--- a/hw/pci-host/xilinx-pcie.c
+++ b/hw/pci-host/xilinx-pcie.c
@@ -309,7 +309,7 @@ static void xilinx_pcie_root_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo xilinx_pcie_root_info = {
diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c
index dc19682970..6953f8b9ac 100644
--- a/hw/ppc/ppc4xx_pci.c
+++ b/hw/ppc/ppc4xx_pci.c
@@ -351,7 +351,7 @@ static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo ppc4xx_host_bridge_info = {
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index a1cdc875b1..9fa5545991 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -675,7 +675,7 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
/*
* Reason: it crashes FIXME find and document the real reason
*/
- dk->cannot_instantiate_with_device_add_yet = true;
+ dk->user_creatable = false;
}
static const TypeInfo spapr_dr_connector_info = {
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index e7567e2e8f..a7cff32bbf 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1994,6 +1994,8 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
dc->props = spapr_phb_properties;
dc->reset = spapr_phb_reset;
dc->vmsd = &vmstate_spapr_pci;
+ /* Supported by TYPE_SPAPR_MACHINE */
+ dc->user_creatable = true;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
hp->plug = spapr_phb_hot_plug_child;
hp->unplug = spapr_phb_hot_unplug_child;
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index a8a1bab50a..66a6fbeb8c 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -872,7 +872,6 @@ static void s390_pcihost_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
- dc->cannot_instantiate_with_device_add_yet = true;
dc->reset = s390_pcihost_reset;
k->init = s390_pcihost_init;
hc->plug = s390_pcihost_hot_plug;
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index 1f2f0ed44a..4008c81002 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -299,7 +299,7 @@ static void milkymist_memcard_class_init(ObjectClass *klass, void *data)
dc->reset = milkymist_memcard_reset;
dc->vmsd = &vmstate_milkymist_memcard;
/* Reason: init() method uses drive_get_next() */
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo milkymist_memcard_info = {
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 82c63a4fb5..55c8098ecd 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -515,7 +515,7 @@ static void pl181_class_init(ObjectClass *klass, void *data)
k->vmsd = &vmstate_pl181;
k->reset = pl181_reset;
/* Reason: init() method uses drive_get_next() */
- k->cannot_instantiate_with_device_add_yet = true;
+ k->user_creatable = false;
k->realize = pl181_realize;
}
diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c
index 1747628f3d..38395c082b 100644
--- a/hw/sh4/sh_pci.c
+++ b/hw/sh4/sh_pci.c
@@ -171,7 +171,7 @@ static void sh_pci_host_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo sh_pci_host_info = {
diff --git a/hw/timer/i8254_common.c b/hw/timer/i8254_common.c
index e18299a482..976d5200f1 100644
--- a/hw/timer/i8254_common.c
+++ b/hw/timer/i8254_common.c
@@ -287,7 +287,7 @@ static void pit_common_class_init(ObjectClass *klass, void *data)
* wired to the HPET, and because of that, some wiring is always
* done by board code.
*/
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo pit_common_type = {
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 4165450250..93de3e1cc5 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -973,7 +973,7 @@ static void rtc_class_initfn(ObjectClass *klass, void *data)
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;
+ dc->user_creatable = false;
}
static void rtc_finalize(Object *obj)
diff --git a/hw/vfio/amd-xgbe.c b/hw/vfio/amd-xgbe.c
index 2c60310cf9..fab196cebf 100644
--- a/hw/vfio/amd-xgbe.c
+++ b/hw/vfio/amd-xgbe.c
@@ -38,6 +38,8 @@ static void vfio_amd_xgbe_class_init(ObjectClass *klass, void *data)
dc->realize = amd_xgbe_realize;
dc->desc = "VFIO AMD XGBE";
dc->vmsd = &vfio_platform_amd_xgbe_vmstate;
+ /* Supported by TYPE_VIRT_MACHINE */
+ dc->user_creatable = true;
}
static const TypeInfo vfio_amd_xgbe_dev_info = {
diff --git a/hw/vfio/calxeda-xgmac.c b/hw/vfio/calxeda-xgmac.c
index bb15d588e5..7bb17af7ad 100644
--- a/hw/vfio/calxeda-xgmac.c
+++ b/hw/vfio/calxeda-xgmac.c
@@ -38,6 +38,8 @@ static void vfio_calxeda_xgmac_class_init(ObjectClass *klass, void *data)
dc->realize = calxeda_xgmac_realize;
dc->desc = "VFIO Calxeda XGMAC";
dc->vmsd = &vfio_platform_calxeda_xgmac_vmstate;
+ /* Supported by TYPE_VIRT_MACHINE */
+ dc->user_creatable = true;
}
static const TypeInfo vfio_calxeda_xgmac_dev_info = {
diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
index 2cac47d6c4..3570f37e56 100644
--- a/hw/xen/xen_backend.c
+++ b/hw/xen/xen_backend.c
@@ -619,6 +619,8 @@ static void xendev_class_init(ObjectClass *klass, void *data)
dc->props = xendev_properties;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ /* xen-backend devices can be plugged/unplugged dynamically */
+ dc->user_creatable = true;
}
static const TypeInfo xendev_type_info = {
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 4bf86b0ad8..e69489ec6c 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -103,16 +103,17 @@ typedef struct DeviceClass {
Property *props;
/*
- * Shall we hide this device model from -device / device_add?
+ * Can this device be instantiated with -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.
+ * behavior would be cruel; clearing this flag will protect them.
+ * It should never be cleared without a comment explaining why it
+ * is cleared.
* TODO remove once we're there
*/
- bool cannot_instantiate_with_device_add_yet;
+ bool user_creatable;
bool hotpluggable;
/* callbacks */
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 1d69fa7a8f..d206fc93dd 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -134,12 +134,12 @@ extern PropertyInfo qdev_prop_arraylen;
* 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;
+ * dc->user_creatable = false;
*
* - 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;
+ * * no need for dc->user_creatable = false;
* *|
*/
#define DEFINE_PROP_PTR(_n, _s, _f) \
diff --git a/monitor.c b/monitor.c
index 078cba5c86..afbacfe1cb 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3254,7 +3254,7 @@ void device_add_completion(ReadLineState *rs, int nb_args, const char *str)
TYPE_DEVICE);
name = object_class_get_name(OBJECT_CLASS(dc));
- if (!dc->cannot_instantiate_with_device_add_yet
+ if (dc->user_creatable
&& !strncmp(name, str, len)) {
readline_add_completion(rs, name);
}
diff --git a/qdev-monitor.c b/qdev-monitor.c
index e61d596ef7..3ecbf0bd25 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -114,7 +114,7 @@ static void qdev_print_devinfo(DeviceClass *dc)
if (dc->desc) {
error_printf(", desc \"%s\"", dc->desc);
}
- if (dc->cannot_instantiate_with_device_add_yet) {
+ if (!dc->user_creatable) {
error_printf(", no-user");
}
error_printf("\n");
@@ -156,7 +156,7 @@ static void qdev_print_devinfos(bool show_no_user)
? !test_bit(i, dc->categories)
: !bitmap_empty(dc->categories, DEVICE_CATEGORY_MAX))
|| (!show_no_user
- && dc->cannot_instantiate_with_device_add_yet)) {
+ && !dc->user_creatable)) {
continue;
}
if (!cat_printed) {
@@ -241,7 +241,7 @@ static DeviceClass *qdev_get_device_class(const char **driver, Error **errp)
}
dc = DEVICE_CLASS(oc);
- if (dc->cannot_instantiate_with_device_add_yet ||
+ if (!dc->user_creatable ||
(qdev_hotplug && !dc->hotpluggable)) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
"pluggable device type");
diff --git a/qom/cpu.c b/qom/cpu.c
index f9111a02ba..50698767dd 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -453,7 +453,7 @@ static void cpu_class_init(ObjectClass *klass, void *data)
* 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;
+ dc->user_creatable = false;
}
static const TypeInfo cpu_type_info = {
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 5e768404a1..a41d595c23 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -4075,7 +4075,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
cc->cpu_exec_enter = x86_cpu_exec_enter;
cc->cpu_exec_exit = x86_cpu_exec_exit;
- dc->cannot_instantiate_with_device_add_yet = false;
+ dc->user_creatable = true;
}
static const TypeInfo x86_cpu_type_info = {
diff --git a/tests/test-x86-cpuid-compat.c b/tests/test-x86-cpuid-compat.c
index 79a2e69a28..6c71e46391 100644
--- a/tests/test-x86-cpuid-compat.c
+++ b/tests/test-x86-cpuid-compat.c
@@ -1,6 +1,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qapi/qmp/qlist.h"
+#include "qapi/qmp/qstring.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qint.h"
#include "qapi/qmp/qbool.h"
@@ -78,6 +79,90 @@ static void add_cpuid_test(const char *name, const char *cmdline,
qtest_add_data_func(name, args, test_cpuid_prop);
}
+
+/* Parameters to a add_feature_test() test case */
+typedef struct FeatureTestArgs {
+ /* cmdline to start QEMU */
+ const char *cmdline;
+ /*
+ * cpuid-input-eax and cpuid-input-ecx values to look for,
+ * in "feature-words" and "filtered-features" properties.
+ */
+ uint32_t in_eax, in_ecx;
+ /* The register name to look for, in the X86CPUFeatureWordInfo array */
+ const char *reg;
+ /* The bit to check in X86CPUFeatureWordInfo.features */
+ int bitnr;
+ /* The expected value for the bit in (X86CPUFeatureWordInfo.features) */
+ bool expected_value;
+} FeatureTestArgs;
+
+/* Get the value for a feature word in a X86CPUFeatureWordInfo list */
+static uint32_t get_feature_word(QList *features, uint32_t eax, uint32_t ecx,
+ const char *reg)
+{
+ const QListEntry *e;
+
+ for (e = qlist_first(features); e; e = qlist_next(e)) {
+ QDict *w = qobject_to_qdict(qlist_entry_obj(e));
+ const char *rreg = qdict_get_str(w, "cpuid-register");
+ uint32_t reax = qdict_get_int(w, "cpuid-input-eax");
+ bool has_ecx = qdict_haskey(w, "cpuid-input-ecx");
+ uint32_t recx = 0;
+
+ if (has_ecx) {
+ recx = qdict_get_int(w, "cpuid-input-ecx");
+ }
+ if (eax == reax && (!has_ecx || ecx == recx) && !strcmp(rreg, reg)) {
+ return qint_get_int(qobject_to_qint(qdict_get(w, "features")));
+ }
+ }
+ return 0;
+}
+
+static void test_feature_flag(const void *data)
+{
+ const FeatureTestArgs *args = data;
+ char *path;
+ QList *present, *filtered;
+ uint32_t value;
+
+ qtest_start(args->cmdline);
+ path = get_cpu0_qom_path();
+ present = qobject_to_qlist(qom_get(path, "feature-words"));
+ filtered = qobject_to_qlist(qom_get(path, "filtered-features"));
+ value = get_feature_word(present, args->in_eax, args->in_ecx, args->reg);
+ value |= get_feature_word(filtered, args->in_eax, args->in_ecx, args->reg);
+ qtest_end();
+
+ g_assert(!!(value & (1U << args->bitnr)) == args->expected_value);
+
+ QDECREF(present);
+ QDECREF(filtered);
+ g_free(path);
+}
+
+/*
+ * Add test case to ensure that a given feature flag is set in
+ * either "feature-words" or "filtered-features", when running QEMU
+ * using cmdline
+ */
+static FeatureTestArgs *add_feature_test(const char *name, const char *cmdline,
+ uint32_t eax, uint32_t ecx,
+ const char *reg, int bitnr,
+ bool expected_value)
+{
+ FeatureTestArgs *args = g_new0(FeatureTestArgs, 1);
+ args->cmdline = cmdline;
+ args->in_eax = eax;
+ args->in_ecx = ecx;
+ args->reg = reg;
+ args->bitnr = bitnr;
+ args->expected_value = expected_value;
+ qtest_add_data_func(name, args, test_feature_flag);
+ return args;
+}
+
#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
static void test_plus_minus_subprocess(void)
{
@@ -229,5 +314,31 @@ int main(int argc, char **argv)
"-machine pc-i440fx-2.7 -cpu 486,+xstore",
"xlevel2", 0);
+ /* Test feature parsing */
+ add_feature_test("x86/cpuid/features/plus",
+ "-cpu 486,+arat",
+ 6, 0, "EAX", 2, true);
+ add_feature_test("x86/cpuid/features/minus",
+ "-cpu pentium,-mmx",
+ 1, 0, "EDX", 23, false);
+ add_feature_test("x86/cpuid/features/on",
+ "-cpu 486,arat=on",
+ 6, 0, "EAX", 2, true);
+ add_feature_test("x86/cpuid/features/off",
+ "-cpu pentium,mmx=off",
+ 1, 0, "EDX", 23, false);
+ add_feature_test("x86/cpuid/features/max-plus-invtsc",
+ "-cpu max,+invtsc",
+ 0x80000007, 0, "EDX", 8, true);
+ add_feature_test("x86/cpuid/features/max-invtsc-on",
+ "-cpu max,invtsc=on",
+ 0x80000007, 0, "EDX", 8, true);
+ add_feature_test("x86/cpuid/features/max-minus-mmx",
+ "-cpu max,-mmx",
+ 1, 0, "EDX", 23, false);
+ add_feature_test("x86/cpuid/features/max-invtsc-on,mmx=off",
+ "-cpu max,mmx=off",
+ 1, 0, "EDX", 23, false);
+
return g_test_run();
}