0a7476
From 6013f8d130b617ab0ff14075e225b4bb8836702e Mon Sep 17 00:00:00 2001
0a7476
Message-Id: <6013f8d130b617ab0ff14075e225b4bb8836702e@dist-git>
0a7476
From: Bing Niu <bing.niu@intel.com>
0a7476
Date: Mon, 15 Apr 2019 17:32:49 +0200
0a7476
Subject: [PATCH] util: Add MBA allocation to virresctrl
0a7476
MIME-Version: 1.0
0a7476
Content-Type: text/plain; charset=UTF-8
0a7476
Content-Transfer-Encoding: 8bit
0a7476
0a7476
Add memory bandwidth allocation support to virresctrl class.
0a7476
Introducing virResctrlAllocMemBW which is used for allocating memory
0a7476
bandwidth. Following virResctrlAllocPerType, it also employs a
0a7476
nested sparse array to indicate whether allocation is available for
0a7476
particular last level cache.
0a7476
0a7476
Signed-off-by: Bing Niu <bing.niu@intel.com>
0a7476
Reviewed-by: John Ferlan <jferlan@redhat.com>
0a7476
(cherry picked from commit 4c727dacbf1bd2a8c4797daf6192b81b85f872f1)
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: <6c5c1d7dfd4415699a0bf7a5461c99e915dfea1b.1555342313.git.phrdina@redhat.com>
0a7476
Reviewed-by: Ján Tomko <jtomko@redhat.com>
0a7476
---
0a7476
 src/util/virresctrl.c | 63 ++++++++++++++++++++++++++++++++++++++++---
0a7476
 1 file changed, 59 insertions(+), 4 deletions(-)
0a7476
0a7476
diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
0a7476
index f454868f1e..8a25798f7d 100644
0a7476
--- a/src/util/virresctrl.c
0a7476
+++ b/src/util/virresctrl.c
0a7476
@@ -36,9 +36,9 @@ VIR_LOG_INIT("util.virresctrl")
0a7476
 
0a7476
 
0a7476
 /* Resctrl is short for Resource Control.  It might be implemented for various
0a7476
- * resources, but at the time of this writing this is only supported for cache
0a7476
- * allocation technology (aka CAT).  Hence the reson for leaving 'Cache' out of
0a7476
- * all the structure and function names for now (can be added later if needed.
0a7476
+ * resources. Currently this supports cache allocation technology (aka CAT) and
0a7476
+ * memory bandwidth allocation (aka MBA). More resources technologies may be
0a7476
+ * added in the future.
0a7476
  */
0a7476
 
0a7476
 
0a7476
@@ -89,6 +89,9 @@ typedef virResctrlAllocPerType *virResctrlAllocPerTypePtr;
0a7476
 typedef struct _virResctrlAllocPerLevel virResctrlAllocPerLevel;
0a7476
 typedef virResctrlAllocPerLevel *virResctrlAllocPerLevelPtr;
0a7476
 
0a7476
+typedef struct _virResctrlAllocMemBW virResctrlAllocMemBW;
0a7476
+typedef virResctrlAllocMemBW *virResctrlAllocMemBWPtr;
0a7476
+
0a7476
 
0a7476
 /* Class definitions and initializations */
0a7476
 static virClassPtr virResctrlInfoClass;
0a7476
@@ -180,7 +183,10 @@ virResctrlInfoDispose(void *obj)
0a7476
  * consequently a directory under /sys/fs/resctrl).  Since it can have multiple
0a7476
  * parts of multiple caches allocated it is represented as bunch of nested
0a7476
  * sparse arrays (by sparse I mean array of pointers so that each might be NULL
0a7476
- * in case there is no allocation for that particular one (level, cache, ...)).
0a7476
+ * in case there is no allocation for that particular cache allocation (level,
0a7476
+ * cache, ...) or memory allocation for particular node).
0a7476
+ *
0a7476
+ * =====Cache allocation technology (CAT)=====
0a7476
  *
0a7476
  * Since one allocation can be made for caches on different levels, the first
0a7476
  * nested sparse array is of types virResctrlAllocPerLevel.  For example if you
0a7476
@@ -205,6 +211,17 @@ virResctrlInfoDispose(void *obj)
0a7476
  * all of them.  While doing that we store the bitmask in a sparse array of
0a7476
  * virBitmaps named `masks` indexed the same way as `sizes`.  The upper bounds
0a7476
  * of the sparse arrays are stored in nmasks or nsizes, respectively.
0a7476
+ + *
0a7476
+ * =====Memory Bandwidth allocation technology (MBA)=====
0a7476
+ *
0a7476
+ * The memory bandwidth allocation support in virResctrlAlloc works in the
0a7476
+ * same fashion as CAT. However, memory bandwidth controller doesn't have a
0a7476
+ * hierarchy organization as cache, each node have one memory bandwidth
0a7476
+ * controller to memory bandwidth distribution. The number of memory bandwidth
0a7476
+ * controller is identical with number of last level cache. So MBA also employs
0a7476
+ * a sparse array to represent whether a memory bandwidth allocation happens
0a7476
+ * on corresponding node. The available memory controller number is collected
0a7476
+ * in 'virResctrlInfo'.
0a7476
  */
0a7476
 struct _virResctrlAllocPerType {
0a7476
     /* There could be bool saying whether this is set or not, but since everything
0a7476
@@ -225,12 +242,24 @@ struct _virResctrlAllocPerLevel {
0a7476
      * VIR_CACHE_TYPE_LAST number of items */
0a7476
 };
0a7476
 
0a7476
+/*
0a7476
+ * virResctrlAllocMemBW represents one memory bandwidth allocation.
0a7476
+ * Since it can have several last level caches in a NUMA system, it is
0a7476
+ * also represented as a nested sparse arrays as virRestrlAllocPerLevel.
0a7476
+ */
0a7476
+struct _virResctrlAllocMemBW {
0a7476
+    unsigned int **bandwidths;
0a7476
+    size_t nbandwidths;
0a7476
+};
0a7476
+
0a7476
 struct _virResctrlAlloc {
0a7476
     virObject parent;
0a7476
 
0a7476
     virResctrlAllocPerLevelPtr *levels;
0a7476
     size_t nlevels;
0a7476
 
0a7476
+    virResctrlAllocMemBWPtr mem_bw;
0a7476
+
0a7476
     /* The identifier (any unique string for now) */
0a7476
     char *id;
0a7476
     /* libvirt-generated path in /sys/fs/resctrl for this particular
0a7476
@@ -274,6 +303,13 @@ virResctrlAllocDispose(void *obj)
0a7476
         VIR_FREE(level);
0a7476
     }
0a7476
 
0a7476
+    if (alloc->mem_bw) {
0a7476
+        virResctrlAllocMemBWPtr mem_bw = alloc->mem_bw;
0a7476
+        for (i = 0; i < mem_bw->nbandwidths; i++)
0a7476
+            VIR_FREE(mem_bw->bandwidths[i]);
0a7476
+        VIR_FREE(alloc->mem_bw);
0a7476
+    }
0a7476
+
0a7476
     VIR_FREE(alloc->id);
0a7476
     VIR_FREE(alloc->path);
0a7476
     VIR_FREE(alloc->levels);
0a7476
@@ -692,6 +728,9 @@ virResctrlAllocIsEmpty(virResctrlAllocPtr alloc)
0a7476
     if (!alloc)
0a7476
         return true;
0a7476
 
0a7476
+    if (alloc->mem_bw)
0a7476
+        return false;
0a7476
+
0a7476
     for (i = 0; i < alloc->nlevels; i++) {
0a7476
         virResctrlAllocPerLevelPtr a_level = alloc->levels[i];
0a7476
 
0a7476
@@ -1266,6 +1305,22 @@ virResctrlAllocNewFromInfo(virResctrlInfoPtr info)
0a7476
         }
0a7476
     }
0a7476
 
0a7476
+    /* set default free memory bandwidth to 100%*/
0a7476
+    if (info->membw_info) {
0a7476
+        if (VIR_ALLOC(ret->mem_bw) < 0)
0a7476
+            goto error;
0a7476
+
0a7476
+        if (VIR_EXPAND_N(ret->mem_bw->bandwidths, ret->mem_bw->nbandwidths,
0a7476
+                         info->membw_info->max_id + 1) < 0)
0a7476
+            goto error;
0a7476
+
0a7476
+        for (i = 0; i < ret->mem_bw->nbandwidths; i++) {
0a7476
+            if (VIR_ALLOC(ret->mem_bw->bandwidths[i]) < 0)
0a7476
+                goto error;
0a7476
+            *(ret->mem_bw->bandwidths[i]) = 100;
0a7476
+        }
0a7476
+    }
0a7476
+
0a7476
  cleanup:
0a7476
     virBitmapFree(mask);
0a7476
     return ret;
0a7476
-- 
0a7476
2.21.0
0a7476