@@ -22,14 +22,44 @@
#include "hw/core/cpu-slot.h"
+static inline
+CPUTopoStatEntry *get_topo_stat_entry(CPUTopoStat *stat,
+ CPUTopoLevel level)
+{
+ assert(level != CPU_TOPO_UNKNOWN);
+
+ return &stat->entries[TOPO_STAT_ENTRY_IDX(level)];
+}
+
static void cpu_slot_add_topo_info(CPUTopoState *root, CPUTopoState *child)
{
CPUSlot *slot = CPU_SLOT(root);
CPUTopoLevel level = CPU_TOPO_LEVEL(child);
+ CPUTopoStatEntry *entry;
if (level == CPU_TOPO_CORE) {
- QTAILQ_INSERT_TAIL(&slot->cores, CPU_CORE(child), node);
+ CPUCore *core = CPU_CORE(child);
+ CPUTopoStatEntry *thread_entry;
+
+ QTAILQ_INSERT_TAIL(&slot->cores, core, node);
+
+ /* Max CPUs per core is pre-configured by "nr-threads". */
+ slot->stat.max_cpus += core->nr_threads;
+ slot->stat.pre_plugged_cpus += core->plugged_threads;
+
+ thread_entry = get_topo_stat_entry(&slot->stat, CPU_TOPO_THREAD);
+ if (child->max_children > thread_entry->max_units) {
+ thread_entry->max_units = child->max_children;
+ }
}
+
+ entry = get_topo_stat_entry(&slot->stat, level);
+ entry->total_units++;
+ if (child->parent->num_children > entry->max_units) {
+ entry->max_units = child->parent->num_children;
+ }
+
+ set_bit(level, slot->stat.curr_levels);
return;
}
@@ -37,10 +67,18 @@ static void cpu_slot_del_topo_info(CPUTopoState *root, CPUTopoState *child)
{
CPUSlot *slot = CPU_SLOT(root);
CPUTopoLevel level = CPU_TOPO_LEVEL(child);
+ CPUTopoStatEntry *entry;
+
+ assert(level != CPU_TOPO_UNKNOWN);
if (level == CPU_TOPO_CORE) {
QTAILQ_REMOVE(&slot->cores, CPU_CORE(child), node);
}
+
+ entry = get_topo_stat_entry(&slot->stat, level);
+ entry->total_units--;
+
+ /* No need to update entries[*].max_units and curr_levels. */
return;
}
@@ -73,6 +111,7 @@ static void cpu_slot_instance_init(Object *obj)
CPUSlot *slot = CPU_SLOT(obj);
QTAILQ_INIT(&slot->cores);
+ set_bit(CPU_TOPO_ROOT, slot->stat.curr_levels);
}
static const TypeInfo cpu_slot_type_info = {
@@ -25,6 +25,47 @@
#include "hw/cpu/core.h"
#include "hw/qdev-core.h"
+/**
+ * @USER_AVAIL_LEVEL_NUM: the number of total topology levels in topology
+ * bitmap, which includes CPU_TOPO_UNKNOWN.
+ */
+#define USER_AVAIL_LEVEL_NUM (CPU_TOPO_ROOT + 1)
+
+/**
+ * @VALID_LEVEL_NUM: the number of valid topology levels, which excludes
+ * CPU_TOPO_UNKNOWN and CPU_TOPO_ROOT.
+ */
+#define VALID_LEVEL_NUM (CPU_TOPO_ROOT - 1)
+
+#define TOPO_STAT_ENTRY_IDX(level) ((level) - 1)
+
+/**
+ * CPUTopoStatEntry:
+ * @total: Total number of topological units at the same level that are
+ * currently inserted in CPU slot
+ * @max: Maximum number of topological units at the same level under the
+ * parent topolofical container
+ */
+typedef struct CPUTopoStatEntry {
+ unsigned int total_units;
+ unsigned int max_units;
+} CPUTopoStatEntry;
+
+/**
+ * CPUTopoStat:
+ * @max_cpus: Maximum number of CPUs in CPU slot.
+ * @pre_plugged_cpus: Number of pre-plugged CPUs in CPU slot.
+ * @entries: Detail count information for valid topology levels under
+ * CPU slot
+ * @curr_levels: Current CPU topology levels inserted in CPU slot
+ */
+typedef struct CPUTopoStat {
+ unsigned int max_cpus;
+ unsigned int pre_plugged_cpus;
+ CPUTopoStatEntry entries[VALID_LEVEL_NUM];
+ DECLARE_BITMAP(curr_levels, USER_AVAIL_LEVEL_NUM);
+} CPUTopoStat;
+
#define TYPE_CPU_SLOT "cpu-slot"
OBJECT_DECLARE_SIMPLE_TYPE(CPUSlot, CPU_SLOT)
@@ -35,6 +76,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(CPUSlot, CPU_SLOT)
* where the cpu-slot is the root. cpu-slot can maintain similar
* queues for other topology levels to facilitate traversal
* when necessary.
+ * @stat: Statistical topology information for topology tree.
*/
struct CPUSlot {
/*< private >*/
@@ -42,6 +84,7 @@ struct CPUSlot {
/*< public >*/
QTAILQ_HEAD(, CPUCore) cores;
+ CPUTopoStat stat;
};
#endif /* CPU_SLOT_H */