summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/arm/allwinner-a10.c6
-rw-r--r--hw/arm/digic.c6
-rw-r--r--hw/arm/xlnx-zynqmp.c6
-rw-r--r--hw/pci-host/versatile.c11
-rw-r--r--include/hw/qdev-core.h13
-rw-r--r--qmp.c5
-rw-r--r--target-alpha/cpu.c7
-rw-r--r--target-arm/cpu.c11
-rw-r--r--target-cris/cpu.c7
-rw-r--r--target-i386/cpu.c8
-rw-r--r--target-lm32/cpu.c7
-rw-r--r--target-m68k/cpu.c7
-rw-r--r--target-microblaze/cpu.c6
-rw-r--r--target-mips/cpu.c7
-rw-r--r--target-moxie/cpu.c7
-rw-r--r--target-openrisc/cpu.c7
-rw-r--r--target-ppc/kvm.c4
-rw-r--r--target-s390x/cpu.c7
-rw-r--r--target-sh4/cpu.c7
-rw-r--r--target-sparc/cpu.c7
-rw-r--r--target-tricore/cpu.c6
-rw-r--r--target-unicore32/cpu.c7
-rw-r--r--target-xtensa/cpu.c7
23 files changed, 166 insertions, 0 deletions
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
index ff249af335..43dc0a12de 100644
--- a/hw/arm/allwinner-a10.c
+++ b/hw/arm/allwinner-a10.c
@@ -103,6 +103,12 @@ static void aw_a10_class_init(ObjectClass *oc, void *data)
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = aw_a10_realize;
+
+ /*
+ * Reason: creates an ARM CPU, thus use after free(), see
+ * arm_cpu_class_init()
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo aw_a10_type_info = {
diff --git a/hw/arm/digic.c b/hw/arm/digic.c
index ec8c330602..90f8190c48 100644
--- a/hw/arm/digic.c
+++ b/hw/arm/digic.c
@@ -97,6 +97,12 @@ static void digic_class_init(ObjectClass *oc, void *data)
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = digic_realize;
+
+ /*
+ * Reason: creates an ARM CPU, thus use after free(), see
+ * arm_cpu_class_init()
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo digic_type_info = {
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 62ef4ceb32..5157565f99 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -248,6 +248,12 @@ static void xlnx_zynqmp_class_init(ObjectClass *oc, void *data)
dc->props = xlnx_zynqmp_props;
dc->realize = xlnx_zynqmp_realize;
+
+ /*
+ * Reason: creates an ARM CPU, thus use after free(), see
+ * arm_cpu_class_init()
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo xlnx_zynqmp_type_info = {
diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
index 6d23553094..7172b90958 100644
--- a/hw/pci-host/versatile.c
+++ b/hw/pci-host/versatile.c
@@ -500,6 +500,8 @@ static void pci_vpb_class_init(ObjectClass *klass, void *data)
dc->reset = pci_vpb_reset;
dc->vmsd = &pci_vpb_vmstate;
dc->props = pci_vpb_properties;
+ /* Reason: object_unref() hangs */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo pci_vpb_info = {
@@ -521,10 +523,19 @@ static void pci_realview_init(Object *obj)
s->mem_win_size[2] = 0x08000000;
}
+static void pci_realview_class_init(ObjectClass *class, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(class);
+
+ /* Reason: object_unref() hangs */
+ dc->cannot_destroy_with_object_finalize_yet = true;
+}
+
static const TypeInfo pci_realview_info = {
.name = "realview_pci",
.parent = TYPE_VERSATILE_PCI,
.instance_init = pci_realview_init,
+ .class_init = pci_realview_class_init,
};
static void versatile_pci_register_types(void)
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 038b54d94b..8057aedaa6 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -114,6 +114,19 @@ typedef struct DeviceClass {
* TODO remove once we're there
*/
bool cannot_instantiate_with_device_add_yet;
+ /*
+ * Does this device model survive object_unref(object_new(TNAME))?
+ * All device models should, and this flag shouldn't exist. Some
+ * devices crash in object_new(), some crash or hang in
+ * object_unref(). Makes introspecting properties with
+ * qmp_device_list_properties() dangerous. Bad, because it's used
+ * by -device FOO,help. This flag serves to protect that code.
+ * It should never be set without a comment explaining why it is
+ * set.
+ * TODO remove once we're there
+ */
+ bool cannot_destroy_with_object_finalize_yet;
+
bool hotpluggable;
/* callbacks */
diff --git a/qmp.c b/qmp.c
index 8603c46bdb..6998ca2fc6 100644
--- a/qmp.c
+++ b/qmp.c
@@ -520,6 +520,11 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
return NULL;
}
+ if (DEVICE_CLASS(klass)->cannot_destroy_with_object_finalize_yet) {
+ error_setg(errp, "Can't list properties of device '%s'", typename);
+ return NULL;
+ }
+
obj = object_new(typename);
QTAILQ_FOREACH(prop, &obj->properties, node) {
diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
index 421d7e5364..ff1926a5d0 100644
--- a/target-alpha/cpu.c
+++ b/target-alpha/cpu.c
@@ -298,6 +298,13 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
dc->vmsd = &vmstate_alpha_cpu;
#endif
cc->gdb_num_core_regs = 67;
+
+ /*
+ * Reason: alpha_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo alpha_cpu_type_info = {
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 8b4323dd08..ce0b8c09c5 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -1403,6 +1403,17 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->debug_excp_handler = arm_debug_excp_handler;
cc->disas_set_info = arm_disas_set_info;
+
+ /*
+ * Reason: arm_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ *
+ * Once this is fixed, the devices that create ARM CPUs should be
+ * updated not to set cannot_destroy_with_object_finalize_yet,
+ * unless they still screw up something else.
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void cpu_register(const ARMCPUInfo *info)
diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index b17e849e2a..aa5e1c57c1 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -308,6 +308,13 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_stop_before_watchpoint = true;
cc->disas_set_info = cris_disas_set_info;
+
+ /*
+ * Reason: cris_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo cris_cpu_type_info = {
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 7a779b1653..4d1b085332 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1475,6 +1475,8 @@ static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
*/
dc->props = host_x86_cpu_properties;
+ /* Reason: host_x86_cpu_initfn() dies when !kvm_enabled() */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void host_x86_cpu_initfn(Object *obj)
@@ -3200,6 +3202,12 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
#endif
cc->cpu_exec_enter = x86_cpu_exec_enter;
cc->cpu_exec_exit = x86_cpu_exec_exit;
+
+ /*
+ * Reason: x86_cpu_initfn() calls cpu_exec_init(), which saves the
+ * object in cpus -> dangling pointer after final object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo x86_cpu_type_info = {
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index c2b77c6986..d0ab2786ae 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -275,6 +275,13 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_num_core_regs = 32 + 7;
cc->gdb_stop_before_watchpoint = true;
cc->debug_excp_handler = lm32_debug_excp_handler;
+
+ /*
+ * Reason: lm32_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void lm32_register_cpu_type(const LM32CPUInfo *info)
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 4f246da748..97527ef32a 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -212,6 +212,13 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
dc->vmsd = &vmstate_m68k_cpu;
cc->gdb_num_core_regs = 18;
cc->gdb_core_xml_file = "cf-core.xml";
+
+ /*
+ * Reason: m68k_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void register_cpu_type(const M68kCPUInfo *info)
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 9ac509af3e..15b46f7686 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -264,6 +264,12 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_num_core_regs = 32 + 5;
cc->disas_set_info = mb_disas_set_info;
+
+ /*
+ * Reason: mb_cpu_initfn() calls cpu_exec_init(), which saves the
+ * object in cpus -> dangling pointer after final object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo mb_cpu_type_info = {
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index 4027d0f417..7fe1f0407f 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -153,6 +153,13 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
cc->gdb_num_core_regs = 73;
cc->gdb_stop_before_watchpoint = true;
+
+ /*
+ * Reason: mips_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo mips_cpu_type_info = {
diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
index 6b035aaab3..3af37799b7 100644
--- a/target-moxie/cpu.c
+++ b/target-moxie/cpu.c
@@ -114,6 +114,13 @@ static void moxie_cpu_class_init(ObjectClass *oc, void *data)
cc->get_phys_page_debug = moxie_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_moxie_cpu;
#endif
+
+ /*
+ * Reason: moxie_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void moxielite_initfn(Object *obj)
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index d97f3c03c2..cc5e2d1c5d 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -177,6 +177,13 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
dc->vmsd = &vmstate_openrisc_cpu;
#endif
cc->gdb_num_core_regs = 32 + 3;
+
+ /*
+ * Reason: openrisc_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void cpu_register(const OpenRISCCPUInfo *info)
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 110436d088..a307a13deb 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -2188,6 +2188,7 @@ static void kvmppc_host_cpu_initfn(Object *obj)
static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
{
+ DeviceClass *dc = DEVICE_CLASS(oc);
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
uint32_t vmx = kvmppc_get_vmx();
uint32_t dfp = kvmppc_get_dfp();
@@ -2214,6 +2215,9 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
if (icache_size != -1) {
pcc->l1_icache_size = icache_size;
}
+
+ /* Reason: kvmppc_host_cpu_initfn() dies when !kvm_enabled() */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
bool kvmppc_has_cap_epr(void)
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index c3e21b445c..ccfaa8a919 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -353,6 +353,13 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
#endif
cc->gdb_num_core_regs = S390_NUM_CORE_REGS;
cc->gdb_core_xml_file = "s390x-core64.xml";
+
+ /*
+ * Reason: s390_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo s390_cpu_type_info = {
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index 5c65ab4df5..64e4467c04 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -290,6 +290,13 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
#endif
dc->vmsd = &vmstate_sh_cpu;
cc->gdb_num_core_regs = 59;
+
+ /*
+ * Reason: superh_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo superh_cpu_type_info = {
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 9528e3afbb..82bb72ab79 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -854,6 +854,13 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
#else
cc->gdb_num_core_regs = 72;
#endif
+
+ /*
+ * Reason: sparc_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo sparc_cpu_type_info = {
diff --git a/target-tricore/cpu.c b/target-tricore/cpu.c
index 2029ef651a..ed8b030ef5 100644
--- a/target-tricore/cpu.c
+++ b/target-tricore/cpu.c
@@ -170,6 +170,12 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data)
cc->set_pc = tricore_cpu_set_pc;
cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb;
+ /*
+ * Reason: tricore_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void cpu_register(const TriCoreCPUInfo *info)
diff --git a/target-unicore32/cpu.c b/target-unicore32/cpu.c
index fc451a1a35..e5252ebaf8 100644
--- a/target-unicore32/cpu.c
+++ b/target-unicore32/cpu.c
@@ -155,6 +155,13 @@ static void uc32_cpu_class_init(ObjectClass *oc, void *data)
cc->get_phys_page_debug = uc32_cpu_get_phys_page_debug;
#endif
dc->vmsd = &vmstate_uc32_cpu;
+
+ /*
+ * Reason: uc32_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void uc32_register_cpu_type(const UniCore32CPUInfo *info)
diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index da8129db50..4e49bee9b5 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -155,6 +155,13 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
#endif
cc->debug_excp_handler = xtensa_breakpoint_handler;
dc->vmsd = &vmstate_xtensa_cpu;
+
+ /*
+ * Reason: xtensa_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo xtensa_cpu_type_info = {