CPUs are the single largest source of orphans in /machine/unattached
because virtually every board that isn't SoC-based creates them via
cpu_create(), which calls object_new() with no parent.  This is also
where the user-visible garbage in query-cpus-fast comes from: qom_path
reads /machine/unattached/device[N] instead of /machine/cpu[N].

Apply the same rename-and-reintroduce treatment: mechanically rename
cpu_create() to cpu_create_orphan() and reintroduce cpu_create()
with a leading (parent, id, ...) pair built on object_new_child().
On realize failure the parented variant unparents (rather than
unrefs) since the sole reference is held by the parent.

The mechanical rename part is generated by

  spatch --sp-file \
      scripts/coccinelle/qom-parent/cpu-create-orphan.cocci \
      --in-place --include-headers --dir .

or equivalently

  git ls-files '*.[ch]' '*.[ch].inc' '*.rst' '*.py' | \
      grep -v '^subprojects/' | \
      xargs sed -i 's/\bcpu_create\b/cpu_create_orphan/g'

Assisted-by: Kiro
Signed-off-by: Alexander Graf <[email protected]>
---
 bsd-user/main.c                                   |  2 +-
 hw/alpha/dp264.c                                  |  2 +-
 hw/arm/musicpal.c                                 |  2 +-
 hw/arm/omap1.c                                    |  2 +-
 hw/arm/strongarm.c                                |  2 +-
 hw/core/cpu-common.c                              | 14 +++++++++++++-
 hw/core/null-machine.c                            |  2 +-
 hw/hppa/machine.c                                 |  2 +-
 hw/m68k/an5206.c                                  |  2 +-
 hw/m68k/mcf5208.c                                 |  2 +-
 hw/m68k/next-cube.c                               |  2 +-
 hw/m68k/virt.c                                    |  2 +-
 hw/or1k/or1k-sim.c                                |  2 +-
 hw/or1k/virt.c                                    |  2 +-
 hw/ppc/amigaone.c                                 |  2 +-
 hw/ppc/mac_newworld.c                             |  2 +-
 hw/ppc/mac_oldworld.c                             |  2 +-
 hw/ppc/pegasos.c                                  |  2 +-
 hw/ppc/ppc440_bamboo.c                            |  2 +-
 hw/ppc/prep.c                                     |  2 +-
 hw/ppc/sam460ex.c                                 |  2 +-
 hw/ppc/virtex_ml507.c                             |  2 +-
 hw/sh4/r2d.c                                      |  2 +-
 hw/tricore/tricore_testboard.c                    |  2 +-
 hw/xtensa/sim.c                                   |  2 +-
 hw/xtensa/xtfpga.c                                |  2 +-
 include/hw/core/cpu.h                             | 15 ++++++++++++++-
 linux-user/main.c                                 |  4 ++--
 .../coccinelle/qom-parent/cpu-create-orphan.cocci | 13 +++++++++++++
 29 files changed, 67 insertions(+), 29 deletions(-)
 create mode 100644 scripts/coccinelle/qom-parent/cpu-create-orphan.cocci

diff --git a/bsd-user/main.c b/bsd-user/main.c
index 4f1544342e..618b1adf4d 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -475,7 +475,7 @@ int main(int argc, char **argv)
     set_preferred_target_page_bits(ctz32(host_page_size));
     finalize_target_page_bits();
 
-    cpu = cpu_create(cpu_type);
+    cpu = cpu_create_orphan(cpu_type);
     env = cpu_env(cpu);
     cpu_reset(cpu);
     thread_cpu = cpu;
diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index b07dcebaa0..512b270838 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -65,7 +65,7 @@ static void clipper_init(MachineState *machine)
     /* Create up to 4 cpus.  */
     memset(cpus, 0, sizeof(cpus));
     for (i = 0; i < smp_cpus; ++i) {
-        cpus[i] = ALPHA_CPU(cpu_create(machine->cpu_type));
+        cpus[i] = ALPHA_CPU(cpu_create_orphan(machine->cpu_type));
     }
 
     /*
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index baab159bfd..a07359813e 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -1232,7 +1232,7 @@ static void musicpal_init(MachineState *machine)
         exit(EXIT_FAILURE);
     }
 
-    cpu = ARM_CPU(cpu_create(machine->cpu_type));
+    cpu = ARM_CPU(cpu_create_orphan(machine->cpu_type));
 
     memory_region_add_subregion(address_space_mem, 0, machine->ram);
 
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
index 9115d12fad..eefa2e441a 100644
--- a/hw/arm/omap1.c
+++ b/hw/arm/omap1.c
@@ -3749,7 +3749,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion 
*dram,
     MemoryRegion *system_memory = get_system_memory();
 
     /* Core */
-    s->cpu = ARM_CPU(cpu_create(cpu_type));
+    s->cpu = ARM_CPU(cpu_create_orphan(cpu_type));
     s->sdram_size = memory_region_size(dram);
     s->sram_size = OMAP15XX_SRAM_SIZE;
 
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index f67aaa23ed..1704db8baa 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -1620,7 +1620,7 @@ StrongARMState *sa1110_init(const char *cpu_type)
         exit(1);
     }
 
-    s->cpu = ARM_CPU(cpu_create(cpu_type));
+    s->cpu = ARM_CPU(cpu_create_orphan(cpu_type));
 
     s->pic = sysbus_create_varargs_orphan("strongarm_pic", 0x90050000,
                     qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ),
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
index e314f916f8..eef243c1ad 100644
--- a/hw/core/cpu-common.c
+++ b/hw/core/cpu-common.c
@@ -56,7 +56,19 @@ bool cpu_exists(int64_t id)
     return !!cpu_by_arch_id(id);
 }
 
-CPUState *cpu_create(const char *typename)
+CPUState *cpu_create(Object *parent, const char *id, const char *typename)
+{
+    Error *err = NULL;
+    CPUState *cpu = CPU(object_new_child(parent, id, typename));
+    if (!qdev_realize(DEVICE(cpu), NULL, &err)) {
+        error_report_err(err);
+        object_unparent(OBJECT(cpu));
+        exit(EXIT_FAILURE);
+    }
+    return cpu;
+}
+
+CPUState *cpu_create_orphan(const char *typename)
 {
     Error *err = NULL;
     CPUState *cpu = CPU(object_new(typename));
diff --git a/hw/core/null-machine.c b/hw/core/null-machine.c
index f132a7b89b..7cc4b9ab3b 100644
--- a/hw/core/null-machine.c
+++ b/hw/core/null-machine.c
@@ -25,7 +25,7 @@ static void machine_none_init(MachineState *mch)
 
     /* Initialize CPU (if user asked for it) */
     if (mch->cpu_type) {
-        cpu = cpu_create(mch->cpu_type);
+        cpu = cpu_create_orphan(mch->cpu_type);
         if (!cpu) {
             error_report("Unable to initialize CPU");
             exit(1);
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index 44dab9225a..a4b8e9ee77 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -298,7 +298,7 @@ static TranslateFn 
*machine_HP_common_init_cpus(MachineState *machine)
 
     /* Create CPUs.  */
     for (unsigned int i = 0; i < smp_cpus; i++) {
-        cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type));
+        cpu[i] = HPPA_CPU(cpu_create_orphan(machine->cpu_type));
     }
 
     /* Initialize memory */
diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c
index f29c3b5226..b649605140 100644
--- a/hw/m68k/an5206.c
+++ b/hw/m68k/an5206.c
@@ -46,7 +46,7 @@ static void an5206_init(MachineState *machine)
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *sram = g_new(MemoryRegion, 1);
 
-    cpu = M68K_CPU(cpu_create(machine->cpu_type));
+    cpu = M68K_CPU(cpu_create_orphan(machine->cpu_type));
     env = &cpu->env;
 
     /* Initialize CPU registers.  */
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index a8068c91f2..d79ec173e6 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -288,7 +288,7 @@ static void mcf5208evb_init(MachineState *machine)
     MemoryRegion *sram = g_new(MemoryRegion, 1);
     DeviceState *intc;
 
-    cpu = M68K_CPU(cpu_create(machine->cpu_type));
+    cpu = M68K_CPU(cpu_create_orphan(machine->cpu_type));
     env = &cpu->env;
 
     /* Initialize CPU registers.  */
diff --git a/hw/m68k/next-cube.c b/hw/m68k/next-cube.c
index 0c1f5b4481..d97168d9f3 100644
--- a/hw/m68k/next-cube.c
+++ b/hw/m68k/next-cube.c
@@ -1260,7 +1260,7 @@ static void next_cube_init(MachineState *machine)
     DeviceState *pcdev;
 
     /* Initialize the cpu core */
-    cpu = M68K_CPU(cpu_create(machine->cpu_type));
+    cpu = M68K_CPU(cpu_create_orphan(machine->cpu_type));
     if (!cpu) {
         error_report("Unable to find m68k CPU definition");
         exit(1);
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index e2af0196e8..64ac8c8166 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -145,7 +145,7 @@ static void virt_init(MachineState *machine)
     reset_info = g_new0(ResetInfo, 1);
 
     /* init CPUs */
-    cpu = M68K_CPU(cpu_create(machine->cpu_type));
+    cpu = M68K_CPU(cpu_create_orphan(machine->cpu_type));
 
     reset_info->cpu = cpu;
     qemu_register_reset(main_cpu_reset, reset_info);
diff --git a/hw/or1k/or1k-sim.c b/hw/or1k/or1k-sim.c
index bd668d0e47..6962313315 100644
--- a/hw/or1k/or1k-sim.c
+++ b/hw/or1k/or1k-sim.c
@@ -299,7 +299,7 @@ static void openrisc_sim_init(MachineState *machine)
 
     assert(smp_cpus >= 1 && smp_cpus <= OR1KSIM_CPUS_MAX);
     for (n = 0; n < smp_cpus; n++) {
-        cpus[n] = OPENRISC_CPU(cpu_create(machine->cpu_type));
+        cpus[n] = OPENRISC_CPU(cpu_create_orphan(machine->cpu_type));
         if (cpus[n] == NULL) {
             fprintf(stderr, "Unable to find CPU definition!\n");
             exit(1);
diff --git a/hw/or1k/virt.c b/hw/or1k/virt.c
index 9451a0b7df..f222efafde 100644
--- a/hw/or1k/virt.c
+++ b/hw/or1k/virt.c
@@ -481,7 +481,7 @@ static void openrisc_virt_init(MachineState *machine)
 
     assert(smp_cpus >= 1 && smp_cpus <= VIRT_CPUS_MAX);
     for (n = 0; n < smp_cpus; n++) {
-        cpus[n] = OPENRISC_CPU(cpu_create(machine->cpu_type));
+        cpus[n] = OPENRISC_CPU(cpu_create_orphan(machine->cpu_type));
         if (cpus[n] == NULL) {
             fprintf(stderr, "Unable to find CPU definition!\n");
             exit(1);
diff --git a/hw/ppc/amigaone.c b/hw/ppc/amigaone.c
index c6b331ff16..80802d42c6 100644
--- a/hw/ppc/amigaone.c
+++ b/hw/ppc/amigaone.c
@@ -279,7 +279,7 @@ static void amigaone_init(MachineState *machine)
     struct boot_info *bi = NULL;
 
     /* init CPU */
-    cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
+    cpu = POWERPC_CPU(cpu_create_orphan(machine->cpu_type));
     env = &cpu->env;
     if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
         error_report("Incompatible CPU, only 6xx bus supported");
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 72baeef60a..8c46ecd6d1 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -159,7 +159,7 @@ static void ppc_core99_init(MachineState *machine)
 
     /* init CPUs */
     for (i = 0; i < machine->smp.cpus; i++) {
-        cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
+        cpu = POWERPC_CPU(cpu_create_orphan(machine->cpu_type));
         env = &cpu->env;
 
         /* Set time-base frequency to 100 Mhz */
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index e6c5830c38..4c5746b754 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -111,7 +111,7 @@ static void ppc_heathrow_init(MachineState *machine)
 
     /* init CPUs */
     for (i = 0; i < machine->smp.cpus; i++) {
-        cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
+        cpu = POWERPC_CPU(cpu_create_orphan(machine->cpu_type));
         env = &cpu->env;
 
         /* Set time-base frequency to 16.6 Mhz */
diff --git a/hw/ppc/pegasos.c b/hw/ppc/pegasos.c
index 0030068ab3..bba73f60c8 100644
--- a/hw/ppc/pegasos.c
+++ b/hw/ppc/pegasos.c
@@ -163,7 +163,7 @@ static void pegasos_init(MachineState *machine)
     uint8_t *spd_data;
 
     /* init CPU */
-    pm->cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
+    pm->cpu = POWERPC_CPU(cpu_create_orphan(machine->cpu_type));
     env = &pm->cpu->env;
     if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
         error_report("Incompatible CPU, only 6xx bus supported");
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 7a6c3ebec5..68c7328129 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -148,7 +148,7 @@ static void bamboo_init(MachineState *machine)
         exit(EXIT_FAILURE);
     }
 
-    cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
+    cpu = POWERPC_CPU(cpu_create_orphan(machine->cpu_type));
     env = &cpu->env;
 
     if (env->mmu_model != POWERPC_MMU_BOOKE) {
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 32a28bc12a..c861e022f0 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -257,7 +257,7 @@ static void ibm_40p_init(MachineState *machine)
     }
 
     /* init CPU */
-    cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
+    cpu = POWERPC_CPU(cpu_create_orphan(machine->cpu_type));
     env = &cpu->env;
     if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
         error_report("only 6xx bus is supported on this machine");
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index 39e704dfaa..d23d2c2bd8 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -260,7 +260,7 @@ static void sam460ex_init(MachineState *machine)
     uint8_t *spd_data;
     int success;
 
-    cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
+    cpu = POWERPC_CPU(cpu_create_orphan(machine->cpu_type));
     env = &cpu->env;
     if (env->mmu_model != POWERPC_MMU_BOOKE) {
         error_report("Only MMU model BookE is supported by this machine.");
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index d7fd72d353..9163d8acf8 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -76,7 +76,7 @@ static PowerPCCPU *ppc440_init_xilinx(const char *cpu_type, 
uint32_t sysclk)
     DeviceState *uicdev;
     SysBusDevice *uicsbd;
 
-    cpu = POWERPC_CPU(cpu_create(cpu_type));
+    cpu = POWERPC_CPU(cpu_create_orphan(cpu_type));
     env = &cpu->env;
 
     ppc_booke_timers_init(cpu, sysclk, 0/* no flags */);
diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
index 6f8d270fae..9f313a77cb 100644
--- a/hw/sh4/r2d.c
+++ b/hw/sh4/r2d.c
@@ -251,7 +251,7 @@ static void r2d_init(MachineState *machine)
     USBBus *usb_bus;
     r2d_fpga_t *fpga;
 
-    cpu = SUPERH_CPU(cpu_create(machine->cpu_type));
+    cpu = SUPERH_CPU(cpu_create_orphan(machine->cpu_type));
     env = &cpu->env;
 
     reset_info = g_new0(ResetData, 1);
diff --git a/hw/tricore/tricore_testboard.c b/hw/tricore/tricore_testboard.c
index afed9ad0ae..69794d3445 100644
--- a/hw/tricore/tricore_testboard.c
+++ b/hw/tricore/tricore_testboard.c
@@ -67,7 +67,7 @@ static void tricore_testboard_init(MachineState *machine, int 
board_id)
     MemoryRegion *pcp_data = g_new(MemoryRegion, 1);
     MemoryRegion *pcp_text = g_new(MemoryRegion, 1);
 
-    cpu = TRICORE_CPU(cpu_create(machine->cpu_type));
+    cpu = TRICORE_CPU(cpu_create_orphan(machine->cpu_type));
     env = &cpu->env;
     memory_region_init_ram(ext_cram, NULL, "powerlink_ext_c.ram",
                            2 * MiB, &error_fatal);
diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c
index 835cd04fe0..17245a0388 100644
--- a/hw/xtensa/sim.c
+++ b/hw/xtensa/sim.c
@@ -63,7 +63,7 @@ XtensaCPU *xtensa_sim_common_init(MachineState *machine)
     int n;
 
     for (n = 0; n < machine->smp.cpus; n++) {
-        cpu = XTENSA_CPU(cpu_create(machine->cpu_type));
+        cpu = XTENSA_CPU(cpu_create_orphan(machine->cpu_type));
         env = &cpu->env;
 
         env->sregs[PRID] = n;
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index 4b1009a398..0ee7350945 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -250,7 +250,7 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, 
MachineState *machine)
     for (n = 0; n < smp_cpus; n++) {
         CPUXtensaState *cenv = NULL;
 
-        cpu = XTENSA_CPU(cpu_create(machine->cpu_type));
+        cpu = XTENSA_CPU(cpu_create_orphan(machine->cpu_type));
         cenv = &cpu->env;
         if (!env) {
             env = cenv;
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index b54035fb13..1b2ec1ab1e 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -846,13 +846,26 @@ char *cpu_model_from_type(const char *typename);
 
 /**
  * cpu_create:
+ * @parent: the QOM parent (usually the machine or SoC container)
+ * @id: child<> property name, e.g. "cpu[0]" or "cpu[*]"
+ * @typename: the CPU type
+ *
+ * Instantiates a CPU as a child of @parent under @id and realizes it.
+ * The returned CPU is owned by @parent.
+ *
+ * Returns: A #CPUState.  Failure to realize is fatal.
+ */
+CPUState *cpu_create(Object *parent, const char *id, const char *typename);
+
+/**
+ * cpu_create_orphan:
  * @typename: The CPU type.
  *
  * Instantiates a CPU and realizes the CPU.
  *
  * Returns: A #CPUState or %NULL if an error occurred.
  */
-CPUState *cpu_create(const char *typename);
+CPUState *cpu_create_orphan(const char *typename);
 
 /**
  * parse_cpu_option:
diff --git a/linux-user/main.c b/linux-user/main.c
index c08c73fd80..53c7768a5e 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -237,7 +237,7 @@ void init_task_state(TaskState *ts)
 CPUArchState *cpu_copy(CPUArchState *env)
 {
     CPUState *cpu = env_cpu(env);
-    CPUState *new_cpu = cpu_create(cpu_type);
+    CPUState *new_cpu = cpu_create_orphan(cpu_type);
     CPUArchState *new_env = cpu_env(new_cpu);
     CPUBreakpoint *bp;
 
@@ -819,7 +819,7 @@ int main(int argc, char **argv, char **envp)
     set_preferred_target_page_bits(ctz32(host_page_size));
     finalize_target_page_bits();
 
-    cpu = cpu_create(cpu_type);
+    cpu = cpu_create_orphan(cpu_type);
     env = cpu_env(cpu);
     cpu_reset(cpu);
     thread_cpu = cpu;
diff --git a/scripts/coccinelle/qom-parent/cpu-create-orphan.cocci 
b/scripts/coccinelle/qom-parent/cpu-create-orphan.cocci
new file mode 100644
index 0000000000..c268c05b0c
--- /dev/null
+++ b/scripts/coccinelle/qom-parent/cpu-create-orphan.cocci
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+// Rename cpu_create() to cpu_create_orphan() so that the short
+// name can be reintroduced with a mandatory (parent, id, type)
+// signature.
+//
+// spatch --sp-file scripts/coccinelle/qom-parent/cpu-create-orphan.cocci \
+//        --in-place --include-headers --dir .
+
+@@
+@@
+- cpu_create
++ cpu_create_orphan
-- 
2.47.1


Reply via email to