The virt and DSP machine models build the same core subsystem,
let's abstract out that part.

The CPUs are now grouped in a TYPE_CPU_CLUSTER.

Signed-off-by: Brian Cain <[email protected]>
---
 include/hw/hexagon/hex-subsys.h |  24 ++++++++
 include/hw/hexagon/hexagon.h    |   4 ++
 include/hw/hexagon/virt.h       |   1 -
 hw/hexagon/hex-subsys.c         | 105 ++++++++++++++++++++++++++++++++
 hw/hexagon/hexagon_dsp.c        |  40 ++----------
 hw/hexagon/virt.c               |  52 +++-------------
 hw/hexagon/Kconfig              |   1 +
 hw/hexagon/meson.build          |   1 +
 8 files changed, 147 insertions(+), 81 deletions(-)
 create mode 100644 include/hw/hexagon/hex-subsys.h
 create mode 100644 hw/hexagon/hex-subsys.c

diff --git a/include/hw/hexagon/hex-subsys.h b/include/hw/hexagon/hex-subsys.h
new file mode 100644
index 00000000000..73403e8951c
--- /dev/null
+++ b/include/hw/hexagon/hex-subsys.h
@@ -0,0 +1,24 @@
+/*
+ * Hexagon subsystem helpers shared between the machine models.
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_HEXAGON_HEX_SUBSYS_H
+#define HW_HEXAGON_HEX_SUBSYS_H
+
+#include "hw/hexagon/hexagon.h"
+#include "hw/core/qdev.h"
+
+/* Create the subsystem shared by every Hexagon machine. */
+void hex_subsys_create(HexagonCommonMachineState *hms,
+                       const struct hexagon_machine_config *m_cfg, Rev_t rev);
+
+/* Realize a CPU into the subsystem, then hex_subsys_realize_cluster(). */
+void hex_subsys_realize_cpu(HexagonCommonMachineState *hms, DeviceState *cpu);
+
+/* Realize the CPU cluster, once all CPUs have been parented into it. */
+void hex_subsys_realize_cluster(HexagonCommonMachineState *hms);
+
+#endif /* HW_HEXAGON_HEX_SUBSYS_H */
diff --git a/include/hw/hexagon/hexagon.h b/include/hw/hexagon/hexagon.h
index 1034b09c2ac..31669a829f8 100644
--- a/include/hw/hexagon/hexagon.h
+++ b/include/hw/hexagon/hexagon.h
@@ -156,6 +156,10 @@ struct HexagonCommonMachineState {
 
     MemoryRegion ram;
     MemoryRegion cfgtable_rom;
+    MemoryRegion vtcm;
+    DeviceState *cluster;
+    DeviceState *glob_regs;
+    DeviceState *tlb;
 };
 
 #endif
diff --git a/include/hw/hexagon/virt.h b/include/hw/hexagon/virt.h
index fcb47762194..cf0cd2f8f22 100644
--- a/include/hw/hexagon/virt.h
+++ b/include/hw/hexagon/virt.h
@@ -17,7 +17,6 @@ struct HexagonVirtMachineState {
     int fdt_size;
     MemoryRegion *sys;
     MemoryRegion tcm;
-    MemoryRegion vtcm;
     MemoryRegion bios;
     Clock *apb_clk;
 };
diff --git a/hw/hexagon/hex-subsys.c b/hw/hexagon/hex-subsys.c
new file mode 100644
index 00000000000..638b6429100
--- /dev/null
+++ b/hw/hexagon/hex-subsys.c
@@ -0,0 +1,105 @@
+/*
+ * Hexagon subsystem helpers shared between the machine models.
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/hexagon/hex-subsys.h"
+#include "hw/hexagon/hexagon_globalreg.h"
+#include "hw/hexagon/hexagon_tlb.h"
+#include "hw/cpu/cluster.h"
+#include "hw/core/loader.h"
+#include "hw/core/qdev-properties.h"
+#include "hw/core/qdev.h"
+#include "hw/core/sysbus.h"
+#include "system/address-spaces.h"
+
+static DeviceState *globalreg_create(HexagonCommonMachineState *hms,
+                                     const struct hexagon_machine_config 
*m_cfg,
+                                     Rev_t rev)
+{
+    DeviceState *glob_regs = qdev_new(TYPE_HEXAGON_GLOBALREG);
+
+    object_property_add_child(OBJECT(hms), "global-regs", OBJECT(glob_regs));
+    qdev_prop_set_uint64(glob_regs, "config-table-addr", m_cfg->cfgbase);
+    qdev_prop_set_uint32(glob_regs, "dsp-rev", rev);
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(glob_regs), &error_fatal);
+
+    return glob_regs;
+}
+
+static DeviceState *tlb_create(HexagonCommonMachineState *hms,
+                               const struct hexagon_machine_config *m_cfg)
+{
+    DeviceState *tlb = qdev_new(TYPE_HEXAGON_TLB);
+
+    object_property_add_child(OBJECT(hms), "tlb", OBJECT(tlb));
+    qdev_prop_set_uint32(tlb, "num-entries", 
m_cfg->cfgtable.jtlb_size_entries);
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(tlb), &error_fatal);
+
+    return tlb;
+}
+
+static DeviceState *cluster_create(HexagonCommonMachineState *hms)
+{
+    DeviceState *cluster = qdev_new(TYPE_CPU_CLUSTER);
+
+    object_property_add_child(OBJECT(hms), "cluster", OBJECT(cluster));
+    qdev_prop_set_uint32(cluster, "cluster-id", 0);
+
+    return cluster;
+}
+
+void hex_subsys_create(HexagonCommonMachineState *hms,
+                       const struct hexagon_machine_config *m_cfg, Rev_t rev)
+{
+    MachineState *machine = MACHINE(hms);
+    MemoryRegion *sysmem = get_system_memory();
+
+    /* Main DDR at the reset vector. */
+    memory_region_init_ram(&hms->ram, NULL, "ddr.ram", machine->ram_size,
+                           &error_fatal);
+    memory_region_add_subregion(sysmem, 0x0, &hms->ram);
+
+    /* Config-table ROM and the blob that backs it. */
+    memory_region_init_rom(&hms->cfgtable_rom, NULL, "config_table.rom",
+                           sizeof(m_cfg->cfgtable), &error_fatal);
+    memory_region_add_subregion(sysmem, m_cfg->cfgbase, &hms->cfgtable_rom);
+    rom_add_blob_fixed_as("config_table.rom", &m_cfg->cfgtable,
+                          sizeof(m_cfg->cfgtable), m_cfg->cfgbase,
+                          &address_space_memory);
+
+    if (m_cfg->cfgtable.vtcm_size_kb > 0) {
+        memory_region_init_ram(&hms->vtcm, NULL, "vtcm.ram",
+                               m_cfg->cfgtable.vtcm_size_kb * 1024,
+                               &error_fatal);
+        memory_region_add_subregion(sysmem, m_cfg->cfgtable.vtcm_base << 16,
+                                    &hms->vtcm);
+    }
+
+    hms->cluster = cluster_create(hms);
+    hms->glob_regs = globalreg_create(hms, m_cfg, rev);
+    hms->tlb = tlb_create(hms, m_cfg);
+}
+
+void hex_subsys_realize_cpu(HexagonCommonMachineState *hms, DeviceState *cpu)
+{
+    object_property_add_child(OBJECT(hms->cluster), "cpu[*]", OBJECT(cpu));
+    object_property_set_link(OBJECT(cpu), "global-regs",
+                             OBJECT(hms->glob_regs), &error_fatal);
+    object_property_set_link(OBJECT(cpu), "tlb", OBJECT(hms->tlb),
+                             &error_fatal);
+    qdev_realize_and_unref(cpu, NULL, &error_fatal);
+}
+
+void hex_subsys_realize_cluster(HexagonCommonMachineState *hms)
+{
+    /*
+     * The cluster must be realized after its CPUs have been parented into it
+     * (see hex_subsys_realize_cpu()), so this is called once the CPUs exist.
+     */
+    qdev_realize_and_unref(hms->cluster, NULL, &error_fatal);
+}
diff --git a/hw/hexagon/hexagon_dsp.c b/hw/hexagon/hexagon_dsp.c
index aa493993229..5275ab92386 100644
--- a/hw/hexagon/hexagon_dsp.c
+++ b/hw/hexagon/hexagon_dsp.c
@@ -14,8 +14,7 @@
 #include "hw/core/boards.h"
 #include "hw/core/qdev-properties.h"
 #include "hw/hexagon/hexagon.h"
-#include "hw/hexagon/hexagon_globalreg.h"
-#include "hw/hexagon/hexagon_tlb.h"
+#include "hw/hexagon/hex-subsys.h"
 #include "hw/core/loader.h"
 #include "qapi/error.h"
 #include "qemu/error-report.h"
@@ -108,9 +107,6 @@ static void hexagon_common_init(MachineState *machine, 
Rev_t rev,
 {
     HexagonCommonMachineState *hms = HEXAGON_COMMON_MACHINE(machine);
     HexagonDspMachineState *dms = HEXAGON_DSP_MACHINE(machine);
-    MemoryRegion *address_space;
-    DeviceState *glob_regs_dev;
-    DeviceState *tlb_dev;
 
     memset(&hexagon_binfo, 0, sizeof(hexagon_binfo));
     if (machine->kernel_filename) {
@@ -120,29 +116,7 @@ static void hexagon_common_init(MachineState *machine, 
Rev_t rev,
 
     machine->enable_graphics = 0;
 
-    address_space = get_system_memory();
-
-    memory_region_init_rom(&hms->cfgtable_rom, NULL, "config_table.rom",
-                           sizeof(m_cfg->cfgtable), &error_fatal);
-    memory_region_add_subregion(address_space, m_cfg->cfgbase,
-                                &hms->cfgtable_rom);
-
-    memory_region_init_ram(&hms->ram, NULL, "ddr.ram",
-                           machine->ram_size, &error_fatal);
-    memory_region_add_subregion(address_space, 0x0, &hms->ram);
-
-    glob_regs_dev = qdev_new(TYPE_HEXAGON_GLOBALREG);
-    object_property_add_child(OBJECT(machine), "global-regs",
-                              OBJECT(glob_regs_dev));
-    qdev_prop_set_uint64(glob_regs_dev, "config-table-addr", m_cfg->cfgbase);
-    qdev_prop_set_uint32(glob_regs_dev, "dsp-rev", rev);
-    sysbus_realize_and_unref(SYS_BUS_DEVICE(glob_regs_dev), &error_fatal);
-
-    tlb_dev = qdev_new(TYPE_HEXAGON_TLB);
-    object_property_add_child(OBJECT(machine), "tlb", OBJECT(tlb_dev));
-    qdev_prop_set_uint32(tlb_dev, "num-entries",
-                         m_cfg->cfgtable.jtlb_size_entries);
-    sysbus_realize_and_unref(SYS_BUS_DEVICE(tlb_dev), &error_fatal);
+    hex_subsys_create(hms, m_cfg, rev);
 
     for (int i = 0; i < machine->smp.cpus; i++) {
         HexagonCPU *cpu = HEXAGON_CPU(object_new(machine->cpu_type));
@@ -156,16 +130,10 @@ static void hexagon_common_init(MachineState *machine, 
Rev_t rev,
         if (i == 0) {
             hexagon_init_bootstrap(dms, cpu);
         }
-        object_property_set_link(OBJECT(cpu), "global-regs",
-                                 OBJECT(glob_regs_dev), &error_fatal);
-        object_property_set_link(OBJECT(cpu), "tlb",
-                                 OBJECT(tlb_dev), &error_fatal);
-        qdev_realize_and_unref(DEVICE(cpu), NULL, &error_fatal);
+        hex_subsys_realize_cpu(hms, DEVICE(cpu));
     }
 
-    rom_add_blob_fixed_as("config_table.rom", &m_cfg->cfgtable,
-                          sizeof(m_cfg->cfgtable), m_cfg->cfgbase,
-                          &address_space_memory);
+    hex_subsys_realize_cluster(hms);
 }
 
 static void init_mc(MachineClass *mc)
diff --git a/hw/hexagon/virt.c b/hw/hexagon/virt.c
index a3638998b87..ac2b6605dbd 100644
--- a/hw/hexagon/virt.c
+++ b/hw/hexagon/virt.c
@@ -13,8 +13,7 @@
 #include "hw/core/clock.h"
 #include "hw/core/sysbus-fdt.h"
 #include "hw/hexagon/hexagon.h"
-#include "hw/hexagon/hexagon_globalreg.h"
-#include "hw/hexagon/hexagon_tlb.h"
+#include "hw/hexagon/hex-subsys.h"
 #include "hw/core/loader.h"
 #include "hw/core/qdev-properties.h"
 #include "hw/core/qdev-clock.h"
@@ -74,11 +73,6 @@ static void fdt_add_hvx(HexagonVirtMachineState *vms,
     const MachineState *ms = MACHINE(vms);
     uint32_t vtcm_size_bytes = m_cfg->cfgtable.vtcm_size_kb * 1024;
     if (vtcm_size_bytes > 0) {
-        memory_region_init_ram(&vms->vtcm, NULL, "vtcm.ram", vtcm_size_bytes,
-                               &error_fatal);
-        memory_region_add_subregion(vms->sys, m_cfg->cfgtable.vtcm_base << 16,
-                                    &vms->vtcm);
-
         qemu_fdt_add_subnode(ms->fdt, "/soc/vtcm");
         qemu_fdt_setprop_string(ms->fdt, "/soc/vtcm", "compatible",
                                 "qcom,hexagon_vtcm");
@@ -237,9 +231,6 @@ static void virt_init(MachineState *ms)
 {
     HexagonVirtMachineState *vms = HEXAGON_VIRT_MACHINE(ms);
     const struct hexagon_machine_config *m_cfg = &v68n_1024;
-    DeviceState *gsregs_dev;
-    DeviceState *tlb_dev;
-    DeviceState *cpu0;
     int32_t clk_phandle;
 
     qemu_fdt_setprop_string(ms->fdt, "/chosen", "bootargs", 
ms->kernel_cmdline);
@@ -250,9 +241,7 @@ static void virt_init(MachineState *ms)
     vms->apb_clk = clock_new(OBJECT(ms), "apb-pclk");
     clock_set_hz(vms->apb_clk, 24000000);
 
-    memory_region_init_ram(&vms->parent_obj.ram, NULL, "ddr.ram",
-                           ms->ram_size, &error_fatal);
-    memory_region_add_subregion(vms->sys, 0x0, &vms->parent_obj.ram);
+    hex_subsys_create(&vms->parent_obj, m_cfg, v68_rev);
 
     if (m_cfg->l2tcm_size) {
         memory_region_init_ram(&vms->tcm, NULL, "tcm.ram", m_cfg->l2tcm_size,
@@ -261,57 +250,32 @@ static void virt_init(MachineState *ms)
                                     &vms->tcm);
     }
 
-    memory_region_init_rom(&vms->parent_obj.cfgtable_rom, NULL,
-                           "config_table.rom", sizeof(m_cfg->cfgtable),
-                           &error_fatal);
-    memory_region_add_subregion(vms->sys, m_cfg->cfgbase,
-                                &vms->parent_obj.cfgtable_rom);
     fdt_add_hvx(vms, m_cfg);
 
-    gsregs_dev = qdev_new(TYPE_HEXAGON_GLOBALREG);
-    object_property_add_child(OBJECT(ms), "global-regs", OBJECT(gsregs_dev));
-    qdev_prop_set_uint64(gsregs_dev, "config-table-addr", m_cfg->cfgbase);
-    qdev_prop_set_uint32(gsregs_dev, "dsp-rev", v68_rev);
-    sysbus_realize_and_unref(SYS_BUS_DEVICE(gsregs_dev), &error_fatal);
-
-    tlb_dev = qdev_new(TYPE_HEXAGON_TLB);
-    object_property_add_child(OBJECT(ms), "tlb", OBJECT(tlb_dev));
-    qdev_prop_set_uint32(tlb_dev, "num-entries",
-                         m_cfg->cfgtable.jtlb_size_entries);
-    sysbus_realize_and_unref(SYS_BUS_DEVICE(tlb_dev), &error_fatal);
-
-    cpu0 = NULL;
     for (int i = 0; i < ms->smp.cpus; i++) {
         HexagonCPU *cpu = HEXAGON_CPU(object_new(ms->cpu_type));
         qemu_register_reset(do_cpu_reset, cpu);
 
         if (i == 0) {
-            cpu0 = DEVICE(cpu);
             if (ms->kernel_filename) {
                 uint64_t entry = load_kernel(vms);
-                qdev_prop_set_uint32(cpu0, "exec-start-addr", entry);
+                qdev_prop_set_uint32(DEVICE(cpu), "exec-start-addr", entry);
             } else if (ms->firmware) {
                 uint64_t entry = load_bios(vms);
-                qdev_prop_set_uint32(cpu0, "exec-start-addr", entry);
+                qdev_prop_set_uint32(DEVICE(cpu), "exec-start-addr", entry);
             }
         }
         qdev_prop_set_uint32(DEVICE(cpu), "htid", i);
         qdev_prop_set_bit(DEVICE(cpu), "start-powered-off", (i != 0));
-        object_property_set_link(OBJECT(cpu), "global-regs",
-                                 OBJECT(gsregs_dev), &error_fatal);
-        object_property_set_link(OBJECT(cpu), "tlb",
-                                 OBJECT(tlb_dev), &error_fatal);
-
-        qdev_realize_and_unref(DEVICE(cpu), NULL, &error_fatal);
+        hex_subsys_realize_cpu(&vms->parent_obj, DEVICE(cpu));
     }
+
+    hex_subsys_realize_cluster(&vms->parent_obj);
+
     fdt_add_cpu_nodes(vms);
     clk_phandle = fdt_add_clocks(vms);
     fdt_add_uart(vms, VIRT_UART0, clk_phandle);
 
-    rom_add_blob_fixed_as("config_table.rom", &m_cfg->cfgtable,
-                          sizeof(m_cfg->cfgtable), m_cfg->cfgbase,
-                          &address_space_memory);
-
     hexagon_load_fdt(vms);
 }
 
diff --git a/hw/hexagon/Kconfig b/hw/hexagon/Kconfig
index 52065ab3b22..121c548bbb9 100644
--- a/hw/hexagon/Kconfig
+++ b/hw/hexagon/Kconfig
@@ -2,6 +2,7 @@ config HEX_DSP
     bool
     default y
     depends on HEXAGON
+    select CPU_CLUSTER
 
 config HEX_VIRT
     bool
diff --git a/hw/hexagon/meson.build b/hw/hexagon/meson.build
index bade3a32921..720a5d54dcc 100644
--- a/hw/hexagon/meson.build
+++ b/hw/hexagon/meson.build
@@ -1,6 +1,7 @@
 hexagon_ss = ss.source_set()
 hexagon_ss.add(files('hexagon_tlb.c'))
 hexagon_ss.add(files('hexagon_globalreg.c'))
+hexagon_ss.add(when: 'CONFIG_HEX_DSP', if_true: files('hex-subsys.c'))
 hexagon_ss.add(when: 'CONFIG_HEX_DSP', if_true: files('hexagon_dsp.c'))
 hexagon_ss.add(when: 'CONFIG_HEX_VIRT', if_true: files('virt.c'))
 
-- 
2.34.1

Reply via email to