]> xenbits.xensource.com Git - libvirt.git/commitdiff
cpu: Allow fine tuning of "host-model" cpu
authorPeter Krempa <pkrempa@redhat.com>
Mon, 15 Jul 2013 15:38:55 +0000 (17:38 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Tue, 16 Jul 2013 08:51:30 +0000 (10:51 +0200)
https://bugzilla.redhat.com/show_bug.cgi?id=799354

Until now, the "host-model" cpu mode couldn't be influenced. This patch
allows to use the <feature> elements to either enable or disable
specific CPU flags. This can be used to force flags that can be emulated
even if the host CPU doesn't support them.

docs/formatdomain.html.in
src/conf/cpu_conf.c
src/cpu/cpu_x86.c

index 52a6353bd6941dfb4808af1e38c6c3c1c5ec8b2b..d2dbcb8ca9d39a63f3ff8612aa15d08b56ec7823 100644 (file)
           copying host CPU definition from capabilities XML into domain XML.
           Since the CPU definition is copied just before starting a domain,
           exactly the same XML can be used on different hosts while still
-          providing the best guest CPU each host supports. Neither
-          <code>match</code> attribute nor any <code>feature</code> elements
-          can be used in this mode. Specifying CPU model is not supported
-          either, but <code>model</code>'s <code>fallback</code> attribute may
-          still be used. Libvirt does not model every aspect of each CPU so
+          providing the best guest CPU each host supports. The
+          <code>match</code> attribute can't be used in this mode. Specifying
+          CPU model is not supported either, but <code>model</code>'s
+          <code>fallback</code> attribute may still be used. Using the
+          <code>feature</code> element, specific flags may be enabled or
+          disabled specifically in addition to the host model. This may be
+          used to fine tune features that can be emulated.
+          <span class="since">(Since 1.1.1)</span>.
+          Libvirt does not model every aspect of each CPU so
           the guest CPU will not match the host CPU exactly. On the other
           hand, the ABI provided to the guest is reproducible. During
           migration, complete CPU model definition is transferred to the
index 1e657ad91eec1970c0e1a7f4278bf2d80b02d8bd..d3fbebac6765158a9bf5aee27541d93a9765a4aa 100644 (file)
@@ -361,7 +361,7 @@ virCPUDefParseXML(const xmlNodePtr node,
         goto error;
 
     if (n > 0) {
-        if (!def->model) {
+        if (!def->model && def->mode != VIR_CPU_MODE_HOST_MODEL) {
             virReportError(VIR_ERR_XML_ERROR, "%s",
                            _("Non-empty feature list specified without "
                              "CPU model"));
@@ -574,7 +574,9 @@ virCPUDefFormatBuf(virBufferPtr buf,
                       (def->mode == VIR_CPU_MODE_HOST_MODEL ||
                        (def->mode == VIR_CPU_MODE_CUSTOM && def->model)));
 
-    if (!def->model && def->nfeatures) {
+    if (!def->model &&
+        def->mode != VIR_CPU_MODE_HOST_MODEL &&
+        def->nfeatures) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("Non-empty feature list specified without CPU model"));
         return -1;
@@ -614,32 +616,30 @@ virCPUDefFormatBuf(virBufferPtr buf,
         virBufferAddLit(buf, "/>\n");
     }
 
-    if (formatModel) {
-        for (i = 0; i < def->nfeatures; i++) {
-            virCPUFeatureDefPtr feature = def->features + i;
+    for (i = 0; i < def->nfeatures; i++) {
+        virCPUFeatureDefPtr feature = def->features + i;
 
-            if (!feature->name) {
-                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                               _("Missing CPU feature name"));
-                return -1;
-            }
+        if (!feature->name) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Missing CPU feature name"));
+            return -1;
+        }
 
-            if (def->type == VIR_CPU_TYPE_GUEST) {
-                const char *policy;
-
-                policy = virCPUFeaturePolicyTypeToString(feature->policy);
-                if (!policy) {
-                    virReportError(VIR_ERR_INTERNAL_ERROR,
-                                   _("Unexpected CPU feature policy %d"),
-                                   feature->policy);
-                    return -1;
-                }
-                virBufferAsprintf(buf, "<feature policy='%s' name='%s'/>\n",
-                                  policy, feature->name);
-            } else {
-                virBufferAsprintf(buf, "<feature name='%s'/>\n",
-                                  feature->name);
+        if (def->type == VIR_CPU_TYPE_GUEST) {
+            const char *policy;
+
+            policy = virCPUFeaturePolicyTypeToString(feature->policy);
+            if (!policy) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Unexpected CPU feature policy %d"),
+                               feature->policy);
+                return -1;
             }
+            virBufferAsprintf(buf, "<feature policy='%s' name='%s'/>\n",
+                              policy, feature->name);
+        } else {
+            virBufferAsprintf(buf, "<feature name='%s'/>\n",
+                              feature->name);
         }
     }
 
index 928a67b96af325e27932c2edc3928a50b11e7661..cc7926e779a3bbd67ed3ae7c34f24ec29e4ffc68 100644 (file)
@@ -1739,6 +1739,41 @@ cleanup:
     return ret;
 }
 
+
+static int
+x86UpdateHostModel(virCPUDefPtr guest,
+                   const virCPUDefPtr host)
+{
+    virCPUDefPtr oldguest;
+    size_t i;
+
+    guest->match = VIR_CPU_MATCH_EXACT;
+
+    /* no updates are required */
+    if (guest->nfeatures == 0) {
+        virCPUDefFreeModel(guest);
+        return virCPUDefCopyModel(guest, host, true);
+    }
+
+    /* update the host model according to the desired configuration */
+    if (!(oldguest = virCPUDefCopy(guest)))
+        return -1;
+
+    virCPUDefFreeModel(guest);
+    if (virCPUDefCopyModel(guest, host, true) < 0)
+        return -1;
+
+    for (i = 0; i < oldguest->nfeatures; i++) {
+        if (virCPUDefUpdateFeature(guest,
+                                   oldguest->features[i].name,
+                                   oldguest->features[i].policy) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+
 static int
 x86Update(virCPUDefPtr guest,
           const virCPUDefPtr host)
@@ -1748,11 +1783,10 @@ x86Update(virCPUDefPtr guest,
         return x86UpdateCustom(guest, host);
 
     case VIR_CPU_MODE_HOST_MODEL:
+        return x86UpdateHostModel(guest, host);
+
     case VIR_CPU_MODE_HOST_PASSTHROUGH:
-        if (guest->mode == VIR_CPU_MODE_HOST_MODEL)
-            guest->match = VIR_CPU_MATCH_EXACT;
-        else
-            guest->match = VIR_CPU_MATCH_MINIMUM;
+        guest->match = VIR_CPU_MATCH_MINIMUM;
         virCPUDefFreeModel(guest);
         return virCPUDefCopyModel(guest, host, true);