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; }