[libvirt] [PATCH] Added the attribute vendor_id to the cpu model

Hendrik Schwartke hendrik at os-t.de
Wed Jun 27 10:27:05 UTC 2012


Hi,

last week I posted a patch to fake the vendor_id of the guest cpu.
I'm writing an application which depends on this feature so I'm 
wondering if anyone has had a look at it?

Best regards
Hendrik


On 21.06.2012 16:58, Hendrik Schwartke wrote:
> Introducing the attribute vendor_id to force the CPUID instruction
> in a kvm guest to return the specified vendor.
> ---
>   docs/schemas/domaincommon.rng |    7 +++++
>   src/conf/cpu_conf.c           |   61 ++++++++++++++++++++++++++++++++---------
>   src/conf/cpu_conf.h           |    3 ++
>   src/qemu/qemu_command.c       |    6 +++-
>   tests/testutilsqemu.c         |    1 +
>   5 files changed, 64 insertions(+), 14 deletions(-)
>
> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
> index 46e539d..a246e8b 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -2820,6 +2820,13 @@
>             </choice>
>           </attribute>
>         </optional>
> +<optional>
> +<attribute name="vendor_id">
> +<data type="string">
> +<param name='pattern'>.{12}</param>
> +</data>
> +</attribute>
> +</optional>
>         <choice>
>           <text/>
>           <empty/>
> diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
> index b520f7c..b8ca7a5 100644
> --- a/src/conf/cpu_conf.c
> +++ b/src/conf/cpu_conf.c
> @@ -22,6 +22,7 @@
>    */
>
>   #include<config.h>
> +#include<ctype.h>
>
>   #include "virterror_internal.h"
>   #include "memory.h"
> @@ -68,6 +69,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 +106,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,19 +291,42 @@ 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, "%s",
> +                                  _("vendor id must be 12 characters long"));
> +                    VIR_FREE(vendor_id);
> +                    goto error;
> +               }
> +               for(i=0; i<strlen(vendor_id); i++) {
> +                   if(!isprint(vendor_id[i]) || isspace(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 +614,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 +766,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"),
> diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h
> index f8b7bf9..3daadbd 100644
> --- a/src/conf/cpu_conf.h
> +++ b/src/conf/cpu_conf.h
> @@ -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;
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index bd4f96a..56ecefb 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -3910,7 +3910,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)
> @@ -3924,6 +3926,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)
> diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
> index 8d5a3bf..8b7cb33 100644
> --- a/tests/testutilsqemu.c
> +++ b/tests/testutilsqemu.c
> @@ -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 */




More information about the libvir-list mailing list