bitmap_or(seen_cpus, seen_cpus,
numa_info[i].node_cpu, MAX_CPUMASK_BITS);
}
+
+ if (!bitmap_full(seen_cpus, max_cpus)) {
+ char *msg;
+ bitmap_complement(seen_cpus, seen_cpus, max_cpus);
+ msg = enumerate_cpus(seen_cpus, max_cpus);
+ error_report("warning: CPU(s) not present in any NUMA nodes: %s", msg);
+ error_report("warning: All CPU(s) up to maxcpus should be described "
+ "in NUMA config");
+ g_free(msg);
+ }
}
-void parse_numa_opts(void)
+void parse_numa_opts(MachineClass *mc)
{
int i;
break;
}
}
- /* assigning the VCPUs round-robin is easier to implement, guest OSes
- * must cope with this anyway, because there are BIOSes out there in
- * real machines which also use this scheme.
+ /* Historically VCPUs were assigned in round-robin order to NUMA
+ * nodes. However it causes issues with guest not handling it nice
+ * in case where cores/threads from a multicore CPU appear on
+ * different nodes. So allow boards to override default distribution
+ * rule grouping VCPUs by socket so that VCPUs from the same socket
+ * would be on the same node.
*/
if (i == nb_numa_nodes) {
for (i = 0; i < max_cpus; i++) {
- set_bit(i, numa_info[i % nb_numa_nodes].node_cpu);
+ unsigned node_id = i % nb_numa_nodes;
+ if (mc->cpu_index_to_socket_id) {
+ node_id = mc->cpu_index_to_socket_id(i) % nb_numa_nodes;
+ }
+
+ set_bit(i, numa_info[node_id].node_cpu);
}
}