diff mbox series

[RFC,v2,04/15] hw/cpu: Introduce CPU slot to manage CPU topology

Message ID 20240919015533.766754-5-zhao1.liu@intel.com (mailing list archive)
State New
Headers show
Series qom-topo: Abstract CPU Topology Level to Topology Device | expand

Commit Message

Zhao Liu Sept. 19, 2024, 1:55 a.m. UTC
When there's a CPU topology tree, original MachineState.smp (CpuTopology
structure) is not enough to dynamically monitor changes of the tree or
update topology information in time.

To address this, introduce the CPU slot, as the root of CPU topology
tree, which is used to update and maintain global topological statistics
by listening any changes of topology device (realize() and unrealize()).

Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
---
 MAINTAINERS               |   2 +
 hw/cpu/cpu-slot.c         | 140 ++++++++++++++++++++++++++++++++++++++
 hw/cpu/meson.build        |   1 +
 include/hw/cpu/cpu-slot.h |  72 ++++++++++++++++++++
 4 files changed, 215 insertions(+)
 create mode 100644 hw/cpu/cpu-slot.c
 create mode 100644 include/hw/cpu/cpu-slot.h
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 230267597b5f..8e5b2cd91dca 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1884,6 +1884,7 @@  F: hw/core/machine-smp.c
 F: hw/core/null-machine.c
 F: hw/core/numa.c
 F: hw/cpu/cluster.c
+F: hw/cpu/cpu-slot.c
 F: hw/cpu/cpu-topology.c
 F: qapi/machine.json
 F: qapi/machine-common.json
@@ -1891,6 +1892,7 @@  F: qapi/machine-target.json
 F: include/hw/boards.h
 F: include/hw/core/cpu.h
 F: include/hw/cpu/cluster.h
+F: include/hw/cpu/cpu-slot.h
 F: include/hw/cpu/cpu-topology.h
 F: include/sysemu/numa.h
 F: tests/functional/test_cpu_queries.py
diff --git a/hw/cpu/cpu-slot.c b/hw/cpu/cpu-slot.c
new file mode 100644
index 000000000000..66ef8d9faa97
--- /dev/null
+++ b/hw/cpu/cpu-slot.c
@@ -0,0 +1,140 @@ 
+/*
+ * CPU slot abstraction - manage CPU topology
+ *
+ * Copyright (C) 2024 Intel Corporation.
+ *
+ * Author: Zhao Liu <zhao1.liu@intel.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/boards.h"
+#include "hw/cpu/cpu-slot.h"
+#include "hw/cpu/cpu-topology.h"
+#include "hw/qdev-core.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "qapi/error.h"
+
+static void cpu_slot_add_topo_info(CPUSlot *slot, CPUTopoState *topo)
+{
+    CpuTopologyLevel level = GET_CPU_TOPO_LEVEL(topo);
+    CPUTopoStatEntry *entry;
+    int instances_num;
+
+    entry = &slot->stat.entries[level];
+    entry->total_instances++;
+
+    instances_num = cpu_topo_get_instances_num(topo);
+    if (instances_num > entry->max_instances) {
+        entry->max_instances = instances_num;
+    }
+
+    set_bit(level, slot->stat.curr_levels);
+
+    return;
+}
+
+static void cpu_slot_device_realize(DeviceListener *listener,
+                                    DeviceState *dev)
+{
+    CPUSlot *slot = container_of(listener, CPUSlot, listener);
+    CPUTopoState *topo;
+
+    if (!object_dynamic_cast(OBJECT(dev), TYPE_CPU_TOPO)) {
+        return;
+    }
+
+    topo = CPU_TOPO(dev);
+    cpu_slot_add_topo_info(slot, topo);
+}
+
+static void cpu_slot_del_topo_info(CPUSlot *slot, CPUTopoState *topo)
+{
+    CpuTopologyLevel level = GET_CPU_TOPO_LEVEL(topo);
+    CPUTopoStatEntry *entry;
+
+    entry = &slot->stat.entries[level];
+    entry->total_instances--;
+
+    return;
+}
+
+static void cpu_slot_device_unrealize(DeviceListener *listener,
+                                      DeviceState *dev)
+{
+    CPUSlot *slot = container_of(listener, CPUSlot, listener);
+    CPUTopoState *topo;
+
+    if (!object_dynamic_cast(OBJECT(dev), TYPE_CPU_TOPO)) {
+        return;
+    }
+
+    topo = CPU_TOPO(dev);
+    cpu_slot_del_topo_info(slot, topo);
+}
+
+DeviceListener cpu_slot_device_listener = {
+    .realize = cpu_slot_device_realize,
+    .unrealize = cpu_slot_device_unrealize,
+};
+
+static bool slot_bus_check_topology(CPUBusState *cbus,
+                                    CPUTopoState *topo,
+                                    Error **errp)
+{
+    CPUSlot *slot = CPU_SLOT(BUS(cbus)->parent);
+    CpuTopologyLevel level = GET_CPU_TOPO_LEVEL(topo);
+
+    if (!test_bit(level, slot->supported_levels)) {
+        error_setg(errp, "cpu topo: level %s is not supported",
+                   CpuTopologyLevel_str(level));
+        return false;
+    }
+    return true;
+}
+
+static void cpu_slot_realize(DeviceState *dev, Error **errp)
+{
+    CPUSlot *slot = CPU_SLOT(dev);
+
+    slot->listener = cpu_slot_device_listener;
+    device_listener_register(&slot->listener);
+
+    qbus_init(&slot->bus, sizeof(CPUBusState),
+              TYPE_CPU_BUS, dev, "cpu-slot");
+    slot->bus.check_topology = slot_bus_check_topology;
+}
+
+static void cpu_slot_unrealize(DeviceState *dev)
+{
+    CPUSlot *slot = CPU_SLOT(dev);
+
+    device_listener_unregister(&slot->listener);
+}
+
+static void cpu_slot_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+    dc->realize = cpu_slot_realize;
+    dc->unrealize = cpu_slot_unrealize;
+}
+
+static const TypeInfo cpu_slot_type_info = {
+    .name = TYPE_CPU_SLOT,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .class_init = cpu_slot_class_init,
+    .instance_size = sizeof(CPUSlot),
+};
+
+static void cpu_slot_register_types(void)
+{
+    type_register_static(&cpu_slot_type_info);
+}
+
+type_init(cpu_slot_register_types)
diff --git a/hw/cpu/meson.build b/hw/cpu/meson.build
index 6c6546646608..358e2b3960fa 100644
--- a/hw/cpu/meson.build
+++ b/hw/cpu/meson.build
@@ -1,6 +1,7 @@ 
 common_ss.add(files('cpu-topology.c'))
 
 system_ss.add(files('core.c'))
+system_ss.add(files('cpu-slot.c'))
 system_ss.add(when: 'CONFIG_CPU_CLUSTER', if_true: files('cluster.c'))
 
 system_ss.add(when: 'CONFIG_ARM11MPCORE', if_true: files('arm11mpcore.c'))
diff --git a/include/hw/cpu/cpu-slot.h b/include/hw/cpu/cpu-slot.h
new file mode 100644
index 000000000000..9d02d5de578e
--- /dev/null
+++ b/include/hw/cpu/cpu-slot.h
@@ -0,0 +1,72 @@ 
+/*
+ * CPU slot abstraction header
+ *
+ * Copyright (C) 2024 Intel Corporation.
+ *
+ * Author: Zhao Liu <zhao1.liu@intel.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#ifndef CPU_SLOT_H
+#define CPU_SLOT_H
+
+#include "hw/cpu/cpu-topology.h"
+#include "hw/qdev-core.h"
+#include "hw/sysbus.h"
+#include "qapi/qapi-types-machine-common.h"
+#include "qom/object.h"
+
+/**
+ * CPUTopoStatEntry:
+ * @total_instances: Total number of topological instances at the same level
+ *                   that are currently inserted in CPU slot
+ * @max_instances: Maximum number of topological instances at the same level
+ *                 under the parent topological container
+ */
+typedef struct CPUTopoStatEntry {
+    int total_instances;
+    int max_instances;
+} CPUTopoStatEntry;
+
+/**
+ * CPUTopoStat:
+ * @entries: Detail count information for valid topology levels under
+ *           CPU slot
+ * @curr_levels: Current CPU topology levels inserted in CPU slot
+ */
+typedef struct CPUTopoStat {
+    /* TODO: Exclude invalid and default levels. */
+    CPUTopoStatEntry entries[CPU_TOPOLOGY_LEVEL__MAX];
+    DECLARE_BITMAP(curr_levels, CPU_TOPOLOGY_LEVEL__MAX);
+} CPUTopoStat;
+
+#define TYPE_CPU_SLOT "cpu-slot"
+OBJECT_DECLARE_SIMPLE_TYPE(CPUSlot, CPU_SLOT)
+
+/**
+ * CPUSlot:
+ * @cores: Queue consisting of all the cores in the topology tree
+ *     where the cpu-slot is the root. cpu-slot can maintain similar
+ *     queues for other topology levels to facilitate traversal
+ *     when necessary.
+ * @stat: Topological statistics for topology tree.
+ * @bus: CPU bus to add the children topology device.
+ * @supported_levels: Supported topology levels for topology tree.
+ * @listener: Hooks to listen realize() and unrealize() of topology
+ *            device.
+ */
+struct CPUSlot {
+    /*< private >*/
+    SysBusDevice parent_obj;
+
+    /*< public >*/
+    CPUBusState bus;
+    CPUTopoStat stat;
+    DECLARE_BITMAP(supported_levels, CPU_TOPOLOGY_LEVEL__MAX);
+
+    DeviceListener listener;
+};
+
+#endif /* CPU_SLOT_H */