mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
conf: Add memory bandwidth allocation capability of host
Add new XML section to report host's memory bandwidth allocation capability. The format as below example: <host> ..... <memory_bandwidth> <node id='0' cpus='0-19'> <control granularity='10' min ='10' maxAllocs='8'/> </node> </memory_bandwidth> </host> granularity ---- granularity of memory bandwidth, unit percentage. min ---- minimum memory bandwidth allowed, unit percentage. maxAllocs ---- maximum memory bandwidth allocation group supported. Signed-off-by: Bing Niu <bing.niu@intel.com> Reviewed-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
parent
8d6f508e64
commit
7995fecc25
@ -51,6 +51,9 @@
|
||||
<optional>
|
||||
<ref name='cache'/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name='memory_bandwidth'/>
|
||||
</optional>
|
||||
<zeroOrMore>
|
||||
<ref name='secmodel'/>
|
||||
</zeroOrMore>
|
||||
@ -326,6 +329,36 @@
|
||||
</attribute>
|
||||
</define>
|
||||
|
||||
<define name='memory_bandwidth'>
|
||||
<element name='memory_bandwidth'>
|
||||
<oneOrMore>
|
||||
<element name='node'>
|
||||
<attribute name='id'>
|
||||
<ref name='unsignedInt'/>
|
||||
</attribute>
|
||||
<attribute name='cpus'>
|
||||
<ref name='cpuset'/>
|
||||
</attribute>
|
||||
<zeroOrMore>
|
||||
<element name='control'>
|
||||
<attribute name='granularity'>
|
||||
<ref name='unsignedInt'/>
|
||||
</attribute>
|
||||
<optional>
|
||||
<attribute name='min'>
|
||||
<ref name='unsignedInt'/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<attribute name='maxAllocs'>
|
||||
<ref name='unsignedInt'/>
|
||||
</attribute>
|
||||
</element>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
</oneOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name='guestcaps'>
|
||||
<element name='guest'>
|
||||
<ref name='ostype'/>
|
||||
|
@ -197,6 +197,16 @@ virCapabilitiesFreeNUMAInfo(virCapsPtr caps)
|
||||
caps->host.nnumaCell = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
virCapsHostMemBWNodeFree(virCapsHostMemBWNodePtr ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
virBitmapFree(ptr->cpus);
|
||||
VIR_FREE(ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
virCapabilitiesClearSecModel(virCapsHostSecModelPtr secmodel)
|
||||
{
|
||||
@ -239,6 +249,10 @@ virCapsDispose(void *object)
|
||||
virCapsHostCacheBankFree(caps->host.caches[i]);
|
||||
VIR_FREE(caps->host.caches);
|
||||
|
||||
for (i = 0; i < caps->host.nnodes; i++)
|
||||
virCapsHostMemBWNodeFree(caps->host.nodes[i]);
|
||||
VIR_FREE(caps->host.nodes);
|
||||
|
||||
VIR_FREE(caps->host.netprefix);
|
||||
VIR_FREE(caps->host.pagesSize);
|
||||
virCPUDefFree(caps->host.cpu);
|
||||
@ -946,6 +960,58 @@ virCapabilitiesFormatCaches(virBufferPtr buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
virCapabilitiesFormatMemoryBandwidth(virBufferPtr buf,
|
||||
size_t nnodes,
|
||||
virCapsHostMemBWNodePtr *nodes)
|
||||
{
|
||||
size_t i = 0;
|
||||
virBuffer controlBuf = VIR_BUFFER_INITIALIZER;
|
||||
|
||||
if (!nnodes)
|
||||
return 0;
|
||||
|
||||
virBufferAddLit(buf, "<memory_bandwidth>\n");
|
||||
virBufferAdjustIndent(buf, 2);
|
||||
|
||||
for (i = 0; i < nnodes; i++) {
|
||||
virCapsHostMemBWNodePtr node = nodes[i];
|
||||
virResctrlInfoMemBWPerNodePtr control = &node->control;
|
||||
char *cpus_str = virBitmapFormat(node->cpus);
|
||||
|
||||
if (!cpus_str)
|
||||
return -1;
|
||||
|
||||
virBufferAsprintf(buf,
|
||||
"<node id='%u' cpus='%s'",
|
||||
node->id, cpus_str);
|
||||
VIR_FREE(cpus_str);
|
||||
|
||||
virBufferSetChildIndent(&controlBuf, buf);
|
||||
virBufferAsprintf(&controlBuf,
|
||||
"<control granularity='%u' min ='%u' "
|
||||
"maxAllocs='%u'/>\n",
|
||||
control->granularity, control->min,
|
||||
control->max_allocation);
|
||||
|
||||
if (virBufferCheckError(&controlBuf) < 0)
|
||||
return -1;
|
||||
|
||||
if (virBufferUse(&controlBuf)) {
|
||||
virBufferAddLit(buf, ">\n");
|
||||
virBufferAddBuffer(buf, &controlBuf);
|
||||
virBufferAddLit(buf, "</node>\n");
|
||||
} else {
|
||||
virBufferAddLit(buf, "/>\n");
|
||||
}
|
||||
}
|
||||
|
||||
virBufferAdjustIndent(buf, -2);
|
||||
virBufferAddLit(buf, "</memory_bandwidth>\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* virCapabilitiesFormatXML:
|
||||
* @caps: capabilities to format
|
||||
@ -1049,6 +1115,10 @@ virCapabilitiesFormatXML(virCapsPtr caps)
|
||||
caps->host.caches) < 0)
|
||||
goto error;
|
||||
|
||||
if (virCapabilitiesFormatMemoryBandwidth(&buf, caps->host.nnodes,
|
||||
caps->host.nodes) < 0)
|
||||
goto error;
|
||||
|
||||
for (i = 0; i < caps->host.nsecModels; i++) {
|
||||
virBufferAddLit(&buf, "<secmodel>\n");
|
||||
virBufferAdjustIndent(&buf, 2);
|
||||
@ -1591,6 +1661,40 @@ virCapabilitiesInitResctrl(virCapsPtr caps)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virCapabilitiesInitResctrlMemory(virCapsPtr caps)
|
||||
{
|
||||
virCapsHostMemBWNodePtr node = NULL;
|
||||
size_t i = 0;
|
||||
int ret = -1;
|
||||
|
||||
for (i = 0; i < caps->host.ncaches; i++) {
|
||||
virCapsHostCacheBankPtr bank = caps->host.caches[i];
|
||||
if (VIR_ALLOC(node) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virResctrlInfoGetMemoryBandwidth(caps->host.resctrl,
|
||||
bank->level, &node->control) > 0) {
|
||||
node->id = bank->id;
|
||||
if (!(node->cpus = virBitmapNewCopy(bank->cpus)))
|
||||
goto cleanup;
|
||||
|
||||
if (VIR_APPEND_ELEMENT(caps->host.nodes,
|
||||
caps->host.nnodes, node) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
virCapsHostMemBWNodeFree(node);
|
||||
node = NULL;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
virCapsHostMemBWNodeFree(node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
virCapabilitiesInitCaches(virCapsPtr caps)
|
||||
{
|
||||
@ -1720,6 +1824,9 @@ virCapabilitiesInitCaches(virCapsPtr caps)
|
||||
qsort(caps->host.caches, caps->host.ncaches,
|
||||
sizeof(*caps->host.caches), virCapsHostCacheBankSorter);
|
||||
|
||||
if (virCapabilitiesInitResctrlMemory(caps) < 0)
|
||||
goto cleanup;
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
VIR_FREE(type);
|
||||
|
@ -151,6 +151,14 @@ struct _virCapsHostCacheBank {
|
||||
virResctrlInfoPerCachePtr *controls;
|
||||
};
|
||||
|
||||
typedef struct _virCapsHostMemBWNode virCapsHostMemBWNode;
|
||||
typedef virCapsHostMemBWNode *virCapsHostMemBWNodePtr;
|
||||
struct _virCapsHostMemBWNode {
|
||||
unsigned int id;
|
||||
virBitmapPtr cpus; /* All CPUs that belong to this node*/
|
||||
virResctrlInfoMemBWPerNode control;
|
||||
};
|
||||
|
||||
typedef struct _virCapsHost virCapsHost;
|
||||
typedef virCapsHost *virCapsHostPtr;
|
||||
struct _virCapsHost {
|
||||
@ -175,6 +183,9 @@ struct _virCapsHost {
|
||||
size_t ncaches;
|
||||
virCapsHostCacheBankPtr *caches;
|
||||
|
||||
size_t nnodes;
|
||||
virCapsHostMemBWNodePtr *nodes;
|
||||
|
||||
size_t nsecModels;
|
||||
virCapsHostSecModelPtr secModels;
|
||||
|
||||
|
@ -629,6 +629,26 @@ virResctrlInfoIsEmpty(virResctrlInfoPtr resctrl)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
virResctrlInfoGetMemoryBandwidth(virResctrlInfoPtr resctrl,
|
||||
unsigned int level,
|
||||
virResctrlInfoMemBWPerNodePtr control)
|
||||
{
|
||||
virResctrlInfoMemBWPtr membw_info = resctrl->membw_info;
|
||||
|
||||
if (!membw_info)
|
||||
return 0;
|
||||
|
||||
if (membw_info->last_level_cache != level)
|
||||
return 0;
|
||||
|
||||
control->granularity = membw_info->bandwidth_granularity;
|
||||
control->min = membw_info->min_bandwidth;
|
||||
control->max_allocation = membw_info->max_allocation;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
virResctrlInfoGetCache(virResctrlInfoPtr resctrl,
|
||||
unsigned int level,
|
||||
|
@ -50,6 +50,17 @@ struct _virResctrlInfoPerCache {
|
||||
unsigned int max_allocation;
|
||||
};
|
||||
|
||||
typedef struct _virResctrlInfoMemBWPerNode virResctrlInfoMemBWPerNode;
|
||||
typedef virResctrlInfoMemBWPerNode *virResctrlInfoMemBWPerNodePtr;
|
||||
struct _virResctrlInfoMemBWPerNode {
|
||||
/* Smallest possible increase of the allocation bandwidth in percentage */
|
||||
unsigned int granularity;
|
||||
/* Minimal allocatable bandwidth in percentage */
|
||||
unsigned int min;
|
||||
/* Maximum number of simultaneous allocations */
|
||||
unsigned int max_allocation;
|
||||
};
|
||||
|
||||
typedef struct _virResctrlInfo virResctrlInfo;
|
||||
typedef virResctrlInfo *virResctrlInfoPtr;
|
||||
|
||||
@ -63,6 +74,10 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl,
|
||||
size_t *ncontrols,
|
||||
virResctrlInfoPerCachePtr **controls);
|
||||
|
||||
int
|
||||
virResctrlInfoGetMemoryBandwidth(virResctrlInfoPtr resctrl,
|
||||
unsigned int level,
|
||||
virResctrlInfoMemBWPerNodePtr control);
|
||||
/* Alloc-related things */
|
||||
typedef struct _virResctrlAlloc virResctrlAlloc;
|
||||
typedef virResctrlAlloc *virResctrlAllocPtr;
|
||||
|
@ -0,0 +1 @@
|
||||
10
|
@ -0,0 +1 @@
|
||||
10
|
@ -0,0 +1 @@
|
||||
4
|
@ -49,6 +49,14 @@
|
||||
<control granularity='768' min='1536' unit='KiB' type='both' maxAllocs='4'/>
|
||||
</bank>
|
||||
</cache>
|
||||
<memory_bandwidth>
|
||||
<node id='0' cpus='0-5'>
|
||||
<control granularity='10' min ='10' maxAllocs='4'/>
|
||||
</node>
|
||||
<node id='1' cpus='6-11'>
|
||||
<control granularity='10' min ='10' maxAllocs='4'/>
|
||||
</node>
|
||||
</memory_bandwidth>
|
||||
</host>
|
||||
|
||||
</capabilities>
|
||||
|
@ -1 +1,2 @@
|
||||
L3:0=000ff;1=000f0
|
||||
MB:0=100;1=100
|
||||
|
Loading…
Reference in New Issue
Block a user