cpu: Allow fine tuning of "host-model" cpu

https://bugzilla.redhat.com/show_bug.cgi?id=799354

Until now, the "host-model" cpu mode couldn't be influenced. This patch
allows to use the <feature> elements to either enable or disable
specific CPU flags. This can be used to force flags that can be emulated
even if the host CPU doesn't support them.
This commit is contained in:
Peter Krempa 2013-07-15 17:38:55 +02:00
parent 90f9fb5a7c
commit 3c8be55c04
3 changed files with 72 additions and 34 deletions

View File

@ -901,11 +901,15 @@
copying host CPU definition from capabilities XML into domain XML.
Since the CPU definition is copied just before starting a domain,
exactly the same XML can be used on different hosts while still
providing the best guest CPU each host supports. Neither
<code>match</code> attribute nor any <code>feature</code> elements
can be used in this mode. Specifying CPU model is not supported
either, but <code>model</code>'s <code>fallback</code> attribute may
still be used. Libvirt does not model every aspect of each CPU so
providing the best guest CPU each host supports. The
<code>match</code> attribute can't be used in this mode. Specifying
CPU model is not supported either, but <code>model</code>'s
<code>fallback</code> attribute may still be used. Using the
<code>feature</code> element, specific flags may be enabled or
disabled specifically in addition to the host model. This may be
used to fine tune features that can be emulated.
<span class="since">(Since 1.1.1)</span>.
Libvirt does not model every aspect of each CPU so
the guest CPU will not match the host CPU exactly. On the other
hand, the ABI provided to the guest is reproducible. During
migration, complete CPU model definition is transferred to the

View File

@ -361,7 +361,7 @@ virCPUDefParseXML(const xmlNodePtr node,
goto error;
if (n > 0) {
if (!def->model) {
if (!def->model && def->mode != VIR_CPU_MODE_HOST_MODEL) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Non-empty feature list specified without "
"CPU model"));
@ -574,7 +574,9 @@ virCPUDefFormatBuf(virBufferPtr buf,
(def->mode == VIR_CPU_MODE_HOST_MODEL ||
(def->mode == VIR_CPU_MODE_CUSTOM && def->model)));
if (!def->model && def->nfeatures) {
if (!def->model &&
def->mode != VIR_CPU_MODE_HOST_MODEL &&
def->nfeatures) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Non-empty feature list specified without CPU model"));
return -1;
@ -614,32 +616,30 @@ virCPUDefFormatBuf(virBufferPtr buf,
virBufferAddLit(buf, "/>\n");
}
if (formatModel) {
for (i = 0; i < def->nfeatures; i++) {
virCPUFeatureDefPtr feature = def->features + i;
for (i = 0; i < def->nfeatures; i++) {
virCPUFeatureDefPtr feature = def->features + i;
if (!feature->name) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing CPU feature name"));
if (!feature->name) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing CPU feature name"));
return -1;
}
if (def->type == VIR_CPU_TYPE_GUEST) {
const char *policy;
policy = virCPUFeaturePolicyTypeToString(feature->policy);
if (!policy) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected CPU feature policy %d"),
feature->policy);
return -1;
}
if (def->type == VIR_CPU_TYPE_GUEST) {
const char *policy;
policy = virCPUFeaturePolicyTypeToString(feature->policy);
if (!policy) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected CPU feature policy %d"),
feature->policy);
return -1;
}
virBufferAsprintf(buf, "<feature policy='%s' name='%s'/>\n",
policy, feature->name);
} else {
virBufferAsprintf(buf, "<feature name='%s'/>\n",
feature->name);
}
virBufferAsprintf(buf, "<feature policy='%s' name='%s'/>\n",
policy, feature->name);
} else {
virBufferAsprintf(buf, "<feature name='%s'/>\n",
feature->name);
}
}

View File

@ -1739,6 +1739,41 @@ cleanup:
return ret;
}
static int
x86UpdateHostModel(virCPUDefPtr guest,
const virCPUDefPtr host)
{
virCPUDefPtr oldguest;
size_t i;
guest->match = VIR_CPU_MATCH_EXACT;
/* no updates are required */
if (guest->nfeatures == 0) {
virCPUDefFreeModel(guest);
return virCPUDefCopyModel(guest, host, true);
}
/* update the host model according to the desired configuration */
if (!(oldguest = virCPUDefCopy(guest)))
return -1;
virCPUDefFreeModel(guest);
if (virCPUDefCopyModel(guest, host, true) < 0)
return -1;
for (i = 0; i < oldguest->nfeatures; i++) {
if (virCPUDefUpdateFeature(guest,
oldguest->features[i].name,
oldguest->features[i].policy) < 0)
return -1;
}
return 0;
}
static int
x86Update(virCPUDefPtr guest,
const virCPUDefPtr host)
@ -1748,11 +1783,10 @@ x86Update(virCPUDefPtr guest,
return x86UpdateCustom(guest, host);
case VIR_CPU_MODE_HOST_MODEL:
return x86UpdateHostModel(guest, host);
case VIR_CPU_MODE_HOST_PASSTHROUGH:
if (guest->mode == VIR_CPU_MODE_HOST_MODEL)
guest->match = VIR_CPU_MATCH_EXACT;
else
guest->match = VIR_CPU_MATCH_MINIMUM;
guest->match = VIR_CPU_MATCH_MINIMUM;
virCPUDefFreeModel(guest);
return virCPUDefCopyModel(guest, host, true);