[libvirt] [PATCH] Added the attribute vendor_id to the cpu model
Michal Privoznik
mprivozn at redhat.com
Wed Jun 27 15:14:42 UTC 2012
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
More information about the libvir-list
mailing list