[RFC PATCH v2 009/137] cpu: Make cpu_create() take a QOM parent

Alexander Graf <[email protected]>
Newsgroups org.nongnu.qemu-arm,org.nongnu.qemu-devel,org.nongnu.qemu-riscv
Message-ID <[email protected]>
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'

AI-used-for: code (refactoring)
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 694481ae3e..5269ea42a5 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -474,7 +474,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 60a695b7ca..966322dbb3 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -235,7 +235,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;
 
@@ -817,7 +817,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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.