[libvirt] [PATCH 02/10] util: add interface retrieving CMT capability

Wang Huaqiang huaqiang.wang at intel.com
Mon Aug 27 11:23:05 UTC 2018


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 at 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




More information about the libvir-list mailing list