]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Added the attribute vendor_id to the cpu model
authorHendrik Schwartke <hendrik@os-t.de>
Thu, 28 Jun 2012 10:21:17 +0000 (12:21 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 3 Jul 2012 10:06:38 +0000 (12:06 +0200)
Introducing the attribute vendor_id to force the CPUID instruction
in a kvm guest to return the specified vendor.

docs/schemas/domaincommon.rng
src/conf/cpu_conf.c
src/conf/cpu_conf.h
src/qemu/qemu_command.c
tests/testutilsqemu.c

index 912a1a22a899ae4a4a97db785cacdf5c5c29df53..3d205b09ee6e597dc495ecd19cefbb26874b3d09 100644 (file)
           </choice>
         </attribute>
       </optional>
+      <optional>
+        <attribute name="vendor_id">
+          <data type="string">
+            <param name='pattern'>[^,]{12}</param>
+          </data>
+        </attribute>
+      </optional>
       <choice>
         <text/>
         <empty/>
index b520f7c6417cf2d1ad7e02651e806cbf70dd72f6..7fe3c1ef97eb478eeb10bd214aac768176cf502e 100644 (file)
@@ -68,6 +68,7 @@ virCPUDefFreeModel(virCPUDefPtr def)
 
     VIR_FREE(def->model);
     VIR_FREE(def->vendor);
+    VIR_FREE(def->vendor_id);
 
     for (i = 0; i < def->nfeatures; i++)
         VIR_FREE(def->features[i].name);
@@ -104,6 +105,7 @@ virCPUDefCopyModel(virCPUDefPtr dst,
 
     if ((src->model && !(dst->model = strdup(src->model)))
         || (src->vendor && !(dst->vendor = strdup(src->vendor)))
+        || (src->vendor_id && !(dst->vendor_id = strdup(src->vendor_id)))
         || VIR_ALLOC_N(dst->features, src->nfeatures) < 0)
         goto no_memory;
     dst->nfeatures_max = dst->nfeatures = src->nfeatures;
@@ -288,18 +290,46 @@ virCPUDefParseXML(const xmlNodePtr node,
     }
 
     if (def->type == VIR_CPU_TYPE_GUEST &&
-        def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH &&
-        virXPathBoolean("boolean(./model[1]/@fallback)", ctxt)) {
-        const char *fallback;
-
-        fallback = virXPathString("string(./model[1]/@fallback)", ctxt);
-        if (fallback) {
-            def->fallback = virCPUFallbackTypeFromString(fallback);
-            VIR_FREE(fallback);
-            if (def->fallback < 0) {
-                virCPUReportError(VIR_ERR_XML_ERROR, "%s",
-                                  _("Invalid fallback attribute"));
-                goto error;
+        def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH) {
+
+        if (virXPathBoolean("boolean(./model[1]/@fallback)", ctxt)) {
+            const char *fallback;
+
+            fallback = virXPathString("string(./model[1]/@fallback)", ctxt);
+            if (fallback) {
+                def->fallback = virCPUFallbackTypeFromString(fallback);
+                VIR_FREE(fallback);
+                if (def->fallback < 0) {
+                    virCPUReportError(VIR_ERR_XML_ERROR, "%s",
+                                      _("Invalid fallback attribute"));
+                    goto error;
+                }
+            }
+
+            if (virXPathBoolean("boolean(./model[1]/@vendor_id)", ctxt)) {
+                char *vendor_id;
+
+                vendor_id = virXPathString("string(./model[1]/@vendor_id)",
+                                           ctxt);
+                if (!vendor_id ||
+                    strlen(vendor_id) != VIR_CPU_VENDOR_ID_LENGTH) {
+                    virCPUReportError(VIR_ERR_XML_ERROR,
+                                      _("vendor_id must be exactly"
+                                        " %d characters long"),
+                                      VIR_CPU_VENDOR_ID_LENGTH);
+                    VIR_FREE(vendor_id);
+                    goto error;
+                }
+                /* ensure that the string can be passed to qemu*/
+                for (i = 0; i < strlen(vendor_id); i++) {
+                    if (vendor_id[i]==',') {
+                        virCPUReportError(VIR_ERR_XML_ERROR, "%s",
+                                          _("vendor id is invalid"));
+                        VIR_FREE(vendor_id);
+                        goto error;
+                    }
+                }
+                def->vendor_id = vendor_id;
             }
         }
     }
@@ -588,6 +618,8 @@ virCPUDefFormatBuf(virBufferPtr buf,
                 return -1;
             }
             virBufferAsprintf(buf, " fallback='%s'", fallback);
+            if (def->vendor_id)
+                virBufferAsprintf(buf, " vendor_id='%s'", def->vendor_id);
         }
         if (formatModel && def->model) {
             virBufferAsprintf(buf, ">%s</model>\n", def->model);
@@ -738,6 +770,13 @@ virCPUDefIsEqual(virCPUDefPtr src,
         goto cleanup;
     }
 
+    if (STRNEQ_NULLABLE(src->vendor_id, dst->vendor_id)) {
+        virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                          _("Target CPU model %s does not match source %s"),
+                          NULLSTR(dst->vendor_id), NULLSTR(src->vendor_id));
+        goto cleanup;
+    }
+
     if (src->sockets != dst->sockets) {
         virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Target CPU sockets %d does not match source %d"),
index f8b7bf95631e713ecbeee16bbacf8965834663d0..2df0a506bf21d010b027e578f1cec361bd98c1a3 100644 (file)
@@ -28,6 +28,8 @@
 # include "buf.h"
 # include "xml.h"
 
+# define VIR_CPU_VENDOR_ID_LENGTH 12
+
 enum virCPUType {
     VIR_CPU_TYPE_HOST,
     VIR_CPU_TYPE_GUEST,
@@ -103,6 +105,7 @@ struct _virCPUDef {
     int match;          /* enum virCPUMatch */
     char *arch;
     char *model;
+    char *vendor_id;    /* vendor id returned by CPUID in the guest */
     int fallback;       /* enum virCPUFallback */
     char *vendor;
     unsigned int sockets;
index 6549f577019225d9ff8fa1629c24f00306a3169b..528b18935247b07b28e02a09d83d867ae71c088e 100644 (file)
@@ -3913,7 +3913,9 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
             }
             virBufferAddLit(&buf, "host");
         } else {
-            if (VIR_ALLOC(guest) < 0 || !(guest->arch = strdup(host->arch)))
+            if (VIR_ALLOC(guest) < 0 ||
+                !(guest->arch = strdup(host->arch)) ||
+                (cpu->vendor_id && !(guest->vendor_id = strdup(cpu->vendor_id))))
                 goto no_memory;
 
             if (cpu->match == VIR_CPU_MATCH_MINIMUM)
@@ -3927,6 +3929,8 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
                 goto cleanup;
 
             virBufferAdd(&buf, guest->model, -1);
+            if (guest->vendor_id)
+                virBufferAsprintf(&buf, ",vendor=%s", guest->vendor_id);
             for (i = 0; i < guest->nfeatures; i++) {
                 char sign;
                 if (guest->features[i].policy == VIR_CPU_FEATURE_DISABLE)
index 8d5a3bff3817a105a9df8c7f34554fa00cb83abd..8b7cb3300bd8be2c2c7e5d570ffb435e3d391fa5 100644 (file)
@@ -116,6 +116,7 @@ virCapsPtr testQemuCapsInit(void) {
         0,                      /* match */
         (char *) "x86_64",      /* arch */
         (char *) "core2duo",    /* model */
+        NULL,                   /* vendor_id */
         0,                      /* fallback */
         (char *) "Intel",       /* vendor */
         1,                      /* sockets */