diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 2efee8f0c0..3dd2d0822d 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -132,6 +132,7 @@ typedef enum { VIR_FROM_PERF = 65, /* Error from perf */ VIR_FROM_LIBSSH = 66, /* Error from libssh connection transport */ + VIR_FROM_RESCTRL = 67, /* Error from resource control */ # ifdef VIR_ENUM_SENTINELS VIR_ERR_DOMAIN_LAST diff --git a/src/Makefile.am b/src/Makefile.am index b8e8754829..c3c7a8f04d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -167,6 +167,7 @@ UTIL_SOURCES = \ util/virprocess.c util/virprocess.h \ util/virqemu.c util/virqemu.h \ util/virrandom.h util/virrandom.c \ + util/virresctrl.h util/virresctrl.c \ util/virrotatingfile.h util/virrotatingfile.c \ util/virscsi.c util/virscsi.h \ util/virscsihost.c util/virscsihost.h \ diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index e851539bd6..18849adfca 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c @@ -31,8 +31,6 @@ #include #include "capabilities.h" -#include "c-ctype.h" -#include "count-one-bits.h" #include "cpu_conf.h" #include "domain_conf.h" #include "physmem.h" @@ -52,7 +50,6 @@ #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") @@ -1539,12 +1536,6 @@ VIR_ENUM_IMPL(virCacheKernel, VIR_CACHE_TYPE_LAST, "Instruction", "Data") -/* Our naming for cache types and scopes */ -VIR_ENUM_IMPL(virCache, VIR_CACHE_TYPE_LAST, - "both", - "code", - "data") - bool virCapsHostCacheBankEquals(virCapsHostCacheBankPtr a, virCapsHostCacheBankPtr b) @@ -1571,111 +1562,6 @@ virCapsHostCacheBankFree(virCapsHostCacheBankPtr 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 *tmp = NULL; - char *path = NULL; - char *cbm_mask = NULL; - char *type_upper = NULL; - unsigned int bits = 0; - 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); - - for (tmp = cbm_mask; *tmp != '\0'; tmp++) { - if (c_isxdigit(*tmp)) - bits += count_one_bits(virHexToBin(*tmp)); - } - - control->granularity = bank->size / bits; - if (min_cbm_bits != 1) - control->min = min_cbm_bits * control->granularity; - - 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) { @@ -1760,17 +1646,27 @@ virCapabilitiesInitCaches(virCapsPtr caps) SYSFS_SYSTEM_PATH, pos, ent->d_name) < 0) goto cleanup; - typeret = virCapabilitiesGetCacheControlType(bank); + typeret = virResctrlGetCacheControlType(bank->level); if (typeret == 0) { - if (virCapabilitiesGetCacheControl(bank, - VIR_CACHE_TYPE_BOTH) < 0) + if (virResctrlGetCacheInfo(bank->level, + bank->size, + VIR_CACHE_TYPE_BOTH, + &bank->controls, + &bank->ncontrols) < 0) goto cleanup; } else if (typeret == 1) { - if (virCapabilitiesGetCacheControl(bank, - VIR_CACHE_TYPE_CODE) < 0 || - virCapabilitiesGetCacheControl(bank, - VIR_CACHE_TYPE_DATA) < 0) + if (virResctrlGetCacheInfo(bank->level, + bank->size, + VIR_CACHE_TYPE_CODE, + &bank->controls, + &bank->ncontrols) < 0) + goto cleanup; + if (virResctrlGetCacheInfo(bank->level, + bank->size, + VIR_CACHE_TYPE_DATA, + &bank->controls, + &bank->ncontrols) < 0) goto cleanup; } diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h index 39a9bc6892..bd64498d1c 100644 --- a/src/conf/capabilities.h +++ b/src/conf/capabilities.h @@ -30,6 +30,7 @@ # include "virarch.h" # include "virmacaddr.h" # include "virobject.h" +# include "virresctrl.h" # include @@ -138,29 +139,6 @@ struct _virCapsHostSecModel { virCapsHostSecModelLabelPtr labels; }; -typedef enum { - VIR_CACHE_TYPE_BOTH, - VIR_CACHE_TYPE_CODE, - VIR_CACHE_TYPE_DATA, - - VIR_CACHE_TYPE_LAST -} virCacheType; - -VIR_ENUM_DECL(virCache); - -typedef struct _virCapsHostCacheControl virCapsHostCacheControl; -typedef virCapsHostCacheControl *virCapsHostCacheControlPtr; -struct _virCapsHostCacheControl { - /* Smallest possible increase of the allocation size in bytes */ - unsigned long long granularity; - /* Minimal allocatable size in bytes (if different from granularity) */ - unsigned long long min; - /* Type of the allocation */ - virCacheType scope; - /* Maximum number of simultaneous allocations */ - unsigned int max_allocation; -}; - typedef struct _virCapsHostCacheBank virCapsHostCacheBank; typedef virCapsHostCacheBank *virCapsHostCacheBankPtr; struct _virCapsHostCacheBank { @@ -170,7 +148,7 @@ struct _virCapsHostCacheBank { virCacheType type; /* Data, Instruction or Unified */ virBitmapPtr cpus; /* All CPUs that share this bank */ size_t ncontrols; - virCapsHostCacheControlPtr *controls; + virResctrlPtr *controls; }; typedef struct _virCapsHost virCapsHost; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e6868b55fd..447dd938d0 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2465,6 +2465,13 @@ virRandomGenerateWWN; virRandomInt; +# util/virresctrl.h +virCacheTypeFromString; +virCacheTypeToString; +virResctrlGetCacheControlType; +virResctrlGetCacheInfo; + + # util/virrotatingfile.h virRotatingFileReaderConsume; virRotatingFileReaderFree; diff --git a/src/util/virerror.c b/src/util/virerror.c index ef17fb5e6e..a5a2d6ed10 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -139,6 +139,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST, "Perf", /* 65 */ "Libssh transport layer", + "Resource control", ) diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c new file mode 100644 index 0000000000..dfc062c2a0 --- /dev/null +++ b/src/util/virresctrl.c @@ -0,0 +1,153 @@ +/* + * virresctrl.c: + * + * 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 + * . + */ + +#include + +#include "virresctrl.h" + +#include "c-ctype.h" +#include "count-one-bits.h" +#include "viralloc.h" +#include "virfile.h" +#include "virlog.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_RESCTRL + +VIR_LOG_INIT("util.virresctrl") + +#define SYSFS_RESCTRL_PATH "/sys/fs/resctrl" + +/* Resctrl is short for Resource Control. It might be implemented for various + * resources, but at the time of this writing this is only supported for cache + * allocation technology (aka CAT). Hence the reson for leaving 'Cache' out of + * all the structure and function names for now (can be added later if needed. + */ + +/* Our naming for cache types and scopes */ +VIR_ENUM_IMPL(virCache, VIR_CACHE_TYPE_LAST, + "both", + "code", + "data") + +int +virResctrlGetCacheInfo(unsigned int level, + unsigned long long size, + virCacheType scope, + virResctrlPtr **controls, + size_t *ncontrols) +{ + int ret = -1; + char *tmp = NULL; + char *path = NULL; + char *cbm_mask = NULL; + char *type_upper = NULL; + unsigned int bits = 0; + unsigned int min_cbm_bits = 0; + virResctrlPtr 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", + level, + type_upper ? type_upper : "") < 0) + goto cleanup; + + if (virFileReadValueString(&cbm_mask, + SYSFS_RESCTRL_PATH + "/info/L%u%s/cbm_mask", + level, + type_upper ? type_upper: "") < 0) + goto cleanup; + + if (virFileReadValueUint(&min_cbm_bits, + SYSFS_RESCTRL_PATH "/info/L%u%s/min_cbm_bits", + level, + type_upper ? type_upper : "") < 0) + goto cleanup; + + virStringTrimOptionalNewline(cbm_mask); + + for (tmp = cbm_mask; *tmp != '\0'; tmp++) { + if (c_isxdigit(*tmp)) + bits += count_one_bits(virHexToBin(*tmp)); + } + + control->granularity = size / bits; + if (min_cbm_bits != 1) + control->min = min_cbm_bits * control->granularity; + + control->scope = scope; + + if (VIR_APPEND_ELEMENT(*controls, *ncontrols, control) < 0) + goto cleanup; + + ret = 0; + + cleanup: + VIR_FREE(path); + VIR_FREE(cbm_mask); + VIR_FREE(type_upper); + VIR_FREE(control); + return ret; +} + + +/* + * This function tests which TYPE of cache control is supported + * Return values are: + * -1: not supported + * 0: CAT + * 1: CDP + */ +int +virResctrlGetCacheControlType(unsigned int level) +{ + int ret = -1; + char *path = NULL; + + if (virAsprintf(&path, + SYSFS_RESCTRL_PATH "/info/L%u", + 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", + level) < 0) + return -1; + if (virFileExists(path)) + ret = 1; + } + + VIR_FREE(path); + return ret; +} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h new file mode 100644 index 0000000000..ee219cbb92 --- /dev/null +++ b/src/util/virresctrl.h @@ -0,0 +1,63 @@ +/* + * virresctrl.h: + * + * 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 + * . + */ + +#ifndef __VIR_RESCTRL_H__ +# define __VIR_RESCTRL_H__ + +# include "internal.h" + +# include "virbitmap.h" +# include "virutil.h" + + +typedef enum { + VIR_CACHE_TYPE_BOTH, + VIR_CACHE_TYPE_CODE, + VIR_CACHE_TYPE_DATA, + + VIR_CACHE_TYPE_LAST +} virCacheType; + +VIR_ENUM_DECL(virCache); + + +typedef struct _virResctrl virResctrl; +typedef virResctrl *virResctrlPtr; +struct _virResctrl { + /* Smallest possible increase of the allocation size in bytes */ + unsigned long long granularity; + /* Minimal allocatable size in bytes (if different from granularity) */ + unsigned long long min; + /* Type of the allocation */ + virCacheType scope; + /* Maximum number of simultaneous allocations */ + unsigned int max_allocation; +}; + + +int +virResctrlGetCacheInfo(unsigned int level, + unsigned long long size, + virCacheType scope, + virResctrlPtr **controls, + size_t *ncontrols); + +int +virResctrlGetCacheControlType(unsigned int level); + +#endif /* __VIR_RESCTRL_H__ */