]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
hw/arm/virt: Remember CPU phandles rather than looking them up by name
authorPeter Maydell <peter.maydell@linaro.org>
Fri, 27 Mar 2026 11:16:51 +0000 (11:16 +0000)
committerPeter Maydell <peter.maydell@linaro.org>
Thu, 7 May 2026 14:14:58 +0000 (15:14 +0100)
In fdt_add_cpu_nodes(), we currently add phandles for each CPU node
if we are going to add a topology description, and when we do, we
re-look-up the phandle by node name when creating the topology
description.

For GICv5 we will also want to refer to the CPU phandles; so always
add a phandle, and keep track of those phandles in the
VirtMachineState so we don't have to look them up by name in the dtb
every time.

The phandle property is extra data in the final DTB, but only a tiny
amount, so it's not worth trying to carefully track the conditions
when we're going to need them so we only emit them when required.

(We need to change the smp_cpus variable to unsigned because
otherwise gcc thinks that we might be passing a negative number to
g_new0() and produces an error:

/usr/include/glib-2.0/glib/gmem.h:270:19: error: argument 1 range [1844674407156206796818446744073709551615] exceeds maximum object size 9223372036854775807 [-Werror=alloc-size-larger-than=]
  270 |             __p = g_##func##_n (__n, __s);                      \
      |                   ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/glib-2.0/glib/gmem.h:332:57: note: in expansion of macro ‘_G_NEW’
  332 | #define g_new0(struct_type, n_structs)                  _G_NEW (struct_type, n_structs, malloc0)
      |                                                         ^~~~~~
../../hw/arm/virt.c:469:25: note: in expansion of macro ‘g_new0’
  469 |     vms->cpu_phandles = g_new0(uint32_t, smp_cpus);
      |                         ^~~~~~

)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Message-id: 20260327111700.795099-57-peter.maydell@linaro.org

hw/arm/virt.c
include/hw/arm/virt.h

index fe19030886bb8d525e966b88ae020f66a2aec207..58e05acb8cd386c87cdc5d301b609ba0600153ca 100644 (file)
@@ -595,14 +595,14 @@ static bool partial_cache_description(const MachineState *ms, int num_caches)
     return false;
 }
 
-static void fdt_add_cpu_nodes(const VirtMachineState *vms)
+static void fdt_add_cpu_nodes(VirtMachineState *vms)
 {
     int cpu;
     int addr_cells = 1;
     const MachineState *ms = MACHINE(vms);
     const MachineClass *mc = MACHINE_GET_CLASS(ms);
     const VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
-    int smp_cpus = ms->smp.cpus;
+    unsigned int smp_cpus = ms->smp.cpus;
     int socket_id, cluster_id, core_id;
     uint32_t next_level = 0;
     uint32_t socket_offset = 0;
@@ -656,6 +656,8 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
     qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#address-cells", addr_cells);
     qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#size-cells", 0x0);
 
+    vms->cpu_phandles = g_new0(uint32_t, smp_cpus);
+
     for (cpu = smp_cpus - 1; cpu >= 0; cpu--) {
         socket_id = cpu / (ms->smp.clusters * ms->smp.cores * ms->smp.threads);
         cluster_id = cpu / (ms->smp.cores * ms->smp.threads) % ms->smp.clusters;
@@ -665,6 +667,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
         ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
         CPUState *cs = CPU(armcpu);
         const char *prefix = NULL;
+        uint32_t phandle;
 
         qemu_fdt_add_subnode(ms->fdt, nodename);
         qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "cpu");
@@ -689,10 +692,9 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
                 ms->possible_cpus->cpus[cs->cpu_index].props.node_id);
         }
 
-        if (!vmc->no_cpu_topology) {
-            qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
-                                  qemu_fdt_alloc_phandle(ms->fdt));
-        }
+        phandle = qemu_fdt_alloc_phandle(ms->fdt);
+        qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", phandle);
+        vms->cpu_phandles[cpu] = phandle;
 
         if (!vmc->no_cpu_topology && num_cache) {
             for (uint8_t i = 0; i < num_cache; i++) {
@@ -847,7 +849,6 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
         qemu_fdt_add_subnode(ms->fdt, "/cpus/cpu-map");
 
         for (cpu = smp_cpus - 1; cpu >= 0; cpu--) {
-            char *cpu_path = g_strdup_printf("/cpus/cpu@%d", cpu);
             char *map_path;
 
             if (ms->smp.threads > 1) {
@@ -865,10 +866,10 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
                     cpu % ms->smp.cores);
             }
             qemu_fdt_add_path(ms->fdt, map_path);
-            qemu_fdt_setprop_phandle(ms->fdt, map_path, "cpu", cpu_path);
+            qemu_fdt_setprop_cell(ms->fdt, map_path, "cpu",
+                                  vms->cpu_phandles[cpu]);
 
             g_free(map_path);
-            g_free(cpu_path);
         }
     }
 }
index 13e135a4606722aa1780acfa9495b9c82e8f31d3..b74ffada7e1d1463357adf080be830a92bb4ec77 100644 (file)
@@ -176,6 +176,7 @@ struct VirtMachineState {
     uint32_t gic_phandle;
     uint32_t msi_phandle;
     uint32_t iommu_phandle;
+    uint32_t *cpu_phandles;
     int psci_conduit;
     uint8_t virtio_transports;
     hwaddr highest_gpa;