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")); I'd reword this: virCPUReportError(VIR_ERR_XML_ERROR, _("vendor_id must be exactly %d characters long"), VIR_CPU_VENDOR_ID_LENGTH); I know vendor_id length is unlikely to change but nobody knows ... > + VIR_FREE(vendor_id); > + goto error; > + } > + for(i=0; i<strlen(vendor_id); i++) { > + if(!isprint(vendor_id[i]) || isspace(vendor_id[i])) { This should be c_isprint() and c_isspace(); however, I am not sure but I think vendor id can contain spaces, doesn't it? Anyway, then you should not #include <ctype.h> but #include "c-ctype.h" > + 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 > + Insert one space between '#' and define so this is indented properly. > 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 */ > Otherwise looking good. Can somebody chime in and provide more light on allowed characters in vendor id? Michal -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list