@@ -1684,6 +1684,10 @@ void machine_run_board_post_init(MachineState *machine, Error **errp)
{
MachineClass *machine_class = MACHINE_GET_CLASS(machine);
+ if (!machine_validate_topo_tree(machine, errp)) {
+ return;
+ }
+
if (machine_class->post_init) {
machine_class->post_init(machine);
}
@@ -47,6 +47,7 @@ static void cpu_slot_device_realize(DeviceListener *listener,
{
CPUSlot *slot = container_of(listener, CPUSlot, listener);
CPUTopoState *topo;
+ int max_children;
if (!object_dynamic_cast(OBJECT(dev), TYPE_CPU_TOPO)) {
return;
@@ -54,6 +55,13 @@ static void cpu_slot_device_realize(DeviceListener *listener,
topo = CPU_TOPO(dev);
cpu_slot_add_topo_info(slot, topo);
+
+ if (dev->parent_bus) {
+ max_children = slot->stat.entries[GET_CPU_TOPO_LEVEL(topo)].max_limit;
+ if (dev->parent_bus->num_children == max_children) {
+ qbus_mark_full(dev->parent_bus);
+ }
+ }
}
static void cpu_slot_del_topo_info(CPUSlot *slot, CPUTopoState *topo)
@@ -79,6 +87,10 @@ static void cpu_slot_device_unrealize(DeviceListener *listener,
topo = CPU_TOPO(dev);
cpu_slot_del_topo_info(slot, topo);
+
+ if (dev->parent_bus) {
+ qbus_mask_full(dev->parent_bus);
+ }
}
DeviceListener cpu_slot_device_listener = {
@@ -443,3 +455,23 @@ bool machine_parse_custom_topo_config(MachineState *ms,
return true;
}
+
+bool machine_validate_topo_tree(MachineState *ms, Error **errp)
+{
+ int cpus;
+
+ if (!ms->topo || !ms->topo->custom_topo_enabled) {
+ return true;
+ }
+
+ cpus = ms->topo->stat.entries[CPU_TOPOLOGY_LEVEL_THREAD].total_instances;
+ if (cpus < ms->smp.cpus) {
+ error_setg(errp, "machine requires at least %d online CPUs, "
+ "but currently only %d CPUs",
+ ms->smp.cpus, cpus);
+ return false;
+ }
+
+ /* TODO: Add checks for other levels to honor more -smp parameters. */
+ return true;
+}
@@ -84,5 +84,6 @@ int get_max_topo_by_level(const MachineState *ms, CpuTopologyLevel level);
bool machine_parse_custom_topo_config(MachineState *ms,
const SMPConfiguration *config,
Error **errp);
+bool machine_validate_topo_tree(MachineState *ms, Error **errp);
#endif /* CPU_SLOT_H */
@@ -1063,6 +1063,11 @@ static inline void qbus_mark_full(BusState *bus)
bus->full = true;
}
+static inline void qbus_mask_full(BusState *bus)
+{
+ bus->full = false;
+}
+
void device_listener_register(DeviceListener *listener);
void device_listener_unregister(DeviceListener *listener);
Apply max_limit to CPU topology and prevent the number of topology devices from exceeding the max limitation configured by user. Additionally, ensure that CPUs created from the CLI via custom topology meet at least the requirements of smp.cpus. This guarantees that custom topology will always have CPUs. Signed-off-by: Zhao Liu <zhao1.liu@intel.com> --- hw/core/machine.c | 4 ++++ hw/cpu/cpu-slot.c | 32 ++++++++++++++++++++++++++++++++ include/hw/cpu/cpu-slot.h | 1 + include/hw/qdev-core.h | 5 +++++ 4 files changed, 42 insertions(+)