提交 0ab409cc 编写于 作者: E Eli Qiao 提交者: Martin Kletzander

Expose resource control capabilities for caches

Add cache resource control into capabilities for CAT without CDP:

  <cache>
    <bank id='0' level='3' type='unified' size='15360' unit='KiB' cpus='0-5'>
      <control min='768' unit='KiB' scope='both' max_allocation='4'/>
    </bank>
  </cache>

and with CDP:

  <cache>
    <bank id='0' level='3' type='unified' size='15360' unit='KiB' cpus='0-5'>
      <control min='768' unit='KiB' scope='code' max_allocation='4'/>
      <control min='768' unit='KiB' scope='data' max_allocation='4'/>
    </bank>
  </cache>

Also add new test cases for vircaps2xmltest.
Signed-off-by: NEli Qiao <liyong.qiao@intel.com>
上级 7b4e9b2c
...@@ -261,13 +261,7 @@ ...@@ -261,13 +261,7 @@
<attribute name='level'> <attribute name='level'>
<ref name='unsignedInt'/> <ref name='unsignedInt'/>
</attribute> </attribute>
<attribute name='type'> <ref name='cacheType'/>
<choice>
<value>both</value>
<value>code</value>
<value>data</value>
</choice>
</attribute>
<attribute name='size'> <attribute name='size'>
<ref name='unsignedInt'/> <ref name='unsignedInt'/>
</attribute> </attribute>
...@@ -277,11 +271,35 @@ ...@@ -277,11 +271,35 @@
<attribute name='cpus'> <attribute name='cpus'>
<ref name='cpuset'/> <ref name='cpuset'/>
</attribute> </attribute>
<zeroOrMore>
<element name='control'>
<attribute name='min'>
<ref name='unsignedInt'/>
</attribute>
<attribute name='unit'>
<ref name='unit'/>
</attribute>
<ref name='cacheType'/>
<attribute name='maxAllocs'>
<ref name='unsignedInt'/>
</attribute>
</element>
</zeroOrMore>
</element> </element>
</oneOrMore> </oneOrMore>
</element> </element>
</define> </define>
<define name='cacheType'>
<attribute name='type'>
<choice>
<value>both</value>
<value>code</value>
<value>data</value>
</choice>
</attribute>
</define>
<define name='guestcaps'> <define name='guestcaps'>
<element name='guest'> <element name='guest'>
<ref name='ostype'/> <ref name='ostype'/>
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#define VIR_FROM_THIS VIR_FROM_CAPABILITIES #define VIR_FROM_THIS VIR_FROM_CAPABILITIES
#define SYSFS_SYSTEM_PATH "/sys/devices/system" #define SYSFS_SYSTEM_PATH "/sys/devices/system"
#define SYSFS_RESCTRL_PATH "/sys/fs/resctrl"
VIR_LOG_INIT("conf.capabilities") VIR_LOG_INIT("conf.capabilities")
...@@ -872,6 +873,9 @@ virCapabilitiesFormatCaches(virBufferPtr buf, ...@@ -872,6 +873,9 @@ virCapabilitiesFormatCaches(virBufferPtr buf,
virCapsHostCacheBankPtr *caches) virCapsHostCacheBankPtr *caches)
{ {
size_t i = 0; size_t i = 0;
size_t j = 0;
int indent = virBufferGetIndent(buf, false);
virBuffer controlBuf = VIR_BUFFER_INITIALIZER;
if (!ncaches) if (!ncaches)
return 0; return 0;
...@@ -893,13 +897,33 @@ virCapabilitiesFormatCaches(virBufferPtr buf, ...@@ -893,13 +897,33 @@ virCapabilitiesFormatCaches(virBufferPtr buf,
*/ */
virBufferAsprintf(buf, virBufferAsprintf(buf,
"<bank id='%u' level='%u' type='%s' " "<bank id='%u' level='%u' type='%s' "
"size='%llu' unit='%s' cpus='%s'/>\n", "size='%llu' unit='%s' cpus='%s'",
bank->id, bank->level, bank->id, bank->level,
virCacheTypeToString(bank->type), virCacheTypeToString(bank->type),
bank->size >> (kilos * 10), bank->size >> (kilos * 10),
kilos ? "KiB" : "B", kilos ? "KiB" : "B",
cpus_str); cpus_str);
virBufferAdjustIndent(&controlBuf, indent + 4);
for (j = 0; j < bank->ncontrols; j++) {
bool min_kilos = !(bank->controls[j]->min % 1024);
virBufferAsprintf(&controlBuf,
"<control min='%llu' unit='%s' "
"type='%s' maxAllocs='%u'/>\n",
bank->controls[j]->min >> (min_kilos * 10),
min_kilos ? "KiB" : "B",
virCacheTypeToString(bank->controls[j]->scope),
bank->controls[j]->max_allocation);
}
if (virBufferUse(&controlBuf)) {
virBufferAddLit(buf, ">\n");
virBufferAddBuffer(buf, &controlBuf);
virBufferAddLit(buf, "</bank>\n");
} else {
virBufferAddLit(buf, "/>\n");
}
VIR_FREE(cpus_str); VIR_FREE(cpus_str);
} }
...@@ -1519,13 +1543,115 @@ virCapsHostCacheBankEquals(virCapsHostCacheBankPtr a, ...@@ -1519,13 +1543,115 @@ virCapsHostCacheBankEquals(virCapsHostCacheBankPtr a,
void void
virCapsHostCacheBankFree(virCapsHostCacheBankPtr ptr) virCapsHostCacheBankFree(virCapsHostCacheBankPtr ptr)
{ {
size_t i;
if (!ptr) if (!ptr)
return; return;
virBitmapFree(ptr->cpus); virBitmapFree(ptr->cpus);
for (i = 0; i < ptr->ncontrols; i++)
VIR_FREE(ptr->controls[i]);
VIR_FREE(ptr->controls);
VIR_FREE(ptr); VIR_FREE(ptr);
} }
/*
* This function tests which TYPE of cache control is supported
* Return values are:
* -1: not supported
* 0: CAT
* 1: CDP
*/
static int
virCapabilitiesGetCacheControlType(virCapsHostCacheBankPtr bank)
{
int ret = -1;
char *path = NULL;
if (virAsprintf(&path,
SYSFS_RESCTRL_PATH "/info/L%u",
bank->level) < 0)
return -1;
if (virFileExists(path)) {
ret = 0;
} else {
VIR_FREE(path);
/*
* If CDP is enabled, there will be both CODE and DATA, but it's enough
* to check one of those only.
*/
if (virAsprintf(&path,
SYSFS_RESCTRL_PATH "/info/L%uCODE",
bank->level) < 0)
return -1;
if (virFileExists(path))
ret = 1;
}
VIR_FREE(path);
return ret;
}
static int
virCapabilitiesGetCacheControl(virCapsHostCacheBankPtr bank,
virCacheType scope)
{
int ret = -1;
char *path = NULL;
char *cbm_mask = NULL;
char *type_upper = NULL;
unsigned int min_cbm_bits = 0;
virCapsHostCacheControlPtr control;
if (VIR_ALLOC(control) < 0)
goto cleanup;
if (scope != VIR_CACHE_TYPE_BOTH &&
virStringToUpper(&type_upper, virCacheTypeToString(scope)) < 0)
goto cleanup;
if (virFileReadValueUint(&control->max_allocation,
SYSFS_RESCTRL_PATH "/info/L%u%s/num_closids",
bank->level,
type_upper ? type_upper : "") < 0)
goto cleanup;
if (virFileReadValueString(&cbm_mask,
SYSFS_RESCTRL_PATH
"/info/L%u%s/cbm_mask",
bank->level,
type_upper ? type_upper: "") < 0)
goto cleanup;
if (virFileReadValueUint(&min_cbm_bits,
SYSFS_RESCTRL_PATH "/info/L%u%s/min_cbm_bits",
bank->level,
type_upper ? type_upper : "") < 0)
goto cleanup;
virStringTrimOptionalNewline(cbm_mask);
/* cbm_mask: cache bit mask, it's in hex, eg: fffff */
control->min = min_cbm_bits * bank->size / (strlen(cbm_mask) * 4);
control->scope = scope;
if (VIR_APPEND_ELEMENT(bank->controls,
bank->ncontrols,
control) < 0)
goto cleanup;
ret = 0;
cleanup:
VIR_FREE(path);
VIR_FREE(cbm_mask);
VIR_FREE(type_upper);
VIR_FREE(control);
return ret;
}
int int
virCapabilitiesInitCaches(virCapsPtr caps) virCapabilitiesInitCaches(virCapsPtr caps)
{ {
...@@ -1534,6 +1660,7 @@ virCapabilitiesInitCaches(virCapsPtr caps) ...@@ -1534,6 +1660,7 @@ virCapabilitiesInitCaches(virCapsPtr caps)
ssize_t pos = -1; ssize_t pos = -1;
DIR *dirp = NULL; DIR *dirp = NULL;
int ret = -1; int ret = -1;
int typeret;
char *path = NULL; char *path = NULL;
char *type = NULL; char *type = NULL;
struct dirent *ent = NULL; struct dirent *ent = NULL;
...@@ -1609,12 +1736,27 @@ virCapabilitiesInitCaches(virCapsPtr caps) ...@@ -1609,12 +1736,27 @@ virCapabilitiesInitCaches(virCapsPtr caps)
SYSFS_SYSTEM_PATH, pos, ent->d_name) < 0) SYSFS_SYSTEM_PATH, pos, ent->d_name) < 0)
goto cleanup; goto cleanup;
typeret = virCapabilitiesGetCacheControlType(bank);
if (typeret == 0) {
if (virCapabilitiesGetCacheControl(bank,
VIR_CACHE_TYPE_BOTH) < 0)
goto cleanup;
} else if (typeret == 1) {
if (virCapabilitiesGetCacheControl(bank,
VIR_CACHE_TYPE_CODE) < 0 ||
virCapabilitiesGetCacheControl(bank,
VIR_CACHE_TYPE_DATA) < 0)
goto cleanup;
}
kernel_type = virCacheKernelTypeFromString(type); kernel_type = virCacheKernelTypeFromString(type);
if (kernel_type < 0) { if (kernel_type < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unknown cache type '%s'"), type); _("Unknown cache type '%s'"), type);
goto cleanup; goto cleanup;
} }
bank->type = kernel_type; bank->type = kernel_type;
VIR_FREE(type); VIR_FREE(type);
......
...@@ -148,6 +148,14 @@ typedef enum { ...@@ -148,6 +148,14 @@ typedef enum {
VIR_ENUM_DECL(virCache); VIR_ENUM_DECL(virCache);
typedef struct _virCapsHostCacheControl virCapsHostCacheControl;
typedef virCapsHostCacheControl *virCapsHostCacheControlPtr;
struct _virCapsHostCacheControl {
unsigned long long min; /* minimum cache control size in B */
virCacheType scope; /* data, code or both */
unsigned int max_allocation; /* max number of supported allocations */
};
typedef struct _virCapsHostCacheBank virCapsHostCacheBank; typedef struct _virCapsHostCacheBank virCapsHostCacheBank;
typedef virCapsHostCacheBank *virCapsHostCacheBankPtr; typedef virCapsHostCacheBank *virCapsHostCacheBankPtr;
struct _virCapsHostCacheBank { struct _virCapsHostCacheBank {
...@@ -156,6 +164,8 @@ struct _virCapsHostCacheBank { ...@@ -156,6 +164,8 @@ struct _virCapsHostCacheBank {
unsigned long long size; /* B */ unsigned long long size; /* B */
virCacheType type; /* Data, Instruction or Unified */ virCacheType type; /* Data, Instruction or Unified */
virBitmapPtr cpus; /* All CPUs that share this bank */ virBitmapPtr cpus; /* All CPUs that share this bank */
size_t ncontrols;
virCapsHostCacheControlPtr *controls;
}; };
typedef struct _virCapsHost virCapsHost; typedef struct _virCapsHost virCapsHost;
......
L3DATA:0=fffff;1=fffff
L3CODE:0=fffff;1=fffff
../linux-resctrl/system/
\ No newline at end of file
<capabilities>
<host>
<cpu>
<arch>x86_64</arch>
</cpu>
<power_management/>
<migration_features>
<live/>
</migration_features>
<topology>
<cells num='2'>
<cell id='0'>
<memory unit='KiB'>1048576</memory>
<pages unit='KiB' size='4'>2048</pages>
<pages unit='KiB' size='2048'>4096</pages>
<pages unit='KiB' size='1048576'>6144</pages>
<cpus num='6'>
<cpu id='0' socket_id='0' core_id='0' siblings='0'/>
<cpu id='1' socket_id='0' core_id='1' siblings='1'/>
<cpu id='2' socket_id='0' core_id='2' siblings='2'/>
<cpu id='3' socket_id='0' core_id='3' siblings='3'/>
<cpu id='4' socket_id='0' core_id='4' siblings='4'/>
<cpu id='5' socket_id='0' core_id='5' siblings='5'/>
</cpus>
</cell>
<cell id='1'>
<memory unit='KiB'>2097152</memory>
<pages unit='KiB' size='4'>4096</pages>
<pages unit='KiB' size='2048'>6144</pages>
<pages unit='KiB' size='1048576'>8192</pages>
<cpus num='6'>
<cpu id='6' socket_id='1' core_id='0' siblings='6'/>
<cpu id='7' socket_id='1' core_id='1' siblings='7'/>
<cpu id='8' socket_id='1' core_id='2' siblings='8'/>
<cpu id='9' socket_id='1' core_id='3' siblings='9'/>
<cpu id='10' socket_id='1' core_id='4' siblings='10'/>
<cpu id='11' socket_id='1' core_id='5' siblings='11'/>
</cpus>
</cell>
</cells>
</topology>
<cache>
<bank id='0' level='3' type='both' size='15360' unit='KiB' cpus='0-5'>
<control min='768' unit='KiB' type='code' maxAllocs='8'/>
<control min='768' unit='KiB' type='data' maxAllocs='8'/>
</bank>
<bank id='1' level='3' type='both' size='15360' unit='KiB' cpus='6-11'>
<control min='768' unit='KiB' type='code' maxAllocs='8'/>
<control min='768' unit='KiB' type='data' maxAllocs='8'/>
</bank>
</cache>
</host>
</capabilities>
...@@ -41,8 +41,12 @@ ...@@ -41,8 +41,12 @@
</cells> </cells>
</topology> </topology>
<cache> <cache>
<bank id='0' level='3' type='both' size='15360' unit='KiB' cpus='0-5'/> <bank id='0' level='3' type='both' size='15360' unit='KiB' cpus='0-5'>
<bank id='1' level='3' type='both' size='15360' unit='KiB' cpus='6-11'/> <control min='1536' unit='KiB' type='both' maxAllocs='4'/>
</bank>
<bank id='1' level='3' type='both' size='15360' unit='KiB' cpus='6-11'>
<control min='1536' unit='KiB' type='both' maxAllocs='4'/>
</bank>
</cache> </cache>
</host> </host>
......
...@@ -47,6 +47,7 @@ test_virCapabilities(const void *opaque) ...@@ -47,6 +47,7 @@ test_virCapabilities(const void *opaque)
char *capsXML = NULL; char *capsXML = NULL;
char *path = NULL; char *path = NULL;
char *dir = NULL; char *dir = NULL;
char *resctrl = NULL;
int ret = -1; int ret = -1;
/* /*
...@@ -58,7 +59,12 @@ test_virCapabilities(const void *opaque) ...@@ -58,7 +59,12 @@ test_virCapabilities(const void *opaque)
data->resctrl ? "/system" : "") < 0) data->resctrl ? "/system" : "") < 0)
goto cleanup; goto cleanup;
if (virAsprintf(&resctrl, "%s/vircaps2xmldata/linux-%s/resctrl",
abs_srcdir, data->filename) < 0)
goto cleanup;
virFileWrapperAddPrefix("/sys/devices/system", dir); virFileWrapperAddPrefix("/sys/devices/system", dir);
virFileWrapperAddPrefix("/sys/fs/resctrl", resctrl);
caps = virCapabilitiesNew(data->arch, data->offlineMigrate, data->liveMigrate); caps = virCapabilitiesNew(data->arch, data->offlineMigrate, data->liveMigrate);
if (!caps) if (!caps)
...@@ -84,6 +90,7 @@ test_virCapabilities(const void *opaque) ...@@ -84,6 +90,7 @@ test_virCapabilities(const void *opaque)
cleanup: cleanup:
VIR_FREE(dir); VIR_FREE(dir);
VIR_FREE(resctrl);
VIR_FREE(path); VIR_FREE(path);
VIR_FREE(capsXML); VIR_FREE(capsXML);
virObjectUnref(caps); virObjectUnref(caps);
...@@ -112,6 +119,7 @@ mymain(void) ...@@ -112,6 +119,7 @@ mymain(void)
DO_TEST("caches", VIR_ARCH_X86_64); DO_TEST("caches", VIR_ARCH_X86_64);
DO_TEST_FULL("resctrl", VIR_ARCH_X86_64, true, true, true); DO_TEST_FULL("resctrl", VIR_ARCH_X86_64, true, true, true);
DO_TEST_FULL("resctrl-cdp", VIR_ARCH_X86_64, true, true, true);
return ret; return ret;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册