6d3351
From a5cb43154905e2708bf90988bd2aa5f2fca6b935 Mon Sep 17 00:00:00 2001
6d3351
Message-Id: <a5cb43154905e2708bf90988bd2aa5f2fca6b935@dist-git>
6d3351
From: Jiri Denemark <jdenemar@redhat.com>
6d3351
Date: Mon, 24 Apr 2017 15:40:07 +0200
6d3351
Subject: [PATCH] Add support for CPU cache specification
6d3351
6d3351
This patch introduces
6d3351
6d3351
    <cache level='N' mode='emulate'/>
6d3351
    <cache mode='passthrough'/>
6d3351
    <cache mode='disable'/>
6d3351
6d3351
sub element of /domain/cpu. Currently only a single <cache> element is
6d3351
allowed.
6d3351
6d3351
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
6d3351
(cherry picked from commit a646a6016a7c62688988f7cfaa22e1340c2ce761)
6d3351
6d3351
https://bugzilla.redhat.com/show_bug.cgi?id=1428952
6d3351
6d3351
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
6d3351
---
6d3351
 docs/formatdomain.html.in                          | 35 ++++++++++++
6d3351
 docs/schemas/cputypes.rng                          | 21 ++++++++
6d3351
 docs/schemas/domaincommon.rng                      |  3 ++
6d3351
 src/conf/cpu_conf.c                                | 62 ++++++++++++++++++++++
6d3351
 src/conf/cpu_conf.h                                | 19 +++++++
6d3351
 src/libvirt_private.syms                           |  2 +
6d3351
 .../generic-cpu-cache-disable.xml                  | 20 +++++++
6d3351
 .../generic-cpu-cache-emulate.xml                  | 20 +++++++
6d3351
 .../generic-cpu-cache-passthrough.xml              | 20 +++++++
6d3351
 tests/genericxml2xmltest.c                         |  4 ++
6d3351
 10 files changed, 206 insertions(+)
6d3351
 create mode 100644 tests/genericxml2xmlindata/generic-cpu-cache-disable.xml
6d3351
 create mode 100644 tests/genericxml2xmlindata/generic-cpu-cache-emulate.xml
6d3351
 create mode 100644 tests/genericxml2xmlindata/generic-cpu-cache-passthrough.xml
6d3351
6d3351
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
6d3351
index aae5e9c07..aee1e1442 100644
6d3351
--- a/docs/formatdomain.html.in
6d3351
+++ b/docs/formatdomain.html.in
6d3351
@@ -1198,6 +1198,7 @@
6d3351
   <model fallback='allow'>core2duo</model>
6d3351
   <vendor>Intel</vendor>
6d3351
   <topology sockets='1' cores='2' threads='1'/>
6d3351
+  <cache level='3' mode='emulate'/>
6d3351
   <feature policy='disable' name='lahf_lm'/>
6d3351
 </cpu>
6d3351
 ...
6d3351
@@ -1211,6 +1212,7 @@
6d3351
 
6d3351
 
6d3351
 <cpu mode='host-passthrough'>
6d3351
+  <cache mode='passthrough'/>
6d3351
   <feature policy='disable' name='lahf_lm'/>
6d3351
 ...
6d3351
 
6d3351
@@ -1431,6 +1433,39 @@
6d3351
         Since 0.8.5 the policy
6d3351
         attribute can be omitted and will default to require.
6d3351
       
6d3351
+
6d3351
+      
cache
6d3351
+      
Since 3.3.0 the cache
6d3351
+        element describes the virtual CPU cache. If the element is missing,
6d3351
+        the hypervisor will use a sensible default.
6d3351
+
6d3351
+        
6d3351
+          
level
6d3351
+          
This optional attribute specifies which cache level is described
6d3351
+            by the element. Missing attribute means the element describes all
6d3351
+            CPU cache levels at once. Mixing cache elements with
6d3351
+            the level attribute set and those without the
6d3351
+            attribute is forbidden.
6d3351
+
6d3351
+          
mode
6d3351
+          
6d3351
+            The following values are supported:
6d3351
+            
6d3351
+              
emulate
6d3351
+              
The hypervisor will provide a fake CPU cache data.
6d3351
+
6d3351
+              
passthrough
6d3351
+              
The real CPU cache data reported by the host CPU will be
6d3351
+                passed through to the virtual CPU.
6d3351
+
6d3351
+              
disable
6d3351
+              
The virtual CPU will report no CPU cache of the specified
6d3351
+                level (or no cache at all if the level attribute
6d3351
+                is missing).
6d3351
+            
6d3351
+          
6d3351
+        
6d3351
+      
6d3351
     
6d3351
 
6d3351
     

6d3351
diff --git a/docs/schemas/cputypes.rng b/docs/schemas/cputypes.rng
6d3351
index 8189114e3..3eef16abc 100644
6d3351
--- a/docs/schemas/cputypes.rng
6d3351
+++ b/docs/schemas/cputypes.rng
6d3351
@@ -142,4 +142,25 @@
6d3351
     </data>
6d3351
   </define>
6d3351
 
6d3351
+  <define name="cpuCache">
6d3351
+    <element name="cache">
6d3351
+      <optional>
6d3351
+        <attribute name="level">
6d3351
+          <choice>
6d3351
+            <value>1</value>
6d3351
+            <value>2</value>
6d3351
+            <value>3</value>
6d3351
+          </choice>
6d3351
+        </attribute>
6d3351
+      </optional>
6d3351
+      <attribute name="mode">
6d3351
+        <choice>
6d3351
+          <value>emulate</value>
6d3351
+          <value>passthrough</value>
6d3351
+          <value>disable</value>
6d3351
+        </choice>
6d3351
+      </attribute>
6d3351
+    </element>
6d3351
+  </define>
6d3351
+
6d3351
 </grammar>
6d3351
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
6d3351
index edc225fe5..d5c28ee3c 100644
6d3351
--- a/docs/schemas/domaincommon.rng
6d3351
+++ b/docs/schemas/domaincommon.rng
6d3351
@@ -4545,6 +4545,9 @@
6d3351
         <optional>
6d3351
           <ref name="cpuNuma"/>
6d3351
         </optional>
6d3351
+        <optional>
6d3351
+          <ref name="cpuCache"/>
6d3351
+        </optional>
6d3351
       </interleave>
6d3351
     </element>
6d3351
   </define>
6d3351
diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
6d3351
index 623b1699f..1b098c476 100644
6d3351
--- a/src/conf/cpu_conf.c
6d3351
+++ b/src/conf/cpu_conf.c
6d3351
@@ -62,6 +62,12 @@ VIR_ENUM_IMPL(virCPUFeaturePolicy, VIR_CPU_FEATURE_LAST,
6d3351
               "disable",
6d3351
               "forbid")
6d3351
 
6d3351
+VIR_ENUM_IMPL(virCPUCacheMode, VIR_CPU_CACHE_MODE_LAST,
6d3351
+              "emulate",
6d3351
+              "passthrough",
6d3351
+              "disable")
6d3351
+
6d3351
+
6d3351
 void
6d3351
 virCPUDefFreeFeatures(virCPUDefPtr def)
6d3351
 {
6d3351
@@ -92,6 +98,7 @@ virCPUDefFree(virCPUDefPtr def)
6d3351
         return;
6d3351
 
6d3351
     virCPUDefFreeModel(def);
6d3351
+    VIR_FREE(def->cache);
6d3351
     VIR_FREE(def);
6d3351
 }
6d3351
 
6d3351
@@ -204,7 +211,18 @@ virCPUDefCopyWithoutModel(const virCPUDef *cpu)
6d3351
     copy->threads = cpu->threads;
6d3351
     copy->arch = cpu->arch;
6d3351
 
6d3351
+    if (cpu->cache) {
6d3351
+        if (VIR_ALLOC(copy->cache) < 0)
6d3351
+            goto error;
6d3351
+
6d3351
+        *copy->cache = *cpu->cache;
6d3351
+    }
6d3351
+
6d3351
     return copy;
6d3351
+
6d3351
+ error:
6d3351
+    virCPUDefFree(copy);
6d3351
+    return NULL;
6d3351
 }
6d3351
 
6d3351
 
6d3351
@@ -489,6 +507,41 @@ virCPUDefParseXML(xmlNodePtr node,
6d3351
         def->features[i].policy = policy;
6d3351
     }
6d3351
 
6d3351
+    if (virXPathInt("count(./cache)", ctxt, &n) < 0) {
6d3351
+        goto cleanup;
6d3351
+    } else if (n > 1) {
6d3351
+        virReportError(VIR_ERR_XML_ERROR, "%s",
6d3351
+                       _("at most one CPU cache element may be specified"));
6d3351
+        goto cleanup;
6d3351
+    } else if (n == 1) {
6d3351
+        int level = -1;
6d3351
+        char *strmode;
6d3351
+        int mode;
6d3351
+
6d3351
+        if (virXPathBoolean("boolean(./cache[1]/@level)", ctxt) == 1 &&
6d3351
+            (virXPathInt("string(./cache[1]/@level)", ctxt, &level) < 0 ||
6d3351
+             level < 1 || level > 3)) {
6d3351
+            virReportError(VIR_ERR_XML_ERROR, "%s",
6d3351
+                           _("invalid CPU cache level, must be in range [1,3]"));
6d3351
+            goto cleanup;
6d3351
+        }
6d3351
+
6d3351
+        if (!(strmode = virXPathString("string(./cache[1]/@mode)", ctxt)) ||
6d3351
+            (mode = virCPUCacheModeTypeFromString(strmode)) < 0) {
6d3351
+            VIR_FREE(strmode);
6d3351
+            virReportError(VIR_ERR_XML_ERROR, "%s",
6d3351
+                           _("missing or invalid CPU cache mode"));
6d3351
+            goto cleanup;
6d3351
+        }
6d3351
+        VIR_FREE(strmode);
6d3351
+
6d3351
+        if (VIR_ALLOC(def->cache) < 0)
6d3351
+            goto cleanup;
6d3351
+
6d3351
+        def->cache->level = level;
6d3351
+        def->cache->mode = mode;
6d3351
+    }
6d3351
+
6d3351
  cleanup:
6d3351
     ctxt->node = oldnode;
6d3351
     VIR_FREE(fallback);
6d3351
@@ -662,6 +715,15 @@ virCPUDefFormatBuf(virBufferPtr buf,
6d3351
         virBufferAddLit(buf, "/>\n");
6d3351
     }
6d3351
 
6d3351
+    if (def->cache) {
6d3351
+        virBufferAddLit(buf, "
6d3351
+        if (def->cache->level != -1)
6d3351
+            virBufferAsprintf(buf, "level='%d' ", def->cache->level);
6d3351
+        virBufferAsprintf(buf, "mode='%s'",
6d3351
+                          virCPUCacheModeTypeToString(def->cache->mode));
6d3351
+        virBufferAddLit(buf, "/>\n");
6d3351
+    }
6d3351
+
6d3351
     for (i = 0; i < def->nfeatures; i++) {
6d3351
         virCPUFeatureDefPtr feature = def->features + i;
6d3351
 
6d3351
diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h
6d3351
index 3e02deed4..09438b68b 100644
6d3351
--- a/src/conf/cpu_conf.h
6d3351
+++ b/src/conf/cpu_conf.h
6d3351
@@ -103,6 +103,24 @@ struct _virCPUFeatureDef {
6d3351
 };
6d3351
 
6d3351
 
6d3351
+typedef enum {
6d3351
+    VIR_CPU_CACHE_MODE_EMULATE,
6d3351
+    VIR_CPU_CACHE_MODE_PASSTHROUGH,
6d3351
+    VIR_CPU_CACHE_MODE_DISABLE,
6d3351
+
6d3351
+    VIR_CPU_CACHE_MODE_LAST
6d3351
+} virCPUCacheMode;
6d3351
+
6d3351
+VIR_ENUM_DECL(virCPUCacheMode);
6d3351
+
6d3351
+typedef struct _virCPUCacheDef virCPUCacheDef;
6d3351
+typedef virCPUCacheDef *virCPUCacheDefPtr;
6d3351
+struct _virCPUCacheDef {
6d3351
+    int level;          /* -1 for unspecified */
6d3351
+    virCPUCacheMode mode;
6d3351
+};
6d3351
+
6d3351
+
6d3351
 typedef struct _virCPUDef virCPUDef;
6d3351
 typedef virCPUDef *virCPUDefPtr;
6d3351
 struct _virCPUDef {
6d3351
@@ -121,6 +139,7 @@ struct _virCPUDef {
6d3351
     size_t nfeatures;
6d3351
     size_t nfeatures_max;
6d3351
     virCPUFeatureDefPtr features;
6d3351
+    virCPUCacheDefPtr cache;
6d3351
 };
6d3351
 
6d3351
 
6d3351
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
6d3351
index b551cb86a..9a334311d 100644
6d3351
--- a/src/libvirt_private.syms
6d3351
+++ b/src/libvirt_private.syms
6d3351
@@ -67,6 +67,8 @@ virCapabilitiesSetNetPrefix;
6d3351
 
6d3351
 
6d3351
 # conf/cpu_conf.h
6d3351
+virCPUCacheModeTypeFromString;
6d3351
+virCPUCacheModeTypeToString;
6d3351
 virCPUDefAddFeature;
6d3351
 virCPUDefCopy;
6d3351
 virCPUDefCopyModel;
6d3351
diff --git a/tests/genericxml2xmlindata/generic-cpu-cache-disable.xml b/tests/genericxml2xmlindata/generic-cpu-cache-disable.xml
6d3351
new file mode 100644
6d3351
index 000000000..25f65cc6e
6d3351
--- /dev/null
6d3351
+++ b/tests/genericxml2xmlindata/generic-cpu-cache-disable.xml
6d3351
@@ -0,0 +1,20 @@
6d3351
+<domain type='kvm'>
6d3351
+  <name>foo</name>
6d3351
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
6d3351
+  <memory unit='KiB'>219136</memory>
6d3351
+  <currentMemory unit='KiB'>219136</currentMemory>
6d3351
+  <vcpu placement='static'>1</vcpu>
6d3351
+  <os>
6d3351
+    <type arch='i686' machine='pc'>hvm</type>
6d3351
+    <boot dev='hd'/>
6d3351
+  </os>
6d3351
+  <cpu mode='host-passthrough'>
6d3351
+    <cache mode='disable'/>
6d3351
+  </cpu>
6d3351
+  <clock offset='utc'/>
6d3351
+  <on_poweroff>destroy</on_poweroff>
6d3351
+  <on_reboot>restart</on_reboot>
6d3351
+  <on_crash>destroy</on_crash>
6d3351
+  <devices>
6d3351
+  </devices>
6d3351
+</domain>
6d3351
diff --git a/tests/genericxml2xmlindata/generic-cpu-cache-emulate.xml b/tests/genericxml2xmlindata/generic-cpu-cache-emulate.xml
6d3351
new file mode 100644
6d3351
index 000000000..6ea57cbf6
6d3351
--- /dev/null
6d3351
+++ b/tests/genericxml2xmlindata/generic-cpu-cache-emulate.xml
6d3351
@@ -0,0 +1,20 @@
6d3351
+<domain type='kvm'>
6d3351
+  <name>foo</name>
6d3351
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
6d3351
+  <memory unit='KiB'>219136</memory>
6d3351
+  <currentMemory unit='KiB'>219136</currentMemory>
6d3351
+  <vcpu placement='static'>1</vcpu>
6d3351
+  <os>
6d3351
+    <type arch='i686' machine='pc'>hvm</type>
6d3351
+    <boot dev='hd'/>
6d3351
+  </os>
6d3351
+  <cpu mode='host-passthrough'>
6d3351
+    <cache level='3' mode='emulate'/>
6d3351
+  </cpu>
6d3351
+  <clock offset='utc'/>
6d3351
+  <on_poweroff>destroy</on_poweroff>
6d3351
+  <on_reboot>restart</on_reboot>
6d3351
+  <on_crash>destroy</on_crash>
6d3351
+  <devices>
6d3351
+  </devices>
6d3351
+</domain>
6d3351
diff --git a/tests/genericxml2xmlindata/generic-cpu-cache-passthrough.xml b/tests/genericxml2xmlindata/generic-cpu-cache-passthrough.xml
6d3351
new file mode 100644
6d3351
index 000000000..8d4c186c9
6d3351
--- /dev/null
6d3351
+++ b/tests/genericxml2xmlindata/generic-cpu-cache-passthrough.xml
6d3351
@@ -0,0 +1,20 @@
6d3351
+<domain type='kvm'>
6d3351
+  <name>foo</name>
6d3351
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
6d3351
+  <memory unit='KiB'>219136</memory>
6d3351
+  <currentMemory unit='KiB'>219136</currentMemory>
6d3351
+  <vcpu placement='static'>1</vcpu>
6d3351
+  <os>
6d3351
+    <type arch='i686' machine='pc'>hvm</type>
6d3351
+    <boot dev='hd'/>
6d3351
+  </os>
6d3351
+  <cpu mode='host-passthrough'>
6d3351
+    <cache mode='passthrough'/>
6d3351
+  </cpu>
6d3351
+  <clock offset='utc'/>
6d3351
+  <on_poweroff>destroy</on_poweroff>
6d3351
+  <on_reboot>restart</on_reboot>
6d3351
+  <on_crash>destroy</on_crash>
6d3351
+  <devices>
6d3351
+  </devices>
6d3351
+</domain>
6d3351
diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c
6d3351
index 488190270..ab1ebce9f 100644
6d3351
--- a/tests/genericxml2xmltest.c
6d3351
+++ b/tests/genericxml2xmltest.c
6d3351
@@ -100,6 +100,10 @@ mymain(void)
6d3351
 
6d3351
     DO_TEST("vcpus-individual");
6d3351
 
6d3351
+    DO_TEST("cpu-cache-emulate");
6d3351
+    DO_TEST("cpu-cache-passthrough");
6d3351
+    DO_TEST("cpu-cache-disable");
6d3351
+
6d3351
     virObjectUnref(caps);
6d3351
     virObjectUnref(xmlopt);
6d3351
 
6d3351
-- 
6d3351
2.12.2
6d3351