/* * Build NUMA Toplogy with cell id starting from (0 + seq) * for testing */ static virCapsPtr buildNUMATopology(int seq) { virCapsPtr caps; virCapsHostNUMACellCPUPtr cell_cpus = NULL; int core_id, cell_id; int id; if ((caps = virCapabilitiesNew(VIR_ARCH_X86_64, false, false)) == NULL) goto error; id = 0; for (cell_id = 0; cell_id < MAX_CELLS; cell_id++) { if (VIR_ALLOC_N(cell_cpus, MAX_CPUS_IN_CELL) < 0) goto error; for (core_id = 0; core_id < MAX_CPUS_IN_CELL; core_id++) { cell_cpus[core_id].id = id + core_id; cell_cpus[core_id].socket_id = cell_id + seq; cell_cpus[core_id].core_id = id + core_id; if (!(cell_cpus[core_id].siblings = virBitmapNew(MAX_CPUS_IN_CELL))) goto error; ignore_value(virBitmapSetBit(cell_cpus[core_id].siblings, id)); } id++; if (virCapabilitiesAddHostNUMACell(caps, cell_id + seq, MAX_MEM_IN_CELL, MAX_CPUS_IN_CELL, cell_cpus, VIR_ARCH_NONE, NULL, VIR_ARCH_NONE, NULL) < 0) goto error; cell_cpus = NULL; } return caps; error: virCapabilitiesClearHostNUMACellCPUTopology(cell_cpus, MAX_CPUS_IN_CELL); VIR_FREE(cell_cpus); virObjectUnref(caps); return NULL; }
static int libxlCapsInitNuma(libxl_ctx *ctx, virCapsPtr caps) { libxl_numainfo *numa_info = NULL; libxl_cputopology *cpu_topo = NULL; int nr_nodes = 0, nr_cpus = 0; virCapsHostNUMACellCPUPtr *cpus = NULL; int *nr_cpus_node = NULL; size_t i; int ret = -1; /* Let's try to fetch all the topology information */ numa_info = libxl_get_numainfo(ctx, &nr_nodes); if (numa_info == NULL || nr_nodes == 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("libxl_get_numainfo failed")); goto cleanup; } else { cpu_topo = libxl_get_cpu_topology(ctx, &nr_cpus); if (cpu_topo == NULL || nr_cpus == 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("libxl_get_cpu_topology failed")); goto cleanup; } } if (VIR_ALLOC_N(cpus, nr_nodes) < 0) goto cleanup; if (VIR_ALLOC_N(nr_cpus_node, nr_nodes) < 0) goto cleanup; /* For each node, prepare a list of CPUs belonging to that node */ for (i = 0; i < nr_cpus; i++) { int node = cpu_topo[i].node; if (cpu_topo[i].core == LIBXL_CPUTOPOLOGY_INVALID_ENTRY) continue; nr_cpus_node[node]++; if (nr_cpus_node[node] == 1) { if (VIR_ALLOC(cpus[node]) < 0) goto cleanup; } else { if (VIR_REALLOC_N(cpus[node], nr_cpus_node[node]) < 0) goto cleanup; } /* Mapping between what libxl tells and what libvirt wants */ cpus[node][nr_cpus_node[node]-1].id = i; cpus[node][nr_cpus_node[node]-1].socket_id = cpu_topo[i].socket; cpus[node][nr_cpus_node[node]-1].core_id = cpu_topo[i].core; /* Allocate the siblings maps. We will be filling them later */ cpus[node][nr_cpus_node[node]-1].siblings = virBitmapNew(nr_cpus); if (!cpus[node][nr_cpus_node[node]-1].siblings) { virReportOOMError(); goto cleanup; } } /* Let's now populate the siblings bitmaps */ for (i = 0; i < nr_cpus; i++) { int node = cpu_topo[i].node; size_t j; if (cpu_topo[i].core == LIBXL_CPUTOPOLOGY_INVALID_ENTRY) continue; for (j = 0; j < nr_cpus_node[node]; j++) { if (cpus[node][j].socket_id == cpu_topo[i].socket && cpus[node][j].core_id == cpu_topo[i].core) ignore_value(virBitmapSetBit(cpus[node][j].siblings, i)); } } for (i = 0; i < nr_nodes; i++) { if (numa_info[i].size == LIBXL_NUMAINFO_INVALID_ENTRY) continue; if (virCapabilitiesAddHostNUMACell(caps, i, nr_cpus_node[i], numa_info[i].size / 1024, cpus[i]) < 0) { virCapabilitiesClearHostNUMACellCPUTopology(cpus[i], nr_cpus_node[i]); goto cleanup; } /* This is safe, as the CPU list is now stored in the NUMA cell */ cpus[i] = NULL; } ret = 0; cleanup: if (ret != 0) { for (i = 0; cpus && i < nr_nodes; i++) VIR_FREE(cpus[i]); virCapabilitiesFreeNUMAInfo(caps); } VIR_FREE(cpus); VIR_FREE(nr_cpus_node); libxl_cputopology_list_free(cpu_topo, nr_cpus); libxl_numainfo_list_free(numa_info, nr_nodes); return ret; }
int nodeCapsInitNUMA(virCapsPtr caps) { int n; unsigned long *mask = NULL; unsigned long *allonesmask = NULL; int *cpus = NULL; int ret = -1; int max_n_cpus = NUMA_MAX_N_CPUS; if (numa_available() < 0) return 0; int mask_n_bytes = max_n_cpus / 8; if (VIR_ALLOC_N(mask, mask_n_bytes / sizeof *mask) < 0) goto cleanup; if (VIR_ALLOC_N(allonesmask, mask_n_bytes / sizeof *mask) < 0) goto cleanup; memset(allonesmask, 0xff, mask_n_bytes); for (n = 0 ; n <= numa_max_node() ; n++) { int i; int ncpus; /* The first time this returns -1, ENOENT if node doesn't exist... */ if (numa_node_to_cpus(n, mask, mask_n_bytes) < 0) { VIR_WARN("NUMA topology for cell %d of %d not available, ignoring", n, numa_max_node()+1); continue; } /* second, third... times it returns an all-1's mask */ if (memcmp(mask, allonesmask, mask_n_bytes) == 0) { VIR_DEBUG("NUMA topology for cell %d of %d is all ones, ignoring", n, numa_max_node()+1); continue; } for (ncpus = 0, i = 0 ; i < max_n_cpus ; i++) if (MASK_CPU_ISSET(mask, i)) ncpus++; if (VIR_ALLOC_N(cpus, ncpus) < 0) goto cleanup; for (ncpus = 0, i = 0 ; i < max_n_cpus ; i++) if (MASK_CPU_ISSET(mask, i)) cpus[ncpus++] = i; if (virCapabilitiesAddHostNUMACell(caps, n, ncpus, cpus) < 0) goto cleanup; VIR_FREE(cpus); } ret = 0; cleanup: VIR_FREE(cpus); VIR_FREE(mask); VIR_FREE(allonesmask); return ret; }
static virCapsPtr buildVirCapabilities(int max_cells, int max_cpus_in_cell, int max_mem_in_cell) { virCapsPtr caps; virCapsHostNUMACellCPUPtr cell_cpus = NULL; virCapsHostNUMACellSiblingInfoPtr siblings = NULL; int core_id, cell_id, nsiblings; int id; size_t i; if ((caps = virCapabilitiesNew(VIR_ARCH_X86_64, 0, 0)) == NULL) goto error; id = 0; for (cell_id = 0; cell_id < max_cells; cell_id++) { if (VIR_ALLOC_N(cell_cpus, max_cpus_in_cell) < 0) goto error; for (core_id = 0; core_id < max_cpus_in_cell; core_id++) { cell_cpus[core_id].id = id; cell_cpus[core_id].socket_id = cell_id; cell_cpus[core_id].core_id = id + core_id; if (!(cell_cpus[core_id].siblings = virBitmapNew(max_cpus_in_cell))) goto error; ignore_value(virBitmapSetBit(cell_cpus[core_id].siblings, id)); } id++; if (VIR_ALLOC_N(siblings, max_cells) < 0) goto error; nsiblings = max_cells; for (i = 0; i < nsiblings; i++) { siblings[i].node = i; /* Some magical constants, see virNumaGetDistances() * for their description. */ siblings[i].distance = cell_id == i ? 10 : 20; } if (virCapabilitiesAddHostNUMACell(caps, cell_id, max_mem_in_cell, max_cpus_in_cell, cell_cpus, nsiblings, siblings, 0, NULL) < 0) goto error; cell_cpus = NULL; siblings = NULL; } return caps; error: virCapabilitiesClearHostNUMACellCPUTopology(cell_cpus, max_cpus_in_cell); VIR_FREE(cell_cpus); VIR_FREE(siblings); virObjectUnref(caps); return NULL; }