Introduce function for reporting CMT capability through going through
files under /sys/fs/info/L3_MON.
This patch is co-work with later patches and report these
information to domain.
Signed-off-by: Wang Huaqiang <huaqiang.wang(a)intel.com>
---
src/conf/capabilities.c | 6 ++-
src/conf/capabilities.h | 1 +
src/util/virresctrl.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++--
src/util/virresctrl.h | 17 ++++++-
4 files changed, 137 insertions(+), 7 deletions(-)
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index 326bd15..5280348 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -1626,6 +1626,9 @@ virCapsHostCacheBankFree(virCapsHostCacheBankPtr ptr)
virBitmapFree(ptr->cpus);
for (i = 0; i < ptr->ncontrols; i++)
VIR_FREE(ptr->controls[i]);
+ if (ptr->monitor && ptr->monitor->features)
+ virStringListFree(ptr->monitor->features);
+ VIR_FREE(ptr->monitor);
VIR_FREE(ptr->controls);
VIR_FREE(ptr);
}
@@ -1801,7 +1804,8 @@ virCapabilitiesInitCaches(virCapsPtr caps)
bank->level,
bank->size,
&bank->ncontrols,
- &bank->controls) < 0)
+ &bank->controls,
+ &bank->monitor) < 0)
goto cleanup;
if (VIR_APPEND_ELEMENT(caps->host.caches,
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index 046e275..3ed2523 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -149,6 +149,7 @@ struct _virCapsHostCacheBank {
virBitmapPtr cpus; /* All CPUs that share this bank */
size_t ncontrols;
virResctrlInfoPerCachePtr *controls;
+ virResctrlInfoMonPtr monitor;
};
typedef struct _virCapsHostMemBWNode virCapsHostMemBWNode;
diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
index 4b5442f..2f6923a 100644
--- a/src/util/virresctrl.c
+++ b/src/util/virresctrl.c
@@ -146,6 +146,8 @@ struct _virResctrlInfo {
size_t nlevels;
virResctrlInfoMemBWPtr membw_info;
+
+ virResctrlInfoMonPtr monitor_info;
};
@@ -171,6 +173,9 @@ virResctrlInfoDispose(void *obj)
VIR_FREE(level);
}
+ if (resctrl->monitor_info)
+ virStringListFree(resctrl->monitor_info->features);
+ VIR_FREE(resctrl->monitor_info);
VIR_FREE(resctrl->membw_info);
VIR_FREE(resctrl->levels);
}
@@ -556,6 +561,81 @@ virResctrlGetMemoryBandwidthInfo(virResctrlInfoPtr resctrl)
static int
+virResctrlGetMonitorInfo(virResctrlInfoPtr resctrl)
+{
+ int rv = -1;
+ char *featurestr = NULL;
+ char **lines = NULL;
+ size_t nlines = 0;
+ size_t i = 0;
+ int ret = -1;
+ virResctrlInfoMonPtr info = NULL;
+
+ if (VIR_ALLOC(info) < 0)
+ return -1;
+
+ rv = virFileReadValueUint(&info->max_allocation,
+ SYSFS_RESCTRL_PATH "/info/L3_MON/num_rmids");
+ if (rv == -2) {
+ /* The file doesn't exist, so it's unusable for us,
+ * probably resource monitoring feature unsupported */
+ VIR_WARN("The path '" SYSFS_RESCTRL_PATH
"/info/L3_MON/num_rmids' "
+ "does not exist");
+
+ ret = 0;
+ goto cleanup;
+ } else if (rv < 0) {
+ /* Other failures are fatal, so just quit */
+ goto cleanup;
+ }
+
+ rv = virFileReadValueUint(&info->cache_threshold,
+ SYSFS_RESCTRL_PATH
+ "/info/L3_MON/max_threshold_occupancy");
+
+ if (rv == -2) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot get max_threshold_occupancy from resctrl"
+ " info"));
+ }
+ if (rv < 0)
+ goto cleanup;
+
+ rv = virFileReadValueString(&featurestr,
+ SYSFS_RESCTRL_PATH
+ "/info/L3_MON/mon_features");
+ if (rv == -2)
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot get mon_features from resctrl info"));
+ if (rv < 0)
+ goto cleanup;
+
+ lines = virStringSplitCount(featurestr, "\n", 0, &nlines);
+
+ for (i = 0; i < nlines; i++) {
+ if (STREQLEN(lines[i], "llc_", strlen("llc_")) ||
+ STREQLEN(lines[i], "mbm_", strlen("mbm_"))) {
+ if (virStringListAdd(&info->features, lines[i]) < 0)
+ goto cleanup;
+ info->nfeatures++;
+ }
+ }
+
+ VIR_FREE(featurestr);
+ virStringListFree(lines);
+ resctrl->monitor_info = info;
+ return 0;
+
+ cleanup:
+ VIR_FREE(featurestr);
+ virStringListFree(lines);
+ virStringListFree(info->features);
+ VIR_FREE(info);
+ return ret;
+}
+
+
+static int
virResctrlGetInfo(virResctrlInfoPtr resctrl)
{
DIR *dirp = NULL;
@@ -569,6 +649,10 @@ virResctrlGetInfo(virResctrlInfoPtr resctrl)
if (ret < 0)
goto cleanup;
+ ret = virResctrlGetMonitorInfo(resctrl);
+ if (ret < 0)
+ goto cleanup;
+
ret = virResctrlGetCacheInfo(resctrl, dirp);
if (ret < 0)
goto cleanup;
@@ -654,16 +738,21 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl,
unsigned int level,
unsigned long long size,
size_t *ncontrols,
- virResctrlInfoPerCachePtr **controls)
+ virResctrlInfoPerCachePtr **controls,
+ virResctrlInfoMonPtr *monitor)
{
virResctrlInfoPerLevelPtr i_level = NULL;
virResctrlInfoPerTypePtr i_type = NULL;
+ virResctrlInfoMonPtr cachemon = NULL;
size_t i = 0;
int ret = -1;
if (virResctrlInfoIsEmpty(resctrl))
return 0;
+ if (VIR_ALLOC(cachemon) < 0)
+ return -1;
+
/* Let's take the opportunity to update the number of last level
* cache. This number of memory bandwidth controller is same with
* last level cache */
@@ -716,14 +805,35 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl,
memcpy((*controls)[*ncontrols - 1], &i_type->control,
sizeof(i_type->control));
}
- ret = 0;
- cleanup:
- return ret;
+ cachemon->max_allocation = 0;
+
+ if (resctrl->monitor_info) {
+ virResctrlInfoMonPtr info = resctrl->monitor_info;
+
+ cachemon->max_allocation = info->max_allocation;
+ cachemon->cache_threshold = info->cache_threshold;
+ for (i = 0; i < info->nfeatures; i++) {
+ /* Only cares about last level cache */
+ if (STREQLEN(info->features[i], "llc_",
strlen("llc_"))) {
+ if (virStringListAdd(&cachemon->features,
+ info->features[i]) < 0)
+ goto error;
+ cachemon->nfeatures++;
+ }
+ }
+ }
+
+ if (cachemon->features)
+ *monitor = cachemon;
+
+ return 0;
error:
while (*ncontrols)
VIR_FREE((*controls)[--*ncontrols]);
VIR_FREE(*controls);
- goto cleanup;
+ virStringListFree(cachemon->features);
+ VIR_FREE(cachemon);
+ return ret;
}
diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h
index cfd56dd..51bb68b 100644
--- a/src/util/virresctrl.h
+++ b/src/util/virresctrl.h
@@ -61,6 +61,19 @@ struct _virResctrlInfoMemBWPerNode {
unsigned int max_allocation;
};
+typedef struct _virResctrlInfoMon virResctrlInfoMon;
+typedef virResctrlInfoMon *virResctrlInfoMonPtr;
+/* Information about resource monitoring group */
+struct _virResctrlInfoMon {
+ /* null-terminal string list for hw supported monitor feature */
+ char **features;
+ size_t nfeatures;
+ /* Maximum number of simultaneous allocations */
+ unsigned int max_allocation;
+ /* determines the occupancy at which an RMID can be freed */
+ unsigned int cache_threshold;
+};
+
typedef struct _virResctrlInfo virResctrlInfo;
typedef virResctrlInfo *virResctrlInfoPtr;
@@ -72,7 +85,9 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl,
unsigned int level,
unsigned long long size,
size_t *ncontrols,
- virResctrlInfoPerCachePtr **controls);
+ virResctrlInfoPerCachePtr **controls,
+ virResctrlInfoMonPtr *monitor);
+
int
virResctrlInfoGetMemoryBandwidth(virResctrlInfoPtr resctrl,
--
2.7.4