libvirt/src/conf/numa_conf.c

1948 lines
57 KiB
C
Raw Normal View History

/*
* numa_conf.c
*
* Copyright (C) 2014-2015 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "numa_conf.h"
#include "domain_conf.h"
#include "viralloc.h"
#include "virnuma.h"
#include "virstring.h"
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
/*
* Distance definitions defined Conform ACPI 2.0 SLIT.
* See include/linux/topology.h
*/
#define LOCAL_DISTANCE 10
#define REMOTE_DISTANCE 20
/* SLIT entry value is a one-byte unsigned integer. */
#define UNREACHABLE 255
#define VIR_FROM_THIS VIR_FROM_DOMAIN
VIR_ENUM_IMPL(virDomainNumatuneMemMode,
VIR_DOMAIN_NUMATUNE_MEM_LAST,
"strict",
"preferred",
"interleave",
"restrictive",
);
VIR_ENUM_IMPL(virDomainNumatunePlacement,
VIR_DOMAIN_NUMATUNE_PLACEMENT_LAST,
"default",
"static",
"auto",
);
VIR_ENUM_IMPL(virDomainMemoryAccess,
VIR_DOMAIN_MEMORY_ACCESS_LAST,
"default",
"shared",
"private",
);
VIR_ENUM_IMPL(virDomainCacheAssociativity,
VIR_DOMAIN_CACHE_ASSOCIATIVITY_LAST,
"none",
"direct",
"full",
);
VIR_ENUM_IMPL(virDomainCachePolicy,
VIR_DOMAIN_CACHE_POLICY_LAST,
"none",
"writeback",
"writethrough",
);
VIR_ENUM_IMPL(virDomainMemoryLatency,
VIR_DOMAIN_MEMORY_LATENCY_LAST,
"none",
"access",
"read",
"write"
);
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
typedef struct _virDomainNumaDistance virDomainNumaDistance;
typedef struct _virDomainNumaCache virDomainNumaCache;
typedef struct _virDomainNumaInterconnect virDomainNumaInterconnect;
typedef struct _virDomainNumaNode virDomainNumaNode;
struct _virDomainNuma {
struct {
bool specified;
virBitmap *nodeset;
virDomainNumatuneMemMode mode;
virDomainNumatunePlacement placement;
} memory; /* pinning for all the memory */
struct _virDomainNumaNode {
unsigned long long mem; /* memory size in KiB */
virBitmap *cpumask; /* bitmap of vCPUs corresponding to the node */
virBitmap *nodeset; /* host memory nodes where this guest node resides */
virDomainNumatuneMemMode mode; /* memory mode selection */
virDomainMemoryAccess memAccess; /* shared memory access configuration */
virTristateBool discard; /* discard-data for memory-backend-file */
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
struct _virDomainNumaDistance {
unsigned int value; /* locality value for node i->j or j->i */
unsigned int cellid;
} *distances; /* remote node distances */
size_t ndistances;
struct _virDomainNumaCache {
unsigned int level; /* cache level */
unsigned int size; /* cache size */
unsigned int line; /* line size, !!! in bytes !!! */
virDomainCacheAssociativity associativity; /* cache associativity */
virDomainCachePolicy policy; /* cache policy */
} *caches;
size_t ncaches;
} *mem_nodes; /* guest node configuration */
size_t nmem_nodes;
struct _virDomainNumaInterconnect {
virDomainNumaInterconnectType type; /* whether structure describes latency
or bandwidth */
unsigned int initiator; /* the initiator NUMA node */
unsigned int target; /* the target NUMA node */
unsigned int cache; /* the target cache on @target; if 0 then the
memory on @target */
virDomainMemoryLatency accessType; /* what type of access is defined */
unsigned long value; /* value itself */
} *interconnects;
size_t ninterconnects;
/* Future NUMA tuning related stuff should go here. */
};
bool
virDomainNumatuneNodeSpecified(virDomainNuma *numatune,
int cellid)
{
if (numatune &&
cellid >= 0 &&
cellid < numatune->nmem_nodes)
return numatune->mem_nodes[cellid].nodeset;
return false;
}
static int
virDomainNumatuneNodeParseXML(virDomainNuma *numa,
xmlXPathContextPtr ctxt)
{
int n = 0;
size_t i = 0;
g_autofree xmlNodePtr *nodes = NULL;
if ((n = virXPathNodeSet("./numatune/memnode", ctxt, &nodes)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot extract memnode nodes"));
return -1;
}
if (!n)
return 0;
if (numa->memory.specified &&
numa->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Per-node binding is not compatible with "
"automatic NUMA placement."));
return -1;
}
if (!numa->nmem_nodes) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Element 'memnode' is invalid without "
"any guest NUMA cells"));
return -1;
}
for (i = 0; i < n; i++) {
unsigned int cellid = 0;
virDomainNumaNode *mem_node = NULL;
xmlNodePtr cur_node = nodes[i];
g_autofree char *tmp = NULL;
if (virXMLPropUInt(cur_node, "cellid", 10, VIR_XML_PROP_REQUIRED,
&cellid) < 0)
return -1;
if (cellid >= numa->nmem_nodes) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Argument 'cellid' in memnode element must "
"correspond to existing guest's NUMA cell"));
return -1;
}
mem_node = &numa->mem_nodes[cellid];
if (mem_node->nodeset) {
virReportError(VIR_ERR_XML_ERROR,
_("Multiple memnode elements with cellid %u"),
cellid);
return -1;
}
if (virXMLPropEnumDefault(cur_node, "mode",
virDomainNumatuneMemModeTypeFromString,
VIR_XML_PROP_NONE, &mem_node->mode,
VIR_DOMAIN_NUMATUNE_MEM_STRICT) < 0)
return -1;
if (numa->memory.mode == VIR_DOMAIN_NUMATUNE_MEM_RESTRICTIVE &&
mem_node->mode != VIR_DOMAIN_NUMATUNE_MEM_RESTRICTIVE) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("'restrictive' mode is required in memnode element "
"when mode is 'restrictive' in memory element"));
return -1;
}
tmp = virXMLPropString(cur_node, "nodeset");
if (!tmp) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Missing required nodeset attribute "
"in memnode element"));
return -1;
}
if (virBitmapParse(tmp, &mem_node->nodeset, VIR_DOMAIN_CPUMASK_LEN) < 0)
return -1;
if (virBitmapIsAllClear(mem_node->nodeset)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Invalid value of 'nodeset': %s"), tmp);
return -1;
}
}
return 0;
}
int
virDomainNumatuneParseXML(virDomainNuma *numa,
bool placement_static,
xmlXPathContextPtr ctxt)
{
char *tmp = NULL;
int mode = -1;
int n = 0;
int placement = -1;
int ret = -1;
virBitmap *nodeset = NULL;
xmlNodePtr node = NULL;
if (virXPathInt("count(./numatune)", ctxt, &n) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot extract numatune nodes"));
goto cleanup;
} else if (n > 1) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("only one numatune is supported"));
goto cleanup;
}
node = virXPathNode("./numatune/memory[1]", ctxt);
if (!placement_static && !node)
placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO;
if (node) {
if ((tmp = virXMLPropString(node, "mode")) &&
(mode = virDomainNumatuneMemModeTypeFromString(tmp)) < 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unsupported NUMA memory tuning mode '%s'"), tmp);
goto cleanup;
}
VIR_FREE(tmp);
if ((tmp = virXMLPropString(node, "placement")) &&
(placement = virDomainNumatunePlacementTypeFromString(tmp)) < 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unsupported NUMA memory placement mode '%s'"), tmp);
goto cleanup;
}
VIR_FREE(tmp);
tmp = virXMLPropString(node, "nodeset");
if (tmp) {
if (virBitmapParse(tmp, &nodeset, VIR_DOMAIN_CPUMASK_LEN) < 0)
goto cleanup;
if (virBitmapIsAllClear(nodeset)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Invalid value of 'nodeset': %s"), tmp);
goto cleanup;
}
VIR_FREE(tmp);
}
}
if (virDomainNumatuneSet(numa,
placement_static,
placement,
mode,
nodeset) < 0)
goto cleanup;
if (virDomainNumatuneNodeParseXML(numa, ctxt) < 0)
goto cleanup;
ret = 0;
cleanup:
virBitmapFree(nodeset);
VIR_FREE(tmp);
return ret;
}
int
virDomainNumatuneFormatXML(virBuffer *buf,
virDomainNuma *numatune)
{
const char *tmp = NULL;
char *nodeset = NULL;
bool nodesetSpecified = false;
size_t i = 0;
if (!numatune)
return 0;
for (i = 0; i < numatune->nmem_nodes; i++) {
if (numatune->mem_nodes[i].nodeset) {
nodesetSpecified = true;
break;
}
}
if (!nodesetSpecified && !numatune->memory.specified)
return 0;
virBufferAddLit(buf, "<numatune>\n");
virBufferAdjustIndent(buf, 2);
if (numatune->memory.specified) {
tmp = virDomainNumatuneMemModeTypeToString(numatune->memory.mode);
virBufferAsprintf(buf, "<memory mode='%s' ", tmp);
if (numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC) {
if (!(nodeset = virBitmapFormat(numatune->memory.nodeset)))
return -1;
virBufferAsprintf(buf, "nodeset='%s'/>\n", nodeset);
VIR_FREE(nodeset);
} else if (numatune->memory.placement) {
tmp = virDomainNumatunePlacementTypeToString(numatune->memory.placement);
virBufferAsprintf(buf, "placement='%s'/>\n", tmp);
}
}
for (i = 0; i < numatune->nmem_nodes; i++) {
virDomainNumaNode *mem_node = &numatune->mem_nodes[i];
if (!mem_node->nodeset)
continue;
if (!(nodeset = virBitmapFormat(mem_node->nodeset)))
return -1;
virBufferAsprintf(buf,
"<memnode cellid='%zu' mode='%s' nodeset='%s'/>\n",
i,
virDomainNumatuneMemModeTypeToString(mem_node->mode),
nodeset);
VIR_FREE(nodeset);
}
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</numatune>\n");
return 0;
}
void
virDomainNumaFree(virDomainNuma *numa)
{
size_t i = 0;
if (!numa)
return;
virBitmapFree(numa->memory.nodeset);
for (i = 0; i < numa->nmem_nodes; i++) {
virBitmapFree(numa->mem_nodes[i].cpumask);
virBitmapFree(numa->mem_nodes[i].nodeset);
if (numa->mem_nodes[i].ndistances > 0)
g_free(numa->mem_nodes[i].distances);
g_free(numa->mem_nodes[i].caches);
}
g_free(numa->mem_nodes);
g_free(numa->interconnects);
g_free(numa);
}
/**
* virDomainNumatuneGetMode:
* @numatune: pointer to numatune definition
* @cellid: cell selector
* @mode: where to store the result
*
* Get the defined mode for domain's memory. It's safe to pass
* NULL to @mode if the return value is the only info needed.
*
* Returns: 0 on success (with @mode updated)
* -1 if no mode was defined in XML
*/
int virDomainNumatuneGetMode(virDomainNuma *numatune,
int cellid,
virDomainNumatuneMemMode *mode)
{
virDomainNumatuneMemMode tmp_mode;
if (!numatune)
return -1;
if (virDomainNumatuneNodeSpecified(numatune, cellid))
tmp_mode = numatune->mem_nodes[cellid].mode;
else if (numatune->memory.specified)
tmp_mode = numatune->memory.mode;
else
return -1;
if (mode)
*mode = tmp_mode;
return 0;
}
virBitmap *
virDomainNumatuneGetNodeset(virDomainNuma *numatune,
virBitmap *auto_nodeset,
int cellid)
{
if (!numatune)
return NULL;
if (numatune->memory.specified &&
numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO)
return auto_nodeset;
if (virDomainNumatuneNodeSpecified(numatune, cellid))
return numatune->mem_nodes[cellid].nodeset;
if (!numatune->memory.specified)
return NULL;
return numatune->memory.nodeset;
}
char *
virDomainNumatuneFormatNodeset(virDomainNuma *numatune,
virBitmap *auto_nodeset,
int cellid)
{
return virBitmapFormat(virDomainNumatuneGetNodeset(numatune,
auto_nodeset,
cellid));
}
int
virDomainNumatuneMaybeGetNodeset(virDomainNuma *numatune,
virBitmap *auto_nodeset,
virBitmap **retNodeset,
int cellid)
{
*retNodeset = NULL;
if (!numatune)
return 0;
if (!virDomainNumatuneNodeSpecified(numatune, cellid) &&
!numatune->memory.specified)
return 0;
if (numatune->memory.specified &&
numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO &&
!auto_nodeset) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Advice from numad is needed in case of "
"automatic numa placement"));
return -1;
}
*retNodeset = virDomainNumatuneGetNodeset(numatune, auto_nodeset, cellid);
return 0;
}
int
virDomainNumatuneMaybeFormatNodeset(virDomainNuma *numatune,
virBitmap *auto_nodeset,
char **mask,
int cellid)
{
virBitmap *nodeset;
if (virDomainNumatuneMaybeGetNodeset(numatune, auto_nodeset, &nodeset,
cellid) < 0)
return -1;
if (nodeset &&
!(*mask = virBitmapFormat(nodeset)))
return -1;
return 0;
}
int
virDomainNumatuneSet(virDomainNuma *numa,
bool placement_static,
int placement,
int mode,
virBitmap *nodeset)
{
/* No need to do anything in this case */
if (mode == -1 && placement == -1 && !nodeset)
return 0;
if (!numa->memory.specified) {
if (mode == -1)
mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
if (placement == -1)
placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_DEFAULT;
}
/* Range checks */
if (mode != -1 &&
(mode < 0 || mode >= VIR_DOMAIN_NUMATUNE_MEM_LAST)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unsupported numatune mode '%d'"),
mode);
return -1;
}
if (placement != -1 &&
(placement < 0 || placement >= VIR_DOMAIN_NUMATUNE_PLACEMENT_LAST)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unsupported numatune placement '%d'"),
mode);
return -1;
}
if (mode != -1)
numa->memory.mode = mode;
if (nodeset) {
virBitmapFree(numa->memory.nodeset);
numa->memory.nodeset = virBitmapNewCopy(nodeset);
if (placement == -1)
placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC;
}
if (placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_DEFAULT) {
if (numa->memory.nodeset || placement_static)
placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC;
else
placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO;
}
if (placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC &&
!numa->memory.nodeset) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("nodeset for NUMA memory tuning must be set "
"if 'placement' is 'static'"));
return -1;
}
/* setting nodeset when placement auto is invalid */
if (placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO &&
numa->memory.nodeset) {
virBitmapFree(numa->memory.nodeset);
numa->memory.nodeset = NULL;
}
if (placement != -1)
numa->memory.placement = placement;
numa->memory.specified = true;
return 0;
}
static bool
virDomainNumaNodesEqual(virDomainNuma *n1,
virDomainNuma *n2)
{
size_t i = 0;
if (n1->nmem_nodes != n2->nmem_nodes)
return false;
for (i = 0; i < n1->nmem_nodes; i++) {
virDomainNumaNode *nd1 = &n1->mem_nodes[i];
virDomainNumaNode *nd2 = &n2->mem_nodes[i];
if (!nd1->nodeset && !nd2->nodeset)
continue;
if (nd1->mode != nd2->mode)
return false;
if (!virBitmapEqual(nd1->nodeset, nd2->nodeset))
return false;
}
return true;
}
bool
virDomainNumaEquals(virDomainNuma *n1,
virDomainNuma *n2)
{
if (!n1 && !n2)
return true;
if (!n1 || !n2)
return false;
if (!n1->memory.specified && !n2->memory.specified)
return virDomainNumaNodesEqual(n1, n2);
if (!n1->memory.specified || !n2->memory.specified)
return false;
if (n1->memory.mode != n2->memory.mode)
return false;
if (n1->memory.placement != n2->memory.placement)
return false;
if (!virBitmapEqual(n1->memory.nodeset, n2->memory.nodeset))
return false;
return virDomainNumaNodesEqual(n1, n2);
}
bool
virDomainNumatuneHasPlacementAuto(virDomainNuma *numatune)
{
if (!numatune)
return false;
if (!numatune->memory.specified)
return false;
if (numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO)
return true;
return false;
}
bool
virDomainNumatuneHasPerNodeBinding(virDomainNuma *numatune)
{
size_t i = 0;
if (!numatune)
return false;
for (i = 0; i < numatune->nmem_nodes; i++) {
if (numatune->mem_nodes[i].nodeset)
return true;
}
return false;
}
int
virDomainNumatuneSpecifiedMaxNode(virDomainNuma *numatune)
{
int ret = -1;
virBitmap *nodemask = NULL;
size_t i;
int bit;
if (!numatune)
return ret;
nodemask = virDomainNumatuneGetNodeset(numatune, NULL, -1);
if (nodemask)
ret = virBitmapLastSetBit(nodemask);
for (i = 0; i < numatune->nmem_nodes; i++) {
nodemask = numatune->mem_nodes[i].nodeset;
if (!nodemask)
continue;
bit = virBitmapLastSetBit(nodemask);
if (bit > ret)
ret = bit;
}
return ret;
}
bool
virDomainNumatuneNodesetIsAvailable(virDomainNuma *numatune,
virBitmap *auto_nodeset)
{
size_t i = 0;
virBitmap *b = NULL;
if (!numatune)
return true;
b = virDomainNumatuneGetNodeset(numatune, auto_nodeset, -1);
if (!virNumaNodesetIsAvailable(b))
return false;
for (i = 0; i < numatune->nmem_nodes; i++) {
b = virDomainNumatuneGetNodeset(numatune, auto_nodeset, i);
if (!virNumaNodesetIsAvailable(b))
return false;
}
return true;
}
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
static int
virDomainNumaDefNodeDistanceParseXML(virDomainNuma *def,
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
xmlXPathContextPtr ctxt,
unsigned int cur_cell)
{
int ret = -1;
int sibling;
char *tmp = NULL;
xmlNodePtr *nodes = NULL;
size_t i, ndistances = def->nmem_nodes;
if (ndistances == 0)
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
return 0;
/* check if NUMA distances definition is present */
if (!virXPathNode("./distances[1]", ctxt))
return 0;
if ((sibling = virXPathNodeSet("./distances[1]/sibling", ctxt, &nodes)) <= 0) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("NUMA distances defined without siblings"));
goto cleanup;
}
for (i = 0; i < sibling; i++) {
virDomainNumaDistance *ldist;
virDomainNumaDistance *rdist;
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
unsigned int sibling_id, sibling_value;
/* siblings are in order of parsing or explicitly numbered */
if (!(tmp = virXMLPropString(nodes[i], "id"))) {
virReportError(VIR_ERR_XML_ERROR,
_("Missing 'id' attribute in NUMA "
"distances under 'cell id %d'"),
cur_cell);
goto cleanup;
}
/* The "id" needs to be applicable */
if (virStrToLong_uip(tmp, NULL, 10, &sibling_id) < 0) {
virReportError(VIR_ERR_XML_ERROR,
_("Invalid 'id' attribute in NUMA "
"distances for sibling: '%s'"),
tmp);
goto cleanup;
}
VIR_FREE(tmp);
/* The "id" needs to be within numa/cell range */
if (sibling_id >= ndistances) {
virReportError(VIR_ERR_XML_ERROR,
_("'sibling_id %d' does not refer to a "
"valid cell within NUMA 'cell id %d'"),
sibling_id, cur_cell);
goto cleanup;
}
/* We need a locality value. Check and correct
* distance to local and distance to remote node.
*/
if (!(tmp = virXMLPropString(nodes[i], "value"))) {
virReportError(VIR_ERR_XML_ERROR,
_("Missing 'value' attribute in NUMA distances "
"under 'cell id %d' for 'sibling id %d'"),
cur_cell, sibling_id);
goto cleanup;
}
/* The "value" needs to be applicable */
if (virStrToLong_uip(tmp, NULL, 10, &sibling_value) < 0) {
virReportError(VIR_ERR_XML_ERROR,
_("'value %s' is invalid for "
"'sibling id %d' under NUMA 'cell id %d'"),
tmp, sibling_id, cur_cell);
goto cleanup;
}
VIR_FREE(tmp);
/* Assure LOCAL_DISTANCE <= "value" <= UNREACHABLE
* and correct LOCAL_DISTANCE setting if such applies.
*/
if ((sibling_value < LOCAL_DISTANCE ||
sibling_value > UNREACHABLE) ||
(sibling_id == cur_cell &&
sibling_value != LOCAL_DISTANCE) ||
(sibling_id != cur_cell &&
sibling_value == LOCAL_DISTANCE)) {
virReportError(VIR_ERR_XML_ERROR,
_("'value %d' is invalid for "
"'sibling id %d' under NUMA 'cell id %d'"),
sibling_value, sibling_id, cur_cell);
goto cleanup;
}
/* Apply the local / remote distance */
ldist = def->mem_nodes[cur_cell].distances;
if (!ldist) {
ldist = g_new0(virDomainNumaDistance, ndistances);
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
ldist[cur_cell].value = LOCAL_DISTANCE;
ldist[cur_cell].cellid = cur_cell;
def->mem_nodes[cur_cell].ndistances = ndistances;
def->mem_nodes[cur_cell].distances = ldist;
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
}
ldist[sibling_id].cellid = sibling_id;
ldist[sibling_id].value = sibling_value;
/* Apply symmetry if none given */
rdist = def->mem_nodes[sibling_id].distances;
if (!rdist) {
rdist = g_new0(virDomainNumaDistance, ndistances);
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
rdist[sibling_id].value = LOCAL_DISTANCE;
rdist[sibling_id].cellid = sibling_id;
def->mem_nodes[sibling_id].ndistances = ndistances;
def->mem_nodes[sibling_id].distances = rdist;
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
}
rdist[cur_cell].cellid = cur_cell;
if (!rdist[cur_cell].value)
rdist[cur_cell].value = sibling_value;
}
ret = 0;
cleanup:
if (ret < 0) {
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
for (i = 0; i < ndistances; i++)
VIR_FREE(def->mem_nodes[i].distances);
def->mem_nodes[i].ndistances = 0;
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
}
VIR_FREE(nodes);
VIR_FREE(tmp);
return ret;
}
static int
virDomainNumaDefNodeCacheParseXML(virDomainNuma *def,
xmlXPathContextPtr ctxt,
unsigned int cur_cell)
{
g_autofree xmlNodePtr *nodes = NULL;
int n;
size_t i;
if ((n = virXPathNodeSet("./cache", ctxt, &nodes)) < 0)
return -1;
def->mem_nodes[cur_cell].caches = g_new0(virDomainNumaCache, n);
for (i = 0; i < n; i++) {
VIR_XPATH_NODE_AUTORESTORE(ctxt)
virDomainNumaCache *cache = &def->mem_nodes[cur_cell].caches[i];
g_autofree char *tmp = NULL;
unsigned int level;
int associativity;
int policy;
unsigned long long size;
unsigned long long line;
if (!(tmp = virXMLPropString(nodes[i], "level"))) {
virReportError(VIR_ERR_XML_ERROR,
_("Missing 'level' attribute in cache "
"element for NUMA node %d"),
cur_cell);
return -1;
}
if (virStrToLong_uip(tmp, NULL, 10, &level) < 0 ||
level == 0) {
virReportError(VIR_ERR_XML_ERROR,
_("Invalid 'level' attribute in cache "
"element for NUMA node %d"),
cur_cell);
return -1;
}
VIR_FREE(tmp);
if (!(tmp = virXMLPropString(nodes[i], "associativity"))) {
virReportError(VIR_ERR_XML_ERROR,
_("Missing 'associativity' attribute in cache "
"element for NUMA node %d"),
cur_cell);
return -1;
}
if ((associativity = virDomainCacheAssociativityTypeFromString(tmp)) < 0) {
virReportError(VIR_ERR_XML_ERROR,
_("Invalid cache associativity '%s'"),
tmp);
return -1;
}
VIR_FREE(tmp);
if (!(tmp = virXMLPropString(nodes[i], "policy"))) {
virReportError(VIR_ERR_XML_ERROR,
_("Missing 'policy' attribute in cache "
"element for NUMA node %d"),
cur_cell);
}
if ((policy = virDomainCachePolicyTypeFromString(tmp)) < 0) {
virReportError(VIR_ERR_XML_ERROR,
_("Invalid cache policy '%s'"),
tmp);
return -1;
}
VIR_FREE(tmp);
ctxt->node = nodes[i];
if (virDomainParseMemory("./size/@value", "./size/unit",
ctxt, &size, true, false) < 0)
return -1;
if (virParseScaledValue("./line/@value", "./line/unit",
ctxt, &line, 1, ULLONG_MAX, true) < 0)
return -1;
*cache = (virDomainNumaCache){level, size, line, associativity, policy};
def->mem_nodes[cur_cell].ncaches++;
}
return 0;
}
int
virDomainNumaDefParseXML(virDomainNuma *def,
xmlXPathContextPtr ctxt)
{
xmlNodePtr *nodes = NULL;
char *tmp = NULL;
int n;
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
size_t i, j;
int ret = -1;
/* check if NUMA definition is present */
if (!virXPathNode("./cpu/numa[1]", ctxt))
return 0;
if ((n = virXPathNodeSet("./cpu/numa[1]/cell", ctxt, &nodes)) <= 0) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("NUMA topology defined without NUMA cells"));
goto cleanup;
}
def->mem_nodes = g_new0(struct _virDomainNumaNode, n);
def->nmem_nodes = n;
for (i = 0; i < n; i++) {
VIR_XPATH_NODE_AUTORESTORE(ctxt)
int rc;
unsigned int cur_cell = i;
/* cells are in order of parsing or explicitly numbered */
if ((tmp = virXMLPropString(nodes[i], "id"))) {
if (virStrToLong_uip(tmp, NULL, 10, &cur_cell) < 0) {
virReportError(VIR_ERR_XML_ERROR,
_("Invalid 'id' attribute in NUMA cell: '%s'"),
tmp);
goto cleanup;
}
if (cur_cell >= n) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Exactly one 'cell' element per guest "
"NUMA cell allowed, non-contiguous ranges or "
"ranges not starting from 0 are not allowed"));
goto cleanup;
}
}
VIR_FREE(tmp);
if (def->mem_nodes[cur_cell].mem) {
virReportError(VIR_ERR_XML_ERROR,
_("Duplicate NUMA cell info for cell id '%u'"),
cur_cell);
goto cleanup;
}
if ((tmp = virXMLPropString(nodes[i], "cpus"))) {
g_autoptr(virBitmap) cpumask = NULL;
if (virBitmapParse(tmp, &cpumask, VIR_DOMAIN_CPUMASK_LEN) < 0)
goto cleanup;
if (!virBitmapIsAllClear(cpumask))
def->mem_nodes[cur_cell].cpumask = g_steal_pointer(&cpumask);
VIR_FREE(tmp);
}
for (j = 0; j < n; j++) {
if (j == cur_cell ||
!def->mem_nodes[j].cpumask ||
!def->mem_nodes[cur_cell].cpumask)
continue;
if (virBitmapOverlaps(def->mem_nodes[j].cpumask,
def->mem_nodes[cur_cell].cpumask)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("NUMA cells %u and %zu have overlapping vCPU ids"),
cur_cell, j);
goto cleanup;
}
}
ctxt->node = nodes[i];
if (virDomainParseMemory("./@memory", "./@unit", ctxt,
&def->mem_nodes[cur_cell].mem, true, false) < 0)
goto cleanup;
if ((tmp = virXMLPropString(nodes[i], "memAccess"))) {
if ((rc = virDomainMemoryAccessTypeFromString(tmp)) <= 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Invalid 'memAccess' attribute value '%s'"),
tmp);
goto cleanup;
}
def->mem_nodes[cur_cell].memAccess = rc;
VIR_FREE(tmp);
}
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
if ((tmp = virXMLPropString(nodes[i], "discard"))) {
if ((rc = virTristateBoolTypeFromString(tmp)) <= 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Invalid 'discard' attribute value '%s'"),
tmp);
goto cleanup;
}
def->mem_nodes[cur_cell].discard = rc;
VIR_FREE(tmp);
}
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
/* Parse NUMA distances info */
if (virDomainNumaDefNodeDistanceParseXML(def, ctxt, cur_cell) < 0)
goto cleanup;
/* Parse cache info */
if (virDomainNumaDefNodeCacheParseXML(def, ctxt, cur_cell) < 0)
goto cleanup;
}
VIR_FREE(nodes);
if ((n = virXPathNodeSet("./cpu/numa[1]/interconnects[1]/latency|"
"./cpu/numa[1]/interconnects[1]/bandwidth", ctxt, &nodes)) < 0)
goto cleanup;
def->interconnects = g_new0(virDomainNumaInterconnect, n);
for (i = 0; i < n; i++) {
virDomainNumaInterconnectType type;
unsigned int initiator;
unsigned int target;
unsigned int cache = 0;
int accessType;
unsigned long long value;
if (virXMLNodeNameEqual(nodes[i], "latency")) {
type = VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_LATENCY;
if (!(tmp = virXMLPropString(nodes[i], "value"))) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Missing 'value' attribute in NUMA interconnects"));
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
goto cleanup;
}
if (virStrToLong_ullp(tmp, NULL, 10, &value) < 0) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Invalid 'value' attribute in NUMA interconnects"));
goto cleanup;
}
VIR_FREE(tmp);
} else if (virXMLNodeNameEqual(nodes[i], "bandwidth")) {
VIR_XPATH_NODE_AUTORESTORE(ctxt)
type = VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_BANDWIDTH;
ctxt->node = nodes[i];
if (virDomainParseMemory("./@value", "./@unit", ctxt, &value, true, false) < 0)
goto cleanup;
} else {
/* Ignore yet unknown child elements. */
continue;
}
if (!(tmp = virXMLPropString(nodes[i], "initiator"))) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Missing 'initiator' attribute in NUMA interconnects"));
goto cleanup;
}
if (virStrToLong_uip(tmp, NULL, 10, &initiator) < 0) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Invalid 'initiator' attribute in NUMA interconnects"));
goto cleanup;
}
VIR_FREE(tmp);
if (!(tmp = virXMLPropString(nodes[i], "target"))) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Missing 'target' attribute in NUMA interconnects"));
goto cleanup;
}
if (virStrToLong_uip(tmp, NULL, 10, &target) < 0) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Invalid 'target' attribute in NUMA interconnects"));
goto cleanup;
}
VIR_FREE(tmp);
/* cache attribute is optional */
if ((tmp = virXMLPropString(nodes[i], "cache"))) {
if (virStrToLong_uip(tmp, NULL, 10, &cache) < 0 ||
cache == 0) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Invalid 'cache' attribute in NUMA interconnects"));
goto cleanup;
}
}
VIR_FREE(tmp);
if (!(tmp = virXMLPropString(nodes[i], "type"))) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Missing 'type' attribute in NUMA interconnects"));
goto cleanup;
}
if ((accessType = virDomainMemoryLatencyTypeFromString(tmp)) <= 0) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Invalid 'type' attribute in NUMA interconnects"));
goto cleanup;
}
VIR_FREE(tmp);
def->interconnects[i] = (virDomainNumaInterconnect) {type, initiator, target,
cache, accessType, value};
def->ninterconnects++;
}
ret = 0;
cleanup:
VIR_FREE(nodes);
VIR_FREE(tmp);
return ret;
}
int
virDomainNumaDefFormatXML(virBuffer *buf,
virDomainNuma *def)
{
virDomainMemoryAccess memAccess;
virTristateBool discard;
size_t ncells = virDomainNumaGetNodeCount(def);
size_t i;
if (ncells == 0)
return 0;
virBufferAddLit(buf, "<numa>\n");
virBufferAdjustIndent(buf, 2);
for (i = 0; i < ncells; i++) {
virBitmap *cpumask = virDomainNumaGetNodeCpumask(def, i);
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
int ndistances;
size_t ncaches;
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
memAccess = virDomainNumaGetNodeMemoryAccessMode(def, i);
discard = virDomainNumaGetNodeDiscard(def, i);
virBufferAddLit(buf, "<cell");
virBufferAsprintf(buf, " id='%zu'", i);
if (cpumask) {
g_autofree char *cpustr = virBitmapFormat(cpumask);
if (!cpustr)
return -1;
virBufferAsprintf(buf, " cpus='%s'", cpustr);
}
virBufferAsprintf(buf, " memory='%llu'",
virDomainNumaGetNodeMemorySize(def, i));
virBufferAddLit(buf, " unit='KiB'");
if (memAccess)
virBufferAsprintf(buf, " memAccess='%s'",
virDomainMemoryAccessTypeToString(memAccess));
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
if (discard)
virBufferAsprintf(buf, " discard='%s'",
virTristateBoolTypeToString(discard));
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
ndistances = def->mem_nodes[i].ndistances;
ncaches = def->mem_nodes[i].ncaches;
if (ndistances == 0 && ncaches == 0) {
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
virBufferAddLit(buf, "/>\n");
} else {
size_t j;
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2);
if (ndistances) {
virDomainNumaDistance *distances = def->mem_nodes[i].distances;
virBufferAddLit(buf, "<distances>\n");
virBufferAdjustIndent(buf, 2);
for (j = 0; j < ndistances; j++) {
if (distances[j].value) {
virBufferAddLit(buf, "<sibling");
virBufferAsprintf(buf, " id='%d'", distances[j].cellid);
virBufferAsprintf(buf, " value='%d'", distances[j].value);
virBufferAddLit(buf, "/>\n");
}
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
}
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</distances>\n");
}
for (j = 0; j < ncaches; j++) {
virDomainNumaCache *cache = &def->mem_nodes[i].caches[j];
virBufferAsprintf(buf, "<cache level='%u'", cache->level);
if (cache->associativity) {
virBufferAsprintf(buf, " associativity='%s'",
virDomainCacheAssociativityTypeToString(cache->associativity));
}
if (cache->policy) {
virBufferAsprintf(buf, " policy='%s'",
virDomainCachePolicyTypeToString(cache->policy));
}
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2);
virBufferAsprintf(buf,
"<size value='%u' unit='KiB'/>\n",
cache->size);
if (cache->line) {
virBufferAsprintf(buf,
"<line value='%u' unit='B'/>\n",
cache->line);
}
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</cache>\n");
numa: describe siblings distances within cells Add support for describing NUMA distances in a domain's <numa> <cell> XML description. Below is an example of a 4 node setup: <cpu> <numa> <cell id='0' cpus='0-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='4-7' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='8-11' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> <cell id='3' cpus='12-15' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> A <cell> defines a NUMA node. <distances> describes the NUMA distance from the <cell> to the other NUMA nodes (the <sibling>s). For example, in above XML description, the distance between NUMA node0 <cell id='0' ...> and NUMA node2 <sibling id='2' ...> is 31. Valid distance values are '10 <= value <= 255'. A distance value of 10 represents the distance to the node itself. A distance value of 20 represents the default value for remote nodes but other values are possible depending on the physical topology of the system. When distances are not fully described, any missing sibling distance values will default to 10 for local nodes and 20 for remote nodes. If distance is given for A -> B, then we default B -> A to the same value instead of 20. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:20 +00:00
}
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</cell>\n");
}
}
if (def->ninterconnects) {
virBufferAddLit(buf, "<interconnects>\n");
virBufferAdjustIndent(buf, 2);
}
for (i = 0; i < def->ninterconnects; i++) {
virDomainNumaInterconnect *l = &def->interconnects[i];
switch (l->type) {
case VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_LATENCY:
virBufferAddLit(buf, "<latency");
break;
case VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_BANDWIDTH:
virBufferAddLit(buf, "<bandwidth");
}
virBufferAsprintf(buf,
" initiator='%u' target='%u'",
l->initiator, l->target);
if (l->cache > 0) {
virBufferAsprintf(buf,
" cache='%u'",
l->cache);
}
virBufferAsprintf(buf,
" type='%s' value='%lu'",
virDomainMemoryLatencyTypeToString(l->accessType),
l->value);
if (l->type == VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_BANDWIDTH)
virBufferAddLit(buf, " unit='KiB'");
virBufferAddLit(buf, "/>\n");
}
if (def->ninterconnects) {
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</interconnects>\n");
}
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</numa>\n");
return 0;
}
int
virDomainNumaDefValidate(const virDomainNuma *def)
{
size_t i;
size_t j;
if (!def)
return 0;
for (i = 0; i < def->nmem_nodes; i++) {
const virDomainNumaNode *node = &def->mem_nodes[i];
g_autoptr(virBitmap) levelsSeen = virBitmapNew(0);
for (j = 0; j < node->ncaches; j++) {
const virDomainNumaCache *cache = &node->caches[j];
/* Relax this if there's ever fourth layer of cache */
if (cache->level > 3) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Ain't nobody heard of that much cache level"));
return -1;
}
if (virBitmapIsBitSet(levelsSeen, cache->level)) {
virReportError(VIR_ERR_XML_ERROR,
_("Cache level '%u' already defined"),
cache->level);
return -1;
}
if (virBitmapSetBitExpand(levelsSeen, cache->level))
return -1;
}
}
for (i = 0; i < def->ninterconnects; i++) {
const virDomainNumaInterconnect *l = &def->interconnects[i];
if (l->initiator >= def->nmem_nodes) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("'initiator' refers to a non-existent NUMA node"));
return -1;
}
if (l->target >= def->nmem_nodes) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("'target' refers to a non-existent NUMA node"));
return -1;
}
if (!def->mem_nodes[l->initiator].cpumask) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("NUMA nodes without CPUs can't be initiator"));
return -1;
}
if (l->cache > 0) {
for (j = 0; j < def->mem_nodes[l->target].ncaches; j++) {
numa_conf: Properly check for caches in virDomainNumaDefValidate() When adding support for HMAT, in f0611fe8830 I've introduced a check which aims to validate /domain/cpu/numa/interconnects. As a part of that, there is a loop which checks whether all <latency/> with @cache attribute refer to an existing cache level. For instance: <cpu mode='host-model' check='partial'> <numa> <cell id='0' cpus='0-5' memory='512000' unit='KiB' discard='yes'> <cache level='1' associativity='direct' policy='writeback'> <size value='8' unit='KiB'/> <line value='5' unit='B'/> </cache> </cell> <interconnects> <latency initiator='0' target='0' cache='1' type='access' value='5'/> <bandwidth initiator='0' target='0' type='access' value='204800' unit='KiB'/> </interconnects> </numa> </cpu> This XML defines that accessing L1 cache of node #0 from node #0 has latency of 5ns. However, the loop was not written properly. Well, the check in it, as it was always checking for the first cache in the target node and not the rest. Therefore, the following example errors out: <cpu mode='host-model' check='partial'> <numa> <cell id='0' cpus='0-5' memory='512000' unit='KiB' discard='yes'> <cache level='3' associativity='direct' policy='writeback'> <size value='10' unit='KiB'/> <line value='8' unit='B'/> </cache> <cache level='1' associativity='direct' policy='writeback'> <size value='8' unit='KiB'/> <line value='5' unit='B'/> </cache> </cell> <interconnects> <latency initiator='0' target='0' cache='1' type='access' value='5'/> <bandwidth initiator='0' target='0' type='access' value='204800' unit='KiB'/> </interconnects> </numa> </cpu> This errors out even though it is a valid configuration. The L1 cache under node #0 is still present. Fixes: f0611fe8830 Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Laine Stump <laine@redhat.com>
2020-08-18 10:46:38 +00:00
const virDomainNumaCache *cache = &def->mem_nodes[l->target].caches[j];
if (l->cache == cache->level)
break;
}
if (j == def->mem_nodes[l->target].ncaches) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("'cache' refers to a non-existent NUMA node cache"));
return -1;
}
}
for (j = 0; j < i; j++) {
const virDomainNumaInterconnect *ll = &def->interconnects[j];
if (l->type == ll->type &&
l->initiator == ll->initiator &&
l->target == ll->target &&
l->cache == ll->cache &&
l->accessType == ll->accessType) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Duplicate info for NUMA latencies"));
return -1;
}
if (l->initiator != l->target &&
l->initiator == ll->target &&
l->target == ll->initiator) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Link already defined"));
return -1;
}
}
}
return 0;
}
unsigned int
virDomainNumaGetCPUCountTotal(virDomainNuma *numa)
{
size_t i;
unsigned int ret = 0;
for (i = 0; i < numa->nmem_nodes; i++) {
virBitmap *cpumask = virDomainNumaGetNodeCpumask(numa, i);
if (cpumask)
ret += virBitmapCountBits(cpumask);
}
return ret;
}
unsigned int
virDomainNumaGetMaxCPUID(virDomainNuma *numa)
{
size_t i;
unsigned int ret = 0;
for (i = 0; i < numa->nmem_nodes; i++) {
virBitmap *cpumask = virDomainNumaGetNodeCpumask(numa, i);
int bit;
if (cpumask) {
bit = virBitmapLastSetBit(cpumask);
if (bit > ret)
ret = bit;
}
}
return ret;
}
virDomainNuma *
virDomainNumaNew(void)
{
return g_new0(virDomainNuma, 1);
}
bool
virDomainNumaCheckABIStability(virDomainNuma *src,
virDomainNuma *tgt)
{
size_t i;
size_t j;
if (virDomainNumaGetNodeCount(src) != virDomainNumaGetNodeCount(tgt)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Target NUMA node count '%zu' doesn't match "
"source '%zu'"),
virDomainNumaGetNodeCount(tgt),
virDomainNumaGetNodeCount(src));
return false;
}
for (i = 0; i < virDomainNumaGetNodeCount(src); i++) {
if (virDomainNumaGetNodeMemorySize(src, i) !=
virDomainNumaGetNodeMemorySize(tgt, i)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Size of target NUMA node %zu (%llu) doesn't "
"match source (%llu)"), i,
virDomainNumaGetNodeMemorySize(tgt, i),
virDomainNumaGetNodeMemorySize(src, i));
return false;
}
if (!virBitmapEqual(virDomainNumaGetNodeCpumask(src, i),
virDomainNumaGetNodeCpumask(tgt, i))) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Processor mask of target NUMA node %zu doesn't "
"match source"), i);
return false;
}
for (j = 0; j < virDomainNumaGetNodeCount(src); j++) {
if (virDomainNumaGetNodeDistance(src, i, j) !=
virDomainNumaGetNodeDistance(tgt, i, j)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Target NUMA distance from %zu to %zu "
"doesn't match source"), i, j);
return false;
}
}
}
return true;
}
size_t
virDomainNumaGetNodeCount(virDomainNuma *numa)
{
if (!numa)
return 0;
return numa->nmem_nodes;
}
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
size_t
virDomainNumaSetNodeCount(virDomainNuma *numa, size_t nmem_nodes)
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
{
if (!nmem_nodes) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot set an empty mem_nodes set"));
return 0;
}
if (numa->mem_nodes) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot alter an existing mem_nodes set"));
return 0;
}
numa->mem_nodes = g_new0(struct _virDomainNumaNode, nmem_nodes);
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
numa->nmem_nodes = nmem_nodes;
return numa->nmem_nodes;
}
bool
virDomainNumaNodeDistanceIsUsingDefaults(virDomainNuma *numa,
size_t node,
size_t sibling)
{
if (node >= numa->nmem_nodes ||
sibling >= numa->nmem_nodes)
return false;
if (!numa->mem_nodes[node].distances)
return true;
if (numa->mem_nodes[node].distances[sibling].value == LOCAL_DISTANCE ||
numa->mem_nodes[node].distances[sibling].value == REMOTE_DISTANCE)
return true;
return false;
}
bool
virDomainNumaNodesDistancesAreBeingSet(virDomainNuma *numa)
{
size_t ncells = virDomainNumaGetNodeCount(numa);
size_t i, j;
for (i = 0; i < ncells; i++) {
for (j = 0; j < ncells; j++) {
if (virDomainNumaNodeDistanceIsUsingDefaults(numa, i, j))
continue;
return true;
}
}
return false;
}
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
size_t
virDomainNumaGetNodeDistance(virDomainNuma *numa,
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
size_t node,
size_t cellid)
{
virDomainNumaDistance *distances = NULL;
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
if (node < numa->nmem_nodes)
distances = numa->mem_nodes[node].distances;
/*
* Present the configured distance value. If
* out of range or not available set the platform
* defined default for local and remote nodes.
*/
if (!distances ||
cellid >= numa->nmem_nodes ||
!distances[cellid].value)
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
return (node == cellid) ? LOCAL_DISTANCE : REMOTE_DISTANCE;
return distances[cellid].value;
}
int
virDomainNumaSetNodeDistance(virDomainNuma *numa,
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
size_t node,
size_t cellid,
unsigned int value)
{
virDomainNumaDistance *distances;
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
if (node >= numa->nmem_nodes) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Argument 'node' %zu outranges "
"defined number of NUMA nodes"),
node);
return -1;
}
distances = numa->mem_nodes[node].distances;
if (!distances ||
cellid >= numa->mem_nodes[node].ndistances) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Arguments under memnode element do not "
"correspond with existing guest's NUMA cell"));
return -1;
}
/*
* Advanced Configuration and Power Interface
* Specification version 6.1. Chapter 5.2.17
* System Locality Distance Information Table
* ... Distance values of 0-9 are reserved.
*/
if (value < LOCAL_DISTANCE ||
value > UNREACHABLE) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Distance value of %d is not in valid range"),
value);
return -1;
}
if (value == LOCAL_DISTANCE && node != cellid) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Distance value %d under node %zu is "
"LOCAL_DISTANCE and should be set to 10"),
value, node);
return -1;
}
distances[cellid].cellid = cellid;
distances[cellid].value = value;
return distances[cellid].value;
}
size_t
virDomainNumaSetNodeDistanceCount(virDomainNuma *numa,
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
size_t node,
size_t ndistances)
{
virDomainNumaDistance *distances;
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
distances = numa->mem_nodes[node].distances;
if (distances) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Cannot alter an existing nmem_nodes distances set for node: %zu"),
node);
return 0;
}
distances = g_new0(struct _virDomainNumaDistance, ndistances);
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
numa->mem_nodes[node].distances = distances;
numa->mem_nodes[node].ndistances = ndistances;
return numa->mem_nodes[node].ndistances;
}
virBitmap *
virDomainNumaGetNodeCpumask(virDomainNuma *numa,
size_t node)
{
return numa->mem_nodes[node].cpumask;
}
void
virDomainNumaSetNodeCpumask(virDomainNuma *numa,
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
size_t node,
virBitmap *cpumask)
xenconfig: add domxml conversions for xen-xl This patch converts NUMA configurations between the Xen libxl configuration file format and libvirt's XML format. XML HVM domain on a 4 node (2 cores/socket) configuration: <cpu> <numa> <cell id='0' cpus='0-1' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='10'/> <sibling id='1' value='21'/> <sibling id='2' value='31'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='1' cpus='2-3' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='10'/> <sibling id='2' value='21'/> <sibling id='3' value='31'/> </distances> </cell> <cell id='2' cpus='3-4' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='31'/> <sibling id='1' value='21'/> <sibling id='2' value='10'/> <sibling id='3' value='21'/> </distances> </cell> <cell id='3' cpus='5-6' memory='2097152' unit='KiB'> <distances> <sibling id='0' value='21'/> <sibling id='1' value='31'/> <sibling id='2' value='21'/> <sibling id='3' value='10'/> </distances> </cell> </numa> </cpu> Xen xl.cfg domain configuration: vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"], ["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"], ["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"], ["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]] If there is no XML <distances> description amongst the <cell> data the conversion schema from xml to native will generate 10 for local and 20 for all remote instances. Signed-off-by: Wim ten Have <wim.ten.have@oracle.com> Reviewed-by: Jim Fehlig <jfehlig@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2017-11-02 15:47:21 +00:00
{
numa->mem_nodes[node].cpumask = cpumask;
}
virDomainMemoryAccess
virDomainNumaGetNodeMemoryAccessMode(virDomainNuma *numa,
size_t node)
{
return numa->mem_nodes[node].memAccess;
}
virTristateBool
virDomainNumaGetNodeDiscard(virDomainNuma *numa,
size_t node)
{
return numa->mem_nodes[node].discard;
}
unsigned long long
virDomainNumaGetNodeMemorySize(virDomainNuma *numa,
size_t node)
{
return numa->mem_nodes[node].mem;
}
void
virDomainNumaSetNodeMemorySize(virDomainNuma *numa,
size_t node,
unsigned long long size)
{
numa->mem_nodes[node].mem = size;
}
unsigned long long
virDomainNumaGetMemorySize(virDomainNuma *numa)
{
size_t i;
unsigned long long ret = 0;
for (i = 0; i < numa->nmem_nodes; i++)
ret += numa->mem_nodes[i].mem;
return ret;
}
int
virDomainNumaFillCPUsInNode(virDomainNuma *numa,
size_t node,
unsigned int maxCpus)
{
g_autoptr(virBitmap) maxCPUsBitmap = virBitmapNew(maxCpus);
size_t i;
if (node >= virDomainNumaGetNodeCount(numa))
return -1;
virBitmapSetAll(maxCPUsBitmap);
for (i = 0; i < numa->nmem_nodes; i++) {
virBitmap *nodeCpus = virDomainNumaGetNodeCpumask(numa, i);
if (i == node || !nodeCpus)
continue;
virBitmapSubtract(maxCPUsBitmap, nodeCpus);
}
if (!virBitmapEqual(numa->mem_nodes[node].cpumask, maxCPUsBitmap)) {
virBitmapFree(numa->mem_nodes[node].cpumask);
numa->mem_nodes[node].cpumask = g_steal_pointer(&maxCPUsBitmap);
}
return 0;
}
bool
virDomainNumaHasHMAT(const virDomainNuma *numa)
{
size_t i;
if (!numa)
return false;
if (numa->ninterconnects)
return true;
for (i = 0; i < numa->nmem_nodes; i++) {
if (numa->mem_nodes[i].ncaches)
return true;
}
return false;
}
size_t
virDomainNumaGetNodeCacheCount(const virDomainNuma *numa,
size_t node)
{
if (!numa || node >= numa->nmem_nodes)
return 0;
return numa->mem_nodes[node].ncaches;
}
int
virDomainNumaGetNodeCache(const virDomainNuma *numa,
size_t node,
size_t cache,
unsigned int *level,
unsigned int *size,
unsigned int *line,
virDomainCacheAssociativity *associativity,
virDomainCachePolicy *policy)
{
const virDomainNumaNode *cell;
if (!numa || node >= numa->nmem_nodes)
return -1;
cell = &numa->mem_nodes[node];
if (cache >= cell->ncaches)
return -1;
*level = cell->caches[cache].level;
*size = cell->caches[cache].size;
*line = cell->caches[cache].line;
*associativity = cell->caches[cache].associativity;
*policy = cell->caches[cache].policy;
return 0;
}
ssize_t
virDomainNumaGetNodeInitiator(const virDomainNuma *numa,
size_t node)
{
size_t i;
unsigned int maxBandwidth = 0;
ssize_t candidateBandwidth = -1;
unsigned int minLatency = UINT_MAX;
ssize_t candidateLatency = -1;
if (!numa || node >= numa->nmem_nodes)
return -1;
/* A NUMA node which has at least one vCPU is initiator to itself by
* definition. */
if (numa->mem_nodes[node].cpumask)
return node;
/* For the rest, "NUMA node that has best performance (the lowest
* latency or largest bandwidth) to this NUMA node." */
for (i = 0; i < numa->ninterconnects; i++) {
const virDomainNumaInterconnect *l = &numa->interconnects[i];
if (l->target != node)
continue;
switch (l->type) {
case VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_LATENCY:
if (l->value < minLatency) {
minLatency = l->value;
candidateLatency = l->initiator;
}
break;
case VIR_DOMAIN_NUMA_INTERCONNECT_TYPE_BANDWIDTH:
if (l->value > maxBandwidth) {
maxBandwidth = l->value;
candidateBandwidth = l->initiator;
}
break;
}
}
if (candidateLatency >= 0)
return candidateLatency;
return candidateBandwidth;
}
size_t
virDomainNumaGetInterconnectsCount(const virDomainNuma *numa)
{
if (!numa)
return 0;
return numa->ninterconnects;
}
int
virDomainNumaGetInterconnect(const virDomainNuma *numa,
size_t i,
virDomainNumaInterconnectType *type,
unsigned int *initiator,
unsigned int *target,
unsigned int *cache,
virDomainMemoryLatency *accessType,
unsigned long *value)
{
const virDomainNumaInterconnect *l;
if (!numa || i >= numa->ninterconnects)
return -1;
l = &numa->interconnects[i];
*type = l->type;
*initiator = l->initiator;
*target = l->target;
*cache = l->cache;
*accessType = l->accessType;
*value = l->value;
return 0;
}