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

5c27b6
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
5c27b6
index 6acc107c3..bd2823ff7 100644
5c27b6
--- a/docs/schemas/domaincommon.rng
5c27b6
+++ b/docs/schemas/domaincommon.rng
5c27b6
@@ -4388,6 +4388,9 @@
5c27b6
         <optional>
5c27b6
           <ref name="cpuNuma"/>
5c27b6
         </optional>
5c27b6
+        <optional>
5c27b6
+          <ref name="cpuCache"/>
5c27b6
+        </optional>
5c27b6
       </interleave>
5c27b6
     </element>
5c27b6
   </define>
5c27b6
@@ -4511,6 +4514,27 @@
5c27b6
     </element>
5c27b6
   </define>
5c27b6
 
5c27b6
+  <define name="cpuCache">
5c27b6
+    <element name="cache">
5c27b6
+      <optional>
5c27b6
+        <attribute name="level">
5c27b6
+          <choice>
5c27b6
+            <value>1</value>
5c27b6
+            <value>2</value>
5c27b6
+            <value>3</value>
5c27b6
+          </choice>
5c27b6
+        </attribute>
5c27b6
+      </optional>
5c27b6
+      <attribute name="mode">
5c27b6
+        <choice>
5c27b6
+          <value>emulate</value>
5c27b6
+          <value>passthrough</value>
5c27b6
+          <value>disable</value>
5c27b6
+        </choice>
5c27b6
+      </attribute>
5c27b6
+    </element>
5c27b6
+  </define>
5c27b6
+
5c27b6
   
5c27b6
       System information specification:
5c27b6
        Placeholder for system specific informations likes the ones
5c27b6
diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
5c27b6
index 9ffaf1e95..d16864a9f 100644
5c27b6
--- a/src/conf/cpu_conf.c
5c27b6
+++ b/src/conf/cpu_conf.c
5c27b6
@@ -56,6 +56,12 @@ VIR_ENUM_IMPL(virCPUFeaturePolicy, VIR_CPU_FEATURE_LAST,
5c27b6
               "disable",
5c27b6
               "forbid")
5c27b6
 
5c27b6
+VIR_ENUM_IMPL(virCPUCacheMode, VIR_CPU_CACHE_MODE_LAST,
5c27b6
+              "emulate",
5c27b6
+              "passthrough",
5c27b6
+              "disable")
5c27b6
+
5c27b6
+
5c27b6
 void ATTRIBUTE_NONNULL(1)
5c27b6
 virCPUDefFreeModel(virCPUDefPtr def)
5c27b6
 {
5c27b6
@@ -77,6 +83,7 @@ virCPUDefFree(virCPUDefPtr def)
5c27b6
         return;
5c27b6
 
5c27b6
     virCPUDefFreeModel(def);
5c27b6
+    VIR_FREE(def->cache);
5c27b6
     VIR_FREE(def);
5c27b6
 }
5c27b6
 
5c27b6
@@ -131,6 +138,13 @@ virCPUDefCopy(const virCPUDef *cpu)
5c27b6
     copy->threads = cpu->threads;
5c27b6
     copy->arch = cpu->arch;
5c27b6
 
5c27b6
+    if (cpu->cache) {
5c27b6
+        if (VIR_ALLOC(copy->cache) < 0)
5c27b6
+            goto error;
5c27b6
+
5c27b6
+        *copy->cache = *cpu->cache;
5c27b6
+    }
5c27b6
+
5c27b6
     if (virCPUDefCopyModel(copy, cpu, false) < 0)
5c27b6
         goto error;
5c27b6
 
5c27b6
@@ -389,6 +403,41 @@ virCPUDefParseXML(xmlNodePtr node,
5c27b6
         def->features[i].policy = policy;
5c27b6
     }
5c27b6
 
5c27b6
+    if (virXPathInt("count(./cache)", ctxt, &n) < 0) {
5c27b6
+        goto cleanup;
5c27b6
+    } else if (n > 1) {
5c27b6
+        virReportError(VIR_ERR_XML_ERROR, "%s",
5c27b6
+                       _("at most one CPU cache element may be specified"));
5c27b6
+        goto cleanup;
5c27b6
+    } else if (n == 1) {
5c27b6
+        int level = -1;
5c27b6
+        char *strmode;
5c27b6
+        int mode;
5c27b6
+
5c27b6
+        if (virXPathBoolean("boolean(./cache[1]/@level)", ctxt) == 1 &&
5c27b6
+            (virXPathInt("string(./cache[1]/@level)", ctxt, &level) < 0 ||
5c27b6
+             level < 1 || level > 3)) {
5c27b6
+            virReportError(VIR_ERR_XML_ERROR, "%s",
5c27b6
+                           _("invalid CPU cache level, must be in range [1,3]"));
5c27b6
+            goto cleanup;
5c27b6
+        }
5c27b6
+
5c27b6
+        if (!(strmode = virXPathString("string(./cache[1]/@mode)", ctxt)) ||
5c27b6
+            (mode = virCPUCacheModeTypeFromString(strmode)) < 0) {
5c27b6
+            VIR_FREE(strmode);
5c27b6
+            virReportError(VIR_ERR_XML_ERROR, "%s",
5c27b6
+                           _("missing or invalid CPU cache mode"));
5c27b6
+            goto cleanup;
5c27b6
+        }
5c27b6
+        VIR_FREE(strmode);
5c27b6
+
5c27b6
+        if (VIR_ALLOC(def->cache) < 0)
5c27b6
+            goto cleanup;
5c27b6
+
5c27b6
+        def->cache->level = level;
5c27b6
+        def->cache->mode = mode;
5c27b6
+    }
5c27b6
+
5c27b6
  cleanup:
5c27b6
     ctxt->node = oldnode;
5c27b6
     VIR_FREE(fallback);
5c27b6
@@ -557,6 +606,15 @@ virCPUDefFormatBuf(virBufferPtr buf,
5c27b6
         virBufferAddLit(buf, "/>\n");
5c27b6
     }
5c27b6
 
5c27b6
+    if (def->cache) {
5c27b6
+        virBufferAddLit(buf, "
5c27b6
+        if (def->cache->level != -1)
5c27b6
+            virBufferAsprintf(buf, "level='%d' ", def->cache->level);
5c27b6
+        virBufferAsprintf(buf, "mode='%s'",
5c27b6
+                          virCPUCacheModeTypeToString(def->cache->mode));
5c27b6
+        virBufferAddLit(buf, "/>\n");
5c27b6
+    }
5c27b6
+
5c27b6
     for (i = 0; i < def->nfeatures; i++) {
5c27b6
         virCPUFeatureDefPtr feature = def->features + i;
5c27b6
 
5c27b6
diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h
5c27b6
index 705ba6d90..53541d15f 100644
5c27b6
--- a/src/conf/cpu_conf.h
5c27b6
+++ b/src/conf/cpu_conf.h
5c27b6
@@ -92,6 +92,24 @@ struct _virCPUFeatureDef {
5c27b6
 };
5c27b6
 
5c27b6
 
5c27b6
+typedef enum {
5c27b6
+    VIR_CPU_CACHE_MODE_EMULATE,
5c27b6
+    VIR_CPU_CACHE_MODE_PASSTHROUGH,
5c27b6
+    VIR_CPU_CACHE_MODE_DISABLE,
5c27b6
+
5c27b6
+    VIR_CPU_CACHE_MODE_LAST
5c27b6
+} virCPUCacheMode;
5c27b6
+
5c27b6
+VIR_ENUM_DECL(virCPUCacheMode);
5c27b6
+
5c27b6
+typedef struct _virCPUCacheDef virCPUCacheDef;
5c27b6
+typedef virCPUCacheDef *virCPUCacheDefPtr;
5c27b6
+struct _virCPUCacheDef {
5c27b6
+    int level;          /* -1 for unspecified */
5c27b6
+    virCPUCacheMode mode;
5c27b6
+};
5c27b6
+
5c27b6
+
5c27b6
 typedef struct _virCPUDef virCPUDef;
5c27b6
 typedef virCPUDef *virCPUDefPtr;
5c27b6
 struct _virCPUDef {
5c27b6
@@ -109,6 +127,7 @@ struct _virCPUDef {
5c27b6
     size_t nfeatures;
5c27b6
     size_t nfeatures_max;
5c27b6
     virCPUFeatureDefPtr features;
5c27b6
+    virCPUCacheDefPtr cache;
5c27b6
 };
5c27b6
 
5c27b6
 
5c27b6
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
5c27b6
index e2dbee92d..bfeb1e58f 100644
5c27b6
--- a/src/libvirt_private.syms
5c27b6
+++ b/src/libvirt_private.syms
5c27b6
@@ -63,6 +63,8 @@ virCapabilitiesSetNetPrefix;
5c27b6
 
5c27b6
 
5c27b6
 # conf/cpu_conf.h
5c27b6
+virCPUCacheModeTypeFromString;
5c27b6
+virCPUCacheModeTypeToString;
5c27b6
 virCPUDefAddFeature;
5c27b6
 virCPUDefCopy;
5c27b6
 virCPUDefCopyModel;
5c27b6
diff --git a/tests/genericxml2xmlindata/generic-cpu-cache-disable.xml b/tests/genericxml2xmlindata/generic-cpu-cache-disable.xml
5c27b6
new file mode 100644
5c27b6
index 000000000..25f65cc6e
5c27b6
--- /dev/null
5c27b6
+++ b/tests/genericxml2xmlindata/generic-cpu-cache-disable.xml
5c27b6
@@ -0,0 +1,20 @@
5c27b6
+<domain type='kvm'>
5c27b6
+  <name>foo</name>
5c27b6
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
5c27b6
+  <memory unit='KiB'>219136</memory>
5c27b6
+  <currentMemory unit='KiB'>219136</currentMemory>
5c27b6
+  <vcpu placement='static'>1</vcpu>
5c27b6
+  <os>
5c27b6
+    <type arch='i686' machine='pc'>hvm</type>
5c27b6
+    <boot dev='hd'/>
5c27b6
+  </os>
5c27b6
+  <cpu mode='host-passthrough'>
5c27b6
+    <cache mode='disable'/>
5c27b6
+  </cpu>
5c27b6
+  <clock offset='utc'/>
5c27b6
+  <on_poweroff>destroy</on_poweroff>
5c27b6
+  <on_reboot>restart</on_reboot>
5c27b6
+  <on_crash>destroy</on_crash>
5c27b6
+  <devices>
5c27b6
+  </devices>
5c27b6
+</domain>
5c27b6
diff --git a/tests/genericxml2xmlindata/generic-cpu-cache-emulate.xml b/tests/genericxml2xmlindata/generic-cpu-cache-emulate.xml
5c27b6
new file mode 100644
5c27b6
index 000000000..6ea57cbf6
5c27b6
--- /dev/null
5c27b6
+++ b/tests/genericxml2xmlindata/generic-cpu-cache-emulate.xml
5c27b6
@@ -0,0 +1,20 @@
5c27b6
+<domain type='kvm'>
5c27b6
+  <name>foo</name>
5c27b6
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
5c27b6
+  <memory unit='KiB'>219136</memory>
5c27b6
+  <currentMemory unit='KiB'>219136</currentMemory>
5c27b6
+  <vcpu placement='static'>1</vcpu>
5c27b6
+  <os>
5c27b6
+    <type arch='i686' machine='pc'>hvm</type>
5c27b6
+    <boot dev='hd'/>
5c27b6
+  </os>
5c27b6
+  <cpu mode='host-passthrough'>
5c27b6
+    <cache level='3' mode='emulate'/>
5c27b6
+  </cpu>
5c27b6
+  <clock offset='utc'/>
5c27b6
+  <on_poweroff>destroy</on_poweroff>
5c27b6
+  <on_reboot>restart</on_reboot>
5c27b6
+  <on_crash>destroy</on_crash>
5c27b6
+  <devices>
5c27b6
+  </devices>
5c27b6
+</domain>
5c27b6
diff --git a/tests/genericxml2xmlindata/generic-cpu-cache-passthrough.xml b/tests/genericxml2xmlindata/generic-cpu-cache-passthrough.xml
5c27b6
new file mode 100644
5c27b6
index 000000000..8d4c186c9
5c27b6
--- /dev/null
5c27b6
+++ b/tests/genericxml2xmlindata/generic-cpu-cache-passthrough.xml
5c27b6
@@ -0,0 +1,20 @@
5c27b6
+<domain type='kvm'>
5c27b6
+  <name>foo</name>
5c27b6
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
5c27b6
+  <memory unit='KiB'>219136</memory>
5c27b6
+  <currentMemory unit='KiB'>219136</currentMemory>
5c27b6
+  <vcpu placement='static'>1</vcpu>
5c27b6
+  <os>
5c27b6
+    <type arch='i686' machine='pc'>hvm</type>
5c27b6
+    <boot dev='hd'/>
5c27b6
+  </os>
5c27b6
+  <cpu mode='host-passthrough'>
5c27b6
+    <cache mode='passthrough'/>
5c27b6
+  </cpu>
5c27b6
+  <clock offset='utc'/>
5c27b6
+  <on_poweroff>destroy</on_poweroff>
5c27b6
+  <on_reboot>restart</on_reboot>
5c27b6
+  <on_crash>destroy</on_crash>
5c27b6
+  <devices>
5c27b6
+  </devices>
5c27b6
+</domain>
5c27b6
diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c
5c27b6
index 2ea239648..17afc1dc9 100644
5c27b6
--- a/tests/genericxml2xmltest.c
5c27b6
+++ b/tests/genericxml2xmltest.c
5c27b6
@@ -99,6 +99,10 @@ mymain(void)
5c27b6
 
5c27b6
     DO_TEST("vcpus-individual");
5c27b6
 
5c27b6
+    DO_TEST("cpu-cache-emulate");
5c27b6
+    DO_TEST("cpu-cache-passthrough");
5c27b6
+    DO_TEST("cpu-cache-disable");
5c27b6
+
5c27b6
     virObjectUnref(caps);
5c27b6
     virObjectUnref(xmlopt);
5c27b6
 
5c27b6
-- 
5c27b6
2.12.2
5c27b6