Treat vCPU attribute absence as a request to place the whole emulator
process in one resctrl group for both allocation and monitoring. Parsing
such XML failed until now.

A whole-process group has no vcpu list and no id. It formats back as a
bare cachetune, memorytune, energytune or monitor element.

Track the scope with a whole_process flag and enforce the rules beside
the existing monitor checks. A domain's allocations are either all
whole-process or all per-vCPU. A whole-process monitor needs a
whole-process allocation, does not mix with explicit monitors and is
unique per resource type. A whole-process allocation may still carry
explicit per-vCPU monitors, as it already spans every thread.
Monitors that omit vcpus inside an explicit allocation inherit the
allocation's vcpu scope instead of covering the whole process.
This behavior represents the resctrl dependency between allocation
and monitoring.

Out of range and empty vcpus attributes still remain silently dropped.

Signed-off-by: Jedrzej Wasiukiewicz <[email protected]>
---
 src/conf/domain_conf.c                        | 231 ++++++++++++------
 src/conf/domain_conf.h                        |   2 +
 .../cachetune-monitor-empty-vcpus.xml         |  30 +++
 .../cachetune-monitor-inherit-alloc.xml       |  30 +++
 .../cachetune-wholeprocess-duplicate.xml      |  32 +++
 ...chetune-wholeprocess-monitor-duplicate.xml |  31 +++
 .../cachetune-wholeprocess-monitors.xml       |  31 +++
 .../energytune-colliding-monitor.xml          |  30 +++
 .../energytune-wholeprocess.xml               |  29 +++
 .../memorytune-wholeprocess.xml               |  29 +++
 .../resctrl-wholeprocess-alloc-monitor.xml    |  32 +++
 .../resctrl-wholeprocess-layering.xml         |  32 +++
 .../resctrl-wholeprocess-monitors.xml         |  33 +++
 .../cachetune-monitor-inherit-alloc.xml       |  30 +++
 tests/genericxml2xmltest.c                    |  11 +
 15 files changed, 545 insertions(+), 68 deletions(-)
 create mode 100644 tests/genericxml2xmlindata/cachetune-monitor-empty-vcpus.xml
 create mode 100644 
tests/genericxml2xmlindata/cachetune-monitor-inherit-alloc.xml
 create mode 100644 
tests/genericxml2xmlindata/cachetune-wholeprocess-duplicate.xml
 create mode 100644 
tests/genericxml2xmlindata/cachetune-wholeprocess-monitor-duplicate.xml
 create mode 100644 
tests/genericxml2xmlindata/cachetune-wholeprocess-monitors.xml
 create mode 100644 tests/genericxml2xmlindata/energytune-colliding-monitor.xml
 create mode 100644 tests/genericxml2xmlindata/energytune-wholeprocess.xml
 create mode 100644 tests/genericxml2xmlindata/memorytune-wholeprocess.xml
 create mode 100644 
tests/genericxml2xmlindata/resctrl-wholeprocess-alloc-monitor.xml
 create mode 100644 tests/genericxml2xmlindata/resctrl-wholeprocess-layering.xml
 create mode 100644 tests/genericxml2xmlindata/resctrl-wholeprocess-monitors.xml
 create mode 100644 
tests/genericxml2xmloutdata/cachetune-monitor-inherit-alloc.xml

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 45235d74bc..5e8f7ea429 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -18771,15 +18771,17 @@ virDomainDefParseBootOptions(virDomainDef *def,
 static int
 virDomainResctrlParseVcpus(virDomainDef *def,
                            xmlNodePtr node,
-                           virBitmap **vcpus)
+                           virBitmap **vcpus,
+                           bool *whole_process)
 {
     g_autofree char *vcpus_str = NULL;
+    *vcpus = NULL;
 
     vcpus_str = virXMLPropString(node, "vcpus");
-    if (!vcpus_str) {
-        virReportError(VIR_ERR_XML_ERROR, _("Missing %1$s attribute 'vcpus'"),
-                       node->name);
-        return -1;
+    *whole_process = !vcpus_str;
+    if (*whole_process) {
+        *vcpus = virBitmapNew(0);
+        return 0;
     }
     if (virBitmapParse(vcpus_str, vcpus, VIR_DOMAIN_CPUMASK_LEN) < 0) {
         virReportError(VIR_ERR_XML_ERROR,
@@ -18859,6 +18861,9 @@ virDomainCachetuneDefParseCache(xmlXPathContextPtr ctxt,
 /* Checking if the monitor's vcpus and tag is conflicted with existing
  * allocation and monitors.
  *
+ * A whole-process monitor must not be mixed with explicit monitors and may
+ * cover each resource type only once.
+ *
  * Returns 1 if @monitor->vcpus equals to @resctrl->vcpus, then the monitor
  * will share the underlying resctrl group with @resctrl->alloc. Returns -1
  * if any conflict found. Returns 0 if no conflict and @monitor->vcpus is
@@ -18875,17 +18880,40 @@ virDomainResctrlValidateMonitor(virDomainResctrlDef 
*resctrl,
     bool vcpus_overlap_no_resctrl = false;
     bool default_alloc_monitor = virResctrlAllocIsEmpty(resctrl->alloc);
 
+    if (resctrl->nmonitors > 0 &&
+        resctrl->monitors[0]->whole_process != monitor->whole_process) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Whole-process and explicit monitors cannot be 
mixed"));
+        return -1;
+    }
+
+    if (monitor->whole_process) {
+        for (i = 0; i < resctrl->nmonitors; i++) {
+            if (resctrl->monitors[i]->tag == monitor->tag) {
+                virReportError(VIR_ERR_XML_ERROR, "%s",
+                               _("Duplicate whole-process monitor of the same 
resource type"));
+                return -1;
+            }
+        }
+
+        return 0;
+    }
+
     if (virBitmapIsAllClear(monitor->vcpus)) {
         virReportError(VIR_ERR_INVALID_ARG, "%s",
                        _("vcpus is empty"));
         return -1;
     }
 
-    while ((vcpu = virBitmapNextSetBit(monitor->vcpus, vcpu)) >= 0) {
-        if (!virBitmapIsBitSet(resctrl->vcpus, vcpu)) {
-            virReportError(VIR_ERR_INVALID_ARG, "%s",
-                           _("Monitor vcpus conflicts with allocation"));
-            return -1;
+    /* A whole-process allocation covers every thread, so it does not constrain
+     * an explicit monitor's vcpus. */
+    if (!resctrl->whole_process) {
+        while ((vcpu = virBitmapNextSetBit(monitor->vcpus, vcpu)) >= 0) {
+            if (!virBitmapIsBitSet(resctrl->vcpus, vcpu)) {
+                virReportError(VIR_ERR_INVALID_ARG, "%s",
+                               _("Monitor vcpus conflicts with allocation"));
+                return -1;
+            }
         }
     }
 
@@ -18952,6 +18980,7 @@ virDomainResctrlMonDefParse(virDomainDef *def,
 
     for (i = 0; i < n; i++) {
         g_autofree char *id = NULL;
+        bool whole_process = false;
 
         domresmon = g_new0(virDomainResctrlMonDef, 1);
 
@@ -18977,27 +19006,41 @@ virDomainResctrlMonDefParse(virDomainDef *def,
             }
         }
 
-        if (virDomainResctrlParseVcpus(def, nodes[i], &domresmon->vcpus) < 0)
+        if (virDomainResctrlParseVcpus(def, nodes[i], &domresmon->vcpus,
+                                       &whole_process) < 0)
             goto cleanup;
 
+        /* A monitor that omits vcpus inside an explicit allocation inherits
+         * the allocation's vcpu scope instead of covering the whole process. 
*/
+        if (whole_process && !resctrl->whole_process) {
+            virBitmapFree(domresmon->vcpus);
+            domresmon->vcpus = virBitmapNewCopy(resctrl->vcpus);
+            whole_process = false;
+        }
+
+        domresmon->whole_process = whole_process;
+
         rv = virDomainResctrlValidateMonitor(resctrl, domresmon);
         if (rv < 0)
             goto cleanup;
 
-        /* If monitor's vcpu list is identical to the vcpu list of the
-         * associated allocation, set monitor's id to the same value
-         * as the allocation. */
-        if (rv == 1) {
-            id = g_strdup(virResctrlAllocGetID(resctrl->alloc));
-        } else {
-            g_autofree char *tmp = virBitmapFormat(domresmon->vcpus);
+        /* A whole-process monitor keeps its id unset, which selects the bare
+         * machine name. Otherwise, if the monitor's vcpu list is identical to
+         * the vcpu list of the associated allocation, share the allocation's
+         * id. */
+        if (!whole_process) {
+            if (rv == 1) {
+                id = g_strdup(virResctrlAllocGetID(resctrl->alloc));
+            } else {
+                g_autofree char *tmp = virBitmapFormat(domresmon->vcpus);
 
-            id = g_strdup_printf("vcpus_%s", tmp);
+                id = g_strdup_printf("vcpus_%s", tmp);
+            }
         }
 
         virResctrlMonitorSetAlloc(domresmon->instance, resctrl->alloc);
 
-        if (virResctrlMonitorSetID(domresmon->instance, id) < 0)
+        if (id && virResctrlMonitorSetID(domresmon->instance, id) < 0)
             goto cleanup;
 
         VIR_APPEND_ELEMENT(resctrl->monitors, resctrl->nmonitors, domresmon);
@@ -19014,39 +19057,64 @@ static virDomainResctrlDef *
 virDomainResctrlNew(xmlNodePtr node,
                     virResctrlAlloc *alloc,
                     virBitmap *vcpus,
+                    bool whole_process,
                     unsigned int flags)
 {
     virDomainResctrlDef *resctrl = NULL;
     g_autofree char *vcpus_str = NULL;
     g_autofree char *alloc_id = NULL;
 
-    /* We need to format it back because we need to be consistent in the naming
-     * even when users specify some "sub-optimal" string there. */
-    vcpus_str = virBitmapFormat(vcpus);
+    /* A whole-process group omits the "vcpus" suffix. */
+    if (!whole_process) {
+        /* We need to format it back because we need to be consistent in the 
naming
+         * even when users specify some "sub-optimal" string there. */
+        vcpus_str = virBitmapFormat(vcpus);
 
-    if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
-        alloc_id = virXMLPropString(node, "id");
+        if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
+            alloc_id = virXMLPropString(node, "id");
 
-    if (!alloc_id) {
-        /* The number of allocations is limited and the directory structure is 
flat,
-         * not hierarchical, so we need to have all same allocations in one
-         * directory, so it's nice to have it named appropriately.  For now 
it's
-         * 'vcpus_...' but it's designed in order for it to be changeable in 
the
-         * future (it's part of the status XML). */
-        alloc_id = g_strdup_printf("vcpus_%s", vcpus_str);
-    }
+        if (!alloc_id) {
+            /* The number of allocations is limited and the directory 
structure is flat,
+             * not hierarchical, so we need to have all same allocations in one
+             * directory, so it's nice to have it named appropriately.  For 
now it's
+             * 'vcpus_...' but it's designed in order for it to be changeable 
in the
+             * future (it's part of the status XML). */
+            alloc_id = g_strdup_printf("vcpus_%s", vcpus_str);
+        }
 
-    if (virResctrlAllocSetID(alloc, alloc_id) < 0)
-        return NULL;
+        if (virResctrlAllocSetID(alloc, alloc_id) < 0)
+            return NULL;
+    }
 
     resctrl = g_new0(virDomainResctrlDef, 1);
     resctrl->vcpus = virBitmapNewCopy(vcpus);
+    resctrl->whole_process = whole_process;
     resctrl->alloc = virObjectRef(alloc);
 
     return resctrl;
 }
 
 
+/* Whole-process and per-vcpu allocations cannot be mixed: assigning explicit
+ * vCPUs to their own group would pull them out of the whole-process group. */
+static int
+virDomainResctrlValidateScope(virDomainDef *def,
+                              bool whole_process)
+{
+    size_t i;
+
+    for (i = 0; i < def->nresctrls; i++) {
+        if (def->resctrls[i]->whole_process != whole_process) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("Whole-process and per-vcpu resctrl allocations 
cannot be mixed"));
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
 static int
 virDomainCachetuneDefParse(virDomainDef *def,
                            xmlXPathContextPtr ctxt,
@@ -19058,16 +19126,17 @@ virDomainCachetuneDefParse(virDomainDef *def,
     ssize_t i = 0;
     int n;
     int ret = -1;
+    bool whole_process = false;
     g_autoptr(virBitmap) vcpus = NULL;
     g_autofree xmlNodePtr *nodes = NULL;
     g_autoptr(virResctrlAlloc) alloc = NULL;
 
     ctxt->node = node;
 
-    if (virDomainResctrlParseVcpus(def, node, &vcpus) < 0)
+    if (virDomainResctrlParseVcpus(def, node, &vcpus, &whole_process) < 0)
         return -1;
 
-    if (virBitmapIsAllClear(vcpus))
+    if (!whole_process && virBitmapIsAllClear(vcpus))
         return 0;
 
     if ((n = virXPathNodeSet("./cache", ctxt, &nodes)) < 0)
@@ -19082,6 +19151,9 @@ virDomainCachetuneDefParse(virDomainDef *def,
         return -1;
     }
 
+    if (virDomainResctrlValidateScope(def, whole_process) < 0)
+        return -1;
+
     if (!(alloc = virResctrlAllocNew()))
         return -1;
 
@@ -19090,7 +19162,7 @@ virDomainCachetuneDefParse(virDomainDef *def,
             return -1;
     }
 
-    if (!(resctrl = virDomainResctrlNew(node, alloc, vcpus, flags)))
+    if (!(resctrl = virDomainResctrlNew(node, alloc, vcpus, whole_process, 
flags)))
         return -1;
 
     if (virDomainResctrlMonDefParse(def, ctxt, node,
@@ -19426,15 +19498,16 @@ virDomainMemorytuneDefParse(virDomainDef *def,
     ssize_t i = 0;
     size_t nmons = 0;
     size_t ret = -1;
+    bool whole_process = false;
 
     int n;
 
     ctxt->node = node;
 
-    if (virDomainResctrlParseVcpus(def, node, &vcpus) < 0)
+    if (virDomainResctrlParseVcpus(def, node, &vcpus, &whole_process) < 0)
         return -1;
 
-    if (virBitmapIsAllClear(vcpus))
+    if (!whole_process && virBitmapIsAllClear(vcpus))
         return 0;
 
     if ((n = virXPathNodeSet("./node", ctxt, &nodes)) < 0)
@@ -19446,6 +19519,8 @@ virDomainMemorytuneDefParse(virDomainDef *def,
     if (resctrl) {
         alloc = virObjectRef(resctrl->alloc);
     } else {
+        if (virDomainResctrlValidateScope(def, whole_process) < 0)
+            return -1;
         if (!(alloc = virResctrlAllocNew()))
             return -1;
     }
@@ -19461,7 +19536,8 @@ virDomainMemorytuneDefParse(virDomainDef *def,
      * just update the existing alloc information, which is done in above
      * virDomainMemorytuneDefParseMemory */
     if (!resctrl) {
-        if (!(newresctrl = virDomainResctrlNew(node, alloc, vcpus, flags)))
+        if (!(newresctrl = virDomainResctrlNew(node, alloc, vcpus,
+                                               whole_process, flags)))
             return -1;
 
         resctrl = newresctrl;
@@ -19501,15 +19577,16 @@ virDomainEnergytuneDefParse(virDomainDef *def,
     virDomainResctrlDef *newresctrl = NULL;
     g_autoptr(virBitmap) vcpus = NULL;
     g_autoptr(virResctrlAlloc) alloc = NULL;
+    bool whole_process = false;
     size_t nmons;
     int ret = -1;
 
     ctxt->node = node;
 
-    if (virDomainResctrlParseVcpus(def, node, &vcpus) < 0)
+    if (virDomainResctrlParseVcpus(def, node, &vcpus, &whole_process) < 0)
         return -1;
 
-    if (virBitmapIsAllClear(vcpus))
+    if (!whole_process && virBitmapIsAllClear(vcpus))
         return 0;
 
     if (virDomainResctrlVcpuMatch(def, vcpus, &resctrl) < 0)
@@ -19518,9 +19595,12 @@ virDomainEnergytuneDefParse(virDomainDef *def,
     if (resctrl) {
         alloc = virObjectRef(resctrl->alloc);
     } else {
+        if (virDomainResctrlValidateScope(def, whole_process) < 0)
+            return -1;
         if (!(alloc = virResctrlAllocNew()))
             return -1;
-        if (!(newresctrl = virDomainResctrlNew(node, alloc, vcpus, flags)))
+        if (!(newresctrl = virDomainResctrlNew(node, alloc, vcpus,
+                                               whole_process, flags)))
             return -1;
         resctrl = newresctrl;
     }
@@ -28701,16 +28781,22 @@ 
virDomainResctrlMonDefFormatHelper(virDomainResctrlMonDef *domresmon,
     if (domresmon->tag != tag)
         return 0;
 
-    virBufferAddLit(buf, "<monitor ");
+    virBufferAddLit(buf, "<monitor");
 
     if (tag == VIR_RESCTRL_MONITOR_TYPE_CACHE) {
-        virBufferAsprintf(buf, "level='%u' ",
+        virBufferAsprintf(buf, " level='%u'",
                           VIR_DOMAIN_RESCTRL_MONITOR_CACHELEVEL);
     }
 
+    /* A whole-process monitor has no vcpus attribute. */
+    if (domresmon->whole_process) {
+        virBufferAddLit(buf, "/>\n");
+        return 0;
+    }
+
     vcpus = virBitmapFormat(domresmon->vcpus);
 
-    virBufferAsprintf(buf, "vcpus='%s'/>\n", vcpus);
+    virBufferAsprintf(buf, " vcpus='%s'/>\n", vcpus);
 
     return 0;
 }
@@ -28741,16 +28827,19 @@ virDomainCachetuneDefFormat(virBuffer *buf,
     if (!virBufferUse(&childrenBuf))
         return 0;
 
-    vcpus = virBitmapFormat(resctrl->vcpus);
+    /* A whole-process group has no vcpus and no id to format. */
+    if (!resctrl->whole_process) {
+        vcpus = virBitmapFormat(resctrl->vcpus);
 
-    virBufferAsprintf(&attrBuf, " vcpus='%s'", vcpus);
+        virBufferAsprintf(&attrBuf, " vcpus='%s'", vcpus);
 
-    if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
-        const char *alloc_id = virResctrlAllocGetID(resctrl->alloc);
-        if (!alloc_id)
-            return -1;
+        if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
+            const char *alloc_id = virResctrlAllocGetID(resctrl->alloc);
+            if (!alloc_id)
+                return -1;
 
-        virBufferAsprintf(&attrBuf, " id='%s'", alloc_id);
+            virBufferAsprintf(&attrBuf, " id='%s'", alloc_id);
+        }
     }
 
     virXMLFormatElement(buf, "cachetune", &attrBuf, &childrenBuf);
@@ -28798,16 +28887,19 @@ virDomainMemorytuneDefFormat(virBuffer *buf,
     if (!virBufferUse(&childrenBuf))
         return 0;
 
-    vcpus = virBitmapFormat(resctrl->vcpus);
+    /* A whole-process group has no vcpus and no id to format. */
+    if (!resctrl->whole_process) {
+        vcpus = virBitmapFormat(resctrl->vcpus);
 
-    virBufferAsprintf(&attrBuf, " vcpus='%s'", vcpus);
+        virBufferAsprintf(&attrBuf, " vcpus='%s'", vcpus);
 
-    if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
-        const char *alloc_id = virResctrlAllocGetID(resctrl->alloc);
-        if (!alloc_id)
-            return -1;
+        if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
+            const char *alloc_id = virResctrlAllocGetID(resctrl->alloc);
+            if (!alloc_id)
+                return -1;
 
-        virBufferAsprintf(&attrBuf, " id='%s'", alloc_id);
+            virBufferAsprintf(&attrBuf, " id='%s'", alloc_id);
+        }
     }
 
     virXMLFormatElement(buf, "memorytune", &attrBuf, &childrenBuf);
@@ -28836,15 +28928,18 @@ virDomainEnergytuneDefFormat(virBuffer *buf,
     if (!virBufferUse(&childrenBuf))
         return 0;
 
-    vcpus = virBitmapFormat(resctrl->vcpus);
-    virBufferAsprintf(&attrBuf, " vcpus='%s'", vcpus);
+    /* A whole-process group has no vcpus and no id to format. */
+    if (!resctrl->whole_process) {
+        vcpus = virBitmapFormat(resctrl->vcpus);
+        virBufferAsprintf(&attrBuf, " vcpus='%s'", vcpus);
 
-    if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
-        const char *alloc_id = virResctrlAllocGetID(resctrl->alloc);
-        if (!alloc_id)
-            return -1;
+        if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
+            const char *alloc_id = virResctrlAllocGetID(resctrl->alloc);
+            if (!alloc_id)
+                return -1;
 
-        virBufferAsprintf(&attrBuf, " id='%s'", alloc_id);
+            virBufferAsprintf(&attrBuf, " id='%s'", alloc_id);
+        }
     }
 
     virXMLFormatElement(buf, "energytune", &attrBuf, &childrenBuf);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 91f57de0f1..ed1c2ae8b0 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2935,12 +2935,14 @@ struct _virDomainCputune {
 
 struct _virDomainResctrlMonDef {
     virBitmap *vcpus;
+    bool whole_process;
     virResctrlMonitorType tag;
     virResctrlMonitor *instance;
 };
 
 struct _virDomainResctrlDef {
     virBitmap *vcpus;
+    bool whole_process;
     virResctrlAlloc *alloc;
 
     virDomainResctrlMonDef **monitors;
diff --git a/tests/genericxml2xmlindata/cachetune-monitor-empty-vcpus.xml 
b/tests/genericxml2xmlindata/cachetune-monitor-empty-vcpus.xml
new file mode 100644
index 0000000000..a79ad71635
--- /dev/null
+++ b/tests/genericxml2xmlindata/cachetune-monitor-empty-vcpus.xml
@@ -0,0 +1,30 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>4</vcpu>
+  <cputune>
+    <cachetune vcpus='0-1'>
+      <cache id='0' level='3' type='both' size='3' unit='MiB'/>
+      <monitor level='3' vcpus='8-9'/>
+    </cachetune>
+  </cputune>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-i386</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmlindata/cachetune-monitor-inherit-alloc.xml 
b/tests/genericxml2xmlindata/cachetune-monitor-inherit-alloc.xml
new file mode 100644
index 0000000000..b8b0460d1f
--- /dev/null
+++ b/tests/genericxml2xmlindata/cachetune-monitor-inherit-alloc.xml
@@ -0,0 +1,30 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>4</vcpu>
+  <cputune>
+    <cachetune vcpus='0-1'>
+      <cache id='0' level='3' type='both' size='3' unit='MiB'/>
+      <monitor level='3'/>
+    </cachetune>
+  </cputune>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-i386</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmlindata/cachetune-wholeprocess-duplicate.xml 
b/tests/genericxml2xmlindata/cachetune-wholeprocess-duplicate.xml
new file mode 100644
index 0000000000..c828b659f7
--- /dev/null
+++ b/tests/genericxml2xmlindata/cachetune-wholeprocess-duplicate.xml
@@ -0,0 +1,32 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>4</vcpu>
+  <cputune>
+    <cachetune>
+      <cache id='0' level='3' type='both' size='3' unit='MiB'/>
+    </cachetune>
+    <cachetune>
+      <cache id='1' level='3' type='both' size='3' unit='MiB'/>
+    </cachetune>
+  </cputune>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-i386</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git 
a/tests/genericxml2xmlindata/cachetune-wholeprocess-monitor-duplicate.xml 
b/tests/genericxml2xmlindata/cachetune-wholeprocess-monitor-duplicate.xml
new file mode 100644
index 0000000000..898a51de87
--- /dev/null
+++ b/tests/genericxml2xmlindata/cachetune-wholeprocess-monitor-duplicate.xml
@@ -0,0 +1,31 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>4</vcpu>
+  <cputune>
+    <cachetune>
+      <cache id='0' level='3' type='both' size='3' unit='MiB'/>
+      <monitor level='3'/>
+      <monitor level='3'/>
+    </cachetune>
+  </cputune>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-i386</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmlindata/cachetune-wholeprocess-monitors.xml 
b/tests/genericxml2xmlindata/cachetune-wholeprocess-monitors.xml
new file mode 100644
index 0000000000..550ae2df31
--- /dev/null
+++ b/tests/genericxml2xmlindata/cachetune-wholeprocess-monitors.xml
@@ -0,0 +1,31 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>4</vcpu>
+  <cputune>
+    <cachetune>
+      <cache id='0' level='3' type='both' size='3' unit='MiB'/>
+      <monitor level='3' vcpus='0-1'/>
+      <monitor level='3' vcpus='2-3'/>
+    </cachetune>
+  </cputune>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-i386</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmlindata/energytune-colliding-monitor.xml 
b/tests/genericxml2xmlindata/energytune-colliding-monitor.xml
new file mode 100644
index 0000000000..f07da2620f
--- /dev/null
+++ b/tests/genericxml2xmlindata/energytune-colliding-monitor.xml
@@ -0,0 +1,30 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>4</vcpu>
+  <cputune>
+    <energytune>
+      <monitor/>
+      <monitor vcpus='0-1'/>
+    </energytune>
+  </cputune>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-i386</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmlindata/energytune-wholeprocess.xml 
b/tests/genericxml2xmlindata/energytune-wholeprocess.xml
new file mode 100644
index 0000000000..ebac5e9bc9
--- /dev/null
+++ b/tests/genericxml2xmlindata/energytune-wholeprocess.xml
@@ -0,0 +1,29 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>4</vcpu>
+  <cputune>
+    <energytune>
+      <monitor/>
+    </energytune>
+  </cputune>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-i386</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmlindata/memorytune-wholeprocess.xml 
b/tests/genericxml2xmlindata/memorytune-wholeprocess.xml
new file mode 100644
index 0000000000..496fccc7e6
--- /dev/null
+++ b/tests/genericxml2xmlindata/memorytune-wholeprocess.xml
@@ -0,0 +1,29 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>4</vcpu>
+  <cputune>
+    <memorytune>
+      <node id='0' bandwidth='60'/>
+    </memorytune>
+  </cputune>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-i386</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmlindata/resctrl-wholeprocess-alloc-monitor.xml 
b/tests/genericxml2xmlindata/resctrl-wholeprocess-alloc-monitor.xml
new file mode 100644
index 0000000000..ad0a904dc7
--- /dev/null
+++ b/tests/genericxml2xmlindata/resctrl-wholeprocess-alloc-monitor.xml
@@ -0,0 +1,32 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>4</vcpu>
+  <cputune>
+    <cachetune>
+      <cache id='0' level='3' type='both' size='3' unit='MiB'/>
+    </cachetune>
+    <energytune>
+      <monitor/>
+    </energytune>
+  </cputune>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-i386</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmlindata/resctrl-wholeprocess-layering.xml 
b/tests/genericxml2xmlindata/resctrl-wholeprocess-layering.xml
new file mode 100644
index 0000000000..aebd613d78
--- /dev/null
+++ b/tests/genericxml2xmlindata/resctrl-wholeprocess-layering.xml
@@ -0,0 +1,32 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>4</vcpu>
+  <cputune>
+    <cachetune>
+      <cache id='0' level='3' type='both' size='3' unit='MiB'/>
+    </cachetune>
+    <memorytune vcpus='0-1'>
+      <node id='0' bandwidth='60'/>
+    </memorytune>
+  </cputune>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-i386</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmlindata/resctrl-wholeprocess-monitors.xml 
b/tests/genericxml2xmlindata/resctrl-wholeprocess-monitors.xml
new file mode 100644
index 0000000000..35f20c6c11
--- /dev/null
+++ b/tests/genericxml2xmlindata/resctrl-wholeprocess-monitors.xml
@@ -0,0 +1,33 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>4</vcpu>
+  <cputune>
+    <cachetune>
+      <cache id='0' level='3' type='both' size='3' unit='MiB'/>
+      <monitor level='3'/>
+    </cachetune>
+    <energytune>
+      <monitor/>
+    </energytune>
+  </cputune>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-i386</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmloutdata/cachetune-monitor-inherit-alloc.xml 
b/tests/genericxml2xmloutdata/cachetune-monitor-inherit-alloc.xml
new file mode 100644
index 0000000000..70dcf39285
--- /dev/null
+++ b/tests/genericxml2xmloutdata/cachetune-monitor-inherit-alloc.xml
@@ -0,0 +1,30 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>4</vcpu>
+  <cputune>
+    <cachetune vcpus='0-1'>
+      <cache id='0' level='3' type='both' size='3' unit='MiB'/>
+      <monitor level='3' vcpus='0-1'/>
+    </cachetune>
+  </cputune>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-i386</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c
index 169c71efa3..8492a6266e 100644
--- a/tests/genericxml2xmltest.c
+++ b/tests/genericxml2xmltest.c
@@ -211,6 +211,17 @@ mymain(void)
     DO_TEST("cachetune-cdp");
     DO_TEST("cachetune");
     DO_TEST("energytune");
+    DO_TEST("energytune-wholeprocess");
+    DO_TEST("memorytune-wholeprocess");
+    DO_TEST("cachetune-wholeprocess-monitors");
+    DO_TEST("resctrl-wholeprocess-monitors");
+    DO_TEST("resctrl-wholeprocess-alloc-monitor");
+    DO_TEST_FAIL_INACTIVE("resctrl-wholeprocess-layering");
+    DO_TEST_FAIL_INACTIVE("cachetune-wholeprocess-duplicate");
+    DO_TEST_FAIL_INACTIVE("cachetune-wholeprocess-monitor-duplicate");
+    DO_TEST_DIFFERENT("cachetune-monitor-inherit-alloc");
+    DO_TEST_FAIL_INACTIVE("energytune-colliding-monitor");
+    DO_TEST_FAIL_INACTIVE("cachetune-monitor-empty-vcpus");
     DO_TEST_DIFFERENT("cachetune-extra-tunes");
     DO_TEST_FAIL_INACTIVE("cachetune-colliding-allocs");
     DO_TEST_FAIL_INACTIVE("cachetune-colliding-tunes");
-- 
2.43.0

---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial 
Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | 
Kapital zakladowy 200.000 PLN.
Spolka oswiadcza, ze posiada status duzego przedsiebiorcy w rozumieniu ustawy z 
dnia 8 marca 2013 r. o przeciwdzialaniu nadmiernym opoznieniom w transakcjach 
handlowych.

Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i 
moze zawierac informacje poufne. W razie przypadkowego otrzymania tej 
wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; 
jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole 
use of the intended recipient(s). If you are not the intended recipient, please 
contact the sender and delete all copies; any review or distribution by others 
is strictly prohibited.

Reply via email to