diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng
index 26f0aa22bd3fe5193049dc7904d2582a26d25e8e..e5cbfa362ec00c44e1dd2e6578e78747dc80cff1 100644
--- a/docs/schemas/capability.rng
+++ b/docs/schemas/capability.rng
@@ -261,13 +261,7 @@
-
-
- both
- code
- data
-
-
+
@@ -277,11 +271,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ both
+ code
+ data
+
+
+
+
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index 43b15761a83c5bca12e31c83e02f71901306214f..3becc7e18c62937febdfbe449a5ff0bf77615459 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -51,6 +51,7 @@
#define VIR_FROM_THIS VIR_FROM_CAPABILITIES
#define SYSFS_SYSTEM_PATH "/sys/devices/system"
+#define SYSFS_RESCTRL_PATH "/sys/fs/resctrl"
VIR_LOG_INIT("conf.capabilities")
@@ -872,6 +873,9 @@ virCapabilitiesFormatCaches(virBufferPtr buf,
virCapsHostCacheBankPtr *caches)
{
size_t i = 0;
+ size_t j = 0;
+ int indent = virBufferGetIndent(buf, false);
+ virBuffer controlBuf = VIR_BUFFER_INITIALIZER;
if (!ncaches)
return 0;
@@ -893,13 +897,33 @@ virCapabilitiesFormatCaches(virBufferPtr buf,
*/
virBufferAsprintf(buf,
"\n",
+ "size='%llu' unit='%s' cpus='%s'",
bank->id, bank->level,
virCacheTypeToString(bank->type),
bank->size >> (kilos * 10),
kilos ? "KiB" : "B",
cpus_str);
+ virBufferAdjustIndent(&controlBuf, indent + 4);
+ for (j = 0; j < bank->ncontrols; j++) {
+ bool min_kilos = !(bank->controls[j]->min % 1024);
+ virBufferAsprintf(&controlBuf,
+ "\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, "\n");
+ } else {
+ virBufferAddLit(buf, "/>\n");
+ }
+
VIR_FREE(cpus_str);
}
@@ -1519,13 +1543,115 @@ virCapsHostCacheBankEquals(virCapsHostCacheBankPtr a,
void
virCapsHostCacheBankFree(virCapsHostCacheBankPtr ptr)
{
+ size_t i;
+
if (!ptr)
return;
virBitmapFree(ptr->cpus);
+ for (i = 0; i < ptr->ncontrols; i++)
+ VIR_FREE(ptr->controls[i]);
+ VIR_FREE(ptr->controls);
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
virCapabilitiesInitCaches(virCapsPtr caps)
{
@@ -1534,6 +1660,7 @@ virCapabilitiesInitCaches(virCapsPtr caps)
ssize_t pos = -1;
DIR *dirp = NULL;
int ret = -1;
+ int typeret;
char *path = NULL;
char *type = NULL;
struct dirent *ent = NULL;
@@ -1609,12 +1736,27 @@ virCapabilitiesInitCaches(virCapsPtr caps)
SYSFS_SYSTEM_PATH, pos, ent->d_name) < 0)
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);
if (kernel_type < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unknown cache type '%s'"), type);
goto cleanup;
}
+
bank->type = kernel_type;
VIR_FREE(type);
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index a8cccf7184a54c92e4babc1dcd9b4ba4d4feb295..ee87d598ef66274b981b9e4a49450ac26a4e9919 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -148,6 +148,14 @@ typedef enum {
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 virCapsHostCacheBank *virCapsHostCacheBankPtr;
struct _virCapsHostCacheBank {
@@ -156,6 +164,8 @@ struct _virCapsHostCacheBank {
unsigned long long size; /* B */
virCacheType type; /* Data, Instruction or Unified */
virBitmapPtr cpus; /* All CPUs that share this bank */
+ size_t ncontrols;
+ virCapsHostCacheControlPtr *controls;
};
typedef struct _virCapsHost virCapsHost;
diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/cpus b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/cpus
new file mode 100644
index 0000000000000000000000000000000000000000..b3a79aa9539f55a27340a614720892b0f2d5b271
--- /dev/null
+++ b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/cpus
@@ -0,0 +1 @@
+ffffff,ffffffff,ffffffff
diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3CODE/cbm_mask b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3CODE/cbm_mask
new file mode 100755
index 0000000000000000000000000000000000000000..78031dae83bfe3e99852a1c6ac48416fe794a0fc
--- /dev/null
+++ b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3CODE/cbm_mask
@@ -0,0 +1 @@
+fffff
diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3CODE/min_cbm_bits b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3CODE/min_cbm_bits
new file mode 100755
index 0000000000000000000000000000000000000000..d00491fd7e5bb6fa28c517a0bb32b8b506539d4d
--- /dev/null
+++ b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3CODE/min_cbm_bits
@@ -0,0 +1 @@
+1
diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3CODE/num_closids b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3CODE/num_closids
new file mode 100755
index 0000000000000000000000000000000000000000..45a4fb75db864000d01701c0f7a51864bd4daabf
--- /dev/null
+++ b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3CODE/num_closids
@@ -0,0 +1 @@
+8
diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3DATA/cbm_mask b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3DATA/cbm_mask
new file mode 100755
index 0000000000000000000000000000000000000000..78031dae83bfe3e99852a1c6ac48416fe794a0fc
--- /dev/null
+++ b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3DATA/cbm_mask
@@ -0,0 +1 @@
+fffff
diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3DATA/min_cbm_bits b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3DATA/min_cbm_bits
new file mode 100755
index 0000000000000000000000000000000000000000..d00491fd7e5bb6fa28c517a0bb32b8b506539d4d
--- /dev/null
+++ b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3DATA/min_cbm_bits
@@ -0,0 +1 @@
+1
diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3DATA/num_closids b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3DATA/num_closids
new file mode 100755
index 0000000000000000000000000000000000000000..45a4fb75db864000d01701c0f7a51864bd4daabf
--- /dev/null
+++ b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/info/L3DATA/num_closids
@@ -0,0 +1 @@
+8
diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/manualres/cpus b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/manualres/cpus
new file mode 100644
index 0000000000000000000000000000000000000000..ede4cc264a442383c128dc3e4a0f6a92712cd5d9
--- /dev/null
+++ b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/manualres/cpus
@@ -0,0 +1 @@
+000000,00000000,00000000
diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/manualres/schemata b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/manualres/schemata
new file mode 100644
index 0000000000000000000000000000000000000000..a0ef3819f066d082e8a842818ef5c781c774a82f
--- /dev/null
+++ b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/manualres/schemata
@@ -0,0 +1,2 @@
+L3DATA:0=c0000;1=c0000
+L3CODE:0=30000;1=30000
diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/manualres/tasks b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/manualres/tasks
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/schemata b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/schemata
new file mode 100644
index 0000000000000000000000000000000000000000..89dc76b86465d8d5f0fa3b9ee003c2d9bf50395c
--- /dev/null
+++ b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/schemata
@@ -0,0 +1,2 @@
+L3DATA:0=fffff;1=fffff
+L3CODE:0=fffff;1=fffff
diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/tasks b/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/tasks
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/system b/tests/vircaps2xmldata/linux-resctrl-cdp/system
new file mode 120000
index 0000000000000000000000000000000000000000..2f3a1d9d6ccc54e153e3c169640a78ad95aaafb6
--- /dev/null
+++ b/tests/vircaps2xmldata/linux-resctrl-cdp/system
@@ -0,0 +1 @@
+../linux-resctrl/system/
\ No newline at end of file
diff --git a/tests/vircaps2xmldata/vircaps-x86_64-resctrl-cdp.xml b/tests/vircaps2xmldata/vircaps-x86_64-resctrl-cdp.xml
new file mode 100644
index 0000000000000000000000000000000000000000..49aa0b98ca88ebe4951422221bd075708305462c
--- /dev/null
+++ b/tests/vircaps2xmldata/vircaps-x86_64-resctrl-cdp.xml
@@ -0,0 +1,55 @@
+
+
+
+
+ x86_64
+
+
+
+
+
+
+
+
+ 1048576
+ 2048
+ 4096
+ 6144
+
+
+
+
+
+
+
+
+ |
+
+ 2097152
+ 4096
+ 6144
+ 8192
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml b/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml
index 6677791321fe6f9e4a8a469900140c4c0a6ea74f..cb78b4ab788dcb90d0dc2f457008a1479087ed01 100644
--- a/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml
+++ b/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml
@@ -41,8 +41,12 @@
-
-
+
+
+
+
+
+
diff --git a/tests/vircaps2xmltest.c b/tests/vircaps2xmltest.c
index 137598e6724fadb984a82c297d1fca2f69d8493b..ae1cd521111eab5d821f6affcc4307db02462726 100644
--- a/tests/vircaps2xmltest.c
+++ b/tests/vircaps2xmltest.c
@@ -47,6 +47,7 @@ test_virCapabilities(const void *opaque)
char *capsXML = NULL;
char *path = NULL;
char *dir = NULL;
+ char *resctrl = NULL;
int ret = -1;
/*
@@ -58,7 +59,12 @@ test_virCapabilities(const void *opaque)
data->resctrl ? "/system" : "") < 0)
goto cleanup;
+ if (virAsprintf(&resctrl, "%s/vircaps2xmldata/linux-%s/resctrl",
+ abs_srcdir, data->filename) < 0)
+ goto cleanup;
+
virFileWrapperAddPrefix("/sys/devices/system", dir);
+ virFileWrapperAddPrefix("/sys/fs/resctrl", resctrl);
caps = virCapabilitiesNew(data->arch, data->offlineMigrate, data->liveMigrate);
if (!caps)
@@ -84,6 +90,7 @@ test_virCapabilities(const void *opaque)
cleanup:
VIR_FREE(dir);
+ VIR_FREE(resctrl);
VIR_FREE(path);
VIR_FREE(capsXML);
virObjectUnref(caps);
@@ -112,6 +119,7 @@ mymain(void)
DO_TEST("caches", VIR_ARCH_X86_64);
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;
}