The attribute can be used to request a specific way of checking whether the virtual CPU matches created by the hypervisor matches the specification in domain XML. Signed-off-by: Jiri Denemark <jdenemar@xxxxxxxxxx> --- docs/formatdomain.html.in | 30 ++++++++++++++++++++++++++++++ docs/schemas/cputypes.rng | 10 ++++++++++ docs/schemas/domaincommon.rng | 3 +++ src/conf/cpu_conf.c | 30 ++++++++++++++++++++++++++++++ src/conf/cpu_conf.h | 12 ++++++++++++ src/conf/domain_conf.c | 21 +++++++++++++++++++++ 6 files changed, 106 insertions(+) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 75367d6dd..3bea3c75a 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1247,6 +1247,36 @@ <span class="since">Since 0.8.5</span> the <code>match</code> attribute can be omitted and will default to <code>exact</code>. + Sometimes the hypervisor is not able to create a virtual CPU exactly + matching the specification passed by libvirt. + <span class="since">Since 3.2.0</span>, an optional <code>check</code> + attribute can be used to request a specific way of checking whether + the virtual CPU matches the specification. It is usually safe to omit + this attribute when starting a domain and stick with the default + value. Once the domain starts, libvirt will automatically change the + <code>check</code> attribute to the best supported value to ensure the + virtual CPU does not change when the domain is migrated to another + host. The following values can be used: + + <dl> + <dt><code>none</code></dt> + <dd>Libvirt does no checking and it is up to the hypervisor to + refuse to start the domain if it cannot provide the requested CPU. + With QEMU this means no checking is done at all since the default + behavior of QEMU is to emit warnings, but start the domain anyway. + </dd> + + <dt><code>partial</code></dt> + <dd>Libvirt will check the guest CPU specification before starting + a domain, but the rest is left on the hypervisor. It can still + provide a different virtual CPU.</dd> + + <dt><code>full</code></dt> + <dd>The virtual CPU created by the hypervisor will be checked + against the CPU specification and the domain will not be started + unless the two CPUs match.</dd> + </dl> + <span class="since">Since 0.9.10</span>, an optional <code>mode</code> attribute may be used to make it easier to configure a guest CPU to be as close to host CPU as possible. Possible values for the diff --git a/docs/schemas/cputypes.rng b/docs/schemas/cputypes.rng index 7cc9dd3d8..8189114e3 100644 --- a/docs/schemas/cputypes.rng +++ b/docs/schemas/cputypes.rng @@ -23,6 +23,16 @@ </attribute> </define> + <define name="cpuCheck"> + <attribute name="check"> + <choice> + <value>none</value> + <value>partial</value> + <value>full</value> + </choice> + </attribute> + </define> + <define name="cpuModel"> <element name="model"> <optional> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 5e593285e..767d6979c 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4503,6 +4503,9 @@ <optional> <ref name="cpuMatch"/> </optional> + <optional> + <ref name="cpuCheck"/> + </optional> <interleave> <optional> <ref name="cpuModel"/> diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index 2724fa30a..90accaea7 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -45,6 +45,12 @@ VIR_ENUM_IMPL(virCPUMatch, VIR_CPU_MATCH_LAST, "exact", "strict") +VIR_ENUM_IMPL(virCPUCheck, VIR_CPU_CHECK_LAST, + "default", + "none", + "partial", + "full") + VIR_ENUM_IMPL(virCPUFallback, VIR_CPU_FALLBACK_LAST, "allow", "forbid") @@ -182,6 +188,7 @@ virCPUDefCopyWithoutModel(const virCPUDef *cpu) copy->type = cpu->type; copy->mode = cpu->mode; copy->match = cpu->match; + copy->check = cpu->check; copy->fallback = cpu->fallback; copy->sockets = cpu->sockets; copy->cores = cpu->cores; @@ -277,6 +284,7 @@ virCPUDefParseXML(xmlNodePtr node, if (def->type == VIR_CPU_TYPE_GUEST) { char *match = virXMLPropString(node, "match"); + char *check; if (!match) { if (virXPathBoolean("boolean(./model)", ctxt)) @@ -294,6 +302,18 @@ virCPUDefParseXML(xmlNodePtr node, goto error; } } + + if ((check = virXMLPropString(node, "check"))) { + def->check = virCPUCheckTypeFromString(check); + VIR_FREE(check); + + if (def->check < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Invalid check attribute for CPU " + "specification")); + goto error; + } + } } if (def->type == VIR_CPU_TYPE_HOST) { @@ -532,6 +552,16 @@ virCPUDefFormatBufFull(virBufferPtr buf, } virBufferAsprintf(&attributeBuf, " match='%s'", tmp); } + + if (def->check) { + if (!(tmp = virCPUCheckTypeToString(def->check))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unexpected CPU check policy %d"), + def->check); + goto cleanup; + } + virBufferAsprintf(&attributeBuf, " check='%s'", tmp); + } } /* Format children */ diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h index cc3fbf0a4..507f630dc 100644 --- a/src/conf/cpu_conf.h +++ b/src/conf/cpu_conf.h @@ -64,6 +64,17 @@ typedef enum { VIR_ENUM_DECL(virCPUMatch) typedef enum { + VIR_CPU_CHECK_DEFAULT, + VIR_CPU_CHECK_NONE, + VIR_CPU_CHECK_PARTIAL, + VIR_CPU_CHECK_FULL, + + VIR_CPU_CHECK_LAST +} virCPUCheck; + +VIR_ENUM_DECL(virCPUCheck) + +typedef enum { VIR_CPU_FALLBACK_ALLOW, VIR_CPU_FALLBACK_FORBID, @@ -98,6 +109,7 @@ struct _virCPUDef { int type; /* enum virCPUType */ int mode; /* enum virCPUMode */ int match; /* enum virCPUMatch */ + int check; /* virCPUCheck */ virArch arch; char *model; char *vendor_id; /* vendor id returned by CPUID in the guest */ diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 88d419e27..a2cdb260a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4587,6 +4587,24 @@ virDomainVcpuDefPostParse(virDomainDefPtr def) static int +virDomainDefPostParseCPU(virDomainDefPtr def) +{ + if (!def->cpu) + return 0; + + if (def->cpu->mode == VIR_CPU_MODE_CUSTOM && + !def->cpu->model && + def->cpu->check != VIR_CPU_CHECK_DEFAULT) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("check attribute specified for CPU with no model")); + return -1; + } + + return 0; +} + + +static int virDomainDefPostParseInternal(virDomainDefPtr def, struct virDomainDefPostParseDeviceIteratorData *data) { @@ -4636,6 +4654,9 @@ virDomainDefPostParseInternal(virDomainDefPtr def, virDomainDefPostParseGraphics(def); + if (virDomainDefPostParseCPU(def) < 0) + return -1; + return 0; } -- 2.12.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list