0a7476
From c402803b725543f690abd96175df12dbee224c58 Mon Sep 17 00:00:00 2001
0a7476
Message-Id: <c402803b725543f690abd96175df12dbee224c58@dist-git>
0a7476
From: Bing Niu <bing.niu@intel.com>
0a7476
Date: Mon, 15 Apr 2019 17:32:47 +0200
0a7476
Subject: [PATCH] util: Add MBA capability information query to resctrl
0a7476
MIME-Version: 1.0
0a7476
Content-Type: text/plain; charset=UTF-8
0a7476
Content-Transfer-Encoding: 8bit
0a7476
0a7476
Introducing virResctrlInfoMemBW for the information memory bandwidth
0a7476
allocation information.
0a7476
0a7476
Signed-off-by: Bing Niu <bing.niu@intel.com>
0a7476
Reviewed-by: John Ferlan <jferlan@redhat.com>
0a7476
(cherry picked from commit a24da791b8d489600807158c45451012ae1a8270)
0a7476
0a7476
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1468650
0a7476
0a7476
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
0a7476
Message-Id: <5bf94bb7ee189420dfd99b19ff423c9650b1e637.1555342313.git.phrdina@redhat.com>
0a7476
Reviewed-by: Ján Tomko <jtomko@redhat.com>
0a7476
---
0a7476
 src/util/virresctrl.c | 84 +++++++++++++++++++++++++++++++++++++++++++
0a7476
 1 file changed, 84 insertions(+)
0a7476
0a7476
diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
0a7476
index a38c9261b6..b12a05cb0f 100644
0a7476
--- a/src/util/virresctrl.c
0a7476
+++ b/src/util/virresctrl.c
0a7476
@@ -80,6 +80,9 @@ typedef virResctrlInfoPerType *virResctrlInfoPerTypePtr;
0a7476
 typedef struct _virResctrlInfoPerLevel virResctrlInfoPerLevel;
0a7476
 typedef virResctrlInfoPerLevel *virResctrlInfoPerLevelPtr;
0a7476
 
0a7476
+typedef struct _virResctrlInfoMemBW virResctrlInfoMemBW;
0a7476
+typedef virResctrlInfoMemBW *virResctrlInfoMemBWPtr;
0a7476
+
0a7476
 typedef struct _virResctrlAllocPerType virResctrlAllocPerType;
0a7476
 typedef virResctrlAllocPerType *virResctrlAllocPerTypePtr;
0a7476
 
0a7476
@@ -116,11 +119,30 @@ struct _virResctrlInfoPerLevel {
0a7476
     virResctrlInfoPerTypePtr *types;
0a7476
 };
0a7476
 
0a7476
+/* Information about memory bandwidth allocation */
0a7476
+struct _virResctrlInfoMemBW {
0a7476
+    /* minimum memory bandwidth allowed */
0a7476
+    unsigned int min_bandwidth;
0a7476
+    /* bandwidth granularity */
0a7476
+    unsigned int bandwidth_granularity;
0a7476
+    /* Maximum number of simultaneous allocations */
0a7476
+    unsigned int max_allocation;
0a7476
+    /* level number of last level cache */
0a7476
+    unsigned int last_level_cache;
0a7476
+    /* max id of last level cache, this is used to track
0a7476
+     * how many last level cache available in host system,
0a7476
+     * the number of memory bandwidth allocation controller
0a7476
+     * is identical with last level cache. */
0a7476
+    unsigned int max_id;
0a7476
+};
0a7476
+
0a7476
 struct _virResctrlInfo {
0a7476
     virObject parent;
0a7476
 
0a7476
     virResctrlInfoPerLevelPtr *levels;
0a7476
     size_t nlevels;
0a7476
+
0a7476
+    virResctrlInfoMemBWPtr membw_info;
0a7476
 };
0a7476
 
0a7476
 
0a7476
@@ -146,6 +168,7 @@ virResctrlInfoDispose(void *obj)
0a7476
         VIR_FREE(level);
0a7476
     }
0a7476
 
0a7476
+    VIR_FREE(resctrl->membw_info);
0a7476
     VIR_FREE(resctrl->levels);
0a7476
 }
0a7476
 
0a7476
@@ -442,6 +465,60 @@ virResctrlGetCacheInfo(virResctrlInfoPtr resctrl,
0a7476
 }
0a7476
 
0a7476
 
0a7476
+static int
0a7476
+virResctrlGetMemoryBandwidthInfo(virResctrlInfoPtr resctrl)
0a7476
+{
0a7476
+    int ret = -1;
0a7476
+    int rv = -1;
0a7476
+    virResctrlInfoMemBWPtr i_membw = NULL;
0a7476
+
0a7476
+    /* query memory bandwidth allocation info */
0a7476
+    if (VIR_ALLOC(i_membw) < 0)
0a7476
+        goto cleanup;
0a7476
+    rv = virFileReadValueUint(&i_membw->bandwidth_granularity,
0a7476
+                              SYSFS_RESCTRL_PATH "/info/MB/bandwidth_gran");
0a7476
+    if (rv == -2) {
0a7476
+        /* The file doesn't exist, so it's unusable for us,
0a7476
+         * probably memory bandwidth allocation unsupported */
0a7476
+        VIR_INFO("The path '" SYSFS_RESCTRL_PATH "/info/MB/bandwidth_gran'"
0a7476
+                 "does not exist");
0a7476
+        ret = 0;
0a7476
+        goto cleanup;
0a7476
+    } else if (rv < 0) {
0a7476
+        /* Other failures are fatal, so just quit */
0a7476
+        goto cleanup;
0a7476
+    }
0a7476
+
0a7476
+    rv = virFileReadValueUint(&i_membw->min_bandwidth,
0a7476
+                              SYSFS_RESCTRL_PATH "/info/MB/min_bandwidth");
0a7476
+    if (rv == -2) {
0a7476
+        /* If the previous file exists, so should this one. Hence -2 is
0a7476
+         * fatal in this case (errors out in next condition) - the kernel
0a7476
+         * interface might've changed too much or something else is wrong. */
0a7476
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
0a7476
+                       _("Cannot get min bandwidth from resctrl memory info"));
0a7476
+    }
0a7476
+    if (rv < 0)
0a7476
+        goto cleanup;
0a7476
+
0a7476
+    rv = virFileReadValueUint(&i_membw->max_allocation,
0a7476
+                              SYSFS_RESCTRL_PATH "/info/MB/num_closids");
0a7476
+    if (rv == -2) {
0a7476
+         /* Similar reasoning to min_bandwidth above. */
0a7476
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
0a7476
+                       _("Cannot get max allocation from resctrl memory info"));
0a7476
+    }
0a7476
+    if (rv < 0)
0a7476
+        goto cleanup;
0a7476
+
0a7476
+    VIR_STEAL_PTR(resctrl->membw_info, i_membw);
0a7476
+    ret = 0;
0a7476
+ cleanup:
0a7476
+    VIR_FREE(i_membw);
0a7476
+    return ret;
0a7476
+}
0a7476
+
0a7476
+
0a7476
 static int
0a7476
 virResctrlGetInfo(virResctrlInfoPtr resctrl)
0a7476
 {
0a7476
@@ -452,6 +529,10 @@ virResctrlGetInfo(virResctrlInfoPtr resctrl)
0a7476
     if (ret <= 0)
0a7476
         goto cleanup;
0a7476
 
0a7476
+    ret = virResctrlGetMemoryBandwidthInfo(resctrl);
0a7476
+    if (ret < 0)
0a7476
+        goto cleanup;
0a7476
+
0a7476
     ret = virResctrlGetCacheInfo(resctrl, dirp);
0a7476
     if (ret < 0)
0a7476
         goto cleanup;
0a7476
@@ -493,6 +574,9 @@ virResctrlInfoIsEmpty(virResctrlInfoPtr resctrl)
0a7476
     if (!resctrl)
0a7476
         return true;
0a7476
 
0a7476
+    if (resctrl->membw_info)
0a7476
+        return false;
0a7476
+
0a7476
     for (i = 0; i < resctrl->nlevels; i++) {
0a7476
         virResctrlInfoPerLevelPtr i_level = resctrl->levels[i];
0a7476
 
0a7476
-- 
0a7476
2.21.0
0a7476