void numa_set_mem_node_id(ram_addr_t addr, uint64_t size, uint32_t node)
{
- struct numa_addr_range *range = g_malloc0(sizeof(*range));
+ struct numa_addr_range *range;
+ /*
+ * Memory-less nodes can come here with 0 size in which case,
+ * there is nothing to do.
+ */
+ if (!size) {
+ return;
+ }
+
+ range = g_malloc0(sizeof(*range));
range->mem_start = addr;
range->mem_end = addr + size - 1;
QLIST_INSERT_HEAD(&numa_info[node].addr, range, entry);
}
}
+static void numa_set_mem_ranges(void)
+{
+ int i;
+ ram_addr_t mem_start = 0;
+
+ /*
+ * Deduce start address of each node and use it to store
+ * the address range info in numa_info address range list
+ */
+ for (i = 0; i < nb_numa_nodes; i++) {
+ numa_set_mem_node_id(mem_start, numa_info[i].node_mem, i);
+ mem_start += numa_info[i].node_mem;
+ }
+}
+
+/*
+ * Check if @addr falls under NUMA @node.
+ */
+static bool numa_addr_belongs_to_node(ram_addr_t addr, uint32_t node)
+{
+ struct numa_addr_range *range;
+
+ QLIST_FOREACH(range, &numa_info[node].addr, entry) {
+ if (addr >= range->mem_start && addr <= range->mem_end) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+ * Given an address, return the index of the NUMA node to which the
+ * address belongs to.
+ */
+uint32_t numa_get_node(ram_addr_t addr, Error **errp)
+{
+ uint32_t i;
+
+ /* For non NUMA configurations, check if the addr falls under node 0 */
+ if (!nb_numa_nodes) {
+ if (numa_addr_belongs_to_node(addr, 0)) {
+ return 0;
+ }
+ }
+
+ for (i = 0; i < nb_numa_nodes; i++) {
+ if (numa_addr_belongs_to_node(addr, i)) {
+ return i;
+ }
+ }
+
+ error_setg(errp, "Address 0x" RAM_ADDR_FMT " doesn't belong to any "
+ "NUMA node", addr);
+ return -1;
+}
+
static void numa_node_parse(NumaNodeOptions *node, QemuOpts *opts, Error **errp)
{
uint16_t nodenr;
goto error;
}
- switch (object->kind) {
+ switch (object->type) {
case NUMA_OPTIONS_KIND_NODE:
- numa_node_parse(object->node, opts, &err);
+ numa_node_parse(object->u.node, opts, &err);
if (err) {
goto error;
}
bitmap_and(seen_cpus, seen_cpus,
numa_info[i].node_cpu, MAX_CPUMASK_BITS);
error_report("CPU(s) present in multiple NUMA nodes: %s",
- enumerate_cpus(seen_cpus, max_cpus));;
+ enumerate_cpus(seen_cpus, max_cpus));
exit(EXIT_FAILURE);
}
bitmap_or(seen_cpus, seen_cpus,
QLIST_INIT(&numa_info[i].addr);
}
+ numa_set_mem_ranges();
+
for (i = 0; i < nb_numa_nodes; i++) {
if (!bitmap_empty(numa_info[i].node_cpu, MAX_CPUMASK_BITS)) {
break;
}
validate_numa_cpus();
+ } else {
+ numa_set_mem_node_id(0, ram_size, 0);
}
}
*/
if (err) {
error_report_err(err);
- memory_region_init_ram(mr, owner, name, ram_size, &error_abort);
+ memory_region_init_ram(mr, owner, name, ram_size, &error_fatal);
}
#else
fprintf(stderr, "-mem-path not supported on this host\n");
exit(1);
#endif
} else {
- memory_region_init_ram(mr, owner, name, ram_size, &error_abort);
+ memory_region_init_ram(mr, owner, name, ram_size, &error_fatal);
}
vmstate_register_ram_global(mr);
}
MemoryDeviceInfo *value = info->value;
if (value) {
- switch (value->kind) {
+ switch (value->type) {
case MEMORY_DEVICE_INFO_KIND_DIMM:
- node_mem[value->dimm->node] += value->dimm->size;
+ node_mem[value->u.dimm->node] += value->u.dimm->size;
break;
default:
break;